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