"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.ingressTemplate = exports.upsertIngress = void 0;
const logger_1 = require("@atomist/automation-client/lib/util/logger");
const _ = require("lodash");
const error_1 = require("../support/error");
const retry_1 = require("../support/retry");
const labels_1 = require("./labels");
const metadata_1 = require("./metadata");
const patch_1 = require("./patch");
const request_1 = require("./request");
const resource_1 = require("./resource");
/**
 * If `req.port` and `req.path` are truthy, create or patch an ingress
 * for a Kubernetes application.  Any provided `req.ingressSpec` is
 * merged using [[ingressTemplate]] before creating/patching.
 *
 * @param req Kuberenetes resource request
 * @return Kubernetes spec used to create/patch resource
 */
async function upsertIngress(req) {
    const slug = request_1.appName(req);
    if (!req.port) {
        logger_1.logger.debug(`Port not provided, will not create ingress ${slug}`);
        return undefined;
    }
    if (!req.path) {
        logger_1.logger.debug(`Path not provided, will not upsert ingress ${slug}`);
        return undefined;
    }
    const spec = await ingressTemplate(req);
    try {
        await req.clients.net.readNamespacedIngress(spec.metadata.name, spec.metadata.namespace);
    }
    catch (e) {
        logger_1.logger.debug(`Failed to read ingress ${slug}, creating: ${error_1.k8sErrMsg(e)}`);
        logger_1.logger.info(`Creating ingress ${slug} using '${resource_1.logObject(spec)}'`);
        await retry_1.logRetry(() => req.clients.net.createNamespacedIngress(spec.metadata.namespace, spec), `create ingress ${slug}`);
        return spec;
    }
    logger_1.logger.info(`Ingress ${slug} exists, patching using '${resource_1.logObject(spec)}'`);
    await retry_1.logRetry(() => req.clients.net.patchNamespacedIngress(spec.metadata.name, spec.metadata.namespace, spec, undefined, undefined, undefined, undefined, patch_1.patchHeaders(req)), `patch ingress ${slug}`);
    return spec;
}
exports.upsertIngress = upsertIngress;
/**
 * Create an ingress HTTP path.
 *
 * @param req ingress request
 * @return ingress HTTP path
 */
function httpIngressPath(req) {
    const httpPath = {
        path: req.path,
        backend: {
            serviceName: req.name,
            servicePort: "http",
        },
    };
    return httpPath;
}
/**
 * Create the ingress for a deployment namespace.  If the
 * request has an `ingressSpec`, it is merged into the spec created
 * by this function using `lodash.merge(default, req.ingressSpec)`.
 *
 * It is possible to override the ingress name using the
 * [[KubernetesApplication.ingressSpec]].  If you do this, make sure
 * you know what you are doing.
 *
 * @param req Kubernestes application
 * @return ingress spec with single rule
 */
async function ingressTemplate(req) {
    const labels = labels_1.applicationLabels(req);
    const metadata = metadata_1.metadataTemplate({
        name: req.name,
        namespace: req.ns,
        labels,
    });
    const httpPath = httpIngressPath(req);
    const rule = {
        http: {
            paths: [httpPath],
        },
    };
    const apiVersion = "networking.k8s.io/v1beta1";
    const kind = "Ingress";
    const i = {
        apiVersion,
        kind,
        metadata,
        spec: {
            rules: [rule],
        },
    };
    if (req.ingressSpec) {
        _.merge(i, req.ingressSpec, { apiVersion, kind });
        i.metadata.namespace = req.ns;
    }
    return i;
}
exports.ingressTemplate = ingressTemplate;
//# sourceMappingURL=ingress.js.map