From 4a8ca6e97dc00fc1549adb215e7a56c4ed7574f6 Mon Sep 17 00:00:00 2001 From: Eliezer Rodrigues Soares Date: Wed, 23 Oct 2024 14:25:32 -0300 Subject: [PATCH 1/3] stk-cli: create action initial commit. --- runtime-unified-action/.stkignore | 1 + runtime-unified-action/action.yaml | 23 ++++++++++ runtime-unified-action/docs/en-us/docs.md | 54 +++++++++++++++++++++++ runtime-unified-action/docs/pt-br/docs.md | 54 +++++++++++++++++++++++ runtime-unified-action/script.py | 4 ++ 5 files changed, 136 insertions(+) create mode 100644 runtime-unified-action/.stkignore create mode 100644 runtime-unified-action/action.yaml create mode 100644 runtime-unified-action/docs/en-us/docs.md create mode 100644 runtime-unified-action/docs/pt-br/docs.md create mode 100644 runtime-unified-action/script.py diff --git a/runtime-unified-action/.stkignore b/runtime-unified-action/.stkignore new file mode 100644 index 0000000..e6045cc --- /dev/null +++ b/runtime-unified-action/.stkignore @@ -0,0 +1 @@ +# Este arquivo pode ser usado para ignorar arquivos e pastas ao publicar um artefato. \ No newline at end of file diff --git a/runtime-unified-action/action.yaml b/runtime-unified-action/action.yaml new file mode 100644 index 0000000..11b8eec --- /dev/null +++ b/runtime-unified-action/action.yaml @@ -0,0 +1,23 @@ +schema-version: v3 +kind: action +metadata: + name: runtime-unified-action + display-name: runtime-unified-action + description: Descreva sua action explicando o propósito. + version: 0.0.1 +spec: + type: python + docs: + pt-br: docs/pt-br/docs.md + en-us: docs/en-us/docs.md + repository: https://github.com/stack-spot/workflow-stackspot-actions-runtime-selfhosted.git + inputs: + - label: What is your name? + name: user_name + type: text + required: false + pattern: '^[A-Za-z]+(?:\s[A-Za-z]+)*$' + help: 'Inform your name' + python: + workdir: . + script: script.py diff --git a/runtime-unified-action/docs/en-us/docs.md b/runtime-unified-action/docs/en-us/docs.md new file mode 100644 index 0000000..ad8afc2 --- /dev/null +++ b/runtime-unified-action/docs/en-us/docs.md @@ -0,0 +1,54 @@ + +## Action name + + + +## Requirements + + + +## Usage + + + +## Release Notes + + \ No newline at end of file diff --git a/runtime-unified-action/docs/pt-br/docs.md b/runtime-unified-action/docs/pt-br/docs.md new file mode 100644 index 0000000..9778ea6 --- /dev/null +++ b/runtime-unified-action/docs/pt-br/docs.md @@ -0,0 +1,54 @@ + +## Nome Action + + + +## Pré-requisitos + + + +## Uso + + + +## Release Notes + + \ No newline at end of file diff --git a/runtime-unified-action/script.py b/runtime-unified-action/script.py new file mode 100644 index 0000000..b534d3f --- /dev/null +++ b/runtime-unified-action/script.py @@ -0,0 +1,4 @@ + + +def run(metadata): + print(f"Hello {metadata.inputs.get('user_name')}!") From b8f4f7933f2cc8edb8f0f786d341f06ec33af096 Mon Sep 17 00:00:00 2001 From: Eliezer Rodrigues Soares Date: Mon, 28 Oct 2024 15:51:50 -0300 Subject: [PATCH 2/3] add new action unified --- runtime-unified-action/action.yaml | 84 ++++++++++++++++++- runtime-unified-action/script.py | 125 ++++++++++++++++++++++++++++- script.py | 11 ++- 3 files changed, 213 insertions(+), 7 deletions(-) diff --git a/runtime-unified-action/action.yaml b/runtime-unified-action/action.yaml index 11b8eec..af88393 100644 --- a/runtime-unified-action/action.yaml +++ b/runtime-unified-action/action.yaml @@ -12,12 +12,88 @@ spec: en-us: docs/en-us/docs.md repository: https://github.com/stack-spot/workflow-stackspot-actions-runtime-selfhosted.git inputs: - - label: What is your name? - name: user_name + - label: "CLIENT ID" + name: client_id + type: text + required: true + + - label: "CLIENT KEY" + name: client_key + type: text + required: true + + - label: "CLIENT REALM" + name: client_realm + type: text + required: true + + - label: "Git Repository Name" + name: repository_name + type: text + required: true + + - label: "AWS ACCESS KEY ID from console" + name: aws_access_key_id + type: text + required: true + + - label: "AWS SECRET ACCESS KEY from console" + name: aws_secret_access_key + type: text + required: true + + - label: "AWS SESSION TOKEN from console" + name: aws_session_token + type: text + required: true + + - label: "AWS REGION" + name: aws_region + type: text + required: true + + - label: "Terraform parallelism order" + name: tf_parallelism + type: text + default: "10" + required: false + + - label: "Terraform Modules" + name: features_terraform_modules type: text required: false - pattern: '^[A-Za-z]+(?:\s[A-Za-z]+)*$' - help: 'Inform your name' + + - label: "Path to mount inside the docker" + name: path_to_mount + type: text + default: "." + required: false + + - label: "If Runtimes will allow execution of the local-exec command within terraform" + name: localexec_enabled + type: bool + required: false + + - label: "Level tf log provider - info, debug, warn or trace" + name: tf_log_provider + type: text + required: false + + - label: "Features Log Level" + name: features_level_log + type: text + required: false + + - label: "Base Path Output" + name: base_path_output + type: text + required: false + + - label: "Run ID that contains its tasks" + name: run_id + type: text + required: true + python: workdir: . script: script.py diff --git a/runtime-unified-action/script.py b/runtime-unified-action/script.py index b534d3f..ed7be7f 100644 --- a/runtime-unified-action/script.py +++ b/runtime-unified-action/script.py @@ -1,4 +1,127 @@ +import os +import sys +import subprocess +import logging +from typing import List + +# Configure logging +logging.basicConfig( + level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s" +) + + +STK_IAM_DOMAIN = os.getenv("STK_IAM_DOMAIN", "https://idm.stackspot.com") +STK_RUNTIME_MANAGER_DOMAIN = os.getenv( + "STK_RUNTIME_MANAGER_DOMAIN", "https://runtime-manager.v1.stackspot.com" +) +CONTAINER_UNIFIED_URL = os.getenv( + "CONTAINER_UNIFIED_URL", "stackspot/runtime-job-unified:latest" +) + +FEATURES_BASEPATH_TMP = "/tmp/runtime/deploys" +FEATURES_BASEPATH_EBS = "/opt/runtime" +FEATURES_TEMPLATES_FILEPATH = "/app/" +FEATURES_BASEPATH_TERRAFORM = "/root/.asdf/shims/terraform" + + +def check(result: subprocess.Popen) -> None: + """ + Checks the result of a subprocess execution. If the return code is non-zero, + it logs an error message and exits the program. + + Args: + result (subprocess.Popen): The result of the subprocess execution. + """ + result.wait() # Wait for the process to complete + if result.returncode != 0: + logging.error(f"Failed to execute: {result.args}") + logging.error(f"Error output: {result.stderr.read()}") + sys.exit(1) + + +def run_command(command: List[str]) -> subprocess.Popen: + """ + Runs a command using subprocess.Popen and returns the result. + + Args: + command (List[str]): The command to be executed as a list of strings. + + Returns: + subprocess.Popen: The result of the command execution. + """ + try: + logging.info(f"Running command: {' '.join(command)}") + # Start the process + process = subprocess.Popen( + command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True + ) + + # Read and print output in real-time + for line in process.stdout: + print(line, end="") # Print each line as it is produced + + # Check the result after the process completes + check(process) + return process + except Exception as e: + logging.error(f"Exception occurred while running command: {command}") + logging.error(str(e)) + sys.exit(1) + + +def build_flags(inputs: dict) -> list: + + TF_PARALLELISM=f"-parallelism={inputs.get('tf_parallelism') or '10'}" + + docker_flags: dict = dict( + FEATURES_LEVEL_LOG=inputs.get("features_level_log") or "info", + FEATURES_TERRAFORM_LOGPROVIDER=inputs.get("tf_log_provider") or "info", + FEATURES_RELEASE_LOCALEXEC=inputs.get("localexec_enabled") or "False", + FEATURES_TERRAFORM_MODULES=inputs.get("features_terraform_modules") or "[]", + AWS_ACCESS_KEY_ID=inputs["aws_access_key_id"], + AWS_SECRET_ACCESS_KEY=inputs["aws_secret_access_key"], + AWS_SESSION_TOKEN=inputs["aws_session_token"], + AUTHENTICATE_CLIENT_ID=inputs["client_id"], + AUTHENTICATE_CLIENT_SECRET=inputs["client_key"], + AUTHENTICATE_CLIENT_REALMS=inputs["client_realm"], + REPOSITORY_NAME=inputs["repository_name"], + AWS_REGION=inputs["aws_region"], + AUTHENTICATE_URL=STK_IAM_DOMAIN, + FEATURES_API_MANAGER=STK_RUNTIME_MANAGER_DOMAIN, + FEATURES_BASEPATH_TMP=FEATURES_BASEPATH_TMP, + FEATURES_BASEPATH_EBS=FEATURES_BASEPATH_EBS, + FEATURES_TEMPLATES_FILEPATH=FEATURES_TEMPLATES_FILEPATH, + FEATURES_BASEPATH_TERRAFORM=FEATURES_BASEPATH_TERRAFORM, + TF_CLI_ARGS_apply=TF_PARALLELISM, + TF_CLI_ARGS_plan=TF_PARALLELISM, + TF_CLI_ARGS_destroy=TF_PARALLELISM + + ) + flags = [] + for k, v in docker_flags.items(): + flags += ["-e", f"{k}={v}"] + + return flags def run(metadata): - print(f"Hello {metadata.inputs.get('user_name')}!") + inputs: dict = metadata.inputs + run_id: str = inputs["run_id"] + base_path_output: str = inputs.get("base_path_output") or "." + path_to_mount: str = inputs.get("path_to_mount") or "." + path_to_mount = f"{path_to_mount}:/app-volume" + + flags = build_flags(inputs) + cmd = ( + ["docker", "run", "--rm", "-v", path_to_mount] + + flags + + [ + "--entrypoint=/app/stackspot-runtime-job", + CONTAINER_UNIFIED_URL, + "start", + f"--run-id={run_id}", + f"--base-path-output={base_path_output}", + ] + ) + + run_command(cmd) diff --git a/script.py b/script.py index 1aea4cd..c7cfb0c 100644 --- a/script.py +++ b/script.py @@ -53,11 +53,18 @@ def run_tasks(file_tasks: str, run_action: RunAction): IAC_SELF_HOSTED=lambda **i: run_action("runtime-iac-action", **i), DEPLOY_SELF_HOSTED=lambda **i: run_action("runtime-deploy-action", **i), DESTROY_SELF_HOSTED=lambda **i: run_action("runtime-destroy-action", **i), + UNIFIED_IAC=lambda **i: run_action("runtime-unified-action", **i), + UNIFIED_DEPLOY=lambda **i: run_action("runtime-unified-action", **i), + UNIFIED_DESTROY=lambda **i: run_action("runtime-unified-action", **i) ) for t in data.get("tasks") or []: - runner = task_runners.get(t["taskType"]) - runner and runner(run_task_id=t["runTaskId"]) + task_type = t["taskType"] + runner = task_runners.get(task_type) + if "UNIFIED" in task_type: + runner and runner(run_id=data.get("runId")) + else: + runner and runner(run_task_id=t["runTaskId"]) def run(metadata): From 6a5987d715bf02aca319fb40ed1689a591871f7b Mon Sep 17 00:00:00 2001 From: Eliezer Rodrigues Soares Date: Mon, 28 Oct 2024 17:21:36 -0300 Subject: [PATCH 3/3] lint --- runtime-unified-action/script.py | 5 ++--- script.py | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/runtime-unified-action/script.py b/runtime-unified-action/script.py index ed7be7f..dec9aea 100644 --- a/runtime-unified-action/script.py +++ b/runtime-unified-action/script.py @@ -71,7 +71,7 @@ def run_command(command: List[str]) -> subprocess.Popen: def build_flags(inputs: dict) -> list: - TF_PARALLELISM=f"-parallelism={inputs.get('tf_parallelism') or '10'}" + TF_PARALLELISM = f"-parallelism={inputs.get('tf_parallelism') or '10'}" docker_flags: dict = dict( FEATURES_LEVEL_LOG=inputs.get("features_level_log") or "info", @@ -94,8 +94,7 @@ def build_flags(inputs: dict) -> list: FEATURES_BASEPATH_TERRAFORM=FEATURES_BASEPATH_TERRAFORM, TF_CLI_ARGS_apply=TF_PARALLELISM, TF_CLI_ARGS_plan=TF_PARALLELISM, - TF_CLI_ARGS_destroy=TF_PARALLELISM - + TF_CLI_ARGS_destroy=TF_PARALLELISM, ) flags = [] for k, v in docker_flags.items(): diff --git a/script.py b/script.py index c7cfb0c..be55ccc 100644 --- a/script.py +++ b/script.py @@ -55,14 +55,14 @@ def run_tasks(file_tasks: str, run_action: RunAction): DESTROY_SELF_HOSTED=lambda **i: run_action("runtime-destroy-action", **i), UNIFIED_IAC=lambda **i: run_action("runtime-unified-action", **i), UNIFIED_DEPLOY=lambda **i: run_action("runtime-unified-action", **i), - UNIFIED_DESTROY=lambda **i: run_action("runtime-unified-action", **i) + UNIFIED_DESTROY=lambda **i: run_action("runtime-unified-action", **i), ) for t in data.get("tasks") or []: task_type = t["taskType"] runner = task_runners.get(task_type) if "UNIFIED" in task_type: - runner and runner(run_id=data.get("runId")) + runner and runner(run_id=data.get("runId")) else: runner and runner(run_task_id=t["runTaskId"])