Terraform Visual
rover
Object
variable "health_check" {
type = object({
type = string
protocol = string
timeout = number
})
default = {
protocol = "http"
type = "ipv4"
timeout = 20
}
}
# 先运行 terraform plan 或者 apply,然后再运行 terraform console 来测试
# 直接 .出属性,或者[""]
-> % terraform console
> var.health_check
{
"protocol" = "http"
"timeout" = 20
"type" = "ipv4"
}
> var.health_check.type
"ipv4"
> var.health_check["type"]
"ipv4
Map
Basic Usage of Maps
variable "region" {
type = "string"
default = "us-east-1"
}
variable "ami" {
type = map(string)
default = {
"us-east-1" = "ami-123456",
"us-west-1" = "ami-abcdef"
}
}
locals {
defaults = {
instance_type = "t2.micro",
count = 1
}
overrides = {
us-east-1 = {
instance_type = "t2.large",
count = 2
}
}
instance_types = {
"small" = "t2.micro",
"large" = "t2.large"
}
}
#
resource "aws_instance" "example" {
ami = var.ami[var.region]
instance_type = "t2.micro"
}
# merging maps
# count
resource "aws_instance" "advanced_example" {
count = merge(local.defaults, local.overrides[var.region]).count
ami = var.ami[var.region]
instance_type = merge(local.defaults, local.overrides[var.region]).instance_type
}
# Conditionals with Maps
resource "aws_instance" "conditional_example" {
count = var.size == "large" ? local.instance_types["large"] : local.instance_types["small"]
ami = var.ami[var.aws_region]
instance_type = local.instance_types[var.size]
}
# Looping Over Maps
# for_each each.key/each.value
resource "aws_instance" "looping_example" {
for_each = var.ami
ami = each.value
instance_type = "t2.micro"
tags = {
"Name" = "Instance-${each.key}"
}
}
Map for_each
variable "map" {
type = map(string)
default = {
"name" = "value"
}
}
# terraform console
# 也可以 [""]获取值,但是一般map的key是不确定的
> var.map
tomap({
"name" = "value"
})
> var.map["name"]
"value"
# 对于map而已,k 就是key值,v就是 value值
> {for k, v in var.map: k=>v}
{
"name" = "value"
}
# map 也有length
> length(var.map)
1
Basic Filtering of Maps
variable "input_map" {
default = {
"a" = "apple",
"b" = "banana",
"c" = "cherry"
}
}
# Filtering Based on Key
{for k, v in var.input_map : k => v if substr(k, 0, 1) == "a"}
{
"a" = "apple"
}
# Filtering Based on Value
{for k, v in var.input_map : k => v if contains(["apple", "banana"], v)}
{
"a" = "apple",
"b" = "banana"
}
# Filtering and Transforming Map Values
{for k, v in var.input_map : k => upper(v) if substr(k, 0, 1) == "b"}
{
"b" = "BANANA"
}
# To combine these maps into one while filtering
variable "first_map" {
default = {
"a" = "apple",
"b" = "banana"
}
}
variable "second_map" {
default = {
"c" = "cherry",
"d" = "date"
}
}
{
{for k, v in var.first_map : k => v if substr(k, 0, 1) == "a"},
{for k, v in var.second_map : k => v if substr(k, 0, 1) == "d"}
}
{
"a" = "apple",
"d" = "date"
}
Map(Object)
variable "instance_details" {
type = map(object({
zone = string
size = string
}))
default = {
"instance1" = { zone = "us-west-1a", size = "t2.micro" },
"instance2" = { zone = "us-west-1b", size = "t2.small" }
}
}
- Basic Iteration with count
shell resource "aws_instance" "example" { count = length(var.instance_details) ami = "ami-123456" instance_type = var.instance_details[keys(var.instance_details)[count.index]].size availability_zone = var.instance_details[keys(var.instance_details)[count.index]].zone }
- Advanced Iteration with for_eachshell resource "aws_instance" "example" { for_each = var.instance_details ami = "ami-123456" instance_type = each.value.size availability_zone = each.value.zone tags = { Name = each.key } }
Conditional Iteration
locals {
filtered_instance_details = { for k, v in var.instance_details : k => v if v.zone == "us-west-1a" }
}
resource "aws_instance" "filtered_example" {
for_each = local.filtered_instance_details
ami = "ami-123456"
instance_type = each.value.size
availability_zone = each.value.zone
}
List
List(string)
> var.list-string
tolist([
"value",
"value1",
])
# List 都是有长度的
> length(var.list-string)
2
# 可以通过 index 取值
> var.list-string[1]
"value1"
# 不管是k还是v,都是用的v的值
> [for k,v in var.set: upper(k)]
[
"VALUE",
"VALUE1",
]
List(Object)
variable "iam_list" {
type = list(object({
name = string
trust = string
account = number
}))
default = [
{
name = "name1"
trust = "trust1"
account = 123
}
]
}
> var.iam_list
tolist([
{
"account" = 123
"name" = "name1"
"trust" = "trust1"
},
])
# 对于List(object) k,v 时,k 就是 index
# k=>v 这就是转成 map 了,key是index,value就是原来 list中的object
# 与 List(map(string)) 不同的是,map的是"0"=tomap({})
# 而 List(object) 为 "0" = {} ,
> {for k, v in var.iam_list: k=>v}
{
"0" = {
"account" = 123
"name" = "name1"
"trust" = "trust1"
}
}
# 单独的 v 就是里面的一个一个的 object
> [for v in var.iam_list: v]
[
{
"account" = 123
"name" = "name1"
"trust" = "trust1"
},
]
# 只单独的 k 就是 index
> [for k,v in var.iam_list: k]
[
0,
]
# List 的有 length
> length(var.iam_list)
1
# 可以通过 index去获取
> var.iam_list[0]
{
"account" = 123
"name" = "name1"
"trust" = "trust1"
}
List(map(string))
variable "list-map" {
type = list(map(string))
default = [
{
"key" = "value"
"name" = "rick"
}
]
}
# terraform console
> var.list-map
tolist([
tomap({
"key" = "value"
"name" = "rick"
}),
])
# 可以看 list 数量
> length(var.list-map)
1
# k为索引,v为值,这里的v值是map
> {for k,v in var.list-map: k=>v}
{
"0" = tomap({
"key" = "value"
"name" = "rick"
})
}
dynamic
resource "aws_security_group" "example" {
name = "example-group"
dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = ingress.value.from_port
to_port = ingress.value.to_port
protocol = ingress.value.protocol
cidr_blocks = ingress.value.cidr_blocks
}
}
}
execute shell/bash scripts
Basic Execution Using null_resource
resource "null_resource" "example" { provisioner "local-exec" { command = "echo Hello, World!" } }
- Advanced Usage: Passing Variables and Output
shell variable "greeting" { description = "Greeting to display" type = string default = "Hello, Terraform!" } resource "null_resource" "advanced_example" { provisioner "local-exec" { command = "echo ${var.greeting} > greeting.txt" environment = { GREETING = var.greeting } } }
- Advanced Usage: Passing Variables and Output
Executing Scripts From Files
resource "null_resource" "script_file" { provisioner "local-exec" { command = "bash ${path.module}/setup.sh" } }
- Using remote-exec for Remote Execution
shell resource "aws_instance" "web" { ami = "ami-a1b2c3d4" instance_type = "t2.micro" provisioner "remote-exec" { inline = [ "sudo apt-get update", "sudo apt-get install -y nginx", ] connection { type = "ssh" user = "ubuntu" private_key = file("~/mykey.pem") host = self.public_ip } } }
- Using remote-exec for Remote Execution
Basic File Copy with Terraform ```shell resource "aws_instance" "example" { ami = "ami-abc123" instance_type = "t2.micro"
provisioner "file" { source = "./source_file.txt" destination = "/tmp/destination_file.txt"
connection {
type = "ssh"
user = "ec2-user"
private_key = file("~/.ssh/id_rsa")
host = self.public_ip
}
} }
- Advanced Folder Synchronization
```shell
resource "null_resource" "sync_folder" {
triggers = {
always_run = "${timestamp()}"
}
provisioner "local-exec" {
command = "rsync -avz ./source_folder/ ec2-user@${aws_instance.example.public_ip}:/tmp/destination_folder"
environment = {
AWS_DEFAULT_REGION = var.region
}
}
}
Set
variable "set" {
type = set(string)
default = [ "value", "value", "value1" ]
}
# terraform console
> var.set
toset([
"value",
"value1",
])
# set 数据有length很正常
> length(var.set)
2
# 这里不管用 k,v 都是 v的值
> [for k,v in var.set: upper(k)]
[
"VALUE",
"VALUE1",
]