DDetB.Log
article thumbnail
이 포스팅은 CloudNet@ 팀이 진행하는 테라폼 기초 입문 스터디에 참여하며 ‘테라폼으로 시작하는 IaC’ 책을 기준하여 정리한 글입니다.

Local Values

코드 내에서 사용자가 지정한 값 또는 속성 값을 가공해 참조 가능한 local (지역 값)은 외부에서 입력되지 않고, 코드 내에서만 가공되어 동작하는 값을 선언

main.tf

variable "prefix" {
  default = "hello"
}

locals {
  name    = "terraform"
  content = "${var.prefix} ${local.name}"
  my_info = {
    age    = 20
    region = "KR"
  }
  my_nums = [1, 2, 3, 4, 5]
}

실행 및 확인

$ terraform init && terraform plan && terraform apply -auto-approve

$ terraform console
> local.content
"hello terraform"
> local.my_info.age
20

=> 로컬은 한번만 선언 가능하며, 중복 선언하면 오류 발생

Output Values

Output은 주로 테라폼 코드의 프로비저닝 수행 후의 결과 속성 값을 확인하는 용도로 사용

main.tf

resource "local_file" "abc" {
  content  = "abc123"
  filename = "${path.module}/abc.txt"
}

output "file_id" {
  value = local_file.abc.id
}

output "file_abspath" {
  value = abspath(local_file.abc.filename)
}

[참고] abspath(): 파일 시스템 경로를 포함하는 문자열을 가져와 절대 경로로 변환하는 함수

실행 및 확인

$ terraform init && terraform plan
...
  + create

