"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.kubernetesDeployHandler = exports.HandleKubernetesDeploy = void 0;
const configuration_1 = require("@atomist/automation-client/lib/configuration");
const GraphQL = require("@atomist/automation-client/lib/graph/graphQL");
const HandlerResult_1 = require("@atomist/automation-client/lib/HandlerResult");
const logger_1 = require("@atomist/automation-client/lib/util/logger");
const stringify = require("json-stringify-safe");
const storeGoals_1 = require("../../../api-helper/goal/storeGoals");
const LoggingProgressLog_1 = require("../../../api-helper/log/LoggingProgressLog");
const WriteToAllProgressLog_1 = require("../../../api-helper/log/WriteToAllProgressLog");
const types_1 = require("../../../typings/types");
const fulfiller_1 = require("../deploy/fulfiller");
/**
 * Event handler for deploying an application to a Kubernetes cluster.
 * The definition of the application to be deployed is handled by the
 * [[KubernetesDeploy]] goal of this or another SDM.  This SDM will
 * execute deployments configured for it, see [[eligibleDeployGoal]]
 * and [[verifyKubernetesApplicationDeploy]] for details.
 */
exports.HandleKubernetesDeploy = async (ef, context) => {
    if (!ef || !ef.data || !ef.data.SdmGoal) {
        const message = "Received event had no SdmGoal";
        logger_1.logger.warn(message);
        return { code: 0, message };
    }
    const logFactory = configuration_1.configurationValue("sdm.logFactory");
    return Promise.all(ef.data.SdmGoal.map(async (g) => {
        const goalEvent = g;
        const progressLog = new WriteToAllProgressLog_1.WriteToAllProgressLog(goalEvent.name, new LoggingProgressLog_1.LoggingProgressLog(goalEvent.name, "debug"), await logFactory(context, goalEvent));
        try {
            const result = await fulfiller_1.executeKubernetesDeployFulfill({ context, goalEvent, progressLog });
            const updateParams = {
                state: result.code ? types_1.SdmGoalState.failure : types_1.SdmGoalState.success,
                description: result.description,
                error: result.code ? new Error(result.message) : undefined,
                externalUrls: result.externalUrls,
            };
            try {
                await storeGoals_1.updateGoal(context, goalEvent, updateParams);
            }
            catch (e) {
                const msg = `Failed to update SDM goal ${goalEventString(goalEvent)} with params '${stringify(updateParams)}': ${e.message}`;
                progressLog.write(msg);
                result.message = `${e.message}; ${msg}`;
            }
            if (!result.code) {
                result.code = 0;
            }
            return result;
        }
        catch (e) {
            return failGoal(context, goalEvent, e.message, progressLog);
        }
    })).then(HandlerResult_1.reduceResults);
};
/**
 * Create an event handler registration for this SDM to deploy
 * requested Kubernetes applications.
 */
function kubernetesDeployHandler(self) {
    return {
        name: "KubernetesDeploy",
        description: "Deploy application resources to Kubernetes cluster",
        tags: ["deploy", "kubernetes"],
        subscription: GraphQL.subscription({
            name: "KubernetesDeployRequestedSdmGoal",
            variables: { fulfillmentName: self },
        }),
        listener: exports.HandleKubernetesDeploy,
    };
}
exports.kubernetesDeployHandler = kubernetesDeployHandler;
/**
 * Fail the provided goal using the message to set the description and
 * error message.
 *
 * @param context handler context to use to send the update
 * @param goalEvent SDM goal to update
 * @param message informative error message
 * @return a failure handler result using the provided error message
 */
async function failGoal(context, goalEvent, message, log) {
    log.write(message);
    const params = {
        state: types_1.SdmGoalState.failure,
        description: message,
        error: new Error(message),
    };
    try {
        await storeGoals_1.updateGoal(context, goalEvent, params);
    }
    catch (e) {
        const msg = `Failed to update SDM goal '${goalEventString(goalEvent)}' with params '${stringify(params)}': ${e.message}`;
        log.write(msg);
        return { code: 2, message: `${message}; ${msg}` };
    }
    return { code: 1, message };
}
/** Unique string for goal event. */
function goalEventString(goalEvent) {
    return `${goalEvent.goalSetId}/${goalEvent.uniqueName}`;
}
//# sourceMappingURL=kubernetesDeploy.js.map