Traffic split - canary deployment

This commit is contained in:
Vidya Reddy 2022-07-20 12:34:31 +05:30
parent 634370ab70
commit 534896c172
7 changed files with 43 additions and 22 deletions

View File

@ -38,7 +38,6 @@ inputs:
traffic-split-annotations: traffic-split-annotations:
description: 'Traffic split annotations in the form of key/value pair can be used' description: 'Traffic split annotations in the form of key/value pair can be used'
required: false required: false
default: 0
baseline-and-canary-replicas: baseline-and-canary-replicas:
description: 'Baseline and canary replicas count. Valid value between 0 to 100 (inclusive)' description: 'Baseline and canary replicas count. Valid value between 0 to 100 (inclusive)'
required: false required: false

View File

@ -19,7 +19,8 @@ import {parseRouteStrategy} from '../types/routeStrategy'
export async function deploy( export async function deploy(
kubectl: Kubectl, kubectl: Kubectl,
manifestFilePaths: string[], manifestFilePaths: string[],
deploymentStrategy: DeploymentStrategy deploymentStrategy: DeploymentStrategy,
annotations: {[key: string]: string} = {}
) { ) {
// update manifests // update manifests
const inputManifestFiles: string[] = updateManifestFiles(manifestFilePaths) const inputManifestFiles: string[] = updateManifestFiles(manifestFilePaths)
@ -34,7 +35,8 @@ export async function deploy(
inputManifestFiles, inputManifestFiles,
deploymentStrategy, deploymentStrategy,
kubectl, kubectl,
trafficSplitMethod trafficSplitMethod,
annotations
) )
core.endGroup() core.endGroup()
core.debug('Deployed manifest files: ' + deployedManifestFiles) core.debug('Deployed manifest files: ' + deployedManifestFiles)
@ -55,7 +57,7 @@ export async function deploy(
const routeStrategy = parseRouteStrategy( const routeStrategy = parseRouteStrategy(
core.getInput('route-method', {required: true}) core.getInput('route-method', {required: true})
) )
await routeBlueGreen(kubectl, inputManifestFiles, routeStrategy) await routeBlueGreen(kubectl, inputManifestFiles, routeStrategy) //----
core.endGroup() core.endGroup()
} }

View File