Terraform will perform the following actions:

  # local_file.abc will be created
  + resource "local_file" "abc" {
      + content              = "abc123"
      + content_base64sha256 = (known after apply)
      + content_base64sha512 = (known after apply)
      + content_md5          = (known after apply)
      + content_sha1         = (known after apply)
      + content_sha256       = (known after apply)
      + content_sha512       = (known after apply)
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "./abc.txt"
      + id                   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + file_abspath = "/home/aiden/terraform_study/week02/workspaces/3.8/abc.txt"
  + file_id      = (known after apply)

=> plan 실행 시, 이미 정해진 속성 값은 출력하지만 apply 시점에 정해지는 값들은 출력 되지 않음

반복문

terraform 공식 문서에는 반복문으로 구분되어있지 않고, meta-argument 중 하나로 구분되어 있음. list 형태의 값 목록이나 Key-Value 형태의 문자열 집합인 데이터가 있는 경우, 아래의 반복문을 활용하여 수동으로 반복적 선언할 필요 없음.

  • count
  • for_each
  • for
  • dynamic

count

count에서 생성되는 참조값은 count.index이며, 반복하는 경우 0부터 1씩 증가해 인덱스가 부여

main.tf

resource "local_file" "abc" {
  count    = 5
  content  = "abc"
  filename = "${path.module}/abc.txt"
}

output "filecontent" {
  value = local_file.abc.*.content
}

output "fileid" {
  value = local_file.abc.*.id
}

output "filename" {
  value = local_file.abc.*.filename
}

실행 및 확인

$ terraform init && terraform apply -auto-approve
...

$ terraform state list
local_file.abc[0]
local_file.abc[1]
local_file.abc[2]
local_file.abc[3]
local_file.abc[4]

$ ls *.txt
abc.txt

$ terraform output
filecontent = [
  "abc",
  "abc",
  "abc",
  "abc",
  "abc",
]
fileid = [
  "a9993e364706816aba3e25717850c26c9cd0d89d",
  "a9993e364706816aba3e25717850c26c9cd0d89d",
  "a9993e364706816aba3e25717850c26c9cd0d89d",
  "a9993e364706816aba3e25717850c26c9cd0d89d",
  "a9993e364706816aba3e25717850c26c9cd0d89d",
]
filename = [
  "./abc.txt",
  "./abc.txt",
  "./abc.txt",
  "./abc.txt",
  "./abc.txt",
]

=> 동일한 파일명을 생성하므로 결과적으로 하나의 파일만 존재

=> terraform console을 통해 local_file.abc[0] ~ local_file.abc[4] 의 속성을 확인 가능

main.tf 수정

resource "local_file" "abc" {
  count    = 5
  content  = "abc${count.index}"
  filename = "${path.module}/abc${count.index}.txt"
}

output "fileid" {
  value = local_file.abc.*.id
}

output "filename" {
  value = local_file.abc.*.filename
}

output "filecontent" {
  value = local_file.abc.*.content
}

실행 및 확인

$ terraform apply -auto-approve
...

$ terraform state list
local_file.abc[0]
local_file.abc[1]
local_file.abc[2]
local_file.abc[3]
local_file.abc[4]

$ ls *.txt
abc0.txt  abc1.txt  abc2.txt  abc3.txt  abc4.txt
[주의] 외부 변수가 list 타입인 경우 중간에 값이 삭제되면 인덱스가 줄어들어 의도했던 중간 값에 대한 리소스만 삭제되는 것이 아니라 이후의 정의된 리소스들도 삭제되고 재생성됨

for_each

리소스 또는 모듈 블록에서 for_each에 입력된 데이터 형태가 map 또는 set이면, 선언된 key 값 개수만큼 리소스를 생성

main.tf

resource "local_file" "abc" {
  for_each = {
    a = "content a"
    b = "content b"
  }
  content  = each.value
  filename = "${path.module}/${each.key}.txt"
}

실행 및 확인

$ terraform apply -auto-approve
...

$ terraform state list
local_file.abc["a"]
local_file.abc["b"]

$ cat a.txt; echo
content a

$ cat b.txt; echo
content b

main.tf 수정

variable "names" {
  default = {
    a = "content a"
    b = "content b"
    c = "content c"
  }
}

resource "local_file" "abc" {
  for_each = var.names
  content  = each.value
  filename = "${path.module}/abc-${each.key}.txt"
}

resource "local_file" "def" {
  for_each = local_file.abc
  content  = each.value.content
  filename = "${path.module}/def-${each.key}.txt"
}

실행 및 확인

$ terraform apply -auto-approve
...

$ ls *.txt
abc-a.txt  abc-b.txt  abc-c.txt  def-a.txt  def-b.txt  def-c.txt

=> key 값은 count의 index와는 달리 고유하므로 중간에 값을 삭제한 후 다시 적용해도 해당 값에 대해서만 리소스를 삭제

for

복합 형식 값의 형태를 변환하는 데 사용하며 for_each와 다름. list 값의 포맷을 변경하거나 특정 접두사 prefix를 추가하는 등의 동작 가능.

main.tf

variable "names" {
  default = ["a", "b", "c"]
}

resource "local_file" "abc" {
  content  = jsonencode(var.names) # 결과 : ["a", "b", "c"]
  filename = "${path.module}/abc.txt"
}

실행 및 확인

$ terraform apply -auto-approve
...

$ cat abc.txt ;echo
["a","b","c"]

main.tf 수정

variable "names" {
  default = ["a", "b", "c"]
}

resource "local_file" "abc" {
  content  = jsonencode([for s in var.names : upper(s)]) # 결과 : ["A", "B", "C"]
  filename = "${path.module}/abc.txt"
}

실행 및 확인

$ terraform apply -auto-approve
...

$ cat abc.txt ;echo
["A","B","C"]

=> names의 값들을 이터레이팅 하면서 upper 함수를 적용 후 리턴하는 형태

dynamic

dynamic 자체로 반복문은 아니며 블록의 한 종류. 리소스의 내부 속성 요소 중 반복이 필요한 경우, dynamic 블록으로 표현되는 부분만 동적인 블록으로 생성할 수 있음.

data "archive_file" "dotfiles" {
  type        = "zip"
  output_path = "${path.module}/dotfiles.zip"

  source {
    content  = "hello a"
    filename = "${path.module}/a.txt"
  }

  source {
    content  = "hello b"
    filename = "${path.module}/b.txt"
  }

  source {
    content  = "hello c"
    filename = "${path.module}/c.txt"
  }
}

위의 설정 파일을 dynamic 블록을 적용하여 작성 가능.

main.tf

variable "names" {
  default = {
    a = "hello a"
    b = "hello b"
    c = "hello c"
  }
}

data "archive_file" "dotfiles" {
  type        = "zip"
  output_path = "${path.module}/dotfiles.zip"

  dynamic "source" {
    for_each = var.names
    content {
      content  = source.value
      filename = "${path.module}/${source.key}.txt"
    }
  }
}

실행 및 확인

$ terraform apply -auto-approve
...

$ ls *.zip
dotfiles.zip

$ unzip dotfiles.zip
Archive:  dotfiles.zip
  inflating: a.txt                   
  inflating: b.txt                   
  inflating: c.txt

=> dynamic 블록을 통해 동일한 설정이 가능함을 확인

profile

DDetB.Log

@DDetMok

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!