UNPKG

@atomist/sdm

Version:

Atomist Software Delivery Machine SDK

126 lines 5.42 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.hasMetadataAnnotation = exports.filterIgnoredSpecs = exports.calculateChanges = exports.changeResource = void 0; const configuration_1 = require("@atomist/automation-client/lib/configuration"); const _ = require("lodash"); const apply_1 = require("../kubernetes/apply"); const delete_1 = require("../kubernetes/delete"); const secret_1 = require("../kubernetes/secret"); const spec_1 = require("../kubernetes/spec"); const application_1 = require("./application"); const previousSpecVersion_1 = require("./previousSpecVersion"); /** * Delete/apply resources in change. The spec file provided by the * change.path may contain multiple specs. The requested change is * applied to each. */ async function changeResource(p, change) { const beforeContents = await previousSpecVersion_1.previousSpecVersion(p.baseDir, change.path, change.sha); const beforeSpecs = spec_1.parseKubernetesSpecs(beforeContents); let specs; if (change.change !== "delete") { const specFile = await p.getFile(change.path); if (!specFile) { throw new Error(`Resource spec file '${change.path}' does not exist in project`); } const specContents = await specFile.getContent(); specs = spec_1.parseKubernetesSpecs(specContents); } const changes = calculateChanges(beforeSpecs, specs, change.change); const syncOpts = configuration_1.configurationValue("sdm.k8s.options.sync", {}); for (const specChange of changes) { let changer; if (specChange.change === "delete") { changer = delete_1.deleteSpec; } else { changer = apply_1.applySpec; } _.set(specChange.spec, "metadata.annotations['atomist.com/sync-sha']", change.sha); if (specChange.change !== "delete" && specChange.spec.kind === "Secret" && syncOpts.secretKey) { specChange.spec = await secret_1.decryptSecret(specChange.spec, syncOpts.secretKey); } await changer(specChange.spec); } } exports.changeResource = changeResource; /** * Inspect before and after specs to determine actions. * * If the action is "delete", return delete actions for all specs in * `before` that do not have an ignore annotation for the current SDM, * as the "delete" action implies there are no `after` specs. * * If the action is "apply", return apply actions for all specs in * `after` and delete actions for all specs in `before` that are not * in `after` that do not have an ignore annotation for the current * SDM. If a `before` spec contains a sync ignore annotation for the * current SDM and the `after` annotation does not, the `after` spec * with an "apply" action is included in the returned changes. If an * `after` spec contains a sync ignore annotation for the current SDM, * then it is omitted from the returned changes, regardless of whether * it appears in the `before` specs or not. * * @param before The specs before the change * @param after The specs after the change * @param change The type of change * @return Array containing the type of change for each spec */ function calculateChanges(before, after, change) { const beforeFiltered = filterIgnoredSpecs(before); if (change === "delete") { return beforeFiltered.map(spec => ({ change, spec })); } const changes = filterIgnoredSpecs(after).map(spec => ({ change, spec })); for (const spec of beforeFiltered) { if (!after.some(a => application_1.sameObject(a, spec))) { changes.push({ change: "delete", spec }); } } return changes; } exports.calculateChanges = calculateChanges; /** * Returned array of specs with those that should be ignored filtered * out. * * @param specs Array of specs to check * @return Array of not ignored specs. */ function filterIgnoredSpecs(specs) { if (!specs) { return []; } return specs.filter(spec => !hasMetadataAnnotation(spec, "sync", "ignore")); } exports.filterIgnoredSpecs = filterIgnoredSpecs; /** * Check if the Kubernetes Object has an annotation that is relevant to the current SDM * @param spec the spec to inspect * @param annotationKey the key to validate for * @param annotationValue the value validate for * @returns the result of the annotation inspection */ function hasMetadataAnnotation(spec, annotationKey, annotationValue) { const sdmName = configuration_1.configurationValue("name"); const nameKey = `atomist.com/sdm-pack-k8s/${annotationKey}/${sdmName}`; const specValue = _.get(spec, `metadata.annotations['${nameKey}']`); return !!specValue && specValue === annotationValue; } exports.hasMetadataAnnotation = hasMetadataAnnotation; //# sourceMappingURL=change.js.map