package com.mirantis.mk

/**
 *
 *  Functions to work with Helm
 *
 */

/**
 * Build index file for helm chart
 * @param extra_params   additional params, e.g. --url repository_URL
 * @param charts_dir     path to a directory
 */

def helmRepoIndex(extra_params='', charts_dir='.'){
    sh("helm repo index ${extra_params} ${charts_dir}")
}

/**
 * Rebuild index file for helm chart repo
 * @param helmRepoUrl  repository with helm charts
 * @param md5Remote    md5 sum of index.yaml for check
 */

def helmMergeRepoIndex(helmRepoUrl, md5Remote='') {
    def common      = new com.mirantis.mk.Common()

    def helmRepoDir    = '.'
    def helmExtraParams = "--url ${helmRepoUrl}"

    def indexRes = common.shCmdStatus("wget -O index-upstream.yaml ${helmRepoUrl}/index.yaml")
    if (indexRes['status']){
        if (indexRes['status'] == 8 && indexRes['stderr'].contains('ERROR 404') && !md5Remote) {
            common.warningMsg("Index.yaml not found in ${helmRepoUrl} and will be fully regenerated")
        } else {
            error("Something went wrong during index.yaml download: ${indexRes['stderr']}")
        }
    } else {
        if (md5Remote) {
            def md5Local = sh(script: "md5sum index-upstream.yaml | cut -d ' ' -f 1", returnStdout: true).readLines()[0]
            if (md5Local != md5Remote) {
                  error 'Target repository already exist, but upstream index.yaml broken or not found'
            }
        }
        helmExtraParams += " --merge index-upstream.yaml"
    }
    helm.helmRepoIndex(helmExtraParams, helmRepoDir)
}

/**
 * Generates version for helm chart based on information from git repository. Tries to search
 * first parent git tag using pattern '[0-9]*-{tagSuffix}', if found that tag will be used
 * in final version, if not found - version will be formed as '{defaultVersion}-{tagSuffix}'. Number
 * of commits since last tag or sha of current commit can be added to version.
 *
 * @param repoDir        string, path to a directory with git repository of helm charts
 * @param devVersion     Boolean, if set to true development version will be calculated e.g 0.1.0-mcp-{sha of current commit}
 * @param increment      Boolean, if set to true patch version will be incremented (e.g 0.1.0 -> 0.1.1)
 * @param defaultVersion string, value of version which will be used in case no tags found. should be semver2 compatible
 * @param tagSuffix      string, suffix which will be used for finding tags in git repository, also if tag not found, it
 *                               it will be added to {defaultVersion} e.g {defaultVersion}-{tagSuffix}
 */

def generateChartVersionFromGit(repoDir, devVersion = true, increment = false, defaultVersion = '0.1.0', tagSuffix = 'mcp') {
    def common = new com.mirantis.mk.Common()
    def git = new com.mirantis.mk.Git()
    String initialVersion = "${defaultVersion}-${tagSuffix}"
    String countRange
    String versionData
    String tagPattern = "[0-9]*-${tagSuffix}"
    dir(repoDir){
        Map cmd = common.shCmdStatus("git describe --tags --first-parent --abbrev=0 --match ${tagPattern}")
        String lastTag = cmd['stdout'].trim()

        if (cmd['status'] != 0){
            if (cmd['stderr'].contains('fatal: No names found, cannot describe anything')){
                common.warningMsg("No parent git tag found, using initial version ${initialVersion}")
                versionData = initialVersion
                countRange = 'HEAD'
            } else {
                error("Something went wrong, cannot find git information ${cmd['stderr']}")
            }
        } else {
            versionData = lastTag
            countRange = "${lastTag}..HEAD"
        }
        List versionParts = versionData.tokenize('-')

        if (versionParts.size() == 2 && common.isSemVer(versionData) && versionParts[1] == tagSuffix){
            String commitsSinceTag = sh(script: "git rev-list --count ${countRange}", returnStdout: true).trim()
            String commitSha = sh(script: 'git rev-parse --short=7 HEAD', returnStdout: true).trim()

            if (commitsSinceTag == '0'){
                return versionData
            }

            if (devVersion){
                versionParts.add(commitSha)
            } else {
                versionParts.add(commitsSinceTag)
            }
            // Patch version will be incremented e.g. 0.1.0 -> 0.1.1
            if (increment) {
                versionParts[0] = git.incrementVersion(versionParts[0])
            }
            return versionParts.join('-')
        }
        error "Version ${versionData} doesn't contain required suffix ${tagSuffix} or not in semver2 format"
    }
}

/**
 * Takes a list of dependencies and a version, and sets a version for each dependency in requirements.yaml. If dependency isn't
 * found in requirements.yaml or requirements.yaml does not exist - does nothing.
 *
 * @param chartPath      string, path to a directory with helm chart
 * @param dependencies   list of hashes with names and versions of dependencies in format:
 *                       [['name': 'chart-name1', 'version': '0.1.0-myversion'], ['name': 'chart-name2', 'version': '0.2.0-myversion']]
 */

def setChartDependenciesVersion(chartPath, List dependencies){
    def common = new com.mirantis.mk.Common()
    if (!dependencies){
        error 'No list of target dependencies is specified'
    }
    def reqsFilePath = "${chartPath}/requirements.yaml"
    def chartYaml = readYaml file: "${chartPath}/Chart.yaml"
    def reqsUpdateNeeded = false
    def reqsMap = [:]
    if (fileExists(reqsFilePath)){
        reqsMap = readYaml file: reqsFilePath
        for (i in dependencies) {
            for (item in reqsMap.get('dependencies', [])){
                if (item['name'] == i['name']){
                    common.infoMsg("Set version ${i['version']} for dependency ${i['name']} in chart ${chartYaml['name']}")
                    item['version'] = i['version']
                    reqsUpdateNeeded = true
                }
            }
        }
    }
    if (reqsUpdateNeeded){
        sh "rm ${reqsFilePath}"
        writeYaml file: reqsFilePath, data: reqsMap
    } else {
        common.warningMsg("requirements.yaml doesn't exist at path ${reqsFilePath} or chart doesn't contain ${dependencies}, nothing to set")
    }
}
