mirror of
https://github.com/Azure/k8s-deploy.git
synced 2026-04-14 18:42:20 +08:00
Changes for annotate namespace and test cases
This commit is contained in:
parent
fc977b0f8b
commit
62f2b9a070
@ -6,6 +6,8 @@ import * as deployment from '../src/utilities/strategy-helpers/deployment-helper
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as io from '@actions/io';
|
import * as io from '@actions/io';
|
||||||
import * as toolCache from '@actions/tool-cache';
|
import * as toolCache from '@actions/tool-cache';
|
||||||
|
import * as fileHelper from '../src/utilities/files-helper';
|
||||||
|
import { workflowAnnotations } from '../src/constants';
|
||||||
|
|
||||||
import { Kubectl, Resource } from '../src/kubectl-object-model';
|
import { Kubectl, Resource } from '../src/kubectl-object-model';
|
||||||
|
|
||||||
@ -24,9 +26,29 @@ const stableVersionUrl = 'https://storage.googleapis.com/kubernetes-release/rele
|
|||||||
|
|
||||||
var deploymentYaml = "";
|
var deploymentYaml = "";
|
||||||
|
|
||||||
|
const getAllPodsMock = {
|
||||||
|
'code': 0,
|
||||||
|
'stdout': '{"apiVersion": "v1","items": [{"apiVersion": "v1","kind": "Pod","metadata": {"labels": {"app": "testapp","pod-template-hash": "776cbc86f9"},"name": "testpod-776cbc86f9-pjrb6","namespace": "testnamespace","ownerReferences": [{"apiVersion": "apps/v1","blockOwnerDeletion": true,"controller": true,"kind": "ReplicaSet","name": "testpod-776cbc86f9","uid": "de544628-6589-4354-81fe-05faf00d336a"}],"resourceVersion": "12362496","selfLink": "/api/v1/namespaces/akskodey8187/pods/akskodey-776cbc86f9-pjrb6","uid": "c7d5f4c1-11a1-4884-8a66-09b015c72f69"},"spec": {"containers": [{"image": "imageId","imagePullPolicy": "IfNotPresent","name": "containerName","ports": [{"containerPort": 80,"protocol": "TCP"}]}]},"status": {"hostIP": "10.240.0.4","phase": "Running","podIP": "10.244.0.25","qosClass": "BestEffort","startTime": "2020-06-04T07:59:42Z"}}]}'
|
||||||
|
};
|
||||||
|
|
||||||
|
const getNamespaceMock = {
|
||||||
|
'code': 0,
|
||||||
|
'stdout': '{"apiVersion": "v1","kind": "Namespace","metadata": {"annotations": {"workflow": ".github/workflows/workflow.yml","runUri": "https://github.com/testRepo/actions/runs/12345"}},"spec": {"finalizers": ["kubernetes"]},"status": {"phase": "Active"}}'
|
||||||
|
};
|
||||||
|
|
||||||
|
const resources: Resource[] = [{ type: "Deployment", name: "AppName" }];
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
deploymentYaml = fs.readFileSync(path.join(__dirname, 'manifests', 'deployment.yml'), 'utf8');
|
deploymentYaml = fs.readFileSync(path.join(__dirname, 'manifests', 'deployment.yml'), 'utf8');
|
||||||
|
|
||||||
process.env["KUBECONFIG"] = 'kubeConfig';
|
process.env["KUBECONFIG"] = 'kubeConfig';
|
||||||
|
process.env['GITHUB_RUN_ID'] = '12345';
|
||||||
|
process.env['GITHUB_WORKFLOW'] = '.github/workflows/workflow.yml';
|
||||||
|
process.env['GITHUB_JOB'] = 'build-and-deploy';
|
||||||
|
process.env['GITHUB_ACTOR'] = 'testUser';
|
||||||
|
process.env['GITHUB_REPOSITORY'] = 'testRepo';
|
||||||
|
process.env['GITHUB_SHA'] = 'testCommit';
|
||||||
|
process.env['GITHUB_REF'] = 'testBranch';
|
||||||
})
|
})
|
||||||
|
|
||||||
test("setKubectlPath() - install a particular version", async () => {
|
test("setKubectlPath() - install a particular version", async () => {
|
||||||
@ -182,9 +204,12 @@ test("deployment - deploy() - Invokes with manifestfiles", async () => {
|
|||||||
const KubernetesObjectUtilityMock = mocked(KubernetesObjectUtility, true);
|
const KubernetesObjectUtilityMock = mocked(KubernetesObjectUtility, true);
|
||||||
const kubeCtl: jest.Mocked<Kubectl> = new Kubectl("") as any;
|
const kubeCtl: jest.Mocked<Kubectl> = new Kubectl("") as any;
|
||||||
kubeCtl.apply = jest.fn().mockReturnValue("");
|
kubeCtl.apply = jest.fn().mockReturnValue("");
|
||||||
const resources: Resource[] = [{ type: "Deployment", name: "AppName" }];
|
|
||||||
KubernetesObjectUtilityMock.getResources = jest.fn().mockReturnValue(resources);
|
KubernetesObjectUtilityMock.getResources = jest.fn().mockReturnValue(resources);
|
||||||
kubeCtl.getResource = jest.fn().mockReturnValue("");
|
kubeCtl.getResource = jest.fn().mockReturnValue(getNamespaceMock);
|
||||||
|
kubeCtl.getAllPods = jest.fn().mockReturnValue(getAllPodsMock);
|
||||||
|
kubeCtl.describe = jest.fn().mockReturnValue("");
|
||||||
|
kubeCtl.annotateFiles = jest.fn().mockReturnValue("");
|
||||||
|
kubeCtl.annotate = jest.fn().mockReturnValue("");
|
||||||
KubernetesManifestUtilityMock.checkManifestStability = jest.fn().mockReturnValue("");
|
KubernetesManifestUtilityMock.checkManifestStability = jest.fn().mockReturnValue("");
|
||||||
|
|
||||||
const readFileSpy = jest.spyOn(fs, 'readFileSync').mockImplementation(() => deploymentYaml);
|
const readFileSpy = jest.spyOn(fs, 'readFileSync').mockImplementation(() => deploymentYaml);
|
||||||
@ -193,4 +218,25 @@ test("deployment - deploy() - Invokes with manifestfiles", async () => {
|
|||||||
await expect(deployment.deploy(kubeCtl, ['manifests/deployment.yaml'], undefined)).resolves.not.toThrowError();
|
await expect(deployment.deploy(kubeCtl, ['manifests/deployment.yaml'], undefined)).resolves.not.toThrowError();
|
||||||
expect(readFileSpy).toBeCalledWith("manifests/deployment.yaml");
|
expect(readFileSpy).toBeCalledWith("manifests/deployment.yaml");
|
||||||
expect(kubeCtl.getResource).toBeCalledWith("ingress", "AppName");
|
expect(kubeCtl.getResource).toBeCalledWith("ingress", "AppName");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("deployment - deploy() - Annotate resources", async () => {
|
||||||
|
const KubernetesManifestUtilityMock = mocked(KubernetesManifestUtility, true);
|
||||||
|
KubernetesManifestUtilityMock.checkManifestStability = jest.fn().mockReturnValue("");
|
||||||
|
const KubernetesObjectUtilityMock = mocked(KubernetesObjectUtility, true);
|
||||||
|
KubernetesObjectUtilityMock.getResources = jest.fn().mockReturnValue(resources);
|
||||||
|
const fileHelperMock = mocked(fileHelper, true);
|
||||||
|
fileHelperMock.writeObjectsToFile = jest.fn().mockReturnValue(["~/Deployment_testapp_currentTimestamp"]);
|
||||||
|
const kubeCtl: jest.Mocked<Kubectl> = new Kubectl("") as any;
|
||||||
|
kubeCtl.apply = jest.fn().mockReturnValue("");
|
||||||
|
kubeCtl.getResource = jest.fn().mockReturnValue(getNamespaceMock);
|
||||||
|
kubeCtl.getAllPods = jest.fn().mockReturnValue(getAllPodsMock);
|
||||||
|
kubeCtl.getNewReplicaSet = jest.fn().mockReturnValue("testpod-776cbc86f9");
|
||||||
|
kubeCtl.annotateFiles = jest.fn().mockReturnValue("");
|
||||||
|
kubeCtl.annotate = jest.fn().mockReturnValue("");
|
||||||
|
|
||||||
|
//Invoke and assert
|
||||||
|
await expect(deployment.deploy(kubeCtl, ['manifests/deployment.yaml'], undefined)).resolves.not.toThrowError();
|
||||||
|
expect(kubeCtl.annotateFiles).toBeCalledWith(["~/Deployment_testapp_currentTimestamp"], workflowAnnotations, true);
|
||||||
|
expect(kubeCtl.annotate).toBeCalledTimes(2);
|
||||||
});
|
});
|
||||||
@ -27,10 +27,12 @@ exports.workloadTypes = ['deployment', 'replicaset', 'daemonset', 'pod', 'statef
|
|||||||
exports.workloadTypesWithRolloutStatus = ['deployment', 'daemonset', 'statefulset'];
|
exports.workloadTypesWithRolloutStatus = ['deployment', 'daemonset', 'statefulset'];
|
||||||
exports.workflowAnnotations = [
|
exports.workflowAnnotations = [
|
||||||
`run=${process.env['GITHUB_RUN_ID']}`,
|
`run=${process.env['GITHUB_RUN_ID']}`,
|
||||||
`workflow="${process.env['GITHUB_WORKFLOW']}"`,
|
`repository=${process.env['GITHUB_REPOSITORY']}`,
|
||||||
`jobName="${process.env['GITHUB_JOB']}"`,
|
`workflow=${process.env['GITHUB_WORKFLOW']}`,
|
||||||
|
`jobName=${process.env['GITHUB_JOB']}`,
|
||||||
`createdBy=${process.env['GITHUB_ACTOR']}`,
|
`createdBy=${process.env['GITHUB_ACTOR']}`,
|
||||||
`runUri=https://github.com/${process.env['GITHUB_REPOSITORY']}/actions/runs/${process.env['GITHUB_RUN_ID']}`,
|
`runUri=https://github.com/${process.env['GITHUB_REPOSITORY']}/actions/runs/${process.env['GITHUB_RUN_ID']}`,
|
||||||
`commit=${process.env['GITHUB_SHA']}`,
|
`commit=${process.env['GITHUB_SHA']}`,
|
||||||
`branch=${process.env['GITHUB_REF']}`
|
`branch=${process.env['GITHUB_REF']}`,
|
||||||
|
`deployTimestamp=${Date.now()}`
|
||||||
];
|
];
|
||||||
|
|||||||
@ -112,6 +112,7 @@ function checkManifestStability(kubectl, resources) {
|
|||||||
}
|
}
|
||||||
function annotateResources(files, kubectl, resourceTypes, allPods) {
|
function annotateResources(files, kubectl, resourceTypes, allPods) {
|
||||||
const annotateResults = [];
|
const annotateResults = [];
|
||||||
|
annotateResults.push(utility_1.annotateNamespace(kubectl, TaskInputParameters.namespace));
|
||||||
annotateResults.push(kubectl.annotateFiles(files, models.workflowAnnotations, true));
|
annotateResults.push(kubectl.annotateFiles(files, models.workflowAnnotations, true));
|
||||||
resourceTypes.forEach(resource => {
|
resourceTypes.forEach(resource => {
|
||||||
if (resource.type.toUpperCase() !== models.KubernetesWorkload.pod.toUpperCase()) {
|
if (resource.type.toUpperCase() !== models.KubernetesWorkload.pod.toUpperCase()) {
|
||||||
@ -149,7 +150,7 @@ function updateResourceObjects(filePaths, imagePullSecrets, containers) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
core.debug('New K8s objects after addin imagePullSecrets are :' + JSON.stringify(newObjectsList));
|
core.debug('New K8s objects after adding imagePullSecrets are :' + JSON.stringify(newObjectsList));
|
||||||
const newFilePaths = fileHelper.writeObjectsToFile(newObjectsList);
|
const newFilePaths = fileHelper.writeObjectsToFile(newObjectsList);
|
||||||
return newFilePaths;
|
return newFilePaths;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.getCurrentTime = exports.getRandomInt = exports.sleep = exports.annotateChildPods = exports.checkForErrors = exports.isEqual = exports.getExecutableExtension = void 0;
|
exports.getCurrentTime = exports.getRandomInt = exports.sleep = exports.annotateNamespace = exports.annotateChildPods = exports.checkForErrors = exports.isEqual = exports.getExecutableExtension = void 0;
|
||||||
const os = require("os");
|
const os = require("os");
|
||||||
const core = require("@actions/core");
|
const core = require("@actions/core");
|
||||||
const constants_1 = require("../constants");
|
const constants_1 = require("../constants");
|
||||||
@ -71,6 +71,20 @@ function annotateChildPods(kubectl, resourceType, resourceName, allPods) {
|
|||||||
return commandExecutionResults;
|
return commandExecutionResults;
|
||||||
}
|
}
|
||||||
exports.annotateChildPods = annotateChildPods;
|
exports.annotateChildPods = annotateChildPods;
|
||||||
|
function annotateNamespace(kubectl, namespaceName) {
|
||||||
|
let annotate = true;
|
||||||
|
const result = kubectl.getResource('namespace', namespaceName);
|
||||||
|
this.checkForErrors([result]);
|
||||||
|
const annotationsSet = JSON.parse(result.stdout).metadata.annotations;
|
||||||
|
if (!!annotationsSet && !!annotationsSet.runUri && annotationsSet.runUri.indexOf(process.env['GITHUB_REPOSITORY']) == -1) {
|
||||||
|
annotate = false;
|
||||||
|
core.debug(`Skipping 'annotate namespace' as namespace annotated by other workflow`);
|
||||||
|
}
|
||||||
|
if (annotate) {
|
||||||
|
return kubectl.annotate('namespace', namespaceName, constants_1.workflowAnnotations, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.annotateNamespace = annotateNamespace;
|
||||||
function sleep(timeout) {
|
function sleep(timeout) {
|
||||||
return new Promise(resolve => setTimeout(resolve, timeout));
|
return new Promise(resolve => setTimeout(resolve, timeout));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,12 +25,14 @@ export const deploymentTypes: string[] = ['deployment', 'replicaset', 'daemonset
|
|||||||
export const workloadTypes: string[] = ['deployment', 'replicaset', 'daemonset', 'pod', 'statefulset', 'job', 'cronjob'];
|
export const workloadTypes: string[] = ['deployment', 'replicaset', 'daemonset', 'pod', 'statefulset', 'job', 'cronjob'];
|
||||||
export const workloadTypesWithRolloutStatus: string[] = ['deployment', 'daemonset', 'statefulset'];
|
export const workloadTypesWithRolloutStatus: string[] = ['deployment', 'daemonset', 'statefulset'];
|
||||||
|
|
||||||
export let workflowAnnotations = [
|
export const workflowAnnotations = [
|
||||||
`run=${process.env['GITHUB_RUN_ID']}`,
|
`run=${process.env['GITHUB_RUN_ID']}`,
|
||||||
`workflow="${process.env['GITHUB_WORKFLOW']}"`,
|
`repository=${process.env['GITHUB_REPOSITORY']}`,
|
||||||
`jobName="${process.env['GITHUB_JOB']}"`,
|
`workflow=${process.env['GITHUB_WORKFLOW']}`,
|
||||||
|
`jobName=${process.env['GITHUB_JOB']}`,
|
||||||
`createdBy=${process.env['GITHUB_ACTOR']}`,
|
`createdBy=${process.env['GITHUB_ACTOR']}`,
|
||||||
`runUri=https://github.com/${process.env['GITHUB_REPOSITORY']}/actions/runs/${process.env['GITHUB_RUN_ID']}`,
|
`runUri=https://github.com/${process.env['GITHUB_REPOSITORY']}/actions/runs/${process.env['GITHUB_RUN_ID']}`,
|
||||||
`commit=${process.env['GITHUB_SHA']}`,
|
`commit=${process.env['GITHUB_SHA']}`,
|
||||||
`branch=${process.env['GITHUB_REF']}`
|
`branch=${process.env['GITHUB_REF']}`,
|
||||||
|
`deployTimestamp=${Date.now()}`
|
||||||
];
|
];
|
||||||
@ -1,5 +1,4 @@
|
|||||||
import { ToolRunner, IExecOptions, IExecSyncResult } from "./utilities/tool-runner";
|
import { ToolRunner, IExecOptions, IExecSyncResult } from "./utilities/tool-runner";
|
||||||
import * as core from '@actions/core';
|
|
||||||
|
|
||||||
export interface Resource {
|
export interface Resource {
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import { IExecSyncResult } from '../../utilities/tool-runner';
|
|||||||
|
|
||||||
import { deployPodCanary } from './pod-canary-deployment-helper';
|
import { deployPodCanary } from './pod-canary-deployment-helper';
|
||||||
import { deploySMICanary } from './smi-canary-deployment-helper';
|
import { deploySMICanary } from './smi-canary-deployment-helper';
|
||||||
import { checkForErrors, annotateChildPods } from "../utility";
|
import { checkForErrors, annotateChildPods, annotateNamespace } from "../utility";
|
||||||
|
|
||||||
|
|
||||||
export async function deploy(kubectl: Kubectl, manifestFilePaths: string[], deploymentStrategy: string) {
|
export async function deploy(kubectl: Kubectl, manifestFilePaths: string[], deploymentStrategy: string) {
|
||||||
@ -114,6 +114,7 @@ async function checkManifestStability(kubectl: Kubectl, resources: Resource[]):
|
|||||||
|
|
||||||
function annotateResources(files: string[], kubectl: Kubectl, resourceTypes: Resource[], allPods: any) {
|
function annotateResources(files: string[], kubectl: Kubectl, resourceTypes: Resource[], allPods: any) {
|
||||||
const annotateResults: IExecSyncResult[] = [];
|
const annotateResults: IExecSyncResult[] = [];
|
||||||
|
annotateResults.push(annotateNamespace(kubectl, TaskInputParameters.namespace));
|
||||||
annotateResults.push(kubectl.annotateFiles(files, models.workflowAnnotations, true));
|
annotateResults.push(kubectl.annotateFiles(files, models.workflowAnnotations, true));
|
||||||
resourceTypes.forEach(resource => {
|
resourceTypes.forEach(resource => {
|
||||||
if (resource.type.toUpperCase() !== models.KubernetesWorkload.pod.toUpperCase()) {
|
if (resource.type.toUpperCase() !== models.KubernetesWorkload.pod.toUpperCase()) {
|
||||||
@ -152,7 +153,7 @@ function updateResourceObjects(filePaths: string[], imagePullSecrets: string[],
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
core.debug('New K8s objects after addin imagePullSecrets are :' + JSON.stringify(newObjectsList));
|
core.debug('New K8s objects after adding imagePullSecrets are :' + JSON.stringify(newObjectsList));
|
||||||
const newFilePaths = fileHelper.writeObjectsToFile(newObjectsList);
|
const newFilePaths = fileHelper.writeObjectsToFile(newObjectsList);
|
||||||
return newFilePaths;
|
return newFilePaths;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -73,6 +73,20 @@ export function annotateChildPods(kubectl: Kubectl, resourceType: string, resour
|
|||||||
return commandExecutionResults;
|
return commandExecutionResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function annotateNamespace(kubectl: Kubectl, namespaceName: string): IExecSyncResult {
|
||||||
|
let annotate = true;
|
||||||
|
const result = kubectl.getResource('namespace', namespaceName);
|
||||||
|
this.checkForErrors([result]);
|
||||||
|
const annotationsSet = JSON.parse(result.stdout).metadata.annotations;
|
||||||
|
if (!!annotationsSet && !!annotationsSet.runUri && annotationsSet.runUri.indexOf(process.env['GITHUB_REPOSITORY']) == -1) {
|
||||||
|
annotate = false;
|
||||||
|
core.debug(`Skipping 'annotate namespace' as namespace annotated by other workflow`);
|
||||||
|
}
|
||||||
|
if (annotate) {
|
||||||
|
return kubectl.annotate('namespace', namespaceName, workflowAnnotations, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function sleep(timeout: number) {
|
export function sleep(timeout: number) {
|
||||||
return new Promise(resolve => setTimeout(resolve, timeout));
|
return new Promise(resolve => setTimeout(resolve, timeout));
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user