Skip to content

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

active
IDE:
claude
codex
vscode
Version:
1.0.0
Owner:pcorazao
github-actions
workflow
dojo360

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 destroy across 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: true to 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

2. OIDC Configuration (for awsOptum and azureOptum)

3. GitHub Environment Setup

  • Environments created matching your environment input
  • 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

InputDescriptionExample
aide-idAide ID from aide.optum.com for metadata retrieval"ABC12345"
cloud-typeCloud provider type (see Supported Cloud Types)"awsOptum", "azureOptum", "gcp", "awsChc20"
domainDomain for metadata retrieval"platform", "data"
environmentTarget environment for destruction (defines approvals)"dev", "qa", "prd"
team-nameTeam name for metadata retrieval"platform-team"

Optional Inputs - Backend Configuration

InputDescriptionDefault
backend-typeBackend type for Terraform state"azurerm"
azurerm-backend-configure-inlineConfigure Azure RM backend inlinetrue
remote-state-file-nameRemote state filename""
remote-state-folder-nameRemote state folder name""

Optional Inputs - Cloud-Specific

InputDescriptionDefault
aws-role-to-assumeAWS IAM Role ARN for destruction""
azure-roleAzure Service Principal role"contributor"
pcam-rolePCAM role for Azure"contributor"

Optional Inputs - Terraform Configuration

InputDescriptionDefault
terraform-directoryDirectory with Terraform code"."
terraform-versionTerraform version to use"1.9.2"
terraform-loggingTerraform logging level"off"
terraform-provider-network-mirrorProvider mirror URL"https://repo1.uhc.com/artifactory/api/terraform/terraform-virtual/providers/"
terraform-vars-filesComma-separated tfvars files""
terraform-vars-valuesJSON string of tfvars""

Optional Inputs - Execution Control

InputDescriptionDefault
run-plan-onlyOnly run terraform plan, don't destroyfalse
runner-labelsComma-separated runner labels""

Optional Inputs - Secrets Management

InputDescriptionDefault
prm-base-urlPRM instance base URL"https://prm.optum.com"
terraform-volcan-secretsVolcan secrets mapping (comma-separated)""
volcan-base-urlVolcan instance base URL"volcan-cloud.optum.com"

Optional Inputs - Terraform Enterprise

InputDescriptionDefault
tfe-hostnameTerraform Enterprise hostname""
tfe-organizationTFE organization name""
tfe-workspaceTFE 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:

  1. Resources have deletion protection enabled
  2. Dependencies prevent destruction
  3. 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:

  1. Verify OIDC configuration in AWS/Azure
  2. Check IAM role trust policy includes GitHub OIDC provider
  3. Confirm id-token: write permission 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:

  1. Check GitHub environment protection rules
  2. Verify required reviewers have notifications enabled
  3. Consider increasing timeout or removing approval for non-prod
# Adjust timeout in job configuration
jobs:
  destroy:
    timeout-minutes: 60  # Increase from default

πŸ”— Related Workflows


πŸ“š Additional Resources

Documentation

Sample Applications

Support


⚠️ Known Issues

  • None at this time: The Terraform Destroy workflow is stable and production-ready

πŸŽ“ Learning Path

  1. Start Here: Review this skill document completely
  2. Practice: Use Example 1 (Basic Destroy) in development environment
  3. Experiment: Try Example 4 (Plan-Only) to understand impact
  4. Advance: Implement Example 2 or 3 for cloud-specific scenarios
  5. Production: Use Example 6 for cost optimization strategies

Recommended Template Order

  1. basic-destroy.yml - Simple single-environment destroy
  2. plan-only-review.yml - Review before destruction
  3. azure-destroy-azurerm.yml - Azure-specific patterns
  4. aws-destroy-s3-backend.yml - AWS-specific patterns
  5. scheduled-cost-savings.yml - Automated teardown schedules
  6. multi-environment-destroy.yml - Destroy multiple environments

Last Updated: 2025-01-28 Workflow Version: [email protected] (beta) Skill Status: Complete βœ…

Related Assets