Table of Contents
Terraform
Debugging
# https://developer.hashicorp.com/terraform/internals/debugging # investigage errors export TF_LOG="TRACE" export TF_LOG_PATH="./terraform.log"
Glossary
Terraform Module | A Terraform module is a set of Terraform configuration files in a single directory. |
Installation https://askubuntu.com/questions/983351/how-to-install-terraform-in-ubuntu
Introduction: https://www.terraform.io/intro/getting-started/build.html
Skeleton project https://github.com/skipidar/terraform-skeleton
Apply terraform bash script
#!/bin/bash set -eo pipefail if [[ ! -d ".terraform" ]] then terraform init fi terraform validate terraform plan #terraform apply
Upgrade terraform provider
https://developer.hashicorp.com/terraform/tutorials/configuration-language/provider-versioning
terraform init -upgrade Initializing the backend... Initializing provider plugins... - Finding hashicorp/aws versions matching "~> 5.0"... - Installing hashicorp/aws v5.21.0... - Installed hashicorp/aws v5.21.0 (signed by HashiCorp) Terraform has made some changes to the provider dependency selections recorded in the .terraform.lock.hcl file. Review those changes and commit them to your version control system if they represent changes you intended to make. Terraform has been successfully initialized!
Main
Create “main.tf”
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 3.0" } } } provider "aws" { profile = "default" region = format("%s", var.aws_region) }
Variables
Create “variables.tf”
variable "aws_region" { description = "The AWS region to deploy the resources into" type = string default = "eu-central-1" } variable "aws_account_id" { description = "The AWS account identifier of the project" type = string default = "1234567891234" } variable "prefix" { description = "The resource prefix" type = string default = "alf-dev-con1" } locals { iot_policy = "${var.prefix}-thing2" }
locals defines inner variables. Only here one can combine other variables
Use the variable
provider "aws" { profile = "default" region = var.region }
Data
When you define data
blocks Terraform communicates with the AWS provider to query AWS and fetch the list of requested resources, mentioned in data-block.
You can apply filters.
# Find the latest available AMI that is tagged with Component = web data "aws_ami" "web" { filter { name = "state" values = ["available"] } filter { name = "tag:Component" values = ["web"] } most_recent = true }
Create templates.tf
data "template_file" "tf_iot_policy" { vars = { aws_region = "${var.aws_region}" aws_account_id = "${var.aws_account_id}" } template = <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iot:Connect", "iot:Publish", "iot:Receive", "iot:Subscribe" ], "Resource": "arn:aws:iot:$${aws_region}:$${aws_account_id}:*" } ] } EOF }
Usage
resource "aws_iot_policy" "iot_policy" { name = "${local.iot_policy}" policy = "${data.template_file.tf_iot_policy.rendered}" }
Dynamic block
See https://spacelift.io/blog/terraform-dynamic-blocks
To replace the repetitive code as here in a module:
resource "azurerm_virtual_network" "dynamic_block" { name = "vnet-dynamicblock-example-centralus" resource_group_name = azurerm_resource_group.dynamic_block.name location = azurerm_resource_group.dynamic_block.location address_space = ["10.10.0.0/16"] subnet { name = "snet1" address_prefix = "10.10.1.0/24" } subnet { name = "snet2" address_prefix = "10.10.2.0/24" } subnet { name = "snet3" address_prefix = "10.10.3.0/24" } subnet { name = "snet4" address_prefix = "10.10.4.0/24" } }
Use the “dynamic” block
resource "azurerm_virtual_network" "dynamic_block" { name = "vnet-dynamicblock-example-centralus" resource_group_name = azurerm_resource_group.dynamic_block.name location = azurerm_resource_group.dynamic_block.location address_space = ["10.10.0.0/16"] dynamic "subnet" { for_each = var.subnets iterator = item #optional content { name = item.value.name address_prefix = item.value.address_prefix } } }
Declare a variable in your module
variable "subnets" { description = "list of values to assign to subnets" type = list(object({ name = string address_prefix = string })) }
USAGE of your module
Assigning values to the variable “subnets”, which are taken by the module above.
subnets = [ { name = "snet1", address_prefix = "10.10.1.0/24" }, { name = "snet2", address_prefix = "10.10.2.0/24" }, { name = "snet3", address_prefix = "10.10.3.0/24" }, { name = "snet4", address_prefix = "10.10.4.0/24" } ]