Skip to content

Musti4096/Terraform_Notes

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

68 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Terraform Notes

Terraform Lock HCL File

it locks all versions for us.

Terraform plan and apply

terraform plan -out=plan1 # we define our plan as plan1

terraform apply plan1 # execute our plan wihtout confirmation

Terraform State

  • we cna store our state file in our local machine, remote state ( blob or terraform cloud)
terraform show -json #it shows our state file with json format

terraform state list #list the resources that we created

Terraform Console

  • we use console for some testing issues
terraform console # we can enter console

docker_container.nginx_container.ip_address #we can reach container ip address.

Terraform Output

Terraform Outputs

  • it gives us some information about our resources and we can consume them in another resource
output "IP-Address" {
  value       = docker_container.nginx_container.ip_address
  description = "IP address of container"
}

output "container-name" {
  value = docker_container.nginx_container.name
}
terraform output #with that command we can see all outputs

Terraform Functions

Terraform Functions

Join Function

Join Function

join (seperator, list)

join ", ", ["foo", "bar", "baz"]
join(":", [docker_container.nginx_container.ip_address, docker_container.nginx_container.ports[0].external]) #we can join ip address and ports then use it in output

Terraform Random Resources

Random Resource

resource "random_string" "random" {
  length           = 16
  special          = true
  override_special = "/@ÂŁ$"
}
terraform {
  required_providers {
    docker = {
      source = "kreuzwerker/docker"
    }
  }
}
provider "docker" {}

resource "docker_image" "nginx_image" {
  name = "nginx:alpine"
}

resource "random_string" "random" {
  length  = 4
  special = false
  upper   = false
}

resource "random_string" "random2" {
  length  = 4
  special = false
  upper   = false
}

resource "docker_container" "nginx_container" {
  name  = join("-", ["nginx", random_string.random.result])
  image = docker_image.nginx_image.latest
  ports {
    internal = "80"
    # external = "80"
  }
}

resource "docker_container" "nginx_container2" {
  name  = join("-", ["nginx", random_string.random2.result])
  image = docker_image.nginx_image.latest
  ports {
    internal = "80"
    # external = "80"
  }
}

output "IP-Address" {
  value       = join(":", [docker_container.nginx_container.ip_address, docker_container.nginx_container.ports[0].external])
  description = "IP address of container"
}

output "container-name" {
  value = docker_container.nginx_container.name
}

output "container-name-2" {
  value = docker_container.nginx_container2.name
}

Multiple Resources and Count

Terraform Count

resource "random_string" "random" {
  count   = 2
  length  = 4
  special = false
  upper   = false
}
resource "docker_image" "nginx_image" {
  name = "nginx:alpine"
}

resource "random_string" "random" {
  count   = 2
  length  = 4
  special = false
  upper   = false
}


resource "docker_container" "nginx_container" {
  count = 2
  name  = join("-", ["nginx", random_string.random[count.index].result])
  image = docker_image.nginx_image.latest
  ports {
    internal = "80"
    # external = "80"
  }
}


output "IP-Address" {
  value       = join(":", [docker_container.nginx_container[0].ip_address, docker_container.nginx_container[0].ports[0].external])
  description = "IP address of container"
}

output "container-name" {
  value = docker_container.nginx_container[0].name
}

output "container2-name" {
  value = docker_container.nginx_container[1].name
}

The Splat Expression

The Splat Expression

output "container-name" {
  value = docker_container.nginx_container[*].name
}

For Loops

For Expression

output "IP-Address" {
  value       = [for i in docker_container.nginx_container[*] : join(":", [i.ip_address], i.ports[*]["external"])]
  description = "IP address of container"
}

output "container-name" {
  value = docker_container.nginx_container[*].name
}
[for i in docker_container.nginx_container[*] : join(":", [i.ip_address], [i.ports[0]["external"]])]

[for i in docker_container.nginx_container[*] : join(":", [i.ip_address], i.ports[*]["external"])]

