Terraform Apps and Infra 4 - Hands-on CLI

CLI to manipulate a Terraform deployment

  • Task

      graph TD
    A[Main Terraform code]
    B[default workspace]
    C[test workspace]
    D[default workspace state file is terraform.tfstate]
    E[test workspace state file resides in terraform.tfstate.d directorys]
    F(terraform.workspace value is default)
    G(terraform.workspace value is test)
    H(deploys to PRO account)
    I(deploys to staging account)
    
    A --> B
    B --> D
    D --> F
    F --> H
    A --> C  
    C --> E
    E --> G
    G --> I
  • Terraform code

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # depending on the workspace, we select different regions
    provider "aws" {
    region = terraform.workspace == "default" ? "us-east-1" : "us-west-2"
    }

    # Get Linux AMI ID using SSM Parameter endpoint in us-east-1
    data "aws_ssm_parameter" "linuxAmi" {
    name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
    }

    # Create and bootstrap EC2 in us-east-1
    resource "aws_instance" "ec2-vm" {
    ami = data.aws_ssm_parameter.linuxAmi.value
    instance_type = "t3.micro"
    associate_public_ip_address = true
    vpc_security_group_ids = [aws_security_group.sg.id]
    subnet_id = aws_subnet.subnet.id
    tags = {
    Name = "${terraform.workspace}-ec2"
    }
    }
  • CLI commands required

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    # WORKSPACES
    # check which workspaces we have. WeAt least we get default
    terraform workspace list
    terraform workspace new test
    # check we have automatically switched to the new one
    terraform workspace list

    # DEPLOY ON TEST WORKSPACE
    terraform init
    # avoid inputing "yes" all the time with auto-approve
    terraform apply --auto-approve
    # check deployment
    terraform state list

    # DEPLOY ON DEFAULT
    terraform workspace select default
    # check we are indeed on default
    terraform workspace list
    # check state is empty for this workspace
    terraform state list
    terraform init
    # avoid inputing "yes" all the time with auto-approve
    terraform apply --auto-approve
    # check deployment
    terraform state list
    # check there is a terraform.tfstate.d directory, which contains the test workspace
    ls

    # CLEAN UP TEST
    terraform workspace select test
    terraform workspace destroy --auto-approve
    terraform workspace select default
    terraform workspace delete test

Build and test Terraform module

  • Tasks

      graph LR
    
    subgraph Modules
    A[main.tf]
    B[variables.tf]
    C[outputs.tf]
    end
    
    D[main_code.tf]
    E(EC2 VM)
    
    B -- variables:inputs --> D
    C -- outputs returned by module --> D
    D --> E
  • Terraform code

    • Terraform VPC module
      • main.tf
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        # vpc module
        provider "aws" {
        region = var.region
        }

        resource "aws_vpc" "this" {
        cidr_block = "10.0.0.0/16"
        }

        resource "aws_subnet" "this" {
        vpc_id = aws_vpc.this.id
        cidr_block = "10.0.1.0/24"
        }

        data "aws_ssm_parameter" "this" {
        name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
        }
      • variables.tf
        1
        2
        3
        4
        variable "region" {
        type = string
        default = "us-east-1"
        }
      • outputs.tf
        1
        2
        3
        4
        5
        6
        7
        # critical to exporting values
        output "subnet_id" {
        value = aws_subnet.this.id
        }
        output "ami_id" {
        value = data.aws_ssm_parameter.this.value
        }
    • Terraform project module
      • main.tf
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        variable "main_region" {
        type = string
        default = "us-east-1"
        }

        provider "aws" {
        region = var.main_region
        }

        # invokes the VPC module
        module "vpc" {
        source = "./modules/vpc"
        region = var.main_region
        }

        resource "aws_instance" "my-instance" {
        ami = module.vpc.ami_id
        subnet_id = module.vpc.subnet_id
        instance_type = "t2.micro"
        }
      • outputs.tf
        1
        2
        3
        4
        output "PrivateIP" {
        description = "Private IP of EC2 instance"
        value = aws_instance.my-instance.private_ip
        }
  • CLI

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    # check terraform status
    terraform version

    # create project structure
    mkdir terraform_project
    cd terraform_project
    mkdir -p modules/vpc
    cd /home/cloud_user/terraform_project/modules/vpc/

    # main project directory
    cd ~/terraform_project

    # DEPLOY AND TEST
    # format the code in all of your files pre-deployment
    terraform fmt -recursive
    terraform init
    terraform validate
    # review actions that will be performed when you deploy
    terraform plan
    # deploy
    terraform apply --auto-approve
    # check
    terraform state list

    # CLEAN UP
    terraform destroy