UNPKG

@atomist/sdm

Version:

Atomist Software Delivery Machine SDK

189 lines 8.6 kB
"use strict"; /* * Copyright © 2020 Atomist, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.initiateKubernetesDeploy = exports.defaultDataSources = exports.KubernetesDeploy = exports.KubernetesDeployDataSources = exports.goalEventSlug = void 0; const _ = require("lodash"); const GoalNameGenerator_1 = require("../../../api/goal/GoalNameGenerator"); const GoalWithFulfillment_1 = require("../../../api/goal/GoalWithFulfillment"); const commonPushTests_1 = require("../../../api/mapping/support/commonPushTests"); const modes_1 = require("../../../core/machine/modes"); const types_1 = require("../../../typings/types"); const cluster_1 = require("./cluster"); const data_1 = require("./data"); const deploy_1 = require("./deploy"); /** Return repository slug for SDM goal event. */ function goalEventSlug(goalEvent) { return `${goalEvent.repo.owner}/${goalEvent.repo.name}`; } exports.goalEventSlug = goalEventSlug; /** * Sources of information for Kubernetes goal application data. */ var KubernetesDeployDataSources; (function (KubernetesDeployDataSources) { /** Read deployment spec from `.atomist/kubernetes`. */ KubernetesDeployDataSources["DeploymentSpec"] = "DeploymentSpec"; /** Read EXPOSE from Dockerfile to get service port. */ KubernetesDeployDataSources["Dockerfile"] = "Dockerfile"; /** Parse `goalEvent.data` as JSON. */ KubernetesDeployDataSources["GoalEvent"] = "GoalEvent"; /** Read ingress spec from `.atomist/kubernetes`. */ KubernetesDeployDataSources["IngressSpec"] = "IngressSpec"; /** Read role-binding spec from `.atomist/kubernetes`. */ KubernetesDeployDataSources["RoleBindingSpec"] = "RoleBindingSpec"; /** Read role spec from `.atomist/kubernetes`. */ KubernetesDeployDataSources["RoleSpec"] = "RoleSpec"; /** Load `sdm.configuration.sdm.k8s.app`. */ KubernetesDeployDataSources["SdmConfiguration"] = "SdmConfiguration"; /** Read service-account spec from `.atomist/kubernetes`. */ KubernetesDeployDataSources["ServiceAccountSpec"] = "ServiceAccountSpec"; /** Read service spec from `.atomist/kubernetes`. */ KubernetesDeployDataSources["ServiceSpec"] = "ServiceSpec"; })(KubernetesDeployDataSources = exports.KubernetesDeployDataSources || (exports.KubernetesDeployDataSources = {})); /** * Goal that initiates deploying an application to a Kubernetes * cluster. Deploying the application is completed by the * [[kubernetesDeployHandler]] event handler. By default, this goal * will be configured such that it is fulfilled by the SDM that * creates it. To have this goal be executed by another SDM, set the * fulfillment name to the name of that SDM: * * const deploy = new KubernetesDeploy() * .with({ name: otherSdm.configuration.name }); * */ class KubernetesDeploy extends GoalWithFulfillment_1.FulfillableGoalWithRegistrations { /** * Create a KubernetesDeploy object. * * @param details Define unique aspects of this Kubernetes deployment, see [[KubernetesDeploy.details]]. * @param dependsOn Other goals that must complete successfully before scheduling this goal. */ constructor(details = {}, ...dependsOn) { super(GoalWithFulfillment_1.getGoalDefinitionFrom(details, GoalNameGenerator_1.DefaultGoalNameGenerator.generateName("kubernetes-deploy")), ...dependsOn); this.details = details; } /** * Register a deployment with the initiator fulfillment. */ with(registration) { const fulfillment = registration.name || this.sdm.configuration.name; this.addFulfillment({ name: fulfillment, goalExecutor: initiateKubernetesDeploy(this, registration), pushTest: registration.pushTest, }); this.updateGoalName(fulfillment); return this; } /** * Called by the SDM on initialization. This function calls * `super.register` and adds a startup listener to the SDM. * * The startup listener registers a default goal fulfillment that * adds itself as fulfiller of its deployment requests if this * goal has no fulfillments or callbacks at startup. */ register(sdm) { super.register(sdm); sdm.addStartupListener(async () => { if (this.fulfillments.length === 0 && this.callbacks.length === 0) { this.with({ pushTest: commonPushTests_1.AnyPush }); } }); } /** * Set the goal "name" and goal definition "displayName". If any * goal definition description is not set, populate it with a * reasonable default. * * @param fulfillment Name of fulfillment, typically the cluster-scoped name of k8s-sdm * @return object */ updateGoalName(fulfillment) { const env = (this.details && this.details.environment) ? this.details.environment : this.environment; const clusterLabel = cluster_1.getClusterLabel(env, fulfillment); const displayName = this.definition.displayName || "deploy"; const goalName = `${displayName}${clusterLabel}`; this.definition.displayName = goalName; const defaultDefinitions = { canceledDescription: `Canceled: ${goalName}`, completedDescription: `Deployed${clusterLabel}`, failedDescription: `Deployment${clusterLabel} failed`, plannedDescription: `Planned: ${goalName}`, requestedDescription: `Requested: ${goalName}`, skippedDescription: `Skipped: ${goalName}`, stoppedDescription: `Stopped: ${goalName}`, waitingForApprovalDescription: `Successfully deployed${clusterLabel}`, waitingForPreApprovalDescription: `Deploy${clusterLabel} pending approval`, workingDescription: `Deploying${clusterLabel}`, }; _.defaultsDeep(this.definition, defaultDefinitions); return this; } } exports.KubernetesDeploy = KubernetesDeploy; /** * Populate data sources properrty of registration with all possible * KubernetesGoalDataSources if it is not defined. Otherwise, leave * it as is. The registration object is modified directly and * returned. * * @param registration Kubernetes deploy object registration * @return registration with data sources */ function defaultDataSources(registration) { if (!registration.dataSources) { registration.dataSources = Object.values(KubernetesDeployDataSources); } return registration; } exports.defaultDataSources = defaultDataSources; /** * If in SDM team mode, this goal executor generates and stores the * Kubernetes application data for deploying an application to * Kubernetes. It returns the augmented SdmGoalEvent with the * Kubernetes application information in the `data` property and the * state of the SdmGoalEvent set to "requested". The actual * deployment is done by the [[kubernetesDeployHandler]] event * handler. * * It will call [[defaultDataSources]] to populate the default * repository data sources if none are provided in the registration. * * If in SDM local mode, generate the Kubernetes application data and * deploy the application. * * @param k8Deploy Kubernetes deploy object * @param registration Kubernetes deploy object registration * @return An ExecuteGoal result that is not really a result, but an intermediate state. */ function initiateKubernetesDeploy(k8Deploy, registration) { return async (goalInvocation) => { defaultDataSources(registration); const goalEvent = await data_1.generateKubernetesGoalEventData(k8Deploy, registration, goalInvocation); if (modes_1.isInLocalMode()) { return deploy_1.deployApplication(goalEvent, goalInvocation.context, goalInvocation.progressLog); } else { goalEvent.state = types_1.SdmGoalState.requested; return goalEvent; } }; } exports.initiateKubernetesDeploy = initiateKubernetesDeploy; //# sourceMappingURL=goal.js.map