Skip to content

Commit 71e93a7

Browse files
Vidya2606Vidya Reddy
andauthored
Added Traffic split annotations (#215)
* Added Traffic split annotations * traffic split - blueGreen deployment * traffic split - canary deployment * Traffic split annotations - canary deployment * updated Readme and action.yml * Traffic split - canary deployment * clean code * Clean code * Clean code * Create annotation object * Updated Readme and action.yml * Spelling correction Co-authored-by: Vidya Reddy <[email protected]>
1 parent 19d66d6 commit 71e93a7

File tree

11 files changed

+78
-30
lines changed

11 files changed

+78
-30
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ Following are the key capabilities of this action:
7474
<td>traffic-split-method </br></br>(Optional)</td>
7575
<td>Acceptable values: pod/smi.<br> Default value: pod <br>SMI: Percentage traffic split is done at request level using service mesh. Service mesh has to be setup by cluster admin. Orchestration of <a href="https://github.com/servicemeshinterface/smi-spec/blob/master/apis/traffic-split/v1alpha3/traffic-split.md" data-raw-source="TrafficSplit](https://github.com/deislabs/smi-spec/blob/master/traffic-split.md)">TrafficSplit</a> objects of SMI is handled by this action. <br>Pod: Percentage split not possible at request level in the absence of service mesh. Percentage input is used to calculate the replicas for baseline and canary as a percentage of replicas specified in the input manifests for the stable variant.</td>
7676
</tr>
77+
<tr>
78+
<td>traffic-split-annotations </br></br>(Optional)</td>
79+
<td>Annotations in the form of key/value pair to be added to TrafficSplit.</td>
7780
<tr>
7881
<td>percentage </br></br>(Optional but required if strategy is canary)</td>
7982
<td>Used to compute the number of replicas of &#39;-baseline&#39; and &#39;-canary&#39; variants of the workloads found in manifest files. For the specified percentage input, if (percentage * numberOfDesirerdReplicas)/100 is not a round number, the floor of this number is used while creating &#39;-baseline&#39; and &#39;-canary&#39;.<br/><br/>For example, if Deployment hello-world was found in the input manifest file with &#39;replicas: 4&#39; and if &#39;strategy: canary&#39; and &#39;percentage: 25&#39; are given as inputs to the action, then the Deployments hello-world-baseline and hello-world-canary are created with 1 replica each. The &#39;-baseline&#39; variant is created with the same image and tag as the stable version (4 replica variant prior to deployment) while the &#39;-canary&#39; variant is created with the image and tag corresponding to the new changes being deployed</td>

action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ inputs:
3535
description: 'Traffic split method to be used. Allowed values are pod and smi'
3636
required: false
3737
default: 'pod'
38+
traffic-split-annotations:
39+
description: 'Annotations in the form of key/value pair to be added to TrafficSplit. Relevant only if deployement strategy is blue-green or canary'
40+
required: false
3841
baseline-and-canary-replicas:
3942
description: 'Baseline and canary replicas count. Valid value between 0 to 100 (inclusive)'
4043
required: false

src/actions/deploy.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import {parseRouteStrategy} from '../types/routeStrategy'
1919
export async function deploy(
2020
kubectl: Kubectl,
2121
manifestFilePaths: string[],
22-
deploymentStrategy: DeploymentStrategy
22+
deploymentStrategy: DeploymentStrategy,
23+
annotations: {[key: string]: string} = {}
2324
) {
2425
// update manifests
2526
const inputManifestFiles: string[] = updateManifestFiles(manifestFilePaths)
@@ -34,7 +35,8 @@ export async function deploy(
3435
inputManifestFiles,
3536
deploymentStrategy,
3637
kubectl,
37-
trafficSplitMethod
38+
trafficSplitMethod,
39+
annotations
3840
)
3941
core.endGroup()
4042
core.debug('Deployed manifest files: ' + deployedManifestFiles)

src/actions/promote.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,15 @@ import {parseRouteStrategy, RouteStrategy} from '../types/routeStrategy'
4040
export async function promote(
4141
kubectl: Kubectl,
4242
manifests: string[],
43-
deploymentStrategy: DeploymentStrategy
43+
deploymentStrategy: DeploymentStrategy,
44+
annotations: {[key: string]: string} = {}
4445
) {
4546
switch (deploymentStrategy) {
4647
case DeploymentStrategy.CANARY:
4748
await promoteCanary(kubectl, manifests)
4849
break
4950
case DeploymentStrategy.BLUE_GREEN:
50-
await promoteBlueGreen(kubectl, manifests)
51+
await promoteBlueGreen(kubectl, manifests, annotations)
5152
break
5253
default:
5354
throw Error('Invalid promote deployment strategy')
@@ -104,7 +105,11 @@ async function promoteCanary(kubectl: Kubectl, manifests: string[]) {
104105
core.endGroup()
105106
}
106107

107-
async function promoteBlueGreen(kubectl: Kubectl, manifests: string[]) {
108+
async function promoteBlueGreen(
109+
kubectl: Kubectl,
110+
manifests: string[],
111+
annotations: {[key: string]: string} = {}
112+
) {
108113
// update container images and pull secrets
109114
const inputManifestFiles: string[] = updateManifestFiles(manifests)
110115
const manifestObjects: BlueGreenManifests =
@@ -157,7 +162,8 @@ async function promoteBlueGreen(kubectl: Kubectl, manifests: string[]) {
157162
await routeBlueGreenSMI(
158163
kubectl,
159164
NONE_LABEL_VALUE,
160-
manifestObjects.serviceEntityList
165+
manifestObjects.serviceEntityList,
166+
annotations
161167
)
162168
await deleteWorkloadsWithLabel(
163169
kubectl,

src/actions/reject.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ import {parseRouteStrategy, RouteStrategy} from '../types/routeStrategy'
1515
export async function reject(
1616
kubectl: Kubectl,
1717
manifests: string[],
18-
deploymentStrategy: DeploymentStrategy
18+
deploymentStrategy: DeploymentStrategy,
19+
annotations: {[key: string]: string} = {}
1920
) {
2021
switch (deploymentStrategy) {
2122
case DeploymentStrategy.CANARY:
2223
await rejectCanary(kubectl, manifests)
2324
break
2425
case DeploymentStrategy.BLUE_GREEN:
25-
await rejectBlueGreen(kubectl, manifests)
26+
await rejectBlueGreen(kubectl, manifests, annotations)
2627
break
2728
default:
2829
throw 'Invalid delete deployment strategy'
@@ -54,7 +55,11 @@ async function rejectCanary(kubectl: Kubectl, manifests: string[]) {
5455
core.endGroup()
5556
}
5657

57-
async function rejectBlueGreen(kubectl: Kubectl, manifests: string[]) {
58+
async function rejectBlueGreen(
59+
kubectl: Kubectl,
60+
manifests: string[],
61+
annotations: {[key: string]: string} = {}
62+
) {
5863
core.startGroup('Rejecting deployment with blue green strategy')
5964

6065
const routeStrategy = parseRouteStrategy(
@@ -63,7 +68,7 @@ async function rejectBlueGreen(kubectl: Kubectl, manifests: string[]) {
6368
if (routeStrategy == RouteStrategy.INGRESS) {
6469
await rejectBlueGreenIngress(kubectl, manifests)
6570
} else if (routeStrategy == RouteStrategy.SMI) {
66-
await rejectBlueGreenSMI(kubectl, manifests)
71+
await rejectBlueGreenSMI(kubectl, manifests, annotations)
6772
} else {
6873
await rejectBlueGreenService(kubectl, manifests)
6974
}

src/run.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {reject} from './actions/reject'
66
import {Action, parseAction} from './types/action'
77
import {parseDeploymentStrategy} from './types/deploymentStrategy'
88
import {getFilesFromDirectories} from './utilities/fileUtils'
9+
import {parseAnnotations} from './types/annotations'
910

1011
export async function run() {
1112
// verify kubeconfig is set
@@ -18,6 +19,9 @@ export async function run() {
1819
const action: Action | undefined = parseAction(
1920
core.getInput('action', {required: true})
2021
)
22+
const annotations = parseAnnotations(
23+
core.getInput('annotations', {required: false})
24+
)
2125
const strategy = parseDeploymentStrategy(core.getInput('strategy'))
2226
const manifestsInput = core.getInput('manifests', {required: true})
2327
const manifestFilePaths = manifestsInput
@@ -34,15 +38,15 @@ export async function run() {
3438
// run action
3539
switch (action) {
3640
case Action.DEPLOY: {
37-
await deploy(kubectl, fullManifestFilePaths, strategy)
41+
await deploy(kubectl, fullManifestFilePaths, strategy, annotations)
3842
break
3943
}
4044
case Action.PROMOTE: {
41-
await promote(kubectl, fullManifestFilePaths, strategy)
45+
await promote(kubectl, fullManifestFilePaths, strategy, annotations)
4246
break
4347
}
4448
case Action.REJECT: {
45-
await reject(kubectl, fullManifestFilePaths, strategy)
49+
await reject(kubectl, fullManifestFilePaths, strategy, annotations)
4650
break
4751
}
4852
default: {

src/strategyHelpers/blueGreen/blueGreenHelper.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ export interface BlueGreenManifests {
4040
export async function routeBlueGreen(
4141
kubectl: Kubectl,
4242
inputManifestFiles: string[],
43-
routeStrategy: RouteStrategy
43+
routeStrategy: RouteStrategy,
44+
annotations: {[key: string]: string} = {}
4445
) {
4546
// sleep for buffer time
4647
const bufferTime: number = parseInt(
@@ -74,7 +75,8 @@ export async function routeBlueGreen(
7475
await routeBlueGreenSMI(
7576
kubectl,
7677
GREEN_LABEL_VALUE,
77-
manifestObjects.serviceEntityList
78+
manifestObjects.serviceEntityList,
79+
annotations
7880
)
7981
} else {
8082
await routeBlueGreenService(

src/strategyHelpers/blueGreen/smiBlueGreenHelper.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ const MAX_VAL = 100
2323

2424
export async function deployBlueGreenSMI(
2525
kubectl: Kubectl,
26-
filePaths: string[]
26+
filePaths: string[],
27+
annotations: {[key: string]: string} = {}
2728
) {
2829
// get all kubernetes objects defined in manifest files
2930
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths)
@@ -37,7 +38,7 @@ export async function deployBlueGreenSMI(
3738
await kubectl.apply(manifestFiles)
3839

3940
// make extraservices and trafficsplit
40-
await setupSMI(kubectl, manifestObjects.serviceEntityList)
41+
await setupSMI(kubectl, manifestObjects.serviceEntityList, annotations)
4142

4243
// create new deloyments
4344
return await createWorkloadsWithLabel(
@@ -68,16 +69,18 @@ export async function promoteBlueGreenSMI(kubectl: Kubectl, manifestObjects) {
6869

6970
export async function rejectBlueGreenSMI(
7071
kubectl: Kubectl,
71-
filePaths: string[]
72+
filePaths: string[],
73+
annotations: {[key: string]: string} = {}
7274
) {
7375
// get all kubernetes objects defined in manifest files
7476
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths)
7577

76-
// route trafficsplit to stable deploymetns
78+
// route trafficsplit to stable deployments
7779
await routeBlueGreenSMI(
7880
kubectl,
7981
NONE_LABEL_VALUE,
80-
manifestObjects.serviceEntityList
82+
manifestObjects.serviceEntityList,
83+
annotations
8184
)
8285

8386
// delete rejected new bluegreen deployments
@@ -91,7 +94,11 @@ export async function rejectBlueGreenSMI(
9194
await cleanupSMI(kubectl, manifestObjects.serviceEntityList)
9295
}
9396

94-
export async function setupSMI(kubectl: Kubectl, serviceEntityList: any[]) {
97+
export async function setupSMI(
98+
kubectl: Kubectl,
99+
serviceEntityList: any[],
100+
annotations: {[key: string]: string} = {}
101+
) {
95102
const newObjectsList = []
96103
const trafficObjectList = []
97104

@@ -117,7 +124,8 @@ export async function setupSMI(kubectl: Kubectl, serviceEntityList: any[]) {
117124
createTrafficSplitObject(
118125
kubectl,
119126
inputObject.metadata.name,
120-
NONE_LABEL_VALUE
127+
NONE_LABEL_VALUE,
128+
annotations
121129
)
122130
})
123131
}
@@ -127,7 +135,8 @@ let trafficSplitAPIVersion = ''
127135
async function createTrafficSplitObject(
128136
kubectl: Kubectl,
129137
name: string,
130-
nextLabel: string
138+
nextLabel: string,
139+
annotations: {[key: string]: string} = {}
131140
): Promise<any> {
132141
// cache traffic split api version
133142
if (!trafficSplitAPIVersion)
@@ -145,7 +154,8 @@ async function createTrafficSplitObject(
145154
apiVersion: trafficSplitAPIVersion,
146155
kind: 'TrafficSplit',
147156
metadata: {
148-
name: getBlueGreenResourceName(name, TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX)
157+
name: getBlueGreenResourceName(name, TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX),
158+
annotations: annotations
149159
},
150160
spec: {
151161
service: name,
@@ -194,14 +204,16 @@ export function getSMIServiceResource(
194204
export async function routeBlueGreenSMI(
195205
kubectl: Kubectl,
196206
nextLabel: string,
197-
serviceEntityList: any[]
207+
serviceEntityList: any[],
208+
annotations: {[key: string]: string} = {}
198209
) {
199210
for (const serviceObject of serviceEntityList) {
200211
// route trafficsplit to given label
201212
await createTrafficSplitObject(
202213
kubectl,
203214
serviceObject.metadata.name,
204-
nextLabel
215+
nextLabel,
216+
annotations
205217
)
206218
}
207219
}

src/strategyHelpers/canary/smiCanaryHelper.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,8 @@ async function getTrafficSplitObject(
288288
name: string,
289289
stableWeight: number,
290290
baselineWeight: number,
291-
canaryWeight: number
291+
canaryWeight: number,
292+
annotations: {[key: string]: string} = {}
292293
): Promise<string> {
293294
// cached version
294295
if (!trafficSplitAPIVersion) {
@@ -301,7 +302,8 @@ async function getTrafficSplitObject(
301302
apiVersion: trafficSplitAPIVersion,
302303
kind: 'TrafficSplit',
303304
metadata: {
304-
name: getTrafficSplitResourceName(name)
305+
name: getTrafficSplitResourceName(name),
306+
annotations: annotations
305307
},
306308
spec: {
307309
backends: [

src/strategyHelpers/deploymentHelper.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ export async function deployManifests(
4141
files: string[],
4242
deploymentStrategy: DeploymentStrategy,
4343
kubectl: Kubectl,
44-
trafficSplitMethod: TrafficSplitMethod
44+
trafficSplitMethod: TrafficSplitMethod,
45+
annotations: {[key: string]: string} = {}
4546
): Promise<string[]> {
4647
switch (deploymentStrategy) {
4748
case DeploymentStrategy.CANARY: {
@@ -63,7 +64,7 @@ export async function deployManifests(
6364
(routeStrategy == RouteStrategy.INGRESS &&
6465
deployBlueGreenIngress(kubectl, files)) ||
6566
(routeStrategy == RouteStrategy.SMI &&
66-
deployBlueGreenSMI(kubectl, files)) ||
67+
deployBlueGreenSMI(kubectl, files, annotations)) ||
6768
deployBlueGreenService(kubectl, files)
6869
)
6970

0 commit comments

Comments
 (0)