SlackIncomingWebhook icon
Pause icon
If icon
Fail icon
Script icon
TerraformCLI icon
Set icon

Self-Service VM Ordering with Approval Gate and Terraform on Google Cloud

Self-service GCP VM ordering with Kestra. Slack notifies approvers, the run pauses for approval, Terraform provisions the VM, and inventory is updated.

Categories
Infrastructure

Turn VM requests into a governed self-service workflow. A requester picks the account, zone, image, and size from dropdown inputs, an approver is pinged in Slack, and the execution pauses until someone explicitly approves. Only then does Terraform provision the Google Cloud instance, after which the VM is registered in a KV-backed inventory and the channel is notified with the external IP. Rejections fail the run with the recorded reason, so every decision is auditable.

How it works

  1. Cascading SELECT inputs (billingAccount, region, zone, osFlavor, vmSize, env, vmType) present a controlled order form; zone uses dependsOn so only zones in the chosen region appear.
  2. The requestApproval task (io.kestra.plugin.notifications.slack.SlackIncomingWebhook) posts the order summary and execution id to Slack.
  3. The waitForApproval task (io.kestra.plugin.core.flow.Pause) suspends the run; on resume the approver provides approved (BOOL) and reason (STRING) via onResume inputs.
  4. The proceedIfApproved task (io.kestra.plugin.core.flow.If) fails the execution with the rejection reason, or continues.
  5. The generateHostname task (io.kestra.plugin.scripts.python.Script) builds a standardized hostname such as gcpdevlnxapp42 and a candidate IP; swap the stub for your CMDB or IPAM lookup.
  6. The createVM task (io.kestra.plugin.terraform.cli.TerraformCLI) runs terraform init, plan, and apply against an inlined main.tf, authenticating with a service account key injected via inputFiles, then exports external_ip.txt.
  7. The updateInventory task (io.kestra.plugin.core.kv.Set) stores the full VM record as JSON in the KV store, and notifyChannel posts the result back to Slack.

What you get

  • A single form-driven entry point for VM requests with constrained, dependent choices.
  • A human approval gate with a recorded approve/reject decision and reason.
  • Terraform provisioning with credentials pulled from secrets, never hardcoded.
  • An inventory record per VM and a Slack confirmation with the external IP.
  • The external IP exposed as a flow output for downstream flows.

Who it's for

  • Platform teams offering VM self-service without giving out cloud console access.
  • Infrastructure engineers who want provisioning requests reviewed before spend happens.
  • IT organizations replacing ticket-driven VM requests with an auditable workflow.

Why orchestrate this with Kestra

Terraform alone cannot pause for a human decision, render an order form, or notify approvers. Kestra adds typed inputs with dependsOn cascading, a first-class Pause task with onResume inputs that capture who decided what and why, secrets management for the service account key, and full execution history linking the request, the approval, and the applied infrastructure.

Prerequisites

  • A GCP project with the Compute Engine API enabled and a service account allowed to create instances.
  • A Slack incoming webhook for the approvals channel.
  • Docker available to the Kestra worker for the Terraform CLI task.

Secrets

  • GCP_SERVICE_ACCOUNT_JSON: full JSON key of the GCP service account used by Terraform.
  • SLACK_WEBHOOK_URL: Slack incoming webhook used for approval requests and confirmations.

Quick start

  1. Add the secrets above to your Kestra namespace.
  2. Adjust the SELECT input values to your real accounts, regions, networks, and sizes.
  3. Replace the stub hostname/IP generation with your CMDB or IPAM lookup.
  4. Execute the flow, review the Slack message, then resume the paused execution with approved: true.

How to extend

  • Add a remote GCS backend to main.tf so a decommissioning flow can terraform destroy from the same state.
  • Replace the KV inventory with ServiceNow CMDB or NetBox API calls.
  • Chain a post-provisioning flow (compliance scan, user onboarding) with a io.kestra.plugin.core.trigger.Flow trigger on SUCCESS.
  • Auto-approve dev requests by wrapping waitForApproval in runIf: {{ inputs.env != 'dev' }}.
  • Track the VM as a governed asset with the EE Assets plugin (io.kestra.plugin.ee.assets.VM).

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.