Ssoon

Chapter (03) 기본 사용법 - HCL - 반복문 본문

Terraform 101 Study 2기

Chapter (03) 기본 사용법 - HCL - 반복문

구구달스 2023. 7. 10. 23:38
CloudNet@ 가시다님이 진행하는 Terraform 101 Study 2기
"테라폼으로 시작하는 IaC" (한빛미디어) 도서로 진행!

✅ 반복문

  • list 형태의 값 목록, key-value 형태의 문자열 집항인 데이터가 있는 경우 -> 동일 내용에 대해 반복문을 사용

🧿 count

  • ResourceModulecount 값이 정수인 인수 포함 -> 선언된 정수 값만큼 ResourceModule 을 생성
  • 생성되는 참조값은 count.index 이며, 0부터 1씩 증가해 index 가 부여됩니다.

main.tf

resource "local_file" "abc" {
  count = 5
  content = "abc"
  filename = "${path.module}/abc.txt"
}
  • 다섯 개의 파일이 생성되어야 하지만 파일명이 동일하기 때문에 하나의 파일만 존재합니다.

 main.tf - count.index 값을 추가

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

 main.tf - list 형태의 배열 활용

variable "names" {
  type = list(string)
  default = ["a","b","c"]
}

resource "local_file" "abc" {
  count = length(var.names)
  content = "abc"
  filename = "${path.module}/abc-${var.names[count.index]}.txt"
}

  • 리소스 값 참조
    • 리소스 : <리소스 타입>.<이름>.[<인덱스 번호>] 
    • 모듈 : module.<모듈 이름>[<인덱스 번호>]

🧿 for_each

  • resource 또는 module 블록에서 for_each 에 입력된 데이터 형태가 map 또는 set -> 선언된 key 값 개수만큼 생성

 main.tf

  • each.key : 인스턴스에 해당하는 map 타입의 key 값
  • each.value : 인스턴스에 해당하는 map 의 value 값
  • 리소스 값 참조
    • 리소스 : <리소스 타입>.<이름>.[<key>] 
    • 모듈 : module.<모듈 이름>[<key>]
resource "local_file" "abc" {
  for_each = {
    a = "content a"
    b = "content b"
  }
  content = each.value
  filename = ${path.module}/${each.key}.txt"
}

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

 main.tf - b = "content b" 삭제

variable "names" {
  default = {
    a = "content a"
    c = "content c"
  } 
}
  • b = "content b" 가 삭제됩니다.

🧿 for

  • 복합 형식 값의 형태를 변환하는 데 사용됩니다.
    • list 타입 : value 또는 index와 value을 변환
    • map 타입 : key 또는 key와 value에 대해 반환
    • set 타입 : key value에 대해 반환

 main.tf 

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

resource "local_file" "abc" {
  content = jsonencode(var.names)
  filename = "${path.module}/abc.txt"
}

 main.tf - for 구문으로 동적 변경한 입력 변수 값

resource "local_file" "abc" {
  content = jsonencode([for s in var.names: upper(s)])
  filename = "${path.module}/abc.txt"
}

for 구문 사용규칙

  • list 유형
    • 반환 받는 값이 하나 -> value / 두개 -> 앞의 인수가 index (i)를 반환하고 뒤의 인수가 value (v)을 반환
  • map 유형
    • 반환 받는 값이 하나 -> key / 두개 -> 앞의 인수가 key (k)를 반환하고 뒤의 인수가 value (v)을 반환
  • 결과 값은 for문을 묶는 기호가 [ ] 인 경우 tuple로 반환, { } 인 경우 object로 반환
  • object 형태 -> key 와 value 에 대한 쌍은 => 기호로 구분
  • { } 형식 사용해 object 형태로 결과 반환 -> key 값은 고유 -> 값 뒤에 그룹화 모드 심볼(...) 를 붙혀서 key 중복 방지
  • if 구문을 추가해 조건 부여 가능

 main.tf - for 구문 규칙 검증

variable "names" {
  type = list(string)
  default = ["a","b"] 
}
output "A_upper_value" {
  value = [for v in var.names: upper(v)]
}
output "B_index_and_value" {
  value = [for i,v in var.names: "${i} is ${v}"]
}
output "C_make_object" {
  value = {for v in var.names: v => upper(v)}
}
output "D_with_filter" {
  value = [for v in var.names: upper(v) if v != "a"]
}

 main.tf - map 유형의 for 구문 규칙 검증

variable "members" {
  type = map(object({
    role = string 
  }))
  default = {
    ab = { role = "member", group = "dev" }
    cd = { role = "admin", group = "dev" }
    ef = { role = "member", group = "ops" }
  }
}

output "A_to_tuple" {
  value = [for k, v in var.members: "${k} is ${v.role}"]
}

output "B_get_only_role" {
  value = {
    for name, user in var.members: name => user.role
    if user.role == "admin"
  }
}

output "C_group" {
  value = {
    for name, user in var.members: user.role => name...
  }
}

🧿 dynamic

  • resource 내에 선언되는 구성 블록을 다중으로 작성되는 경우
    • (ex) AWS Security Group 리소스 구성에 ingress, egress 요소가 resource 내부에서 여러 번 정의되는 경우

 main.tf - 일반적인 블록 속성 반복 적용

resource "provider_resource" "name" {
  name = "some_resource"

  some_setting {
    key = a_value
  }
  some_setting {
    key = b_value
  }
  some_setting {
    key = c_value
  }
  some_setting {
    key = d_value
  }
}
  • 기존 블록의 속성 이름 -> dynamic 블록의 이름으로 선언
  • 기존 블록 속성에 정의되는 내용을 content 블록에 작성
  • 반복문 구문은  for_each 를 사용 -> dynamic 에 지전ㅇ된 이름에 대해 속성 부여

 main.tf - dynamic 블록 적용

resource "provider_resource" "name" {
  name = "some_resource"

  dynamic "some_setting" {
    for_each = {
      a_key = a_value
      b_key = b_value
      c_key = c_value
      d_key = d_value
    }
    content {
      key = some_setting.value
    }
  }
}

 main.tf - resource 내에 반복적으로 선언되는 구성 블록

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

 main.tf - resource 내에 반복적으로 선언되는 구성을 dynamic 블록으로 재구성

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"
    }
  }
}
  • dynamic 블록으로 선언하고 다시 apply을 실행하면 동일한 내용으로 변경사항이 없습니다.

Comments