Terraform for the Absolute Beginners - udemy

Terraform for the Absolute Beginners - udemy - labs

Basic Concepts

IaC tools

3 phases of Terraform

  1. init
  2. plan
  3. apply

.tfstate ?

HCL syntax

<block> <parameters> {
  key1 = value1
  keyN = valueN
}

example:

# resource: block name
# local_file: resource type
#   local = provider
#   file = resource
# pet: resource name
resource "local_file" "pet"{
  # here goes the arguments
  filename = "/root/pets.txt"
  content = "We love pets!"
}

aws-ec2.tf:

resource "aws_instance" "webserver" {
  ami = "ami-123456..."
  instance_type = "t2.micro"
}

aws-s3.tf:

resource "aws_s3_bucket" "data" {
  bucket = "webserver-bucket-org-2206"
  acl = "private"
}

4 steps of basic Terraform workflow

  1. write the .tf file
  2. terraform init
  3. terraform plan
  4. terraform apply

See also: terraform show

Destroy a resource: terraform destroy

provider types

Terraform vars

variables.tf:

variable "var_name" {
  default = "default value"
  # optionals:
  type = <variable-type>
  description = <text>
}

Now we can reference the variable in our main.tf:

resource "local_file" "pet" {
  filename = var.var_name
}

When we explicitly declare a variable we are actually setting a constraint for the values that can be stored in the variable.

Variable types:

Variable definition Precendence:

Terraform uses the last value it finds, overriding any previous values.

This is the sequence (remember: what comes later takes precedence):

  1. environment variables: TF_VAR_varname
  2. terraform.tfvars
  3. *.auto.tfvars or *.auto.tfvars.json (alphabetical order)
  4. -var or -var-file in command line

output variables

output "<variable-name>" {
  value = "<variable-value>"
  <arguments>
}

inspect the value with terraform output or terraform output <variable-name>.

Terraform Commands

# check if config is correct
terraform validate

# formats the code in the config file
terraform fmt

# show the state
terraform show
terraform show -json

# show current providers
terraform providers

# display outputs mentioned in the configs
terraform output

# sync terraform state with the actual state
# NOTE: it doesn't change anything in the resources,
#       only sync the tfstate
terraform refresh

# create a graph for visualization of the dependencies
terraform graph
# install graphviz so you can use it like this
terraform graph | dot -Tsvg > graph.svg

LifeCycle Rules

resource "loca_file" "pet" {
  # ...
  lifecycle {
    create_before_destroy = true
    # prevent_destroy = true
    # ignore_changes = [ tags ]
  }
}

Data Sources

docs

Data Sources allow Terraform to read attributes from resources which are provisioned outside its control.

Example to read attributes from the local file called dogs.txt:

data "local_file" "dog" {
  filename = "/root/dog.txt"
}

resource vs. data source:

resource data source
keyword: resource keyword: data
creates, updates and destroys infrastructure reads infrastructures
aka "managed resources" aka "data resources"

Meta Arguments

count

Creating 3 files

# main.tf
resource "local_file" "pet" {
  filename = var.filename[count.index]
  count = 3
}

# variables.tf
variable "filename" {
  default = [
    "/root/pets.txt",
    "/root/dogs.txt",
    "/root/cats.txt"
  ]
}

Note that count = 3 is hardcoded above 👆

A more dynamic way would be to use count = length(var.filename)

for_each

# main.tf
resource "local_file" "pet" {
  filename = each.value
  for_each = toset(var.filename)
}

# variables.tf
variable "filename" {
  type = list(string)
  default = [
    "/root/pets.txt",
    "/root/dogs.txt",
    "/root/cats.txt"
  ]
}

Version Constraints

When you run terraform init, terraform always get the latest version of each provider plugin.

terraform {
  required_providers {
    local = {
      source = "hashicorp/local"
      version = "1.4.0"
      # version = "!= 1.4.0" # do NOT use 1.4.0
      # version = "< 1.4.0"
      # version = "> 1.4.0"
      # version = "> 1.2.0, < 2.0.0, != 1.4.0"
      # version = "~> 1.4" # keep the major version, increments minor
      # version = "~> 1.2.0" # keep the minor version, increments patch
    }
  }
}

resource "local_file "pet" {
  # ...
}

AWS

IAM

doc: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user

resource "aws_iam_user" "admin-user" {
  name = "lucy"
  tags {
    Description = "Technical Team Leader"
  }
}

S3

# create the bucket
resource "aws_s3_bucket" "finance" {
  bucket = "finance-21092020"
  tags = {
    Description = "Finance and Payroll"
  }
}

# create an object inside the bucket
resource "aws_s3_object" "finance-2020" {
  source = "/root/finance/finance-2020.doc"
  key = "finance-2020.doc"
  bucket = aws_s3_bucket.finance.id
}

Remote State

...

terraform state commands

terraform state show aws_s3_bucket.finance

# terraform state <subcommand> [options] [args]

subcommands: