===== 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 = < 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" } ]