diff --git a/build.py b/build.py index fab74f6..08b6bba 100644 --- a/build.py +++ b/build.py @@ -31,7 +31,7 @@ use_plugin("python.install_dependencies") default_task = "publish" name = 'dda-devops-build' -version = "0.1.0" +version = "0.1.1" summary = "tools to support builds combining gopass, terraform, dda-pallet, aws & hetzner-cloud" description = __doc__ authors = [Author("meissa GmbH", "buero@meissa-gmbh.de")] diff --git a/src/main/python/dda_pallet.py b/src/main/python/dda_pallet.py new file mode 100644 index 0000000..ad92f1f --- /dev/null +++ b/src/main/python/dda_pallet.py @@ -0,0 +1,26 @@ +from subprocess import check_output, call, Popen, PIPE +import sys +import string + +TARGET = 'target.edn' +TEMPLATE_TARGET_CONTENT = string.Template(""" +{:existing [{:node-name "k8s" + :node-ip "$ip"}] + :provisioning-user {:login "root"}} +""") + +def write_target(ip): + with open(TARGET, "w") as output_file: + output_file.write(TEMPLATE_TARGET_CONTENT.substitute({'ip' : ip})) + +def uberjar(tenant, application, spec): + cmd = ['java', '-jar', '../../../target/meissa-tenant-server.jar', '--targets', TARGET, + '--tenant', tenant, '--application', application, spec] + prn_cmd=list(cmd) + print(" ".join(prn_cmd)) + if sys.version_info.major == 3: + output = check_output(cmd, encoding='UTF-8') + else: + output = check_output(cmd) + print(output) + return output diff --git a/src/main/python/meissa_build.py b/src/main/python/meissa_build.py new file mode 100644 index 0000000..0f45a25 --- /dev/null +++ b/src/main/python/meissa_build.py @@ -0,0 +1,21 @@ +import credential +import os + +def init_project(project): + project.set_property('stage', os.environ.get('STAGE', 'intergation')) + project.set_property('http_net_api_key', + credential.gopass_credential_from_env_path('HTTP_NET_API_KEY_PATH')) + project.set_property('hetzner_api_key', + credential.gopass_credential_from_env_path('HETZNER_API_KEY_PATH')) + +def hetzner_api_key(project): + return project.get_property('hetzner_api_key') + +def stage(project): + return project.get_property('stage') + +def tf_import_name(project): + return project.get_property('tf_import_name') + +def tf_import_resource(project): + return project.get_property('tf_import_resource') diff --git a/src/main/python/terraform.py b/src/main/python/terraform.py new file mode 100644 index 0000000..cb5215a --- /dev/null +++ b/src/main/python/terraform.py @@ -0,0 +1,95 @@ +from subprocess import check_output, call, Popen, PIPE +import os +import sys +import json +import meissa_build + +APPLY_PLAN = "proposed_apply.plan" +DESTROY_PLAN = "proposed_destroy.plan" +OUTPUT_JSON = "output.json" + +TF_INIT_CMD = ['init'] +TF_SELECT_WORKSPACE_CMD = ['workspace', 'select'] +TF_NEW_WORKSPACE_CMD = ['workspace', 'new'] +TF_OUTPUT_CMD = ['output', '-json'] +TF_PLAN_CMD = ['plan'] +TF_IMPORT_CMD = ['import'] +TF_APPLY_CMD = ['apply'] +TF_DESTROY_CMD = ['destroy'] + +def copy_common(base_path): + call(['cp', '-f', base_path + '00_build_common/terraform/gitignore_on_target', '.gitignore']) + call(['cp', '-f', base_path + '00_build_common/terraform/aws_provider.tf', 'aws_provider.tf']) + call(['cp', '-f', base_path + '00_build_common/terraform/variables.tf', 'variables.tf']) + +def terraform(cmd, credentials=None, options=None): + tf_cmd = ['terraform'] + tf_cmd.extend(cmd) + prn_cmd=list(tf_cmd) + if credentials: + tf_cmd.extend(credentials) + prn_cmd.extend([credentials[0], credentials[1].split('=', 1)[0] + '=xxx']) + if options: + tf_cmd.extend(options) + prn_cmd.extend(options) + print(" ".join(prn_cmd)) + if sys.version_info.major == 3: + output = check_output(tf_cmd, encoding='UTF-8') + else: + output = check_output(tf_cmd) + print(output) + return output + +def init(project): + terraform(TF_INIT_CMD) + try: + terraform(TF_SELECT_WORKSPACE_CMD, None, [meissa_build.stage(project)]) + except: + terraform(TF_NEW_WORKSPACE_CMD, None, [meissa_build.stage(project)]) + +def write_output(): + output = terraform(TF_OUTPUT_CMD) + with open(OUTPUT_JSON, "w") as output_file: + output_file.write(output) + +def read_output_json(): + with open(OUTPUT_JSON, 'r') as f: + return json.load(f) + +def get_hetzner_api_key_as_var(project): + hetzner_api_key = meissa_build.hetzner_api_key(project) + ret = [] + if hetzner_api_key: + ret.extend(['-var', 'hetzner_api_key=' + hetzner_api_key]) + return ret + +def plan_apply(project): + init(project) + terraform(TF_PLAN_CMD, get_hetzner_api_key_as_var(project), ['-out', APPLY_PLAN]) + +def tf_import(project): + init(project) + terraform(TF_IMPORT_CMD, get_hetzner_api_key_as_var(project), [meissa_build.tf_import_name(project), meissa_build.tf_import_resource(project)]) + +def plan_destroy(project): + init(project) + terraform(TF_PLAN_CMD, get_hetzner_api_key_as_var(project), ['-destroy']) + +def apply(project, auto_approve=None): + if not os.path.isfile(APPLY_PLAN): + plan_apply(project) + else: + init(project) + cmd = [] + if auto_approve: + cmd.extend(['-auto-approve', '-input=false']) + cmd.append(APPLY_PLAN) + terraform(TF_APPLY_CMD, None, cmd) + write_output() + +def destroy(project, auto_approve=None): + cmd = [] + if auto_approve: + cmd.extend(['-auto-approve', '-input=false']) + terraform(TF_DESTROY_CMD, get_hetzner_api_key_as_var(project), cmd) + write_output()