03 - Terraform Syntax

最後更新: 2023-05-25

目錄

  • Variables
  • set vs list
  • object
  • map
  • Variables Input
  • Load variables order
  • Local Values
  • X?0:1
  • Data Source - AMI lookup
  • If
  • Dynamic Block
  • Calling a Child Module
  • name v.s. name_prefix
  • lifecycle

 


Variables

 

Basic: string, number, bool

Complex

  • list(<TYPE>)
  • set(<TYPE>)
  • map(<TYPE>)
  • object({<ATTR NAME> = <TYPE>, ... })

 * For lists or maps, use plural nouns to show that it represents multiple values.

Input Variable

方式1: CLI Variable

 resource "aws_instance" "app_server" {
   ami           = "ami-08d70e59c07c61a3a"
   instance_type = "t3.micro"
   tags = {
     Name = var.web_instance_name
   }
 }

# Setting variables via the command-line

terraform apply -var "web_instance_name=AppServer"

方式2: variables.tf

variable "web_instance_name" {
  description = "App server name"
  type        = string
  default     = "AppServer"
}

default(optional)

The default value will be used if no value is set when calling the module or running Terraform.

nullable

The default value for nullable is true

Passing a null value as a module input argument will override any default value

建議

Support for validation in variables is rather limited

調用

"${var.subnet_id}"

String concat with variable

i.e.

tags = {
  Name = "${var.project-name}-vpc"
}

 


set vs list

 

list - 表示一個有序的集合且需要使用索引來存取元素
set - 表示一個無序的集合且需要確保其中的元素都是唯一的

set of string

variable "my_set" {
  type    = set(string)
  default = ["png", "jpg"]
}

list of string

variable "my_list" {
  type    = list(string)
  default = ["foo", "bar", "baz"]
}

 


object

 

variable "user_information" {
  type = object({
    name    = string
    address = string
  })
  sensitive = true
}

resource "some_resource" "a" {
  name    = var.user_information.name
  address = var.user_information.address
}

 


map

 

variable "awsprops" {
  type = map(string)
  default = {
    region = "ap-east-1"
    vpc    = "lab1-vpc"
    ami    = "ami-05ec72576b2b4738f"
    itype  = "t3.micro"
    tag    = "Lab1"
  }
}

provider "aws" {
  region = lookup(var.awsprops, "region")
  default_tags {
    tags = {
      Terraform   = "true"
      Environment = lookup(var.awsprops, "tag")
    }
  }
}

Lookup Function

lookup retrieves the value of a single element from a "map"

lookup(map, key)

 


Variables Input

 

Input Variables

terraform apply -var='image_id_list=["ami-abc123","ami-def456"]' -var="instance_type=t2.micro"

----

terraform apply -var-file="testing.tfvars"

Terraform also automatically loads a number of variable definitions files if they are present:

    Files named exactly terraform.tfvars or terraform.tfvars.json.
    Any files with names ending in .auto.tfvars or .auto.tfvars.json.
    
-----
    
Environment Variables

environment variables named TF_VAR_ followed by the name of a declared variable.

export TF_VAR_image_id=ami-abc123

 


Load variables order

 

 * LAST Win

Order

  1. Environment variables
  2. The terraform.tfvars file, if present.
  3. The terraform.tfvars.json file, if present.
  4. Any *.auto.tfvars or *.auto.tfvars.json files, processed in lexical order of their filenames.
  5. Any -var and -var-file options on the command line

 


Local Values

 

A local value assigns a name to an "expression"

locals {
  service_name = "forum"
  owner        = "Community Team"
}

The expressions in local values are not limited to literal constants;

locals {
  # Common tags to be assigned to all resources
  common_tags = {
    Service = local.service_name
    Owner   = local.owner
  }
}

# Using Local Values

resource "aws_instance" "example" {
  # ...
  tags = local.common_tags
}

 


X?0:1

 

main.tf

locals {
  create_vpc = var.vpc_id == ""
}

data "aws_vpc" "selected" {
  count = local.create_vpc ? 0 : 1

  id = var.vpc_id
}

 


Data Source - AMI lookup

 

data "aws_ami" "ubuntu_ami" {
  most_recent = true
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }
  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
  owners = ["099720109477"] # Canonical
}

使用

resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu_ami.id
  ...
}

 


If

 

Syntax

condition ? true_val : false_val

Operators

a == b returns true if a and b both have the same type and the same value
a != b is the opposite of a == b
!a returns true if a is false

i.e.

#

var.example != "" ? var.example : "default"

# 果變數 example 的值為 12, 則返回 12, 否則返回字串 "hello"

var.example ? 12 : "hello"

 * In Terraform all numbers can convert automatically to a string
    所以這裡的 12 是 String 來.

if/else

Unfortunately, Terraform doesn't support if/else statements.

So more logically complex statements must be implemented manually.
(&&, ||, !)

count

# one way to deploy a resource multiple times is by using "count"

i.e.

resource "aws_eip" "lab3_app" {
    count = eip == "" ? 1 : 0
    ...
}

 

 


Dynamic Block

 

dynamic "LABEL" {
  content {
    ...
  }
}

i.e.

dynamic "ingress" {
  for_each = local.alb_inbound_ports
  content {
    from_port   = ingress.value
    to_port     = ingress.value
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

iterator - (optional)

iterator = ingress

Sets the name of a temporary variable that represents the current element of the complex value.

If omitted, the name of the variable defaults to the label of the dynamic block

iterator.value

from_port   = ingress.value

value is the value of the current element.

 


Calling a Child Module

 

main.tf

module "alb" {
  source  = "./modules/alb"
  name    = "${var.project-name}-MyALB"
  ...
}

module 的結構

└── alb
    ├── locals.tf
    ├── main.tf
    ├── outputs.tf
    └── variables.tf

module 的 in / out 是透過 outputs.tf 及 variables.tf 進行

 


name v.s. name_prefix

 

name_prefix

Cannot be longer than 6 characters.

name

If omitted, Terraform will assign a random, unique name.
This name must be unique per region per account,
maximum of 32 characters
alphanumeric characters or hyphens, and must not begin or end with a hyphen.

 


lifecycle

 

i.e. aws_alb_target_group

resource "aws_alb_target_group" "web_tg" {
    ...
    lifecycle {
        create_before_destroy = true
    }
}

i.e. aws_ecs_service

resource "aws_ecs_service" "webService" {
  ...
  lifecycle {
    ignore_changes = [desired_count, task_definition]
  }
}

 

 

 

Creative Commons license icon Creative Commons license icon