Skip to content

Commit 01a6551

Browse files
jaiveerkJaiveer Katariya
andauthored
Blue/Green Refactor (#229)
* fresh new branch * Added coverage to gitignore Signed-off-by: Jaiveer Katariya <[email protected]> * reverted package-lock.json Signed-off-by: Jaiveer Katariya <[email protected]> Co-authored-by: Jaiveer Katariya <[email protected]>
1 parent 531cfdc commit 01a6551

31 files changed

+1758
-828
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@ node_modules
22

33
.DS_Store
44
.idea
5-
lib/
5+
lib/
6+
7+
coverage/

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"scripts": {
77
"build": "ncc build src/run.ts -o lib",
88
"test": "jest",
9+
"coverage": "jest --coverage=true",
910
"format": "prettier --write .",
1011
"format-check": "prettier --check ."
1112
},

src/actions/deploy.ts

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,22 @@ import {
66
getResources,
77
updateManifestFiles
88
} from '../utilities/manifestUpdateUtils'
9-
import {routeBlueGreen} from '../strategyHelpers/blueGreen/blueGreenHelper'
109
import {
1110
annotateAndLabelResources,
1211
checkManifestStability,
1312
deployManifests
1413
} from '../strategyHelpers/deploymentHelper'
1514
import {DeploymentStrategy} from '../types/deploymentStrategy'
1615
import {parseTrafficSplitMethod} from '../types/trafficSplitMethod'
17-
import {parseRouteStrategy} from '../types/routeStrategy'
1816

1917
export async function deploy(
2018
kubectl: Kubectl,
2119
manifestFilePaths: string[],
22-
deploymentStrategy: DeploymentStrategy,
23-
annotations: {[key: string]: string} = {}
20+
deploymentStrategy: DeploymentStrategy
2421
) {
2522
// update manifests
2623
const inputManifestFiles: string[] = updateManifestFiles(manifestFilePaths)
27-
core.debug('Input manifest files: ' + inputManifestFiles)
24+
core.debug(`Input manifest files: ${inputManifestFiles}`)
2825

2926
// deploy manifests
3027
core.startGroup('Deploying manifests')
@@ -35,11 +32,10 @@ export async function deploy(
3532
inputManifestFiles,
3633
deploymentStrategy,
3734
kubectl,
38-
trafficSplitMethod,
39-
annotations
35+
trafficSplitMethod
4036
)
37+
core.debug(`Deployed manifest files: ${deployedManifestFiles}`)
4138
core.endGroup()
42-
core.debug('Deployed manifest files: ' + deployedManifestFiles)
4339

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

55-
if (deploymentStrategy == DeploymentStrategy.BLUE_GREEN) {
56-
core.startGroup('Routing blue green')
57-
const routeStrategy = parseRouteStrategy(
58-
core.getInput('route-method', {required: true})
59-
)
60-
await routeBlueGreen(kubectl, inputManifestFiles, routeStrategy)
61-
core.endGroup()
62-
}
63-
6451
// print ingresses
6552
core.startGroup('Printing ingresses')
6653
const ingressResources: Resource[] = getResources(deployedManifestFiles, [
@@ -80,7 +67,7 @@ export async function deploy(
8067
try {
8168
allPods = JSON.parse((await kubectl.getAllPods()).stdout)
8269
} catch (e) {
83-
core.debug('Unable to parse pods: ' + e)
70+
core.debug(`Unable to parse pods: ${e}`)
8471
}
8572
await annotateAndLabelResources(
8673
deployedManifestFiles,

src/actions/promote.ts

Lines changed: 41 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,26 @@ import {
99
import * as models from '../types/kubernetesTypes'
1010
import * as KubernetesManifestUtility from '../utilities/manifestStabilityUtils'
1111
import {
12-
BlueGreenManifests,
13-
deleteWorkloadsAndServicesWithLabel,
14-
deleteWorkloadsWithLabel,
12+
deleteGreenObjects,
1513
getManifestObjects,
16-
GREEN_LABEL_VALUE,
1714
NONE_LABEL_VALUE
1815
} from '../strategyHelpers/blueGreen/blueGreenHelper'
19-
import {
20-
promoteBlueGreenService,
21-
routeBlueGreenService
22-
} from '../strategyHelpers/blueGreen/serviceBlueGreenHelper'
16+
17+
import {BlueGreenManifests} from '../types/blueGreenTypes'
18+
2319
import {
2420
promoteBlueGreenIngress,
25-
routeBlueGreenIngress
26-
} from '../strategyHelpers/blueGreen/ingressBlueGreenHelper'
21+
promoteBlueGreenService,
22+
promoteBlueGreenSMI
23+
} from '../strategyHelpers/blueGreen/promote'
24+
2725
import {
28-
cleanupSMI,
29-
promoteBlueGreenSMI,
26+
routeBlueGreenService,
27+
routeBlueGreenIngressUnchanged,
3028
routeBlueGreenSMI
31-
} from '../strategyHelpers/blueGreen/smiBlueGreenHelper'
29+
} from '../strategyHelpers/blueGreen/route'
30+
31+
import {cleanupSMI} from '../strategyHelpers/blueGreen/smiBlueGreenHelper'
3232
import {Kubectl, Resource} from '../types/kubectl'
3333
import {DeploymentStrategy} from '../types/deploymentStrategy'
3434
import {
@@ -40,15 +40,14 @@ import {parseRouteStrategy, RouteStrategy} from '../types/routeStrategy'
4040
export async function promote(
4141
kubectl: Kubectl,
4242
manifests: string[],
43-
deploymentStrategy: DeploymentStrategy,
44-
annotations: {[key: string]: string} = {}
43+
deploymentStrategy: DeploymentStrategy
4544
) {
4645
switch (deploymentStrategy) {
4746
case DeploymentStrategy.CANARY:
4847
await promoteCanary(kubectl, manifests)
4948
break
5049
case DeploymentStrategy.BLUE_GREEN:
51-
await promoteBlueGreen(kubectl, manifests, annotations)
50+
await promoteBlueGreen(kubectl, manifests)
5251
break
5352
default:
5453
throw Error('Invalid promote deployment strategy')
@@ -98,18 +97,13 @@ async function promoteCanary(kubectl: Kubectl, manifests: string[]) {
9897
)
9998
} catch (ex) {
10099
core.warning(
101-
'Exception occurred while deleting canary and baseline workloads: ' +
102-
ex
100+
`Exception occurred while deleting canary and baseline workloads: ${ex}`
103101
)
104102
}
105103
core.endGroup()
106104
}
107105

108-
async function promoteBlueGreen(
109-
kubectl: Kubectl,
110-
manifests: string[],
111-
annotations: {[key: string]: string} = {}
112-
) {
106+
async function promoteBlueGreen(kubectl: Kubectl, manifests: string[]) {
113107
// update container images and pull secrets
114108
const inputManifestFiles: string[] = updateManifestFiles(manifests)
115109
const manifestObjects: BlueGreenManifests =
@@ -119,20 +113,24 @@ async function promoteBlueGreen(
119113
core.getInput('route-method', {required: true})
120114
)
121115

122-
core.startGroup('Deleting old deployment and making new one')
123-
let result
124-
if (routeStrategy == RouteStrategy.INGRESS) {
125-
result = await promoteBlueGreenIngress(kubectl, manifestObjects)
126-
} else if (routeStrategy == RouteStrategy.SMI) {
127-
result = await promoteBlueGreenSMI(kubectl, manifestObjects)
128-
} else {
129-
result = await promoteBlueGreenService(kubectl, manifestObjects)
130-
}
116+
core.startGroup('Deleting old deployment and making new stable deployment')
117+
118+
const {deployResult} = await (async () => {
119+
switch (routeStrategy) {
120+
case RouteStrategy.INGRESS:
121+
return await promoteBlueGreenIngress(kubectl, manifestObjects)
122+
case RouteStrategy.SMI:
123+
return await promoteBlueGreenSMI(kubectl, manifestObjects)
124+
default:
125+
return await promoteBlueGreenService(kubectl, manifestObjects)
126+
}
127+
})()
128+
131129
core.endGroup()
132130

133131
// checking stability of newly created deployments
134132
core.startGroup('Checking manifest stability')
135-
const deployedManifestFiles = result.newFilePaths
133+
const deployedManifestFiles = deployResult.manifestFiles
136134
const resources: Resource[] = getResources(
137135
deployedManifestFiles,
138136
models.DEPLOYMENT_TYPES.concat([
@@ -146,42 +144,34 @@ async function promoteBlueGreen(
146144
'Routing to new deployments and deleting old workloads and services'
147145
)
148146
if (routeStrategy == RouteStrategy.INGRESS) {
149-
await routeBlueGreenIngress(
147+
await routeBlueGreenIngressUnchanged(
150148
kubectl,
151-
null,
152149
manifestObjects.serviceNameMap,
153150
manifestObjects.ingressEntityList
154151
)
155-
await deleteWorkloadsAndServicesWithLabel(
152+
153+
await deleteGreenObjects(
156154
kubectl,
157-
GREEN_LABEL_VALUE,
158-
manifestObjects.deploymentEntityList,
159-
manifestObjects.serviceEntityList
155+
[].concat(
156+
manifestObjects.deploymentEntityList,
157+
manifestObjects.serviceEntityList
158+
)
160159
)
161160
} else if (routeStrategy == RouteStrategy.SMI) {
162161
await routeBlueGreenSMI(
163162
kubectl,
164163
NONE_LABEL_VALUE,
165-
manifestObjects.serviceEntityList,
166-
annotations
167-
)
168-
await deleteWorkloadsWithLabel(
169-
kubectl,
170-
GREEN_LABEL_VALUE,
171-
manifestObjects.deploymentEntityList
164+
manifestObjects.serviceEntityList
172165
)
166+
await deleteGreenObjects(kubectl, manifestObjects.deploymentEntityList)
173167
await cleanupSMI(kubectl, manifestObjects.serviceEntityList)
174168
} else {
175169
await routeBlueGreenService(
176170
kubectl,
177171
NONE_LABEL_VALUE,
178172
manifestObjects.serviceEntityList
179173
)
180-
await deleteWorkloadsWithLabel(
181-
kubectl,
182-
GREEN_LABEL_VALUE,
183-
manifestObjects.deploymentEntityList
184-
)
174+
await deleteGreenObjects(kubectl, manifestObjects.deploymentEntityList)
185175
}
186176
core.endGroup()
187177
}

src/actions/reject.ts

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ import * as core from '@actions/core'
22
import * as canaryDeploymentHelper from '../strategyHelpers/canary/canaryHelper'
33
import * as SMICanaryDeploymentHelper from '../strategyHelpers/canary/smiCanaryHelper'
44
import {Kubectl} from '../types/kubectl'
5-
import {rejectBlueGreenService} from '../strategyHelpers/blueGreen/serviceBlueGreenHelper'
6-
import {rejectBlueGreenIngress} from '../strategyHelpers/blueGreen/ingressBlueGreenHelper'
7-
import {rejectBlueGreenSMI} from '../strategyHelpers/blueGreen/smiBlueGreenHelper'
5+
import {BlueGreenManifests} from '../types/blueGreenTypes'
6+
import {
7+
rejectBlueGreenIngress,
8+
rejectBlueGreenService,
9+
rejectBlueGreenSMI
10+
} from '../strategyHelpers/blueGreen/reject'
11+
import {getManifestObjects} from '../strategyHelpers/blueGreen/blueGreenHelper'
812
import {DeploymentStrategy} from '../types/deploymentStrategy'
913
import {
1014
parseTrafficSplitMethod,
@@ -15,15 +19,14 @@ import {parseRouteStrategy, RouteStrategy} from '../types/routeStrategy'
1519
export async function reject(
1620
kubectl: Kubectl,
1721
manifests: string[],
18-
deploymentStrategy: DeploymentStrategy,
19-
annotations: {[key: string]: string} = {}
22+
deploymentStrategy: DeploymentStrategy
2023
) {
2124
switch (deploymentStrategy) {
2225
case DeploymentStrategy.CANARY:
2326
await rejectCanary(kubectl, manifests)
2427
break
2528
case DeploymentStrategy.BLUE_GREEN:
26-
await rejectBlueGreen(kubectl, manifests, annotations)
29+
await rejectBlueGreen(kubectl, manifests)
2730
break
2831
default:
2932
throw 'Invalid delete deployment strategy'
@@ -55,22 +58,20 @@ async function rejectCanary(kubectl: Kubectl, manifests: string[]) {
5558
core.endGroup()
5659
}
5760

58-
async function rejectBlueGreen(
59-
kubectl: Kubectl,
60-
manifests: string[],
61-
annotations: {[key: string]: string} = {}
62-
) {
63-
core.startGroup('Rejecting deployment with blue green strategy')
64-
61+
async function rejectBlueGreen(kubectl: Kubectl, manifests: string[]) {
6562
const routeStrategy = parseRouteStrategy(
6663
core.getInput('route-method', {required: true})
6764
)
65+
core.startGroup('Rejecting deployment with blue green strategy')
66+
core.info(`using routeMethod ${routeStrategy}`)
67+
const manifestObjects: BlueGreenManifests = getManifestObjects(manifests)
68+
6869
if (routeStrategy == RouteStrategy.INGRESS) {
69-
await rejectBlueGreenIngress(kubectl, manifests)
70+
await rejectBlueGreenIngress(kubectl, manifestObjects)
7071
} else if (routeStrategy == RouteStrategy.SMI) {
71-
await rejectBlueGreenSMI(kubectl, manifests, annotations)
72+
await rejectBlueGreenSMI(kubectl, manifestObjects)
7273
} else {
73-
await rejectBlueGreenService(kubectl, manifests)
74+
await rejectBlueGreenService(kubectl, manifestObjects)
7475
}
7576
core.endGroup()
7677
}

src/inputUtils.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as core from '@actions/core'
2+
import {parseAnnotations} from './types/annotations'
3+
4+
export const inputAnnotations = parseAnnotations(
5+
core.getInput('annotations', {required: false})
6+
)
7+
8+
export function getBufferTime(): number {
9+
const inputBufferTime = parseInt(
10+
core.getInput('version-switch-buffer') || '0'
11+
)
12+
if (inputBufferTime < 0 || inputBufferTime > 300)
13+
throw Error('Version switch buffer must be between 0 and 300 (inclusive)')
14+
15+
return inputBufferTime
16+
}

src/run.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {Action, parseAction} from './types/action'
77
import {parseDeploymentStrategy} from './types/deploymentStrategy'
88
import {getFilesFromDirectories} from './utilities/fileUtils'
99
import {PrivateKubectl} from './types/privatekubectl'
10-
import {parseAnnotations} from './types/annotations'
1110

1211
export async function run() {
1312
// verify kubeconfig is set
@@ -20,9 +19,6 @@ export async function run() {
2019
const action: Action | undefined = parseAction(
2120
core.getInput('action', {required: true})
2221
)
23-
const annotations = parseAnnotations(
24-
core.getInput('annotations', {required: false})
25-
)
2622
const strategy = parseDeploymentStrategy(core.getInput('strategy'))
2723
const manifestsInput = core.getInput('manifests', {required: true})
2824
const manifestFilePaths = manifestsInput
@@ -51,15 +47,15 @@ export async function run() {
5147
// run action
5248
switch (action) {
5349
case Action.DEPLOY: {
54-
await deploy(kubectl, fullManifestFilePaths, strategy, annotations)
50+
await deploy(kubectl, fullManifestFilePaths, strategy)
5551
break
5652
}
5753
case Action.PROMOTE: {
58-
await promote(kubectl, fullManifestFilePaths, strategy, annotations)
54+
await promote(kubectl, fullManifestFilePaths, strategy)
5955
break
6056
}
6157
case Action.REJECT: {
62-
await reject(kubectl, fullManifestFilePaths, strategy, annotations)
58+
await reject(kubectl, fullManifestFilePaths, strategy)
6359
break
6460
}
6561
default: {

0 commit comments

Comments
 (0)