最後更新: 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
- Environment variables
- The terraform.tfvars file, if present.
- The terraform.tfvars.json file, if present.
- Any *.auto.tfvars or *.auto.tfvars.json files, processed in lexical order of their filenames.
- 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] } }