Skip to content

Commit

Permalink
Blue/Green Refactor (#229)
Browse files Browse the repository at this point in the history
* fresh new branch

* Added coverage to gitignore

Signed-off-by: Jaiveer Katariya <jaiveerkatariya@Jaiveers-MBP.lan>

* reverted package-lock.json

Signed-off-by: Jaiveer Katariya <jaiveerkatariya@Jaiveers-MBP.lan>
Co-authored-by: Jaiveer Katariya <jaiveerkatariya@Jaiveers-MBP.lan>
  • Loading branch information
jaiveerk and Jaiveer Katariya authored Aug 12, 2022
1 parent 531cfdc commit 01a6551
Show file tree
Hide file tree
Showing 31 changed files with 1,758 additions and 828 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ node_modules

.DS_Store
.idea
lib/
lib/

coverage/
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"scripts": {
"build": "ncc build src/run.ts -o lib",
"test": "jest",
"coverage": "jest --coverage=true",
"format": "prettier --write .",
"format-check": "prettier --check ."
},
Expand Down
23 changes: 5 additions & 18 deletions src/actions/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,22 @@ import {
getResources,
updateManifestFiles
} from '../utilities/manifestUpdateUtils'
import {routeBlueGreen} from '../strategyHelpers/blueGreen/blueGreenHelper'
import {
annotateAndLabelResources,
checkManifestStability,
deployManifests
} from '../strategyHelpers/deploymentHelper'
import {DeploymentStrategy} from '../types/deploymentStrategy'
import {parseTrafficSplitMethod} from '../types/trafficSplitMethod'
import {parseRouteStrategy} from '../types/routeStrategy'

export async function deploy(
kubectl: Kubectl,
manifestFilePaths: string[],
deploymentStrategy: DeploymentStrategy,
annotations: {[key: string]: string} = {}
deploymentStrategy: DeploymentStrategy
) {
// update manifests
const inputManifestFiles: string[] = updateManifestFiles(manifestFilePaths)
core.debug('Input manifest files: ' + inputManifestFiles)
core.debug(`Input manifest files: ${inputManifestFiles}`)

// deploy manifests
core.startGroup('Deploying manifests')
Expand All @@ -35,11 +32,10 @@ export async function deploy(
inputManifestFiles,
deploymentStrategy,
kubectl,
trafficSplitMethod,
annotations
trafficSplitMethod
)
core.debug(`Deployed manifest files: ${deployedManifestFiles}`)
core.endGroup()
core.debug('Deployed manifest files: ' + deployedManifestFiles)

// check manifest stability
core.startGroup('Checking manifest stability')
Expand All @@ -52,15 +48,6 @@ export async function deploy(
await checkManifestStability(kubectl, resourceTypes)
core.endGroup()

if (deploymentStrategy == DeploymentStrategy.BLUE_GREEN) {
core.startGroup('Routing blue green')
const routeStrategy = parseRouteStrategy(
core.getInput('route-method', {required: true})
)
await routeBlueGreen(kubectl, inputManifestFiles, routeStrategy)
core.endGroup()
}

// print ingresses
core.startGroup('Printing ingresses')
const ingressResources: Resource[] = getResources(deployedManifestFiles, [
Expand All @@ -80,7 +67,7 @@ export async function deploy(
try {
allPods = JSON.parse((await kubectl.getAllPods()).stdout)
} catch (e) {
core.debug('Unable to parse pods: ' + e)
core.debug(`Unable to parse pods: ${e}`)
}
await annotateAndLabelResources(
deployedManifestFiles,
Expand Down
92 changes: 41 additions & 51 deletions src/actions/promote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,26 @@ import {
import * as models from '../types/kubernetesTypes'
import * as KubernetesManifestUtility from '../utilities/manifestStabilityUtils'
import {
BlueGreenManifests,
deleteWorkloadsAndServicesWithLabel,
deleteWorkloadsWithLabel,
deleteGreenObjects,
getManifestObjects,
GREEN_LABEL_VALUE,
NONE_LABEL_VALUE
} from '../strategyHelpers/blueGreen/blueGreenHelper'
import {
promoteBlueGreenService,
routeBlueGreenService
} from '../strategyHelpers/blueGreen/serviceBlueGreenHelper'

import {BlueGreenManifests} from '../types/blueGreenTypes'

import {
promoteBlueGreenIngress,
routeBlueGreenIngress
} from '../strategyHelpers/blueGreen/ingressBlueGreenHelper'
promoteBlueGreenService,
promoteBlueGreenSMI
} from '../strategyHelpers/blueGreen/promote'

import {
cleanupSMI,
promoteBlueGreenSMI,
routeBlueGreenService,
routeBlueGreenIngressUnchanged,
routeBlueGreenSMI
} from '../strategyHelpers/blueGreen/smiBlueGreenHelper'
} from '../strategyHelpers/blueGreen/route'

import {cleanupSMI} from '../strategyHelpers/blueGreen/smiBlueGreenHelper'
import {Kubectl, Resource} from '../types/kubectl'
import {DeploymentStrategy} from '../types/deploymentStrategy'
import {
Expand All @@ -40,15 +40,14 @@ import {parseRouteStrategy, RouteStrategy} from '../types/routeStrategy'
export async function promote(
kubectl: Kubectl,
manifests: string[],
deploymentStrategy: DeploymentStrategy,
annotations: {[key: string]: string} = {}
deploymentStrategy: DeploymentStrategy
) {
switch (deploymentStrategy) {
case DeploymentStrategy.CANARY:
await promoteCanary(kubectl, manifests)
break
case DeploymentStrategy.BLUE_GREEN:
await promoteBlueGreen(kubectl, manifests, annotations)
await promoteBlueGreen(kubectl, manifests)
break
default:
throw Error('Invalid promote deployment strategy')
Expand Down Expand Up @@ -98,18 +97,13 @@ async function promoteCanary(kubectl: Kubectl, manifests: string[]) {
)
} catch (ex) {
core.warning(
'Exception occurred while deleting canary and baseline workloads: ' +
ex
`Exception occurred while deleting canary and baseline workloads: ${ex}`
)
}
core.endGroup()
}

async function promoteBlueGreen(
kubectl: Kubectl,
manifests: string[],
annotations: {[key: string]: string} = {}
) {
async function promoteBlueGreen(kubectl: Kubectl, manifests: string[]) {
// update container images and pull secrets
const inputManifestFiles: string[] = updateManifestFiles(manifests)
const manifestObjects: BlueGreenManifests =
Expand All @@ -119,20 +113,24 @@ async function promoteBlueGreen(
core.getInput('route-method', {required: true})
)

core.startGroup('Deleting old deployment and making new one')
let result
if (routeStrategy == RouteStrategy.INGRESS) {
result = await promoteBlueGreenIngress(kubectl, manifestObjects)
} else if (routeStrategy == RouteStrategy.SMI) {
result = await promoteBlueGreenSMI(kubectl, manifestObjects)
} else {
result = await promoteBlueGreenService(kubectl, manifestObjects)
}
core.startGroup('Deleting old deployment and making new stable deployment')

const {deployResult} = await (async () => {
switch (routeStrategy) {
case RouteStrategy.INGRESS:
return await promoteBlueGreenIngress(kubectl, manifestObjects)
case RouteStrategy.SMI:
return await promoteBlueGreenSMI(kubectl, manifestObjects)
default:
return await promoteBlueGreenService(kubectl, manifestObjects)
}
})()

core.endGroup()

// checking stability of newly created deployments
core.startGroup('Checking manifest stability')
const deployedManifestFiles = result.newFilePaths
const deployedManifestFiles = deployResult.manifestFiles
const resources: Resource[] = getResources(
deployedManifestFiles,
models.DEPLOYMENT_TYPES.concat([
Expand All @@ -146,42 +144,34 @@ async function promoteBlueGreen(
'Routing to new deployments and deleting old workloads and services'
)
if (routeStrategy == RouteStrategy.INGRESS) {
await routeBlueGreenIngress(
await routeBlueGreenIngressUnchanged(
kubectl,
null,
manifestObjects.serviceNameMap,
manifestObjects.ingressEntityList
)
await deleteWorkloadsAndServicesWithLabel(

await deleteGreenObjects(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.deploymentEntityList,
manifestObjects.serviceEntityList
[].concat(
manifestObjects.deploymentEntityList,
manifestObjects.serviceEntityList
)
)
} else if (routeStrategy == RouteStrategy.SMI) {
await routeBlueGreenSMI(
kubectl,
NONE_LABEL_VALUE,
manifestObjects.serviceEntityList,
annotations
)
await deleteWorkloadsWithLabel(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.deploymentEntityList
manifestObjects.serviceEntityList
)
await deleteGreenObjects(kubectl, manifestObjects.deploymentEntityList)
await cleanupSMI(kubectl, manifestObjects.serviceEntityList)
} else {
await routeBlueGreenService(
kubectl,
NONE_LABEL_VALUE,
manifestObjects.serviceEntityList
)
await deleteWorkloadsWithLabel(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.deploymentEntityList
)
await deleteGreenObjects(kubectl, manifestObjects.deploymentEntityList)
}
core.endGroup()
}
33 changes: 17 additions & 16 deletions src/actions/reject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ import * as core from '@actions/core'
import * as canaryDeploymentHelper from '../strategyHelpers/canary/canaryHelper'
import * as SMICanaryDeploymentHelper from '../strategyHelpers/canary/smiCanaryHelper'
import {Kubectl} from '../types/kubectl'
import {rejectBlueGreenService} from '../strategyHelpers/blueGreen/serviceBlueGreenHelper'
import {rejectBlueGreenIngress} from '../strategyHelpers/blueGreen/ingressBlueGreenHelper'
import {rejectBlueGreenSMI} from '../strategyHelpers/blueGreen/smiBlueGreenHelper'
import {BlueGreenManifests} from '../types/blueGreenTypes'
import {
rejectBlueGreenIngress,
rejectBlueGreenService,
rejectBlueGreenSMI
} from '../strategyHelpers/blueGreen/reject'
import {getManifestObjects} from '../strategyHelpers/blueGreen/blueGreenHelper'
import {DeploymentStrategy} from '../types/deploymentStrategy'
import {
parseTrafficSplitMethod,
Expand All @@ -15,15 +19,14 @@ import {parseRouteStrategy, RouteStrategy} from '../types/routeStrategy'
export async function reject(
kubectl: Kubectl,
manifests: string[],
deploymentStrategy: DeploymentStrategy,
annotations: {[key: string]: string} = {}
deploymentStrategy: DeploymentStrategy
) {
switch (deploymentStrategy) {
case DeploymentStrategy.CANARY:
await rejectCanary(kubectl, manifests)
break
case DeploymentStrategy.BLUE_GREEN:
await rejectBlueGreen(kubectl, manifests, annotations)
await rejectBlueGreen(kubectl, manifests)
break
default:
throw 'Invalid delete deployment strategy'
Expand Down Expand Up @@ -55,22 +58,20 @@ async function rejectCanary(kubectl: Kubectl, manifests: string[]) {
core.endGroup()
}

async function rejectBlueGreen(
kubectl: Kubectl,
manifests: string[],
annotations: {[key: string]: string} = {}
) {
core.startGroup('Rejecting deployment with blue green strategy')

async function rejectBlueGreen(kubectl: Kubectl, manifests: string[]) {
const routeStrategy = parseRouteStrategy(
core.getInput('route-method', {required: true})
)
core.startGroup('Rejecting deployment with blue green strategy')
core.info(`using routeMethod ${routeStrategy}`)
const manifestObjects: BlueGreenManifests = getManifestObjects(manifests)

if (routeStrategy == RouteStrategy.INGRESS) {
await rejectBlueGreenIngress(kubectl, manifests)
await rejectBlueGreenIngress(kubectl, manifestObjects)
} else if (routeStrategy == RouteStrategy.SMI) {
await rejectBlueGreenSMI(kubectl, manifests, annotations)
await rejectBlueGreenSMI(kubectl, manifestObjects)
} else {
await rejectBlueGreenService(kubectl, manifests)
await rejectBlueGreenService(kubectl, manifestObjects)
}
core.endGroup()
}
16 changes: 16 additions & 0 deletions src/inputUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as core from '@actions/core'
import {parseAnnotations} from './types/annotations'

export const inputAnnotations = parseAnnotations(
core.getInput('annotations', {required: false})
)

export function getBufferTime(): number {
const inputBufferTime = parseInt(
core.getInput('version-switch-buffer') || '0'
)
if (inputBufferTime < 0 || inputBufferTime > 300)
throw Error('Version switch buffer must be between 0 and 300 (inclusive)')

return inputBufferTime
}
10 changes: 3 additions & 7 deletions src/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {Action, parseAction} from './types/action'
import {parseDeploymentStrategy} from './types/deploymentStrategy'
import {getFilesFromDirectories} from './utilities/fileUtils'
import {PrivateKubectl} from './types/privatekubectl'
import {parseAnnotations} from './types/annotations'

export async function run() {
// verify kubeconfig is set
Expand All @@ -20,9 +19,6 @@ export async function run() {
const action: Action | undefined = parseAction(
core.getInput('action', {required: true})
)
const annotations = parseAnnotations(
core.getInput('annotations', {required: false})
)
const strategy = parseDeploymentStrategy(core.getInput('strategy'))
const manifestsInput = core.getInput('manifests', {required: true})
const manifestFilePaths = manifestsInput
Expand Down Expand Up @@ -51,15 +47,15 @@ export async function run() {
// run action
switch (action) {
case Action.DEPLOY: {
await deploy(kubectl, fullManifestFilePaths, strategy, annotations)
await deploy(kubectl, fullManifestFilePaths, strategy)
break
}
case Action.PROMOTE: {
await promote(kubectl, fullManifestFilePaths, strategy, annotations)
await promote(kubectl, fullManifestFilePaths, strategy)
break
}
case Action.REJECT: {
await reject(kubectl, fullManifestFilePaths, strategy, annotations)
await reject(kubectl, fullManifestFilePaths, strategy)
break
}
default: {
Expand Down
Loading

0 comments on commit 01a6551

Please sign in to comment.