Terraform: Beginner to Expert

    Part I: Foundations

    Chapter 1: Introduction to Infrastructure as Code

    • The evolution of infrastructure management
    • Challenges of manual infrastructure provisioning
    • The case for infrastructure as code (IaC)
    • How Terraform addresses these challenges

    Chapter 2: Terraform Architecture

    • Core components and workflow
    • HCL syntax and structure
    • Providers, resources, and modules
    • Terraform state management
    • Terraform CLI essentials

    Chapter 3: Setting Up Your Terraform Environment

    • Installation across operating systems
    • Configuration best practices
    • Authentication and secrets management
    • Backend configuration
    • Integration with version control

    Part II: Multi-Cloud Infrastructure Deployment

    Chapter 4: AWS Infrastructure Management

    • AWS provider configuration
    • Core resource types
    • IAM and security implementation
    • Network architecture
    • Storage solutions

    Chapter 5: Azure Resource Provisioning

    • Azure provider setup
    • Resource groups and organization
    • Virtual networks and security
    • PaaS service deployment
    • Hybrid connectivity

    Chapter 6: Google Cloud Platform

    • GCP provider configuration
    • Project structure
    • Network design patterns
    • GCP-specific services
    • Performance optimization

    Chapter 7: Multi-Cloud and Hybrid Deployments

    • Cross-provider architecture
    • Managing multiple providers
    • Abstraction strategies
    • Data sharing between clouds
    • Hybrid cloud-on-premises solutions

    Part III: Production Techniques

    Chapter 8: State Management

    • Remote state configuration
    • State locking mechanisms
    • State file security
    • Import and migration strategies
    • State file troubleshooting

    Chapter 9: Security Best Practices

    • Secrets management
    • IAM implementation patterns
    • Network security configurations
    • Compliance as code
    • Security scanning integration

    Chapter 10: Testing Infrastructure Code

    • Unit testing with Terraform
    • Integration testing strategies
    • Policy validation with Sentinel
    • Automated validation workflows
    • Test-driven infrastructure development

    Part IV: DevOps Integration

    Chapter 11: CI/CD Pipeline Integration

    • Jenkins, GitHub Actions, and GitLab CI examples
    • Automated plan and apply workflows
    • Change management integration
    • Approval processes
    • Release automation

    Chapter 12: Infrastructure as Code Ecosystem

    • Integrating with Packer for image management
    • Ansible, Chef, and Puppet integration
    • Vault for secrets management
    • Consul for service discovery and configuration
    • Kubernetes deployment with Terraform

    Chapter 13: Monitoring and Observability

    • Infrastructure drift detection
    • Cost management and optimization
    • Performance monitoring
    • Disaster recovery strategies
    • Comprehensive logging

    Part V: Advanced Topics

    Chapter 14: Custom Providers and Extensions

    • Building custom providers
    • Using and creating provider plugins
    • Extending Terraform’s functionality
    • Contributing to the Terraform ecosystem

    Chapter 15: Enterprise Patterns and Case Studies

    • Financial services implementation
    • Healthcare compliance scenarios
    • Scaling for large enterprises
    • Multi-region, multi-account strategies

    Chapter 16: Future Trends in Infrastructure Management

    • Terraform Cloud and Terraform Enterprise
    • Policy as code evolution
    • GitOps workflows
    • AI and ML in infrastructure optimization

    Part I: Foundations

    Chapter 1: Introduction to Infrastructure as Code

    Infrastructure management has evolved dramatically over the past decades. Initially, system administrators manually provisioned servers and networks through web consoles or command-line interfaces, a process that was error-prone, time-consuming, and difficult to scale. As cloud computing matured, programmatic APIs emerged, enabling infrastructure to be defined and managed through code.

    Manual infrastructure provisioning presents several challenges:

    • Inconsistency: Human error leads to configuration drift
    • Documentation burden: Keeping track of infrastructure state
    • Time consumption: Repetitive manual processes waste valuable time
    • Lack of auditability: Difficult to track who changed what and when
    • Limited collaboration: Siloed knowledge and processes

    Infrastructure as Code (IaC) addresses these issues by:

    • Providing reproducible, code-defined infrastructure
    • Enabling version control for infrastructure definitions
    • Creating consistent environments across development, testing, and production
    • Reducing time to deploy new environments
    • Supporting collaboration through code review

    HashiCorp Terraform revolutionizes infrastructure management by offering:

    • A unified workflow across all major cloud providers
    • A simple, declarative configuration language
    • A state-based approach to infrastructure management
    • Dependency management between resources
    • Plan and apply workflow for safe changes
    flowchart LR
        A[Manual Provisioning] --> B[Point-and-Click Console]
        B --> C[Infrastructure Creation]
        C --> D[Configuration Drift]
        D --> A
    
        E[Terraform Code] --> F[Version Control]
        F --> G[Terraform Plan]
        G --> H[Terraform Apply]
        H --> I[Consistent Infrastructure]
        I --> E

    Chapter 2: Terraform Architecture

    Terraform’s architecture is built around a core set of components that work together to manage infrastructure across different platforms:

    Core Components:

    • Configuration Files: HCL (HashiCorp Configuration Language) files that define infrastructure
    • Providers: Plugins that interact with APIs of service providers
    • Resources: The infrastructure objects managed by Terraform
    • State: A representation of the real infrastructure and resource metadata
    • Modules: Reusable, encapsulated collections of resources

    HCL Syntax and Structure: Terraform uses HashiCorp Configuration Language (HCL), designed specifically for defining infrastructure:

    # Provider configuration
    provider "aws" {
      region = "us-west-2"
      profile = "production"
    }
    
    # Resource definition
    resource "aws_instance" "web_server" {
      ami           = "ami-0c55b159cbfafe1f0"
      instance_type = "t2.micro"
    
      tags = {
        Name = "WebServer"
        Environment = "Production"
      }
    }
    
    # Output values
    output "instance_ip" {
      value = aws_instance.web_server.public_ip
      description = "The public IP of the web server"
    }
    HCL

    Terraform Workflow:

    sequenceDiagram
        participant User
        participant Terraform CLI
        participant Providers
        participant Infrastructure
        participant State
    
        User->>Terraform CLI: terraform init
        Terraform CLI->>Providers: Download providers
        User->>Terraform CLI: terraform plan
        Terraform CLI->>State: Read current state
        Terraform CLI->>Providers: Check current infrastructure
        Providers->>Infrastructure: API calls to check resources
        Providers-->>Terraform CLI: Return resource status
        Terraform CLI-->>User: Show execution plan
    
        User->>Terraform CLI: terraform apply
        Terraform CLI->>Providers: Create/Update/Delete resources
        Providers->>Infrastructure: API calls to modify resources
        Providers-->>Terraform CLI: Return results
        Terraform CLI->>State: Update state file
        Terraform CLI-->>User: Show apply results

    Terraform State Management:

    • State files track the real-world resources
    • Mapping between Terraform configuration and real resources
    • Metadata for dependency management
    • Performance optimization information
    • Sensitive data storage considerations

    Terraform CLI Essentials:

    • terraform init – Initialize a Terraform working directory
    • terraform plan – Create an execution plan
    • terraform apply – Apply the changes required to reach the desired state
    • terraform destroy – Destroy the Terraform-managed infrastructure
    • terraform fmt – Format configurations for readability
    • terraform validate – Validate configuration syntax
    • terraform state – Advanced state management
    • terraform import – Import existing infrastructure into Terraform

    Chapter 3: Setting Up Your Terraform Environment

    Installation:

    Terraform can be installed across various operating systems:

    Linux:

    curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
    sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
    sudo apt-get update && sudo apt-get install terraform
    Bash

    macOS:

    brew tap hashicorp/tap
    brew install hashicorp/tap/terraform
    Bash

    Windows:

    choco install terraform
    # or
    winget install HashiCorp.Terraform
    Bash

    Configuration Best Practices:

    • Organize configurations by environment or component
    • Use variables for reusable values
    • Structure projects with clear separation: project/ ├── main.tf # Main configuration file ├── variables.tf # Variable definitions ├── outputs.tf # Output definitions ├── providers.tf # Provider configurations ├── terraform.tfvars # Variable values (gitignored) └── modules/ # Custom modules directory └── networking/ # Example module
    • Use terraform validate before applying changes
    • Implement consistent naming conventions

    Authentication and Secrets Management:

    • Use environment variables for provider credentials
    • Leverage cloud provider credential helpers
    • Consider HashiCorp Vault for enterprise secret management
    • Never hardcode secrets in configuration files
    • Use .gitignore to prevent committing sensitive files

    Backend Configuration: Remote backends store Terraform state files securely and enable collaboration:

    terraform {
      backend "s3" {
        bucket         = "terraform-states"
        key            = "production/network/terraform.tfstate"
        region         = "us-east-1"
        encrypt        = true
        dynamodb_table = "terraform-lock"
      }
    }
    HCL

    Common backend options include:

    • S3 with DynamoDB locking (AWS)
    • Azure Blob Storage (Azure)
    • Google Cloud Storage (GCP)
    • HashiCorp Terraform Cloud
    • Consul

    Version Control Integration:

    • Store configurations in Git repositories
    • Use branches for environment isolation
    • Consider using Git hooks for validation
    • Implement branch protection rules for production code

    Part II: Multi-Cloud Infrastructure Deployment

    Chapter 4: AWS Infrastructure Management

    AWS Provider Configuration:

    provider "aws" {
      region = "us-west-2"
    
      # Optional explicit credentials (better to use environment variables)
      # access_key = "AKIAIOSFODNN7EXAMPLE"
      # secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
    
      default_tags {
        tags = {
          Environment = "Production"
          ManagedBy   = "Terraform"
          Owner       = "Infrastructure Team"
        }
      }
    }
    HCL

    Core Resource Types:

    Network Infrastructure:

    # Create a VPC
    resource "aws_vpc" "main" {
      cidr_block           = "10.0.0.0/16"
      enable_dns_hostnames = true
    
      tags = {
        Name = "MainVPC"
      }
    }
    
    # Create subnets
    resource "aws_subnet" "public" {
      count             = 2
      vpc_id            = aws_vpc.main.id
      cidr_block        = "10.0.${count.index}.0/24"
      availability_zone = "us-west-2${["a", "b"][count.index]}"
    
      tags = {
        Name = "Public-${count.index}"
      }
    }
    
    # Create internet gateway
    resource "aws_internet_gateway" "main" {
      vpc_id = aws_vpc.main.id
    
      tags = {
        Name = "MainIGW"
      }
    }
    
    # Create route table
    resource "aws_route_table" "public" {
      vpc_id = aws_vpc.main.id
    
      route {
        cidr_block = "0.0.0.0/0"
        gateway_id = aws_internet_gateway.main.id
      }
    
      tags = {
        Name = "PublicRT"
      }
    }
    HCL

    Compute Resources:

    # Create security group
    resource "aws_security_group" "web" {
      name        = "web-sg"
      description = "Allow web traffic"
      vpc_id      = aws_vpc.main.id
    
      ingress {
        from_port   = 80
        to_port     = 80
        protocol    = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
      }
    
      ingress {
        from_port   = 443
        to_port     = 443
        protocol    = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
      }
    
      egress {
        from_port   = 0
        to_port     = 0
        protocol    = "-1"
        cidr_blocks = ["0.0.0.0/0"]
      }
    }
    
    # Create EC2 instance
    resource "aws_instance" "web" {
      ami                    = "ami-0c55b159cbfafe1f0"
      instance_type          = "t3.micro"
      subnet_id              = aws_subnet.public[0].id
      vpc_security_group_ids = [aws_security_group.web.id]
    
      root_block_device {
        volume_size = 20
        volume_type = "gp3"
      }
    
      tags = {
        Name = "WebServer"
      }
    }
    HCL

    IAM and Security Implementation:

    # Create IAM role
    resource "aws_iam_role" "web_server" {
      name = "web-server-role"
    
      assume_role_policy = jsonencode({
        Version = "2012-10-17"
        Statement = [
          {
            Action = "sts:AssumeRole"
            Effect = "Allow"
            Principal = {
              Service = "ec2.amazonaws.com"
            }
          }
        ]
      })
    }
    
    # Create IAM policy
    resource "aws_iam_policy" "s3_access" {
      name        = "s3-read-access"
      description = "Allow S3 read access"
    
      policy = jsonencode({
        Version = "2012-10-17"
        Statement = [
          {
            Action = [
              "s3:GetObject",
              "s3:ListBucket"
            ]
            Effect   = "Allow"
            Resource = [
              "arn:aws:s3:::example-bucket",
              "arn:aws:s3:::example-bucket/*"
            ]
          }
        ]
      })
    }
    
    # Attach policy to role
    resource "aws_iam_role_policy_attachment" "s3_access" {
      role       = aws_iam_role.web_server.name
      policy_arn = aws_iam_policy.s3_access.arn
    }
    
    # Create instance profile
    resource "aws_iam_instance_profile" "web_server" {
      name = "web-server-profile"
      role = aws_iam_role.web_server.name
    }
    
    # Update instance to use profile
    resource "aws_instance" "web" {
      # ... other configuration ...
      iam_instance_profile = aws_iam_instance_profile.web_server.name
    }
    HCL

    Network Architecture:

    flowchart TD
        A[Internet Gateway] --- B[VPC: 10.0.0.0/16]
        B --- C[Public Subnet: 10.0.0.0/24]
        B --- D[Public Subnet: 10.0.1.0/24]
        B --- E[Private Subnet: 10.0.2.0/24]
        B --- F[Private Subnet: 10.0.3.0/24]
        A --- G[Public Route Table]
        G --- C
        G --- D
        H[NAT Gateway] --- I[Private Route Table]
        I --- E
        I --- F
        H --- C

    Storage Solutions:

    # Create S3 bucket
    resource "aws_s3_bucket" "assets" {
      bucket = "my-company-assets"
    
      tags = {
        Name = "AssetsStorage"
      }
    }
    
    # Configure bucket versioning
    resource "aws_s3_bucket_versioning" "assets" {
      bucket = aws_s3_bucket.assets.id
    
      versioning_configuration {
        status = "Enabled"
      }
    }
    
    # Configure bucket encryption
    resource "aws_s3_bucket_server_side_encryption_configuration" "assets" {
      bucket = aws_s3_bucket.assets.id
    
      rule {
        apply_server_side_encryption_by_default {
          sse_algorithm = "AES256"
        }
      }
    }
    HCL

    Chapter 5: Azure Resource Provisioning

    Azure Provider Setup:

    provider "azurerm" {
      features {}
    
      subscription_id = var.subscription_id
      tenant_id       = var.tenant_id
      # client_id and client_secret better handled via environment variables
    }
    
    # Resource group
    resource "azurerm_resource_group" "main" {
      name     = "production-resources"
      location = "East US"
    
      tags = {
        environment = "Production"
        managed_by  = "Terraform"
      }
    }
    HCL

    Resource Groups and Organization:

    # Network resource group
    resource "azurerm_resource_group" "network" {
      name     = "network-resources"
      location = "East US"
    
      tags = {
        environment = "Production"
        component   = "Network"
      }
    }
    
    # Application resource group
    resource "azurerm_resource_group" "application" {
      name     = "app-resources"
      location = "East US"
    
      tags = {
        environment = "Production"
        component   = "Application"
      }
    }
    
    # Database resource group
    resource "azurerm_resource_group" "database" {
      name     = "db-resources"
      location = "East US"
    
      tags = {
        environment = "Production"
        component   = "Database"
      }
    }
    HCL

    Virtual Networks and Security:

    # Virtual network
    resource "azurerm_virtual_network" "main" {
      name                = "main-vnet"
      address_space       = ["10.0.0.0/16"]
      location            = azurerm_resource_group.network.location
      resource_group_name = azurerm_resource_group.network.name
    }
    
    # Subnets
    resource "azurerm_subnet" "web" {
      name                 = "web-subnet"
      resource_group_name  = azurerm_resource_group.network.name
      virtual_network_name = azurerm_virtual_network.main.name
      address_prefixes     = ["10.0.1.0/24"]
    }
    
    resource "azurerm_subnet" "app" {
      name                 = "app-subnet"
      resource_group_name  = azurerm_resource_group.network.name
      virtual_network_name = azurerm_virtual_network.main.name
      address_prefixes     = ["10.0.2.0/24"]
    }
    
    resource "azurerm_subnet" "db" {
      name                 = "db-subnet"
      resource_group_name  = azurerm_resource_group.network.name
      virtual_network_name = azurerm_virtual_network.main.name
      address_prefixes     = ["10.0.3.0/24"]
    }
    
    # Network security group
    resource "azurerm_network_security_group" "web" {
      name                = "web-nsg"
      location            = azurerm_resource_group.network.location
      resource_group_name = azurerm_resource_group.network.name
    
      security_rule {
        name                       = "HTTP"
        priority                   = 100
        direction                  = "Inbound"
        access                     = "Allow"
        protocol                   = "Tcp"
        source_port_range          = "*"
        destination_port_range     = "80"
        source_address_prefix      = "*"
        destination_address_prefix = "*"
      }
    
      security_rule {
        name                       = "HTTPS"
        priority                   = 110
        direction                  = "Inbound"
        access                     = "Allow"
        protocol                   = "Tcp"
        source_port_range          = "*"
        destination_port_range     = "443"
        source_address_prefix      = "*"
        destination_address_prefix = "*"
      }
    }
    
    # Associate NSG to subnet
    resource "azurerm_subnet_network_security_group_association" "web" {
      subnet_id                 = azurerm_subnet.web.id
      network_security_group_id = azurerm_network_security_group.web.id
    }
    HCL

    PaaS Service Deployment:

    # App Service Plan
    resource "azurerm_app_service_plan" "main" {
      name                = "app-service-plan"
      location            = azurerm_resource_group.application.location
      resource_group_name = azurerm_resource_group.application.name
      kind                = "Linux"
      reserved            = true
    
      sku {
        tier = "Standard"
        size = "S1"
      }
    }
    
    # App Service
    resource "azurerm_app_service" "web" {
      name                = "webapp-${var.environment}"
      location            = azurerm_resource_group.application.location
      resource_group_name = azurerm_resource_group.application.name
      app_service_plan_id = azurerm_app_service_plan.main.id
    
      site_config {
        linux_fx_version = "DOCKER|nginx:latest"
        always_on        = true
      }
    
      app_settings = {
        "WEBSITES_ENABLE_APP_SERVICE_STORAGE" = "false"
        "DOCKER_REGISTRY_SERVER_URL"          = "https://index.docker.io"
      }
    }
    
    # SQL Server
    resource "azurerm_sql_server" "main" {
      name                         = "sql-server-${var.environment}"
      resource_group_name          = azurerm_resource_group.database.name
      location                     = azurerm_resource_group.database.location
      version                      = "12.0"
      administrator_login          = var.db_admin_username
      administrator_login_password = var.db_admin_password
    }
    
    # SQL Database
    resource "azurerm_sql_database" "main" {
      name                = "sql-db-${var.environment}"
      resource_group_name = azurerm_resource_group.database.name
      location            = azurerm_resource_group.database.location
      server_name         = azurerm_sql_server.main.name
    
      edition                          = "Standard"
      requested_service_objective_name = "S1"
    }
    HCL

    Hybrid Connectivity:

    # Virtual Network Gateway
    resource "azurerm_virtual_network_gateway" "main" {
      name                = "vnet-gateway"
      location            = azurerm_resource_group.network.location
      resource_group_name = azurerm_resource_group.network.name
    
      type     = "Vpn"
      vpn_type = "RouteBased"
    
      active_active = false
      enable_bgp    = false
      sku           = "VpnGw1"
    
      ip_configuration {
        name                          = "vnetGatewayConfig"
        public_ip_address_id          = azurerm_public_ip.vpn.id
        private_ip_address_allocation = "Dynamic"
        subnet_id                     = azurerm_subnet.gateway.id
      }
    }
    
    # Local Network Gateway (on-premises endpoint)
    resource "azurerm_local_network_gateway" "onpremise" {
      name                = "onpremise"
      location            = azurerm_resource_group.network.location
      resource_group_name = azurerm_resource_group.network.name
      gateway_address     = var.onpremise_vpn_public_ip
      address_space       = ["192.168.0.0/16"]
    }
    
    # Connection between Azure and on-premises
    resource "azurerm_virtual_network_gateway_connection" "onpremise" {
      name                = "azure-to-onpremise"
      location            = azurerm_resource_group.network.location
      resource_group_name = azurerm_resource_group.network.name
    
      type                       = "IPsec"
      virtual_network_gateway_id = azurerm_virtual_network_gateway.main.id
      local_network_gateway_id   = azurerm_local_network_gateway.onpremise.id
    
      shared_key = var.vpn_shared_key
    }
    HCL

    Chapter 6: Google Cloud Platform

    GCP Provider Configuration:

    provider "google" {
      project     = var.project_id
      region      = var.region
      zone        = var.zone
    }
    
    provider "google-beta" {
      project     = var.project_id
      region      = var.region
      zone        = var.zone
    }
    HCL

    Project Structure:

    # Create a GCP project (requires organization)
    resource "google_project" "my_project" {
      name            = "My Project"
      project_id      = "my-project-id"
      org_id          = var.org_id
      billing_account = var.billing_account
    }
    
    # Enable required APIs
    resource "google_project_service" "compute" {
      project = google_project.my_project.project_id
      service = "compute.googleapis.com"
    }
    
    resource "google_project_service" "container" {
      project = google_project.my_project.project_id
      service = "container.googleapis.com"
    }
    
    resource "google_project_service" "cloudsql" {
      project = google_project.my_project.project_id
      service = "sqladmin.googleapis.com"
    }
    HCL

    Network Design Patterns:

    # VPC network
    resource "google_compute_network" "vpc_network" {
      name                    = "vpc-network"
      auto_create_subnetworks = false
    }
    
    # Subnets
    resource "google_compute_subnetwork" "web_subnet" {
      name          = "web-subnet"
      ip_cidr_range = "10.0.1.0/24"
      region        = var.region
      network       = google_compute_network.vpc_network.id
    }
    
    resource "google_compute_subnetwork" "app_subnet" {
      name          = "app-subnet"
      ip_cidr_range = "10.0.2.0/24"
      region        = var.region
      network       = google_compute_network.vpc_network.id
    }
    
    # Firewall rules
    resource "google_compute_firewall" "web" {
      name    = "allow-web"
      network = google_compute_network.vpc_network.name
    
      allow {
        protocol = "tcp"
        ports    = ["80", "443"]
      }
    
      source_ranges = ["0.0.0.0/0"]
      target_tags   = ["web"]
    }
    
    resource "google_compute_firewall" "ssh" {
      name    = "allow-ssh"
      network = google_compute_network.vpc_network.name
    
      allow {
        protocol = "tcp"
        ports    = ["22"]
      }
    
      source_ranges = [var.admin_cidr_block]
    }
    HCL

    GCP-Specific Services:

    # GKE cluster
    resource "google_container_cluster" "primary" {
      name     = "my-gke-cluster"
      location = var.region
    
      remove_default_node_pool = true
      initial_node_count       = 1
    
      network    = google_compute_network.vpc_network.name
      subnetwork = google_compute_subnetwork.app_subnet.name
    
      master_auth {
        client_certificate_config {
          issue_client_certificate = false
        }
      }
    }
    
    resource "google_container_node_pool" "primary_preemptible_nodes" {
      name       = "my-node-pool"
      location   = var.region
      cluster    = google_container_cluster.primary.name
      node_count = 3
    
      node_config {
        preemptible  = true
        machine_type = "e2-medium"
    
        service_account = google_service_account.gke_sa.email
    
        oauth_scopes = [
          "https://www.googleapis.com/auth/cloud-platform"
        ]
      }
    }
    
    # Cloud SQL
    resource "google_sql_database_instance" "main" {
      name             = "my-database-instance"
      database_version = "POSTGRES_13"
      region           = var.region
    
      settings {
        tier = "db-f1-micro"
    
        ip_configuration {
          ipv4_enabled    = false
          private_network = google_compute_network.vpc_network.id
        }
      }
    }
    
    # Cloud Storage
    resource "google_storage_bucket" "static" {
      name          = "static-assets-bucket"
      location      = "US"
      force_destroy = true
    
      uniform_bucket_level_access = true
    
      website {
        main_page_suffix = "index.html"
        not_found_page   = "404.html"
      }
    }
    HCL

    Performance Optimization:

    # Instance template for managed instance group
    resource "google_compute_instance_template" "web_server" {
      name_prefix  = "web-server-template-"
      machine_type = "e2-medium"
    
      disk {
        source_image = "debian-cloud/debian-10"
        auto_delete  = true
        boot         = true
        disk_type    = "pd-ssd"
        disk_size_gb = 20
      }
    
      network_interface {
        network    = google_compute_network.vpc_network.name
        subnetwork = google_compute_subnetwork.web_subnet.name
    
        access_config {
          // Ephemeral IP
        }
      }
    
      metadata_startup_script = file("startup.sh")
    
      service_account {
        email  = google_service_account.web_sa.email
        scopes = ["cloud-platform"]
      }
    
      tags = ["web"]
    
      lifecycle {
        create_before_destroy = true
      }
    }
    
    # Managed instance group
    resource "google_compute_region_instance_group_manager" "web_servers" {
      name               = "web-server-group"
      base_instance_name = "web"
      region             = var.region
    
      version {
        instance_template = google_compute_instance_template.web_server.id
      }
    
      target_size = 3
    
      named_port {
        name = "http"
        port = 80
      }
    
      auto_healing_policies {
        health_check      = google_compute_health_check.web.id
        initial_delay_sec = 300
      }
    }
    
    # Load balancing
    resource "google_compute_global_address" "default" {
      name = "lb-ip-address"
    }
    
    resource "google_compute_global_forwarding_rule" "default" {
      name       = "global-rule"
      target     = google_compute_target_http_proxy.default.id
      port_range = "80"
      ip_address = google_compute_global_address.default.address
    }
    
    resource "google_compute_target_http_proxy" "default" {
      name    = "http-proxy"
      url_map = google_compute_url_map.default.id
    }
    
    resource "google_compute_url_map" "default" {
      name            = "url-map"
      default_service = google_compute_backend_service.default.id
    }
    
    resource "google_compute_backend_service" "default" {
      name        = "backend-service"
      port_name   = "http"
      protocol    = "HTTP"
      timeout_sec = 10
    
      health_checks = [google_compute_health_check.web.id]
    
      backend {
        group = google_compute_region_instance_group_manager.web_servers.instance_group
      }
    }
    
    resource "google_compute_health_check" "web" {
      name               = "web-health-check"
      check_interval_sec = 5
      timeout_sec        = 5
    
      http_health_check {
        port         = 80
        request_path = "/healthz"
      }
    }
    HCL

    Chapter 7: Multi-Cloud and Hybrid Deployments

    Cross-Provider Architecture:

    # Configure multiple providers
    provider "aws" {
      region = "us-west-2"
      alias  = "west"
    }
    
    provider "aws" {
      region = "us-east-1"
      alias  = "east"
    }
    
    provider "azurerm" {
      features {}
      alias = "primary"
    }
    
    provider "google" {
      project = var.gcp_project
      region  = "us-central1"
      alias   = "gcp"
    }
    
    # Create resources across providers
    module "aws_west_resources" {
      source = "./modules/aws_infrastructure"
    
      providers = {
        aws = aws.west
      }
    
      vpc_cidr           = "10.0.0.0/16"
      environment        = "production"
      availability_zones = ["us-west-2a", "us-west-2b"]
    }
    
    module "aws_east_resources" {
      source = "./modules/aws_infrastructure"
    
      providers = {
        aws = aws.east
      }
    
      vpc_cidr           = "10.1.0.0/16"
      environment        = "production"
      availability_zones = ["us-east-1a", "us-east-1b"]
    }
    
    module "azure_resources" {
      source = "./modules/azure_infrastructure"
    
      providers = {
        azurerm = azurerm.primary
      }
    
      resource_group_location = "East US"
      vnet_address_space      = ["10.2.0.0/16"]
      environment             = "production"
    }
    HCL

    Managing Multiple Providers:

    # Use provider-agnostic module with provider-specific implementations
    module "database" {
      source = "./modules/database"
    
      # Common parameters
      name        = "production-db"
      environment = "production"
    
      # Provider-specific parameters
      aws_enabled   = true
      azure_enabled = true
      gcp_enabled   = false
    
      # Provider objects
      providers = {
        aws     = aws.west
        azurerm = azurerm.primary
        google  = google.gcp
      }
    }
    
    # Output cross-cloud information
    output "database_endpoints" {
      value = {
        aws   = module.database.aws_endpoint
        azure = module.database.azure_endpoint
        gcp   = module.database.gcp_endpoint
      }
    }
    HCL

    Abstraction Strategies: Creating multi-cloud modules with conditional resource creation:

    # Virtual machine module supporting multiple clouds
    # main.tf
    variable "aws_enabled" {
      description = "Whether to create AWS resources"
      type        = bool
      default     = false
    }
    
    variable "azure_enabled" {
      description = "Whether to create Azure resources"
      type        = bool
      default     = false
    }
    
    variable "name" {
      description = "Name for the virtual machine"
      type        = string
    }
    
    # AWS implementation
    resource "aws_instance" "vm" {
      count = var.aws_enabled ? 1 : 0
    
      ami           = "ami-0c55b159cbfafe1f0"
      instance_type = "t3.micro"
    
      tags = {
        Name = var.name
      }
    }
    
    # Azure implementation
    resource "azurerm_linux_virtual_machine" "vm" {
      count = var.azure_enabled ? 1 : 0
    
      name                  = var.name
      resource_group_name   = var.resource_group_name
      location              = var.location
      size                  = "Standard_B1s"
      admin_username        = var.admin_username
      network_interface_ids = [var.nic_id]
    
      admin_ssh_key {
        username   = var.admin_username
        public_key = var.ssh_public_key
      }
    
      os_disk {
        caching              = "ReadWrite"
        storage_account_type = "Standard_LRS"
      }
    
      source_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "18.04-LTS"
        version   = "latest"
      }
    }
    
    # Provide unified outputs
    output "public_ip" {
      value = coalesce(
        var.aws_enabled ? aws_instance.vm[0].public_ip : null,
        var.azure_enabled ? azurerm_linux_virtual_machine.vm[0].public_ip_address : null
      )
    }
    HCL

    Data Sharing Between Clouds:

    # AWS S3 bucket for cross-cloud data sharing
    resource "aws_s3_bucket" "shared_data" {
      bucket = "cross-cloud-shared-data"
    
      tags = {
        Name = "SharedData"
      }
    }
    
    # Azure Storage Account with cross-cloud access
    resource "azurerm_storage_account" "sync" {
      name                     = "crosscloudsync"
      resource_group_name      = azurerm_resource_group.main.name
      location                 = azurerm_resource_group.main.location
      account_tier             = "Standard"
      account_replication_type = "LRS"
    
      network_rules {
        default_action             = "Deny"
        ip_rules                   = ["0.0.0.0/0"] # Configure appropriate IPs
        virtual_network_subnet_ids = [azurerm_subnet.sync.id]
      }
    }
    
    # GCP data transfer service to sync from AWS S3
    resource "google_storage_transfer_job" "s3_to_gcs" {
      description = "S3 to GCS transfer job"
    
      transfer_spec {
        aws_s3_data_source {
          bucket_name = aws_s3_bucket.shared_data.bucket
          aws_access_key {
            access_key_id     = var.aws_access_key
            secret_access_key = var.aws_secret_key
          }
        }
    
        gcs_data_sink {
          bucket_name = google_storage_bucket.gcp_sync.name
        }
      }
    
      schedule {
        schedule_start_date {
          year  = 2025
          month = 1
          day   = 1
        }
    
        start_time_of_day {
          hours   = 0
          minutes = 0
          seconds = 0
          nanos   = 0
        }
        repeat_interval = "86400s" # Daily
      }
    }
    HCL

    Hybrid Cloud-On-premises Solutions:

    # AWS Direct Connect
    resource "aws_dx_connection" "datacenter" {
      name      = "datacenter-connection"
      bandwidth = "1Gbps"
      location  = "EqSe2"
    }
    
    resource "aws_dx_private_virtual_interface" "datacenter" {
      connection_id    = aws_dx_connection.datacenter.id
      name             = "datacenter-vif"
      vlan             = 100
      address_family   = "ipv4"
      bgp_asn          = 65000
      amazon_address   = "169.254.0.1/30"
      customer_address = "169.254.0.2/30"
    
      vpn_gateway_id = aws_vpn_gateway.main.id
    }
    
    # Azure ExpressRoute
    resource "azurerm_express_route_circuit" "datacenter" {
      name                  = "datacenter-expressroute"
      resource_group_name   = azurerm_resource_group.network.name
      location              = azurerm_resource_group.network.location
      service_provider_name = "Equinix"
      peering_location      = "Silicon Valley"
      bandwidth_in_mbps     = 1000
    
      sku {
        tier   = "Premium"
        family = "MeteredData"
      }
    }
    
    # Connect ExpressRoute to VNet
    resource "azurerm_virtual_network_gateway_connection" "datacenter" {
      name                = "datacenter-connection"
      location            = azurerm_resource_group.network.location
      resource_group_name = azurerm_resource_group.network.name
    
      type                           = "ExpressRoute"
      virtual_network_gateway_id     = azurerm_virtual_network_gateway.main.id
      express_route_circuit_id       = azurerm_express_route_circuit.datacenter.id
      authorization_key              = var.expressroute_auth_key
    }
    
    # GCP Cloud Interconnect
    resource "google_compute_interconnect_attachment" "datacenter" {
      name         = "datacenter-interconnect"
      type         = "PARTNER"
      router       = google_compute_router.datacenter.id
      region       = var.region
      bandwidth    = "BPS_1G"
      vlan_tag8021q = 100
    }
    
    resource "google_compute_router" "datacenter" {
      name    = "datacenter-router"
      network = google_compute_network.vpc_network.name
      region  = var.region
    
      bgp {
        asn = 65001
      }
    }
    HCL

    Part III: Production Techniques

    Chapter 8: State Management

    Remote State Configuration:

    # S3 backend configuration
    terraform {
      backend "s3" {
        bucket         = "terraform-states"
        key            = "production/network/terraform.tfstate"
        region         = "us-east-1"
        encrypt        = true
        dynamodb_table = "terraform-lock"
      }
    }
    
    # Azure backend configuration
    terraform {
      backend "azurerm" {
        resource_group_name  = "terraform-states"
        storage_account_name = "terraformstate"
        container_name       = "tfstate"
        key                  = "production.terraform.tfstate"
      }
    }
    
    # GCP backend configuration
    terraform {
      backend "gcs" {
        bucket = "terraform-states"
        prefix = "production"
      }
    }
    
    # Terraform Cloud backend
    terraform {
      backend "remote" {
        organization = "my-company"
    
        workspaces {
          name = "production"
        }
      }
    }
    HCL

    State Locking Mechanisms:

    AWS DynamoDB lock table:

    resource "aws_dynamodb_table" "terraform_locks" {
      name         = "terraform-locks"
      billing_mode = "PAY_PER_REQUEST"
      hash_key     = "LockID"
    
      attribute {
        name = "LockID"
        type = "S"
      }
    
      tags = {
        Name = "TerraformStateLock"
      }
    }
    HCL

    State File Security:

    # S3 bucket for state with encryption and versioning
    resource "aws_s3_bucket" "terraform_state" {
      bucket = "terraform-states"
    
      tags = {
        Name = "TerraformState"
      }
    }
    
    resource "aws_s3_bucket_versioning" "terraform_state" {
      bucket = aws_s3_bucket.terraform_state.id
    
      versioning_configuration {
        status = "Enabled"
      }
    }
    
    resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" {
      bucket = aws_s3_bucket.terraform_state.id
    
      rule {
        apply_server_side_encryption_by_default {
          sse_algorithm = "AES256"
        }
      }
    }
    
    # Restrict access to state bucket
    resource "aws_s3_bucket_public_access_block" "terraform_state" {
      bucket = aws_s3_bucket.terraform_state.id
    
      block_public_acls       = true
      block_public_policy     = true
      ignore_public_acls      = true
      restrict_public_buckets = true
    }
    
    # IAM policy for state access
    resource "aws_iam_policy" "terraform_state_access" {
      name        = "TerraformStateAccess"
      description = "Policy for accessing Terraform state"
    
      policy = jsonencode({
        Version = "2012-10-17"
        Statement = [
          {
            Effect = "Allow"
            Action = [
              "s3:ListBucket",
              "s3:GetObject",
              "s3:PutObject"
            ]
            Resource = [
              aws_s3_bucket.terraform_state.arn,
              "${aws_s3_bucket.terraform_state.arn}/*"
            ]
          },
          {
            Effect = "Allow"
            Action = [
              "dynamodb:DescribeTable",
              "dynamodb:GetItem",
              "dynamodb:PutItem",
              "dynamodb:DeleteItem"
            ]
            Resource = aws_dynamodb_table.terraform_locks.arn
          }
        ]
      })
    }
    HCL

    Import and Migration Strategies:

    Import existing infrastructure:

    terraform import aws_instance.web i-1234567890abcdef0
    Bash

    Migration between backends:

    # Export current state
    terraform state pull > terraform.tfstate
    
    # After reconfiguring backend
    terraform init -migrate-state
    Bash

    State File Troubleshooting:

    Common state issues and resolutions:

    • State locking failures: Check permissions and lock table configuration
    • State file corruption: Restore from versioned backups
    • Resource drift: Use terraform refresh and terraform plan to identify
    • Orphaned resources: Remove with terraform state rm
    • State conflicts: Resolve by merging state files

    State file operations:

    # List resources in state
    terraform state list
    
    # Show resource details
    terraform state show aws_instance.web
    
    # Move resources
    terraform state mv aws_instance.web aws_instance.web_server
    
    # Remove resources from state
    terraform state rm aws_instance.old
    Bash

    Chapter 9: Security Best Practices

    Secrets Management:

    # Integrate with Vault for secrets
    provider "vault" {
      address = "https://vault.example.com:8200"
    }
    
    data "vault_generic_secret" "db_credentials" {
      path = "secret/database"
    }
    
    resource "aws_db_instance" "postgres" {
      allocated_storage    = 20
      engine               = "postgres"
      engine_version       = "14"
      instance_class       = "db.t3.micro"
      db_name              = "mydb"
      username             = data.vault_generic_secret.db_credentials.data["username"]
      password             = data.vault_generic_secret.db_credentials.data["password"]
      parameter_group_name = "default.postgres14"
      skip_final_snapshot  = true
    }
    HCL

    IAM Implementation Patterns:

    Least privilege principle:

    # Granular IAM roles with specific permissions
    resource "aws_iam_role" "ec2_s3_read_only" {
      name = "ec2-s3-read-only"
    
      assume_role_policy = jsonencode({
        Version = "2012-10-17"
        Statement = [
          {
            Action = "sts:AssumeRole"
            Effect = "Allow"
            Principal = {
              Service = "ec2.amazonaws.com"
            }
          }
        ]
      })
    }
    
    resource "aws_iam_role_policy" "s3_read_only" {
      name = "s3-read-only"
      role = aws_iam_role.ec2_s3_read_only.id
    
      policy = jsonencode({
        Version = "2012-10-17"
        Statement = [
          {
            Action = [
              "s3:Get*",
              "s3:List*"
            ]
            Effect   = "Allow"
            Resource = [
              "arn:aws:s3:::specific-bucket",
              "arn:aws:s3:::specific-bucket/*"
            ]
          }
        ]
      })
    }
    HCL

    Network Security Configurations:

    # Security group with minimal access
    resource "aws_security_group" "restricted" {
      name        = "restricted-access"
      description = "Allow minimal traffic"
      vpc_id      = aws_vpc.main.id
    
      # Allow inbound traffic only from internal subnet
      ingress {
        from_port   = 443
        to_port     = 443
        protocol    = "tcp"
        cidr_blocks = [aws_subnet.private.cidr_block]
      }
    
      # Allow outbound only to specific services
      egress {
        from_port   = 443
        to_port     = 443
        protocol    = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
      }
    
      egress {
        from_port   = 80
        to_port     = 80
        protocol    = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
      }
    }
    
    # Azure Network Security Group with detailed rules
    resource "azurerm_network_security_group" "restricted" {
      name                = "restricted-nsg"
      location            = azurerm_resource_group.main.location
      resource_group_name = azurerm_resource_group.main.name
    
      security_rule {
        name                       = "AllowHTTPSInbound"
        priority                   = 100
        direction                  = "Inbound"
        access                     = "Allow"
        protocol                   = "Tcp"
        source_port_range          = "*"
        destination_port_range     = "443"
        source_address_prefix      = "VirtualNetwork"
        destination_address_prefix = "*"
      }
    
      security_rule {
        name                       = "DenyAllInbound"
        priority                   = 4096
        direction                  = "Inbound"
        access                     = "Deny"
        protocol                   = "*"
        source_port_range          = "*"
        destination_port_range     = "*"
        source_address_prefix      = "*"
        destination_address_prefix = "*"
      }
    }
    HCL

    Compliance as Code:

    # Using Sentinel Policy as Code (Terraform Cloud/Enterprise)
    # sentinel.hcl
    policy "enforce-mandatory-tags" {
      enforcement_level = "hard-mandatory"
    }
    
    policy "restrict-instance-type" {
      enforcement_level = "soft-mandatory"
    }
    
    # enforce-mandatory-tags.sentinel
    import "tfplan"
    
    required_tags = [
      "environment",
      "owner",
      "application"
    ]
    
    ec2_instances = filter tfplan.resource_changes as _, rc {
      rc.type is "aws_instance" and
      (rc.change.actions contains "create" or rc.change.actions contains "update")
    }
    
    tags_validation = rule {
      all ec2_instances as _, instance {
        all required_tags as rt {
          instance.change.after.tags contains rt
        }
      }
    }
    
    main = rule {
      tags_validation
    }
    HCL

    Security Scanning Integration:

    # GitHub Actions workflow for Terraform security scanning
    name: Terraform Security Scan
    
    on:
      push:
        branches: [ main ]
      pull_request:
        branches: [ main ]
    
    jobs:
      tfsec:
        name: Run tfsec sarif report
        runs-on: ubuntu-latest
        permissions:
          security-events: write
    
        steps:
          - name: Clone repo
            uses: actions/checkout@v3
    
          - name: Run tfsec
            uses: tfsec/tfsec-sarif-action@v0.1.0
            with:
              sarif_file: tfsec.sarif
    
          - name: Upload SARIF file
            uses: github/codeql-action/upload-sarif@v1
            with:
              sarif_file: tfsec.sarif
    YAML

    Chapter 10: Testing Infrastructure Code

    Unit Testing with Terraform:

    # Example module to test
    # modules/networking/main.tf
    variable "vpc_cidr" {
      type = string
    }
    
    variable "subnet_cidrs" {
      type = list(string)
    }
    
    resource "aws_vpc" "main" {
      cidr_block = var.vpc_cidr
    }
    
    resource "aws_subnet" "main" {
      count      = length(var.subnet_cidrs)
      vpc_id     = aws_vpc.main.id
      cidr_block = var.subnet_cidrs[count.index]
    }
    
    output "vpc_id" {
      value = aws_vpc.main.id
    }
    
    output "subnet_ids" {
      value = aws_subnet.main[*].id
    }
    HCL
    // Test file: modules/networking/main_test.go
    package test
    
    import (
        "testing"
        "github.com/gruntwork-io/terratest/modules/terraform"
        "github.com/stretchr/testify/assert"
    )
    
    func TestNetworkingModule(t *testing.T) {
        terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
            TerraformDir: "../examples/networking",
            Vars: map[string]interface{}{
                "vpc_cidr": "10.0.0.0/16",
                "subnet_cidrs": []string{
                    "10.0.1.0/24",
                    "10.0.2.0/24",
                },
            },
        })
    
        defer terraform.Destroy(t, terraformOptions)
    
        terraform.InitAndApply(t, terraformOptions)
    
        vpcID := terraform.Output(t, terraformOptions, "vpc_id")
        subnetIDs := terraform.OutputList(t, terraformOptions, "subnet_ids")
    
        assert.NotEmpty(t, vpcID)
        assert.Equal(t, 2, len(subnetIDs))
    }
    Go

    Integration Testing Strategies:

    package test
    
    import (
        "fmt"
        "testing"
        "time"
    
        "github.com/gruntwork-io/terratest/modules/http-helper"
        "github.com/gruntwork-io/terratest/modules/terraform"
    )
    
    func TestWebServerDeployment(t *testing.T) {
        terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
            TerraformDir: "../examples/web-server",
        })
    
        defer terraform.Destroy(t, terraformOptions)
    
        terraform.InitAndApply(t, terraformOptions)
    
        publicIP := terraform.Output(t, terraformOptions, "public_ip")
        url := fmt.Sprintf("http://%s", publicIP)
    
        // Test that the web server returns a 200 OK
        http_helper.HttpGetWithRetry(
            t,
            url,
            nil,
            200,
            "Hello, World!",
            30,
            5*time.Second,
        )
    }
    Go

    Policy Validation with Sentinel:

    # restrict-instance-type.sentinel
    import "tfplan"
    
    allowed_types = [
      "t3.micro", 
      "t3.small",
      "t3.medium"
    ]
    
    ec2_instances = filter tfplan.resource_changes as _, rc {
      rc.type is "aws_instance" and
      (rc.change.actions contains "create" or rc.change.actions contains "update")
    }
    
    instance_type_allowed = rule {
      all ec2_instances as _, instance {
        instance.change.after.instance_type in allowed_types
      }
    }
    
    main = rule {
      instance_type_allowed
    }
    Power Query

    Automated Validation Workflows:

    # GitLab CI workflow for Terraform validation
    stages:
      - validate
      - test
      - plan
      - apply
    
    variables:
      TF_ROOT: ${CI_PROJECT_DIR}
      TF_STATE_NAME: default
    
    validate:
      stage: validate
      script:
        - cd ${TF_ROOT}
        - terraform init -backend=false
        - terraform validate
        - terraform fmt -check
    
    test:
      stage: test
      script:
        - cd ${TF_ROOT}/test
        - go test -v ./...
    
    plan:
      stage: plan
      script:
        - cd ${TF_ROOT}
        - terraform init
        - terraform plan -out=plan.tfplan
      artifacts:
        paths:
          - plan.tfplan
        expire_in: 1 week
    
    apply:
      stage: apply
      script:
        - cd ${TF_ROOT}
        - terraform init
        - terraform apply plan.tfplan
      dependencies:
        - plan
      when: manual
      only:
        - main
    YAML

    Test-Driven Infrastructure Development:

    # test/fixtures/s3_bucket/main.tf
    provider "aws" {
      region = "us-west-2"
    }
    
    module "s3_bucket" {
      source = "../../../modules/s3_bucket"
    
      bucket_name          = "test-bucket-${random_id.this.hex}"
      versioning_enabled   = true
      encryption_enabled   = true
      block_public_access  = true
    }
    
    resource "random_id" "this" {
      byte_length = 8
    }
    
    output "bucket_id" {
      value = module.s3_bucket.bucket_id
    }
    
    output "bucket_arn" {
      value = module.s3_bucket.bucket_arn
    }
    HCL
    # test/integration/s3_bucket/controls/s3_bucket_test.rb
    control 's3-bucket' do
      impact 1.0
      title 'Test S3 Bucket Configuration'
    
      bucket_id = input('bucket_id')
    
      describe aws_s3_bucket(bucket_id) do
        it { should exist }
        it { should have_versioning_enabled }
        it { should have_default_encryption_enabled }
        its('bucket_acl.grants.count') { should eq 1 } # Only the owner has access
      end
    
      describe aws_s3_bucket_policy(bucket_id) do
        it { should_not be_public }
      end
    end
    Ruby

    Part IV: DevOps Integration

    Chapter 11: CI/CD Pipeline Integration

    Jenkins Pipeline Integration:

    pipeline {
        agent any
    
        environment {
            TF_IN_AUTOMATION = 'true'
        }
    
        stages {
            stage('Checkout') {
                steps {
                    checkout scm
                }
            }
    
            stage('Terraform Init') {
                steps {
                    sh 'terraform init'
                }
            }
    
            stage('Terraform Validate') {
                steps {
                    sh 'terraform validate'
                    sh 'terraform fmt -check'
                }
            }
    
            stage('Terraform Plan') {
                steps {
                    sh 'terraform plan -out=tfplan'
                    sh 'terraform show -json tfplan > tfplan.json'
                }
            }
    
            stage('Security Scan') {
                steps {
                    sh 'tfsec .'
                    sh 'checkov -f tfplan.json'
                }
            }
    
            stage('Approval') {
                when {
                    branch 'main'
                }
                steps {
                    input message: 'Deploy the infrastructure?'
                }
            }
    
            stage('Terraform Apply') {
                when {
                    branch 'main'
                }
                steps {
                    sh 'terraform apply -auto-approve tfplan'
                }
            }
        }
    
        post {
            always {
                archiveArtifacts artifacts: 'tfplan.json', fingerprint: true
            }
        }
    }
    Groovy

    GitHub Actions Example:

    name: 'Terraform CI/CD'
    
    on:
      push:
        branches: [ main ]
      pull_request:
        branches: [ main ]
    
    jobs:
      terraform:
        name: 'Terraform'
        runs-on: ubuntu-latest
    
        steps:
        - name: Checkout
          uses: actions/checkout@v3
    
        - name: Setup Terraform
          uses: hashicorp/setup-terraform@v2
    
        - name: Terraform Format
          id: fmt
          run: terraform fmt -check
    
        - name: Terraform Init
          id: init
          run: terraform init
    
        - name: Terraform Validate
          id: validate
          run: terraform validate -no-color
    
        - name: Terraform Plan
          id: plan
          if: github.event_name == 'pull_request'
          run: terraform plan -no-color
          continue-on-error: true
    
        - name: Update Pull Request
          uses: actions/github-script@v6
          if: github.event_name == 'pull_request'
          env:
            PLAN: "terraform\n${{ steps.plan.outputs.stdout }}"
          with:
            github-token: ${{ secrets.GITHUB_TOKEN }}
            script: |
              const output = `#### Terraform Format and Style 🖌\`${{ steps.fmt.outcome }}\`
              #### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\`
              #### Terraform Validation 🤖\`${{ steps.validate.outcome }}\`
              #### Terraform Plan 📖\`${{ steps.plan.outcome }}\`
    
              <details><summary>Show Plan</summary>
    
              \`\`\`\n
              ${process.env.PLAN}
              \`\`\`
    
              </details>
    
              *Pushed by: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`;
    
              github.rest.issues.createComment({
                issue_number: context.issue.number,
                owner: context.repo.owner,
                repo: context.repo.repo,
                body: output
              })
    
        - name: Terraform Apply
          if: github.ref == 'refs/heads/main' && github.event_name == 'push'
          run: terraform apply -auto-approve
    YAML

    GitLab CI Example:

    image:
      name: hashicorp/terraform:latest
      entrypoint:
        - '/usr/bin/env'
        - 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
    
    variables:
      TF_ROOT: ${CI_PROJECT_DIR}
      TF_STATE_NAME: default
    
    cache:
      paths:
        - .terraform
    
    before_script:
      - cd ${TF_ROOT}
      - terraform --version
    
    stages:
      - validate
      - test
      - build
      - deploy
      - cleanup
    
    validate:
      stage: validate
      script:
        - terraform init -backend=false
        - terraform fmt -check
        - terraform validate
    
    test:
      stage: test
      image: golang:latest
      script:
        - cd test
        - go test -v ./...
    
    plan:
      stage: build
      script:
        - terraform init
        - terraform plan -out=plan.tfplan
      artifacts:
        paths:
          - plan.tfplan
        reports:
          terraform: plan.json
    
    apply:
      stage: deploy
      script:
        - terraform init
        - terraform apply -auto-approve plan.tfplan
      dependencies:image:
      name: hashicorp/terraform:latest
      entrypoint:
        - '/usr/bin/env'
        - 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
    
    variables:
      TF_ROOT: ${CI_PROJECT_DIR}
      TF_STATE_NAME: default
    
    cache:
      paths:
        - .terraform
    
    before_script:
      - cd ${TF_ROOT}
      - terraform --version
    
    stages:
      - validate
      - test
      - build
      - deploy
      - cleanup
    
    validate:
      stage: validate
      script:
        - terraform init -backend=false
        - terraform fmt -check
        - terraform validate
    
    test:
      stage: test
      image: golang:latest
      script:
        - cd test
        - go test -v ./...
    
    plan:
      stage: build
      script:
        - terraform init
        - terraform plan -out=plan.tfplan
      artifacts:
        paths:
          - plan.tfplan
        reports:
          terraform: plan.json
    
    apply:
      stage: deploy
      script:
        - terraform init
        - terraform apply -auto-approve plan.tfplan
      dependencies:
    
    Similar code found with 6 license types
    
    ---
    
    # HashiCorp Terraform: Production-Grade Infrastructure Management Across Cloud Providers
    
    ## Part IV: DevOps Integration (continued)
    
    ### Chapter 11: CI/CD Pipeline Integration (continued)
    
    **GitLab CI Example (continued):**
    
    ```yaml
    # Complete GitLab CI pipeline
    apply:
      stage: deploy
      script:
        - terraform init
        - terraform apply -auto-approve plan.tfplan
      dependencies:
        - plan
      when: manual
      only:
        - main
    
    destroy:
      stage: cleanup
      script:
        - terraform init
        - terraform destroy -auto-approve
      when: manual
      environment:
        name: production
        action: stop
    YAML

    Automated Plan and Apply Workflows:

    flowchart TD
        A[Code Changes] --> B[CI Trigger]
        B --> C[Terraform Init]
        C --> D[Terraform Validate]
        D --> E[Terraform Plan]
        E --> F{Review Changes}
        F -->|Approved| G[Terraform Apply]
        F -->|Rejected| H[Reject Changes]
        G --> I[Update Documentation]
        G --> J[Notify Team]

    Change Management Integration:

    # Python script to integrate Terraform with ServiceNow
    import requests
    import json
    import os
    import subprocess
    
    # Create change request in ServiceNow
    def create_change_request(plan_summary):
        snow_url = os.environ['SNOW_URL']
        snow_user = os.environ['SNOW_USER']
        snow_pass = os.environ['SNOW_PASS']
    
        headers = {"Content-Type": "application/json"}
        payload = {
            "short_description": "Terraform infrastructure changes",
            "description": plan_summary,
            "type": "normal",
            "risk": "moderate",
            "impact": "3",
            "category": "Infrastructure"
        }
    
        response = requests.post(
            f"{snow_url}/api/now/table/change_request",
            auth=(snow_user, snow_pass),
            headers=headers,
            data=json.dumps(payload)
        )
    
        if response.status_code == 201:
            return response.json()['result']['sys_id']
        else:
            raise Exception(f"Failed to create change request: {response.text}")
    
    # Run Terraform plan and extract summary
    tf_output = subprocess.check_output(["terraform", "plan", "-no-color"]).decode("utf-8")
    plan_summary = "\n".join(line for line in tf_output.split("\n") if "Plan:" in line)
    
    # Create change request
    change_id = create_change_request(plan_summary)
    print(f"Created change request: {change_id}")
    
    # Wait for approval before applying
    # ...
    Python

    Approval Processes:

    # Using Terraform Cloud for approvals
    terraform {
      cloud {
        organization = "my-company"
    
        workspaces {
          name = "production"
        }
      }
    }
    HCL
    // Terraform Cloud workspace configuration (API)
    {
      "data": {
        "type": "workspaces",
        "attributes": {
          "name": "production",
          "auto-apply": false,
          "terraform-version": "1.5.0",
          "execution-mode": "remote",
          "speculative-enabled": true,
          "global-remote-state": false
        }
      }
    }
    JSON

    Release Automation:

    #!/bin/bash
    # Terraform deployment script with versioning and notifications
    
    # Set environment
    ENV=$1
    VERSION=$2
    
    if [ -z "$ENV" ] || [ -z "$VERSION" ]; then
      echo "Usage: $0 <environment> <version>"
      exit 1
    fi
    
    # Checkout specific version
    git checkout tags/v${VERSION}
    
    # Select workspace
    terraform workspace select ${ENV} || terraform workspace new ${ENV}
    
    # Initialize and apply
    terraform init
    terraform apply -auto-approve
    
    # Tag the deployment in git
    git tag -a "deployed-${ENV}-v${VERSION}" -m "Deployed version ${VERSION} to ${ENV}"
    git push origin --tags
    
    # Send notification
    curl -X POST \
      -H "Content-Type: application/json" \
      -d "{\"text\":\"Terraform v${VERSION} successfully deployed to ${ENV}\"}" \
      ${SLACK_WEBHOOK_URL}
    Bash

    Chapter 12: Infrastructure as Code Ecosystem

    Integrating with Packer for Image Management:

    # First define AMI using Packer
    # packer.pkr.hcl
    source "amazon-ebs" "ubuntu" {
      ami_name      = "web-server-${local.timestamp}"
      instance_type = "t2.micro"
      region        = "us-west-2"
      source_ami_filter {
        filters = {
          name                = "ubuntu/images/*ubuntu-focal-20.04-amd64-server-*"
          root-device-type    = "ebs"
          virtualization-type = "hvm"
        }
        most_recent = true
        owners      = ["099720109477"]
      }
      ssh_username = "ubuntu"
    }
    
    build {
      sources = ["source.amazon-ebs.ubuntu"]
    
      provisioner "shell" {
        inline = [
          "sudo apt-get update",
          "sudo apt-get install -y nginx",
          "sudo systemctl enable nginx"
        ]
      }
    
      post-processor "manifest" {
        output     = "manifest.json"
        strip_path = true
      }
    }
    HCL
    # Then reference AMI in Terraform
    data "external" "ami" {
      program = ["jq", "-r", ".builds[-1].artifact_id", "manifest.json"]
    }
    
    locals {
      ami_id = element(split(":", data.external.ami.result.output), 1)
    }
    
    resource "aws_instance" "web" {
      ami           = local.ami_id
      instance_type = "t3.micro"
    
      tags = {
        Name = "WebServer"
      }
    }
    HCL

    Ansible, Chef, and Puppet Integration:

    # Using Ansible with Terraform
    resource "aws_instance" "web" {
      ami           = "ami-0c55b159cbfafe1f0"
      instance_type = "t2.micro"
      key_name      = aws_key_pair.deployer.key_name
    
      provisioner "remote-exec" {
        inline = ["echo 'SSH ready'"]
    
        connection {
          type        = "ssh"
          user        = "ubuntu"
          private_key = file(var.private_key_path)
          host        = self.public_ip
        }
      }
    
      provisioner "local-exec" {
        command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -u ubuntu -i '${self.public_ip},' --private-key ${var.private_key_path} playbook.yml"
      }
    }
    HCL
    # Example Ansible playbook.yml
    ---
    - hosts: all
      become: yes
      tasks:
        - name: Update apt cache
          apt:
            update_cache: yes
    
        - name: Install packages
          apt:
            name: 
              - nginx
              - postgresql-client
              - python3-pip
            state: present
    
        - name: Start nginx
          service:
            name: nginx
            state: started
            enabled: yes
    YAML

    Vault for Secrets Management:

    # Terraform with Vault integration
    provider "vault" {
      address = "https://vault.example.com:8200"
      token   = var.vault_token
    }
    
    data "vault_generic_secret" "database" {
      path = "secret/database/credentials"
    }
    
    resource "aws_db_instance" "database" {
      allocated_storage    = 20
      engine               = "mysql"
      engine_version       = "8.0"
      instance_class       = "db.t3.micro"
      name                 = "mydb"
      username             = data.vault_generic_secret.database.data["username"]
      password             = data.vault_generic_secret.database.data["password"]
      parameter_group_name = "default.mysql8.0"
      skip_final_snapshot  = true
    }
    HCL

    Consul for Service Discovery and Configuration:

    # Using Terraform to set up Consul
    resource "aws_instance" "consul_server" {
      count         = 3
      ami           = "ami-0c55b159cbfafe1f0"
      instance_type = "t3.medium"
    
      user_data = <<-EOF
        #!/bin/bash
        apt-get update
        apt-get install -y unzip
    
        wget https://releases.hashicorp.com/consul/1.13.1/consul_1.13.1_linux_amd64.zip
        unzip consul_1.13.1_linux_amd64.zip
        mv consul /usr/local/bin/
    
        mkdir -p /etc/consul.d
        cat > /etc/consul.d/server.json <<EOL
        {
          "server": true,
          "bootstrap_expect": 3,
          "data_dir": "/var/consul",
          "retry_join": [${join(",", formatlist("\"${aws_instance.consul_server[*].private_ip}\"", range(3)))}],
          "client_addr": "0.0.0.0",
          "ui": true
        }
        EOL
    
        systemctl enable consul
        systemctl start consul
      EOF
    
      tags = {
        Name = "consul-server-${count.index}"
      }
    }
    
    # Consul outputs for service discovery
    output "consul_ui" {
      value = "http://${aws_instance.consul_server[0].public_ip}:8500"
    }
    HCL

    Kubernetes Deployment with Terraform:

    # Setting up EKS with Terraform
    module "eks" {
      source  = "terraform-aws-modules/eks/aws"
      version = "~> 19.0"
    
      cluster_name    = "my-cluster"
      cluster_version = "1.27"
    
      vpc_id     = module.vpc.vpc_id
      subnet_ids = module.vpc.private_subnets
    
      eks_managed_node_group_defaults = {
        ami_type       = "AL2_x86_64"
        instance_types = ["t3.medium"]
      }
    
      eks_managed_node_groups = {
        main = {
          min_size     = 1
          max_size     = 3
          desired_size = 2
    
          instance_types = ["t3.medium"]
          capacity_type  = "ON_DEMAND"
        }
      }
    }
    
    # Using Terraform Kubernetes provider
    provider "kubernetes" {
      host                   = module.eks.cluster_endpoint
      cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
      exec {
        api_version = "client.authentication.k8s.io/v1beta1"
        args        = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
        command     = "aws"
      }
    }
    
    # Deploy an application
    resource "kubernetes_deployment" "example" {
      metadata {
        name = "example-app"
      }
    
      spec {
        replicas = 2
    
        selector {
          match_labels = {
            app = "example"
          }
        }
    
        template {
          metadata {
            labels = {
              app = "example"
            }
          }
    
          spec {
            container {
              image = "nginx:1.21"
              name  = "example"
    
              port {
                container_port = 80
              }
            }
          }
        }
      }
    }
    
    resource "kubernetes_service" "example" {
      metadata {
        name = "example-service"
      }
    
      spec {
        selector = {
          app = "example"
        }
    
        port {
          port        = 80
          target_port = 80
        }
    
        type = "LoadBalancer"
      }
    }
    HCL

    Chapter 13: Monitoring and Observability

    Infrastructure Drift Detection:

    # Output the configuration for drift detection
    resource "local_file" "config_snapshot" {
      content  = jsonencode({
        timestamp   = timestamp()
        vpc_id      = aws_vpc.main.id
        subnet_ids  = aws_subnet.main.*.id
        instances   = [for i in aws_instance.web : {
          id       = i.id
          type     = i.instance_type
          ami      = i.ami
          security_groups = i.security_groups
        }]
      })
      filename = "${path.module}/snapshots/config-${formatdate("YYYY-MM-DD-hh-mm", timestamp())}.json"
    }
    
    # Drift detection script (local-exec)
    resource "null_resource" "drift_detection" {
      triggers = {
        always_run = timestamp()
      }
    
      provisioner "local-exec" {
        command = <<-EOF
          #!/bin/bash
          terraform plan -detailed-exitcode
          if [ $? -eq 2 ]; then
            echo "Drift detected - infrastructure has changed!" | tee drift-alert.txt
            # Send notification
            curl -X POST -H "Content-Type: application/json" -d @drift-alert.txt ${var.notification_url}
          else
            echo "No drift detected"
          fi
        EOF
      }
    
      depends_on = [
        aws_instance.web,
        aws_vpc.main
      ]
    }
    HCL

    Cost Management and Optimization:

    # Tagging resources for cost allocation
    locals {
      common_tags = {
        Project     = var.project_name
        Environment = var.environment
        Owner       = var.owner
        CostCenter  = var.cost_center
      }
    }
    
    resource "aws_instance" "app" {
      ami           = var.ami_id
      instance_type = var.instance_type
    
      tags = merge(
        local.common_tags,
        {
          Name = "AppServer"
        }
      )
    
      # Cost optimization: Use spot instances for non-production
      dynamic "instance_market_options" {
        for_each = var.environment != "production" ? [1] : []
        content {
          market_type = "spot"
          spot_options {
            max_price = var.spot_price
          }
        }
      }
    
      # Cost optimization: Auto-shutdown in dev environments
      user_data = var.environment == "development" ? <<-EOF
        #!/bin/bash
        echo "0 19 * * 1-5 root /usr/sbin/shutdown -h now" > /etc/cron.d/instance-shutdown
      EOF
      : ""
    }
    
    # Cost management using AWS Budget
    resource "aws_budgets_budget" "monthly" {
      name              = "${var.project_name}-monthly-budget"
      budget_type       = "COST"
      limit_amount      = var.monthly_budget_limit
      limit_unit        = "USD"
      time_period_start = "2023-01-01_00:00"
      time_unit         = "MONTHLY"
    
      notification {
        comparison_operator = "GREATER_THAN"
        threshold           = 80
        threshold_type      = "PERCENTAGE"
        notification_type   = "ACTUAL"
    
        subscriber_email_addresses = var.budget_notification_emails
      }
    
      cost_filter {
        name = "TagKeyValue"
        values = [
          "user:Project$${var.project_name}"
        ]
      }
    }
    HCL

    Performance Monitoring:

    # AWS CloudWatch setup
    resource "aws_cloudwatch_dashboard" "main" {
      dashboard_name = "infrastructure-dashboard"
    
      dashboard_body = jsonencode({
        widgets = [
          {
            type   = "metric"
            x      = 0
            y      = 0
            width  = 12
            height = 6
    
            properties = {
              metrics = [
                ["AWS/EC2", "CPUUtilization", "InstanceId", aws_instance.web[0].id],
                ["AWS/EC2", "CPUUtilization", "InstanceId", aws_instance.web[1].id]
              ]
              period = 300
              stat   = "Average"
              region = var.region
              title  = "EC2 CPU Utilization"
            }
          },
          {
            type   = "metric"
            x      = 12
            y      = 0
            width  = 12
            height = 6
    
            properties = {
              metrics = [
                ["AWS/RDS", "CPUUtilization", "DBInstanceIdentifier", aws_db_instance.database.id]
              ]
              period = 300
              stat   = "Average"
              region = var.region
              title  = "RDS CPU Utilization"
            }
          }
        ]
      })
    }
    
    # CloudWatch alarms
    resource "aws_cloudwatch_metric_alarm" "high_cpu" {
      alarm_name          = "ec2-high-cpu"
      comparison_operator = "GreaterThanThreshold"
      evaluation_periods  = 2
      metric_name         = "CPUUtilization"
      namespace           = "AWS/EC2"
      period              = 300
      statistic           = "Average"
      threshold           = 80
      alarm_description   = "This alarm monitors EC2 CPU utilization"
    
      dimensions = {
        InstanceId = aws_instance.web[0].id
      }
    
      alarm_actions = [aws_sns_topic.alerts.arn]
    }
    HCL

    Disaster Recovery Strategies:

    # Cross-region data replication with S3
    resource "aws_s3_bucket" "primary" {
      bucket = "primary-data-bucket"
    }
    
    resource "aws_s3_bucket" "replica" {
      provider = aws.dr_region
      bucket   = "replica-data-bucket"
    }
    
    resource "aws_s3_bucket_versioning" "primary" {
      bucket = aws_s3_bucket.primary.id
    
      versioning_configuration {
        status = "Enabled"
      }
    }
    
    resource "aws_s3_bucket_versioning" "replica" {
      provider = aws.dr_region
      bucket   = aws_s3_bucket.replica.id
    
      versioning_configuration {
        status = "Enabled"
      }
    }
    
    resource "aws_s3_bucket_replication_configuration" "replication" {
      bucket = aws_s3_bucket.primary.id
      role   = aws_iam_role.replication.arn
    
      rule {
        id     = "data-replication"
        status = "Enabled"
    
        destination {
          bucket        = aws_s3_bucket.replica.arn
          storage_class = "STANDARD"
        }
      }
    }
    
    # Database disaster recovery setup
    resource "aws_rds_cluster" "primary" {
      cluster_identifier      = "aurora-primary"
      engine                  = "aurora-mysql"
      database_name           = "mydb"
      master_username         = var.db_username
      master_password         = var.db_password
      backup_retention_period = 7
      preferred_backup_window = "07:00-09:00"
    
      enabled_cloudwatch_logs_exports = ["audit", "error", "general"]
    }
    
    resource "aws_rds_cluster" "replica" {
      provider               = aws.dr_region
      cluster_identifier     = "aurora-replica"
      engine                 = "aurora-mysql"
      replication_source_identifier = aws_rds_cluster.primary.arn
      source_region          = var.primary_region
      backup_retention_period = 7
    
      depends_on = [aws_rds_cluster.primary]
    }
    HCL

    Comprehensive Logging:

    # Centralized logging with CloudWatch Logs
    resource "aws_cloudwatch_log_group" "app_logs" {
      name              = "/app/production"
      retention_in_days = 30
    
      tags = {
        Environment = "production"
        Application = "web-app"
      }
    }
    
    # Log subscription filter to Lambda for processing
    resource "aws_cloudwatch_log_subscription_filter" "log_processor" {
      name            = "log-processor-filter"
      log_group_name  = aws_cloudwatch_log_group.app_logs.name
      filter_pattern  = "ERROR"
      destination_arn = aws_lambda_function.log_processor.arn
    
      depends_on = [
        aws_lambda_permission.cloudwatch_logs
      ]
    }
    
    resource "aws_lambda_function" "log_processor" {
      function_name = "log-processor"
      runtime       = "python3.9"
      handler       = "index.handler"
      filename      = "lambda_function.zip"
      role          = aws_iam_role.lambda_role.arn
    
      environment {
        variables = {
          NOTIFICATION_TOPIC = aws_sns_topic.alerts.arn
        }
      }
    }
    
    resource "aws_lambda_permission" "cloudwatch_logs" {
      statement_id  = "AllowExecutionFromCloudWatchLogs"
      action        = "lambda:InvokeFunction"
      function_name = aws_lambda_function.log_processor.function_name
      principal     = "logs.amazonaws.com"
      source_arn    = "${aws_cloudwatch_log_group.app_logs.arn}:*"
    }
    HCL

    Part V: Advanced Topics

    Chapter 14: Custom Providers and Extensions

    Building Custom Providers:

    // Example structure for a custom provider in Go
    package main
    
    import (
        "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
        "github.com/hashicorp/terraform-plugin-sdk/v2/plugin"
    )
    
    func main() {
        plugin.Serve(&plugin.ServeOpts{
            ProviderFunc: Provider,
        })
    }
    
    // Provider returns a terraform.ResourceProvider
    func Provider() *schema.Provider {
        return &schema.Provider{
            Schema: map[string]*schema.Schema{
                "api_key": {
                    Type:        schema.TypeString,
                    Required:    true,
                    Sensitive:   true,
                    DefaultFunc: schema.EnvDefaultFunc("CUSTOM_API_KEY", nil),
                },
                "api_url": {
                    Type:        schema.TypeString,
                    Required:    true,
                    DefaultFunc: schema.EnvDefaultFunc("CUSTOM_API_URL", nil),
                },
            },
            ResourcesMap: map[string]*schema.Resource{
                "custom_resource": resourceCustomResource(),
            },
            DataSourcesMap: map[string]*schema.Resource{
                "custom_data": dataSourceCustomData(),
            },
            ConfigureFunc: providerConfigure,
        }
    }
    
    func resourceCustomResource() *schema.Resource {
        return &schema.Resource{
            Create: resourceCustomResourceCreate,
            Read:   resourceCustomResourceRead,
            Update: resourceCustomResourceUpdate,
            Delete: resourceCustomResourceDelete,
    
            Schema: map[string]*schema.Schema{
                "name": {
                    Type:     schema.TypeString,
                    Required: true,
                },
                "property": {
                    Type:     schema.TypeString,
                    Optional: true,
                },
            },
        }
    }
    
    // Implementation of CRUD functions
    func resourceCustomResourceCreate(d *schema.ResourceData, meta interface{}) error {
        // Create resource implementation
        return nil
    }
    
    func resourceCustomResourceRead(d *schema.ResourceData, meta interface{}) error {
        // Read resource implementation
        return nil
    }
    
    func resourceCustomResourceUpdate(d *schema.ResourceData, meta interface{}) error {
        // Update resource implementation
        return nil
    }
    
    func resourceCustomResourceDelete(d *schema.ResourceData, meta interface{}) error {
        // Delete resource implementation
        return nil
    }
    
    func providerConfigure(d *schema.ResourceData) (interface{}, error) {
        // Configure API client
        apiKey := d.Get("api_key").(string)
        apiURL := d.Get("api_url").(string)
    
        // Initialize and return client
        return NewClient(apiKey, apiURL), nil
    }
    Go

    Using and Creating Provider Plugins:

    # Using a custom provider
    terraform {
      required_providers {
        custom = {
          source  = "example.com/myorg/custom"
          version = "1.0.0"
        }
      }
    }
    
    provider "custom" {
      api_key = var.api_key
      api_url = var.api_url
    }
    
    resource "custom_resource" "example" {
      name     = "example-resource"
      property = "value"
    }
    HCL
    #!/bin/bash
    # Build and install custom provider
    
    # Build the provider
    cd terraform-provider-custom
    go build -o terraform-provider-custom
    
    # Install the provider in a local dev environment
    mkdir -p ~/.terraform.d/plugins/example.com/myorg/custom/1.0.0/linux_amd64/
    cp terraform-provider-custom ~/.terraform.d/plugins/example.com/myorg/custom/1.0.0/linux_amd64/
    Bash

    Extending Terraform’s Functionality:

    # External data source for custom API integration
    data "external" "api_data" {
      program = ["python", "${path.module}/scripts/fetch_api_data.py"]
    
      query = {
        endpoint = "users"
        filter   = "active=true"
      }
    }
    
    # Use the data
    resource "aws_instance" "user_instances" {
      count         = length(jsondecode(data.external.api_data.result.users))
      ami           = var.ami_id
      instance_type = "t3.micro"
    
      tags = {
        Name = "instance-for-${jsondecode(data.external.api_data.result.users)[count.index].name}"
        Email = jsondecode(data.external.api_data.result.users)[count.index].email
      }
    }
    HCL
    #!/usr/bin/env python3
    # fetch_api_data.py
    import json
    import sys
    import requests
    
    def main():
        # Parse input from Terraform
        stdin = sys.stdin.read()
        query = json.loads(stdin)
    
        # Make API request
        response = requests.get(
            f"https://api.example.com/{query['endpoint']}?{query['filter']}",
            headers={
                "Authorization": f"Bearer {os.environ['API_TOKEN']}"
            }
        )
    
        if response.status_code == 200:
            # Return JSON result to Terraform
            print(json.dumps({"users": response.json()}))
        else:
            sys.exit(1)
    
    if __name__ == "__main__":
        main()
    Python

    Contributing to the Terraform Ecosystem:

    # Use Terraform modules to create reusable infrastructure components
    module "vpc" {
      source  = "terraform-aws-modules/vpc/aws"
      version = "3.14.0"
    
      name = "my-vpc"
      cidr = "10.0.0.0/16"
    
      azs             = ["us-east-1a", "us-east-1b", "us-east-1c"]
      private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
      public_subnets  = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
    
      enable_nat_gateway = true
      single_nat_gateway = true
    
      tags = {
        Terraform   = "true"
        Environment = "production"
      }
    }
    HCL

    Chapter 15: Enterprise Patterns and Case Studies

    Financial Services Implementation:

    flowchart TD
        A[Core Banking Network] --> B[Secure Transit Gateway]
        B --> C[Product VPC]
        B --> D[Data Platform VPC]
        B --> E[Security VPC]
        C --> F[Application Layer]
        F --> G[Database Layer]
        D --> H[Data Lake]
        D --> I[Analytics Cluster]
        E --> J[Security Monitoring]
        E --> K[Compliance Reporting]
    # Example of a financial services infrastructure with security controls
    module "vpc" {
      source  = "terraform-aws-modules/vpc/aws"
      version = "3.14.0"
    
      name = "financial-services-vpc"
      cidr = "10.0.0.0/16"
    
      azs             = ["us-east-1a", "us-east-1b", "us-east-1c"]
      private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
      public_subnets  = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
    
      enable_nat_gateway = true
      enable_vpn_gateway = true
    
      # Enhanced security features
      enable_flow_log                      = true
      flow_log_destination_type            = "s3"
      flow_log_destination_arn             = aws_s3_bucket.flow_logs.arn
      flow_log_traffic_type                = "ALL"
      flow_log_max_aggregation_interval    = 60
    
      # Additional security groups
      manage_default_security_group = true
      default_security_group_ingress = []
      default_security_group_egress  = []
    
      tags = {
        Environment = "Production"
        Compliance  = "PCI-DSS,SOC2"
      }
    }
    
    # Security monitoring
    resource "aws_securityhub_account" "main" {}
    
    resource "aws_securityhub_standards_subscription" "pci_dss" {
      standards_arn = "arn:aws:securityhub:us-east-1::standards/pci-dss/v/3.2.1"
      depends_on    = [aws_securityhub_account.main]
    }
    
    resource "aws_securityhub_standards_subscription" "cis" {
      standards_arn = "arn:aws:securityhub:us-east-1::standards/cis-aws-foundations-benchmark/v/1.2.0"
      depends_on    = [aws_securityhub_account.main]
    }
    HCL

    Healthcare Compliance Scenarios:

    # Healthcare infrastructure with HIPAA compliance
    # Network isolation for PHI data
    resource "aws_vpc" "hipaa_compliant" {
      cidr_block           = "10.0.0.0/16"
      enable_dns_support   = true
      enable_dns_hostnames = true
    
      tags = {
        Name        = "hipaa-vpc"
        Environment = "Production"
        Compliance  = "HIPAA"
      }
    }
    
    # Subnet tiers with specific access controls
    resource "aws_subnet" "phi_data" {
      count             = 3
      vpc_id            = aws_vpc.hipaa_compliant.id
      cidr_block        = "10.0.${count.index + 1}.0/24"
      availability_zone = element(["us-east-1a", "us-east-1b", "us-east-1c"], count.index)
    
      tags = {
        Name        = "phi-data-${count.index + 1}"
        DataType    = "PHI"
        Environment = "Production"
      }
    }
    
    # Encryption for data at rest
    resource "aws_kms_key" "phi_encryption" {
      description             = "Key for PHI data encryption"
      deletion_window_in_days = 30
      enable_key_rotation     = true
    
      tags = {
        Name        = "phi-encryption-key"
        Environment = "Production"
        Compliance  = "HIPAA"
      }
    }
    
    # RDS database with encryption and audit logging
    resource "aws_db_instance" "hipaa_database" {
      allocated_storage       = 100
      engine                  = "postgres"
      engine_version          = "13.4"
      instance_class          = "db.m5.large"
      name                    = "hipaadb"
      username                = var.db_username
      password                = var.db_password
      storage_encrypted       = true
      kms_key_id              = aws_kms_key.phi_encryption.arn
      multi_az                = true
      backup_retention_period = 30
      backup_window           = "03:00-05:00"
      maintenance_window      = "Sun:00:00-Sun:03:00"
    
      enabled_cloudwatch_logs_exports = [
        "postgresql", 
        "upgrade"
      ]
    
      subnet_group_name   = aws_db_subnet_group.hipaa.name
      parameter_group_name = aws_db_parameter_group.hipaa.name
    
      tags = {
        Name        = "hipaa-database"
        Environment = "Production"
        Compliance  = "HIPAA"
      }
    }
    
    # Audit logging for compliance
    resource "aws_cloudtrail" "hipaa_audit" {
      name                          = "hipaa-audit-trail"
      s3_bucket_name                = aws_s3_bucket.audit_logs.id
      s3_key_prefix                 = "trail"
      include_global_service_events = true
      is_multi_region_trail         = true
      enable_log_file_validation    = true
      kms_key_id                    = aws_kms_key.audit_logs.arn
    
      tags = {
        Name        = "hipaa-audit-trail"
        Environment = "Production"
        Compliance  = "HIPAA"
      }
    }
    HCL

    Scaling for Large Enterprises:

    # Example of a multi-account AWS setup using Organizations
    provider "aws" {
      region = "us-east-1"
      alias  = "org_master"
    }
    
    resource "aws_organizations_organization" "org" {
      provider = aws.org_master
    
      feature_set = "ALL"
    
      aws_service_access_principals = [
        "cloudtrail.amazonaws.com",
        "config.amazonaws.com",
        "sso.amazonaws.com"
      ]
    
      enabled_policy_types = [
        "SERVICE_CONTROL_POLICY",
        "TAG_POLICY"
      ]
    }
    
    # Organizational Units structure
    resource "aws_organizations_organizational_unit" "security" {
      provider = aws.org_master
      name     = "Security"
      parent_id = aws_organizations_organization.org.roots[0].id
    }
    
    resource "aws_organizations_organizational_unit" "infrastructure" {
      provider = aws.org_master
      name     = "Infrastructure"
      parent_id = aws_organizations_organization.org.roots[0].id
    }
    
    resource "aws_organizations_organizational_unit" "workloads" {
      provider = aws.org_master
      name     = "Workloads"
      parent_id = aws_organizations_organization.org.roots[0].id
    }
    
    # Service Control Policies
    resource "aws_organizations_policy" "deny_root_user" {
      provider = aws.org_master
      name     = "DenyRootUser"
      content  = <<EOF
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "DenyRootUserAccessExceptCloudtrail",
          "Effect": "Deny",
          "NotAction": [
            "cloudtrail:*"
          ],
          "Resource": "*",
          "Condition": {
            "StringLike": {
              "aws:PrincipalArn": "arn:aws:iam::*:root"
            }
          }
        }
      ]
    }
    EOF
    }
    
    # Attach policy to OUs
    resource "aws_organizations_policy_attachment" "deny_root_to_workloads" {
      provider  = aws.org_master
      policy_id = aws_organizations_policy.deny_root_user.id
      target_id = aws_organizations_organizational_unit.workloads.id
    }
    HCL

    Multi-Region, Multi-Account Strategies:

    flowchart TD
        A[Organization] --> B[Security Account]
        A --> C[Networking Account]
        A --> D[Development OU]
        A --> E[Production OU]
        D --> F[Dev Account US]
        D --> G[Dev Account EU]
        E --> H[Prod Account US]
        E --> I[Prod Account EU]
        C --> J[Transit Gateway]
        J --> F
        J --> G
        J --> H
        J --> I
    # Cross-region, cross-account resource sharing
    # In networking account
    resource "aws_ec2_transit_gateway" "tgw" {
      description                     = "Enterprise Transit Gateway"
      auto_accept_shared_attachments  = "enable"
      default_route_table_association = "enable"
      default_route_table_propagation = "enable"
    
      tags = {
        Name = "enterprise-tgw"
      }
    }
    
    resource "aws_ram_resource_share" "tgw_share" {
      name                      = "enterprise-tgw-share"
      allow_external_principals = false
    
      tags = {
        Name = "tgw-resource-share"
      }
    }
    
    resource "aws_ram_resource_association" "tgw_share_association" {
      resource_share_arn = aws_ram_resource_share.tgw_share.arn
      resource_arn       = aws_ec2_transit_gateway.tgw.arn
    }
    
    # In workload account with different provider configuration
    provider "aws" {
      alias  = "workload"
      region = "us-east-1"
    
      assume_role {
        role_arn     = "arn:aws:iam::${var.workload_account_id}:role/OrganizationAccountAccessRole"
        session_name = "terraform-cross-account"
      }
    }
    
    resource "aws_ec2_transit_gateway_vpc_attachment" "workload_attachment" {
      provider           = aws.workload
      subnet_ids         = var.workload_subnet_ids
      transit_gateway_id = aws_ec2_transit_gateway.tgw.id
      vpc_id             = var.workload_vpc_id
    
      tags = {
        Name = "workload-tgw-attachment"
      }
    }
    HCL

    Terraform Cloud and Terraform Enterprise:

    # Using Terraform Cloud remote operations
    terraform {
      cloud {
        organization = "acme-corp"
    
        workspaces {
          name = "production-infrastructure"
        }
      }
    }
    
    # Environment-specific variables managed in Terraform Cloud
    variable "environment" {
      description = "Environment name"
      type        = string
    }
    
    # Remote state data sources for cross-workspace references
    data "terraform_remote_state" "network" {
      backend = "remote"
    
      config = {
        organization = "acme-corp"
        workspaces = {
          name = "network-infrastructure"
        }
      }
    }
    
    # Use outputs from network workspace
    resource "aws_security_group" "app" {
      vpc_id = data.terraform_remote_state.network.outputs.vpc_id
    
      # Security group rules
    }
    HCL

    Policy as Code Evolution:

    # OPA (Open Policy Agent) policies as Terraform artifacts
    resource "aws_s3_bucket_object" "policy" {
      bucket  = aws_s3_bucket.policies.id
      key     = "terraform/aws_instance_policy.rego"
      content = <<EOF
    package terraform.aws_instance
    
    import input.tfplan as tfplan
    
    allowed_instance_types = ["t3.micro", "t3.small", "t3.medium"]
    
    deny[msg] {
      r := tfplan.resource_changes[_]
      r.type == "aws_instance"
      not contains(allowed_instance_types, r.change.after.instance_type)
    
      msg := sprintf("Instance type '%s' is not allowed", [r.change.after.instance_type])
    }
    EOF
    }
    
    # CI/CD integration for policy enforcement
    resource "null_resource" "policy_check" {
      triggers = {
        policy_hash = filemd5("${path.module}/policies/aws_instance_policy.rego")
      }
    
      provisioner "local-exec" {
        command = <<EOF
          conftest test terraform.plan.json \
            --policy ./policies/ \
            --namespace terraform \
            --no-color
        EOF
      }
    }
    HCL

    GitOps Workflows:

    # GitHub workflow for GitOps with Terraform
    name: 'Terraform GitOps'
    
    on:
      push:
        branches:
          - main
        paths:
          - 'environments/**'
    
      pull_request:
        branches:
          - main
        paths:
          - 'environments/**'
    
    jobs:
      detect-environments:
        runs-on: ubuntu-latest
        outputs:
          matrix: ${{ steps.set-matrix.outputs.matrix }}
        steps:
          - uses: actions/checkout@v3
    
          - name: Find changed environments
            id: set-matrix
            run: |
              CHANGED_DIRS=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }} | grep "^environments/" | cut -d/ -f2 | sort -u | jq -R -s -c 'split("\n") | map(select(length > 0))')
              echo "matrix=${CHANGED_DIRS}" >> $GITHUB_OUTPUT
    
      terraform:
        needs: detect-environments
        runs-on: ubuntu-latest
        strategy:
          matrix:
            environment: ${{ fromJson(needs.detect-environments.outputs.matrix) }}
    
        steps:
          - uses: actions/checkout@v3
    
          - name: Setup Terraform
            uses: hashicorp/setup-terraform@v2
    
          - name: Terraform Init
            run: |
              cd environments/${{ matrix.environment }}
              terraform init
    
          - name: Terraform Plan
            id: plan
            run: |
              cd environments/${{ matrix.environment }}
              terraform plan -no-color
            continue-on-error: true
    
          - name: Terraform Apply
            if: github.ref == 'refs/heads/main' && github.event_name == 'push'
            run: |
              cd environments/${{ matrix.environment }}
              terraform apply -auto-approve
    YAML

    AI and ML in Infrastructure Optimization:

    # Using AI/ML-optimized instance types
    resource "aws_instance" "ml_workload" {
      ami           = data.aws_ami.ubuntu.id
      instance_type = "g4dn.xlarge" # GPU-optimized
    
      root_block_device {
        volume_size = 100
        volume_type = "gp3"
        iops        = 3000
      }
    
      tags = {
        Name = "ml-training-instance"
      }
    }
    
    # Integrating with AI services
    resource "aws_sagemaker_notebook_instance" "ml_notebook" {
      name          = "ml-notebook"
      role_arn      = aws_iam_role.sagemaker.arn
      instance_type = "ml.t3.medium"
    }
    
    resource "aws_sagemaker_endpoint_configuration" "model_endpoint" {
      name = "model-endpoint-config"
    
      production_variants {
        variant_name           = "variant-1"
        model_name             = aws_sagemaker_model.model.name
        initial_instance_count = 1
        instance_type          = "ml.m5.large"
      }
    }
    
    resource "aws_sagemaker_endpoint" "model_endpoint" {
      name                 = "model-endpoint"
      endpoint_config_name = aws_sagemaker_endpoint_configuration.model_endpoint.name
    }
    
    # Automated scaling based on ML predictions
    resource "aws_appautoscaling_target" "ecs_target" {
      max_capacity       = 10
      min_capacity       = 1
      resource_id        = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.main.name}"
      scalable_dimension = "ecs:service:DesiredCount"
      service_namespace  = "ecs"
    }
    
    resource "aws_appautoscaling_scheduled_action" "scale_up_prediction" {
      name               = "scale-up-prediction"
      service_namespace  = aws_appautoscaling_target.ecs_target.service_namespace
      resource_id        = aws_appautoscaling_target.ecs_target.resource_id
      scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension
      schedule           = "cron(0 8 * * ? *)" # Based on ML-predicted peak times
    
      scalable_target_action {
        min_capacity = 5
        max_capacity = 10
      }
    }
    HCL

    As infrastructure continues to evolve, Terraform remains a critical tool for creating, managing, and maintaining cloud infrastructure across diverse environments. By implementing modern practices like infrastructure as code, automated testing, and integrating with the broader DevOps ecosystem, organizations can achieve significant improvements in deployment speed, security posture, and operational efficiency.

    The future of infrastructure management is heading toward more automated, intelligent, and policy-driven approaches that can adapt to changing business needs while maintaining security and compliance. As Terraform and its ecosystem continue to grow, organizations that embrace these tools and practices will be well-positioned to thrive in an increasingly complex cloud landscape.


    Discover more from Altgr Blog

    Subscribe to get the latest posts sent to your email.

    Leave a Reply

    Your email address will not be published. Required fields are marked *