UNPKG

@atomist/sdm

Version:

Atomist Software Delivery Machine SDK

130 lines (124 loc) 5.43 kB
/* * 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. */ import { Parameter, Parameters } from "@atomist/automation-client/lib/decorators"; import { HandlerResult } from "@atomist/automation-client/lib/HandlerResult"; import { logger } from "@atomist/automation-client/lib/util/logger"; import * as _ from "lodash"; import { slackSuccessMessage } from "../../../api-helper/misc/slack/messages"; import { CommandListenerInvocation } from "../../../api/listener/CommandListener"; import { SoftwareDeliveryMachine } from "../../../api/machine/SoftwareDeliveryMachine"; import { CommandHandlerRegistration } from "../../../api/registration/CommandHandlerRegistration"; import { deleteApplication } from "../kubernetes/application"; import { cleanName } from "../support/name"; import { K8sDefaultNamespace } from "../support/namespace"; import { syncApplication } from "../sync/application"; @Parameters() export class KubernetesUndeployParameters { @Parameter({ displayName: "Name", description: "name of resources to remove", pattern: /^[a-z](?:[-a-z0-9]*[a-z0-9])?$/, validInput: "a valid Kubernetes resource name, beginning with a lowercase letter, ending with a lowercase" + "letter or number, and containing only lowercase letters, numbers, and dashes (-)", minLength: 1, maxLength: 63, required: true, }) public name: string; @Parameter({ displayName: "Namespace", description: "namespace of resources to remove", pattern: /^[a-z](?:[-a-z0-9]*[a-z0-9])?$/, validInput: "a valid Kubernetes namespace, beginning with a lowercase letter, ending with a lowercase" + "letter or number, and containing only lowercase letters, numbers, and dashes (-)", minLength: 1, maxLength: 63, required: false, }) public ns: string = K8sDefaultNamespace; } /** * Safely remove all resources related to a Kubernetes application. * * If the SDM configuration says this packs commands should be added, * i.e., `sdm.configuration.sdm.k8s.options.addCommands` is `true`, * the command will have the intent `kube undeploy SDM_NAME`. * Otherwise the command will be registered without an intent. */ export function kubernetesUndeploy(sdm: SoftwareDeliveryMachine): CommandHandlerRegistration<KubernetesUndeployParameters> { const cmd: CommandHandlerRegistration<KubernetesUndeployParameters> = { name: "KubernetesUndeploy", description: "remove all resources related to an application from Kubernetes cluster", paramsMaker: KubernetesUndeployParameters, listener: kubeUndeploy, }; if (_.get(sdm, "configuration.sdm.k8s.options.addCommands", false)) { cmd.intent = `kube undeploy ${cleanName(sdm.configuration.name)}`; } return cmd; } /** * Delete an application from a Kubernetes cluster. If any of the * application resources do not exist in the cluster, they are * ignored. In other words, it is not an error to try to delete * something that does not exist. If a sync repo is configured, the * corresponding resource specs are deleted from the sync repo. */ async function kubeUndeploy(ci: CommandListenerInvocation<KubernetesUndeployParameters>): Promise<HandlerResult> { const slug = `${ci.parameters.ns}/${ci.parameters.name}`; const delApp = { name: ci.parameters.name, ns: ci.parameters.ns, workspaceId: ci.context.workspaceId, }; const result: HandlerResult = { code: 0, message: `Successfully deleted ${slug} resources from Kubernetes`, }; try { const deleted = await deleteApplication(delApp); logger.info(result.message); try { await syncApplication(delApp, deleted, "delete"); } catch (err) { result.code++; const msg = `Failed to delete resource specs from sync repo: ${err.message}`; logger.error(msg); result.message = `${result.message} but ${msg}`; } try { await ci.context.messageClient.respond(slackSuccessMessage("Kubernetes Undeploy", result.message)); } catch (err) { const msg = `Failed to send response message: ${err.message}`; logger.error(msg); result.message = `${result.message} but ${msg}`; } } catch (e) { result.code++; result.message = `Failed to delete all ${slug} resources from Kubernetes: ${e.message}`; logger.error(result.message); try { await ci.context.messageClient.respond(result.message); } catch (err) { result.code++; result.message = `${result.message}; Failed to send response message: ${err.message}`; logger.error(result.message); } } return result; }