Terraform
======
Installation
$ curl -s -o /tmp/terraform_1.5.3_linux_amd64.zip 'https://releases.hashicorp.com/terraform/1.5.3/terraform_1.5.3_linux_amd64.zip'
$ unzip /tmp/terraform_1.5.3_linux_amd64.zip -d /tmp/
$ chmod 755 /tmp/terraform
$ sudo mv /tmp/terraform /usr/local/bin/
Verify
$ terraform version
Terraform v1.5.3
on linux_amd64
HCL (HashiCorp Configuration Language) Syntax
<block> <parameters> {
key1 = value1
key2 = value2
}
Example
resource "local_file" "pet" {
filename = "/root/pets.txt"
contennt = "We love pets"
}
block name: resource
resource type: local_file
, local
is provider and file
is resource
resource name: pet
Terraform General Workflow
- Compile Terraform Files
terraform init
, understand providers will be used, download itterraform plan
, check execution plan which is what will be done by Terraformterraform apply
, implemnt execution plan
Basics
Env Variables
export TF_LOG=<log_level>
- INFO
- WARNING
- ERROR
- DEBUG
- TRACE
export TF_LOG_PATH=<file_name>
Variables
Type (Optional)
| Key | Example | Note |
| :—— | :—— | :—— |
| string | “pets.txt” | |
| number | 1 | |
| bool | true/false | |
| any | Default Value | |
| list | [“cat”, “dog”, “cat”] | |
| set | [“cat”, “dog”] | can’t have duplicate element |
| map | pet1 = cat
pet2 = dog | |
| object | Complex Data Structure | |
| tuples | Complex Data Structue | can have different type of elements, but list
can’t |
$ cat <<EOF >variables.tf
variable "filename" {
default = "pets.txt"
type = string
}
variable "content" {
default = "We love panda"
type = string
}
variable "prefix" {
default = "Mrs"
type = string
}
variable "separator" {
default = "."
type = string
}
variable "length" {
default = 3
type = number
}
EOF
$ cat <<EOF >file.tf
resource "local_file" "pet" {
filename = var.filename
content = var.content
file_permission = "0700"
}
resource "random_pet" "my-pet" {
prefix = var.prefix
separator = var.separator
length = var.length
}
EOF
Variable files will be automatically loaded:
- terraform.tfvars (
variable.tf
is needed) - terraform.tfvars.json (
variable.tf
is needed) - *.auto.tfvars (
variable.tf
is needed) - *.auto.tfvars.json (
variable.tf
is needed) - *.tf
Variable Definition Percedence
Order | Operation |
---|---|
1 | Environment Variables |
2 | terraform.tfvars |
3 | *.auto.tfvars(alphabetical order) |
4 | -var or -var-file cmd parameters |
Resources
Resource Attribute
$ cat <<EOF > file.tf
resource "local_file" "pet" {
filename = var.filename
content = "current time is ${time_static.time_current.id}"
file_permission = "0700"
}
resource "time_static" "time_current" {
}
EOF
Output Variable
$ cat <<EOF> time.tf
resource "time_static" "time_current" {
}
output "time" {
value = time_static.time_current.id
}
EOF
$ terraform output
time = "2023-07-22T13:20:26Z"
Provider
$ cat <<EOF> provider.tf
provider "aws" {
region = var.region
s3_use_path_style = true
skip_credentials_validation = true
skip_requesting_account_id = true
endpoints {
s3 = "http://aws:4566"
}
}
EOF
Commands
https://developer.hashicorp.com/terraform/cli/commands/
validate
Validates the configuration files in a directory
fmt
Rewrite Terraform configuration files to a canonical format and style
providers
List all of the provider requirements for all current conguration files
terraform provides mirror ${target directory}
Copy all required provider plugins to a target directory
refresh
Fetch the current state from all managed remote objects and updates the Terraform state.
graph
Outputs the visual execution graph.
terraform graph | dot -Tsvg > graph.svg
State
Json formatted, non-operational
terraform show
to inspect latest state snapshot.
terraform output
to show all output values or specific named values from latest state snapshot.
Meta-Arguments
depends_on
Explicit Dependency
cat <<EOF> file.tf
resource "local_file" "pet" {
filename = var.filename
content = "current time is"
file_permission = "0700"
depends_on = [
time_static.time_current
]
}
resource "time_static" "time_current" {
}
EOF
lifeCycle
Create new resources before destroy old resources
lifecycle {
create_before_destroy = true
}
Prevent resources to be deleted during changes
lifecycle {
prevent_destroy = true
}
Ignore changes to Resources Attributes (specific / all)
lifecycle {
ignore_changes = [
${attribute list}
]
}
count
creates that many instances of the resource or module as count
cat <<EOF >random.tf
resource "random_string" "string" {
length = 6
count = 3
}
EOF
cat <<EOF >variable.tf
variable "project-users" {
type = list(string)
default = [ "matrix1", "matrix2"]
}
EOF
cat <<EOF >pet.tf
resource "random_pet" "pets" {
prefix = var.project-users[count.index]
count = length(var.project-users)
length = 2
}
EOF
for-each
need to defined as set
or map
$ cat <<EOF > variable.tf
variable "filename" {
default = [
"matrix1.txt",
"matrix2.txt"
]
}
EOF
$ cat <<EOF > local.tf
resource "local_file" "matrix" {
filename = each.value
for_each = toset(var.filename)
content = "${each.value}"
}
EOF
Datasources
data "local_file" "terraform" {
filename = "time.tf"
}
Version Constraints
terraform {
required_providers {
local = {
source = "hashicorp/local"
version = "1.4.0"
}
}
}
=
or no operator: eqaul
!=
: not equal
>
, >=
, <
, <=
: Comparisons against a specified version, allowing versions for which the comparison is true. “Greater-than” requests newer versions, and “less-than” requests older versions.
~>
: Allows only the rightmost version component to increment. For example, to allow new patch releases within a specific minor release, use the full version number: ~> 1.0.4 will allow installation of 1.0.5 and 1.0.10 but not 1.1.0. This is usually called the pessimistic constraint operator.
State File
Remote State
OBS
cat <<EOF> terraform.tf
terraform {
backend "s3" {
bucket = "matrix-obs-1"
key = "terraform/terraform.tfstate"
endpoint = "https://obs.ae-ad-1.vb.g42cloud.com"
region = "ae-ad-1"
access_key = "{access key}"
secret_key = "{secret key}"
skip_region_validation = true
skip_credentials_validation = true
}
}
EOF
terraform init
state
cmd
terraform state list
list all resources
terraform state show <address>
show the attributes of a single resource
terraform state mv SOURCE DESTINATION
move resource in state file
terraform state rm ADDRESS
remove resource in state file
Provisioners
cat terraform.tf
......
provisioner "remote-exec" {
echo "this is a remote provisioner from terraform" >> /tmp/terraform.txt
}
connection {
type = "ssh"
host = self.public_ip
user = "ubuntu"
private_key = file(~/.ssh/id_rsa)
}
.....
Module
Make code more easier to be reused. More modules can be checked from Terraform Offical Registry
$ tree .
.
├── dido
│ ├── main.tf
├── local_file
│ ├── main.tf
│ └── variable.tf
└── matrix
└── main.tf
3 directories, 4 files
$ cat local_file/main.tf
resource "local_file" "localfile" {
filename = "/tmp/${var.name}/module.txt"
content = "it was generated by module with var: ${var.name}"
}
$ cat local_file/variable.tf
variable "name" {
type = string
}
$ cat matrix/main.tf
module "local_file_matrix" {
source = "../local_file"
name = "matrix"
}
$ cat dido/main.tf
module "local_file_dido" {
source = "../local_file"
name = "dido"
}