In automation environments such as Azure DevOps you can’t use Terraforms interactive approval. Therefore you create a deployment plan, wait for a plan approval and apply the deployment plan. This blog implements a plan approval in Azure Pipelines using the Manual Intervention-task.
Plan Approval Release Pipeline
A plan approval release pipeline first creates a Terraform plan and waits for an approval before applying the plan. The following release pipeline implements plan approval using the Manual Intervention-task. This task notifies selected users or groups and waits for a manual approval.
Remark This pipeline requires the Terraform Extension-extension. Ask your administrator to install and configure it.
Release Pipeline
The release consists of two stages: Test and Production. Deployments are controlled using release variables.
The associated source repository is available at GitHub.
For the sake of simplicity this example doesn’t use any stage-specific configuration. Include additional configuration using additional Release variables and apply them using the Replace Tokens-task.
Deployment Pipeline
The deployment pipeline configures Terraform, plans the required changes, waits for approval and applies the changes. Since pipeline artifacts are not supported in release pipelines the deployments assumes that the infra is unchanged while awaiting approval.
Command Reference | Task | Configuration |
---|---|---|
Init | Configuration Directory | $(System.DefaultWorkingDirectory)/GitHub/terraform/projects/$(Terraform.Project)/stacks/$(Terraform.Stack) |
State Key | $(Terraform.Project)/$(Terraform.Configuration) | |
Plan | Configuration Directory | $(System.DefaultWorkingDirectory)/GitHub/terraform/projects/$(Terraform.Project)/stacks/$(Terraform.Stack) |
Command Args | -input=false -var-file=”$(System.DefaultWorkingDirectory)/GitHub/terraform/projects/$(Terraform.Project)/settings/$(Terraform.Configuration).tfvars” | |
Apply | Configuration Directory | $(System.DefaultWorkingDirectory)/GitHub/terraform/projects/$(Terraform.Project)/stacks/$(Terraform.Stack) |
Command Args | -input=false -auto-approve -lock-timeout=0s -var-file=”$(System.DefaultWorkingDirectory)/GitHub/terraform/projects/$(Terraform.Project)/settings/$(Terraform.Configuration).tfvars” |
Discussion
Azure Pipelines also supports Gates and yaml-pipelines. Gates are used to control deployments, and yaml-pipelines are used to store the build and release pipelines next to your source code. Why don’t you use that?
I do think that Gates and yaml-pipelines should be used instead of the Manual Intervention-task. Currently this implies moving the pipelines approval configuration to the project-level environment configuration[1]. I dislike this, because I prefer self-contained pipelines.
But can’t you use Gates without yaml-pipelines? Sadly Release Pipelines don’t support publishing pipeline artifacts. This is overcome by using external infrastructure, but I rather wait for the Azure DevOps team to implement it with yaml-pipelines [2].
Conclusion
Use the manual intervention-task to approve your Terraform deployments. Although Release Pipelines don’t allow to execute the planned plan, it’s always better to have a controlled deployment over a blind one.