"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.Container = exports.ContainerResult = exports.ContainerOutput = exports.ContainerInput = exports.ContainerProjectHome = exports.ContainerProgressReporter = exports.container = exports.ContainerRegistrationGoalDataKey = void 0;
const progress_1 = require("../../../api-helper/goal/progress/progress");
const GoalNameGenerator_1 = require("../../../api/goal/GoalNameGenerator");
const GoalWithFulfillment_1 = require("../../../api/goal/GoalWithFulfillment");
const KubernetesFulfillmentGoalScheduler_1 = require("../../../pack/k8s/scheduler/KubernetesFulfillmentGoalScheduler");
const array_1 = require("../../util/misc/array");
const goalCaching_1 = require("../cache/goalCaching");
const docker_1 = require("./docker");
const util_1 = require("./util");
exports.ContainerRegistrationGoalDataKey = "@atomist/sdm/container";
/**
 * Create and return a container goal with the provided container
 * specification.
 *
 * @param displayName Goal display name
 * @param registration Goal containers, volumes, cache details, etc.
 * @return SDM container goal
 */
function container(displayName, registration) {
    return new Container({ displayName }).with(registration);
}
exports.container = container;
exports.ContainerProgressReporter = progress_1.testProgressReporter({
    test: /docker 'network' 'create'/i,
    phase: "starting up",
}, {
    test: /docker 'network' 'rm'/i,
    phase: "shutting down",
}, {
    test: /docker 'run' .* '--workdir=[a-zA-Z\/]*' .* '--network-alias=([a-zA-Z \-_]*)'/i,
    phase: "running $1",
}, {
    test: /atm:phase=(.*)/i,
    phase: "$1",
});
/**
 * File system location of goal project in containers.
 */
exports.ContainerProjectHome = "/atm/home";
/**
 * File system location for goal container input.
 */
exports.ContainerInput = "/atm/input";
/**
 * File system location for goal container output.
 */
exports.ContainerOutput = "/atm/output";
/**
 * Goal execution result file
 */
exports.ContainerResult = `${exports.ContainerOutput}/result.json`;
/**
 * Goal run as a container, as seen on TV.
 */
class Container extends GoalWithFulfillment_1.FulfillableGoalWithRegistrations {
    constructor(details = {}, ...dependsOn) {
        const prefix = "container" + (details.displayName ? `-${details.displayName}` : "");
        const detailsToUse = Object.assign(Object.assign({}, details), { isolate: true });
        super(GoalWithFulfillment_1.getGoalDefinitionFrom(detailsToUse, GoalNameGenerator_1.DefaultGoalNameGenerator.generateName(prefix)), ...dependsOn);
        this.details = detailsToUse;
    }
    register(sdm) {
        var _a, _b;
        super.register(sdm);
        const goalSchedulers = array_1.toArray(sdm.configuration.sdm.goalScheduler) || [];
        if (util_1.runningInK8s()) {
            // load lazily to prevent early and unwanted initialization of expensive K8s api
            const kgs = require("../../../pack/k8s/scheduler/KubernetesGoalScheduler");
            // Make sure that the KubernetesGoalScheduler gets added if needed
            if (!goalSchedulers.some(gs => gs instanceof kgs.KubernetesGoalScheduler)) {
                if (!process.env.ATOMIST_ISOLATED_GOAL && kgs.isConfiguredInEnv("kubernetes", "kubernetes-all")) {
                    sdm.configuration.sdm.goalScheduler = [...goalSchedulers, new kgs.KubernetesGoalScheduler()];
                }
            }
        }
        else if (util_1.runningAsGoogleCloudFunction()) {
            const options = (_b = (_a = sdm.configuration.sdm) === null || _a === void 0 ? void 0 : _a.k8s) === null || _b === void 0 ? void 0 : _b.fulfillment;
            if (!goalSchedulers.some(gs => gs instanceof KubernetesFulfillmentGoalScheduler_1.KubernetesFulfillmentGoalScheduler)) {
                sdm.configuration.sdm.goalScheduler = [
                    ...goalSchedulers,
                    new KubernetesFulfillmentGoalScheduler_1.KubernetesFulfillmentGoalScheduler(options),
                ];
            }
        }
    }
    with(registration) {
        super.with(registration);
        registration.name = (registration.name || `container-${this.definition.displayName}`).replace(/\.+/g, "-");
        if (!this.details.scheduler) {
            if (util_1.runningInK8s()) {
                const k8sContainerScheduler = require("../../../pack/k8s/container").k8sContainerScheduler;
                this.details.scheduler = k8sContainerScheduler;
            }
            else if (util_1.runningAsGoogleCloudFunction()) {
                const k8sSkillContainerScheduler = require("../../../pack/k8s/container").k8sSkillContainerScheduler;
                this.details.scheduler = k8sSkillContainerScheduler;
            }
            else {
                this.details.scheduler = docker_1.dockerContainerScheduler;
            }
        }
        this.details.scheduler(this, registration);
        if (registration.input && registration.input.length > 0) {
            this.withProjectListener(goalCaching_1.cacheRestore({ entries: registration.input }));
        }
        if (registration.output && registration.output.length > 0) {
            this.withProjectListener(goalCaching_1.cachePut({ entries: registration.output }));
        }
        return this;
    }
    addFulfillment(fulfillment) {
        return super.addFulfillment(fulfillment);
    }
    addFulfillmentCallback(cb) {
        return super.addFulfillmentCallback(cb);
    }
}
exports.Container = Container;
//# sourceMappingURL=container.js.map