diff --git a/src/org/ods/component/AbstractDeploymentStrategy.groovy b/src/org/ods/component/AbstractDeploymentStrategy.groovy index 32213c70b0..bcb6cfe936 100644 --- a/src/org/ods/component/AbstractDeploymentStrategy.groovy +++ b/src/org/ods/component/AbstractDeploymentStrategy.groovy @@ -32,23 +32,6 @@ abstract class AbstractDeploymentStrategy implements IDeploymentStrategy { originalVersions } - protected findOrCreateImageStream(String targetProject, String image) { - try { - openShift.findOrCreateImageStream(targetProject, image) - } catch (Exception ex) { - steps.error "Could not find/create ImageStream ${image} in ${targetProject}. Error was: ${ex}" - } - } - - protected void retagImages(String targetProject, Set images) { - images.each { image -> - findOrCreateImageStream(targetProject, image) - openShift.importImageTagFromProject( - targetProject, image, context.cdProject, options.imageTag, options.imageTag - ) - } - } - @TypeChecked(TypeCheckingMode.SKIP) protected Set getBuiltImages() { context.buildArtifactURIs.builds.keySet().findAll { it -> diff --git a/src/org/ods/component/DeploymentConfig.groovy b/src/org/ods/component/DeploymentConfig.groovy new file mode 100644 index 0000000000..feb847d6ab --- /dev/null +++ b/src/org/ods/component/DeploymentConfig.groovy @@ -0,0 +1,78 @@ + +package org.ods.component + +class DeploymentConfig { + + public void updateCommonConfig(IContext context, Map config) { + if (!config.selector) { + config.selector = context.selector + } + if (!config.imageTag) { + config.imageTag = context.shortGitCommit + } + if (!config.deployTimeoutMinutes) { + config.deployTimeoutMinutes = context.openshiftRolloutTimeout ?: 15 + } + if (!config.deployTimeoutRetries) { + config.deployTimeoutRetries = context.openshiftRolloutTimeoutRetries ?: 5 + } + } + + public void updateHelmConfig(IContext context, Map config){ + if (!config.chartDir) { + config.chartDir = 'chart' + } + if (!config.containsKey('helmReleaseName')) { + config.helmReleaseName = context.componentId + } + if (!config.containsKey('helmValues')) { + config.helmValues = [:] + } + if (!config.containsKey('helmValuesFiles')) { + config.helmValuesFiles = [ 'values.yaml' ] + } + if (!config.containsKey('helmEnvBasedValuesFiles')) { + config.helmEnvBasedValuesFiles = [] + } + if (!config.containsKey('helmDefaultFlags')) { + config.helmDefaultFlags = ['--install', '--atomic'] + } + if (!config.containsKey('helmAdditionalFlags')) { + config.helmAdditionalFlags = [] + } + if (!config.containsKey('helmDiff')) { + config.helmDiff = true + } + if (!config.helmPrivateKeyCredentialsId) { + config.helmPrivateKeyCredentialsId = "${context.cdProject}-helm-private-key" + } + } + + @NonCPS + public static void updateTailorConfig(IContext context, Map config) { + if (!config.openshiftDir) { + config.openshiftDir = 'openshift' + } + if (!config.tailorPrivateKeyCredentialsId) { + config.tailorPrivateKeyCredentialsId = "${context.cdProject}-tailor-private-key" + } + if (!config.tailorSelector) { + config.tailorSelector = config.selector + } + if (!config.containsKey('tailorVerify')) { + config.tailorVerify = true + } + if (!config.containsKey('tailorExclude')) { + config.tailorExclude = 'bc,is' + } + if (!config.containsKey('tailorParamFile')) { + config.tailorParamFile = '' // none apart the automatic param file + } + if (!config.containsKey('tailorPreserve')) { + config.tailorPreserve = [] // do not preserve any paths in live config + } + if (!config.containsKey('tailorParams')) { + config.tailorParams = [] + } + } +} \ No newline at end of file diff --git a/src/org/ods/component/HelmDeploymentStrategy.groovy b/src/org/ods/component/HelmDeploymentStrategy.groovy index 7b0fb2e1c7..87e61c7de6 100644 --- a/src/org/ods/component/HelmDeploymentStrategy.groovy +++ b/src/org/ods/component/HelmDeploymentStrategy.groovy @@ -18,6 +18,8 @@ class HelmDeploymentStrategy extends AbstractDeploymentStrategy { private final JenkinsService jenkins private final ILogger logger private final IPipelineSteps steps + private final IImageRepository imageRepository + // assigned in constructor private final RolloutOpenShiftDeploymentOptions options @@ -28,8 +30,13 @@ class HelmDeploymentStrategy extends AbstractDeploymentStrategy { Map config, OpenShiftService openShift, JenkinsService jenkins, + IImageRepository imageRepository, ILogger logger ) { + // TODO + // DeploymentConfig deploymentConfig = new DeploymentConfig() + // deploymentConfig.updateCommonConfig(context, config) + // deploymentConfig.updateHelmConfig(context, config) if (!config.selector) { config.selector = context.selector } @@ -42,7 +49,6 @@ class HelmDeploymentStrategy extends AbstractDeploymentStrategy { if (!config.deployTimeoutRetries) { config.deployTimeoutRetries = context.openshiftRolloutTimeoutRetries ?: 5 } - // Helm options if (!config.chartDir) { config.chartDir = 'chart' } @@ -53,7 +59,7 @@ class HelmDeploymentStrategy extends AbstractDeploymentStrategy { config.helmValues = [:] } if (!config.containsKey('helmValuesFiles')) { - config.helmValuesFiles = ['values.yaml'] + config.helmValuesFiles = [ 'values.yaml' ] } if (!config.containsKey('helmEnvBasedValuesFiles')) { config.helmEnvBasedValuesFiles = [] @@ -70,6 +76,7 @@ class HelmDeploymentStrategy extends AbstractDeploymentStrategy { if (!config.helmPrivateKeyCredentialsId) { config.helmPrivateKeyCredentialsId = "${context.cdProject}-helm-private-key" } + this.context = context this.logger = logger this.steps = steps @@ -77,21 +84,23 @@ class HelmDeploymentStrategy extends AbstractDeploymentStrategy { this.options = new RolloutOpenShiftDeploymentOptions(config) this.openShift = openShift this.jenkins = jenkins + this.imageRepository = imageRepository } @Override - Map> deploy() { - if (!context.environment) { - logger.warn 'Skipping because of empty (target) environment ...' - return [:] + Map> deploy() { + // Maybe we need to deploy to another namespace (ie we want to deploy a monitoring stack into a specific namespace) + def targetProject = context.targetProject + if (options.helmValues['namespaceOverride']) { + targetProject = options.helmValues['namespaceOverride'] + logger.info("Override namespace deployment to ${targetProject} ") } - - // Tag images which have been built in this pipeline from cd project into target project - retagImages(context.targetProject, getBuiltImages()) + logger.info("Retagging images for ${targetProject} ") + imageRepository.retagImages(targetProject, getBuiltImages(), options.imageTag, options.imageTag) logger.info("Rolling out ${context.componentId} with HELM, selector: ${options.selector}") - helmUpgrade(context.targetProject) - HelmStatus helmStatus = openShift.helmStatus(context.targetProject, options.helmReleaseName) + helmUpgrade(targetProject) + HelmStatus helmStatus = openShift.helmStatus(targetProject, options.helmReleaseName) if (logger.debugMode) { def helmStatusMap = helmStatus.toMap() logger.debug("${this.class.name} -- HELM STATUS: ${helmStatusMap}") @@ -101,17 +110,16 @@ 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(helmStatus) + def rolloutData = getRolloutData(helmStatus, targetProject) return rolloutData } - private void helmUpgrade(String targetProject) { + private void helmUpgrade(String targetProject) { steps.dir(options.chartDir) { jenkins.maybeWithPrivateKeyCredentials(options.helmPrivateKeyCredentialsId) { String pkeyFile -> if (pkeyFile) { steps.sh(script: "gpg --import ${pkeyFile}", label: 'Import private key into keyring') - } - + } // we add two things persistent - as these NEVER change (and are env independent) options.helmValues['registry'] = context.clusterRegistryAddress options.helmValues['componentId'] = context.componentId @@ -162,7 +170,7 @@ class HelmDeploymentStrategy extends AbstractDeploymentStrategy { // ] @TypeChecked(TypeCheckingMode.SKIP) private Map> getRolloutData( - HelmStatus helmStatus + HelmStatus helmStatus, String targetProject ) { Map> rolloutData = [:] @@ -175,7 +183,7 @@ class HelmDeploymentStrategy extends AbstractDeploymentStrategy { [ type: 'helm', selector: options.selector, - namespace: context.targetProject, + namespace: targetProject, chartDir: options.chartDir, helmReleaseName: options.helmReleaseName, helmEnvBasedValuesFiles: options.helmEnvBasedValuesFiles, @@ -187,14 +195,14 @@ class HelmDeploymentStrategy extends AbstractDeploymentStrategy { ] ) def podDataContext = [ - "targetProject=${context.targetProject}", + "targetProject=${targetProject}", "selector=${options.selector}", "name=${name}", ] def msgPodsNotFound = "Could not find 'running' pod(s) for '${podDataContext.join(', ')}'" List podData = null for (def i = 0; i < options.deployTimeoutRetries; i++) { - podData = openShift.checkForPodData(context.targetProject, options.selector, name) + podData = openShift.checkForPodData(targetProject, options.selector, name) if (podData) { break } diff --git a/src/org/ods/component/IImageRepository.groovy b/src/org/ods/component/IImageRepository.groovy new file mode 100644 index 0000000000..a9992c9b4d --- /dev/null +++ b/src/org/ods/component/IImageRepository.groovy @@ -0,0 +1,7 @@ +package org.ods.component + +interface IImageRepository { + + void retagImages(String targetProject, Set images, String sourceTag, String targetTag) + +} diff --git a/src/org/ods/component/ImageRepositoryEKS.groovy b/src/org/ods/component/ImageRepositoryEKS.groovy new file mode 100644 index 0000000000..ae8a69a2e5 --- /dev/null +++ b/src/org/ods/component/ImageRepositoryEKS.groovy @@ -0,0 +1,56 @@ +package org.ods.component + +import org.ods.services.EKSService +import org.ods.util.IPipelineSteps +import org.ods.component.IContext + +class ImageRepositoryEKS implements IImageRepository { + + // Constructor arguments + private final IPipelineSteps steps + private final IContext context + private final EKSService eks + + private final String ocToken + private final String awsPassword + + @SuppressWarnings(['AbcMetric', 'CyclomaticComplexity', 'ParameterCount']) + ImageRepositoryEKS( + IPipelineSteps steps, + IContext context, + EKSService eks, + String ocToken, + String awsPassword + ) { + this.steps = steps + this.context = context + this.eks = eks + this.ocToken = ocToken + this.awsPassword = awsPassword + } + + public void retagImages(String targetProject, Set images, String sourceTag, String targetTag) { + images.each { image -> + eks.createRepository(image) + copyImage(image, context, sourceTag, targetTag) + } + } + + private int copyImage(image, context, sourceTag, targetTag) { + String ocCredentials="jenkins:$ocToken" + String awsCredentials="AWS:$awsPassword" + String dockerSource="docker://${context.config.dockerRegistry}/${context.cdProject}/${image}:${sourceTag}" + String awsTarget="docker://${eks.getECRRegistry()}/${image}:${targetTag}" + + return steps.sh( + script: """ + skopeo copy \ + --src-tls-verify=false --src-creds "${ocCredentials}"\ + --dest-tls-verify=false --dest-creds "${awsCredentials}"\ + $dockerSource $awsTarget + """, + returnStatus: true, + label: "Copy image to awsTarget ${awsTarget}" + ) as int + } +} diff --git a/src/org/ods/component/ImageRepositoryOpenshift.groovy b/src/org/ods/component/ImageRepositoryOpenshift.groovy new file mode 100644 index 0000000000..bc63fedf27 --- /dev/null +++ b/src/org/ods/component/ImageRepositoryOpenshift.groovy @@ -0,0 +1,40 @@ +package org.ods.component + +import org.ods.services.OpenShiftService +import org.ods.util.IPipelineSteps + +class ImageRepositoryOpenshift implements IImageRepository { + + // Constructor arguments + private final IPipelineSteps steps + private final IContext context + private final OpenShiftService openShift + + @SuppressWarnings(['AbcMetric', 'CyclomaticComplexity', 'ParameterCount']) + ImageRepositoryOpenshift( + IPipelineSteps steps, + IContext context, + OpenShiftService openShift + ) { + this.steps = steps + this.context = context + this.openShift = openShift + } + + public void retagImages(String targetProject, Set images, String sourceTag, String targetTag) { + images.each { image -> + findOrCreateImageStream(targetProject, image) + openShift.importImageTagFromProject( + targetProject, image, context.cdProject, sourceTag, targetTag + ) + } + } + + private findOrCreateImageStream(String targetProject, String image) { + try { + openShift.findOrCreateImageStream(targetProject, image) + } catch (Exception ex) { + steps.error "Could not find/create ImageStream ${image} in ${targetProject}. Error was: ${ex}" + } + } +} diff --git a/src/org/ods/component/RolloutEKSDeploymentStage.groovy b/src/org/ods/component/RolloutEKSDeploymentStage.groovy new file mode 100644 index 0000000000..48184907de --- /dev/null +++ b/src/org/ods/component/RolloutEKSDeploymentStage.groovy @@ -0,0 +1,107 @@ +package org.ods.component + +import groovy.transform.TypeChecked +import groovy.transform.TypeCheckingMode +import org.ods.services.JenkinsService +import org.ods.services.OpenShiftService +import org.ods.util.ILogger +import org.ods.util.PipelineSteps +import org.ods.util.IPipelineSteps +import org.ods.services.EKSService +import com.cloudbees.groovy.cps.NonCPS + +@SuppressWarnings('ParameterCount') +@TypeChecked +class RolloutEKSDeploymentStage extends Stage { + + public final String STAGE_NAME = 'Deploy to OpenShift' + private final OpenShiftService openShift + private final JenkinsService jenkins + private final RolloutOpenShiftDeploymentOptions options + private IDeploymentStrategy deploymentStrategy + private Map config + private Map awsEnvironmentVars + + @SuppressWarnings(['AbcMetric', 'CyclomaticComplexity']) + @TypeChecked(TypeCheckingMode.SKIP) + RolloutEKSDeploymentStage( + def script, + IContext context, + Map config, + OpenShiftService openShift, + JenkinsService jenkins, + Map awsEnvironmentVars, + ILogger logger) { + super(script, context, logger) + + // TODO + // DeploymentConfig deploymentConfig = new DeploymentConfig() + // deploymentConfig.updateCommonConfig(context, config) + // deploymentConfig.updateHelmConfig(context, config) + if (!config.selector) { + config.selector = context.selector + } + if (!config.imageTag) { + config.imageTag = context.shortGitCommit + } + if (!config.deployTimeoutMinutes) { + config.deployTimeoutMinutes = context.openshiftRolloutTimeout ?: 15 + } + if (!config.deployTimeoutRetries) { + config.deployTimeoutRetries = context.openshiftRolloutTimeoutRetries ?: 5 + } + if (!config.chartDir) { + config.chartDir = 'chart' + } + if (!config.containsKey('helmReleaseName')) { + config.helmReleaseName = context.componentId + } + if (!config.containsKey('helmValues')) { + config.helmValues = [:] + } + if (!config.containsKey('helmValuesFiles')) { + config.helmValuesFiles = [ 'values.yaml' ] + } + if (!config.containsKey('helmEnvBasedValuesFiles')) { + config.helmEnvBasedValuesFiles = [] + } + if (!config.containsKey('helmDefaultFlags')) { + config.helmDefaultFlags = ['--install', '--atomic'] + } + if (!config.containsKey('helmAdditionalFlags')) { + config.helmAdditionalFlags = [] + } + if (!config.containsKey('helmDiff')) { + config.helmDiff = true + } + if (!config.helmPrivateKeyCredentialsId) { + config.helmPrivateKeyCredentialsId = "${context.cdProject}-helm-private-key" + } + this.config = config + this.options = new RolloutOpenShiftDeploymentOptions(config) + this.openShift = openShift + this.jenkins = jenkins + this.awsEnvironmentVars = awsEnvironmentVars + } + + // This is called from Stage#execute if the branch being built is eligible. + protected run() { + EKSService eks = new EKSService(steps, context, awsEnvironmentVars, logger) + String ocToken = eks.getOCTOken() + eks.setEKSCluster() // This should be set after getOCTOken!!! + String awsPassword = eks.getLoginPassword() + ImageRepositoryEKS imageRepository = new ImageRepositoryEKS(steps, context, eks, ocToken, awsPassword) + deploymentStrategy = new HelmDeploymentStrategy(steps, context, config, openShift, jenkins, imageRepository, logger) + + logger.info("deploymentStrategy: ${deploymentStrategy} -- ${deploymentStrategy.class.name}") + return deploymentStrategy.deploy() + } + + protected String stageLabel() { + if (options.selector != context.selector) { + return "${STAGE_NAME} (${options.selector})" + } + STAGE_NAME + } + +} diff --git a/src/org/ods/component/RolloutOpenShiftDeploymentOptions.groovy b/src/org/ods/component/RolloutOpenShiftDeploymentOptions.groovy index 3fe467406b..22e69ec361 100644 --- a/src/org/ods/component/RolloutOpenShiftDeploymentOptions.groovy +++ b/src/org/ods/component/RolloutOpenShiftDeploymentOptions.groovy @@ -5,6 +5,8 @@ import groovy.transform.TypeChecked @TypeChecked class RolloutOpenShiftDeploymentOptions extends Options { + String envPath + /** * Selector scope used to determine which resources are part of a component * (defaults to `context.selector`). */ diff --git a/src/org/ods/component/RolloutOpenShiftDeploymentStage.groovy b/src/org/ods/component/RolloutOpenShiftDeploymentStage.groovy index 323a0f0c6b..e428be27ee 100644 --- a/src/org/ods/component/RolloutOpenShiftDeploymentStage.groovy +++ b/src/org/ods/component/RolloutOpenShiftDeploymentStage.groovy @@ -29,7 +29,11 @@ class RolloutOpenShiftDeploymentStage extends Stage { JenkinsService jenkins, ILogger logger) { super(script, context, logger) - + + // TODO + // DeploymentConfig deploymentConfig = new DeploymentConfig() + // deploymentConfig.updateCommonConfig(context, config) + // deploymentConfig.updateHelmConfig(context, config) if (!config.selector) { config.selector = context.selector } @@ -42,7 +46,6 @@ class RolloutOpenShiftDeploymentStage extends Stage { if (!config.deployTimeoutRetries) { config.deployTimeoutRetries = context.openshiftRolloutTimeoutRetries ?: 5 } - // Helm options if (!config.chartDir) { config.chartDir = 'chart' } @@ -70,9 +73,8 @@ class RolloutOpenShiftDeploymentStage extends Stage { if (!config.helmPrivateKeyCredentialsId) { config.helmPrivateKeyCredentialsId = "${context.cdProject}-helm-private-key" } - // Tailor options if (!config.openshiftDir) { - config.openshiftDir = 'openshift' + config.openshiftDir = 'openshift' } if (!config.tailorPrivateKeyCredentialsId) { config.tailorPrivateKeyCredentialsId = "${context.cdProject}-tailor-private-key" @@ -121,18 +123,20 @@ class RolloutOpenShiftDeploymentStage extends Stage { throw new IllegalStateException("Must be either a Tailor based deployment or a Helm based deployment") } + IPipelineSteps steps = new PipelineSteps(script) + IImageRepository imageRepository = new ImageRepositoryOpenShift(steps, context, openShift) + // Use tailorDeployment in the following cases: // (1) We have an openshiftDir // (2) We do not have an openshiftDir but neither do we have an indication that it is Helm - IPipelineSteps steps = new PipelineSteps(script) if (isTailorDeployment || (!isHelmDeployment && !isTailorDeployment)) { - deploymentStrategy = new TailorDeploymentStrategy(steps, context, config, openShift, jenkins, logger) + deploymentStrategy = new TailorDeploymentStrategy(steps, context, config, openShift, jenkins, imageRepository, logger) String resourcePath = 'org/ods/component/RolloutOpenShiftDeploymentStage.deprecate-tailor.GString.txt' def msg = this.steps.libraryResource(resourcePath) logger.warn(msg) } if (isHelmDeployment) { - deploymentStrategy = new HelmDeploymentStrategy(steps, context, config, openShift, jenkins, logger) + deploymentStrategy = new HelmDeploymentStrategy(steps, context, config, openShift, jenkins, imageRepository, logger) } logger.info("deploymentStrategy: ${deploymentStrategy} -- ${deploymentStrategy.class.name}") return deploymentStrategy.deploy() diff --git a/src/org/ods/component/TailorDeploymentStrategy.groovy b/src/org/ods/component/TailorDeploymentStrategy.groovy index cfe1d45e84..42c4f432f5 100644 --- a/src/org/ods/component/TailorDeploymentStrategy.groovy +++ b/src/org/ods/component/TailorDeploymentStrategy.groovy @@ -19,6 +19,7 @@ class TailorDeploymentStrategy extends AbstractDeploymentStrategy { // assigned in constructor private final RolloutOpenShiftDeploymentOptions options + private final IImageRepository imageRepository @SuppressWarnings(['AbcMetric', 'CyclomaticComplexity', 'ParameterCount']) TailorDeploymentStrategy( @@ -27,45 +28,13 @@ class TailorDeploymentStrategy extends AbstractDeploymentStrategy { Map config, OpenShiftService openShift, JenkinsService jenkins, + IImageRepository imageRepository, ILogger logger ) { - if (!config.selector) { - config.selector = context.selector - } - if (!config.imageTag) { - config.imageTag = context.shortGitCommit - } - if (!config.deployTimeoutMinutes) { - config.deployTimeoutMinutes = context.openshiftRolloutTimeout ?: 15 - } - if (!config.deployTimeoutRetries) { - config.deployTimeoutRetries = context.openshiftRolloutTimeoutRetries ?: 5 - } - // Tailor options - if (!config.openshiftDir) { - config.openshiftDir = 'openshift' - } - if (!config.tailorPrivateKeyCredentialsId) { - config.tailorPrivateKeyCredentialsId = "${context.cdProject}-tailor-private-key" - } - if (!config.tailorSelector) { - config.tailorSelector = config.selector - } - if (!config.containsKey('tailorVerify')) { - config.tailorVerify = true - } - if (!config.containsKey('tailorExclude')) { - config.tailorExclude = 'bc,is' - } - if (!config.containsKey('tailorParamFile')) { - config.tailorParamFile = '' // none apart the automatic param file - } - if (!config.containsKey('tailorPreserve')) { - config.tailorPreserve = [] // do not preserve any paths in live config - } - if (!config.containsKey('tailorParams')) { - config.tailorParams = [] - } + DeploymentConfig deploymentConfig = new DeploymentConfig() + deploymentConfig.updateCommonConfig(context, config) + deploymentConfig.updateTailorConfig(context, config) + this.context = context this.logger = logger this.steps = steps @@ -73,6 +42,7 @@ class TailorDeploymentStrategy extends AbstractDeploymentStrategy { this.options = new RolloutOpenShiftDeploymentOptions(config) this.openShift = openShift this.jenkins = jenkins + this.imageRepository = imageRepository } @Override @@ -96,7 +66,7 @@ class TailorDeploymentStrategy extends AbstractDeploymentStrategy { def refreshResources = false // Tag images which have been built in this pipeline from cd project into target project - retagImages(context.targetProject, getBuiltImages()) + imageRepository.retagImages(context.targetProject, getBuiltImages(), options.imageTag, options.imageTag) if (steps.fileExists(options.openshiftDir)) { refreshResources = true diff --git a/src/org/ods/services/EKSService.groovy b/src/org/ods/services/EKSService.groovy new file mode 100644 index 0000000000..2952544692 --- /dev/null +++ b/src/org/ods/services/EKSService.groovy @@ -0,0 +1,81 @@ +package org.ods.services + +import org.ods.util.IPipelineSteps +import org.ods.component.IContext +import org.ods.util.ILogger + +class EKSService { + // Constructor arguments + private final IPipelineSteps steps + private final IContext context + private final Map awsEnvironmentVars + private final ILogger logger + + @SuppressWarnings(['AbcMetric', 'CyclomaticComplexity', 'ParameterCount']) + EKSService( + IPipelineSteps steps, + IContext context, + Map awsEnvironmentVars, + ILogger logger + ) { + this.steps = steps + this.context = context + this.awsEnvironmentVars = awsEnvironmentVars + this.logger = logger + } + + + protected String getOCTOken() { + return steps.sh( + script: "oc whoami -t", + returnStdout: true + ).trim() + } + + protected setEKSCluster() { + withCredentials((awsEnvironmentVars.credentials.key as String).toLowerCase(), + (awsEnvironmentVars.credentials.secret as String).toLowerCase()) { + executeCommand('aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID --profile default') + executeCommand('aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY --profile default') + executeCommand("aws configure set region ${awsEnvironmentVars.region} --profile default") + executeCommand("aws eks list-clusters") + executeCommand("aws eks update-kubeconfig --region ${awsEnvironmentVars.region} --name ${awsEnvironmentVars.eksCluster}") + executeCommand("kubectl create namespace ${context.getProjectId()}-${context.getEnvironment()}", false) + } + } + + protected String getLoginPassword() { + return steps.sh( + script: "aws ecr get-login-password --region ${awsEnvironmentVars.region}", + returnStdout: true + ).trim() + } + + protected String getECRRegistry() { + return "${awsEnvironmentVars.account}.dkr.ecr.${awsEnvironmentVars.region}.amazonaws.com" + } + + protected void createRepository(String repositoryName) { + executeCommand("aws ecr create-repository --repository-name ${repositoryName} --region ${awsEnvironmentVars.region}", false) + } + + private void executeCommand(String command, boolean showError = true) { + def status = steps.sh( + script: command, + returnStatus: true, + label: "Executing command: ${command}" + ) as int + if (status != 0 && showError) { + steps.error("Error executing ${command}, status ${status}") + } + } + + private withCredentials(String awsAccessKeyId, String awsSecretAccessKey, Closure block) { + steps.withCredentials([ + steps.string(credentialsId: awsAccessKeyId, variable: 'AWS_ACCESS_KEY_ID'), + steps.string(credentialsId: awsSecretAccessKey, variable: 'AWS_SECRET_ACCESS_KEY') + ]) { + block(steps.env.AWS_ACCESS_KEY_ID, steps.env.AWS_SECRET_ACCESS_KEY) + } + } +} \ No newline at end of file diff --git a/src/org/ods/services/OpenShiftService.groovy b/src/org/ods/services/OpenShiftService.groovy index e9f4b21401..e76a317c51 100644 --- a/src/org/ods/services/OpenShiftService.groovy +++ b/src/org/ods/services/OpenShiftService.groovy @@ -1052,7 +1052,7 @@ class OpenShiftService { @TypeChecked(TypeCheckingMode.SKIP) List parsePodJson(podJson, String resourceName = null) { List pods = [] - if (podJson && podJson.items.collect { it.status?.phase?.toLowerCase() }.every { it == 'running' }) { + if (podJson && podJson.items.collect { it.status?.phase?.toLowerCase() }.every { it == 'running' || it == 'Running' }) { // If we got passed a resourceName we need to collect all the pod data from each pod pods = extractPodData(podJson) } diff --git a/vars/odsComponentStageRolloutEKSDeployment.groovy b/vars/odsComponentStageRolloutEKSDeployment.groovy new file mode 100644 index 0000000000..738da78242 --- /dev/null +++ b/vars/odsComponentStageRolloutEKSDeployment.groovy @@ -0,0 +1,35 @@ +import org.ods.component.RolloutEKSDeploymentStage +import org.ods.component.IContext + +import org.ods.services.OpenShiftService +import org.ods.services.JenkinsService +import org.ods.services.ServiceRegistry +import org.ods.util.Logger +import org.ods.util.ILogger + +def call(IContext context, Map config = [:]) { + ILogger logger = ServiceRegistry.instance.get(Logger) + // this is only for testing, because we need access to the script context :( + if (!logger) { + logger = new Logger (this, !!env.DEBUG) + } + if (!context.environment) { + logger.warn 'Skipping because of empty (target) environment ...' + return + } + if (!config.envPath) { + config.envPath = "./environments" + } + + Map awsEnvironmentVars = readYaml(file: "${config.envPath}/${context.environment}.yml") + return new RolloutEKSDeploymentStage( + this, + context, + config, + ServiceRegistry.instance.get(OpenShiftService), + ServiceRegistry.instance.get(JenkinsService), + awsEnvironmentVars, + logger + ).execute() +} +return this