|
#### first class expresssion |
|
variable "ami" {} |
|
resource "aws_instance" "example" { |
|
ami = var.ami |
|
} |
|
|
|
#### list & map |
|
resource "aws_instance" "example" { |
|
vpc_security_group_ids = var.security_group_id != "" ? [var.security_group_id] : [] |
|
} |
|
|
|
# In 0.12, HCL resolves this by making an explicit distinction between attributes and blocks. Attributes are single-assigned values using the assignment operator =. Blocks are repeated maps of key/value configuration pairs |
|
resource "aws_security_group" "example" { |
|
|
|
# "ingress" is parsed as a block because there is no equals sign |
|
ingress { |
|
# .. |
|
} |
|
|
|
# "value" is parsed as a attribute as it has equal sign |
|
value = { |
|
# .. |
|
} |
|
} |
|
|
|
### For Expressions for List and Map Transformations |
|
variable "subnet_numbers" { |
|
description = "List of 8-bit numbers of subnets of base_cidr_block that should be granted access." |
|
default = [1, 2, 3] |
|
} |
|
|
|
resource "aws_security_group" "example" { |
|
# For each number in subnet_numbers, extend the CIDR prefix of the |
|
# requested VPC to produce a subnet CIDR prefix. |
|
# For the default value of subnet_numbers above and a VPC CIDR prefix |
|
# of 10.1.0.0/16, this would produce: |
|
# ["10.1.1.0/24", "10.1.2.0/24", "10.1.3.0/24"] |
|
cidr_blocks = [ |
|
for num in var.subnet_numbers: |
|
cidrsubnet(data.aws_vpc.example.cidr_block, 8, num) |
|
] |
|
} |
|
} |
|
|
|
### How to produce a map |
|
output "instance_private_ip_addresses" { |
|
# Result is a map from instance id to private IP address, such as: |
|
# {"i-1234" = "192.168.1.2", "i-5678" = "192.168.1.5"} |
|
value = { |
|
for instance in aws_instance.example: |
|
instance.id => instance.private_ip |
|
# if statement |
|
if instance.associate_public_ip_address |
|
} |
|
} |
|
|
|
output "instances_by_availability_zone" { |
|
# Result is a map from availability zone to instance ids, such as: |
|
# {"us-east-1a": ["i-1234", "i-5678"]} |
|
value = { |
|
for instance in aws_instance.example: |
|
# mind the ... |
|
instance.availability_zone => instance.id... |
|
} |
|
} |
|
|
|
### Dynamic Nested Blocks |
|
locals { |
|
base_cidr_block = "10.0.0.0/16" |
|
} |
|
|
|
variable "subnets" { |
|
default = [ |
|
{ |
|
name = "a" |
|
number = 1 |
|
}, |
|
{ |
|
name = "b" |
|
number = 2 |
|
}, |
|
] |
|
} |
|
|
|
variable "var_list" { |
|
type = list(string) |
|
default = ["a1", "a2"] |
|
} |
|
|
|
resource "azurerm_virtual_network" "example" { |
|
name = "example-network" |
|
resource_group_name = azurerm_resource_group.test.name |
|
address_space = [local.base_cidr_block] |
|
location = "West US" |
|
|
|
dynamic "subnet" { |
|
# [{"name": "a", "prefix": "10.1.0.0/24"}, |
|
# {"name": "b", "prefix": "10.2.0.0/24"}, |
|
for_each = [for s in subnets: { |
|
name = s.name |
|
prefix = cidrsubnet(local.base_cidr_block, 4, s.number) |
|
}] |
|
|
|
content { |
|
name = subnet.name |
|
address_prefix = subnet.prefix |
|
} |
|
} |
|
} |
|
|
|
resource "sample_dynamic_block_with_list" "example" { |
|
name = "example" |
|
|
|
dynamic "block" { |
|
for_each = toset(var.var_list) |
|
|
|
content { |
|
name = block.key |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
### Splat operator |
|
# before only work with resource with "count", now work for any list value |
|
output "instance_ip_addrs" { |
|
value = google_compute_instance.example.network_interface.*.address |
|
} |
|
|
|
# full splat operator |
|
# instead of network_interface.*. |
|
output "instance_net_ip_addrs" { |
|
value = google_compute_instance.example.network_interface[*].access_config[0].assigned_nat_ip |
|
} |
|
|
|
### Conditional Operator Improvements |
|
locals { |
|
first_id = length(azurerm_virtual_machine.example) > 0 ? azurerm_virtual_machine.example[0].id : "" |
|
|
|
buckets = (var.env == "dev" ? [var.build_bucket, var.qa_bucket] : [var.prod_bucket]) |
|
} |
|
|
|
### Conditionally Omitted Arguments |
|
variable "override_private_ip" { |
|
type = string |
|
default = null |
|
} |
|
|
|
resource "aws_instance" "example" { |
|
# By using the new null value, the aws_instance resource can dynamically assign a private IP address when no override is provided, |
|
# but set an explicit IP address if the calling module provides a value for override_private_ip. |
|
private_ip = var.override_private_ip |
|
} |
|
|
|
### Complex Values |
|
# complex objects can now be passed to child modules as inputs, and returned to parent modules as outputs |
|
# access with `for network in var.networks` |
|
module "subnets" { |
|
source = "./subnets" |
|
|
|
parent_vpc_id = "vpc-abcd1234" |
|
networks = { |
|
production_a = { |
|
network_number = 1 |
|
availability_zone = "us-east-1a" |
|
} |
|
production_b = { |
|
network_number = 2 |
|
availability_zone = "us-east-1b" |
|
} |
|
staging_a = { |
|
network_number = 1 |
|
availability_zone = "us-east-1a" |
|
} |
|
} |
|
} |
|
|
|
### Rich types |
|
variable "networks" { |
|
# custom type |
|
# no quote |
|
type = map(object({ |
|
network_number = number |
|
availability_zone = string |
|
tags = map(string) |
|
})) |
|
} |
|
|
|
### Resources and Modules as Values |
|
# return the whole object |
|
output "vpc" { |
|
value = aws_vpc.example |
|
} |
|
|
|
### New Template syntax |
|
locals { |
|
lb_config = <<EOT |
|
%{ for instance in opc_compute_instance.example ~} |
|
server ${instance.label} ${instance.ip_address}:8080 |
|
%{ endfor } |
|
EOT |
|
} |
|
|
|
### JSON comment |
|
{ |
|
"variable": { |
|
"example": { |
|
"#": "This property is ignored", |
|
"default": "foo" |
|
} |
|
} |
|
} |
|
|
|
### Validation |
|
|
|
variable "word-length" { |
|
|
|
validation { |
|
# The condition here identifies if the integer if greater than 1 |
|
condition = var.word-length > 1 |
|
error_message = "The variable is not greater than 5. Word length has to be at a minimum > 1." |
|
} |
|
} |
|
|
|
variable "os" { |
|
|
|
validation { |
|
# The condition here identifies if the variable contains the string "linxu" OR "windows". |
|
condition = can(regex("linux|windows", var.os)) |
|
error_message = "ERROR: Operating System must be Windows OR Linux." |
|
} |
|
} |
|
|
|
locals { |
|
|
|
# This variable holds the all the IPs addresses for the S3 service returned by the endpoint. The return value is of the type list OR a string error value. |
|
s3_ips = try(distinct([ |
|
for items in jsondecode(data.http.primary-server.body).prefixes: |
|
items.ip_prefix if items.service == "S3" |
|
]), "NO LIST PROVIDED IN LOCALS SERVICES VARIABLE") |
|
|
|
} |
|
|
|
} |
elasticache import force
new resource
here