-
Notifications
You must be signed in to change notification settings - Fork 57
TIR - remove dynamic pod data and surface helm status #1135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
97463ee
449dd9e
5a0a021
0e23c03
555745c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ import groovy.transform.TypeChecked | |
| import groovy.transform.TypeCheckingMode | ||
| import org.ods.services.JenkinsService | ||
| import org.ods.services.OpenShiftService | ||
| import org.ods.util.HelmStatusSimpleData | ||
| import org.ods.util.ILogger | ||
| import org.ods.util.PipelineSteps | ||
| import org.ods.util.PodData | ||
|
|
@@ -94,10 +95,16 @@ class HelmDeploymentStrategy extends AbstractDeploymentStrategy { | |
|
|
||
| logger.info "Rolling out ${context.componentId} with HELM, selector: ${options.selector}" | ||
| helmUpgrade(context.targetProject) | ||
| HelmStatusSimpleData helmStatus = openShift.helmStatus(context.targetProject, options.helmReleaseName) | ||
| def helmStatusMap = helmStatus.toMap() | ||
| def deploymentResources = getDeploymentResources(helmStatus) | ||
|
|
||
| def deploymentResources = openShift.getResourcesForComponent( | ||
| context.targetProject, DEPLOYMENT_KINDS, options.selector | ||
| ) | ||
| logger.info("${this.class.name} -- HELM STATUS") | ||
| logger.info( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Logging the contents of the helm status map is detailed debug info. Please change this to logger.debug and enclose it in a condition on logger.getDebugOn() so that no processing is done, if debug mode is inactive. |
||
| JsonOutput.prettyPrint( | ||
| JsonOutput.toJson(helmStatusMap))) | ||
|
|
||
| // not sure if we need both HELM STATUS and DEPLOYMENT RESOURCES" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please, don't leave this kind of comments. Could you make a decision and remove it? |
||
| logger.info("${this.class.name} -- DEPLOYMENT RESOURCES") | ||
| logger.info( | ||
| JsonOutput.prettyPrint( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This also feels like debug level. Let's discuss this.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The logging of DEPLOYMENT RESOURCES comes from master. Should it be changed? |
||
|
|
@@ -107,11 +114,12 @@ class HelmDeploymentStrategy extends AbstractDeploymentStrategy { | |
| // // we assume that Helm does "Deployment" that should work for most | ||
| // // cases since they don't have triggers. | ||
| // metadataSvc.updateMetadata(false, deploymentResources) | ||
| def rolloutData = getRolloutData(deploymentResources) ?: [:] | ||
| def rolloutData = getRolloutData(helmStatus) | ||
| logger.info(JsonOutput.prettyPrint(JsonOutput.toJson(rolloutData))) | ||
| return rolloutData | ||
| } | ||
|
|
||
| @SuppressWarnings(['UnnecessaryCast']) // otherwise IDE marked up helmUpgrade call | ||
| private void helmUpgrade(String targetProject) { | ||
| steps.dir(options.chartDir) { | ||
| jenkins.maybeWithPrivateKeyCredentials(options.helmPrivateKeyCredentialsId) { String pkeyFile -> | ||
|
|
@@ -124,7 +132,7 @@ class HelmDeploymentStrategy extends AbstractDeploymentStrategy { | |
| options.helmValues['componentId'] = context.componentId | ||
|
|
||
| // we persist the original ones set from outside - here we just add ours | ||
| Map mergedHelmValues = [:] | ||
| Map mergedHelmValues = [:] as Map<String, String> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not use def here?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the suggestion - I will make that change and also look out for similar cases. |
||
| mergedHelmValues << options.helmValues | ||
|
|
||
| // we add the global ones - this allows usage in subcharts | ||
|
|
@@ -140,7 +148,7 @@ class HelmDeploymentStrategy extends AbstractDeploymentStrategy { | |
| mergedHelmValues['global.imageTag'] = options.imageTag | ||
|
|
||
| // deal with dynamic value files - which are env dependent | ||
| def mergedHelmValuesFiles = [] | ||
| def mergedHelmValuesFiles = [] as List<String> | ||
| mergedHelmValuesFiles.addAll(options.helmValuesFiles) | ||
|
|
||
| options.helmEnvBasedValuesFiles.each { envValueFile -> | ||
|
|
@@ -161,46 +169,66 @@ class HelmDeploymentStrategy extends AbstractDeploymentStrategy { | |
| } | ||
| } | ||
|
|
||
| private Map<String, List<String>> getDeploymentResources(HelmStatusSimpleData helmStatus) { | ||
| helmStatus.getResourcesByKind(DEPLOYMENT_KINDS) | ||
| } | ||
|
|
||
| // rollout returns a map like this: | ||
| // [ | ||
| // 'DeploymentConfig/foo': [[podName: 'foo-a', ...], [podName: 'foo-b', ...]], | ||
| // 'Deployment/bar': [[podName: 'bar-a', ...]] | ||
| // ] | ||
| @TypeChecked(TypeCheckingMode.SKIP) | ||
| private Map<String, List<PodData>> getRolloutData( | ||
| Map<String, List<String>> deploymentResources) { | ||
|
|
||
| HelmStatusSimpleData helmStatus | ||
| ) { | ||
| def rolloutData = [:] | ||
| deploymentResources.each { resourceKind, resourceNames -> | ||
| resourceNames.each { resourceName -> | ||
| def podData = [] | ||
| for (def i = 0; i < options.deployTimeoutRetries; i++) { | ||
| podData = openShift.checkForPodData(context.targetProject, options.selector, resourceName) | ||
| if (!podData.isEmpty()) { | ||
| break | ||
| } | ||
| steps.echo("Could not find 'running' pod(s) with label '${options.selector}' - waiting") | ||
| steps.sleep(12) | ||
| helmStatus.resources.each { resource -> | ||
| if (! (resource.kind in DEPLOYMENT_KINDS)) { | ||
| return // continues with next | ||
| } | ||
| context.addDeploymentToArtifactURIs("${resource.name}-deploymentMean", | ||
| [ | ||
| 'type': 'helm', | ||
| 'selector': options.selector, | ||
| 'chartDir': options.chartDir, | ||
| 'helmReleaseName': options.helmReleaseName, | ||
| 'helmEnvBasedValuesFiles': options.helmEnvBasedValuesFiles, | ||
| 'helmValuesFiles': options.helmValuesFiles, | ||
| 'helmValues': options.helmValues, | ||
| 'helmDefaultFlags': options.helmDefaultFlags, | ||
| 'helmAdditionalFlags': options.helmAdditionalFlags, | ||
| 'helmStatus': helmStatus.toMap(), | ||
| ] | ||
| ) | ||
| def podDataContext = [ | ||
| "targetProject=${context.targetProject}", | ||
| "selector=${options.selector}", | ||
| "name=${resource.name}", | ||
| ] | ||
| def msgPodsNotFound = "Could not find 'running' pod(s) for '${podDataContext.join(', ')}'" | ||
| List<PodData> podData = null | ||
| for (def i = 0; i < options.deployTimeoutRetries; i++) { | ||
| podData = openShift.checkForPodData(context.targetProject, options.selector, resource.name) | ||
| if (podData) { | ||
| break | ||
| } | ||
| context.addDeploymentToArtifactURIs("${resourceName}-deploymentMean", | ||
| [ | ||
| 'type': 'helm', | ||
| 'selector': options.selector, | ||
| 'chartDir': options.chartDir, | ||
| 'helmReleaseName': options.helmReleaseName, | ||
| 'helmEnvBasedValuesFiles': options.helmEnvBasedValuesFiles, | ||
| 'helmValuesFiles': options.helmValuesFiles, | ||
| 'helmValues': options.helmValues, | ||
| 'helmDefaultFlags': options.helmDefaultFlags, | ||
| 'helmAdditionalFlags': options.helmAdditionalFlags | ||
| ]) | ||
| rolloutData["${resourceKind}/${resourceName}"] = podData | ||
| // TODO: Once the orchestration pipeline can deal with multiple replicas, | ||
| // update this to store multiple pod artifacts. | ||
| // TODO: Potential conflict if resourceName is duplicated between | ||
| // Deployment and DeploymentConfig resource. | ||
| context.addDeploymentToArtifactURIs(resourceName, podData[0]?.toMap()) | ||
| steps.echo("${msgPodsNotFound} - waiting") | ||
| steps.sleep(12) | ||
| } | ||
| if (!podData) { | ||
| throw new RuntimeException(msgPodsNotFound) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's better to use a specific exception that can be specifically caught, if necessary.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My expectation is that it should never happen. Would there be a reason to nonetheless catch it somewhere? |
||
| } | ||
|
|
||
| logger.debug("Helm podData for ${podDataContext.join(', ')}: " + | ||
| "${JsonOutput.prettyPrint(JsonOutput.toJson(podData))}") | ||
|
|
||
| rolloutData["${resource.kind}/${resource.name}"] = podData | ||
| // TODO: Once the orchestration pipeline can deal with multiple replicas, | ||
| // update this to store multiple pod artifacts. | ||
| // TODO: Potential conflict if resourceName is duplicated between | ||
| // Deployment and DeploymentConfig resource. | ||
| context.addDeploymentToArtifactURIs(resource.name, podData[0]?.toMap()) | ||
| } | ||
| rolloutData | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| package org.ods.orchestration.phases | ||
|
|
||
| import groovy.json.JsonOutput | ||
| import groovy.transform.TypeChecked | ||
| import groovy.transform.TypeCheckingMode | ||
| import org.ods.util.IPipelineSteps | ||
|
|
@@ -11,6 +12,7 @@ import org.ods.services.GitService | |
| import org.ods.orchestration.util.DeploymentDescriptor | ||
| import org.ods.orchestration.util.MROPipelineUtil | ||
| import org.ods.orchestration.util.Project | ||
| import org.ods.util.PodData | ||
|
|
||
| // Deploy ODS comnponent (code or service) to 'qa' or 'prod'. | ||
| @TypeChecked | ||
|
|
@@ -58,21 +60,29 @@ class DeployOdsComponent { | |
| applyTemplates(openShiftDir, deploymentMean) | ||
|
|
||
| def retries = project.environmentConfig?.openshiftRolloutTimeoutRetries ?: 10 | ||
| def podData = null | ||
| def podDataContext = [ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this data is only to generate an error message, please, generate only when you are about to echo the message.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. May rationale here was that the case where no pods are not found is not typically happening. If we move the message generation in a conditional it could be that the code itself is flawed and potentially cause an exception. |
||
| "targetProject=${project.targetProject}", | ||
| "selector=${deploymentMean.selector}", | ||
| "name=${deploymentName}", | ||
| ] | ||
| def msgPodsNotFound = "Could not find 'running' pod(s) for '${podDataContext.join(', ')}'" | ||
| List<PodData> podData = null | ||
| for (def i = 0; i < retries; i++) { | ||
| podData = os.checkForPodData(project.targetProject, deploymentMean.selector, deploymentName) | ||
| if (podData) { | ||
| break | ||
| } | ||
| steps.echo("Could not find 'running' pod(s) with label '${deploymentMean.selector}' - waiting") | ||
| steps.echo("${msgPodsNotFound} - waiting") | ||
| steps.sleep(12) | ||
| } | ||
|
|
||
| if (!podData) { | ||
| throw new RuntimeException("Could not find 'running' pod(s) with label " + | ||
| "'${deploymentMean.selector}'") | ||
| throw new RuntimeException(msgPodsNotFound) | ||
| } | ||
|
|
||
| logger.info("Helm podData for '${podDataContext.join(', ')}': " + | ||
| "${JsonOutput.prettyPrint(JsonOutput.toJson(podData))}") | ||
|
|
||
| // TODO: Once the orchestration pipeline can deal with multiple replicas, | ||
| // update this to deal with multiple pods. | ||
| def pod = podData[0].toMap() | ||
|
|
@@ -227,6 +237,15 @@ class DeployOdsComponent { | |
| deploymentMean.helmDefaultFlags, | ||
| deploymentMean.helmAdditionalFlags, | ||
| true) | ||
|
|
||
| def helmStatus = os. helmStatus(project.targetProject, deploymentMean.helmReleaseName) | ||
| def helmStatusMap = helmStatus.toMap() | ||
| deploymentMean.helmStatus = helmStatusMap | ||
| logger.info("${this.class.name} -- HELM STATUS") | ||
| logger.info( | ||
| JsonOutput.prettyPrint( | ||
| JsonOutput.toJson(helmStatusMap))) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks will change! |
||
|
|
||
| } | ||
| } | ||
| jenkins.maybeWithPrivateKeyCredentials(secretName) { String pkeyFile -> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This map seems to be used only for logging purposes. I would enclose the instruction that performs the log in a condition on logger.getDebugOn() and generate the map inside, so that it isn't generated unless necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you - will adjust the code!