mirror of
https://github.com/Azure/k8s-deploy.git
synced 2026-04-12 01:15:09 +08:00
Merge branch 'releases/v1' into users/koushdey/addAnnotationsResourceView
This commit is contained in:
commit
7da7f474fa
@ -8,6 +8,8 @@ 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 * as fileHelper from '../src/utilities/files-helper';
|
||||||
import { workflowAnnotations } from '../src/constants';
|
import { workflowAnnotations } from '../src/constants';
|
||||||
|
import * as utility from '../src/utilities/utility';
|
||||||
|
import * as inputParam from '../src/input-parameters';
|
||||||
|
|
||||||
import { Kubectl, Resource } from '../src/kubectl-object-model';
|
import { Kubectl, Resource } from '../src/kubectl-object-model';
|
||||||
|
|
||||||
@ -18,6 +20,8 @@ var path = require('path');
|
|||||||
|
|
||||||
const coreMock = mocked(core, true);
|
const coreMock = mocked(core, true);
|
||||||
const ioMock = mocked(io, true);
|
const ioMock = mocked(io, true);
|
||||||
|
const utilityMock = mocked(utility, true);
|
||||||
|
const inputParamMock = mocked(inputParam, true);
|
||||||
|
|
||||||
const toolCacheMock = mocked(toolCache, true);
|
const toolCacheMock = mocked(toolCache, true);
|
||||||
const fileUtility = mocked(fs, true);
|
const fileUtility = mocked(fs, true);
|
||||||
@ -220,6 +224,40 @@ test("deployment - deploy() - Invokes with manifestfiles", async () => {
|
|||||||
expect(kubeCtl.getResource).toBeCalledWith("ingress", "AppName");
|
expect(kubeCtl.getResource).toBeCalledWith("ingress", "AppName");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("run() - deploy force flag on", async () => {
|
||||||
|
const kubectlVersion = 'v1.18.0'
|
||||||
|
//Mocks
|
||||||
|
coreMock.getInput = jest.fn().mockImplementation((name) => {
|
||||||
|
if (name == 'manifests') {
|
||||||
|
return 'manifests/deployment.yaml';
|
||||||
|
}
|
||||||
|
if (name == 'action') {
|
||||||
|
return 'deploy';
|
||||||
|
}
|
||||||
|
if (name == 'strategy') {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (name == 'force') {
|
||||||
|
return 'true';
|
||||||
|
}
|
||||||
|
return kubectlVersion;
|
||||||
|
});
|
||||||
|
|
||||||
|
inputParamMock.forceDeployment = true;
|
||||||
|
coreMock.setFailed = jest.fn();
|
||||||
|
toolCacheMock.find = jest.fn().mockReturnValue('validPath');
|
||||||
|
toolCacheMock.downloadTool = jest.fn().mockReturnValue('downloadpath');
|
||||||
|
toolCacheMock.cacheFile = jest.fn().mockReturnValue('cachepath');
|
||||||
|
fileUtility.chmodSync = jest.fn();
|
||||||
|
utilityMock.checkForErrors = jest.fn();
|
||||||
|
const deploySpy = jest.spyOn(Kubectl.prototype, 'apply').mockImplementation();
|
||||||
|
|
||||||
|
//Invoke and assert
|
||||||
|
await expect(action.run()).resolves.not.toThrow();
|
||||||
|
expect(deploySpy).toBeCalledWith(expect.anything(), true);
|
||||||
|
deploySpy.mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
test("deployment - deploy() - Annotate resources", async () => {
|
test("deployment - deploy() - Annotate resources", async () => {
|
||||||
const KubernetesManifestUtilityMock = mocked(KubernetesManifestUtility, true);
|
const KubernetesManifestUtilityMock = mocked(KubernetesManifestUtility, true);
|
||||||
KubernetesManifestUtilityMock.checkManifestStability = jest.fn().mockReturnValue("");
|
KubernetesManifestUtilityMock.checkManifestStability = jest.fn().mockReturnValue("");
|
||||||
|
|||||||
@ -41,6 +41,10 @@ inputs:
|
|||||||
description: 'deploy/promote/reject'
|
description: 'deploy/promote/reject'
|
||||||
required: true
|
required: true
|
||||||
default: 'deploy'
|
default: 'deploy'
|
||||||
|
force:
|
||||||
|
description: 'Deploy when a previous deployment already exists. If true then --force argument is added to the apply command.'
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
|
||||||
branding:
|
branding:
|
||||||
color: 'green' # optional, decorates the entry in the GitHub Marketplace
|
color: 'green' # optional, decorates the entry in the GitHub Marketplace
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.args = exports.baselineAndCanaryReplicas = exports.trafficSplitMethod = exports.deploymentStrategy = exports.canaryPercentage = exports.manifests = exports.imagePullSecrets = exports.containers = exports.namespace = void 0;
|
exports.forceDeployment = exports.args = exports.baselineAndCanaryReplicas = exports.trafficSplitMethod = exports.deploymentStrategy = exports.canaryPercentage = exports.manifests = exports.imagePullSecrets = exports.containers = exports.namespace = void 0;
|
||||||
const core = require("@actions/core");
|
const core = require("@actions/core");
|
||||||
exports.namespace = core.getInput('namespace');
|
exports.namespace = core.getInput('namespace');
|
||||||
exports.containers = core.getInput('images').split('\n');
|
exports.containers = core.getInput('images').split('\n');
|
||||||
@ -11,6 +11,7 @@ exports.deploymentStrategy = core.getInput('strategy');
|
|||||||
exports.trafficSplitMethod = core.getInput('traffic-split-method');
|
exports.trafficSplitMethod = core.getInput('traffic-split-method');
|
||||||
exports.baselineAndCanaryReplicas = core.getInput('baseline-and-canary-replicas');
|
exports.baselineAndCanaryReplicas = core.getInput('baseline-and-canary-replicas');
|
||||||
exports.args = core.getInput('arguments');
|
exports.args = core.getInput('arguments');
|
||||||
|
exports.forceDeployment = core.getInput('force').toLowerCase() == 'true';
|
||||||
if (!exports.namespace) {
|
if (!exports.namespace) {
|
||||||
core.debug('Namespace was not supplied; using "default" namespace instead.');
|
core.debug('Namespace was not supplied; using "default" namespace instead.');
|
||||||
exports.namespace = 'default';
|
exports.namespace = 'default';
|
||||||
|
|||||||
@ -13,8 +13,13 @@ class Kubectl {
|
|||||||
this.namespace = 'default';
|
this.namespace = 'default';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
apply(configurationPaths) {
|
apply(configurationPaths, force) {
|
||||||
return this.execute(['apply', '-f', this.createInlineArray(configurationPaths)]);
|
let applyArgs = ['apply', '-f', this.createInlineArray(configurationPaths)];
|
||||||
|
if (!!force) {
|
||||||
|
console.log("force flag is on, deployment will continue even if previous deployment already exists");
|
||||||
|
applyArgs.push('--force');
|
||||||
|
}
|
||||||
|
return this.execute(applyArgs);
|
||||||
}
|
}
|
||||||
describe(resourceType, resourceName, silent) {
|
describe(resourceType, resourceName, silent) {
|
||||||
return this.execute(['describe', resourceType, resourceName], silent);
|
return this.execute(['describe', resourceType, resourceName], silent);
|
||||||
|
|||||||
@ -76,10 +76,10 @@ function deployManifests(files, kubectl, isCanaryDeploymentStrategy) {
|
|||||||
else {
|
else {
|
||||||
if (canaryDeploymentHelper.isSMICanaryStrategy()) {
|
if (canaryDeploymentHelper.isSMICanaryStrategy()) {
|
||||||
const updatedManifests = appendStableVersionLabelToResource(files, kubectl);
|
const updatedManifests = appendStableVersionLabelToResource(files, kubectl);
|
||||||
result = kubectl.apply(updatedManifests);
|
result = kubectl.apply(updatedManifests, TaskInputParameters.forceDeployment);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = kubectl.apply(files);
|
result = kubectl.apply(files, TaskInputParameters.forceDeployment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
utility_1.checkForErrors([result]);
|
utility_1.checkForErrors([result]);
|
||||||
|
|||||||
@ -48,7 +48,7 @@ function deployPodCanary(kubectl, filePaths) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
|
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
|
||||||
const result = kubectl.apply(manifestFiles);
|
const result = kubectl.apply(manifestFiles, TaskInputParameters.forceDeployment);
|
||||||
return { 'result': result, 'newFilePaths': manifestFiles };
|
return { 'result': result, 'newFilePaths': manifestFiles };
|
||||||
}
|
}
|
||||||
exports.deployPodCanary = deployPodCanary;
|
exports.deployPodCanary = deployPodCanary;
|
||||||
|
|||||||
@ -56,7 +56,7 @@ function deploySMICanary(kubectl, filePaths) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
|
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
|
||||||
const result = kubectl.apply(manifestFiles);
|
const result = kubectl.apply(manifestFiles, TaskInputParameters.forceDeployment);
|
||||||
createCanaryService(kubectl, filePaths);
|
createCanaryService(kubectl, filePaths);
|
||||||
return { 'result': result, 'newFilePaths': manifestFiles };
|
return { 'result': result, 'newFilePaths': manifestFiles };
|
||||||
}
|
}
|
||||||
@ -111,7 +111,7 @@ function createCanaryService(kubectl, filePaths) {
|
|||||||
});
|
});
|
||||||
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
|
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
|
||||||
manifestFiles.push(...trafficObjectsList);
|
manifestFiles.push(...trafficObjectsList);
|
||||||
const result = kubectl.apply(manifestFiles);
|
const result = kubectl.apply(manifestFiles, TaskInputParameters.forceDeployment);
|
||||||
utility_1.checkForErrors([result]);
|
utility_1.checkForErrors([result]);
|
||||||
}
|
}
|
||||||
function redirectTrafficToCanaryDeployment(kubectl, manifestFilePaths) {
|
function redirectTrafficToCanaryDeployment(kubectl, manifestFilePaths) {
|
||||||
@ -144,7 +144,7 @@ function adjustTraffic(kubectl, manifestFilePaths, stableWeight, canaryWeight) {
|
|||||||
if (trafficSplitManifests.length <= 0) {
|
if (trafficSplitManifests.length <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const result = kubectl.apply(trafficSplitManifests);
|
const result = kubectl.apply(trafficSplitManifests, TaskInputParameters.forceDeployment);
|
||||||
core.debug('serviceObjects:' + serviceObjects.join(',') + ' result:' + result);
|
core.debug('serviceObjects:' + serviceObjects.join(',') + ' result:' + result);
|
||||||
utility_1.checkForErrors([result]);
|
utility_1.checkForErrors([result]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ export const deploymentStrategy: string = core.getInput('strategy');
|
|||||||
export const trafficSplitMethod: string = core.getInput('traffic-split-method');
|
export const trafficSplitMethod: string = core.getInput('traffic-split-method');
|
||||||
export const baselineAndCanaryReplicas: string = core.getInput('baseline-and-canary-replicas');
|
export const baselineAndCanaryReplicas: string = core.getInput('baseline-and-canary-replicas');
|
||||||
export const args: string = core.getInput('arguments');
|
export const args: string = core.getInput('arguments');
|
||||||
|
export const forceDeployment: boolean = core.getInput('force').toLowerCase() == 'true';
|
||||||
|
|
||||||
if (!namespace) {
|
if (!namespace) {
|
||||||
core.debug('Namespace was not supplied; using "default" namespace instead.');
|
core.debug('Namespace was not supplied; using "default" namespace instead.');
|
||||||
|
|||||||
@ -20,8 +20,15 @@ export class Kubectl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public apply(configurationPaths: string | string[]): IExecSyncResult {
|
public apply(configurationPaths: string | string[], force?: boolean): IExecSyncResult {
|
||||||
return this.execute(['apply', '-f', this.createInlineArray(configurationPaths)]);
|
let applyArgs: string[] = ['apply', '-f', this.createInlineArray(configurationPaths)];
|
||||||
|
|
||||||
|
if (!!force) {
|
||||||
|
console.log("force flag is on, deployment will continue even if previous deployment already exists");
|
||||||
|
applyArgs.push('--force');
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.execute(applyArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public describe(resourceType: string, resourceName: string, silent?: boolean): IExecSyncResult {
|
public describe(resourceType: string, resourceName: string, silent?: boolean): IExecSyncResult {
|
||||||
|
|||||||
@ -76,10 +76,10 @@ function deployManifests(files: string[], kubectl: Kubectl, isCanaryDeploymentSt
|
|||||||
} else {
|
} else {
|
||||||
if (canaryDeploymentHelper.isSMICanaryStrategy()) {
|
if (canaryDeploymentHelper.isSMICanaryStrategy()) {
|
||||||
const updatedManifests = appendStableVersionLabelToResource(files, kubectl);
|
const updatedManifests = appendStableVersionLabelToResource(files, kubectl);
|
||||||
result = kubectl.apply(updatedManifests);
|
result = kubectl.apply(updatedManifests, TaskInputParameters.forceDeployment);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = kubectl.apply(files);
|
result = kubectl.apply(files, TaskInputParameters.forceDeployment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
checkForErrors([result]);
|
checkForErrors([result]);
|
||||||
|
|||||||
@ -52,7 +52,7 @@ export function deployPodCanary(kubectl: Kubectl, filePaths: string[]) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
|
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
|
||||||
const result = kubectl.apply(manifestFiles);
|
const result = kubectl.apply(manifestFiles, TaskInputParameters.forceDeployment);
|
||||||
return { 'result': result, 'newFilePaths': manifestFiles };
|
return { 'result': result, 'newFilePaths': manifestFiles };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -60,7 +60,7 @@ export function deploySMICanary(kubectl: Kubectl, filePaths: string[]) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
|
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
|
||||||
const result = kubectl.apply(manifestFiles);
|
const result = kubectl.apply(manifestFiles, TaskInputParameters.forceDeployment);
|
||||||
createCanaryService(kubectl, filePaths);
|
createCanaryService(kubectl, filePaths);
|
||||||
return { 'result': result, 'newFilePaths': manifestFiles };
|
return { 'result': result, 'newFilePaths': manifestFiles };
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ function createCanaryService(kubectl: Kubectl, filePaths: string[]) {
|
|||||||
|
|
||||||
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
|
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
|
||||||
manifestFiles.push(...trafficObjectsList);
|
manifestFiles.push(...trafficObjectsList);
|
||||||
const result = kubectl.apply(manifestFiles);
|
const result = kubectl.apply(manifestFiles, TaskInputParameters.forceDeployment);
|
||||||
checkForErrors([result]);
|
checkForErrors([result]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ function adjustTraffic(kubectl: Kubectl, manifestFilePaths: string[], stableWeig
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = kubectl.apply(trafficSplitManifests);
|
const result = kubectl.apply(trafficSplitManifests, TaskInputParameters.forceDeployment);
|
||||||
core.debug('serviceObjects:' + serviceObjects.join(',') + ' result:' + result);
|
core.debug('serviceObjects:' + serviceObjects.join(',') + ' result:' + result);
|
||||||
checkForErrors([result]);
|
checkForErrors([result]);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user