import * as core from '@actions/core' import * as deploy from './deploy' import * as canaryDeploymentHelper from '../strategyHelpers/canary/canaryHelper' import * as SMICanaryDeploymentHelper from '../strategyHelpers/canary/smiCanaryHelper' import { getResources, updateManifestFiles } from '../utilities/manifestUpdateUtils' import * as models from '../types/kubernetesTypes' import * as KubernetesManifestUtility from '../utilities/manifestStabilityUtils' import { BlueGreenManifests, deleteWorkloadsAndServicesWithLabel, deleteWorkloadsWithLabel, getManifestObjects, GREEN_LABEL_VALUE, NONE_LABEL_VALUE } from '../strategyHelpers/blueGreen/blueGreenHelper' import { promoteBlueGreenService, routeBlueGreenService } from '../strategyHelpers/blueGreen/serviceBlueGreenHelper' import { promoteBlueGreenIngress, routeBlueGreenIngress } from '../strategyHelpers/blueGreen/ingressBlueGreenHelper' import { cleanupSMI, promoteBlueGreenSMI, routeBlueGreenSMI } from '../strategyHelpers/blueGreen/smiBlueGreenHelper' import {Kubectl, Resource} from '../types/kubectl' import {DeploymentStrategy} from '../types/deploymentStrategy' import { parseTrafficSplitMethod, TrafficSplitMethod } from '../types/trafficSplitMethod' import {parseRouteStrategy, RouteStrategy} from '../types/routeStrategy' export async function promote( kubectl: Kubectl, manifests: string[], deploymentStrategy: DeploymentStrategy ) { switch (deploymentStrategy) { case DeploymentStrategy.CANARY: await promoteCanary(kubectl, manifests) break case DeploymentStrategy.BLUE_GREEN: await promoteBlueGreen(kubectl, manifests) break default: throw Error('Invalid promote deployment strategy') } } async function promoteCanary(kubectl: Kubectl, manifests: string[]) { let includeServices = false const trafficSplitMethod = parseTrafficSplitMethod( core.getInput('traffic-split-method', {required: true}) ) if (trafficSplitMethod == TrafficSplitMethod.SMI) { includeServices = true // In case of SMI traffic split strategy when deployment is promoted, first we will redirect traffic to // canary deployment, then update stable deployment and then redirect traffic to stable deployment core.info('Redirecting traffic to canary deployment') await SMICanaryDeploymentHelper.redirectTrafficToCanaryDeployment( kubectl, manifests ) core.info('Deploying input manifests with SMI canary strategy') await deploy.deploy(kubectl, manifests, DeploymentStrategy.CANARY) core.info('Redirecting traffic to stable deployment') await SMICanaryDeploymentHelper.redirectTrafficToStableDeployment( kubectl, manifests ) } else { core.info('Deploying input manifests') await deploy.deploy(kubectl, manifests, DeploymentStrategy.CANARY) } core.info('Deleting canary and baseline workloads') try { await canaryDeploymentHelper.deleteCanaryDeployment( kubectl, manifests, includeServices ) } catch (ex) { core.warning( 'Exception occurred while deleting canary and baseline workloads: ' + ex ) } } async function promoteBlueGreen(kubectl: Kubectl, manifests: string[]) { // update container images and pull secrets const inputManifestFiles: string[] = updateManifestFiles(manifests) const manifestObjects: BlueGreenManifests = getManifestObjects(inputManifestFiles) const routeStrategy = parseRouteStrategy( core.getInput('route-method', {required: true}) ) core.info('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) } // checking stability of newly created deployments core.info('Checking manifest stability') const deployedManifestFiles = result.newFilePaths const resources: Resource[] = getResources( deployedManifestFiles, models.DEPLOYMENT_TYPES.concat([ models.DiscoveryAndLoadBalancerResource.SERVICE ]) ) await KubernetesManifestUtility.checkManifestStability(kubectl, resources) core.info( 'Routing to new deployments and deleting old workloads and services' ) if (routeStrategy == RouteStrategy.INGRESS) { await routeBlueGreenIngress( kubectl, null, manifestObjects.serviceNameMap, manifestObjects.ingressEntityList ) await deleteWorkloadsAndServicesWithLabel( kubectl, GREEN_LABEL_VALUE, manifestObjects.deploymentEntityList, manifestObjects.serviceEntityList ) } else if (routeStrategy == RouteStrategy.SMI) { await routeBlueGreenSMI( kubectl, NONE_LABEL_VALUE, manifestObjects.serviceEntityList ) await deleteWorkloadsWithLabel( kubectl, GREEN_LABEL_VALUE, manifestObjects.deploymentEntityList ) await cleanupSMI(kubectl, manifestObjects.serviceEntityList) } else { await routeBlueGreenService( kubectl, NONE_LABEL_VALUE, manifestObjects.serviceEntityList ) await deleteWorkloadsWithLabel( kubectl, GREEN_LABEL_VALUE, manifestObjects.deploymentEntityList ) } }