@atomist/sdm
Version:
Atomist Software Delivery Machine SDK
189 lines • 8.6 kB
JavaScript
;
/*
* 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