id: hetzner-vm-destroy namespace: hetzner inputs: - id: vm_name type: SELECT displayName: "VM auswählen" description: "VM aus der aktuellen Hetzner-Serverliste auswählen. Vorher hetzner-server-available-list ausführen." expression: "{{ kv('hetzner_server_names') }}" tasks: - id: terraform-destroy-plan type: io.kestra.plugin.terraform.cli.TerraformCLI containerImage: hashicorp/terraform:latest env: AWS_ACCESS_KEY_ID: "{{ secret('AWS_ACCESS_KEY_ID') }}" AWS_SECRET_ACCESS_KEY: "{{ secret('AWS_SECRET_ACCESS_KEY') }}" TF_BACKEND_BUCKET: "{{ secret('TF_BACKEND_BUCKET') }}" TF_BACKEND_ENDPOINT: "{{ secret('TF_BACKEND_ENDPOINT') }}" TF_VAR_hcloud_token: "{{ secret('HCLOUD_TOKEN') }}" TF_VAR_ssh_key_name: "{{ secret('SSH_KEY_NAME') }}" inputFiles: main.tf: | terraform { required_version = ">= 1.5" required_providers { hcloud = { source = "hetznercloud/hcloud" version = "~> 1.49" } } backend "s3" {} } provider "hcloud" { token = var.hcloud_token } data "hcloud_ssh_key" "default" { name = var.ssh_key_name } resource "hcloud_server" "vm" { name = var.vm_name image = "ubuntu-24.04" server_type = var.server_type location = var.location ssh_keys = [data.hcloud_ssh_key.default.id] public_net { ipv4_enabled = true ipv6_enabled = false } labels = { managed_by = "terraform" team = var.team } } output "vm_ipv4" { value = hcloud_server.vm.ipv4_address } variables.tf: | variable "hcloud_token" { type = string sensitive = true } variable "ssh_key_name" { type = string } variable "vm_name" { type = string } variable "server_type" { type = string default = "cx23" } variable "location" { type = string default = "nbg1" } variable "team" { type = string default = "demo" } beforeCommands: - | terraform init -reconfigure \ -backend-config="bucket=$TF_BACKEND_BUCKET" \ -backend-config="endpoints={s3=\"$TF_BACKEND_ENDPOINT\"}" \ -backend-config="key=vms/{{ inputs.vm_name }}/terraform.tfstate" \ -backend-config="region=us-east-1" \ -backend-config="skip_requesting_account_id=true" \ -backend-config="skip_credentials_validation=true" \ -backend-config="skip_metadata_api_check=true" \ -backend-config="skip_region_validation=true" \ -backend-config="use_path_style=true" commands: - | set -eo pipefail terraform plan -destroy -no-color -out=tfdestroyplan \ -var="vm_name={{ inputs.vm_name }}" \ | tee destroy-plan-output.txt outputFiles: - tfdestroyplan - main.tf - variables.tf - destroy-plan-output.txt - id: log-destroy-plan type: io.kestra.plugin.core.log.Log message: | 🧨 Terraform Destroy Plan für VM '{{ inputs.vm_name }}': {{ read(outputs['terraform-destroy-plan'].outputFiles['destroy-plan-output.txt']) }} ────────────────────────────────────────── → Bitte genau prüfen und Execution fortsetzen oder abbrechen. - id: approval-gate type: io.kestra.plugin.core.flow.Pause onResume: - id: approved type: BOOLEAN displayName: "VM wirklich löschen?" description: "True = VM wird gelöscht. False = Execution wird abgebrochen." defaults: false - id: destroy-decision type: io.kestra.plugin.core.flow.If condition: "{{ outputs['approval-gate'].onResume.approved == true }}" then: - id: terraform-destroy-apply type: io.kestra.plugin.terraform.cli.TerraformCLI containerImage: hashicorp/terraform:latest env: AWS_ACCESS_KEY_ID: "{{ secret('AWS_ACCESS_KEY_ID') }}" AWS_SECRET_ACCESS_KEY: "{{ secret('AWS_SECRET_ACCESS_KEY') }}" TF_BACKEND_BUCKET: "{{ secret('TF_BACKEND_BUCKET') }}" TF_BACKEND_ENDPOINT: "{{ secret('TF_BACKEND_ENDPOINT') }}" TF_VAR_hcloud_token: "{{ secret('HCLOUD_TOKEN') }}" TF_VAR_ssh_key_name: "{{ secret('SSH_KEY_NAME') }}" inputFiles: main.tf: "{{ outputs['terraform-destroy-plan'].outputFiles['main.tf'] }}" variables.tf: "{{ outputs['terraform-destroy-plan'].outputFiles['variables.tf'] }}" tfdestroyplan: "{{ outputs['terraform-destroy-plan'].outputFiles['tfdestroyplan'] }}" beforeCommands: - | terraform init -reconfigure \ -backend-config="bucket=$TF_BACKEND_BUCKET" \ -backend-config="endpoints={s3=\"$TF_BACKEND_ENDPOINT\"}" \ -backend-config="key=vms/{{ inputs.vm_name }}/terraform.tfstate" \ -backend-config="region=us-east-1" \ -backend-config="skip_requesting_account_id=true" \ -backend-config="skip_credentials_validation=true" \ -backend-config="skip_metadata_api_check=true" \ -backend-config="skip_region_validation=true" \ -backend-config="use_path_style=true" commands: - | set -eo pipefail terraform apply -auto-approve -no-color tfdestroyplan - id: update_server_inventory_after_destroy type: io.kestra.plugin.core.flow.Subflow namespace: hetzner flowId: hetzner-server-available-list wait: true - id: log-result type: io.kestra.plugin.core.log.Log message: | 🗑️ VM '{{ inputs.vm_name }}' wurde erfolgreich gelöscht. Terraform-State wurde über MinIO/S3 aktualisiert: vms/{{ inputs.vm_name }}/terraform.tfstate Die Hetzner-Serverliste wurde danach ebenfalls aktualisiert: inventory/hetzner-server-available.json inventory/hetzner-server-names.json Kestra KV: hetzner_server_names else: - id: log-aborted type: io.kestra.plugin.core.log.Log message: | ❌ Löschvorgang abgebrochen. VM '{{ inputs.vm_name }}' wurde nicht gelöscht.