Tainting a Source

  • If we want to force some resource to reload and reinstall, then we just use tainting

Tainting

terraform taint random_string.random[0] #just tainted a resource

terraform untaint random_string.random[0] #just untainted a resource

State Locking and Breaking State

terraform apply -lock=false #we just unlock the state
                            # default is lock=true

Terraform Import

Terraform Import

  • if we have more resources out of state, we can include them to our state file with import command

  • first we add resources to our .tf file, then use terraform import <resource_id> command

terraform import docker_container.nginx_container-2 $(docker inspect -f {{.ID}} nginx-yrwl)

Terraform Refresh and Terraform State rm

Terraform Refresh

  • The terraform refresh command reads the current settings from all managed remote objects and updates the Terraform state to match.

-This won't modify your real remote objects, but it will modify the the Terraform state.

terraform refresh

terraform refresh -target random_string.random #just targeted specific resources

Terraform State rm

  • if someone delete our resources that we keep them state file, and we want to update our state file. In thias case we can use terraform state rm command. just remove deleted resources from state file.
terraform state rm random_string.random[1]

Terraform Variables

Variables

terraform {
  required_providers {
    docker = {
      source = "kreuzwerker/docker"
    }
  }
}

provider "docker" {}

variable "ext_port" {
  type    = number
  default = 80
}

variable "int_port" {
  type    = number
  default = 80
}

variable "container_count" {
  type    = number
  default = 1
}

resource "docker_image" "nginx_image" {
  name = "nginx:alpine"
}

resource "random_string" "random" {
  count   = 1
  length  = 4
  special = false
  upper   = false
}


resource "docker_container" "nginx_container" {
  count = var.container_count
  name  = join("-", ["nginx", random_string.random[count.index].result])
  image = docker_image.nginx_image.latest
  ports {
    internal = var.int_port
    external = var.ext_port
  }
}

output "IP-Address" {
  value       = [for i in docker_container.nginx_container[*] : join(":", [i.ip_address], i.ports[*]["external"])]
  description = "IP address of container"
}

output "container-name" {
  value = docker_container.nginx_container[*].name
}

Variable Validation

Custom Variable Rules

variable "ext_port" {
  type    = number
  default = 80
  validation {
    condition     = var.ext_port == 80
    error_message = "The External port must be 80."
  }
}

