Compare commits

..

1 Commits

Author SHA1 Message Date
Oliver King ebc294c887 add clean function 2022-07-06 16:07:01 -04:00
12 changed files with 31 additions and 84 deletions
-3
View File
@@ -74,9 +74,6 @@ Following are the key capabilities of this action:
<td>traffic-split-method </br></br>(Optional)</td>
<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>
</tr>
<tr>
<td>traffic-split-annotations </br></br>(Optional)</td>
<td>Annotations in the form of key/value pair to be added to TrafficSplit.</td>
<tr>
<td>percentage </br></br>(Optional but required if strategy is canary)</td>
<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>
-3
View File
@@ -35,9 +35,6 @@ inputs:
description: 'Traffic split method to be used. Allowed values are pod and smi'
required: false
default: 'pod'
traffic-split-annotations:
description: 'Annotations in the form of key/value pair to be added to TrafficSplit. Relevant only if deployement strategy is blue-green or canary'
required: false
baseline-and-canary-replicas:
description: 'Baseline and canary replicas count. Valid value between 0 to 100 (inclusive)'
required: false
+2 -4
View File
@@ -19,8 +19,7 @@ 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)
@@ -35,8 +34,7 @@ export async function deploy(
inputManifestFiles,
deploymentStrategy,
kubectl,
trafficSplitMethod,
annotations
trafficSplitMethod
)
core.endGroup()
core.debug('Deployed manifest files: ' + deployedManifestFiles)
+4 -10
View File
@@ -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')
@@ -105,11 +104,7 @@ async function promoteCanary(kubectl: Kubectl, manifests: string[]) {
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 =
@@ -162,8 +157,7 @@ async function promoteBlueGreen(
await routeBlueGreenSMI(
kubectl,
NONE_LABEL_VALUE,
manifestObjects.serviceEntityList,
annotations
manifestObjects.serviceEntityList
)
await deleteWorkloadsWithLabel(
kubectl,
+4 -9
View File
@@ -15,15 +15,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'
@@ -55,11 +54,7 @@ async function rejectCanary(kubectl: Kubectl, manifests: string[]) {
core.endGroup()
}
async function rejectBlueGreen(
kubectl: Kubectl,
manifests: string[],
annotations: {[key: string]: string} = {}
) {
async function rejectBlueGreen(kubectl: Kubectl, manifests: string[]) {
core.startGroup('Rejecting deployment with blue green strategy')
const routeStrategy = parseRouteStrategy(
@@ -68,7 +63,7 @@ async function rejectBlueGreen(
if (routeStrategy == RouteStrategy.INGRESS) {
await rejectBlueGreenIngress(kubectl, manifests)
} else if (routeStrategy == RouteStrategy.SMI) {
await rejectBlueGreenSMI(kubectl, manifests, annotations)
await rejectBlueGreenSMI(kubectl, manifests)
} else {
await rejectBlueGreenService(kubectl, manifests)
}
+3 -7
View File
@@ -6,7 +6,6 @@ import {reject} from './actions/reject'
import {Action, parseAction} from './types/action'
import {parseDeploymentStrategy} from './types/deploymentStrategy'
import {getFilesFromDirectories} from './utilities/fileUtils'
import {parseAnnotations} from './types/annotations'
export async function run() {
// verify kubeconfig is set
@@ -19,9 +18,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
@@ -38,15 +34,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: {
@@ -40,8 +40,7 @@ export interface BlueGreenManifests {
export async function routeBlueGreen(
kubectl: Kubectl,
inputManifestFiles: string[],
routeStrategy: RouteStrategy,
annotations: {[key: string]: string} = {}
routeStrategy: RouteStrategy
) {
// sleep for buffer time
const bufferTime: number = parseInt(
@@ -75,8 +74,7 @@ export async function routeBlueGreen(
await routeBlueGreenSMI(
kubectl,
GREEN_LABEL_VALUE,
manifestObjects.serviceEntityList,
annotations
manifestObjects.serviceEntityList
)
} else {
await routeBlueGreenService(
@@ -23,8 +23,7 @@ const MAX_VAL = 100
export async function deployBlueGreenSMI(
kubectl: Kubectl,
filePaths: string[],
annotations: {[key: string]: string} = {}
filePaths: string[]
) {
// get all kubernetes objects defined in manifest files
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths)
@@ -38,7 +37,7 @@ export async function deployBlueGreenSMI(
await kubectl.apply(manifestFiles)
// make extraservices and trafficsplit
await setupSMI(kubectl, manifestObjects.serviceEntityList, annotations)
await setupSMI(kubectl, manifestObjects.serviceEntityList)
// create new deloyments
return await createWorkloadsWithLabel(
@@ -69,18 +68,16 @@ export async function promoteBlueGreenSMI(kubectl: Kubectl, manifestObjects) {
export async function rejectBlueGreenSMI(
kubectl: Kubectl,
filePaths: string[],
annotations: {[key: string]: string} = {}
filePaths: string[]
) {
// get all kubernetes objects defined in manifest files
const manifestObjects: BlueGreenManifests = getManifestObjects(filePaths)
// route trafficsplit to stable deployments
// route trafficsplit to stable deploymetns
await routeBlueGreenSMI(
kubectl,
NONE_LABEL_VALUE,
manifestObjects.serviceEntityList,
annotations
manifestObjects.serviceEntityList
)
// delete rejected new bluegreen deployments
@@ -94,11 +91,7 @@ export async function rejectBlueGreenSMI(
await cleanupSMI(kubectl, manifestObjects.serviceEntityList)
}
export async function setupSMI(
kubectl: Kubectl,
serviceEntityList: any[],
annotations: {[key: string]: string} = {}
) {
export async function setupSMI(kubectl: Kubectl, serviceEntityList: any[]) {
const newObjectsList = []
const trafficObjectList = []
@@ -124,8 +117,7 @@ export async function setupSMI(
createTrafficSplitObject(
kubectl,
inputObject.metadata.name,
NONE_LABEL_VALUE,
annotations
NONE_LABEL_VALUE
)
})
}
@@ -135,8 +127,7 @@ let trafficSplitAPIVersion = ''
async function createTrafficSplitObject(
kubectl: Kubectl,
name: string,
nextLabel: string,
annotations: {[key: string]: string} = {}
nextLabel: string
): Promise<any> {
// cache traffic split api version
if (!trafficSplitAPIVersion)
@@ -154,8 +145,7 @@ async function createTrafficSplitObject(
apiVersion: trafficSplitAPIVersion,
kind: 'TrafficSplit',
metadata: {
name: getBlueGreenResourceName(name, TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX),
annotations: annotations
name: getBlueGreenResourceName(name, TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX)
},
spec: {
service: name,
@@ -204,16 +194,14 @@ export function getSMIServiceResource(
export async function routeBlueGreenSMI(
kubectl: Kubectl,
nextLabel: string,
serviceEntityList: any[],
annotations: {[key: string]: string} = {}
serviceEntityList: any[]
) {
for (const serviceObject of serviceEntityList) {
// route trafficsplit to given label
await createTrafficSplitObject(
kubectl,
serviceObject.metadata.name,
nextLabel,
annotations
nextLabel
)
}
}
@@ -288,8 +288,7 @@ async function getTrafficSplitObject(
name: string,
stableWeight: number,
baselineWeight: number,
canaryWeight: number,
annotations: {[key: string]: string} = {}
canaryWeight: number
): Promise<string> {
// cached version
if (!trafficSplitAPIVersion) {
@@ -302,8 +301,7 @@ async function getTrafficSplitObject(
apiVersion: trafficSplitAPIVersion,
kind: 'TrafficSplit',
metadata: {
name: getTrafficSplitResourceName(name),
annotations: annotations
name: getTrafficSplitResourceName(name)
},
spec: {
backends: [
+2 -3
View File
@@ -41,8 +41,7 @@ export async function deployManifests(
files: string[],
deploymentStrategy: DeploymentStrategy,
kubectl: Kubectl,
trafficSplitMethod: TrafficSplitMethod,
annotations: {[key: string]: string} = {}
trafficSplitMethod: TrafficSplitMethod
): Promise<string[]> {
switch (deploymentStrategy) {
case DeploymentStrategy.CANARY: {
@@ -64,7 +63,7 @@ export async function deployManifests(
(routeStrategy == RouteStrategy.INGRESS &&
deployBlueGreenIngress(kubectl, files)) ||
(routeStrategy == RouteStrategy.SMI &&
deployBlueGreenSMI(kubectl, files, annotations)) ||
deployBlueGreenSMI(kubectl, files)) ||
deployBlueGreenService(kubectl, files)
)
-8
View File
@@ -1,8 +0,0 @@
export function parseAnnotations(str: string) {
if (str == '') {
return {}
} else {
const annotaion = JSON.parse(str)
return new Map(annotaion)
}
}
+1 -6
View File
@@ -23,12 +23,7 @@ export async function getDeploymentConfig(): Promise<DeploymentConfig> {
)
}
let imageNames = core.getInput('images').split('\n') || []
imageNames.forEach((element) => {
if (element === null || '/^s+$/') {
imageNames.pop()
}
})
const imageNames = core.getInput('images').split('\n') || []
const imageDockerfilePathMap: {[id: string]: string} = {}
const pullImages = !(core.getInput('pull-images').toLowerCase() === 'false')