Terraform related projects
- Providers can be cached by using
TF_PLUGIN_CACHE_DIR
so that instead of having to download them each time you runterraform init
, terraform will check initially if they exist in that directory and if they're there then they won't be downloaded
- In cases of having connectivity issues you can use the variable
TF_PLUGIN_DIR
to point to some location where plugins already exist so that they can be used
TF_LOG
ENV var can be set to specific verbosity level to get a better insight
# Format all the files in the directory
terraform fmt -recursive
# State file related
# Remove a resource from state file
terraform state rm <id>
# import a resource into state file
terraform import
# show all deployed resources
terraform state list
# show specifics about a resource
terraform state show <id>
# Move resources between different state files (Useful if we want to rename resources but don't want to destroy and re-create them)
terraform state mv
# Preview state file
terraform state pull
- From the book Terraform in Action
- At minimum each module should have
main.tf
,outputs.tf
andvariables.tf
# Root Module directory structure
variables.tf # Input variables
terraform.tfvars #variable definitions (Setting the vars)
providers.tf # provider declaration
main.tf # entrypoint
outputs.tf # outputs that can be passed to child modules
versions.tf # for provider version locking
- From the course Developing Infrastructure as Code with Terraform (LiveLessons)
- By default Terraform creates 1 resource if no count is specified
- When count attribute is used, Terraform is able to create N Number of resources
# Create 2 S3 buckets
resources "aws_s3_bucket" "s3_bucket" {
count = 2
bucket = "localstack-bucket-${count.index}"
}
- One use case is to also set count to zero in case you want to achieve the following behavior
- The resource to be ignored if its not created # Debugging
- The resource to be destroyed if it was created
- Takes a map of values and iterates over it to create a resource for each item in the map
- Insetad of
countit provides an each object which has akey/value
for each object in the map
locals {
buckets = {
bucket1 = "first-bucket"
bucket2 = "second-bucket"
}
}
resource "aws_s3_bucket" "s3_bucket" {
for_each = local.buckets
bucket = "this-is-my-${each.value}"
}
- For each supports also lists but you should use
toset
with for each to achieve that
locals {
buckets = [ "first-bucket", "second-bucket"]
}
resource "aws_s3_bucket" "s3_bucket" {
for_each = toset(local.buckets)
bucket = "this-is-my-${each.key}"
}
minimum_number_of_buckets = 5
number_of_buckets = var.bucket_count > 0 ? var.bucket_count : local.minimum_number_of_buckets
# Condition
var.bucket_count > 0
# If it evaluates to true
var.bucket_count
# If it evaluates to false
local.minimum_number_of_buckets
- Whatever gets returned is assigned to
number_of_buckets
variable
variable "bucket_count" {
type = number
}
locals {
minimum_number_of_buckets = 5
number_of_buckets = var.bucket_count > 1 ? var.bucket_count : local.minimum_number_of_buckets
}
locals {
// Returns current date and time
// Example for returned output from invoking the function via terraform cli
// "2022-10-11T08:51:58Z"
timestamp = timestamp()
current_year = formatdate("YYYY", local.timestamp)
current_month = formatdate("MMMM", local.timestamp)
tomorrow = formatdate("DD", timeadd(local.timestamp, "24h"))
}
output "date_time" {
value = "${local.current_year} ${local.current_month} ${local.tomorrow}"
}
locals {
my_list = ["one", "zwei", "three"]
# Square brackets are used to return a list
uppercase_list = [for item in local.my_list: upper(item)]
# Curly brackets are used to return a map
uppercase_map_convert = { for item in local.my_list: item => upper(item) }
}
output "iterations" {
value = local.uppercase_map_convert
}
# Filtering
locals {
numbers_list = [0, 1, 2, 3, 4, 5, 6]
# return number if the condition evaluated to true
even_numbers = [for number in local.numbers_list: number if number % 2 == 0]
}
output "even_numbers_list" {
value = local.even_numbers
}
- For outputting documentation, can be used with a similar syntax of Jinja2
- The minus sign after the double less than sign is to indicate character stripping from the lines following
locals {
name = ""
}
output "your_name" {
value = <<-EOT
This is a `heredoc` with directives
%{if local.name == "" }
Plase fill in the name
%{else}
Hi ${local.name}
%{endif}
EOT
}
locals {
numbers_list = [0, 1, 2, 3, 4, 5, 6]
}
output "even_numbers" {
value = <<-EOT
%{for number in local.numbers_list}
%{if number % 2 == 0}
${number} is even
%{endif}
%{endfor}
EOT
}
- A shared storage medium that stores
statefile
and can optionally support locking to prevent statefile corruption
backend "s3" {
bucket = "name"
key = "key"
dynamodb_table = "lock"
}
- Used in case we want same configuration across multiple environments (dev, staging, prod)
- Workspaces are a second state file associated with the configuration
# By default we're already using a default workspace
terraform workspace list # shows default
# Create new workspace
terraform workspace new staging
# Show the current workspace
terraform workspace show
# Select default workspace instead
terraform workspace select default