github-workflows-dojo360-terraform-destroy
Master the Terraform Destroy workflow from Dojo360 to safely tear down and terminate cloud infrastructure across AWS, Azure, and GCP environments
Terraform Destroy Workflow
Master the Terraform Destroy workflow from Dojo360 to safely tear down and terminate cloud infrastructure across AWS, Azure, and GCP environments.
Skill ID: github-workflows-dojo360-terraform-destroy
Workflow: dojo360/pipelines-workflows/.github/workflows/destroy.yml
PADU Status: Emerging
Documentation: Terraform Destroy Index
π Overview
The Terraform Destroy workflow executes terraform destroy operations to safely terminate and tear down Terraform-managed infrastructure in cloud environments. This workflow is essential for:
- Infrastructure Teardown: Complete removal of cloud resources when no longer needed
- Cost Optimization: Terminating development/test environments outside business hours
- Environment Cleanup: Removing temporary or experimental infrastructure
- Disaster Recovery Testing: Tearing down and rebuilding infrastructure
- Emergency Procedures: Controlled destruction of compromised resources
Key Capabilities
- Multi-Cloud Support: Works with AWS, Azure, and GCP resources
- Remote State Management: Supports azurerm, S3, and GCS backends
- Approval Workflows: Environment-based destruction approvals
- Plan-Only Mode: Review destruction impact before execution
- OIDC Authentication: Secure, keyless cloud authentication
- Secrets Integration: PRM, Volcan, and GitHub secrets support
- Terraform Enterprise: Optional TFE backend support
When to Use This Workflow
β Appropriate Use Cases:
- Decommissioning temporary development environments
- Cleaning up after testing or experimentation
- Implementing cost-saving schedules (shutdown non-prod overnight)
- Disaster recovery drills and testing
- Migrating to new infrastructure patterns
- Responding to security incidents requiring resource termination
β οΈ Use with Caution:
- Production environment teardown (requires multiple approvals)
- Partial resource destruction (use targeted destroy carefully)
- Shared infrastructure with dependencies
- Resources with critical data or state
π Key Features
1. Multi-Cloud Destroy Operations
- Execute
terraform destroyacross all major cloud providers - Consistent workflow regardless of cloud type
- Automatic provider configuration based on cloud-type
- Support for hybrid multi-cloud infrastructure
2. Safety Features
Approval Workflows:
- Environment-based approval requirements
- GitHub environment protection rules integration
- Manual confirmation before destruction
- Audit trail of all destroy operations
Plan-Only Mode:
- Review destruction plan without executing
- Validate what will be destroyed
- Share destruction plan with stakeholders
- Set
run-plan-only: trueto preview only
Remote State Protection:
- State file verification before destroy
- Remote backend locking during operations
- State backup and recovery support
3. Backend Flexibility
- Azure RM Backend (default): Azure Storage for state
- S3 Backend: AWS S3 for state management
- GCS Backend: Google Cloud Storage for state
- Terraform Enterprise: TFE remote backend support
4. Authentication Methods
- awsOptum: OIDC-based AWS authentication
- awsChc20: Instance Profile-based AWS authentication
- azureOptum: OIDC-based Azure authentication
- gcp: Google Cloud authentication
5. Secrets Management
- PRM Integration: Password Resource Manager secrets
- Volcan Support: Volcan secrets engine
- GitHub Secrets: Repository and environment secrets
- Dynamic secrets propagation
π Prerequisites
Before using the Terraform Destroy workflow, ensure:
1. Metadata API Onboarding
- Product onboarded to Dojo360 Metadata API
- OR local metadata file created in repository
2. OIDC Configuration (for awsOptum and azureOptum)
- AWS OIDC: AWS OIDC Setup
- Azure OIDC: Azure OIDC Setup
3. GitHub Environment Setup
- Environments created matching your
environmentinput - Protection rules configured for production environments
- Required reviewers assigned for approvals
4. Terraform State
- Remote backend configured and accessible
- State file exists for resources to destroy
- State locking supported by backend
π οΈ Requirements
Terraform Version
- Terraform:
~> 1.9.x(default:1.9.2)
Provider Versions (by cloud type)
- AWS:
~> 5.xx(for AWS operations) - AzureRM:
~> 3.xx(for Azure operations) - GCP:
~> 6.xx(for GCP operations)
π₯ Input Reference
Required Inputs
| Input | Description | Example |
|---|---|---|
aide-id | Aide ID from aide.optum.com for metadata retrieval | "ABC12345" |
cloud-type | Cloud provider type (see Supported Cloud Types) | "awsOptum", "azureOptum", "gcp", "awsChc20" |
domain | Domain for metadata retrieval | "platform", "data" |
environment | Target environment for destruction (defines approvals) | "dev", "qa", "prd" |
team-name | Team name for metadata retrieval | "platform-team" |
Optional Inputs - Backend Configuration
| Input | Description | Default |
|---|---|---|
backend-type | Backend type for Terraform state | "azurerm" |
azurerm-backend-configure-inline | Configure Azure RM backend inline | true |
remote-state-file-name | Remote state filename | "" |
remote-state-folder-name | Remote state folder name | "" |
Optional Inputs - Cloud-Specific
| Input | Description | Default |
|---|---|---|
aws-role-to-assume | AWS IAM Role ARN for destruction | "" |
azure-role | Azure Service Principal role | "contributor" |
pcam-role | PCAM role for Azure | "contributor" |
Optional Inputs - Terraform Configuration
| Input | Description | Default |
|---|---|---|
terraform-directory | Directory with Terraform code | "." |
terraform-version | Terraform version to use | "1.9.2" |
terraform-logging | Terraform logging level | "off" |
terraform-provider-network-mirror | Provider mirror URL | "https://repo1.uhc.com/artifactory/api/terraform/terraform-virtual/providers/" |
terraform-vars-files | Comma-separated tfvars files | "" |
terraform-vars-values | JSON string of tfvars | "" |
Optional Inputs - Execution Control
| Input | Description | Default |
|---|---|---|
run-plan-only | Only run terraform plan, don't destroy | false |
runner-labels | Comma-separated runner labels | "" |
Optional Inputs - Secrets Management
| Input | Description | Default |
|---|---|---|
prm-base-url | PRM instance base URL | "https://prm.optum.com" |
terraform-volcan-secrets | Volcan secrets mapping (comma-separated) | "" |
volcan-base-url | Volcan instance base URL | "volcan-cloud.optum.com" |
Optional Inputs - Terraform Enterprise
| Input | Description | Default |
|---|---|---|
tfe-hostname | Terraform Enterprise hostname | "" |
tfe-organization | TFE organization name | "" |
tfe-workspace | TFE workspace name | "" |
π Required Secrets
GitHub Token
GH_TOKEN: Automatically passed by GitHub during workflow execution- Used for accessing repository and organizational resources
- Automatically available in GitHub Actions context
π» Usage Examples
Example 1: Basic Destroy with Approval
Simple destruction of development environment infrastructure.
name: Destroy Development Infrastructure
on:
workflow_dispatch:
inputs:
confirm:
description: 'Type "destroy" to confirm'
required: true
type: string
jobs:
destroy:
if: ${{ github.event.inputs.confirm == 'destroy' }}
uses: dojo360/pipelines-workflows/.github/workflows/destroy.yml@beta
with:
# Required inputs
aide-id: "ABC12345"
cloud-type: "awsOptum"
domain: "platform"
environment: "dev"
team-name: "platform-engineering"
# Optional - Terraform configuration
terraform-directory: "terraform/infrastructure"
terraform-version: "1.9.2"
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
Example 2: Azure Destroy with Azure RM Backend
Destroy Azure infrastructure using Azure Storage backend.
name: Destroy Azure Infrastructure
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment to destroy'
required: true
type: choice
options:
- dev
- qa
jobs:
destroy:
uses: dojo360/pipelines-workflows/.github/workflows/destroy.yml@beta
with:
# Required inputs
aide-id: "ABC12345"
cloud-type: "azureOptum"
domain: "data"
environment: ${{ github.event.inputs.environment }}
team-name: "data-platform"
# Azure-specific configuration
backend-type: "azurerm"
azurerm-backend-configure-inline: true
azure-role: "contributor"
pcam-role: "contributor"
# Terraform configuration
terraform-directory: "terraform/azure"
remote-state-folder-name: "terraform-state"
remote-state-file-name: "${{ github.event.inputs.environment }}.tfstate"
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
Example 3: AWS Destroy with S3 Backend
Destroy AWS infrastructure with S3 state backend.
name: Destroy AWS Infrastructure
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment to destroy'
required: true
confirm_destroy:
description: 'Confirm destruction (yes/no)'
required: true
jobs:
validate:
runs-on: uhg-runner
steps:
- name: Validate Confirmation
if: ${{ github.event.inputs.confirm_destroy != 'yes' }}
run: |
echo "β Destruction not confirmed. Exiting."
exit 1
destroy:
needs: validate
uses: dojo360/pipelines-workflows/.github/workflows/destroy.yml@beta
with:
# Required inputs
aide-id: "ABC12345"
cloud-type: "awsOptum"
domain: "platform"
environment: ${{ github.event.inputs.environment }}
team-name: "cloud-infrastructure"
# AWS-specific configuration
backend-type: "s3"
aws-role-to-assume: "arn:aws:iam::123456789012:role/terraform-destroy-role"
# Terraform configuration
terraform-directory: "terraform/aws"
terraform-vars-files: "envs/${{ github.event.inputs.environment }}.tfvars"
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
Example 4: Plan-Only Destroy (Review Before Execute)
Review what will be destroyed without executing the destruction.
name: Review Destroy Plan
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment to plan destroy for'
required: true
type: choice
options:
- dev
- qa
- stg
- prd
jobs:
plan-destroy:
uses: dojo360/pipelines-workflows/.github/workflows/destroy.yml@beta
with:
# Required inputs
aide-id: "ABC12345"
cloud-type: "azureOptum"
domain: "platform"
environment: ${{ github.event.inputs.environment }}
team-name: "platform-team"
# Plan-only mode - NO DESTRUCTION OCCURS
run-plan-only: true
# Configuration
terraform-directory: "terraform/infrastructure"
terraform-logging: "info"
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
Example 5: GCP Destroy with GCS Backend
Destroy GCP infrastructure using Google Cloud Storage backend.
name: Destroy GCP Infrastructure
on:
workflow_dispatch:
inputs:
environment:
description: 'GCP environment to destroy'
required: true
project_id:
description: 'GCP Project ID'
required: true
jobs:
destroy:
uses: dojo360/pipelines-workflows/.github/workflows/destroy.yml@beta
with:
# Required inputs
aide-id: "ABC12345"
cloud-type: "gcp"
domain: "platform"
environment: ${{ github.event.inputs.environment }}
team-name: "gcp-platform"
# GCP-specific configuration
backend-type: "gcs"
remote-state-folder-name: "terraform-state"
remote-state-file-name: "${{ github.event.inputs.project_id }}-${{ github.event.inputs.environment }}.tfstate"
# Terraform configuration
terraform-directory: "gcp/terraform"
terraform-vars-values: |
{
"project_id": "${{ github.event.inputs.project_id }}",
"environment": "${{ github.event.inputs.environment }}"
}
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
Example 6: Scheduled Destroy for Cost Savings
Automatically destroy non-production environments outside business hours.
name: Scheduled Environment Teardown
on:
schedule:
# Destroy at 8 PM EST on weekdays (00:00 UTC next day)
- cron: '0 0 * * 2-6'
workflow_dispatch:
jobs:
destroy-dev:
uses: dojo360/pipelines-workflows/.github/workflows/destroy.yml@beta
with:
aide-id: "ABC12345"
cloud-type: "awsOptum"
domain: "platform"
environment: "dev"
team-name: "platform-team"
terraform-directory: "terraform/dev"
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
destroy-qa:
uses: dojo360/pipelines-workflows/.github/workflows/destroy.yml@beta
with:
aide-id: "ABC12345"
cloud-type: "awsOptum"
domain: "platform"
environment: "qa"
team-name: "platform-team"
terraform-directory: "terraform/qa"
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
π― Best Practices
1. Always Use Approval Gates
Configure GitHub environment protection rules for destruction operations:
# GitHub Environment Settings (in repository settings)
environments:
production:
protection_rules:
- type: required_reviewers
reviewers: ["senior-engineers", "platform-leads"]
- type: wait_timer
wait_timer: 300 # 5-minute wait before destruction
2. Use Plan-Only Mode First
Always review the destruction plan before executing:
# Step 1: Run with plan-only
run-plan-only: true
# Step 2: Review the plan output
# Step 3: Re-run with plan-only: false for actual destruction
3. Implement Confirmation Inputs
Require explicit confirmation in workflow dispatch:
on:
workflow_dispatch:
inputs:
confirmation:
description: 'Type "DESTROY" to confirm'
required: true
type: string
jobs:
destroy:
if: ${{ github.event.inputs.confirmation == 'DESTROY' }}
# ... workflow configuration
4. Tag Resources for Safe Destruction
Use Terraform tags to identify destroyable resources:
resource "aws_instance" "example" {
# ... other configuration
tags = {
Environment = "dev"
Destroyable = "true"
CostCenter = "engineering"
}
}
5. Backup Critical Data First
Before destroying infrastructure:
jobs:
backup:
runs-on: uhg-runner
steps:
- name: Backup Database
# ... backup steps
- name: Export Logs
# ... export steps
destroy:
needs: backup
uses: dojo360/pipelines-workflows/.github/workflows/destroy.yml@beta
# ... destroy configuration
6. Use Environment-Specific State Files
Organize state files by environment:
remote-state-file-name: "${{ inputs.environment }}.tfstate"
remote-state-folder-name: "terraform-state/${{ inputs.team-name }}"
7. Document Destruction Reasons
Log why resources are being destroyed:
- name: Log Destruction Reason
run: |
echo "Destroying ${{ inputs.environment }} infrastructure" >> destruction.log
echo "Reason: ${{ inputs.reason }}" >> destruction.log
echo "Initiated by: ${{ github.actor }}" >> destruction.log
echo "Timestamp: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> destruction.log
8. Verify State Before Destroy
Check state file accessibility:
- name: Verify Terraform State
run: |
terraform init
terraform state list
π§ Troubleshooting
Issue 1: State Lock Error
Symptom: "Error acquiring the state lock"
Solution:
# Use terraform-ops workflow to force unlock
uses: dojo360/pipelines-workflows/.github/workflows/terraform-ops.yml@beta
with:
aide-id: "ABC12345"
cloud-type: "awsOptum"
domain: "platform"
environment: "dev"
team-name: "platform-team"
lock-id: "abc123-def456-ghi789" # From error message
Issue 2: Resources Not Destroyed
Symptom: Destroy completes but resources remain
Possible Causes:
- Resources have deletion protection enabled
- Dependencies prevent destruction
- State file out of sync with actual infrastructure
Solution:
# Refresh state
terraform refresh
# List resources in state
terraform state list
# Check for deletion protection
aws rds describe-db-instances --query 'DBInstances[*].[DBInstanceIdentifier,DeletionProtection]'
Issue 3: OIDC Authentication Failure
Symptom: "Error: Unable to assume role"
Solution:
- Verify OIDC configuration in AWS/Azure
- Check IAM role trust policy includes GitHub OIDC provider
- Confirm
id-token: writepermission in workflow
permissions:
id-token: write
contents: read
Issue 4: Backend Access Denied
Symptom: "Error: Failed to get existing workspaces"
Solution:
# Verify backend credentials
backend-type: "azurerm"
azurerm-backend-configure-inline: true
# Check service principal permissions on storage account
# Minimum required: Storage Blob Data Contributor
Issue 5: Approval Timeout
Symptom: Workflow times out waiting for approval
Solution:
- Check GitHub environment protection rules
- Verify required reviewers have notifications enabled
- Consider increasing timeout or removing approval for non-prod
# Adjust timeout in job configuration
jobs:
destroy:
timeout-minutes: 60 # Increase from default
π Related Workflows
- Infrastructure Workflow: Deploy infrastructure (inverse of destroy)
- Infrastructure Promotion: Multi-environment deployment
- Terraform Ops: State management operations (unlock)
π Additional Resources
Documentation
Sample Applications
Support
- Contribution: Submit improvements to destroy.yml
- Issues: Report workflow issues in dojo360/pipelines-workflows repository
β οΈ Known Issues
- None at this time: The Terraform Destroy workflow is stable and production-ready
π Learning Path
- Start Here: Review this skill document completely
- Practice: Use Example 1 (Basic Destroy) in development environment
- Experiment: Try Example 4 (Plan-Only) to understand impact
- Advance: Implement Example 2 or 3 for cloud-specific scenarios
- Production: Use Example 6 for cost optimization strategies
Recommended Template Order
basic-destroy.yml- Simple single-environment destroyplan-only-review.yml- Review before destructionazure-destroy-azurerm.yml- Azure-specific patternsaws-destroy-s3-backend.yml- AWS-specific patternsscheduled-cost-savings.yml- Automated teardown schedulesmulti-environment-destroy.yml- Destroy multiple environments
Last Updated: 2025-01-28
Workflow Version: [email protected] (beta)
Skill Status: Complete β
Related Assets
github-workflows-dojo360-azure-infrastructure
Deploy Azure infrastructure using Terraform with PCAM vaulted access and native Azure authentication through Dojo360 Azure Infrastructure workflow
Owner: pcorazao
github-workflows-dojo360-container-cd
Deploy containerized applications to AWS ECS/Azure ACS using Dojo360 Container CD workflow with blue-green and rolling update strategies
Owner: pcorazao
github-workflows-dojo360-container-promotion
Multi-environment container deployment promotion through prescribed deployment paths with automated approval gates and E2E testing
Owner: pcorazao
github-workflows-dojo360-database
Automate database schema updates using Liquibase via the Dojo360 database workflow (with rollback and validation patterns)
Owner: pcorazao
github-workflows-dojo360-database-promotion
Promote Liquibase database changes across environments (devβqaβcertβprod) with deployment-path validation and approval gates
Owner: pcorazao
github-workflows-dojo360-dockerfile-ci
Build and scan container images from a Dockerfile using Optum golden images and the recommended UHG reusable workflow
Owner: pcorazao

