зеркало из https://github.com/Azure/k8s-deploy.git
New traceability fields added to annotations (#90)
* New traceability fields
This commit is contained in:
Родитель
51b95a5ca2
Коммит
04921d7d06
|
@ -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 deploymentConfig: utility.DeploymentConfig = { manifestFilePaths: ['manifests/deployment.yaml'], helmChartFilePaths: [], dockerfilePaths: {} };
|
||||
let annotationKeyValStr = getWorkflowAnnotationKeyLabel(process.env.GITHUB_WORKFLOW) + '=' + getWorkflowAnnotationsJson('currentCommit', '.github/workflows/workflow.yml', deploymentConfig);
|
||||
const KubernetesManifestUtilityMock = mocked(KubernetesManifestUtility, true);
|
||||
KubernetesManifestUtilityMock.checkManifestStability = jest.fn().mockReturnValue("");
|
||||
const KubernetesObjectUtilityMock = mocked(KubernetesObjectUtility, true);
|
||||
|
@ -301,8 +302,9 @@ test("deployment - deploy() - Annotate & label resources", async () => {
|
|||
const fileHelperMock = mocked(fileHelper, true);
|
||||
const fsMock = (mocked(fs, true));
|
||||
fileHelperMock.getTempDirectory = jest.fn().mockReturnValue("~/Deployment_testapp_currentTimestamp");
|
||||
fsMock.writeFileSync =jest.fn().mockReturnValue("");
|
||||
fsMock.writeFileSync = jest.fn().mockReturnValue("");
|
||||
jest.spyOn(utility, 'getWorkflowFilePath').mockImplementation(() => Promise.resolve(process.env.GITHUB_WORKFLOW));
|
||||
jest.spyOn(utility, 'getDeploymentConfig').mockImplementation(() => Promise.resolve(deploymentConfig));
|
||||
|
||||
const kubeCtl: jest.Mocked<Kubectl> = new Kubectl("") as any;
|
||||
kubeCtl.apply = jest.fn().mockReturnValue("");
|
||||
|
@ -323,7 +325,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 deploymentConfig: utility.DeploymentConfig = { manifestFilePaths: ['manifests/deployment.yaml'], helmChartFilePaths: [], dockerfilePaths: {} }
|
||||
let annotationKeyValStr = getWorkflowAnnotationKeyLabel(process.env.GITHUB_WORKFLOW) + '=' + getWorkflowAnnotationsJson('NA', '.github/workflows/NewWorkflow.yml', deploymentConfig);
|
||||
const KubernetesManifestUtilityMock = mocked(KubernetesManifestUtility, true);
|
||||
KubernetesManifestUtilityMock.checkManifestStability = jest.fn().mockReturnValue("");
|
||||
const KubernetesObjectUtilityMock = mocked(KubernetesObjectUtility, true);
|
||||
|
@ -331,8 +334,9 @@ test("deployment - deploy() - Annotate & label resources for a new workflow", as
|
|||
const fileHelperMock = mocked(fileHelper, true);
|
||||
const fsMock = (mocked(fs, true));
|
||||
fileHelperMock.getTempDirectory = jest.fn().mockReturnValue("~/Deployment_testapp_currentTimestamp");
|
||||
fsMock.writeFileSync =jest.fn().mockReturnValue("");
|
||||
fsMock.writeFileSync = jest.fn().mockReturnValue("");
|
||||
jest.spyOn(httpClient, 'sendRequest').mockImplementation(() => Promise.resolve(getWorkflowsUrlResponse));
|
||||
jest.spyOn(utility, 'getDeploymentConfig').mockImplementation(() => Promise.resolve(deploymentConfig));
|
||||
|
||||
const kubeCtl: jest.Mocked<Kubectl> = new Kubectl("") as any;
|
||||
kubeCtl.apply = jest.fn().mockReturnValue("");
|
||||
|
|
|
@ -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, deploymentConfig) {
|
||||
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"] = deploymentConfig.dockerfilePaths;
|
||||
annotationObject["manifestsPaths"] = deploymentConfig.manifestFilePaths;
|
||||
annotationObject["helmChartPaths"] = deploymentConfig.helmChartFilePaths;
|
||||
annotationObject["provider"] = "GitHub";
|
||||
return JSON.stringify(annotationObject);
|
||||
}
|
||||
exports.getWorkflowAnnotationsJson = getWorkflowAnnotationsJson;
|
||||
function getWorkflowAnnotationKeyLabel(workflowFilePath) {
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DockerExec = void 0;
|
||||
const tool_runner_1 = require("./utilities/tool-runner");
|
||||
class DockerExec {
|
||||
constructor(dockerPath) {
|
||||
this.dockerPath = dockerPath;
|
||||
}
|
||||
;
|
||||
pull(image, args, silent) {
|
||||
args = ['pull', image, ...args];
|
||||
let result = this.execute(args, silent);
|
||||
if (result.stderr != '' && result.code != 0) {
|
||||
throw new Error(`docker images pull failed with: ${result.error}`);
|
||||
}
|
||||
}
|
||||
inspect(image, args, silent) {
|
||||
args = ['inspect', image, ...args];
|
||||
let result = this.execute(args, silent);
|
||||
if (result.stderr != '' && result.code != 0) {
|
||||
throw new Error(`docker inspect call failed with: ${result.error}`);
|
||||
}
|
||||
return result.stdout;
|
||||
}
|
||||
execute(args, silent) {
|
||||
const command = new tool_runner_1.ToolRunner(this.dockerPath);
|
||||
command.arg(args);
|
||||
return command.execSync({ silent: !!silent });
|
||||
}
|
||||
}
|
||||
exports.DockerExec = DockerExec;
|
|
@ -134,15 +134,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 deploymentConfig = yield utility_1.getDeploymentConfig();
|
||||
const annotationKeyLabel = models.getWorkflowAnnotationKeyLabel(workflowFilePath);
|
||||
annotateResources(files, kubectl, resourceTypes, allPods, annotationKeyLabel, workflowFilePath);
|
||||
annotateResources(files, kubectl, resourceTypes, allPods, annotationKeyLabel, workflowFilePath, deploymentConfig);
|
||||
labelResources(files, kubectl, annotationKeyLabel);
|
||||
});
|
||||
}
|
||||
function annotateResources(files, kubectl, resourceTypes, allPods, annotationKey, workflowFilePath) {
|
||||
function annotateResources(files, kubectl, resourceTypes, allPods, annotationKey, workflowFilePath, deploymentConfig) {
|
||||
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, deploymentConfig);
|
||||
annotateResults.push(kubectl.annotate('namespace', TaskInputParameters.namespace, annotationKeyValStr));
|
||||
annotateResults.push(kubectl.annotateFiles(files, annotationKeyValStr));
|
||||
resourceTypes.forEach(resource => {
|
||||
|
|
|
@ -9,11 +9,14 @@ 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.getDeploymentConfig = 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 inputParams = require("../input-parameters");
|
||||
const docker_object_model_1 = require("../docker-object-model");
|
||||
const io = require("@actions/io");
|
||||
function getExecutableExtension() {
|
||||
if (os.type().match(/^Win/)) {
|
||||
return '.exe';
|
||||
|
@ -138,6 +141,36 @@ function annotateChildPods(kubectl, resourceType, resourceName, annotationKeyVal
|
|||
return commandExecutionResults;
|
||||
}
|
||||
exports.annotateChildPods = annotateChildPods;
|
||||
function getDeploymentConfig() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const inputManifestFiles = inputParams.manifests || [];
|
||||
const helmChartPaths = (process.env.HELM_CHART_PATHS && process.env.HELM_CHART_PATHS.split('\n').filter(path => path != "")) || [];
|
||||
const imageNames = inputParams.containers || [];
|
||||
let imageDockerfilePathMap = {};
|
||||
//Fetching from image label if available
|
||||
for (const image of imageNames) {
|
||||
let imageConfig, imageInspectResult;
|
||||
try {
|
||||
yield checkDockerPath();
|
||||
var dockerExec = new docker_object_model_1.DockerExec('docker');
|
||||
dockerExec.pull(image, [], true);
|
||||
imageInspectResult = dockerExec.inspect(image, [], true);
|
||||
imageConfig = JSON.parse(imageInspectResult)[0];
|
||||
imageDockerfilePathMap[image] = getDockerfilePath(imageConfig);
|
||||
}
|
||||
catch (ex) {
|
||||
core.warning(`Failed to get dockerfile path for image ${image.toString()} | ` + ex);
|
||||
}
|
||||
}
|
||||
const deploymentConfig = {
|
||||
manifestFilePaths: inputManifestFiles,
|
||||
helmChartFilePaths: helmChartPaths,
|
||||
dockerfilePaths: imageDockerfilePathMap
|
||||
};
|
||||
return Promise.resolve(deploymentConfig);
|
||||
});
|
||||
}
|
||||
exports.getDeploymentConfig = getDeploymentConfig;
|
||||
function sleep(timeout) {
|
||||
return new Promise(resolve => setTimeout(resolve, timeout));
|
||||
}
|
||||
|
@ -150,3 +183,32 @@ function getCurrentTime() {
|
|||
return new Date().getTime();
|
||||
}
|
||||
exports.getCurrentTime = getCurrentTime;
|
||||
function checkDockerPath() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let dockerPath = yield io.which('docker', false);
|
||||
if (!dockerPath) {
|
||||
throw new Error('Docker is not installed.');
|
||||
}
|
||||
});
|
||||
}
|
||||
function getDockerfilePath(imageConfig) {
|
||||
const DOCKERFILE_PATH_LABEL_KEY = 'dockerfile-path';
|
||||
const ref = process.env.GITHUB_REF && process.env.GITHUB_REF.replace('refs/heads/', '').replace('refs/tags/', '');
|
||||
let pathLabel, pathLink, pathValue = '';
|
||||
if (imageConfig) {
|
||||
if ((imageConfig.Config) && (imageConfig.Config.Labels) && (imageConfig.Config.Labels[DOCKERFILE_PATH_LABEL_KEY])) {
|
||||
pathLabel = imageConfig.Config.Labels[DOCKERFILE_PATH_LABEL_KEY];
|
||||
if (pathValue.startsWith('./')) { //if it is relative filepath convert to link from current repo
|
||||
pathLink = `https://github.com/${process.env.GITHUB_REPOSITORY}/blob/${ref}/${pathLabel}`;
|
||||
pathValue = pathLink;
|
||||
}
|
||||
else {
|
||||
pathValue = pathLabel;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pathValue = '';
|
||||
}
|
||||
}
|
||||
return pathValue;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
'use strict';
|
||||
import { DeploymentConfig } from "./utilities/utility";
|
||||
|
||||
export class KubernetesWorkload {
|
||||
public static pod: string = 'Pod';
|
||||
|
@ -25,21 +26,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, deploymentConfig: DeploymentConfig): 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"] = deploymentConfig.dockerfilePaths;
|
||||
annotationObject["manifestsPaths"] = deploymentConfig.manifestFilePaths
|
||||
annotationObject["helmChartPaths"] = deploymentConfig.helmChartFilePaths;
|
||||
annotationObject["provider"] = "GitHub";
|
||||
|
||||
return JSON.stringify(annotationObject);
|
||||
}
|
||||
|
||||
export function getWorkflowAnnotationKeyLabel(workflowFilePath: string): string {
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
import { ToolRunner, IExecOptions, IExecSyncResult } from "./utilities/tool-runner";
|
||||
|
||||
export class DockerExec {
|
||||
private dockerPath: string;
|
||||
|
||||
constructor(dockerPath: string) {
|
||||
this.dockerPath = dockerPath;
|
||||
};
|
||||
|
||||
public pull(image: string, args: string[], silent?: boolean) {
|
||||
args = ['pull', image, ...args];
|
||||
let result: IExecSyncResult = this.execute(args, silent);
|
||||
if (result.stderr != '' && result.code != 0) {
|
||||
throw new Error(`docker images pull failed with: ${result.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
public inspect(image: string, args: string[], silent?: boolean): any {
|
||||
args = ['inspect', image, ...args];
|
||||
let result: IExecSyncResult = this.execute(args, silent);
|
||||
if (result.stderr != '' && result.code != 0) {
|
||||
throw new Error(`docker inspect call failed with: ${result.error}`);
|
||||
}
|
||||
return result.stdout;
|
||||
}
|
||||
|
||||
private execute(args: string[], silent?: boolean) {
|
||||
const command = new ToolRunner(this.dockerPath);
|
||||
command.arg(args);
|
||||
|
||||
return command.execSync({ silent: !!silent } as IExecOptions);
|
||||
}
|
||||
}
|
|
@ -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, DeploymentConfig, getDeploymentConfig } from "../utility";
|
||||
import { isBlueGreenDeploymentStrategy, isIngressRoute, isSMIRoute, routeBlueGreen } from './blue-green-helper';
|
||||
import { deployBlueGreenService } from './service-blue-green-helper';
|
||||
import { deployBlueGreenIngress } from './ingress-blue-green-helper';
|
||||
|
@ -130,15 +130,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 deploymentConfig = await getDeploymentConfig();
|
||||
const annotationKeyLabel = models.getWorkflowAnnotationKeyLabel(workflowFilePath);
|
||||
annotateResources(files, kubectl, resourceTypes, allPods, annotationKeyLabel, workflowFilePath);
|
||||
annotateResources(files, kubectl, resourceTypes, allPods, annotationKeyLabel, workflowFilePath, deploymentConfig);
|
||||
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, deploymentConfig: DeploymentConfig) {
|
||||
const annotateResults: IExecSyncResult[] = [];
|
||||
const lastSuccessSha = getLastSuccessfulRunSha(kubectl, TaskInputParameters.namespace, annotationKey);
|
||||
let annotationKeyValStr = annotationKey + '=' + models.getWorkflowAnnotationsJson(lastSuccessSha, workflowFilePath);
|
||||
let annotationKeyValStr = annotationKey + '=' + models.getWorkflowAnnotationsJson(lastSuccessSha, workflowFilePath, deploymentConfig);
|
||||
annotateResults.push(kubectl.annotate('namespace', TaskInputParameters.namespace, annotationKeyValStr));
|
||||
annotateResults.push(kubectl.annotateFiles(files, annotationKeyValStr));
|
||||
resourceTypes.forEach(resource => {
|
||||
|
|
|
@ -4,6 +4,15 @@ import { IExecSyncResult } from './tool-runner';
|
|||
import { Kubectl } from '../kubectl-object-model';
|
||||
import { GitHubClient } from '../githubClient';
|
||||
import { StatusCodes } from "./httpClient";
|
||||
import * as inputParams from "../input-parameters";
|
||||
import { DockerExec } from '../docker-object-model';
|
||||
import * as io from '@actions/io';
|
||||
|
||||
export interface DeploymentConfig {
|
||||
manifestFilePaths: string[];
|
||||
helmChartFilePaths: string[];
|
||||
dockerfilePaths: any;
|
||||
}
|
||||
|
||||
export function getExecutableExtension(): string {
|
||||
if (os.type().match(/^Win/)) {
|
||||
|
@ -129,6 +138,39 @@ export function annotateChildPods(kubectl: Kubectl, resourceType: string, resour
|
|||
return commandExecutionResults;
|
||||
}
|
||||
|
||||
export async function getDeploymentConfig(): Promise<DeploymentConfig> {
|
||||
|
||||
const inputManifestFiles = inputParams.manifests || [];
|
||||
const helmChartPaths = (process.env.HELM_CHART_PATHS && process.env.HELM_CHART_PATHS.split('\n').filter(path => path != "")) || [];
|
||||
const imageNames = inputParams.containers || [];
|
||||
let imageDockerfilePathMap: { [id: string]: string; } = {};
|
||||
|
||||
//Fetching from image label if available
|
||||
for (const image of imageNames) {
|
||||
let imageConfig: any, imageInspectResult: string;
|
||||
|
||||
try {
|
||||
await checkDockerPath();
|
||||
var dockerExec: DockerExec = new DockerExec('docker');
|
||||
dockerExec.pull(image, [], true);
|
||||
imageInspectResult = dockerExec.inspect(image, [], true);
|
||||
imageConfig = JSON.parse(imageInspectResult)[0];
|
||||
imageDockerfilePathMap[image] = getDockerfilePath(imageConfig);
|
||||
}
|
||||
catch (ex) {
|
||||
core.warning(`Failed to get dockerfile path for image ${image.toString()} | ` + ex);
|
||||
}
|
||||
}
|
||||
|
||||
const deploymentConfig = <DeploymentConfig>{
|
||||
manifestFilePaths: inputManifestFiles,
|
||||
helmChartFilePaths: helmChartPaths,
|
||||
dockerfilePaths: imageDockerfilePathMap
|
||||
};
|
||||
|
||||
return Promise.resolve(deploymentConfig);
|
||||
}
|
||||
|
||||
export function sleep(timeout: number) {
|
||||
return new Promise(resolve => setTimeout(resolve, timeout));
|
||||
}
|
||||
|
@ -140,3 +182,32 @@ export function getRandomInt(max: number) {
|
|||
export function getCurrentTime(): number {
|
||||
return new Date().getTime();
|
||||
}
|
||||
|
||||
async function checkDockerPath() {
|
||||
let dockerPath = await io.which('docker', false);
|
||||
if (!dockerPath) {
|
||||
throw new Error('Docker is not installed.');
|
||||
}
|
||||
}
|
||||
|
||||
function getDockerfilePath(imageConfig: any): string {
|
||||
const DOCKERFILE_PATH_LABEL_KEY = 'dockerfile-path';
|
||||
const ref: string = process.env.GITHUB_REF && process.env.GITHUB_REF.replace('refs/heads/', '').replace('refs/tags/', '');
|
||||
let pathLabel: string, pathLink: string, pathValue: string = '';
|
||||
if (imageConfig) {
|
||||
if ((imageConfig.Config) && (imageConfig.Config.Labels) && (imageConfig.Config.Labels[DOCKERFILE_PATH_LABEL_KEY])) {
|
||||
pathLabel = imageConfig.Config.Labels[DOCKERFILE_PATH_LABEL_KEY];
|
||||
if (pathValue.startsWith('./')) { //if it is relative filepath convert to link from current repo
|
||||
pathLink = `https://github.com/${process.env.GITHUB_REPOSITORY}/blob/${ref}/${pathLabel}`;
|
||||
pathValue = pathLink;
|
||||
}
|
||||
else {
|
||||
pathValue = pathLabel;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pathValue = '';
|
||||
}
|
||||
}
|
||||
return pathValue;
|
||||
}
|
Загрузка…
Ссылка в новой задаче