@atomist/sdm
Version:
Atomist Software Delivery Machine SDK
174 lines • 6.28 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.deleteApplication = exports.upsertApplication = void 0;
const error_1 = require("../support/error");
const clients_1 = require("./clients");
const config_1 = require("./config");
const delete_1 = require("./delete");
const deployment_1 = require("./deployment");
const ingress_1 = require("./ingress");
const namespace_1 = require("./namespace");
const rbac_1 = require("./rbac");
const request_1 = require("./request");
const secret_1 = require("./secret");
const service_1 = require("./service");
/**
* Create or update all the resources for an application in a
* Kubernetes cluster.
*
* @param app Kubernetes application creation request
* @param sdmFulfiller Registered name of the SDM fulfilling the deployment goal.
* @return Array of resource specs upserted
*/
async function upsertApplication(app, sdmFulfiller) {
let clients;
if (app.mode === "sync") {
clients = clients_1.makeNoOpApiClients();
}
else {
let config;
try {
config = config_1.loadKubeConfig();
}
catch (e) {
e.message = `Failed to load Kubernetes config to deploy ${app.ns}/${app.name}: ${e.message}`;
throw e;
}
clients = clients_1.makeApiClients(config);
}
const req = Object.assign(Object.assign({}, app), { sdmFulfiller, clients });
try {
const k8sResources = [];
k8sResources.push(await namespace_1.upsertNamespace(req));
k8sResources.push(...Object.values((await rbac_1.upsertRbac(req))));
k8sResources.push(await service_1.upsertService(req));
k8sResources.push(...(await secret_1.upsertSecrets(req)));
k8sResources.push(await deployment_1.upsertDeployment(req));
k8sResources.push(await ingress_1.upsertIngress(req));
return k8sResources.filter(r => !!r);
}
catch (e) {
e.message = `Failed to upsert '${request_1.reqString(req)}': ${error_1.k8sErrMsg(e)}`;
throw e;
}
}
exports.upsertApplication = upsertApplication;
/**
* Delete resources associated with an application from a Kubernetes
* cluster. If any resources fail to be deleted, an error is thrown.
* If no resources associated with the application exist, it does
* nothing successfully.
*
* @param req Delete application request object
*/
async function deleteApplication(del) {
const slug = `${del.ns}/${del.name}`;
let config;
try {
config = config_1.loadKubeConfig();
}
catch (e) {
e.message(`Failed to load Kubernetes config to delete ${slug}: ${e.message}`);
throw e;
}
const clients = clients_1.makeApiClients(config);
const req = Object.assign(Object.assign({}, del), { clients });
const deleted = [];
const errs = [];
const resourceDeleters = [
{
kind: "Ingress",
namespaced: true,
api: req.clients.net,
lister: req.clients.net.listNamespacedIngress,
deleter: req.clients.net.deleteNamespacedIngress,
},
{
kind: "Deployment",
namespaced: true,
api: req.clients.apps,
lister: req.clients.apps.listNamespacedDeployment,
deleter: req.clients.apps.deleteNamespacedDeployment,
},
{
kind: "Secret",
namespaced: true,
api: req.clients.core,
lister: req.clients.core.listNamespacedSecret,
deleter: req.clients.core.deleteNamespacedSecret,
},
{
kind: "Service",
namespaced: true,
api: req.clients.core,
lister: req.clients.core.listNamespacedService,
deleter: req.clients.core.deleteNamespacedService,
},
{
kind: "ClusterRoleBinding",
namespaced: false,
api: req.clients.rbac,
lister: req.clients.rbac.listClusterRoleBinding,
deleter: req.clients.rbac.deleteClusterRoleBinding,
},
{
kind: "RoleBinding",
namespaced: true,
api: req.clients.rbac,
lister: req.clients.rbac.listNamespacedRoleBinding,
deleter: req.clients.rbac.deleteNamespacedRoleBinding,
},
{
kind: "ClusterRole",
namespaced: false,
api: req.clients.rbac,
lister: req.clients.rbac.listClusterRole,
deleter: req.clients.rbac.deleteClusterRole,
},
{
kind: "Role",
namespaced: true,
api: req.clients.rbac,
lister: req.clients.rbac.listNamespacedRole,
deleter: req.clients.rbac.deleteNamespacedRole,
},
{
kind: "ServiceAccount",
namespaced: true,
api: req.clients.core,
lister: req.clients.core.listNamespacedServiceAccount,
deleter: req.clients.core.deleteNamespacedServiceAccount,
},
];
for (const rd of resourceDeleters) {
try {
const x = await delete_1.deleteAppResources(Object.assign(Object.assign({}, rd), { req }));
deleted.push(...x);
}
catch (e) {
e.message = `Failed to delete ${rd.kind} for ${slug}: ${error_1.k8sErrMsg(e)}`;
errs.push(e);
}
}
if (errs.length > 0) {
throw new Error(`Failed to delete application '${request_1.reqString(req)}': ${errs.map(e => e.message).join("; ")}`);
}
return deleted;
}
exports.deleteApplication = deleteApplication;
//# sourceMappingURL=application.js.map