#!/usr/bin/env python3

# pydoc-markdown -I bin | awk '/dh.main/ {p=1}; p==0 {print}'

"""
Ortelius' CLI using the dhapi module.

Args:

    ACTION - one of the following

        deploy: deploy the application to the environment
            Usage:
                --dhurl
                --dhuser
                --dhpass
                --appname
                --appversion (optional)
                --deployenv

        approve: approve the application version
            Usage:
                --dhurl
                --dhuser
                --dhpass
                --appname
                --appversion (optional)

        move: move the application version using the supplied task
            Usage:
                --dhurl
                --dhuser
                --dhpass
                --appname
                --appversion (optional)
                --from_domain
                --task

        updatecomp: create/replace the component version for the application verion
            Usage:
                --dhurl
                --dhuser
                --dhpass
                --rsp <name of the component toml file>
                --autoappinc (optional)
                --compautoinc (optional)
                --consumes (optional)
                --provides (optional)
                --deppkg cyclonedx@<cyclonedx json sbom file> (optional)
                --deppkg spdx@<spdx json sbom file> (optional)

           ##### Component TOML Definition for --rsp parameter

            ```toml
            # Application Name and Version to create an associate the Component Version to
            # NOTE: Only needed if you need to assoicate the Component Version to the Application Verion

            Application = ""          # Name of the Applcation including the full Domain Name
            Application_Version = ""  # The semantic version for the Application Version

            # Component Name, Variant and Version
            Name = ""
            Variant = "${GIT_BRANCH}"
            Version = "v1.0.0.${BUILD_NUM}-g${GIT_COMMIT}"                  # 1.0.0 should be replace with your starting version string

            # Export the derived IMAGE_TAG, DOCKERREPO values to the CI/CD Tool via a shell script when using the `envscript` command line action
            [Export]
                IMAGE_TAG = "${Variant}-${Version}"
                DOCKERREPO = "${DockerRepo}"

            # Key/Values to associate to the Component Version.  Custom key/values can be added under this section.
            [Attributes]
                BuildId = "${BUILDID}"                                      # Identifier for the CI job (DERIVED IF NOT SPECIFIED)
                BuildNumber = "${BUILD_NUM}"                                # Build number for the CI job (DERIVED IF NOT SPECIFIED)
                BuildUrl = "${BUILD_URL}"                                   # Build url for the CI job (DERIVED IF NOT SPECIFIED)
                Chart = "$CHART}"                                           # Helm Chart for the component
                ChartNamespace = ""                                         # Name space for the component to be deployed to
                ChartRepo = ""                                              # Helm Chart Repo Name
                ChartRepoUrl = ""                                           # Helm Chart Repo Url
                ChartVersion = "${CHARTVERSION}"                            # Helm Chart version
                CustomAction = ""                                           # Custom Action to assign to the Component
                DeployAlways = ""                                           # Set the Always Deploy option Y/N, default is N
                DockerBuildDate = ""                                        # Timestamp when the image was created (DERIVED IF NOT SPECIFIED)
                DockerRepo = "${DOCKERREPO}"                                # Registry which the image was pushed to
                DockerSha = "${DIGEST}"                                     # Digest for the image (DERIVED IF NOT SPECIFIED)
                DockerTag = "${DOCKERTAG}"                                  # Tag for the image
                GitBranch = "${GIT_BRANCH}"                                 # Git branch in the git repo (DERIVED IF NOT SPECIFIED)
                GitBranchCreateCommit = "${GIT_BRANCH_CREATE_COMMIT}"       # Git commit that the branch was created from (DERIVED IF NOT SPECIFIED)
                GitBranchCreateTimestamp = "${GIT_BRANCH_CREATE_TIMESTAMP}" # Timestamp of when the branch was created (DERIVED IF NOT SPECIFIED)
                GitBranchParent = "${GIT_BRANCH_PARENT}"                    # The parent branch for the current branch (DERIVED IF NOT SPECIFIED)
                GitCommit = "${GIT_COMMIT}"                                 # Git commit that triggered the CI job (DERIVED IF NOT SPECIFIED)
                GitCommitAuthors = "${GIT_COMMIT_AUTHORS}"                  # List of committers for the repo (DERIVED IF NOT SPECIFIED)
                GitCommittersCnt = "${GIT_COMMITTERS_CNT}"                  # Count of GitCommitAuthors (DERIVED IF NOT SPECIFIED)
                GitCommitTimestamp = "${GIT_COMMIT_TIMESTAMP}"              # Timestamp of the current commit (DERIVED IF NOT SPECIFIED)
                GitContribPercentage = "${GIT_CONTRIB_PERCENTAGE}"          # GitCommittersCnt / GitTotalCommittersCnt * 100 (DERIVED IF NOT SPECIFIED)
                GitLinesAdded = "${GIT_LINES_ADDED}"                        # Lines added since the previous commit (DERIVED IF NOT SPECIFIED)
                GitLinesDeleted = "${GIT_LINES_DELETED}"                    # Lines deleted since the previous commit (DERIVED IF NOT SPECIFIED)
                GitLinesTotal = "${GIT_LINES_TOTAL}"                        # Total line count for the branch (DERIVED IF NOT SPECIFIED)
                GitOrg = "${GIT_ORG}"                                       # Orgranization for the repo (DERIVED IF NOT SPECIFIED)
                GitRepo = "${GIT_REPO}"                                     # Git repo that triggered the CI job (DERIVED IF NOT SPECIFIED)
                GitRepoProject = "${GIT_REPO_PROJECT}"                      # Project name part of the repository url (DERIVED IF NOT SPECIFIED)
                GitTag = "${GIT_TAG)"                                       # Git tag in the git repo (DERIVED IF NOT SPECIFIED)
                GitTotalCommittersCnt = "${GIT_TOTAL_COMMITTERS_CNT}"       # Total committers working on this repo
                GitUrl = "${GIT_URL}"                                       # Full url to the git repo (DERIVED IF NOT SPECIFIED)
                License = ""                                                # License file location in the Git Repo (DERIVED IF NOT SPECIFIED)
                operator = ""                                               # Operator name
                Readme = ""                                                 # Readme file location in the Git Repo (DERIVED IF NOT SPECIFIED)
                ServiceOwner = ""                                           # Owner of the Service
                ServiceOwnerEmail = ""                                      # Email for the Owner of the Service
                ServiceOwnerPhone = ""                                      # Phone number for the Owner of the Service
                Swagger = ""                                                # Swagger/OpenApi file location in the Git Repo (DERIVED IF NOT SPECIFIED)
            ```

        assign: assigns a component version to an application verion
            Usage:
                --dhurl
                --dhuser
                --dhpass
                --compname
                --compvariant (optional)
                --compversion (optional)
                --appname
                --appversion (optional)

        kv: assigns the key/values pairs to the component verion
            Usage:
                --dhurl
                --dhuser
                --dhpass
                --compname
                --compvariant (optional)
                --compversion (optional)
                --kvconfig

        envscript: creates a bash file from the component toml file
            Usage:
                --envvars
                --envvars_sh

        export: exports a domain including all objects to stdout
            Usage:
                --dhurl
                --dhuser
                --dhpass
                --from_dom

        import: imports the export file into the new domain
            Usage:
                --dhurl
                --dhuser
                --dhpass
                --from_dom
                --to_dom

#### Parameter Descriptions

    `--appautoinc` Application Auto Increment Version
    `--appname` Application Name
    `--appversion` Application Version
    `--cert` Customer SSL Certificate File
    `--changerequest` Change Request for Component, use multiple time for each Change Request Id
    `--cluster_json` json from kubectl get deploy -n default -o json
    `--compattr` Component Attributes, use multiple time for each attr
    `--compautoinc` Component Auto Increment Version
    `--compname` Component Name
    `--compvariant` Component Variant
    `--compversion` Component Version
    `--consumes`  json file that lists the endpoints the component consumes.  [ {"verb", "get", "path": "/weather"}]
    `--crdatasource` Change Request Data Source for the Component
    `--deploydata` The json file that contains the application, environment and log details
    `--deploydatasave` Name of the json file to save the new component and application versions names to
    `--deployenv` Deployment Environment
    `--deppkg` File name for the Safety, CycloneDx, SPDX json scan data, use multiple time for each file.  Parameter format is: <type>@<filename> where type=safety, cyclonedx, spdx
    `--dhpass` DeployHub Password
    `--dhurl` DeployHub Url
    `--dhuser` DeployHub User
    `--docker` docker Kind of the component item
    `--envs` Environments to Associate App to, use multiple time for each env
    `--envvars_sh` Environment Variables Output shell file
    `--envvars` Component TOML file
    `--file` file Kind of the component item
    `--from_domain` Move from domain
    `--fromdom` From Domain
    `--importfile` File to Import
    `--kvconfig` Directory containing the json and properties file
    `--logdeployment` Records a deployment by a external program
    `--msbranch` New microservice branch being added to the cluster
    `--msname` New microservice being added to the cluster
    `--provides`  json file that lists the endpoints the component provides.  [ {"verb", "get", "path": "/checkout"}]
    `--rsp` Response File for Parameters, ie component.toml
    `--task` Task to use for move
    `--todom` To Domain

"""