variable "int_port" {
  type    = number
  default = 80
  validation {
    condition     = var.int_port <= 65535 && var.int_port > 0
    error_message = "The internal port must be in the valid port range 0 - 65535."
  }
}
Error: Invalid value for variable

  on main.tf line 11:
  11: variable "ext_port" {

The External port must be 80.

This was checked by the validation rule at main.tf:14,3-13.

Sensitive Variables and .tfvars file

Sensivite Variables

  • we just define variables in variables.tf file and put sensitive variables in to .tfvars file
variable "ext_port" {
  type      = number
  sensitive = true
}

Variable Definition Precedence

link

Terraform loads variables in the following order, with later sources taking precedence over earlier ones:

  • Environment variables
  • The terraform.tfvars file, if present.
  • The terraform.tfvars.json file, if present.
  • Any _.auto.tfvars or _.auto.tfvars.json files, processed in lexical order of their filenames.
  • Any -var and -var-file options on the command line, in the order they are provided. (This includes variables set by a Terraform Cloud workspace.)
terraform plan --var-file=centraf.tf #we just used anothter .tfvars file

terraform plan -var ext_port=1980 # we just mention our vars on cli

Local Exec Provisioner

Local-Exec Provisioner

resource "null_resource" "dockervol" {
  provisioner "local-exec" {
    command = "mkdir nginxvol/ || true && sudo chown -R 1000:1000 nginxvol/"
  }
}

Utilizing Local Values

Local Values

locals {
  container_count = length(var.ext_port)
}

resource "docker_container" "nginx_container" {
  count = local.container_count
  name  = join("-", ["nginx", random_string.random[count.index].result])
  image = docker_image.nginx_image.latest
  ports {
    internal = var.int_port
    external = var.ext_port[count.index]
  }
  volumes {
    container_path = "/data"
    host_path      = "/home/mustafa/Terraform/terraform-docker/nginxvol"
  }
}

Min and Max Functions and Expand Expression

Min and Max

max([10,20,30]...) > 30

variable "ext_port" {
  type = list(any)

  validation {
    condition     = max(var.ext_port...) <= 65535 && min(var.ext_port...) > 0
    error_message = "The internal port must be in the valid port range 0 - 65535."
  }
}

Path References and String Interpolations

Path references

Interpolation

resource "docker_container" "nginx_container" {
  count = local.container_count
  name  = join("-", ["nginx", random_string.random[count.index].result])
  image = docker_image.nginx_image.latest
  ports {
    internal = var.int_port
    external = var.ext_port[count.index]
  }
  volumes {
    container_path = "/data"
    host_path      = "${path.cwd}/nginxvol"
  }
}

Maps and LookUps

Map Lookup

variable "image" {
  type        = map(any)
  description = "image for container"
  default = {
    dev  = "nginx:latest"
    prod = "nginx:alpine"
  }
}

resource "docker_image" "nginx_image" {
  name = lookup(var.image, var.env)
}

Terraform Workspaces

Workspace

  • we can also use workspace as a variable inside of resources and locals
locals {
  container_count = length(lookup(var.ext_port, terraform.workspace))
}

resource "docker_container" "nginx_container" {
  count = local.container_count
  name  = join("-", ["nginx", terraform.workspace, random_string.random[count.index].result])
  image = docker_image.nginx_image.latest
  ports {
    internal = var.int_port
    external = lookup(var.ext_port, terraform.workspace)[count.index]
  }
  volumes {
    container_path = "/data"
    host_path      = "${path.cwd}/nginxvol"
  }
}
terraform workspace new dev # create a new called dev workspace and switch to it.

terraform workspace show #show the current working workspace

terraform workspace list # list all workspace

terraform select workspace dev # switch the dev ws.

Terraform Modules

Terraform Graph

  • shows our infra with graph
sudo apt install graphviz # install graph program

terraform graph | dot -Tpdf > graph-plan.pdf # we can save our graph in a pdf file

terraform graph -type=plan=destroy | dot -Tpdf > graph-destroy.pdf # we just create a destroy graph

Flatten Function

Flatten

  • show seperated list values into a one list.
output "IP-Address" {
  value       = flatten(module.container[*].ip-address)
  description = "IP address of container."
}

Lifecycle on Terraform

Lifecycle

resource "docker_volume" "container_volume" {
  name = "${var.name_in}-volume"
  lifecycle {
    prevent_destroy = true
  }
}
terraform destroy -target=module.container[0].docker_container.nginx_container #destroy just specific resource

Terraform for_each parameter

for each

locals {
  deployment = {
    nginx = {
      image = var.image["nginx"][terraform.workspace]
    }
    influxdb = {
      image = var.image["influxdb"][terraform.workspace]
    }
  }
}

module "image" {
  source   = "./image"
  for_each = local.deployment
  image_in = each.value.image
}

cidrsubnet Function

cidrsubnet function

public_cidrs = [for i in range(2, 255, 2): cidrsubnet("10.123.0.0/16", 8, i)]
private_cidrs = [for i in range(1, 255, 2): cidrsubnet("10.123.0.0/16", 8, i)]

Dynamic Content

resource "aws_security_group" "mustafa_sg" {
  for_each    = var.security_groups
  name        = each.value.name
  description = each.value.description
  vpc_id      = aws_vpc.mustafa_vpc.id
  dynamic "ingress" {
    for_each = each.value.ingress
    content {
      from_port   = ingress.value.from
      to_port     = ingress.value.to
      protocol    = ingress.value.protocol
      cidr_blocks = ingress.value.cidr_blocks
    }
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published