k8s-deploy/src/utilities/strategy-helpers/deployment-helper.ts
Sundar b4bc3003e8
added blue green strategy (#47)
* added blue green strategy

* Addressed review comments

* addressed pr comments

* updated names in test

* addressed final pr comments
2020-07-13 08:59:05 +05:30

121 lines
5.4 KiB
TypeScript

'use strict';
import * as fs from 'fs';
import * as yaml from 'js-yaml';
import * as canaryDeploymentHelper from './canary-deployment-helper';
import * as KubernetesObjectUtility from '../resource-object-utility';
import * as TaskInputParameters from '../../input-parameters';
import * as models from '../../constants';
import * as fileHelper from '../files-helper';
import * as utils from '../manifest-utilities';
import * as KubernetesManifestUtility from '../manifest-stability-utility';
import * as KubernetesConstants from '../../constants';
import { Kubectl, Resource } from '../../kubectl-object-model';
import { getUpdatedManifestFiles } from '../manifest-utilities';
import { deployPodCanary } from './pod-canary-deployment-helper';
import { deploySMICanary } from './smi-canary-deployment-helper';
import { checkForErrors } 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';
import { deployBlueGreenSMI } from './smi-blue-green-helper';
export async function deploy(kubectl: Kubectl, manifestFilePaths: string[], deploymentStrategy: string) {
// get manifest files
let inputManifestFiles: string[] = getUpdatedManifestFiles(manifestFilePaths);
// deployment
const deployedManifestFiles = deployManifests(inputManifestFiles, kubectl, isCanaryDeploymentStrategy(deploymentStrategy), isBlueGreenDeploymentStrategy());
// check manifest stability
const resourceTypes: Resource[] = KubernetesObjectUtility.getResources(deployedManifestFiles, models.deploymentTypes.concat([KubernetesConstants.DiscoveryAndLoadBalancerResource.service]));
await checkManifestStability(kubectl, resourceTypes);
// route blue-green deployments
if (isBlueGreenDeploymentStrategy()) {
await routeBlueGreen(kubectl, inputManifestFiles);
}
// print ingress resources
const ingressResources: Resource[] = KubernetesObjectUtility.getResources(deployedManifestFiles, [KubernetesConstants.DiscoveryAndLoadBalancerResource.ingress]);
ingressResources.forEach(ingressResource => {
kubectl.getResource(KubernetesConstants.DiscoveryAndLoadBalancerResource.ingress, ingressResource.name);
});
}
export function getManifestFiles(manifestFilePaths: string[]): string[] {
const files: string[] = utils.getManifestFiles(manifestFilePaths);
if (files == null || files.length === 0) {
throw new Error(`ManifestFileNotFound : ${manifestFilePaths}`);
}
return files;
}
function deployManifests(files: string[], kubectl: Kubectl, isCanaryDeploymentStrategy: boolean, isBlueGreenDeploymentStrategy: boolean): string[] {
let result;
if (isCanaryDeploymentStrategy) {
let canaryDeploymentOutput: any;
if (canaryDeploymentHelper.isSMICanaryStrategy()) {
canaryDeploymentOutput = deploySMICanary(kubectl, files);
} else {
canaryDeploymentOutput = deployPodCanary(kubectl, files);
}
result = canaryDeploymentOutput.result;
files = canaryDeploymentOutput.newFilePaths;
} else if (isBlueGreenDeploymentStrategy) {
let blueGreenDeploymentOutput: any;
if (isIngressRoute()) {
blueGreenDeploymentOutput = deployBlueGreenIngress(kubectl, files);
} else if (isSMIRoute()) {
blueGreenDeploymentOutput = deployBlueGreenSMI(kubectl, files);
} else {
blueGreenDeploymentOutput = deployBlueGreenService(kubectl, files);
}
result = blueGreenDeploymentOutput.result;
files = blueGreenDeploymentOutput.newFilePaths;
} else {
if (canaryDeploymentHelper.isSMICanaryStrategy()) {
const updatedManifests = appendStableVersionLabelToResource(files, kubectl);
result = kubectl.apply(updatedManifests, TaskInputParameters.forceDeployment);
}
else {
result = kubectl.apply(files, TaskInputParameters.forceDeployment);
}
}
checkForErrors([result]);
return files;
}
function appendStableVersionLabelToResource(files: string[], kubectl: Kubectl): string[] {
const manifestFiles = [];
const newObjectsList = [];
files.forEach((filePath: string) => {
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;
}
async function checkManifestStability(kubectl: Kubectl, resources: Resource[]): Promise<void> {
await KubernetesManifestUtility.checkManifestStability(kubectl, resources);
}
function isCanaryDeploymentStrategy(deploymentStrategy: string): boolean {
return deploymentStrategy != null && deploymentStrategy.toUpperCase() === canaryDeploymentHelper.CANARY_DEPLOYMENT_STRATEGY.toUpperCase();
}