# To generate markdown use:
# pydoc-markdown -I bin | awk '/dh.main/ {p=1}; p==0 {print}'

__version__ = "9.3.225"

import json
import os
from pathlib import Path
import re
import stat
import subprocess
import sys
import time
from cmath import exp
from datetime import datetime
from pprint import pprint
from string import Template

import click
import qtoml
import yaml
from deployhub import dhapi
from pydantic import NoneIsAllowedError


@click.command()
@click.argument("action", required=True)
@click.option("--dhurl", help="DeployHub Url", envvar="DHURL", required=True)
@click.option("--dhuser", help="DeployHub User", envvar="DHUSER", required=True)
@click.option("--dhpass", help="DeployHub Password", envvar="DHPASS", required=True)
@click.option("--appname", help="Application Name", envvar="COMPONENT_APPLICATION")
@click.option("--appversion", help="Application Version", envvar="COMPONENT_APPLICATION_VERSION")
@click.option("--appautoinc", help="Application Auto Increment Version", envvar="COMPONENT_APPLICATION_AUTOINC")
@click.option("--deployenv", help="Deployment Environment")
@click.option("--compname", help="Component Name", envvar="COMPONENT_NAME")
@click.option("--compvariant", help="Component Variant", envvar="COMPONENT_VARIANT")
@click.option("--compversion", help="Component Version", envvar="COMPONENT_VERSION")
@click.option("--compautoinc", help="Component Auto Increment Version", envvar="COMPONENT_AUTOINC")
@click.option("--deploydatasave", help="Name of the json file to save the new component and application versions names to")
@click.option("--kvconfig", help="Directory containing the json and properties file", envvar="KVCONFIG")
@click.option("--crdatasource", help="Change Request Data Source for the Component", envvar="CR_DATASOURCE")
@click.option("--changerequest", help="Change Request for Component, use multiple time for each Change Request Id", multiple=True)
@click.option("--deploydata", help="The json file that contains the application, environment and log details", envvar="DEPLOY_DATA")
@click.option("--from_domain", help="Move from domain")
@click.option("--task", help="Task to use for move")
@click.option("--envvars", help="Env Variables TOML file")
@click.option("--envvars_sh", help="Env Variables Output sh file")
@click.option("--docker", "kind", flag_value="docker", default=True, help="Component Item Type")
@click.option("--file", "kind", flag_value="file")
@click.option("--compattr", help="Component Attributes, use multiple time for each attr", multiple=True)
@click.option("--envs", help="Environments to Associate App to, use multiple time for each env", multiple=True)
@click.option("--importfile", help="File to Import")
@click.option("--fromdom", help="From Domain")
@click.option("--todom", help="To Domain")
@click.option("--cluster_json", help="json from kubectl get deploy -n default -o json")
@click.option("--msname", help="New microservice being added to the cluster")
@click.option("--msbranch", help="New microservice branch being added to the cluster")
@click.option(
    "--deppkg", help="File name for the Safety, CycloneDx json scan data, use multiple time for each file.  Parameter format is: <type>@<filename> where type=safety, cyclonedx", multiple=True
)
@click.option("--logdeployment", is_flag=True, help="Records a deployment by a external program")
@click.option("--consumes", help="json file listing end points being consumed")
@click.option("--provides", help="json file listing end points being provided")
@click.option("--rsp", help="Response File for Parameters")
@click.option("--cert", help="Customer SSL Certificate File")
def main(  # noqa: C901
    dhurl,
    dhuser,
    dhpass,
    action,
    appname,
    appversion,
    appautoinc,
    compname,
    compvariant,
    compversion,
    compautoinc,
    kind,
    deployenv,
    envs,
    compattr,
    kvconfig,
    deploydata,
    deploydatasave,
    from_domain,
    task,
    envvars,
    envvars_sh,
    importfile,
    fromdom,
    todom,
    crdatasource,
    changerequest,
    cluster_json,
    msname,
    msbranch,
    deppkg,
    logdeployment,
    consumes,
    provides,
    rsp,
    cert,
):
    """
    ACTION: deploy, updatecomp, approve, move, envscript, kv, cluster, export or import for the type of action to perform.

        deploy: deploy the application to the evironment\n
        approve: approve the application version\n
        move: move the application version using the supplied task\n
        updatecomp: create/replace the component version for the application verion\n
            Predefined Key/Values:\n
                BuildId - Identifier for the CI job\n
                BuildNumber - Build number for the CI job\n
                BuildUrl - url for the CI job\n
                Chart - Helm Chart for the component\n
                ChartNamespace - Name space for the component to be deployed to\n
                ChartRepo - Helm Chart Repo Name\n
                ChartRepoUrl - Helm Chart Repo Url\n
                ChartVersion - Helm Chart version\n
                CustomAction - Custom Action to assign to the Component\n
                DockerBuildDate - Timestamp when the image was created\n
                DockerRepo - Registry which the image was pushed to\n
                DockerSha - Digest for the image\n
                DockerTag - Tag for the image\n
                GitBranch - Git branch in the git repo\n
                GitCommit - Git commit that triggered the CI job\n
                GitRepo - Git repo that triggered the CI job\n
                GitTag - Git tag in the git repo\n
                GitUrl - Full url to the git repo\n
                operator - Operator name\n
                Readme - Readme location in the Git Repo\n
                ServiceOwner - Owner of the Service\n
                ServiceOwnerEmail - Email for the Owner of the Service\n
                ServiceOwnerPhone - Phone number for the Owner of the Service\n

        assign: assigns a component version to an application verion\n
        kv: assigns the key/values pairs to the component verion\n
        envscript: creates a bash file from the component toml file\n
        export: exports a domain including all objects to stdout\n
        import: imports the export file into the new domain\n
    """

    attrs = {}
    if rsp is None:
        rsp = "component.toml"

    if os.path.exists(rsp):
        file = open(rsp)
        lines = file.read()
        file.close()
        mapping = os.environ

        if mapping.get("BLDDATE", None) is None:
            now = datetime.now()
            mapping["BLDDATE"] = now.strftime("%c")
        else:
            mapping["BLDDATE"] = mapping.get("BLDDATE").strip('"')

        template = Template(lines)
        lines = template.safe_substitute(**mapping)

        vardict = qtoml.loads(lines)

        attrvars = vardict.get("Attributes", {})
        for key, val in attrvars.items():
            vardict[key] = val

        # do secord subsitution to resolve as much as possible
        template = Template(lines)
        lines = template.safe_substitute(**vardict)

        vardict = qtoml.loads(lines)

        if appname is None:
            appname = vardict.get("Application", None)

        if appversion is None:
            appversion = vardict.get("Application_Version", None)

        if deployenv is None:
            deployenv = vardict.get("DeployEnv", None)

        if compname is None:
            compname = vardict.get("Name", None)

        if compvariant is None:
            compvariant = vardict.get("Variant", None)

        if compversion is None:
            compversion = vardict.get("Version", None)

        attrs = vardict.get("Attributes", {})

        pprint(vardict)

    if dhapi.is_not_empty(compvariant):
        compvariant = compvariant.replace("/", "_")

    if (
        action.lower() == "kv"
        or action.lower() == "deploy"
        or action.lower() == "cluster"
        or action.lower() == "updatecomp"
        or action.lower() == "approve"
        or action.lower() == "export"
        or action.lower() == "import"
        or action.lower() == "assign"
        or action.lower() == "envscript"
    ):
        if dhapi.is_empty(dhurl):
            print("--dhurl is required")
            sys.exit(1)

        if dhapi.is_empty(dhuser):
            print("--dhuser is required")
            sys.exit(1)

        if dhapi.is_empty(dhpass):
            print("--dhpass is required")
            sys.exit(1)

        errors = []

        if dhapi.is_not_empty(cert):
            dhapi.sslcerts(dhurl, cert)

        cookies = dhapi.login(dhurl, dhuser, dhpass, errors)

        if cookies is None:
            if errors:
                print(errors[0])
            sys.exit(1)

    if action.lower() == "deploy":
        # Deploy Application to Environment
        if dhapi.is_empty(dhurl):
            print("--dhurl is required")
            sys.exit(1)

        if dhapi.is_empty(dhuser):
            print("--dhuser is required")
            sys.exit(1)

        if dhapi.is_empty(dhpass):
            print("--dhpass is required")
            sys.exit(1)

        if dhapi.is_empty(appversion):
            appversion = ""

        retcode = 0
        if dhapi.is_empty(deploydata):
            if dhapi.is_empty(appname) and dhapi.is_empty(compname):
                print("--appname is required")
                sys.exit(1)

            applist = []
            if dhapi.is_not_empty(appname):
                if dhapi.is_not_empty(appname) and dhapi.is_empty(appversion):
                    parts = appname.split(";")
                    if len(parts) == 3:
                        appname = parts[0] + ";" + parts[1]
                        appversion = parts[2]

                data = dhapi.get_application(dhurl, cookies, appname, appversion, True)
                appid = data[0]
                appname = data[1]
                applist.append({"appid": appid, "appname": appname, "deployenv": deployenv, "circleci_pipeline": ""})

                if dhapi.is_empty(deployenv):
                    print("--deployenv is required")
                    sys.exit(1)

            if dhapi.is_empty(appname) and dhapi.is_not_empty(compname):
                data = dhapi.get_component(dhurl, cookies, compname, "", "", True, True)
                parent_compid = data[0]
                data = dhapi.get_component_fromid(dhurl, cookies, parent_compid)

                if data is not None and "result" in data:
                    result = data["result"]
                    if result.get("applications", None) is not None:
                        data = result.get("applications", None)
                        for app in data:
                            appname = app.get("name", "")
                            appid = app.get("id", "")
                            appdata = dhapi.get_application(dhurl, cookies, appname, "latest", True)
                            latest_appid = appdata[0]

                            if appid == latest_appid:
                                app_attrs = dhapi.get_application_attrs(dhurl, cookies, appid)

                                deployenv = ""
                                pipeline = ""
                                for entry in app_attrs:
                                    if "DeployEnv" in entry:
                                        deployenv = entry["DeployEnv"]
                                    if "CircleCI_Pipeline" in entry:
                                        pipeline = entry["CircleCI_Pipeline"]

                                if dhapi.is_not_empty(deployenv):
                                    applist.append({"appid": appid, "appname": appname, "deployenv": deployenv, "circleci_pipeline": pipeline})

            for entry in applist:
                appid = entry["appid"]
                appname = entry["appname"]
                deployenv = entry["deployenv"]
                pipeline = entry["circleci_pipeline"]

                print("Deploying " + appname + " to " + deployenv)
                data = dhapi.deploy_application_by_appid(dhurl, cookies, appid, deployenv)

                deployid = data[0]
                if deployid < 0:
                    print(data[1])
                    sys.exit(1)

                print("Fetching Logs for " + str(deployid))
                data = dhapi.get_logs(dhurl, cookies, deployid)

                print(data[1])
                if data[0]:
                    print("Successful")
                    if dhapi.is_not_empty(pipeline):
                        data = dhapi.run_circleci_pipeline(pipeline)
                        pprint(data)
                else:
                    print("Failed")
                    retcode = retcode + 1

            if retcode == 0:
                sys.exit(0)
            else:
                sys.exit(1)
        else:
            payload = ""
            with open(deploydata, "r") as fin_data:
                payload = fin_data.read()

            data = {}
            if dhapi.is_not_empty(payload):
                data = json.loads(payload)

            if dhapi.is_empty(appname):
                appname = data.get("application", "")
            else:
                data["application"] = appname

            if dhapi.is_empty(appversion):
                appversion = data.get("appversion", "")
            else:
                data["appversion"] = appversion

            if kvconfig is None:
                kvconfig = data.get("kvconfig", "")

            pipeline = data.get("circleci_pipeline", "")

            appversion = dhapi.clean_name(appversion)
            data["appversion"] = appversion

            full_appname = appname
            if dhapi.is_not_empty(appversion):
                full_appname = full_appname + ";" + appversion

            res = dhapi.get_application(dhurl, cookies, full_appname, "latest", False)
            latest_appid = res[0]
            if latest_appid > 0:
                full_appname = dhapi.get_application_name(dhurl, cookies, latest_appid)
            data["application"] = full_appname
            data.pop("appversion", None)

            compname = data.get("config_component", None)
            compvariant = data.get("environment", "")
            compversion = ""

            if compname is None:
                complist = data.get("compversion", [])
                if len(complist) > 0:
                    compname = complist[0]
                    compvariant = ""
                    compversion = ""

            if dhapi.is_empty(deployenv):
                environment = data.get("environment", "")
            else:
                environment = deployenv
                data["environment"] = environment

            if not logdeployment:
                data["skipdeploy"] = "Y"

            with open(deploydata, "w") as fpsave:
                json.dump(data, fpsave)

            # Check if just logging deployment
            if logdeployment:
                data = dhapi.log_deploy_application(dhurl, cookies, deploydata)
                deployid = data.get("deployid", -1)
                appname = data.get("application", appname)
                print("Logged Deployment for " + appname + " to " + environment)
            else:
                data = dhapi.log_deploy_application(dhurl, cookies, deploydata)
                appid = data.get("appid", -1)
                appname = data.get("application", appname)

                print("Deploying " + appname + " to " + deployenv)
                data = dhapi.deploy_application_by_appid(dhurl, cookies, appid, deployenv)

                deployid = data[0]
                if deployid < 0:
                    print(data[1])
                    sys.exit(1)

                print("Fetching Logs for " + str(deployid))
                data = dhapi.get_logs(dhurl, cookies, deployid)

                print(data[1])
                if data[0]:
                    print("Successful")
                    if dhapi.is_not_empty(pipeline):
                        data = dhapi.run_circleci_pipeline(pipeline)
                        pprint(data)
                else:
                    print("Failed")
                    retcode = retcode + 1

            lcompattr = {}
            for attr in compattr:
                key, value = attr.split(":", 1)
                lcompattr[key.lower()] = value

            helmrepo = lcompattr.get("chartrepo", "")
            chartname = lcompattr.get("chart")
            chartversion = lcompattr.get("chartversion", "")
            chartvalues = lcompattr.get("chartvalues", "")
            helmrepouser = lcompattr.get("helmrepouser", "")
            helmrepopass = lcompattr.get("helmrepopass", "")
            helmrepourl = lcompattr.get("chartrepourl", "")
            dockeruser = lcompattr.get("dockeruser", lcompattr.get("helmrepouser", ""))
            dockerpass = lcompattr.get("dockerpass", lcompattr.get("helmrepopass", ""))
            helmtemplate = lcompattr.get("helmtemplate", "")
            helmopts = lcompattr.get("helmopts", "")

            if deployid > 0 and dhapi.is_not_empty(helmtemplate) and dhapi.is_not_empty(helmrepo) and dhapi.is_not_empty(helmrepourl):
                # fetch component and get attributes
                dhapi.upload_helm(
                    dhurl, cookies, compname, chartname, chartversion, chartvalues, helmrepo, helmrepouser, helmrepopass, helmrepourl, helmopts, deployid, dockeruser, dockerpass, helmtemplate
                )

            #            os.remove(deploydata)

            if "." in compvariant:
                compvariant = compvariant.split(".")[-1]

            if compautoinc is None:
                compautoinc = "Y"

            if compname is not None and dhapi.is_not_empty(kvconfig):
                print("Load config from " + kvconfig)
                dhapi.set_kvconfig(dhurl, cookies, kvconfig, appname, appversion, appautoinc, compname, compvariant, compversion, compautoinc, kind, environment, crdatasource, changerequest)

            if retcode == 0:
                sys.exit(0)
            else:
                sys.exit(1)

    elif action.lower() == "updatecomp":
        if dhapi.is_empty(dhurl):
            print("--dhurl is required")
            sys.exit(1)

        if dhapi.is_empty(dhuser):
            print("--dhuser is required")
            sys.exit(1)

        if dhapi.is_empty(dhpass):
            print("--dhpass is required")
            sys.exit(1)

        if dhapi.is_empty(compname):
            print("--compname is required")
            sys.exit(1)

        if dhapi.is_empty(compvariant):
            compvariant = ""

        if dhapi.is_empty(compvariant) and "-v" in compversion:
            compvariant = compversion.split("-v")[0]
            compversion = "v" + compversion.split("-v")[1]

        if dhapi.is_empty(compvariant) and "-V" in compversion:
            compvariant = compversion.split("-V")[0]
            compversion = "v" + compversion.split("-V")[1]

        saveappver = ""
        if dhapi.is_not_empty(appversion):
            saveappver = appversion

        deploydata_dict = {}
        deploydata_dict["application"] = ""
        deploydata_dict["compversion"] = []
        deploydata_dict["rc"] = 0

        if dhapi.is_not_empty(deploydatasave):
            payload = ""
            if os.path.isfile(deploydatasave):
                with open(deploydatasave, "r") as fin_data:
                    payload = fin_data.read()

            data = {}
            if dhapi.is_not_empty(payload):
                data = json.loads(payload)
                deploydata_dict["application"] = data["application"]
                worklist = deploydata_dict["compversion"]
                worklist.extend(data["compversion"])
                deploydata_dict["compversion"] = worklist
                deploydata_dict["rc"] = data["rc"]

        retcode = 0
        cnt = 1
        while True:
            data = dhapi.get_component(dhurl, cookies, compname, "", "", True, True)
            parent_compid = data[0]

            if parent_compid < 0:
                data = dhapi.get_component(dhurl, cookies, compname, compvariant, "", True, True)
                parent_compid = data[0]

            # create component version

            if parent_compid < 0:
                print("Creating Parent Component")
                parent_compid = dhapi.new_component_version(dhurl, cookies, compname, compvariant, "", kind, None, compautoinc)

            print("Creating Component")
            shortname = compname
            if "." in shortname:
                shortname = shortname.split(".")[-1]

            compid = dhapi.new_component_version(dhurl, cookies, compname, compvariant, compversion, kind, None, compautoinc)
            compname = dhapi.get_component_name(dhurl, cookies, compid)
            compversion = ""
            compvariant = ""

            worklist = deploydata_dict["compversion"]
            worklist.append(compname)
            deploydata_dict["compversion"] = worklist

            print("Creation Done: " + compname)

            print("Updating Component Attributes\n")
            for attr in compattr:
                if ":" in attr:
                    key = attr.split(":")[0]
                    value = ":".join(attr.split(":")[1:])
                else:
                    key = attr
                    value = ""

                if "@sha256:" in value:
                    value = value.split("@sha256:")[1]

                if value.startswith("@"):
                    value = value[1:]
                    if os.path.exists(value):
                        value = open(value, "r").read().replace("\n", "")
                        attrs[key] = value
                    else:
                        attrs[key] = ""
                else:
                    attrs[key] = value

            now = datetime.now()
            date_time = now.strftime("%c")

            attrs["BuildUrl"] = attrs.get(
                "BuildUrl", os.getenv("BUILD_URL", os.getenv("GITHUB_SERVER_URL", "") + "/" + os.getenv("GITHUB_REPOSITORY", "") + "/actions/runs/" + os.getenv("GITHUB_RUN_ID", ""))
            )
            attrs["BuildId"] = attrs.get("BuildId", os.getenv("BUILD_ID", os.getenv("BUILD_NUMBER", os.getenv("BUILD_NUM", os.getenv("GITHUB_RUN_ID", "")))))
            attrs["BuildNumber"] = attrs.get("BuildNumber", os.getenv("BUILD_NUMBER", os.getenv("BUILD_NUM", os.getenv("GITHUB_RUN_NUMBER", ""))))
            attrs["DockerBuildDate"] = attrs.get("DockerBuildDate", date_time)

            attrs["DockerRepo"] = attrs.get("DockerRepo", os.getenv("DOCKERREPO", os.getenv("IMAGE_TAG", "")))
            attrs["DockerSha"] = attrs.get("DockerSha", os.getenv("DOCKERSHA", os.getenv("DIGEST", "")))
            attrs["DockerTag"] = attrs.get("DockerTag", os.getenv("DOCKERTAG", os.getenv("IMAGE_TAG", "")))

            if attrs.get("DockerRepo", None) is not None:
                dockerrepo = attrs.get("DockerRepo")
                if ":" in dockerrepo:
                    parts = dockerrepo.split(":")
                    attrs["DockerRepo"] = parts[0]
                    if attrs.get("DockerTag", None) in None:
                        attrs["DockerTag"] = parts[1]

            attrs["GitBranch"] = attrs.get("GitBranch", os.getenv("GIT_BRANCH", ""))
            attrs["GitBranchCreateCommit"] = attrs.get("GitBranchCreateCommit", os.getenv("GIT_BRANCH_CREATE_COMMIT", ""))
            attrs["GitBranchCreateTimestamp"] = attrs.get("GitBranchCreateTimestamp", os.getenv("GIT_BRANCH_CREATE_TIMESTAMP", ""))
            attrs["GitBranchParent"] = attrs.get("GitBranchParent", os.getenv("GIT_BRANCH_PARENT", ""))
            attrs["GitCommit"] = attrs.get("GitCommit", os.getenv("GIT_COMMIT", os.getenv("SHORT_SHA", "")))
            attrs["GitCommitAuthors"] = attrs.get("GitCommitAuthors", os.getenv("GIT_COMMIT_AUTHORS", ""))
            attrs["GitCommittersCnt"] = attrs.get("GitCommittersCnt", os.getenv("GIT_COMMITTERS_CNT", ""))
            attrs["GitCommitTimestamp"] = attrs.get("GitCommitTimestamp", os.getenv("GIT_COMMIT_TIMESTAMP", ""))
            attrs["GitContribPercentage"] = attrs.get("GitContribPercentage", os.getenv("GIT_CONTRIB_PERCENTAGE", ""))
            attrs["GitLinesAdded"] = attrs.get("GitLinesAdded", os.getenv("GIT_LINES_ADDED", ""))
            attrs["GitLinesDeleted"] = attrs.get("GitLinesDeleted", os.getenv("GIT_LINES_DELETED", ""))
            attrs["GitLinesTotal"] = attrs.get("GitLinesTotal", os.getenv("GIT_LINES_TOTAL", ""))
            attrs["GitOrg"] = attrs.get("GitOrg", os.getenv("GIT_ORG", ""))

            if attrs.get("GitRepo", None) is None:
                if "/" in os.getenv("GIT_URL", ""):
                    attrs["GitRepo"] = "/".join(os.getenv("GIT_URL", "").split("/")[-2:]).replace(".git", "")

            attrs["GitRepo"] = attrs.get("GitRepo", os.getenv("GIT_REPO", ""))
            attrs["GitRepoProject"] = attrs.get("GitRepoProject", os.getenv("GIT_REPO_PROJECT", ""))

            gittag = attrs.get("GitTag", None)
            if dhapi.is_empty(gittag) and attrs.get("GitBranch", None) is not None:
                attrs["GitTag"] = attrs.get("GitBranch", os.getenv("GIT_BRANCH", ""))

            attrs["GitTotalCommittersCnt"] = attrs.get("GitTotalCommittersCnt", os.getenv("GIT_TOTAL_COMMITTERS_CNT", ""))
            attrs["GitUrl"] = attrs.get("GitUrl", os.getenv("GIT_URL", ""))

            attrs["JobTriggeredBy"] = attrs.get("JobTriggeredBy", attrs.get("JobTriggerdBy", ""))

            lcompattr = {}
            for key, val in attrs.items():
                lcompattr[key.lower()] = val

            chartpath = None
            if lcompattr.get("chart", None) is None:
                if os.path.exists("helm/" + shortname + "/Chart.yaml"):
                    attrs["Chart"] = "helm/" + shortname
                    chartpath = "helm/" + shortname + "/Chart.yaml"
                elif os.path.exists("helm/" + shortname + "/Chart.yml"):
                    attrs["Chart"] = "helm/" + shortname
                    chartpath = "helm/" + shortname + "/Chart.yml"
                elif os.path.exists("chart/" + shortname + "/Chart.yaml"):
                    attrs["Chart"] = "chart/" + shortname
                    chartpath = "chart/" + shortname + "/Chart.yaml"
                elif os.path.exists("chart/" + shortname + "/Chart.yml"):
                    attrs["Chart"] = "chart/" + shortname
                    chartpath = "chart/" + shortname + "/Chart.yml"
                elif os.path.exists("charts/" + shortname + "/Chart.yaml"):
                    attrs["Chart"] = "charts/" + shortname
                    chartpath = "charts/" + shortname + "/Chart.yaml"
                elif os.path.exists("charts/" + shortname + "/Chart.yml"):
                    attrs["Chart"] = "charts/" + shortname
                    chartpath = "charts/" + shortname + "/Chart.yml"

            if attrs.get("Chart", None) is not None and chartpath is not None:
                chartdata = yaml.safe_load(Path(chartpath).read_text())
                attrs["ChartVersion"] = chartdata.get("version", "")

            attrs.pop("Readme", None)
            attrs.pop("readme", None)
            attrs.pop("README", None)
            attrs.pop("ReadMe", None)
            attrs.pop("Swagger", None)
            attrs.pop("swagger", None)
            attrs.pop("SWAGGER", None)
            attrs.pop("License", None)
            attrs.pop("license", None)
            attrs.pop("LICENSE", None)
            attrs.pop("GradleLicense", None)
            attrs.pop("gradlelicense", None)
            attrs.pop("GRADLELICENSE", None)

            pprint(attrs)
            print("")

            print("Updating Change Requests\n")

            data = dhapi.update_component_attrs(dhurl, cookies, compname, compvariant, compversion, attrs, crdatasource, changerequest)
            print("Attribute Update Done")

            if lcompattr.get("readme", None) is None:
                if os.path.exists("README"):
                    lcompattr["readme"] = "README"
                elif os.path.exists("README.md"):
                    lcompattr["readme"] = "README.md"
                elif os.path.exists("readme"):
                    lcompattr["readme"] = "readme"
                elif os.path.exists("readme.md"):
                    lcompattr["readme"] = "readme.md"

            if lcompattr.get("license", None) is None:
                if os.path.exists("LICENSE"):
                    lcompattr["license"] = "LICENSE"
                elif os.path.exists("LICENSE.md"):
                    lcompattr["license"] = "LICENSE.md"
                elif os.path.exists("license"):
                    lcompattr["license"] = "license"
                elif os.path.exists("license.md"):
                    lcompattr["license"] = "license.md"

            if lcompattr.get("swagger", None) is None:
                if os.path.exists("swagger.yaml"):
                    lcompattr["swagger"] = "swagger.yaml"
                elif os.path.exists("swagger.yml"):
                    lcompattr["swagger"] = "swagger.yml"
                elif os.path.exists("swagger.json"):
                    lcompattr["swagger"] = "swagger.json"

            if lcompattr.get("readme", None) is not None:
                if os.path.exists(lcompattr.get("readme")):
                    dhapi.post_textfile(dhurl, cookies, compid, lcompattr.get("readme", ""), "readme")
                else:
                    print("WARNING: ReadMe not found:" + lcompattr.get("readme"))

            if lcompattr.get("license", None) is not None:
                if os.path.exists(lcompattr.get("license")):
                    dhapi.post_textfile(dhurl, cookies, compid, lcompattr.get("license", ""), "license")
                else:
                    print("WARNING: License not found:" + lcompattr.get("license"))

            if lcompattr.get("swagger", None) is not None:
                if os.path.exists(lcompattr.get("swagger")):
                    dhapi.post_textfile(dhurl, cookies, compid, lcompattr.get("swagger", ""), "swagger")
                else:
                    print("WARNING: Swagger not found:" + lcompattr.get("swagger"))

            glic = None
            if lcompattr.get("gradlelicense", None) is not None:
                if os.path.exists(lcompattr.get("gradlelicense")):
                    # Opening JSON file
                    with open(lcompattr.get("gradlelicense")) as gradle_license:
                        glic = json.load(gradle_license)
                else:
                    print("WARNING: Gradle License not found:" + lcompattr.get("gradlelicense"))

            if deppkg:
                for filename in deppkg:
                    dhapi.update_deppkgs(dhurl, cookies, compid, filename, glic)

            if consumes is not None:
                file = open(consumes)
                payload = file.read().replace("\n", " ")
                file.close()
                print("Adding Consuming End Points")
                dhapi.post_json(dhurl + "/dmadminweb/API2/consumes/" + str(compid), payload, cookies)

            if provides is not None:
                file = open(provides)
                payload = file.read().replace("\n", " ")
                file.close()
                print("Adding Providing End Points")
                dhapi.post_json(dhurl + "/dmadminweb/API2/provides/" + str(compid), payload, cookies)

            applist = []

            print("AppName=" + str(appname) + " AppAutoInc=" + str(appautoinc))
            if dhapi.is_empty(appname) and dhapi.is_not_empty(appautoinc):  # derive appname and inc
                data = dhapi.get_component_fromid(dhurl, cookies, parent_compid)

                if data is not None and "result" in data:
                    result = data["result"]
                    if result.get("applications", None) is not None:
                        data = result.get("applications", None)
                        for app in data:
                            appname = app.get("domain", "") + "." + app.get("name", "")
                            appid = app.get("id", "")
                            appdata = dhapi.get_application_fromid(dhurl, cookies, appid, "latest")
                            latest_appid = appdata[0]
                            # latest_appname = appdata[1]
                            if appid == latest_appid:
                                if appname is not None:
                                    applist.append(appname)
            else:
                if dhapi.is_not_empty(appname):
                    applist.append(appname)

            for appname in applist:
                print(appname)
                if dhapi.is_not_empty(saveappver):
                    appversion = saveappver
                else:
                    appversion = ""

                if dhapi.is_empty(appversion):
                    parts = appname.split(";")
                    if len(parts) == 3:
                        appname = parts[0] + ";" + parts[1]
                        appversion = parts[2]

                if dhapi.is_empty(appversion):
                    parts = appname.split(";")
                    if len(parts) == 3:
                        appname = parts[0] + ";" + parts[1]
                        appversion = parts[2]

                if dhapi.is_empty(appversion):
                    appversion = ""

                print("Application Version Definition:'" + str(appname) + "' '" + appversion + "' AppAutoInc:" + str(appautoinc))
                data = dhapi.new_application(dhurl, cookies, appname, appversion, appautoinc, envs, compid)
                appid = data[0]
                appname = dhapi.get_application_name(dhurl, cookies, appid)
                print("Using Application Version: " + appname)

                deploydata_dict["application"] = appname

                print("Assigning Component Version to Application Version " + appname)

                data = dhapi.add_compver_to_appver(dhurl, cookies, appid, compid)
                print("Assignment Done")

                if dhapi.is_not_empty(deployenv):
                    print("Deploying " + appname + " to " + deployenv)
                    data = dhapi.deploy_application_by_appid(dhurl, cookies, appid, deployenv)

                    deployid = data[0]
                    if deployid < 0:
                        print(data[1])
                        sys.exit(1)

                    print("Fetching Logs for " + str(deployid))
                    data = dhapi.get_logs(dhurl, cookies, deployid)

                    print(data[1])
                    if data[0]:
                        print("Successful")
                    else:
                        print("Failed")
                        retcode = retcode + 1

            compname = os.environ.get("COMPONENT_NAME_" + str(cnt), None)
            compversion = os.environ.get("COMPONENT_VERSION_" + str(cnt), None)
            appname = os.environ.get("COMPONENT_APPLICATION_" + str(cnt), None)
            appversion = os.environ.get("COMPONENT_APPLICATION_VERSION_" + str(cnt), None)

            cnt = cnt + 1

            if compname is None:  # leave loop if no more components defined in env
                break

        if dhapi.is_not_empty(deploydatasave):
            # pprint(deploydata_dict)
            with open(deploydatasave, "w") as fpsave:
                json.dump(deploydata_dict, fpsave)

        if retcode == 0:
            sys.exit(0)
        else:
            sys.exit(1)
    elif action.lower() == "kv":
        if dhapi.is_empty(dhurl):
            print("--dhurl is required")
            sys.exit(1)

        if dhapi.is_empty(dhuser):
            print("--dhuser is required")
            sys.exit(1)

        if dhapi.is_empty(dhpass):
            print("--dhpass is required")
            sys.exit(1)

        if dhapi.is_empty(kvconfig) and dhapi.is_empty(deploydata):
            print("--kvconfig is required")
            sys.exit(1)

        if dhapi.is_not_empty(deploydata):
            with open(deploydata, "r") as fin_data:
                payload = fin_data.read()

            data = None
            if dhapi.is_not_empty(payload):
                data = json.loads(payload)

            appname = data.get("application", "")
            appversion = data.get("appversion", "")
            compname = data.get("config_component", None)
            compvariant = data.get("environment", "")
            compversion = ""
            environment = data.get("environment", "")

            if kvconfig is None:
                kvconfig = data.get("kvconfig", "")

            print("Config for " + appname + " to " + compvariant)

        if dhapi.is_empty(compname):
            print("--compname is required")
            sys.exit(1)

        if "." in compvariant:
            compvariant = compvariant.split(".")[-1]

        if compautoinc is None:
            compautoinc = "Y"

        dhapi.set_kvconfig(dhurl, cookies, kvconfig, appname, appversion, appautoinc, compname, compvariant, compversion, compautoinc, kind, environment, crdatasource, changerequest)

    elif action.lower() == "assign":
        if dhapi.is_empty(dhurl):
            print("--dhurl is required")
            sys.exit(1)

        if dhapi.is_empty(dhuser):
            print("--dhuser is required")
            sys.exit(1)

        if dhapi.is_empty(dhpass):
            print("--dhpass is required")
            sys.exit(1)

        if dhapi.is_empty(appname):
            print("--appname is required")
            sys.exit(1)

        if dhapi.is_empty(compname):
            print("--compname is required")
            sys.exit(1)

        if dhapi.is_empty(compvariant):
            compvariant = ""

        if dhapi.is_empty(compvariant) and "-v" in compversion:
            compvariant = compversion.split("-v")[0]
            compversion = "v" + compversion.split("-v")[1]

        if dhapi.is_empty(compvariant) and "-V" in compversion:
            compvariant = compversion.split("-V")[0]
            compversion = "v" + compversion.split("-V")[1]

        saveappver = ""
        if dhapi.is_not_empty(appversion):
            saveappver = appversion

        assign_completed = []

        deploydata_dict = {}

        if dhapi.is_not_empty(deploydatasave):
            payload = ""
            if os.path.isfile(deploydatasave):
                with open(deploydatasave, "r") as fin_data:
                    payload = fin_data.read()

                if dhapi.is_not_empty(payload):
                    deploydata_dict = json.loads(payload)

        cnt = 1
        while True:
            # create component version
            [compid, name] = dhapi.get_component(dhurl, cookies, compname, compvariant, compversion, True, False)

            if compid > 0:
                print("Found " + name)

                if dhapi.is_not_empty(saveappver):
                    appversion = saveappver

                if dhapi.is_empty(appversion):
                    parts = appname.split(";")
                    if len(parts) == 3:
                        appname = parts[0] + ";" + parts[1]
                        appversion = parts[2]

                if dhapi.is_empty(appversion):
                    parts = appname.split(";")
                    if len(parts) == 3:
                        appname = parts[0] + ";" + parts[1]
                        appversion = parts[2]

                if dhapi.is_empty(appversion):
                    appversion = ""

                data = dhapi.get_application(dhurl, cookies, appname, appversion, True)
                appid = data[0]

                if appid < 0:
                    print("Creating Application Version '" + str(appname) + "' '" + appversion + "'")
                    data = dhapi.new_application(dhurl, cookies, appname, appversion, appautoinc, envs, compid)
                    appid = data[0]
                    appname = dhapi.get_application_name(dhurl, cookies, appid)
                    print("Creation Done: " + appname)

                if appname not in [assign_completed]:
                    dhapi.assign_app_to_env(dhurl, cookies, appname, envs)
                    assign_completed.append(appname)

                full_appname = dhapi.get_application_name(dhurl, cookies, appid)
                full_compname = dhapi.get_component_name(dhurl, cookies, compid)
                print("Assigning Component Version " + name + " to Application Version " + full_appname)
                deploydata_dict["application"] = full_appname
                worklist = deploydata_dict.get("compversion", [])
                worklist.extend([full_compname])
                deploydata_dict["compversion"] = worklist

                data = dhapi.add_compver_to_appver(dhurl, cookies, appid, compid)
                print("Assignment Done")

            compname = os.environ.get("COMPONENT_NAME_" + str(cnt), None)
            compversion = os.environ.get("COMPONENT_VERSION_" + str(cnt), None)
            appname = os.environ.get("COMPONENT_APPLICATION_" + str(cnt), None)
            appversion = os.environ.get("COMPONENT_APPLICATION_VERSION_" + str(cnt), None)

            cnt = cnt + 1

            if compname is None:  # leave loop if no more components defined in env
                break

        if dhapi.is_not_empty(deploydatasave):
            # pprint(deploydata_dict)
            with open(deploydatasave, "w") as fpsave:
                json.dump(deploydata_dict, fpsave)

    elif action.lower() == "approve":
        if dhapi.is_empty(dhurl):
            print("--dhurl is required")
            sys.exit(1)

        if dhapi.is_empty(dhuser):
            print("--dhuser is required")
            sys.exit(1)

        if dhapi.is_empty(dhpass):
            print("--dhpass is required")
            sys.exit(1)

        if dhapi.is_empty(appname):
            print("--appname is required")
            sys.exit(1)

        if dhapi.is_empty(appversion):
            parts = appname.split(";")
            if len(parts) == 3:
                appname = parts[0] + ";" + parts[1]
                appversion = parts[2]

        print("Approving " + appname + " " + appversion)
        data = dhapi.approve_application(dhurl, cookies, appname, appversion)
        print(data[1])
    elif action.lower() == "move":
        if dhapi.is_empty(appname):
            print("--appname is required")
            sys.exit(1)

        if dhapi.is_empty(from_domain):
            print("--from_domain is required")
            sys.exit(1)

        if dhapi.is_empty(task):
            print("--task is required")
            sys.exit(1)

        if dhapi.is_empty(appversion):
            parts = appname.split(";")
            if len(parts) == 3:
                appname = parts[0] + ";" + parts[1]
                appversion = parts[2]

        print("Moving " + appname + " " + appversion + " from " + from_domain)
        data = dhapi.move_application(dhurl, cookies, appname, appversion, from_domain, task)
        print(data[1])
    elif action.lower() == "cluster":
        if dhapi.is_empty(appname):
            print("--appname is required")
            sys.exit(1)

        if dhapi.is_empty(appversion):
            parts = appname.split(";")
            if len(parts) == 3:
                appname = parts[0] + ";" + parts[1]
                appversion = parts[2]

        if dhapi.is_empty(cluster_json):
            print("--json is required")
            sys.exit(1)

        if dhapi.is_empty(todom):
            print("--tomdom is required")
            sys.exit(1)

        print("Syncing cluster from " + cluster_json)
        dhapi.import_cluster(dhurl, cookies, todom, appname, appversion, appautoinc, deployenv, crdatasource, [], cluster_json, msname, msbranch)

    elif action.lower() == "envscript":
        if dhapi.is_empty(envvars):
            print("--envvars is required")
            sys.exit(1)

        print("Creating env shell script from " + envvars)
        envscript(dhurl, cookies, envvars, envvars_sh)
    elif action.lower() == "export":
        if dhapi.is_empty(dhurl):
            print("--dhurl is required")
            sys.exit(1)

        if dhapi.is_empty(dhuser):
            print("--dhuser is required")
            sys.exit(1)

        if dhapi.is_empty(dhpass):
            print("--dhpass is required")
            sys.exit(1)

        if dhapi.is_empty(fromdom):
            print("--fromdom is required")
            sys.exit(1)

        allobjs = {}
        filterdict(dhurl, cookies, "users", fromdom, allobjs)
        filterdict(dhurl, cookies, "groups", fromdom, allobjs)
        filterdict(dhurl, cookies, "comptypes", fromdom, allobjs)
        filterdict(dhurl, cookies, "credentials", fromdom, allobjs)
        filterdict(dhurl, cookies, "endpoints", fromdom, allobjs)
        filterdict(dhurl, cookies, "datasources", fromdom, allobjs)
        filterdict(dhurl, cookies, "tasks", fromdom, allobjs)
        filterdict(dhurl, cookies, "engines", fromdom, allobjs)
        filterdict(dhurl, cookies, "repositories", fromdom, allobjs)
        filterdict(dhurl, cookies, "environments", fromdom, allobjs)
        filterdict(dhurl, cookies, "components", fromdom, allobjs)
        filterdict(dhurl, cookies, "applications", fromdom, allobjs)
        filterdict(dhurl, cookies, "releases", fromdom, allobjs)

        jstr = json.dumps(allobjs, indent=2)
        print(jstr)
    elif action.lower() == "import":
        if dhapi.is_empty(dhurl):
            print("--dhurl is required")
            sys.exit(1)

        if dhapi.is_empty(dhuser):
            print("--dhuser is required")
            sys.exit(1)

        if dhapi.is_empty(dhpass):
            print("--dhpass is required")
            sys.exit(1)

        if dhapi.is_empty(fromdom):
            print("--fromdom is required")
            sys.exit(1)

        if dhapi.is_empty(todom):
            print("--todom is required")
            sys.exit(1)

        if dhapi.is_empty(importfile):
            print("--importfile is required")
            sys.exit(1)

        file = open(importfile, "r")
        all_of_it = file.read()
        file.close()
        jstr = re.sub(fromdom, todom, all_of_it, flags=re.IGNORECASE)
        allobjs = json.loads(jstr)

        importdict(dhurl, cookies, "users", allobjs)
        importdict(dhurl, cookies, "groups", allobjs)
        importdict(dhurl, cookies, "comptypes", allobjs)
        importdict(dhurl, cookies, "credentials", allobjs)
        importdict(dhurl, cookies, "endpoints", allobjs)
        importdict(dhurl, cookies, "datasources", allobjs)
        importdict(dhurl, cookies, "tasks", allobjs)
        importdict(dhurl, cookies, "engines", allobjs)
        importdict(dhurl, cookies, "repositories", allobjs)
        importdict(dhurl, cookies, "environments", allobjs)
        importdict(dhurl, cookies, "components", allobjs)
        importdict(dhurl, cookies, "applications", allobjs)
        importdict(dhurl, cookies, "releases", allobjs)
    else:
        print("Action is not defined.  Use deploy, envscript, approve, move or updatecomp for action")
        sys.exit(1)