@ -6,6 +6,7 @@ import {reject} from './actions/reject'
import {Action, parseAction} from './types/action' import {Action, parseAction} from './types/action'
import {parseDeploymentStrategy} from './types/deploymentStrategy' import {parseDeploymentStrategy} from './types/deploymentStrategy'
import {getFilesFromDirectories} from './utilities/fileUtils' import {getFilesFromDirectories} from './utilities/fileUtils'
import {stringify} from 'querystring'
export async function run() { export async function run() {
// verify kubeconfig is set // verify kubeconfig is set
@ -18,7 +19,8 @@ export async function run() {
const action: Action | undefined = parseAction( const action: Action | undefined = parseAction(
core.getInput('action', {required: true}) core.getInput('action', {required: true})
) )
const annotations: {[key: string]: string} = {} const annotation: {[key: string]: string} = {}
const annotations = core.getInput(stringify(annotation), {required: true})
const strategy = parseDeploymentStrategy(core.getInput('strategy')) const strategy = parseDeploymentStrategy(core.getInput('strategy'))
const manifestsInput = core.getInput('manifests', {required: true}) const manifestsInput = core.getInput('manifests', {required: true})
const manifestFilePaths = manifestsInput const manifestFilePaths = manifestsInput
@ -35,15 +37,30 @@ export async function run() {
// run action // run action
switch (action) { switch (action) {
case Action.DEPLOY: { case Action.DEPLOY: {
await deploy(kubectl, fullManifestFilePaths, strategy) await deploy(
kubectl,
fullManifestFilePaths,
strategy,
JSON.parse(annotations)
)
break break
} }
case Action.PROMOTE: { case Action.PROMOTE: {
await promote(kubectl, fullManifestFilePaths, strategy, annotations) await promote(
kubectl,
fullManifestFilePaths,
strategy,
JSON.parse(annotations)
)
break break
} }
case Action.REJECT: { case Action.REJECT: {
await reject(kubectl, fullManifestFilePaths, strategy, annotations) await reject(
kubectl,
fullManifestFilePaths,
strategy,
JSON.parse(annotations)
)
break break
} }
default: { default: {

View File

@ -23,7 +23,8 @@ const MAX_VAL = 100
export async function deployBlueGreenSMI( export async function deployBlueGreenSMI(
kubectl: Kubectl, kubectl: Kubectl,
filePaths: string[] filePaths: string[],
annotations: {[key: string]: string} = {}
) { ) {
// get all kubernetes objects defined in manifest files // get all kubernetes objects defined in manifest files
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths) const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths)
@ -37,7 +38,7 @@ export async function deployBlueGreenSMI(
await kubectl.apply(manifestFiles) await kubectl.apply(manifestFiles)
// make extraservices and trafficsplit // make extraservices and trafficsplit
await setupSMI(kubectl, manifestObjects.serviceEntityList) await setupSMI(kubectl, manifestObjects.serviceEntityList, annotations)
// create new deloyments // create new deloyments
return await createWorkloadsWithLabel( return await createWorkloadsWithLabel(
@ -93,7 +94,11 @@ export async function rejectBlueGreenSMI(
await cleanupSMI(kubectl, manifestObjects.serviceEntityList) await cleanupSMI(kubectl, manifestObjects.serviceEntityList)
} }
export async function setupSMI(kubectl: Kubectl, serviceEntityList: any[]) { export async function setupSMI(
kubectl: Kubectl,
serviceEntityList: any[],
annotaions: {[key: string]: string} = {}
) {
const newObjectsList = [] const newObjectsList = []
const trafficObjectList = [] const trafficObjectList = []
@ -119,7 +124,8 @@ export async function setupSMI(kubectl: Kubectl, serviceEntityList: any[]) {
createTrafficSplitObject( createTrafficSplitObject(
kubectl, kubectl,
inputObject.metadata.name, inputObject.metadata.name,
NONE_LABEL_VALUE NONE_LABEL_VALUE,
annotaions
) )
}) })
} }

View File

@ -41,7 +41,8 @@ export async function deployManifests(
files: string[], files: string[],
deploymentStrategy: DeploymentStrategy, deploymentStrategy: DeploymentStrategy,
kubectl: Kubectl, kubectl: Kubectl,
trafficSplitMethod: TrafficSplitMethod trafficSplitMethod: TrafficSplitMethod,
annotaions: {[key: string]: string} = {}
): Promise<string[]> { ): Promise<string[]> {
switch (deploymentStrategy) { switch (deploymentStrategy) {
case DeploymentStrategy.CANARY: { case DeploymentStrategy.CANARY: {
@ -63,7 +64,7 @@ export async function deployManifests(
(routeStrategy == RouteStrategy.INGRESS && (routeStrategy == RouteStrategy.INGRESS &&
deployBlueGreenIngress(kubectl, files)) || deployBlueGreenIngress(kubectl, files)) ||
(routeStrategy == RouteStrategy.SMI && (routeStrategy == RouteStrategy.SMI &&
deployBlueGreenSMI(kubectl, files)) || deployBlueGreenSMI(kubectl, files, annotaions)) ||
deployBlueGreenService(kubectl, files) deployBlueGreenService(kubectl, files)
) )

View File

@ -289,15 +289,12 @@ describe('Kubectl class', () => {
it('gets resource', async () => { it('gets resource', async () => {
const resourceType = 'type' const resourceType = 'type'
const name = 'name' const name = 'name'
const annotations: {[key: string]: string} = {} expect(await kubectl.getResource(resourceType, name)).toBe(execReturn)
expect(
await kubectl.getResource(resourceType, name, annotations)
).toBe(execReturn)
expect(exec.getExecOutput).toBeCalledWith( expect(exec.getExecOutput).toBeCalledWith(
kubectlPath, kubectlPath,
[ [
'get', 'get',
`${resourceType}/${name}/${annotations}`, `${resourceType}/${name}`,
'-o', '-o',
'json', 'json',
'--namespace', '--namespace',

View File

@ -135,12 +135,11 @@ export class Kubectl {
public async getResource( public async getResource(
resourceType: string, resourceType: string,
name: string, name: string
annotations: {[key: string]: string} = {}
): Promise<ExecOutput> { ): Promise<ExecOutput> {
return await this.execute([ return await this.execute([
'get', 'get',
`${resourceType}/${name}/${annotations}`, `${resourceType}/${name}`,
'-o', '-o',
'json' 'json'
]) ])