"use strict";
var KubeConfigRepo_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.KubeConfigRepo = void 0;
const tslib_1 = require("tslib");
const _ = require("lodash");
const path = require("path");
const fs = require("fs");
const inversify_1 = require("inversify");
const k8s = require("@kubernetes/client-node");
const codiac_common_1 = require("@codiac.io/codiac-common");
const codiac_ops_common_1 = require("@codiac.io/codiac-ops-common");
const codiac_constants_1 = require("../../codiac-constants");
/** Reads from and writes to the local store of k8s cluster connections file (aka: the kube config).
 * Maintains a current state to limit file system operations.
 *
 * Pure KubeConfig only, no codiac dependencies.
 *
 *
 * TODO: Promote this to a shared lib for relay and cli
 * */
let KubeConfigRepo = KubeConfigRepo_1 = class KubeConfigRepo {
    constructor(cache, logger) {
        this.cache = cache;
        this.logger = logger;
    }
    static bootstrap(ioc) {
        ioc.bind(k8s.KubeConfig).toDynamicValue(ctx => {
            let cfg = new k8s.KubeConfig();
            let filePath = KubeConfigRepo_1.getKubeConfigPath();
            if (fs.existsSync(filePath)) {
                cfg.loadFromFile(filePath);
            }
            return cfg;
        }).inSingletonScope();
        ioc.bind(KubeConfigRepo_1).toSelf();
    }
    /** Throws any exceptions. */
    static getKubeConfigPath() {
        let targetFile = process.env[codiac_constants_1.CliConstants.LOCAL_KUBE_CONFIG_ENV_KEY];
        if (!targetFile) {
            let homeDir = "~/"; // path.posix.resolve("~/");  // NOTE:  This tilde (~) may not be valid on a windows box.
            targetFile = path.posix.join(codiac_ops_common_1.OpsUtils.resolveHomeDir(homeDir), codiac_constants_1.CliConstants.LOCAL_KUBE_CONFIG_PATH_NAME);
        }
        return targetFile;
    }
    get configPath() {
        if (this.__configPath == undefined || _.isEmpty(this.__configPath)) {
            this.__configPath = KubeConfigRepo_1.getKubeConfigPath();
        }
        return this.__configPath;
    }
    // ---------------------------------------------------------------------------------------------------------------------
    // 
    //   DUPLICATED FROM codiac-relay/src/ops/k8s-connector.ts
    // 
    // ---------------------------------------------------------------------------------------------------------------------
    getK8sContext(contextName, clusterName, k8sCfg) {
        let cntx = k8sCfg.contexts.find(c => c.name === contextName);
        if (cntx === undefined) {
            // handling a very odd case where the context we just wrote wasnt found in the kubeconfig.
            cntx = k8sCfg.contexts.find(c => c.cluster === clusterName);
            if (cntx !== undefined) {
                this.logger.warn(`Fetched k8sconfig, but unable to find context in it named [${contextName}].  Continuing with context [${cntx.name}], the first found for cluster [${clusterName}], context user [${cntx.user}]`);
            }
            else {
                cntx = k8sCfg.contexts[0];
                if (cntx.name !== contextName) {
                    this.logger.warn(`Fetched k8sconfig, unable to find context in it named [${contextName}].  Continuing with default context in the fetch [${cntx.name}] [cluster: ${cntx.cluster}], user: ${cntx.user}]`);
                }
            }
        }
        return cntx;
    }
    /** Writes to the local .kube/config file. */
    cacheWrite(contextName, k8sCfg) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            // THIS TRY CATCH FIXES ASSET-STATUS FROM FAILING
            try {
                // ================GOTTA LOCK THIS - it's a singleton
                yield this.cacheRefresh();
                if (this.cache) {
                    // Gotta prevent dups (cluster and prob user too). Error we're getting: 'Duplicate cluster: codiac-cluster-02'
                    _.remove(this.cache.clusters, c => c.name === k8sCfg.clusters[0].name);
                    _.remove(this.cache.users, c => c.name === k8sCfg.users[0].name);
                    _.remove(this.cache.contexts, c => c.name === k8sCfg.contexts[0].name);
                    this.cache.mergeConfig(k8sCfg);
                    let json = this.cache.exportConfig();
                    let cacheFile = KubeConfigRepo_1.getKubeConfigPath();
                    if (!fs.existsSync(path.dirname(cacheFile))) {
                        yield fs.promises.mkdir(path.dirname(cacheFile), { recursive: true });
                    }
                    yield fs.promises.writeFile(cacheFile, json);
                    // THis is no good - it mixes object format with serialized format.
                    // let k8sEntity = {
                    //   apiVersion: "v1",
                    //   kind: "Config",
                    //   preferences: {},
                    //   ...this.cache
                    // };
                    // let k8sEntity = _.cloneDeep<any>(this.cache);
                    // k8sEntity.apiVersion = "v1";
                    // k8sEntity.kind = "Config";
                    // k8sEntity.preferences = {};
                    // let k8sEntityJson = this.cache.exportConfig();  // <--  this appears to be the only way to get the full k8s entity (with the "kind" and "version", etc), BUT this method drops the clusters.  useless.
                    // let k8sEntity = JSON.parse(k8sEntityJson);
                    // let yamlDoc = yaml.stringify(k8sEntity);
                    // fs.writeFileSync(OpsUtils.resolveHomeDir(K8sConnector.KUBE_CONFIG_FILE_PATH), yamlDoc)
                }
                // RELEASE LOCK =================================
            }
            catch (error) {
                this.logger.error('cacheWrite method error', error.message);
            }
        });
    }
    cacheRefresh() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                // ================GOTTA LOCK THIS - it's a singleton
                if (fs.existsSync(this.configPath)) {
                    this.cache.loadFromFile(this.configPath);
                }
                // RELEASE LOCK =================================
                return;
            }
            catch (err) {
                throw err;
            }
        });
    }
};
KubeConfigRepo = KubeConfigRepo_1 = tslib_1.__decorate([
    (0, inversify_1.injectable)(),
    tslib_1.__param(0, (0, inversify_1.inject)(k8s.KubeConfig)),
    tslib_1.__param(1, (0, inversify_1.inject)(codiac_common_1.INTERFACES.IBetterLogger)),
    tslib_1.__metadata("design:paramtypes", [k8s.KubeConfig, Object])
], KubeConfigRepo);
exports.KubeConfigRepo = KubeConfigRepo;
//# sourceMappingURL=kube-config-utils.js.map