def envscript(dhurl, cookies, envvars, envvars_sh):  # noqa: C901
    """
    Add the variabes from the envvars toml file to the shell script.

    Args:
        dhurl (string): url for the server
        cookies (string): cookies from the login
        envvars (string): file name for the environment toml file
        envvars_sh (string): the shell script to update with var from toml file

    Returns:
        no data returned.  Output is in the shell script file.
    """

    if dhapi.is_empty(envvars_sh):
        envvars_sh = "cloudbuild.sh"

    fp_script = open(envvars_sh, "a")

    lines = subprocess.run(["cat", envvars], check=False, stdout=subprocess.PIPE).stdout.decode("utf-8")

    mapping = os.environ

    if mapping.get("BLDDATE", None) is None:
        now = datetime.now()
        mapping["BLDDATE"] = now.strftime("%c")
    else:
        mapping["BLDDATE"] = mapping.get("BLDDATE").strip('"')

    # if the buildnum, git_repo, git_url, git_commit_time, git_lines not in os.environ and not in attrvars and not in export then export
    run_fetch = True
    if mapping.get("SHORT_SHA", None) is None:
        mapping["SHORT_SHA"] = dhapi.run_git("git log --oneline -n 1 | cut -d' '  -f1")

    if mapping.get("GIT_COMMIT", None) is None:
        mapping["GIT_COMMIT"] = dhapi.run_git("git log --oneline -n 1 | cut -d' '  -f1")

    if mapping.get("BUILDNUM", None) is None:
        if run_fetch:
            dhapi.run_git("git fetch --unshallow")
            run_fetch = False
        mapping["BUILDNUM"] = dhapi.run_git('git log --oneline | wc -l | tr -d " "')

    if mapping.get("GIT_REPO", None) is None:
        if run_fetch:
            dhapi.run_git("git fetch --unshallow")
            run_fetch = False
        mapping["GIT_REPO"] = dhapi.run_git("git config --get remote.origin.url | awk -F/ '{print $(NF-1)\"/\"$NF}'| sed 's/.git$//'")

    if mapping.get("GIT_REPO_PROJECT", None) is None:
        if run_fetch:
            dhapi.run_git("git fetch --unshallow")
            run_fetch = False
        mapping["GIT_REPO_PROJECT"] = dhapi.run_git("git config --get remote.origin.url | awk -F/ '{print $(NF-1)}'")

    if mapping.get("GIT_ORG", None) is None:
        if run_fetch:
            dhapi.run_git("git fetch --unshallow")
            run_fetch = False
        mapping["GIT_ORG"] = dhapi.run_git("git config --get remote.origin.url | awk -F/ '{print $NF}'| sed 's/.git$//'")

    if mapping.get("GIT_URL", None) is None:
        if run_fetch:
            dhapi.run_git("git fetch --unshallow")
            run_fetch = 0
        mapping["GIT_URL"] = dhapi.run_git("git config --get remote.origin.url")

    if mapping.get("GIT_BRANCH", None) is None:
        if run_fetch:
            dhapi.run_git("git fetch --unshallow")
            run_fetch = 0
        mapping["GIT_BRANCH"] = dhapi.run_git("git rev-parse --abbrev-ref HEAD")

    if mapping.get("GIT_COMMIT_TIMESTAMP", None) is None:
        if run_fetch:
            dhapi.run_git("git fetch --unshallow")
            run_fetch = 0
        mapping["GIT_COMMIT_TIMESTAMP"] = dhapi.run_git("git log --pretty='format:%cd' " + mapping.get("SHORT_SHA", "") + " | head -1")

    if mapping.get("GIT_BRANCH_PARENT", None) is None:
        if run_fetch:
            dhapi.run_git("git fetch --unshallow")
            run_fetch = 0
        mapping["GIT_BRANCH_PARENT"] = dhapi.run_git('git show-branch -a 2>/dev/null | sed "s/].*//" | grep "\\*" | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed "s/^.*\\[//"')
        print(mapping["GIT_BRANCH_PARENT"])

    if mapping.get("GIT_BRANCH_CREATE_COMMIT", None) is None:
        if run_fetch:
            dhapi.run_git("git fetch --unshallow")
            run_fetch = 0
        mapping["GIT_BRANCH_CREATE_COMMIT"] = dhapi.run_git(
            "git log --oneline --reverse " + mapping.get("GIT_BRANCH_PARENT", "main") + ".." + mapping.get("GIT_BRANCH") + " | head -1 | awk -F' ' '{print $1}'"
        )

    if mapping.get("GIT_BRANCH_CREATE_TIMESTAMP", None) is None:
        if run_fetch:
            dhapi.run_git("git fetch --unshallow")
            run_fetch = 0
        mapping["GIT_BRANCH_CREATE_TIMESTAMP"] = dhapi.run_git("git log --pretty='format:%cd' " + mapping.get("GIT_BRANCH_CREATE_COMMIT", "HEAD") + " | head -1")

    if mapping.get("GIT_COMMIT_AUTHORS", None) is None:
        if run_fetch:
            dhapi.run_git("git fetch --unshallow")
            run_fetch = 0
        mapping["GIT_COMMIT_AUTHORS"] = dhapi.run_git(
            "git rev-list --remotes --pretty --since='"
            + mapping.get("GIT_BRANCH_CREATE_TIMESTAMP", "")
            + "' --until='"
            + mapping.get("GIT_COMMIT_TIMESTAMP", "")
            + "' | grep -i 'Author:' | grep -v dependabot | awk -F'[:<>]' '{print $3}' | sed 's/^ //' | sed 's/ $//' | sort -u | tr '\n' ',' | sed 's/,$//'"
        )

    if mapping.get("GIT_LINES_TOTAL", None) is None:
        if run_fetch:
            dhapi.run_git("git fetch --unshallow")
            run_fetch = 0
        mapping["GIT_LINES_TOTAL"] = dhapi.run_git("wc -l $(git ls-files) | grep total | awk -F' ' '{print $1}'")

    if mapping.get("BASENAME", None) is None:
        mapping["BASENAME"] = os.path.basename(os.getcwd())

    template = Template(lines)
    lines = template.safe_substitute(**mapping)

    vardict = qtoml.loads(lines)

    attrvars = vardict.get("Attributes", {})
    for key, val in attrvars.items():
        vardict[key] = val

    if mapping.get("GIT_TOTAL_COMMITTERS_CNT", None) is None and attrvars.get("TotalCommittersCnt", attrvars.get("GitTotalCommittersCnt", None)) is not None:
        mapping["GIT_TOTAL_COMMITTERS_CNT"] = attrvars.get("TotalCommittersCnt", attrvars.get("GitTotalCommittersCnt", None))

    if mapping.get("GIT_COMMITTERS_CNT", None) is None and mapping.get("GIT_COMMIT_AUTHORS", None) is not None:
        mapping["GIT_COMMITTERS_CNT"] = str(len(mapping.get("GIT_COMMIT_AUTHORS").split(",")))

    if mapping.get("GIT_COMMITTERS_CNT", None) is not None and mapping.get("GIT_TOTAL_COMMITTERS_CNT", None) is not None:
        mapping["GIT_CONTRIB_PERCENTAGE"] = str(round(int(mapping.get("GIT_COMMITTERS_CNT")) / int(mapping.get("GIT_TOTAL_COMMITTERS_CNT")) * 100))
    else:
        mapping["GIT_CONTRIB_PERCENTAGE"] = "0"

    export_vars = vardict.get("Export", {})

    for key, val in mapping.items():
        if export_vars.get(key, None) is None:
            export_vars[key] = val

        if vardict.get(key, None) is None:
            vardict[key] = val

    compname = vardict.get("Name", None)
    compvariant = vardict.get("Variant", None)

    if compname is not None:
        gitcommit = dhapi.get_previous_commit(dhurl, cookies, compname, compvariant)
        if dhapi.is_not_empty(gitcommit):
            if run_fetch:
                dhapi.run_git("git fetch --unshallow")
                run_fetch = 0
            export_vars["GIT_PREVIOUS_COMPONENT_COMMIT"] = gitcommit
            export_vars["GIT_LINES_ADDED"] = dhapi.run_git("git diff --stat " + mapping.get("SHORT_SHA", "") + " " + gitcommit + ' | grep changed | cut -d" " -f5')
            export_vars["GIT_LINES_DELETED"] = dhapi.run_git("git diff --stat " + mapping.get("SHORT_SHA", "") + " " + gitcommit + ' | grep changed | cut -d" " -f7')
        else:
            export_vars["GIT_PREVIOUS_COMPONENT_COMMIT"] = ""
            export_vars["GIT_LINES_ADDED"] = "0"
            export_vars["GIT_LINES_DELETED"] = "0"

    if mapping.get("BASENAME", None) is not None:
        export_vars["BASENAME"] = mapping["BASENAME"]

    for key in sorted(export_vars):
        line = export_vars[key]
        template = Template(line)
        line = template.safe_substitute(**vardict)

        template = Template(line)
        line = template.safe_substitute(**mapping)
        fp_script.write("export " + key + '="' + line + '"\n')

    fp_script.close()
    os.chmod(envvars_sh, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)


