mirror of
https://github.com/Azure/k8s-deploy.git
synced 2026-04-11 16:52:18 +08:00
Initial commit for config files annotations (#78)
* Initial commit for config files annotations * Tests fixed * bug fixes * bug fixes * bug fixes * bug fixes * Fixing annotations * Fixing annotations * Fixing annotations * Review comment changes * Review comment changes * Review comment changes * JSON structure fixes of config paths * LF/CRLF fix * review comments changes * JSON structure fixes * JSON structure fixes * JSON structure fixes * JSON structure fixes * JSON structure fixes * JSON structure fixes * JSON structure fixes * JSON structure fixes * Added reading dockerfile from env var, code cleanup * Tests edited
This commit is contained in:
commit
068b665bf3
@ -38,7 +38,7 @@ const getAllPodsMock = {
|
||||
|
||||
const getNamespaceMock = {
|
||||
'code': 0,
|
||||
'stdout': '{"apiVersion": "v1","kind": "Namespace","metadata": {"annotations": {"githubWorkflow_c11401b9d232942bac19cbc5bc32b42d": "{\'run\': \'202489005\',\'repository\': \'testUser/hello-kubernetes\',\'workflow\': \'workflow1\',\'jobName\': \'build-and-deploy\',\'createdBy\': \'testUser\',\'runUri\': \'https://github.com/testUser/hello-kubernetes/actions/runs/202489005\',\'commit\': \'currentCommit\',\'lastSuccessRunCommit\': \'lastCommit\',\'branch\': \'refs/heads/branch-rename\',\'deployTimestamp\': \'1597062957973\',\'provider\': \'GitHub\'}","githubWorkflow_21fd7a597282ca5adc05ba99018b3706": "{\'run\': \'202504411\',\'repository\': \'testUser/hello-kubernetes\',\'workflow\': \'workflowMaster\',\'jobName\': \'build-and-deploy\',\'createdBy\': \'testUser\',\'runUri\': \'https://github.com/testUser/hello-kubernetes/actions/runs/202504411\',\'commit\': \'currentCommit1\',\'lastSuccessRunCommit\': \'NA\',\'branch\': \'refs/heads/master\',\'deployTimestamp\': \'1597063919873\',\'provider\': \'GitHub\'}"}},"spec": {"finalizers": ["kubernetes"]},"status": {"phase": "Active"}}'
|
||||
'stdout': '{"apiVersion": "v1","kind": "Namespace","metadata": {"annotations": {"githubWorkflow_c11401b9d232942bac19cbc5bc32b42d": "{\'run\': \'202489005\',\'repository\': \'testUser/hello-kubernetes\',\'workflow\': \'workflow1\',\'jobName\': \'build-and-deploy\',\'createdBy\': \'testUser\',\'runUri\': \'https://github.com/testUser/hello-kubernetes/actions/runs/202489005\',\'commit\': \'currentCommit\',\'lastSuccessRunCommit\': \'lastCommit\',\'branch\': \'refs/heads/branch-rename\',\'deployTimestamp\': \'1597062957973\',\'dockerfilePaths\': \'{}\',\'manifestsPaths\': \'[]\',\'helmChartPaths\': \'[]\',\'provider\': \'GitHub\'}","githubWorkflow_21fd7a597282ca5adc05ba99018b3706": "{\'run\': \'202504411\',\'repository\': \'testUser/hello-kubernetes\',\'workflow\': \'workflowMaster\',\'jobName\': \'build-and-deploy\',\'createdBy\': \'testUser\',\'runUri\': \'https://github.com/testUser/hello-kubernetes/actions/runs/202504411\',\'commit\': \'currentCommit1\',\'lastSuccessRunCommit\': \'NA\',\'branch\': \'refs/heads/master\',\'deployTimestamp\': \'1597063919873\',\'dockerfilePaths\': \'{}\',\'manifestsPaths\': \'[]\',\'helmChartPaths\': \'[]\',\'provider\': \'GitHub\'}"}},"spec": {"finalizers": ["kubernetes"]},"status": {"phase": "Active"}}'
|
||||
};
|
||||
|
||||
const getWorkflowsUrlResponse = {
|
||||
@ -293,7 +293,8 @@ test("deployment - deploy() - deploy force flag on", async () => {
|
||||
});
|
||||
|
||||
test("deployment - deploy() - Annotate & label resources", async () => {
|
||||
let annotationKeyValStr = getWorkflowAnnotationKeyLabel(process.env.GITHUB_WORKFLOW) + '=' + getWorkflowAnnotationsJson('currentCommit', '.github/workflows/workflow.yml');
|
||||
let filepathConfigs = { manifestsPaths :['manifests/deployment.yaml'], helmChartPaths : [], dockerfilePaths :{}} ;
|
||||
let annotationKeyValStr = getWorkflowAnnotationKeyLabel(process.env.GITHUB_WORKFLOW) + '=' + getWorkflowAnnotationsJson('currentCommit', '.github/workflows/workflow.yml', filepathConfigs);
|
||||
const KubernetesManifestUtilityMock = mocked(KubernetesManifestUtility, true);
|
||||
KubernetesManifestUtilityMock.checkManifestStability = jest.fn().mockReturnValue("");
|
||||
const KubernetesObjectUtilityMock = mocked(KubernetesObjectUtility, true);
|
||||
@ -301,6 +302,7 @@ test("deployment - deploy() - Annotate & label resources", async () => {
|
||||
const fileHelperMock = mocked(fileHelper, true);
|
||||
fileHelperMock.writeObjectsToFile = jest.fn().mockReturnValue(["~/Deployment_testapp_currentTimestamp"]);
|
||||
jest.spyOn(utility, 'getWorkflowFilePath').mockImplementation(() => Promise.resolve(process.env.GITHUB_WORKFLOW));
|
||||
jest.spyOn(utility, 'getFilePathsConfigs').mockImplementation(()=> Promise.resolve(filepathConfigs));
|
||||
|
||||
const kubeCtl: jest.Mocked<Kubectl> = new Kubectl("") as any;
|
||||
kubeCtl.apply = jest.fn().mockReturnValue("");
|
||||
@ -321,7 +323,8 @@ test("deployment - deploy() - Annotate & label resources", async () => {
|
||||
|
||||
test("deployment - deploy() - Annotate & label resources for a new workflow", async () => {
|
||||
process.env.GITHUB_WORKFLOW = '.github/workflows/NewWorkflow.yml';
|
||||
let annotationKeyValStr = getWorkflowAnnotationKeyLabel(process.env.GITHUB_WORKFLOW) + '=' + getWorkflowAnnotationsJson('NA', '.github/workflows/NewWorkflow.yml');
|
||||
let filepathConfigs = { manifestsPaths :['manifests/deployment.yaml'], helmChartPaths : [], dockerfilePaths :{}} ;
|
||||
let annotationKeyValStr = getWorkflowAnnotationKeyLabel(process.env.GITHUB_WORKFLOW) + '=' + getWorkflowAnnotationsJson('NA', '.github/workflows/NewWorkflow.yml', filepathConfigs);
|
||||
const KubernetesManifestUtilityMock = mocked(KubernetesManifestUtility, true);
|
||||
KubernetesManifestUtilityMock.checkManifestStability = jest.fn().mockReturnValue("");
|
||||
const KubernetesObjectUtilityMock = mocked(KubernetesObjectUtility, true);
|
||||
|
||||
@ -25,21 +25,24 @@ 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) {
|
||||
return `{`
|
||||
+ `'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()}',`
|
||||
+ `'provider': 'GitHub'`
|
||||
+ `}`;
|
||||
function getWorkflowAnnotationsJson(lastSuccessRunSha, workflowFilePath, filePathConfigs) {
|
||||
let annotationObject = {};
|
||||
annotationObject["run"] = process.env.GITHUB_RUN_ID;
|
||||
annotationObject["repository"] = process.env.GITHUB_REPOSITORY;
|
||||
annotationObject["workflow"] = process.env.GITHUB_WORKFLOW;
|
||||
annotationObject["workflowFileName"] = workflowFilePath.replace(".github/workflows/", "");
|
||||
annotationObject["jobName"] = process.env.GITHUB_JOB;
|
||||
annotationObject["createdBy"] = process.env.GITHUB_ACTOR;
|
||||
annotationObject["runUri"] = `https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`;
|
||||
annotationObject["commit"] = process.env.GITHUB_SHA;
|
||||
annotationObject["lastSuccessRunCommit"] = lastSuccessRunSha;
|
||||
annotationObject["branch"] = process.env.GITHUB_REF;
|
||||
annotationObject["deployTimestamp"] = Date.now();
|
||||
annotationObject["dockerfilePaths"] = filePathConfigs.dockerfilePaths;
|
||||
annotationObject["manifestsPaths"] = filePathConfigs.manifestFilePaths;
|
||||
annotationObject["helmChartPaths"] = filePathConfigs.helmChartFilePaths;
|
||||
annotationObject["provider"] = "GitHub";
|
||||
return JSON.stringify(annotationObject);
|
||||
}
|
||||
exports.getWorkflowAnnotationsJson = getWorkflowAnnotationsJson;
|
||||
function getWorkflowAnnotationKeyLabel(workflowFilePath) {
|
||||
|
||||
35
lib/utilities/exec.js
Normal file
35
lib/utilities/exec.js
Normal file
@ -0,0 +1,35 @@
|
||||
"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.exec = void 0;
|
||||
const aexec = require("@actions/exec");
|
||||
exports.exec = (command, args = [], silent) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
let stdout = '';
|
||||
let stderr = '';
|
||||
const options = {
|
||||
silent: silent,
|
||||
ignoreReturnCode: true
|
||||
};
|
||||
options.listeners = {
|
||||
stdout: (data) => {
|
||||
stdout += data.toString();
|
||||
},
|
||||
stderr: (data) => {
|
||||
stderr += data.toString();
|
||||
}
|
||||
};
|
||||
const returnCode = yield aexec.exec(command, args, options);
|
||||
return {
|
||||
success: returnCode === 0,
|
||||
stdout: stdout.trim(),
|
||||
stderr: stderr.trim()
|
||||
};
|
||||
});
|
||||
@ -113,15 +113,16 @@ function 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);
|
||||
annotateResources(files, kubectl, resourceTypes, allPods, annotationKeyLabel, workflowFilePath, filePathsConfig);
|
||||
labelResources(files, kubectl, annotationKeyLabel);
|
||||
});
|
||||
}
|
||||
function annotateResources(files, kubectl, resourceTypes, allPods, annotationKey, workflowFilePath) {
|
||||
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);
|
||||
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 => {
|
||||
|
||||
@ -9,11 +9,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getCurrentTime = exports.getRandomInt = exports.sleep = exports.annotateChildPods = exports.getWorkflowFilePath = exports.getLastSuccessfulRunSha = exports.checkForErrors = exports.isEqual = exports.getExecutableExtension = void 0;
|
||||
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';
|
||||
@ -137,6 +139,81 @@ function annotateChildPods(kubectl, resourceType, resourceName, annotationKeyVal
|
||||
return commandExecutionResults;
|
||||
}
|
||||
exports.annotateChildPods = annotateChildPods;
|
||||
function getFilePathsConfigs() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let filePathsConfig = {};
|
||||
const MANIFEST_PATHS_KEY = 'manifestFilePaths';
|
||||
const HELM_CHART_KEY = 'helmChartFilePaths';
|
||||
const DOCKERFILE_PATH_KEY = 'dockerfilePaths';
|
||||
const DOCKERFILE_PATH_LABEL_KEY = 'dockerfile-path';
|
||||
let inputManifestFiles = inputParams.manifests || [];
|
||||
filePathsConfig[MANIFEST_PATHS_KEY] = inputManifestFiles;
|
||||
let helmChartPaths = (process.env.HELM_CHART_PATHS && process.env.HELM_CHART_PATHS.split('\n').filter(path => path != "")) || [];
|
||||
filePathsConfig[HELM_CHART_KEY] = helmChartPaths;
|
||||
//Parsing dockerfile paths for images
|
||||
let imageNames = core.getInput('images').split('\n');
|
||||
let imageDockerfilePathMap = {};
|
||||
let pathKey, pathVal;
|
||||
//Fetching from env var if available
|
||||
let dockerfilePathsList = (process.env.DOCKERFILE_PATHS && process.env.DOCKERFILE_PATHS.split('\n')) || [];
|
||||
dockerfilePathsList.forEach(path => {
|
||||
if (path) {
|
||||
pathKey = path.split(' ')[0];
|
||||
pathVal = path.split(' ')[1];
|
||||
imageDockerfilePathMap[pathKey] = pathVal;
|
||||
}
|
||||
});
|
||||
//Fetching from image lable if available
|
||||
for (const image of imageNames) {
|
||||
let args = [image];
|
||||
let resultObj;
|
||||
let containerRegistryName = image;
|
||||
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])) {
|
||||
pathVal = resultObj.Config.Labels[DOCKERFILE_PATH_LABEL_KEY];
|
||||
}
|
||||
else {
|
||||
pathVal = 'Not available';
|
||||
}
|
||||
if (!imageDockerfilePathMap[image]) { //If (image : someVal) does not exist from env var parsing then add
|
||||
imageDockerfilePathMap[image] = pathVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
filePathsConfig[DOCKERFILE_PATH_KEY] = imageDockerfilePathMap;
|
||||
return Promise.resolve(filePathsConfig);
|
||||
});
|
||||
}
|
||||
exports.getFilePathsConfigs = getFilePathsConfigs;
|
||||
function sleep(timeout) {
|
||||
return new Promise(resolve => setTimeout(resolve, timeout));
|
||||
}
|
||||
|
||||
15873
package-lock.json
generated
15873
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -8,16 +8,16 @@
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/tool-cache": "^1.0.0",
|
||||
"@actions/io": "^1.0.0",
|
||||
"@actions/core": "^1.2.6",
|
||||
"@actions/exec": "^1.0.0",
|
||||
"@actions/exec": "^1.0.4",
|
||||
"@actions/io": "^1.0.0",
|
||||
"@actions/tool-cache": "^1.0.0",
|
||||
"js-yaml": "3.13.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^25.2.2",
|
||||
"@types/node": "^12.0.10",
|
||||
"jest": "^25.0.0",
|
||||
"@types/jest": "^25.2.2",
|
||||
"ts-jest": "^25.5.1",
|
||||
"typescript": "3.9.5"
|
||||
}
|
||||
|
||||
@ -25,21 +25,25 @@ export const deploymentTypes: string[] = ['deployment', 'replicaset', 'daemonset
|
||||
export const workloadTypes: string[] = ['deployment', 'replicaset', 'daemonset', 'pod', 'statefulset', 'job', 'cronjob'];
|
||||
export const workloadTypesWithRolloutStatus: string[] = ['deployment', 'daemonset', 'statefulset'];
|
||||
|
||||
export function getWorkflowAnnotationsJson(lastSuccessRunSha: string, workflowFilePath: string): string {
|
||||
return `{`
|
||||
+ `'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()}',`
|
||||
+ `'provider': 'GitHub'`
|
||||
+ `}`;
|
||||
export function getWorkflowAnnotationsJson(lastSuccessRunSha: string, workflowFilePath: string, filePathConfigs: any): string {
|
||||
let annotationObject: any = {};
|
||||
annotationObject["run"] = process.env.GITHUB_RUN_ID;
|
||||
annotationObject["repository"] = process.env.GITHUB_REPOSITORY;
|
||||
annotationObject["workflow"] = process.env.GITHUB_WORKFLOW;
|
||||
annotationObject["workflowFileName"] = workflowFilePath.replace(".github/workflows/", "");
|
||||
annotationObject["jobName"] = process.env.GITHUB_JOB;
|
||||
annotationObject["createdBy"] = process.env.GITHUB_ACTOR;
|
||||
annotationObject["runUri"] = `https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`;
|
||||
annotationObject["commit"] = process.env.GITHUB_SHA;
|
||||
annotationObject["lastSuccessRunCommit"] = lastSuccessRunSha;
|
||||
annotationObject["branch"] = process.env.GITHUB_REF;
|
||||
annotationObject["deployTimestamp"] = Date.now();
|
||||
annotationObject["dockerfilePaths"] = filePathConfigs.dockerfilePaths;
|
||||
annotationObject["manifestsPaths"] = filePathConfigs.manifestFilePaths
|
||||
annotationObject["helmChartPaths"] = filePathConfigs.helmChartFilePaths;
|
||||
annotationObject["provider"] = "GitHub";
|
||||
|
||||
return JSON.stringify(annotationObject);
|
||||
}
|
||||
|
||||
export function getWorkflowAnnotationKeyLabel(workflowFilePath: string): string {
|
||||
|
||||
33
src/utilities/exec.ts
Normal file
33
src/utilities/exec.ts
Normal file
@ -0,0 +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<ExecResult> => {
|
||||
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()
|
||||
};
|
||||
};
|
||||
@ -17,7 +17,7 @@ import { IExecSyncResult } from '../../utilities/tool-runner';
|
||||
|
||||
import { deployPodCanary } from './pod-canary-deployment-helper';
|
||||
import { deploySMICanary } from './smi-canary-deployment-helper';
|
||||
import { checkForErrors, annotateChildPods, getWorkflowFilePath, getLastSuccessfulRunSha } from "../utility";
|
||||
import { checkForErrors, annotateChildPods, getWorkflowFilePath, getLastSuccessfulRunSha, getFilePathsConfigs } from "../utility";
|
||||
|
||||
|
||||
export async function deploy(kubectl: Kubectl, manifestFilePaths: string[], deploymentStrategy: string) {
|
||||
@ -114,15 +114,16 @@ async function checkManifestStability(kubectl: Kubectl, resources: Resource[]):
|
||||
|
||||
async function annotateAndLabelResources(files: string[], kubectl: Kubectl, resourceTypes: Resource[], allPods: any) {
|
||||
const workflowFilePath = await getWorkflowFilePath(TaskInputParameters.githubToken);
|
||||
const filePathsConfig = await getFilePathsConfigs();
|
||||
const annotationKeyLabel = models.getWorkflowAnnotationKeyLabel(workflowFilePath);
|
||||
annotateResources(files, kubectl, resourceTypes, allPods, annotationKeyLabel, workflowFilePath);
|
||||
annotateResources(files, kubectl, resourceTypes, allPods, annotationKeyLabel, workflowFilePath, filePathsConfig);
|
||||
labelResources(files, kubectl, annotationKeyLabel);
|
||||
}
|
||||
|
||||
function annotateResources(files: string[], kubectl: Kubectl, resourceTypes: Resource[], allPods: any, annotationKey: string, workflowFilePath: string) {
|
||||
function annotateResources(files: string[], kubectl: Kubectl, resourceTypes: Resource[], allPods: any, annotationKey: string, workflowFilePath: string, filePathsConfig: string) {
|
||||
const annotateResults: IExecSyncResult[] = [];
|
||||
const lastSuccessSha = getLastSuccessfulRunSha(kubectl, TaskInputParameters.namespace, annotationKey);
|
||||
let annotationKeyValStr = annotationKey + '=' + models.getWorkflowAnnotationsJson(lastSuccessSha, workflowFilePath);
|
||||
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 => {
|
||||
|
||||
@ -4,6 +4,8 @@ import { IExecSyncResult } from './tool-runner';
|
||||
import { Kubectl } from '../kubectl-object-model';
|
||||
import { GitHubClient } from '../githubClient';
|
||||
import { StatusCodes } from "./httpClient";
|
||||
import * as exec from "./exec";
|
||||
import * as inputParams from "../input-parameters";
|
||||
|
||||
export function getExecutableExtension(): string {
|
||||
if (os.type().match(/^Win/)) {
|
||||
@ -127,6 +129,93 @@ export function annotateChildPods(kubectl: Kubectl, resourceType: string, resour
|
||||
return commandExecutionResults;
|
||||
}
|
||||
|
||||
export async function getFilePathsConfigs(): Promise<any> {
|
||||
|
||||
let filePathsConfig: any = {};
|
||||
const MANIFEST_PATHS_KEY = 'manifestFilePaths';
|
||||
const HELM_CHART_KEY = 'helmChartFilePaths';
|
||||
const DOCKERFILE_PATH_KEY = 'dockerfilePaths';
|
||||
const DOCKERFILE_PATH_LABEL_KEY = 'dockerfile-path';
|
||||
|
||||
let inputManifestFiles = inputParams.manifests || [];
|
||||
filePathsConfig[MANIFEST_PATHS_KEY] = inputManifestFiles;
|
||||
|
||||
let helmChartPaths = (process.env.HELM_CHART_PATHS && process.env.HELM_CHART_PATHS.split('\n').filter(path => path != "")) || [];
|
||||
filePathsConfig[HELM_CHART_KEY] = helmChartPaths;
|
||||
|
||||
//Parsing dockerfile paths for images
|
||||
let imageNames = core.getInput('images').split('\n');
|
||||
let imageDockerfilePathMap: any = {};
|
||||
let pathKey: any, pathVal: any;
|
||||
|
||||
//Fetching from env var if available
|
||||
let dockerfilePathsList: any[] = (process.env.DOCKERFILE_PATHS && process.env.DOCKERFILE_PATHS.split('\n')) || [];
|
||||
dockerfilePathsList.forEach(path => {
|
||||
if(path){
|
||||
pathKey = path.split(' ')[0];
|
||||
pathVal = path.split(' ')[1];
|
||||
imageDockerfilePathMap[pathKey] = pathVal;
|
||||
}
|
||||
})
|
||||
|
||||
//Fetching from image lable if available
|
||||
for(const image of imageNames){
|
||||
let args: string[] = [image];
|
||||
let resultObj: any;
|
||||
let containerRegistryName = image;
|
||||
|
||||
try{
|
||||
let usrname = process.env.CR_USERNAME || null;
|
||||
let pwd = process.env.CR_PASSWORD || null;
|
||||
if(pwd && usrname)
|
||||
{
|
||||
let loginArgs: string[] = [containerRegistryName, '--username', usrname, '--password', pwd];
|
||||
await 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]}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await 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]}`);
|
||||
}
|
||||
});
|
||||
|
||||
await 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])){
|
||||
pathVal = resultObj.Config.Labels[DOCKERFILE_PATH_LABEL_KEY];
|
||||
}
|
||||
else{
|
||||
pathVal = 'Not available';
|
||||
}
|
||||
if(!imageDockerfilePathMap[image]){ //If (image : someVal) does not exist from env var parsing then add
|
||||
imageDockerfilePathMap[image] = pathVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filePathsConfig[DOCKERFILE_PATH_KEY] = imageDockerfilePathMap;
|
||||
|
||||
return Promise.resolve(filePathsConfig);
|
||||
}
|
||||
|
||||
export function sleep(timeout: number) {
|
||||
return new Promise(resolve => setTimeout(resolve, timeout));
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user