Vidya reddy/prettier code (#203)

This commit is contained in:
Vidya
2022-06-24 13:57:45 -07:00
committed by GitHub
parent 976c5c4981
commit dcd9bc6b1a
71 changed files with 16044 additions and 15876 deletions
+277 -274
View File
@@ -1,355 +1,358 @@
import * as core from "@actions/core";
import * as fs from "fs";
import * as yaml from "js-yaml";
import { Kubectl } from "../../types/kubectl";
import * as core from '@actions/core'
import * as fs from 'fs'
import * as yaml from 'js-yaml'
import {Kubectl} from '../../types/kubectl'
import {
isDeploymentEntity,
isIngressEntity,
isServiceEntity,
KubernetesWorkload,
} from "../../types/kubernetesTypes";
import * as fileHelper from "../../utilities/fileUtils";
import { routeBlueGreenService } from "./serviceBlueGreenHelper";
import { routeBlueGreenIngress } from "./ingressBlueGreenHelper";
import { routeBlueGreenSMI } from "./smiBlueGreenHelper";
isDeploymentEntity,
isIngressEntity,
isServiceEntity,
KubernetesWorkload
} from '../../types/kubernetesTypes'
import * as fileHelper from '../../utilities/fileUtils'
import {routeBlueGreenService} from './serviceBlueGreenHelper'
import {routeBlueGreenIngress} from './ingressBlueGreenHelper'
import {routeBlueGreenSMI} from './smiBlueGreenHelper'
import {
UnsetClusterSpecificDetails,
updateObjectLabels,
updateSelectorLabels,
} from "../../utilities/manifestUpdateUtils";
import { updateSpecLabels } from "../../utilities/manifestSpecLabelUtils";
import { checkForErrors } from "../../utilities/kubectlUtils";
import { sleep } from "../../utilities/timeUtils";
import { RouteStrategy } from "../../types/routeStrategy";
UnsetClusterSpecificDetails,
updateObjectLabels,
updateSelectorLabels
} from '../../utilities/manifestUpdateUtils'
import {updateSpecLabels} from '../../utilities/manifestSpecLabelUtils'
import {checkForErrors} from '../../utilities/kubectlUtils'
import {sleep} from '../../utilities/timeUtils'
import {RouteStrategy} from '../../types/routeStrategy'
export const GREEN_LABEL_VALUE = "green";
export const NONE_LABEL_VALUE = "None";
export const BLUE_GREEN_VERSION_LABEL = "k8s.deploy.color";
export const GREEN_SUFFIX = "-green";
export const STABLE_SUFFIX = "-stable";
export const GREEN_LABEL_VALUE = 'green'
export const NONE_LABEL_VALUE = 'None'
export const BLUE_GREEN_VERSION_LABEL = 'k8s.deploy.color'
export const GREEN_SUFFIX = '-green'
export const STABLE_SUFFIX = '-stable'
export interface BlueGreenManifests {
serviceEntityList: any[];
serviceNameMap: Map<string, string>;
unroutedServiceEntityList: any[];
deploymentEntityList: any[];
ingressEntityList: any[];
otherObjects: any[];
serviceEntityList: any[]
serviceNameMap: Map<string, string>
unroutedServiceEntityList: any[]
deploymentEntityList: any[]
ingressEntityList: any[]
otherObjects: any[]
}
export async function routeBlueGreen(
kubectl: Kubectl,
inputManifestFiles: string[],
routeStrategy: RouteStrategy
kubectl: Kubectl,
inputManifestFiles: string[],
routeStrategy: RouteStrategy
) {
// sleep for buffer time
const bufferTime: number = parseInt(
core.getInput("version-switch-buffer") || "0"
);
if (bufferTime < 0 || bufferTime > 300)
throw Error("Version switch buffer must be between 0 and 300 (inclusive)");
const startSleepDate = new Date();
core.info(
`Starting buffer time of ${bufferTime} minute(s) at ${startSleepDate.toISOString()}`
);
await sleep(bufferTime * 1000 * 60);
const endSleepDate = new Date();
core.info(
`Stopping buffer time of ${bufferTime} minute(s) at ${endSleepDate.toISOString()}`
);
// sleep for buffer time
const bufferTime: number = parseInt(
core.getInput('version-switch-buffer') || '0'
)
if (bufferTime < 0 || bufferTime > 300)
throw Error('Version switch buffer must be between 0 and 300 (inclusive)')
const startSleepDate = new Date()
core.info(
`Starting buffer time of ${bufferTime} minute(s) at ${startSleepDate.toISOString()}`
)
await sleep(bufferTime * 1000 * 60)
const endSleepDate = new Date()
core.info(
`Stopping buffer time of ${bufferTime} minute(s) at ${endSleepDate.toISOString()}`
)
const manifestObjects: BlueGreenManifests =
getManifestObjects(inputManifestFiles);
core.debug("Manifest objects: " + JSON.stringify(manifestObjects));
const manifestObjects: BlueGreenManifests =
getManifestObjects(inputManifestFiles)
core.debug('Manifest objects: ' + JSON.stringify(manifestObjects))
// route to new deployments
if (routeStrategy == RouteStrategy.INGRESS) {
await routeBlueGreenIngress(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.serviceNameMap,
manifestObjects.ingressEntityList
);
} else if (routeStrategy == RouteStrategy.SMI) {
await routeBlueGreenSMI(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.serviceEntityList
);
} else {
await routeBlueGreenService(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.serviceEntityList
);
}
// route to new deployments
if (routeStrategy == RouteStrategy.INGRESS) {
await routeBlueGreenIngress(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.serviceNameMap,
manifestObjects.ingressEntityList
)
} else if (routeStrategy == RouteStrategy.SMI) {
await routeBlueGreenSMI(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.serviceEntityList
)
} else {
await routeBlueGreenService(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.serviceEntityList
)
}
}
export async function deleteWorkloadsWithLabel(
kubectl: Kubectl,
deleteLabel: string,
deploymentEntityList: any[]
kubectl: Kubectl,
deleteLabel: string,
deploymentEntityList: any[]
) {
const resourcesToDelete = [];
deploymentEntityList.forEach((inputObject) => {
const name = inputObject.metadata.name;
const kind = inputObject.kind;
const resourcesToDelete = []
deploymentEntityList.forEach((inputObject) => {
const name = inputObject.metadata.name
const kind = inputObject.kind
if (deleteLabel === NONE_LABEL_VALUE) {
// delete stable deployments
const resourceToDelete = { name, kind };
resourcesToDelete.push(resourceToDelete);
} else {
// delete new green deployments
const resourceToDelete = {
name: getBlueGreenResourceName(name, GREEN_SUFFIX),
kind: kind,
};
resourcesToDelete.push(resourceToDelete);
}
});
if (deleteLabel === NONE_LABEL_VALUE) {
// delete stable deployments
const resourceToDelete = {name, kind}
resourcesToDelete.push(resourceToDelete)
} else {
// delete new green deployments
const resourceToDelete = {
name: getBlueGreenResourceName(name, GREEN_SUFFIX),
kind: kind
}
resourcesToDelete.push(resourceToDelete)
}
})
await deleteObjects(kubectl, resourcesToDelete);
await deleteObjects(kubectl, resourcesToDelete)
}
export async function deleteWorkloadsAndServicesWithLabel(
kubectl: Kubectl,
deleteLabel: string,
deploymentEntityList: any[],
serviceEntityList: any[]
kubectl: Kubectl,
deleteLabel: string,
deploymentEntityList: any[],
serviceEntityList: any[]
) {
// need to delete services and deployments
const deletionEntitiesList = deploymentEntityList.concat(serviceEntityList);
const resourcesToDelete = [];
// need to delete services and deployments
const deletionEntitiesList = deploymentEntityList.concat(serviceEntityList)
const resourcesToDelete = []
deletionEntitiesList.forEach((inputObject) => {
const name = inputObject.metadata.name;
const kind = inputObject.kind;
deletionEntitiesList.forEach((inputObject) => {
const name = inputObject.metadata.name
const kind = inputObject.kind
if (deleteLabel === NONE_LABEL_VALUE) {
// delete stable objects
const resourceToDelete = { name, kind };
resourcesToDelete.push(resourceToDelete);
} else {
// delete green labels
const resourceToDelete = {
name: getBlueGreenResourceName(name, GREEN_SUFFIX),
kind: kind,
};
resourcesToDelete.push(resourceToDelete);
}
});
if (deleteLabel === NONE_LABEL_VALUE) {
// delete stable objects
const resourceToDelete = {name, kind}
resourcesToDelete.push(resourceToDelete)
} else {
// delete green labels
const resourceToDelete = {
name: getBlueGreenResourceName(name, GREEN_SUFFIX),
kind: kind
}
resourcesToDelete.push(resourceToDelete)
}
})
await deleteObjects(kubectl, resourcesToDelete);
await deleteObjects(kubectl, resourcesToDelete)
}
export async function deleteObjects(kubectl: Kubectl, deleteList: any[]) {
// delete services and deployments
for (const delObject of deleteList) {
try {
const result = await kubectl.delete([delObject.kind, delObject.name]);
checkForErrors([result]);
} catch (ex) {
// Ignore failures of delete if it doesn't exist
}
}
// delete services and deployments
for (const delObject of deleteList) {
try {
const result = await kubectl.delete([delObject.kind, delObject.name])
checkForErrors([result])
} catch (ex) {
// Ignore failures of delete if it doesn't exist
}
}
}
// other common functions
export function getManifestObjects(filePaths: string[]): BlueGreenManifests {
const deploymentEntityList = [];
const routedServiceEntityList = [];
const unroutedServiceEntityList = [];
const ingressEntityList = [];
const otherEntitiesList = [];
const serviceNameMap = new Map<string, string>();
const deploymentEntityList = []
const routedServiceEntityList = []
const unroutedServiceEntityList = []
const ingressEntityList = []
const otherEntitiesList = []
const serviceNameMap = new Map<string, string>()
filePaths.forEach((filePath: string) => {
const fileContents = fs.readFileSync(filePath).toString();
yaml.safeLoadAll(fileContents, (inputObject) => {
if (!!inputObject) {
const kind = inputObject.kind;
const name = inputObject.metadata.name;
filePaths.forEach((filePath: string) => {
const fileContents = fs.readFileSync(filePath).toString()
yaml.safeLoadAll(fileContents, (inputObject) => {
if (!!inputObject) {
const kind = inputObject.kind
const name = inputObject.metadata.name
if (isDeploymentEntity(kind)) {
deploymentEntityList.push(inputObject);
} else if (isServiceEntity(kind)) {
if (isServiceRouted(inputObject, deploymentEntityList)) {
routedServiceEntityList.push(inputObject);
serviceNameMap.set(
name,
getBlueGreenResourceName(name, GREEN_SUFFIX)
);
} else {
unroutedServiceEntityList.push(inputObject);
}
} else if (isIngressEntity(kind)) {
ingressEntityList.push(inputObject);
} else {
otherEntitiesList.push(inputObject);
}
}
});
});
if (isDeploymentEntity(kind)) {
deploymentEntityList.push(inputObject)
} else if (isServiceEntity(kind)) {
if (isServiceRouted(inputObject, deploymentEntityList)) {
routedServiceEntityList.push(inputObject)
serviceNameMap.set(
name,
getBlueGreenResourceName(name, GREEN_SUFFIX)
)
} else {
unroutedServiceEntityList.push(inputObject)
}
} else if (isIngressEntity(kind)) {
ingressEntityList.push(inputObject)
} else {
otherEntitiesList.push(inputObject)
}
}
})
})
return {
serviceEntityList: routedServiceEntityList,
serviceNameMap: serviceNameMap,
unroutedServiceEntityList: unroutedServiceEntityList,
deploymentEntityList: deploymentEntityList,
ingressEntityList: ingressEntityList,
otherObjects: otherEntitiesList,
};
return {
serviceEntityList: routedServiceEntityList,
serviceNameMap: serviceNameMap,
unroutedServiceEntityList: unroutedServiceEntityList,
deploymentEntityList: deploymentEntityList,
ingressEntityList: ingressEntityList,
otherObjects: otherEntitiesList
}
}
export function isServiceRouted(
serviceObject: any[],
deploymentEntityList: any[]
serviceObject: any[],
deploymentEntityList: any[]
): boolean {
let shouldBeRouted: boolean = false;
const serviceSelector: any = getServiceSelector(serviceObject);
if (serviceSelector) {
if (
deploymentEntityList.some((depObject) => {
// finding if there is a deployment in the given manifests the service targets
const matchLabels: any = getDeploymentMatchLabels(depObject);
return (
matchLabels &&
isServiceSelectorSubsetOfMatchLabel(serviceSelector, matchLabels)
);
})
) {
shouldBeRouted = true;
}
}
let shouldBeRouted: boolean = false
const serviceSelector: any = getServiceSelector(serviceObject)
if (serviceSelector) {
if (
deploymentEntityList.some((depObject) => {
// finding if there is a deployment in the given manifests the service targets
const matchLabels: any = getDeploymentMatchLabels(depObject)
return (
matchLabels &&
isServiceSelectorSubsetOfMatchLabel(serviceSelector, matchLabels)
)
})
) {
shouldBeRouted = true
}
}
return shouldBeRouted;
return shouldBeRouted
}
export async function createWorkloadsWithLabel(
kubectl: Kubectl,
deploymentObjectList: any[],
nextLabel: string
kubectl: Kubectl,
deploymentObjectList: any[],
nextLabel: string
) {
const newObjectsList = [];
deploymentObjectList.forEach((inputObject) => {
// creating deployment with label
const newBlueGreenObject = getNewBlueGreenObject(inputObject, nextLabel);
core.debug(
"New blue-green object is: " + JSON.stringify(newBlueGreenObject)
);
newObjectsList.push(newBlueGreenObject);
});
const newObjectsList = []
deploymentObjectList.forEach((inputObject) => {
// creating deployment with label
const newBlueGreenObject = getNewBlueGreenObject(inputObject, nextLabel)
core.debug(
'New blue-green object is: ' + JSON.stringify(newBlueGreenObject)
)
newObjectsList.push(newBlueGreenObject)
})
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
const result = await kubectl.apply(manifestFiles);
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList)
const result = await kubectl.apply(manifestFiles)
return { result: result, newFilePaths: manifestFiles };
return {result: result, newFilePaths: manifestFiles}
}
export function getNewBlueGreenObject(
inputObject: any,
labelValue: string
inputObject: any,
labelValue: string
): object {
const newObject = JSON.parse(JSON.stringify(inputObject));
const newObject = JSON.parse(JSON.stringify(inputObject))
// Updating name only if label is green label is given
if (labelValue === GREEN_LABEL_VALUE) {
newObject.metadata.name = getBlueGreenResourceName(
inputObject.metadata.name,
GREEN_SUFFIX
);
}
// Updating name only if label is green label is given
if (labelValue === GREEN_LABEL_VALUE) {
newObject.metadata.name = getBlueGreenResourceName(
inputObject.metadata.name,
GREEN_SUFFIX
)
}
// Adding labels and annotations
addBlueGreenLabelsAndAnnotations(newObject, labelValue);
return newObject;
// Adding labels and annotations
addBlueGreenLabelsAndAnnotations(newObject, labelValue)
return newObject
}
export function addBlueGreenLabelsAndAnnotations(
inputObject: any,
labelValue: string
inputObject: any,
labelValue: string
) {
//creating the k8s.deploy.color label
const newLabels = new Map<string, string>();
newLabels[BLUE_GREEN_VERSION_LABEL] = labelValue;
//creating the k8s.deploy.color label
const newLabels = new Map<string, string>()
newLabels[BLUE_GREEN_VERSION_LABEL] = labelValue
// updating object labels and selector labels
updateObjectLabels(inputObject, newLabels, false);
updateSelectorLabels(inputObject, newLabels, false);
// updating object labels and selector labels
updateObjectLabels(inputObject, newLabels, false)
updateSelectorLabels(inputObject, newLabels, false)
// updating spec labels if it is a service
if (!isServiceEntity(inputObject.kind)) {
updateSpecLabels(inputObject, newLabels, false);
}
// updating spec labels if it is a service
if (!isServiceEntity(inputObject.kind)) {
updateSpecLabels(inputObject, newLabels, false)
}
}
export function getBlueGreenResourceName(name: string, suffix: string) {
return `${name}${suffix}`;
return `${name}${suffix}`
}
export function getDeploymentMatchLabels(deploymentObject: any): any {
if (
deploymentObject?.kind?.toUpperCase() ==
KubernetesWorkload.POD.toUpperCase() &&
deploymentObject?.metadata?.labels
) {
return deploymentObject.metadata.labels;
} else if (deploymentObject?.spec?.selector?.matchLabels) {
return deploymentObject.spec.selector.matchLabels;
}
if (
deploymentObject?.kind?.toUpperCase() ==
KubernetesWorkload.POD.toUpperCase() &&
deploymentObject?.metadata?.labels
) {
return deploymentObject.metadata.labels
} else if (deploymentObject?.spec?.selector?.matchLabels) {
return deploymentObject.spec.selector.matchLabels
}
}
export function getServiceSelector(serviceObject: any): any {
if (serviceObject?.spec?.selector) {
return serviceObject.spec.selector;
}
if (serviceObject?.spec?.selector) {
return serviceObject.spec.selector
}
}
export function isServiceSelectorSubsetOfMatchLabel(
serviceSelector: any,
matchLabels: any
serviceSelector: any,
matchLabels: any
): boolean {
const serviceSelectorMap = new Map();
const matchLabelsMap = new Map();
const serviceSelectorMap = new Map()
const matchLabelsMap = new Map()
JSON.parse(JSON.stringify(serviceSelector), (key, value) => {
serviceSelectorMap.set(key, value);
});
JSON.parse(JSON.stringify(serviceSelector), (key, value) => {
serviceSelectorMap.set(key, value)
})
JSON.parse(JSON.stringify(matchLabels), (key, value) => {
matchLabelsMap.set(key, value);
});
JSON.parse(JSON.stringify(matchLabels), (key, value) => {
matchLabelsMap.set(key, value)
})
let isMatch = true;
serviceSelectorMap.forEach((value, key) => {
if (!!key && (!matchLabelsMap.has(key) || matchLabelsMap.get(key)) != value)
isMatch = false;
});
let isMatch = true
serviceSelectorMap.forEach((value, key) => {
if (
!!key &&
(!matchLabelsMap.has(key) || matchLabelsMap.get(key)) != value
)
isMatch = false
})
return isMatch;
return isMatch
}
export async function fetchResource(
kubectl: Kubectl,
kind: string,
name: string
kubectl: Kubectl,
kind: string,
name: string
) {
const result = await kubectl.getResource(kind, name);
if (result == null || !!result.stderr) {
return null;
}
const result = await kubectl.getResource(kind, name)
if (result == null || !!result.stderr) {
return null
}
if (!!result.stdout) {
const resource = JSON.parse(result.stdout);
if (!!result.stdout) {
const resource = JSON.parse(result.stdout)
try {
UnsetClusterSpecificDetails(resource);
return resource;
} catch (ex) {
core.debug(
`Exception occurred while Parsing ${resource} in Json object: ${ex}`
);
}
}
try {
UnsetClusterSpecificDetails(resource)
return resource
} catch (ex) {
core.debug(
`Exception occurred while Parsing ${resource} in Json object: ${ex}`
)
}
}
}
@@ -1,229 +1,229 @@
import { Kubectl } from "../../types/kubectl";
import * as fileHelper from "../../utilities/fileUtils";
import {Kubectl} from '../../types/kubectl'
import * as fileHelper from '../../utilities/fileUtils'
import {
addBlueGreenLabelsAndAnnotations,
BLUE_GREEN_VERSION_LABEL,
BlueGreenManifests,
createWorkloadsWithLabel,
deleteWorkloadsAndServicesWithLabel,
fetchResource,
getManifestObjects,
getNewBlueGreenObject,
GREEN_LABEL_VALUE,
NONE_LABEL_VALUE,
} from "./blueGreenHelper";
import * as core from "@actions/core";
addBlueGreenLabelsAndAnnotations,
BLUE_GREEN_VERSION_LABEL,
BlueGreenManifests,
createWorkloadsWithLabel,
deleteWorkloadsAndServicesWithLabel,
fetchResource,
getManifestObjects,
getNewBlueGreenObject,
GREEN_LABEL_VALUE,
NONE_LABEL_VALUE
} from './blueGreenHelper'
import * as core from '@actions/core'
const BACKEND = "BACKEND";
const BACKEND = 'BACKEND'
export async function deployBlueGreenIngress(
kubectl: Kubectl,
filePaths: string[]
kubectl: Kubectl,
filePaths: string[]
) {
// get all kubernetes objects defined in manifest files
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths);
// get all kubernetes objects defined in manifest files
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths)
// create deployments with green label value
const result = createWorkloadsWithLabel(
kubectl,
manifestObjects.deploymentEntityList,
GREEN_LABEL_VALUE
);
// create new services and other objects
let newObjectsList = [];
manifestObjects.serviceEntityList.forEach((inputObject) => {
const newBlueGreenObject = getNewBlueGreenObject(
inputObject,
// create deployments with green label value
const result = createWorkloadsWithLabel(
kubectl,
manifestObjects.deploymentEntityList,
GREEN_LABEL_VALUE
);
newObjectsList.push(newBlueGreenObject);
});
newObjectsList = newObjectsList
.concat(manifestObjects.otherObjects)
.concat(manifestObjects.unroutedServiceEntityList);
)
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
await kubectl.apply(manifestFiles);
// create new services and other objects
let newObjectsList = []
manifestObjects.serviceEntityList.forEach((inputObject) => {
const newBlueGreenObject = getNewBlueGreenObject(
inputObject,
GREEN_LABEL_VALUE
)
newObjectsList.push(newBlueGreenObject)
})
newObjectsList = newObjectsList
.concat(manifestObjects.otherObjects)
.concat(manifestObjects.unroutedServiceEntityList)
return result;
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList)
await kubectl.apply(manifestFiles)
return result
}
export async function promoteBlueGreenIngress(
kubectl: Kubectl,
manifestObjects
kubectl: Kubectl,
manifestObjects
) {
//checking if anything to promote
if (
!validateIngressesState(
//checking if anything to promote
if (
!validateIngressesState(
kubectl,
manifestObjects.ingressEntityList,
manifestObjects.serviceNameMap
)
) {
throw 'Ingress not in promote state'
}
// create stable deployments with new configuration
const result = createWorkloadsWithLabel(
kubectl,
manifestObjects.ingressEntityList,
manifestObjects.serviceNameMap
)
) {
throw "Ingress not in promote state";
}
// create stable deployments with new configuration
const result = createWorkloadsWithLabel(
kubectl,
manifestObjects.deploymentEntityList,
NONE_LABEL_VALUE
);
// create stable services with new configuration
const newObjectsList = [];
manifestObjects.serviceEntityList.forEach((inputObject) => {
const newBlueGreenObject = getNewBlueGreenObject(
inputObject,
manifestObjects.deploymentEntityList,
NONE_LABEL_VALUE
);
newObjectsList.push(newBlueGreenObject);
});
)
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
await kubectl.apply(manifestFiles);
// create stable services with new configuration
const newObjectsList = []
manifestObjects.serviceEntityList.forEach((inputObject) => {
const newBlueGreenObject = getNewBlueGreenObject(
inputObject,
NONE_LABEL_VALUE
)
newObjectsList.push(newBlueGreenObject)
})
return result;
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList)
await kubectl.apply(manifestFiles)
return result
}
export async function rejectBlueGreenIngress(
kubectl: Kubectl,
filePaths: string[]
kubectl: Kubectl,
filePaths: string[]
) {
// get all kubernetes objects defined in manifest files
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths);
// get all kubernetes objects defined in manifest files
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths)
// route ingress to stables services
await routeBlueGreenIngress(
kubectl,
null,
manifestObjects.serviceNameMap,
manifestObjects.ingressEntityList
);
// route ingress to stables services
await routeBlueGreenIngress(
kubectl,
null,
manifestObjects.serviceNameMap,
manifestObjects.ingressEntityList
)
// delete green services and deployments
await deleteWorkloadsAndServicesWithLabel(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.deploymentEntityList,
manifestObjects.serviceEntityList
);
// delete green services and deployments
await deleteWorkloadsAndServicesWithLabel(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.deploymentEntityList,
manifestObjects.serviceEntityList
)
}
export async function routeBlueGreenIngress(
kubectl: Kubectl,
nextLabel: string,
serviceNameMap: Map<string, string>,
ingressEntityList: any[]
kubectl: Kubectl,
nextLabel: string,
serviceNameMap: Map<string, string>,
ingressEntityList: any[]
) {
let newObjectsList = [];
let newObjectsList = []
if (!nextLabel) {
newObjectsList = ingressEntityList.filter((ingress) =>
isIngressRouted(ingress, serviceNameMap)
);
} else {
ingressEntityList.forEach((inputObject) => {
if (isIngressRouted(inputObject, serviceNameMap)) {
const newBlueGreenIngressObject = getUpdatedBlueGreenIngress(
inputObject,
serviceNameMap,
GREEN_LABEL_VALUE
);
newObjectsList.push(newBlueGreenIngressObject);
} else {
newObjectsList.push(inputObject);
}
});
}
if (!nextLabel) {
newObjectsList = ingressEntityList.filter((ingress) =>
isIngressRouted(ingress, serviceNameMap)
)
} else {
ingressEntityList.forEach((inputObject) => {
if (isIngressRouted(inputObject, serviceNameMap)) {
const newBlueGreenIngressObject = getUpdatedBlueGreenIngress(
inputObject,
serviceNameMap,
GREEN_LABEL_VALUE
)
newObjectsList.push(newBlueGreenIngressObject)
} else {
newObjectsList.push(inputObject)
}
})
}
core.debug("New objects: " + JSON.stringify(newObjectsList));
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
await kubectl.apply(manifestFiles);
core.debug('New objects: ' + JSON.stringify(newObjectsList))
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList)
await kubectl.apply(manifestFiles)
}
export function validateIngressesState(
kubectl: Kubectl,
ingressEntityList: any[],
serviceNameMap: Map<string, string>
kubectl: Kubectl,
ingressEntityList: any[],
serviceNameMap: Map<string, string>
): boolean {
let areIngressesTargetingNewServices: boolean = true;
ingressEntityList.forEach(async (inputObject) => {
if (isIngressRouted(inputObject, serviceNameMap)) {
//querying existing ingress
const existingIngress = await fetchResource(
kubectl,
inputObject.kind,
inputObject.metadata.name
);
let areIngressesTargetingNewServices: boolean = true
ingressEntityList.forEach(async (inputObject) => {
if (isIngressRouted(inputObject, serviceNameMap)) {
//querying existing ingress
const existingIngress = await fetchResource(
kubectl,
inputObject.kind,
inputObject.metadata.name
)
if (!!existingIngress) {
const currentLabel: string =
existingIngress?.metadata?.labels[BLUE_GREEN_VERSION_LABEL];
if (!!existingIngress) {
const currentLabel: string =
existingIngress?.metadata?.labels[BLUE_GREEN_VERSION_LABEL]
// if not green label, then wrong configuration
if (currentLabel != GREEN_LABEL_VALUE)
areIngressesTargetingNewServices = false;
} else {
// no ingress at all, so nothing to promote
areIngressesTargetingNewServices = false;
// if not green label, then wrong configuration
if (currentLabel != GREEN_LABEL_VALUE)
areIngressesTargetingNewServices = false
} else {
// no ingress at all, so nothing to promote
areIngressesTargetingNewServices = false
}
}
}
});
})
return areIngressesTargetingNewServices;
return areIngressesTargetingNewServices
}
function isIngressRouted(
ingressObject: any,
serviceNameMap: Map<string, string>
ingressObject: any,
serviceNameMap: Map<string, string>
): boolean {
let isIngressRouted: boolean = false;
// check if ingress targets a service in the given manifests
JSON.parse(JSON.stringify(ingressObject), (key, value) => {
if (key === "serviceName" && serviceNameMap.has(value)) {
isIngressRouted = true;
}
let isIngressRouted: boolean = false
// check if ingress targets a service in the given manifests
JSON.parse(JSON.stringify(ingressObject), (key, value) => {
if (key === 'serviceName' && serviceNameMap.has(value)) {
isIngressRouted = true
}
return value;
});
return value
})
return isIngressRouted;
return isIngressRouted
}
export function getUpdatedBlueGreenIngress(
inputObject: any,
serviceNameMap: Map<string, string>,
type: string
inputObject: any,
serviceNameMap: Map<string, string>,
type: string
): object {
if (!type) {
return inputObject;
}
if (!type) {
return inputObject
}
const newObject = JSON.parse(JSON.stringify(inputObject));
// add green labels and values
addBlueGreenLabelsAndAnnotations(newObject, type);
const newObject = JSON.parse(JSON.stringify(inputObject))
// add green labels and values
addBlueGreenLabelsAndAnnotations(newObject, type)
// update ingress labels
return updateIngressBackend(newObject, serviceNameMap);
// update ingress labels
return updateIngressBackend(newObject, serviceNameMap)
}
export function updateIngressBackend(
inputObject: any,
serviceNameMap: Map<string, string>
inputObject: any,
serviceNameMap: Map<string, string>
): any {
inputObject = JSON.parse(JSON.stringify(inputObject), (key, value) => {
if (key.toUpperCase() === BACKEND) {
const { serviceName } = value;
if (serviceNameMap.has(serviceName)) {
// update service name with corresponding bluegreen name only if service is provied in given manifests
value.serviceName = serviceNameMap.get(serviceName);
inputObject = JSON.parse(JSON.stringify(inputObject), (key, value) => {
if (key.toUpperCase() === BACKEND) {
const {serviceName} = value
if (serviceNameMap.has(serviceName)) {
// update service name with corresponding bluegreen name only if service is provied in given manifests
value.serviceName = serviceNameMap.get(serviceName)
}
}
}
return value;
});
return value
})
return inputObject;
return inputObject
}
@@ -1,146 +1,146 @@
import { Kubectl } from "../../types/kubectl";
import * as fileHelper from "../../utilities/fileUtils";
import {Kubectl} from '../../types/kubectl'
import * as fileHelper from '../../utilities/fileUtils'
import {
addBlueGreenLabelsAndAnnotations,
BLUE_GREEN_VERSION_LABEL,
BlueGreenManifests,
createWorkloadsWithLabel,
deleteWorkloadsWithLabel,
fetchResource,
getManifestObjects,
GREEN_LABEL_VALUE,
NONE_LABEL_VALUE,
} from "./blueGreenHelper";
addBlueGreenLabelsAndAnnotations,
BLUE_GREEN_VERSION_LABEL,
BlueGreenManifests,
createWorkloadsWithLabel,
deleteWorkloadsWithLabel,
fetchResource,
getManifestObjects,
GREEN_LABEL_VALUE,
NONE_LABEL_VALUE
} from './blueGreenHelper'
export async function deployBlueGreenService(
kubectl: Kubectl,
filePaths: string[]
kubectl: Kubectl,
filePaths: string[]
) {
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths);
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths)
// create deployments with green label value
const result = await createWorkloadsWithLabel(
kubectl,
manifestObjects.deploymentEntityList,
GREEN_LABEL_VALUE
);
// create deployments with green label value
const result = await createWorkloadsWithLabel(
kubectl,
manifestObjects.deploymentEntityList,
GREEN_LABEL_VALUE
)
// create other non deployment and non service entities
const newObjectsList = manifestObjects.otherObjects
.concat(manifestObjects.ingressEntityList)
.concat(manifestObjects.unroutedServiceEntityList);
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
if (manifestFiles.length > 0) await kubectl.apply(manifestFiles);
// create other non deployment and non service entities
const newObjectsList = manifestObjects.otherObjects
.concat(manifestObjects.ingressEntityList)
.concat(manifestObjects.unroutedServiceEntityList)
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList)
if (manifestFiles.length > 0) await kubectl.apply(manifestFiles)
// returning deployment details to check for rollout stability
return result;
// returning deployment details to check for rollout stability
return result
}
export async function promoteBlueGreenService(
kubectl: Kubectl,
manifestObjects
kubectl: Kubectl,
manifestObjects
) {
// checking if services are in the right state ie. targeting green deployments
if (
!(await validateServicesState(kubectl, manifestObjects.serviceEntityList))
) {
throw "Not inP promote state";
}
// checking if services are in the right state ie. targeting green deployments
if (
!(await validateServicesState(kubectl, manifestObjects.serviceEntityList))
) {
throw 'Not inP promote state'
}
// creating stable deployments with new configurations
return await createWorkloadsWithLabel(
kubectl,
manifestObjects.deploymentEntityList,
NONE_LABEL_VALUE
);
// creating stable deployments with new configurations
return await createWorkloadsWithLabel(
kubectl,
manifestObjects.deploymentEntityList,
NONE_LABEL_VALUE
)
}
export async function rejectBlueGreenService(
kubectl: Kubectl,
filePaths: string[]
kubectl: Kubectl,
filePaths: string[]
) {
// get all kubernetes objects defined in manifest files
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths);
// get all kubernetes objects defined in manifest files
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths)
// route to stable objects
await routeBlueGreenService(
kubectl,
NONE_LABEL_VALUE,
manifestObjects.serviceEntityList
);
// route to stable objects
await routeBlueGreenService(
kubectl,
NONE_LABEL_VALUE,
manifestObjects.serviceEntityList
)
// delete new deployments with green suffix
await deleteWorkloadsWithLabel(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.deploymentEntityList
);
// delete new deployments with green suffix
await deleteWorkloadsWithLabel(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.deploymentEntityList
)
}
export async function routeBlueGreenService(
kubectl: Kubectl,
nextLabel: string,
serviceEntityList: any[]
kubectl: Kubectl,
nextLabel: string,
serviceEntityList: any[]
) {
const newObjectsList = [];
serviceEntityList.forEach((serviceObject) => {
const newBlueGreenServiceObject = getUpdatedBlueGreenService(
serviceObject,
nextLabel
);
newObjectsList.push(newBlueGreenServiceObject);
});
const newObjectsList = []
serviceEntityList.forEach((serviceObject) => {
const newBlueGreenServiceObject = getUpdatedBlueGreenService(
serviceObject,
nextLabel
)
newObjectsList.push(newBlueGreenServiceObject)
})
// configures the services
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
await kubectl.apply(manifestFiles);
// configures the services
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList)
await kubectl.apply(manifestFiles)
}
// add green labels to configure existing service
function getUpdatedBlueGreenService(
inputObject: any,
labelValue: string
inputObject: any,
labelValue: string
): object {
const newObject = JSON.parse(JSON.stringify(inputObject));
const newObject = JSON.parse(JSON.stringify(inputObject))
// Adding labels and annotations.
addBlueGreenLabelsAndAnnotations(newObject, labelValue);
return newObject;
// Adding labels and annotations.
addBlueGreenLabelsAndAnnotations(newObject, labelValue)
return newObject
}
export async function validateServicesState(
kubectl: Kubectl,
serviceEntityList: any[]
kubectl: Kubectl,
serviceEntityList: any[]
): Promise<boolean> {
let areServicesGreen: boolean = true;
let areServicesGreen: boolean = true
for (const serviceObject of serviceEntityList) {
// finding the existing routed service
const existingService = await fetchResource(
kubectl,
serviceObject.kind,
serviceObject.metadata.name
);
for (const serviceObject of serviceEntityList) {
// finding the existing routed service
const existingService = await fetchResource(
kubectl,
serviceObject.kind,
serviceObject.metadata.name
)
if (!!existingService) {
const currentLabel: string = getServiceSpecLabel(existingService);
if (currentLabel != GREEN_LABEL_VALUE) {
// service should be targeting deployments with green label
areServicesGreen = false;
if (!!existingService) {
const currentLabel: string = getServiceSpecLabel(existingService)
if (currentLabel != GREEN_LABEL_VALUE) {
// service should be targeting deployments with green label
areServicesGreen = false
}
} else {
// service targeting deployment doesn't exist
areServicesGreen = false
}
} else {
// service targeting deployment doesn't exist
areServicesGreen = false;
}
}
}
return areServicesGreen;
return areServicesGreen
}
export function getServiceSpecLabel(inputObject: any): string {
if (inputObject?.spec?.selector[BLUE_GREEN_VERSION_LABEL]) {
return inputObject.spec.selector[BLUE_GREEN_VERSION_LABEL];
}
if (inputObject?.spec?.selector[BLUE_GREEN_VERSION_LABEL]) {
return inputObject.spec.selector[BLUE_GREEN_VERSION_LABEL]
}
return "";
return ''
}
@@ -1,272 +1,277 @@
import { Kubectl } from "../../types/kubectl";
import * as kubectlUtils from "../../utilities/trafficSplitUtils";
import * as fileHelper from "../../utilities/fileUtils";
import {Kubectl} from '../../types/kubectl'
import * as kubectlUtils from '../../utilities/trafficSplitUtils'
import * as fileHelper from '../../utilities/fileUtils'
import {
BlueGreenManifests,
createWorkloadsWithLabel,
deleteObjects,
deleteWorkloadsWithLabel,
fetchResource,
getBlueGreenResourceName,
getManifestObjects,
getNewBlueGreenObject,
GREEN_LABEL_VALUE,
GREEN_SUFFIX,
NONE_LABEL_VALUE,
STABLE_SUFFIX,
} from "./blueGreenHelper";
BlueGreenManifests,
createWorkloadsWithLabel,
deleteObjects,
deleteWorkloadsWithLabel,
fetchResource,
getBlueGreenResourceName,
getManifestObjects,
getNewBlueGreenObject,
GREEN_LABEL_VALUE,
GREEN_SUFFIX,
NONE_LABEL_VALUE,
STABLE_SUFFIX
} from './blueGreenHelper'
const TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX = "-trafficsplit";
const TRAFFIC_SPLIT_OBJECT = "TrafficSplit";
const MIN_VAL = 0;
const MAX_VAL = 100;
const TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX = '-trafficsplit'
const TRAFFIC_SPLIT_OBJECT = 'TrafficSplit'
const MIN_VAL = 0
const MAX_VAL = 100
export async function deployBlueGreenSMI(
kubectl: Kubectl,
filePaths: string[]
kubectl: Kubectl,
filePaths: string[]
) {
// get all kubernetes objects defined in manifest files
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths);
// get all kubernetes objects defined in manifest files
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths)
// create services and other objects
const newObjectsList = manifestObjects.otherObjects
.concat(manifestObjects.serviceEntityList)
.concat(manifestObjects.ingressEntityList)
.concat(manifestObjects.unroutedServiceEntityList);
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
await kubectl.apply(manifestFiles);
// create services and other objects
const newObjectsList = manifestObjects.otherObjects
.concat(manifestObjects.serviceEntityList)
.concat(manifestObjects.ingressEntityList)
.concat(manifestObjects.unroutedServiceEntityList)
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList)
await kubectl.apply(manifestFiles)
// make extraservices and trafficsplit
await setupSMI(kubectl, manifestObjects.serviceEntityList);
// make extraservices and trafficsplit
await setupSMI(kubectl, manifestObjects.serviceEntityList)
// create new deloyments
return await createWorkloadsWithLabel(
kubectl,
manifestObjects.deploymentEntityList,
GREEN_LABEL_VALUE
);
// create new deloyments
return await createWorkloadsWithLabel(
kubectl,
manifestObjects.deploymentEntityList,
GREEN_LABEL_VALUE
)
}
export async function promoteBlueGreenSMI(kubectl: Kubectl, manifestObjects) {
// checking if there is something to promote
if (
!(await validateTrafficSplitsState(
kubectl,
manifestObjects.serviceEntityList
))
) {
throw Error("Not in promote state SMI");
}
// checking if there is something to promote
if (
!(await validateTrafficSplitsState(
kubectl,
manifestObjects.serviceEntityList
))
) {
throw Error('Not in promote state SMI')
}
// create stable deployments with new configuration
return await createWorkloadsWithLabel(
kubectl,
manifestObjects.deploymentEntityList,
NONE_LABEL_VALUE
);
// create stable deployments with new configuration
return await createWorkloadsWithLabel(
kubectl,
manifestObjects.deploymentEntityList,
NONE_LABEL_VALUE
)
}
export async function rejectBlueGreenSMI(
kubectl: Kubectl,
filePaths: string[]
kubectl: Kubectl,
filePaths: string[]
) {
// get all kubernetes objects defined in manifest files
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths);
// get all kubernetes objects defined in manifest files
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths)
// route trafficsplit to stable deploymetns
await routeBlueGreenSMI(
kubectl,
NONE_LABEL_VALUE,
manifestObjects.serviceEntityList
);
// route trafficsplit to stable deploymetns
await routeBlueGreenSMI(
kubectl,
NONE_LABEL_VALUE,
manifestObjects.serviceEntityList
)
// delete rejected new bluegreen deployments
await deleteWorkloadsWithLabel(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.deploymentEntityList
);
// delete rejected new bluegreen deployments
await deleteWorkloadsWithLabel(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.deploymentEntityList
)
// delete trafficsplit and extra services
await cleanupSMI(kubectl, manifestObjects.serviceEntityList);
// delete trafficsplit and extra services
await cleanupSMI(kubectl, manifestObjects.serviceEntityList)
}
export async function setupSMI(kubectl: Kubectl, serviceEntityList: any[]) {
const newObjectsList = [];
const trafficObjectList = [];
const newObjectsList = []
const trafficObjectList = []
serviceEntityList.forEach((serviceObject) => {
// create a trafficsplit for service
trafficObjectList.push(serviceObject);
// set up the services for trafficsplit
const newStableService = getSMIServiceResource(
serviceObject,
STABLE_SUFFIX
);
const newGreenService = getSMIServiceResource(serviceObject, GREEN_SUFFIX);
newObjectsList.push(newStableService);
newObjectsList.push(newGreenService);
});
serviceEntityList.forEach((serviceObject) => {
// create a trafficsplit for service
trafficObjectList.push(serviceObject)
// set up the services for trafficsplit
const newStableService = getSMIServiceResource(
serviceObject,
STABLE_SUFFIX
)
const newGreenService = getSMIServiceResource(serviceObject, GREEN_SUFFIX)
newObjectsList.push(newStableService)
newObjectsList.push(newGreenService)
})
// create services
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList);
await kubectl.apply(manifestFiles);
// create services
const manifestFiles = fileHelper.writeObjectsToFile(newObjectsList)
await kubectl.apply(manifestFiles)
// route to stable service
trafficObjectList.forEach((inputObject) => {
createTrafficSplitObject(
kubectl,
inputObject.metadata.name,
NONE_LABEL_VALUE
);
});
// route to stable service
trafficObjectList.forEach((inputObject) => {
createTrafficSplitObject(
kubectl,
inputObject.metadata.name,
NONE_LABEL_VALUE
)
})
}
let trafficSplitAPIVersion = "";
let trafficSplitAPIVersion = ''
async function createTrafficSplitObject(
kubectl: Kubectl,
name: string,
nextLabel: string
kubectl: Kubectl,
name: string,
nextLabel: string
): Promise<any> {
// cache traffic split api version
if (!trafficSplitAPIVersion)
trafficSplitAPIVersion = await kubectlUtils.getTrafficSplitAPIVersion(
kubectl
);
// cache traffic split api version
if (!trafficSplitAPIVersion)
trafficSplitAPIVersion = await kubectlUtils.getTrafficSplitAPIVersion(
kubectl
)
// decide weights based on nextlabel
const stableWeight: number =
nextLabel === GREEN_LABEL_VALUE ? MIN_VAL : MAX_VAL;
const greenWeight: number =
nextLabel === GREEN_LABEL_VALUE ? MAX_VAL : MIN_VAL;
// decide weights based on nextlabel
const stableWeight: number =
nextLabel === GREEN_LABEL_VALUE ? MIN_VAL : MAX_VAL
const greenWeight: number =
nextLabel === GREEN_LABEL_VALUE ? MAX_VAL : MIN_VAL
const trafficSplitObject = JSON.stringify({
apiVersion: trafficSplitAPIVersion,
kind: "TrafficSplit",
metadata: {
name: getBlueGreenResourceName(name, TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX),
},
spec: {
service: name,
backends: [
{
service: getBlueGreenResourceName(name, STABLE_SUFFIX),
weight: stableWeight,
},
{
service: getBlueGreenResourceName(name, GREEN_SUFFIX),
weight: greenWeight,
},
],
},
});
const trafficSplitObject = JSON.stringify({
apiVersion: trafficSplitAPIVersion,
kind: 'TrafficSplit',
metadata: {
name: getBlueGreenResourceName(name, TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX)
},
spec: {
service: name,
backends: [
{
service: getBlueGreenResourceName(name, STABLE_SUFFIX),
weight: stableWeight
},
{
service: getBlueGreenResourceName(name, GREEN_SUFFIX),
weight: greenWeight
}
]
}
})
// create traffic split object
const trafficSplitManifestFile = fileHelper.writeManifestToFile(
trafficSplitObject,
TRAFFIC_SPLIT_OBJECT,
getBlueGreenResourceName(name, TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX)
);
// create traffic split object
const trafficSplitManifestFile = fileHelper.writeManifestToFile(
trafficSplitObject,
TRAFFIC_SPLIT_OBJECT,
getBlueGreenResourceName(name, TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX)
)
await kubectl.apply(trafficSplitManifestFile);
await kubectl.apply(trafficSplitManifestFile)
}
export function getSMIServiceResource(
inputObject: any,
suffix: string
inputObject: any,
suffix: string
): object {
const newObject = JSON.parse(JSON.stringify(inputObject));
const newObject = JSON.parse(JSON.stringify(inputObject))
if (suffix === STABLE_SUFFIX) {
// adding stable suffix to service name
newObject.metadata.name = getBlueGreenResourceName(
inputObject.metadata.name,
STABLE_SUFFIX
);
return getNewBlueGreenObject(newObject, NONE_LABEL_VALUE);
} else {
// green label will be added for these
return getNewBlueGreenObject(newObject, GREEN_LABEL_VALUE);
}
if (suffix === STABLE_SUFFIX) {
// adding stable suffix to service name
newObject.metadata.name = getBlueGreenResourceName(
inputObject.metadata.name,
STABLE_SUFFIX
)
return getNewBlueGreenObject(newObject, NONE_LABEL_VALUE)
} else {
// green label will be added for these
return getNewBlueGreenObject(newObject, GREEN_LABEL_VALUE)
}
}
export async function routeBlueGreenSMI(
kubectl: Kubectl,
nextLabel: string,
serviceEntityList: any[]
kubectl: Kubectl,
nextLabel: string,
serviceEntityList: any[]
) {
for (const serviceObject of serviceEntityList) {
// route trafficsplit to given label
await createTrafficSplitObject(
kubectl,
serviceObject.metadata.name,
nextLabel
);
}
for (const serviceObject of serviceEntityList) {
// route trafficsplit to given label
await createTrafficSplitObject(
kubectl,
serviceObject.metadata.name,
nextLabel
)
}
}
export async function validateTrafficSplitsState(
kubectl: Kubectl,
serviceEntityList: any[]
kubectl: Kubectl,
serviceEntityList: any[]
): Promise<boolean> {
let trafficSplitsInRightState: boolean = true;
let trafficSplitsInRightState: boolean = true
for (const serviceObject of serviceEntityList) {
const name = serviceObject.metadata.name;
let trafficSplitObject = await fetchResource(
kubectl,
TRAFFIC_SPLIT_OBJECT,
getBlueGreenResourceName(name, TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX)
);
for (const serviceObject of serviceEntityList) {
const name = serviceObject.metadata.name
let trafficSplitObject = await fetchResource(
kubectl,
TRAFFIC_SPLIT_OBJECT,
getBlueGreenResourceName(name, TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX)
)
if (!trafficSplitObject) {
// no traffic split exits
trafficSplitsInRightState = false;
}
trafficSplitObject = JSON.parse(JSON.stringify(trafficSplitObject));
trafficSplitObject.spec.backends.forEach((element) => {
// checking if trafficsplit in right state to deploy
if (element.service === getBlueGreenResourceName(name, GREEN_SUFFIX)) {
if (element.weight != MAX_VAL) trafficSplitsInRightState = false;
if (!trafficSplitObject) {
// no traffic split exits
trafficSplitsInRightState = false
}
if (element.service === getBlueGreenResourceName(name, STABLE_SUFFIX)) {
if (element.weight != MIN_VAL) trafficSplitsInRightState = false;
}
});
}
trafficSplitObject = JSON.parse(JSON.stringify(trafficSplitObject))
trafficSplitObject.spec.backends.forEach((element) => {
// checking if trafficsplit in right state to deploy
if (element.service === getBlueGreenResourceName(name, GREEN_SUFFIX)) {
if (element.weight != MAX_VAL) trafficSplitsInRightState = false
}
return trafficSplitsInRightState;
if (
element.service === getBlueGreenResourceName(name, STABLE_SUFFIX)
) {
if (element.weight != MIN_VAL) trafficSplitsInRightState = false
}
})
}
return trafficSplitsInRightState
}
export async function cleanupSMI(kubectl: Kubectl, serviceEntityList: any[]) {
const deleteList = [];
const deleteList = []
serviceEntityList.forEach((serviceObject) => {
deleteList.push({
name: getBlueGreenResourceName(
serviceObject.metadata.name,
TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX
),
kind: TRAFFIC_SPLIT_OBJECT,
});
serviceEntityList.forEach((serviceObject) => {
deleteList.push({
name: getBlueGreenResourceName(
serviceObject.metadata.name,
TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX
),
kind: TRAFFIC_SPLIT_OBJECT
})
deleteList.push({
name: getBlueGreenResourceName(serviceObject.metadata.name, GREEN_SUFFIX),
kind: serviceObject.kind,
});
deleteList.push({
name: getBlueGreenResourceName(
serviceObject.metadata.name,
GREEN_SUFFIX
),
kind: serviceObject.kind
})
deleteList.push({
name: getBlueGreenResourceName(
serviceObject.metadata.name,
STABLE_SUFFIX
),
kind: serviceObject.kind,
});
});
deleteList.push({
name: getBlueGreenResourceName(
serviceObject.metadata.name,
STABLE_SUFFIX
),
kind: serviceObject.kind
})
})
// delete all objects
await deleteObjects(kubectl, deleteList);
// delete all objects
await deleteObjects(kubectl, deleteList)
}