From 77dd040b09dfcedd4df8c37d644c679b4fbbfa0b Mon Sep 17 00:00:00 2001 From: Jyotsna Date: Mon, 23 Nov 2020 13:43:26 +0530 Subject: [PATCH] Review comment changes --- lib/constants.js | 106 ++--- .../strategy-helpers/deployment-helper.js | 354 +++++++------- lib/utilities/utility.js | 438 +++++++++--------- src/utilities/exec.ts | 64 +-- 4 files changed, 481 insertions(+), 481 deletions(-) diff --git a/lib/constants.js b/lib/constants.js index e3ec892e..27413ea9 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -1,53 +1,53 @@ -'use strict'; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.getWorkflowAnnotationKeyLabel = exports.getWorkflowAnnotationsJson = exports.workloadTypesWithRolloutStatus = exports.workloadTypes = exports.deploymentTypes = exports.ServiceTypes = exports.DiscoveryAndLoadBalancerResource = exports.KubernetesWorkload = void 0; -class KubernetesWorkload { -} -exports.KubernetesWorkload = KubernetesWorkload; -KubernetesWorkload.pod = 'Pod'; -KubernetesWorkload.replicaset = 'Replicaset'; -KubernetesWorkload.deployment = 'Deployment'; -KubernetesWorkload.statefulSet = 'StatefulSet'; -KubernetesWorkload.daemonSet = 'DaemonSet'; -KubernetesWorkload.job = 'job'; -KubernetesWorkload.cronjob = 'cronjob'; -class DiscoveryAndLoadBalancerResource { -} -exports.DiscoveryAndLoadBalancerResource = DiscoveryAndLoadBalancerResource; -DiscoveryAndLoadBalancerResource.service = 'service'; -DiscoveryAndLoadBalancerResource.ingress = 'ingress'; -class ServiceTypes { -} -exports.ServiceTypes = ServiceTypes; -ServiceTypes.loadBalancer = 'LoadBalancer'; -ServiceTypes.nodePort = 'NodePort'; -ServiceTypes.clusterIP = 'ClusterIP'; -exports.deploymentTypes = ['deployment', 'replicaset', 'daemonset', 'pod', 'statefulset']; -exports.workloadTypes = ['deployment', 'replicaset', 'daemonset', 'pod', 'statefulset', 'job', 'cronjob']; -exports.workloadTypesWithRolloutStatus = ['deployment', 'daemonset', 'statefulset']; -function getWorkflowAnnotationsJson(lastSuccessRunSha, workflowFilePath, filePathConfigs) { - return JSON.stringify(`{` - + `'run': '${process.env.GITHUB_RUN_ID}',` - + `'repository': '${process.env.GITHUB_REPOSITORY}',` - + `'workflow': '${process.env.GITHUB_WORKFLOW}',` - + `'workflowFileName': '${workflowFilePath.replace(".github/workflows/", "")}',` - + `'jobName': '${process.env.GITHUB_JOB}',` - + `'createdBy': '${process.env.GITHUB_ACTOR}',` - + `'runUri': 'https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}',` - + `'commit': '${process.env.GITHUB_SHA}',` - + `'lastSuccessRunCommit': '${lastSuccessRunSha}',` - + `'branch': '${process.env.GITHUB_REF}',` - + `'deployTimestamp': '${Date.now()}',` - + `'manifestsPaths': '${filePathConfigs.manifestFilePaths}',` - + `'dockerfilePaths': '${filePathConfigs.buildConfigs}',` - + `'provider': 'GitHub'` - + `}`); -} -exports.getWorkflowAnnotationsJson = getWorkflowAnnotationsJson; -function getWorkflowAnnotationKeyLabel(workflowFilePath) { - const hashKey = require("crypto").createHash("MD5") - .update(`${process.env.GITHUB_REPOSITORY}/${workflowFilePath}`) - .digest("hex"); - return `githubWorkflow_${hashKey}`; -} -exports.getWorkflowAnnotationKeyLabel = getWorkflowAnnotationKeyLabel; +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getWorkflowAnnotationKeyLabel = exports.getWorkflowAnnotationsJson = exports.workloadTypesWithRolloutStatus = exports.workloadTypes = exports.deploymentTypes = exports.ServiceTypes = exports.DiscoveryAndLoadBalancerResource = exports.KubernetesWorkload = void 0; +class KubernetesWorkload { +} +exports.KubernetesWorkload = KubernetesWorkload; +KubernetesWorkload.pod = 'Pod'; +KubernetesWorkload.replicaset = 'Replicaset'; +KubernetesWorkload.deployment = 'Deployment'; +KubernetesWorkload.statefulSet = 'StatefulSet'; +KubernetesWorkload.daemonSet = 'DaemonSet'; +KubernetesWorkload.job = 'job'; +KubernetesWorkload.cronjob = 'cronjob'; +class DiscoveryAndLoadBalancerResource { +} +exports.DiscoveryAndLoadBalancerResource = DiscoveryAndLoadBalancerResource; +DiscoveryAndLoadBalancerResource.service = 'service'; +DiscoveryAndLoadBalancerResource.ingress = 'ingress'; +class ServiceTypes { +} +exports.ServiceTypes = ServiceTypes; +ServiceTypes.loadBalancer = 'LoadBalancer'; +ServiceTypes.nodePort = 'NodePort'; +ServiceTypes.clusterIP = 'ClusterIP'; +exports.deploymentTypes = ['deployment', 'replicaset', 'daemonset', 'pod', 'statefulset']; +exports.workloadTypes = ['deployment', 'replicaset', 'daemonset', 'pod', 'statefulset', 'job', 'cronjob']; +exports.workloadTypesWithRolloutStatus = ['deployment', 'daemonset', 'statefulset']; +function getWorkflowAnnotationsJson(lastSuccessRunSha, workflowFilePath, filePathConfigs) { + return JSON.stringify(`{` + + `'run': '${process.env.GITHUB_RUN_ID}',` + + `'repository': '${process.env.GITHUB_REPOSITORY}',` + + `'workflow': '${process.env.GITHUB_WORKFLOW}',` + + `'workflowFileName': '${workflowFilePath.replace(".github/workflows/", "")}',` + + `'jobName': '${process.env.GITHUB_JOB}',` + + `'createdBy': '${process.env.GITHUB_ACTOR}',` + + `'runUri': 'https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}',` + + `'commit': '${process.env.GITHUB_SHA}',` + + `'lastSuccessRunCommit': '${lastSuccessRunSha}',` + + `'branch': '${process.env.GITHUB_REF}',` + + `'deployTimestamp': '${Date.now()}',` + + `'manifestsPaths': '${filePathConfigs.manifestFilePaths}',` + + `'dockerfilePaths': '${filePathConfigs.buildConfigs}',` + + `'provider': 'GitHub'` + + `}`); +} +exports.getWorkflowAnnotationsJson = getWorkflowAnnotationsJson; +function getWorkflowAnnotationKeyLabel(workflowFilePath) { + const hashKey = require("crypto").createHash("MD5") + .update(`${process.env.GITHUB_REPOSITORY}/${workflowFilePath}`) + .digest("hex"); + return `githubWorkflow_${hashKey}`; +} +exports.getWorkflowAnnotationKeyLabel = getWorkflowAnnotationKeyLabel; diff --git a/lib/utilities/strategy-helpers/deployment-helper.js b/lib/utilities/strategy-helpers/deployment-helper.js index 44b6a1e1..c11d3a17 100644 --- a/lib/utilities/strategy-helpers/deployment-helper.js +++ b/lib/utilities/strategy-helpers/deployment-helper.js @@ -1,177 +1,177 @@ -'use strict'; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.deploy = void 0; -const fs = require("fs"); -const core = require("@actions/core"); -const yaml = require("js-yaml"); -const canaryDeploymentHelper = require("./canary-deployment-helper"); -const KubernetesObjectUtility = require("../resource-object-utility"); -const TaskInputParameters = require("../../input-parameters"); -const models = require("../../constants"); -const fileHelper = require("../files-helper"); -const utils = require("../manifest-utilities"); -const KubernetesManifestUtility = require("../manifest-stability-utility"); -const KubernetesConstants = require("../../constants"); -const string_comparison_1 = require("./../string-comparison"); -const pod_canary_deployment_helper_1 = require("./pod-canary-deployment-helper"); -const smi_canary_deployment_helper_1 = require("./smi-canary-deployment-helper"); -const utility_1 = require("../utility"); -function deploy(kubectl, manifestFilePaths, deploymentStrategy) { - return __awaiter(this, void 0, void 0, function* () { - // get manifest files - let inputManifestFiles = getManifestFiles(manifestFilePaths); - // artifact substitution - inputManifestFiles = updateResourceObjects(inputManifestFiles, TaskInputParameters.imagePullSecrets, TaskInputParameters.containers); - // deployment - const deployedManifestFiles = deployManifests(inputManifestFiles, kubectl, isCanaryDeploymentStrategy(deploymentStrategy)); - // check manifest stability - const resourceTypes = KubernetesObjectUtility.getResources(deployedManifestFiles, models.deploymentTypes.concat([KubernetesConstants.DiscoveryAndLoadBalancerResource.service])); - yield checkManifestStability(kubectl, resourceTypes); - // print ingress resources - const ingressResources = KubernetesObjectUtility.getResources(deployedManifestFiles, [KubernetesConstants.DiscoveryAndLoadBalancerResource.ingress]); - ingressResources.forEach(ingressResource => { - kubectl.getResource(KubernetesConstants.DiscoveryAndLoadBalancerResource.ingress, ingressResource.name); - }); - // annotate resources - let allPods; - try { - allPods = JSON.parse((kubectl.getAllPods()).stdout); - } - catch (e) { - core.debug("Unable to parse pods; Error: " + e); - } - annotateAndLabelResources(deployedManifestFiles, kubectl, resourceTypes, allPods); - }); -} -exports.deploy = deploy; -function getManifestFiles(manifestFilePaths) { - const files = utils.getManifestFiles(manifestFilePaths); - if (files == null || files.length === 0) { - throw new Error(`ManifestFileNotFound : ${manifestFilePaths}`); - } - return files; -} -function deployManifests(files, kubectl, isCanaryDeploymentStrategy) { - let result; - if (isCanaryDeploymentStrategy) { - let canaryDeploymentOutput; - if (canaryDeploymentHelper.isSMICanaryStrategy()) { - canaryDeploymentOutput = smi_canary_deployment_helper_1.deploySMICanary(kubectl, files); - } - else { - canaryDeploymentOutput = pod_canary_deployment_helper_1.deployPodCanary(kubectl, files); - } - result = canaryDeploymentOutput.result; - files = canaryDeploymentOutput.newFilePaths; - } - else { - if (canaryDeploymentHelper.isSMICanaryStrategy()) { - const updatedManifests = appendStableVersionLabelToResource(files, kubectl); - result = kubectl.apply(updatedManifests, TaskInputParameters.forceDeployment); - } - else { - result = kubectl.apply(files, TaskInputParameters.forceDeployment); - } - } - utility_1.checkForErrors([result]); - return files; -} -function appendStableVersionLabelToResource(files, kubectl) { - const manifestFiles = []; - const newObjectsList = []; - files.forEach((filePath) => { - const fileContents = fs.readFileSync(filePath); - yaml.safeLoadAll(fileContents, function (inputObject) { - const kind = inputObject.kind; - if (KubernetesObjectUtility.isDeploymentEntity(kind)) { - const updatedObject = canaryDeploymentHelper.markResourceAsStable(inputObject); - newObjectsList.push(updatedObject); - } - else { - manifestFiles.push(filePath); - } - }); - }); - const updatedManifestFiles = fileHelper.writeObjectsToFile(newObjectsList); - manifestFiles.push(...updatedManifestFiles); - return manifestFiles; -} -function checkManifestStability(kubectl, resources) { - return __awaiter(this, void 0, void 0, function* () { - yield KubernetesManifestUtility.checkManifestStability(kubectl, resources); - }); -} -function annotateAndLabelResources(files, kubectl, resourceTypes, allPods) { - return __awaiter(this, void 0, void 0, function* () { - const workflowFilePath = yield utility_1.getWorkflowFilePath(TaskInputParameters.githubToken); - const filePathsConfig = yield utility_1.getFilePathsConfigs(); - const annotationKeyLabel = models.getWorkflowAnnotationKeyLabel(workflowFilePath); - annotateResources(files, kubectl, resourceTypes, allPods, annotationKeyLabel, workflowFilePath, filePathsConfig); - labelResources(files, kubectl, annotationKeyLabel); - }); -} -function annotateResources(files, kubectl, resourceTypes, allPods, annotationKey, workflowFilePath, filePathsConfig) { - const annotateResults = []; - const lastSuccessSha = utility_1.getLastSuccessfulRunSha(kubectl, TaskInputParameters.namespace, annotationKey); - let annotationKeyValStr = annotationKey + '=' + models.getWorkflowAnnotationsJson(lastSuccessSha, workflowFilePath, filePathsConfig); - annotateResults.push(kubectl.annotate('namespace', TaskInputParameters.namespace, annotationKeyValStr)); - annotateResults.push(kubectl.annotateFiles(files, annotationKeyValStr)); - resourceTypes.forEach(resource => { - if (resource.type.toUpperCase() !== models.KubernetesWorkload.pod.toUpperCase()) { - utility_1.annotateChildPods(kubectl, resource.type, resource.name, annotationKeyValStr, allPods) - .forEach(execResult => annotateResults.push(execResult)); - } - }); - utility_1.checkForErrors(annotateResults, true); -} -function labelResources(files, kubectl, label) { - let workflowName = process.env.GITHUB_WORKFLOW; - workflowName = workflowName.startsWith('.github/workflows/') ? - workflowName.replace(".github/workflows/", "") : workflowName; - const labels = [`workflowFriendlyName=${workflowName}`, `workflow=${label}`]; - utility_1.checkForErrors([kubectl.labelFiles(files, labels)], true); -} -function updateResourceObjects(filePaths, imagePullSecrets, containers) { - const newObjectsList = []; - const updateResourceObject = (inputObject) => { - if (!!imagePullSecrets && imagePullSecrets.length > 0) { - KubernetesObjectUtility.updateImagePullSecrets(inputObject, imagePullSecrets, false); - } - if (!!containers && containers.length > 0) { - KubernetesObjectUtility.updateImageDetails(inputObject, containers); - } - }; - filePaths.forEach((filePath) => { - const fileContents = fs.readFileSync(filePath).toString(); - yaml.safeLoadAll(fileContents, function (inputObject) { - if (inputObject && inputObject.kind) { - const kind = inputObject.kind; - if (KubernetesObjectUtility.isWorkloadEntity(kind)) { - updateResourceObject(inputObject); - } - else if (string_comparison_1.isEqual(kind, 'list', string_comparison_1.StringComparer.OrdinalIgnoreCase)) { - let items = inputObject.items; - if (items.length > 0) { - items.forEach((item) => updateResourceObject(item)); - } - } - newObjectsList.push(inputObject); - } - }); - }); - core.debug('New K8s objects after adding imagePullSecrets are :' + JSON.stringify(newObjectsList)); - const newFilePaths = fileHelper.writeObjectsToFile(newObjectsList); - return newFilePaths; -} -function isCanaryDeploymentStrategy(deploymentStrategy) { - return deploymentStrategy != null && deploymentStrategy.toUpperCase() === canaryDeploymentHelper.CANARY_DEPLOYMENT_STRATEGY.toUpperCase(); -} +'use strict'; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.deploy = void 0; +const fs = require("fs"); +const core = require("@actions/core"); +const yaml = require("js-yaml"); +const canaryDeploymentHelper = require("./canary-deployment-helper"); +const KubernetesObjectUtility = require("../resource-object-utility"); +const TaskInputParameters = require("../../input-parameters"); +const models = require("../../constants"); +const fileHelper = require("../files-helper"); +const utils = require("../manifest-utilities"); +const KubernetesManifestUtility = require("../manifest-stability-utility"); +const KubernetesConstants = require("../../constants"); +const string_comparison_1 = require("./../string-comparison"); +const pod_canary_deployment_helper_1 = require("./pod-canary-deployment-helper"); +const smi_canary_deployment_helper_1 = require("./smi-canary-deployment-helper"); +const utility_1 = require("../utility"); +function deploy(kubectl, manifestFilePaths, deploymentStrategy) { + return __awaiter(this, void 0, void 0, function* () { + // get manifest files + let inputManifestFiles = getManifestFiles(manifestFilePaths); + // artifact substitution + inputManifestFiles = updateResourceObjects(inputManifestFiles, TaskInputParameters.imagePullSecrets, TaskInputParameters.containers); + // deployment + const deployedManifestFiles = deployManifests(inputManifestFiles, kubectl, isCanaryDeploymentStrategy(deploymentStrategy)); + // check manifest stability + const resourceTypes = KubernetesObjectUtility.getResources(deployedManifestFiles, models.deploymentTypes.concat([KubernetesConstants.DiscoveryAndLoadBalancerResource.service])); + yield checkManifestStability(kubectl, resourceTypes); + // print ingress resources + const ingressResources = KubernetesObjectUtility.getResources(deployedManifestFiles, [KubernetesConstants.DiscoveryAndLoadBalancerResource.ingress]); + ingressResources.forEach(ingressResource => { + kubectl.getResource(KubernetesConstants.DiscoveryAndLoadBalancerResource.ingress, ingressResource.name); + }); + // annotate resources + let allPods; + try { + allPods = JSON.parse((kubectl.getAllPods()).stdout); + } + catch (e) { + core.debug("Unable to parse pods; Error: " + e); + } + annotateAndLabelResources(deployedManifestFiles, kubectl, resourceTypes, allPods); + }); +} +exports.deploy = deploy; +function getManifestFiles(manifestFilePaths) { + const files = utils.getManifestFiles(manifestFilePaths); + if (files == null || files.length === 0) { + throw new Error(`ManifestFileNotFound : ${manifestFilePaths}`); + } + return files; +} +function deployManifests(files, kubectl, isCanaryDeploymentStrategy) { + let result; + if (isCanaryDeploymentStrategy) { + let canaryDeploymentOutput; + if (canaryDeploymentHelper.isSMICanaryStrategy()) { + canaryDeploymentOutput = smi_canary_deployment_helper_1.deploySMICanary(kubectl, files); + } + else { + canaryDeploymentOutput = pod_canary_deployment_helper_1.deployPodCanary(kubectl, files); + } + result = canaryDeploymentOutput.result; + files = canaryDeploymentOutput.newFilePaths; + } + else { + if (canaryDeploymentHelper.isSMICanaryStrategy()) { + const updatedManifests = appendStableVersionLabelToResource(files, kubectl); + result = kubectl.apply(updatedManifests, TaskInputParameters.forceDeployment); + } + else { + result = kubectl.apply(files, TaskInputParameters.forceDeployment); + } + } + utility_1.checkForErrors([result]); + return files; +} +function appendStableVersionLabelToResource(files, kubectl) { + const manifestFiles = []; + const newObjectsList = []; + files.forEach((filePath) => { + const fileContents = fs.readFileSync(filePath); + yaml.safeLoadAll(fileContents, function (inputObject) { + const kind = inputObject.kind; + if (KubernetesObjectUtility.isDeploymentEntity(kind)) { + const updatedObject = canaryDeploymentHelper.markResourceAsStable(inputObject); + newObjectsList.push(updatedObject); + } + else { + manifestFiles.push(filePath); + } + }); + }); + const updatedManifestFiles = fileHelper.writeObjectsToFile(newObjectsList); + manifestFiles.push(...updatedManifestFiles); + return manifestFiles; +} +function checkManifestStability(kubectl, resources) { + return __awaiter(this, void 0, void 0, function* () { + yield KubernetesManifestUtility.checkManifestStability(kubectl, resources); + }); +} +function annotateAndLabelResources(files, kubectl, resourceTypes, allPods) { + return __awaiter(this, void 0, void 0, function* () { + const workflowFilePath = yield utility_1.getWorkflowFilePath(TaskInputParameters.githubToken); + const filePathsConfig = yield utility_1.getFilePathsConfigs(); + const annotationKeyLabel = models.getWorkflowAnnotationKeyLabel(workflowFilePath); + annotateResources(files, kubectl, resourceTypes, allPods, annotationKeyLabel, workflowFilePath, filePathsConfig); + labelResources(files, kubectl, annotationKeyLabel); + }); +} +function annotateResources(files, kubectl, resourceTypes, allPods, annotationKey, workflowFilePath, filePathsConfig) { + const annotateResults = []; + const lastSuccessSha = utility_1.getLastSuccessfulRunSha(kubectl, TaskInputParameters.namespace, annotationKey); + let annotationKeyValStr = annotationKey + '=' + models.getWorkflowAnnotationsJson(lastSuccessSha, workflowFilePath, filePathsConfig); + annotateResults.push(kubectl.annotate('namespace', TaskInputParameters.namespace, annotationKeyValStr)); + annotateResults.push(kubectl.annotateFiles(files, annotationKeyValStr)); + resourceTypes.forEach(resource => { + if (resource.type.toUpperCase() !== models.KubernetesWorkload.pod.toUpperCase()) { + utility_1.annotateChildPods(kubectl, resource.type, resource.name, annotationKeyValStr, allPods) + .forEach(execResult => annotateResults.push(execResult)); + } + }); + utility_1.checkForErrors(annotateResults, true); +} +function labelResources(files, kubectl, label) { + let workflowName = process.env.GITHUB_WORKFLOW; + workflowName = workflowName.startsWith('.github/workflows/') ? + workflowName.replace(".github/workflows/", "") : workflowName; + const labels = [`workflowFriendlyName=${workflowName}`, `workflow=${label}`]; + utility_1.checkForErrors([kubectl.labelFiles(files, labels)], true); +} +function updateResourceObjects(filePaths, imagePullSecrets, containers) { + const newObjectsList = []; + const updateResourceObject = (inputObject) => { + if (!!imagePullSecrets && imagePullSecrets.length > 0) { + KubernetesObjectUtility.updateImagePullSecrets(inputObject, imagePullSecrets, false); + } + if (!!containers && containers.length > 0) { + KubernetesObjectUtility.updateImageDetails(inputObject, containers); + } + }; + filePaths.forEach((filePath) => { + const fileContents = fs.readFileSync(filePath).toString(); + yaml.safeLoadAll(fileContents, function (inputObject) { + if (inputObject && inputObject.kind) { + const kind = inputObject.kind; + if (KubernetesObjectUtility.isWorkloadEntity(kind)) { + updateResourceObject(inputObject); + } + else if (string_comparison_1.isEqual(kind, 'list', string_comparison_1.StringComparer.OrdinalIgnoreCase)) { + let items = inputObject.items; + if (items.length > 0) { + items.forEach((item) => updateResourceObject(item)); + } + } + newObjectsList.push(inputObject); + } + }); + }); + core.debug('New K8s objects after adding imagePullSecrets are :' + JSON.stringify(newObjectsList)); + const newFilePaths = fileHelper.writeObjectsToFile(newObjectsList); + return newFilePaths; +} +function isCanaryDeploymentStrategy(deploymentStrategy) { + return deploymentStrategy != null && deploymentStrategy.toUpperCase() === canaryDeploymentHelper.CANARY_DEPLOYMENT_STRATEGY.toUpperCase(); +} diff --git a/lib/utilities/utility.js b/lib/utilities/utility.js index 146c62df..85dc21f7 100644 --- a/lib/utilities/utility.js +++ b/lib/utilities/utility.js @@ -1,219 +1,219 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.getCurrentTime = exports.getRandomInt = exports.sleep = exports.getFilePathsConfigs = exports.annotateChildPods = exports.getWorkflowFilePath = exports.getLastSuccessfulRunSha = exports.checkForErrors = exports.isEqual = exports.getExecutableExtension = void 0; -const os = require("os"); -const core = require("@actions/core"); -const githubClient_1 = require("../githubClient"); -const httpClient_1 = require("./httpClient"); -const exec = require("./exec"); -const inputParams = require("../input-parameters"); -function getExecutableExtension() { - if (os.type().match(/^Win/)) { - return '.exe'; - } - return ''; -} -exports.getExecutableExtension = getExecutableExtension; -function isEqual(str1, str2, ignoreCase) { - if (str1 == null && str2 == null) { - return true; - } - if (str1 == null || str2 == null) { - return false; - } - if (ignoreCase) { - return str1.toUpperCase() === str2.toUpperCase(); - } - else { - return str1 === str2; - } -} -exports.isEqual = isEqual; -function checkForErrors(execResults, warnIfError) { - if (execResults.length !== 0) { - let stderr = ''; - execResults.forEach(result => { - if (result && result.stderr) { - if (result.code !== 0) { - stderr += result.stderr + '\n'; - } - else { - core.warning(result.stderr); - } - } - }); - if (stderr.length > 0) { - if (warnIfError) { - core.warning(stderr.trim()); - } - else { - throw new Error(stderr.trim()); - } - } - } -} -exports.checkForErrors = checkForErrors; -function getLastSuccessfulRunSha(kubectl, namespaceName, annotationKey) { - try { - const result = kubectl.getResource('namespace', namespaceName); - if (result) { - if (result.stderr) { - core.warning(`${result.stderr}`); - return process.env.GITHUB_SHA; - } - else if (result.stdout) { - const annotationsSet = JSON.parse(result.stdout).metadata.annotations; - if (annotationsSet && annotationsSet[annotationKey]) { - return JSON.parse(annotationsSet[annotationKey].replace(/'/g, '"')).commit; - } - else { - return 'NA'; - } - } - } - } - catch (ex) { - core.warning(`Failed to get commits from cluster. ${JSON.stringify(ex)}`); - return ''; - } -} -exports.getLastSuccessfulRunSha = getLastSuccessfulRunSha; -function getWorkflowFilePath(githubToken) { - return __awaiter(this, void 0, void 0, function* () { - let workflowFilePath = process.env.GITHUB_WORKFLOW; - if (!workflowFilePath.startsWith('.github/workflows/')) { - const githubClient = new githubClient_1.GitHubClient(process.env.GITHUB_REPOSITORY, githubToken); - const response = yield githubClient.getWorkflows(); - if (response) { - if (response.statusCode == httpClient_1.StatusCodes.OK - && response.body - && response.body.total_count) { - if (response.body.total_count > 0) { - for (let workflow of response.body.workflows) { - if (process.env.GITHUB_WORKFLOW === workflow.name) { - workflowFilePath = workflow.path; - break; - } - } - } - } - else if (response.statusCode != httpClient_1.StatusCodes.OK) { - core.debug(`An error occured while getting list of workflows on the repo. Statuscode: ${response.statusCode}, StatusMessage: ${response.statusMessage}`); - } - } - else { - core.warning(`Failed to get response from workflow list API`); - } - } - return Promise.resolve(workflowFilePath); - }); -} -exports.getWorkflowFilePath = getWorkflowFilePath; -function annotateChildPods(kubectl, resourceType, resourceName, annotationKeyValStr, allPods) { - const commandExecutionResults = []; - let owner = resourceName; - if (resourceType.toLowerCase().indexOf('deployment') > -1) { - owner = kubectl.getNewReplicaSet(resourceName); - } - if (allPods && allPods.items && allPods.items.length > 0) { - allPods.items.forEach((pod) => { - const owners = pod.metadata.ownerReferences; - if (owners) { - owners.forEach(ownerRef => { - if (ownerRef.name === owner) { - commandExecutionResults.push(kubectl.annotate('pod', pod.metadata.name, annotationKeyValStr)); - } - }); - } - }); - } - return commandExecutionResults; -} -exports.annotateChildPods = annotateChildPods; -function getFilePathsConfigs() { - return __awaiter(this, void 0, void 0, function* () { - let filePathsConfig = {}; - const BUILD_CONFIG_KEY = 'buildConfigs'; - const MANIFEST_PATHS_KEY = 'manifestFilePaths'; - const HELM_CHART_KEY = 'helmChartFilePaths'; - const DOCKERFILE_PATH_LABEL_KEY = 'dockerfile-path'; - const DOCKERFILE_PATH_KEY = 'dockerfilePath'; - const CONTAINER_REG_KEY = 'containerRegistryServer'; - let inputManifestFiles = inputParams.manifests || []; - filePathsConfig[MANIFEST_PATHS_KEY] = JSON.stringify(inputManifestFiles); - let helmChartPaths = process.env.HELM_CHART_PATHS || ''; - filePathsConfig[HELM_CHART_KEY] = helmChartPaths; - //Fetch labels from each image - let imageToBuildConfigMap = {}; - let imageNames = core.getInput('images').split('\n'); - for (const image of imageNames) { - let args = [image]; - let resultObj; - let buildConfigMap = {}; - let containerRegistryName = image.toString().split('/')[0]; - try { - let usrname = process.env.CR_USERNAME || null; - let pwd = process.env.CR_PASSWORD || null; - if (pwd && usrname) { - let loginArgs = [containerRegistryName, '--username', usrname, '--password', pwd]; - yield exec.exec('docker login ', loginArgs, true).then(res => { - if (res.stderr != '' && !res.success) { - throw new Error(`docker login failed with: ${res.stderr.match(/(.*)\s*$/)[0]}`); - } - }); - } - yield exec.exec('docker pull ', args, true).then(res => { - if (res.stderr != '' && !res.success) { - throw new Error(`docker images pull failed with: ${res.stderr.match(/(.*)\s*$/)[0]}`); - } - }); - yield exec.exec('docker inspect --type=image', args, true).then(res => { - if (res.stderr != '' && !res.success) { - throw new Error(`docker inspect call failed with: ${res.stderr.match(/(.*)\s*$/)[0]}`); - } - if (!res.stdout) { - resultObj = JSON.parse(res.stdout); - } - }); - } - catch (ex) { - core.warning(`Failed to get dockerfile paths for image ${image.toString()} | ` + ex); - } - if (!resultObj) { - resultObj = resultObj[0]; - if (!(resultObj.Config) && !(resultObj.Config.Labels) && !(resultObj.Config.Labels[DOCKERFILE_PATH_LABEL_KEY])) { - buildConfigMap[DOCKERFILE_PATH_KEY] = resultObj.Config.Labels[DOCKERFILE_PATH_LABEL_KEY]; - } - //Add CR server name to build config - buildConfigMap[CONTAINER_REG_KEY] = containerRegistryName; - if (!resultObj.Id) { - imageToBuildConfigMap[resultObj.Id] = buildConfigMap; - } - } - } - filePathsConfig[BUILD_CONFIG_KEY] = JSON.stringify(imageToBuildConfigMap); - return Promise.resolve(filePathsConfig); - }); -} -exports.getFilePathsConfigs = getFilePathsConfigs; -function sleep(timeout) { - return new Promise(resolve => setTimeout(resolve, timeout)); -} -exports.sleep = sleep; -function getRandomInt(max) { - return Math.floor(Math.random() * Math.floor(max)); -} -exports.getRandomInt = getRandomInt; -function getCurrentTime() { - return new Date().getTime(); -} -exports.getCurrentTime = getCurrentTime; +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getCurrentTime = exports.getRandomInt = exports.sleep = exports.getFilePathsConfigs = exports.annotateChildPods = exports.getWorkflowFilePath = exports.getLastSuccessfulRunSha = exports.checkForErrors = exports.isEqual = exports.getExecutableExtension = void 0; +const os = require("os"); +const core = require("@actions/core"); +const githubClient_1 = require("../githubClient"); +const httpClient_1 = require("./httpClient"); +const exec = require("./exec"); +const inputParams = require("../input-parameters"); +function getExecutableExtension() { + if (os.type().match(/^Win/)) { + return '.exe'; + } + return ''; +} +exports.getExecutableExtension = getExecutableExtension; +function isEqual(str1, str2, ignoreCase) { + if (str1 == null && str2 == null) { + return true; + } + if (str1 == null || str2 == null) { + return false; + } + if (ignoreCase) { + return str1.toUpperCase() === str2.toUpperCase(); + } + else { + return str1 === str2; + } +} +exports.isEqual = isEqual; +function checkForErrors(execResults, warnIfError) { + if (execResults.length !== 0) { + let stderr = ''; + execResults.forEach(result => { + if (result && result.stderr) { + if (result.code !== 0) { + stderr += result.stderr + '\n'; + } + else { + core.warning(result.stderr); + } + } + }); + if (stderr.length > 0) { + if (warnIfError) { + core.warning(stderr.trim()); + } + else { + throw new Error(stderr.trim()); + } + } + } +} +exports.checkForErrors = checkForErrors; +function getLastSuccessfulRunSha(kubectl, namespaceName, annotationKey) { + try { + const result = kubectl.getResource('namespace', namespaceName); + if (result) { + if (result.stderr) { + core.warning(`${result.stderr}`); + return process.env.GITHUB_SHA; + } + else if (result.stdout) { + const annotationsSet = JSON.parse(result.stdout).metadata.annotations; + if (annotationsSet && annotationsSet[annotationKey]) { + return JSON.parse(annotationsSet[annotationKey].replace(/'/g, '"')).commit; + } + else { + return 'NA'; + } + } + } + } + catch (ex) { + core.warning(`Failed to get commits from cluster. ${JSON.stringify(ex)}`); + return ''; + } +} +exports.getLastSuccessfulRunSha = getLastSuccessfulRunSha; +function getWorkflowFilePath(githubToken) { + return __awaiter(this, void 0, void 0, function* () { + let workflowFilePath = process.env.GITHUB_WORKFLOW; + if (!workflowFilePath.startsWith('.github/workflows/')) { + const githubClient = new githubClient_1.GitHubClient(process.env.GITHUB_REPOSITORY, githubToken); + const response = yield githubClient.getWorkflows(); + if (response) { + if (response.statusCode == httpClient_1.StatusCodes.OK + && response.body + && response.body.total_count) { + if (response.body.total_count > 0) { + for (let workflow of response.body.workflows) { + if (process.env.GITHUB_WORKFLOW === workflow.name) { + workflowFilePath = workflow.path; + break; + } + } + } + } + else if (response.statusCode != httpClient_1.StatusCodes.OK) { + core.debug(`An error occured while getting list of workflows on the repo. Statuscode: ${response.statusCode}, StatusMessage: ${response.statusMessage}`); + } + } + else { + core.warning(`Failed to get response from workflow list API`); + } + } + return Promise.resolve(workflowFilePath); + }); +} +exports.getWorkflowFilePath = getWorkflowFilePath; +function annotateChildPods(kubectl, resourceType, resourceName, annotationKeyValStr, allPods) { + const commandExecutionResults = []; + let owner = resourceName; + if (resourceType.toLowerCase().indexOf('deployment') > -1) { + owner = kubectl.getNewReplicaSet(resourceName); + } + if (allPods && allPods.items && allPods.items.length > 0) { + allPods.items.forEach((pod) => { + const owners = pod.metadata.ownerReferences; + if (owners) { + owners.forEach(ownerRef => { + if (ownerRef.name === owner) { + commandExecutionResults.push(kubectl.annotate('pod', pod.metadata.name, annotationKeyValStr)); + } + }); + } + }); + } + return commandExecutionResults; +} +exports.annotateChildPods = annotateChildPods; +function getFilePathsConfigs() { + return __awaiter(this, void 0, void 0, function* () { + let filePathsConfig = {}; + const BUILD_CONFIG_KEY = 'buildConfigs'; + const MANIFEST_PATHS_KEY = 'manifestFilePaths'; + const HELM_CHART_KEY = 'helmChartFilePaths'; + const DOCKERFILE_PATH_LABEL_KEY = 'dockerfile-path'; + const DOCKERFILE_PATH_KEY = 'dockerfilePath'; + const CONTAINER_REG_KEY = 'containerRegistryServer'; + let inputManifestFiles = inputParams.manifests || []; + filePathsConfig[MANIFEST_PATHS_KEY] = JSON.stringify(inputManifestFiles); + let helmChartPaths = process.env.HELM_CHART_PATHS || ''; + filePathsConfig[HELM_CHART_KEY] = helmChartPaths; + //Fetch labels from each image + let imageToBuildConfigMap = {}; + let imageNames = core.getInput('images').split('\n'); + for (const image of imageNames) { + let args = [image]; + let resultObj; + let buildConfigMap = {}; + let containerRegistryName = image.toString().split('/')[0]; + try { + let usrname = process.env.CR_USERNAME || null; + let pwd = process.env.CR_PASSWORD || null; + if (pwd && usrname) { + let loginArgs = [containerRegistryName, '--username', usrname, '--password', pwd]; + yield exec.exec('docker login ', loginArgs, true).then(res => { + if (res.stderr != '' && !res.success) { + throw new Error(`docker login failed with: ${res.stderr.match(/(.*)\s*$/)[0]}`); + } + }); + } + yield exec.exec('docker pull ', args, true).then(res => { + if (res.stderr != '' && !res.success) { + throw new Error(`docker images pull failed with: ${res.stderr.match(/(.*)\s*$/)[0]}`); + } + }); + yield exec.exec('docker inspect --type=image', args, true).then(res => { + if (res.stderr != '' && !res.success) { + throw new Error(`docker inspect call failed with: ${res.stderr.match(/(.*)\s*$/)[0]}`); + } + if (!res.stdout) { + resultObj = JSON.parse(res.stdout); + } + }); + } + catch (ex) { + core.warning(`Failed to get dockerfile paths for image ${image.toString()} | ` + ex); + } + if (!resultObj) { + resultObj = resultObj[0]; + if (!(resultObj.Config) && !(resultObj.Config.Labels) && !(resultObj.Config.Labels[DOCKERFILE_PATH_LABEL_KEY])) { + buildConfigMap[DOCKERFILE_PATH_KEY] = resultObj.Config.Labels[DOCKERFILE_PATH_LABEL_KEY]; + } + //Add CR server name to build config + buildConfigMap[CONTAINER_REG_KEY] = containerRegistryName; + if (!resultObj.Id) { + imageToBuildConfigMap[resultObj.Id] = buildConfigMap; + } + } + } + filePathsConfig[BUILD_CONFIG_KEY] = JSON.stringify(imageToBuildConfigMap); + return Promise.resolve(filePathsConfig); + }); +} +exports.getFilePathsConfigs = getFilePathsConfigs; +function sleep(timeout) { + return new Promise(resolve => setTimeout(resolve, timeout)); +} +exports.sleep = sleep; +function getRandomInt(max) { + return Math.floor(Math.random() * Math.floor(max)); +} +exports.getRandomInt = getRandomInt; +function getCurrentTime() { + return new Date().getTime(); +} +exports.getCurrentTime = getCurrentTime; diff --git a/src/utilities/exec.ts b/src/utilities/exec.ts index ccabb0a1..ac2c00ec 100644 --- a/src/utilities/exec.ts +++ b/src/utilities/exec.ts @@ -1,33 +1,33 @@ -import * as aexec from '@actions/exec'; - -export interface ExecResult { - success: boolean; - stdout: string; - stderr: string; -} - -export const exec = async (command: string, args: string[] = [], silent?: boolean): Promise => { - let stdout: string = ''; - let stderr: string = ''; - - const options: aexec.ExecOptions = { - silent: silent, - ignoreReturnCode: true - }; - options.listeners = { - stdout: (data: Buffer) => { - stdout += data.toString(); - }, - stderr: (data: Buffer) => { - stderr += data.toString(); - } - }; - - const returnCode: number = await aexec.exec(command, args, options); - - return { - success: returnCode === 0, - stdout: stdout.trim(), - stderr: stderr.trim() - }; +import * as aexec from '@actions/exec'; + +export interface ExecResult { + success: boolean; + stdout: string; + stderr: string; +} + +export const exec = async (command: string, args: string[] = [], silent?: boolean): Promise => { + let stdout: string = ''; + let stderr: string = ''; + + const options: aexec.ExecOptions = { + silent: silent, + ignoreReturnCode: true + }; + options.listeners = { + stdout: (data: Buffer) => { + stdout += data.toString(); + }, + stderr: (data: Buffer) => { + stderr += data.toString(); + } + }; + + const returnCode: number = await aexec.exec(command, args, options); + + return { + success: returnCode === 0, + stdout: stdout.trim(), + stderr: stderr.trim() + }; }; \ No newline at end of file