def filterdict(dhurl, cookies, objtype, fromdom, allobjs):
    """
    Export all the objects from the server for the from domain and filter the dictionary for the object name.

    Args:
        dhurl (string): url for the server
        cookies (string): cookies from the login
        objtype (sting): object type to look for in the dictionary
        fromdom (string): name of the domain in the dictionary
        allobjs (dict): return of the objects found

    Returns:
        data returned in allobjs
    """
    data = dhapi.get_json(dhurl + "/dmadminweb/API/export/" + objtype, cookies)

    objlist = []
    for obj in data.get(objtype, []):
        objname = obj.get("objname", "")
        if fromdom.lower() in objname.lower():
            objlist.append(obj)

    allobjs[objtype] = objlist


def importdict(dhurl, cookies, objtype, allobjs):
    """
    Import the objects based on objtype and add them to the server.

    Args:
        dhurl (string): url for the server
        cookies (string): cookies from the login
        objtype (sting): object type to look for in the dictionary
        allobjs (dict): return of the objects found

    Returns:
        no data returned
    """
    print(objtype)

    for obj in allobjs.get(objtype, []):
        pprint(obj)
        jstr = json.dumps(obj, indent=2)
        data = dhapi.post_json(dhurl + "/dmadminweb/API/import/", jstr, cookies)
        pprint(data)


if __name__ == "__main__":
    main()
