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..af88393 --- /dev/null +++ b/runtime-unified-action/action.yaml @@ -0,0 +1,99 @@ +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: "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 + + - 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/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..dec9aea --- /dev/null +++ b/runtime-unified-action/script.py @@ -0,0 +1,126 @@ +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): + 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..be55ccc 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):