IaC/Infrastructure Provisioning

4. Terraform의 다양한 Function(함수)

Somaz 2023. 4. 11. 20:00
728x90
반응형

Overview

2023.04.04 - [Hashicorp] - 1. Terraform 기초 : 설치 및 .tf 파일 설명

2023.04.06 - [Hashicorp] - 2. Terraform 변수 사용법(use-variable)

2023.04.10 - [Hashicorp] - 3. Terraform 다양한 변수(variable, local, data...output, input)

 

오늘은 테라폼의 다양한 Function에 대해 공부해보려고 한다.

 

Terraform Functions

 


1. coalesce(Collection Function)

coalesce임의 개수의 인수를 취하고 null 또는 빈 문자열이 아닌 첫 번째 인수를 반환한다.

 


 

 

Syntax

> coalesce("a", "b")
a
> coalesce("", "b")
b
> coalesce(1,2)
1

 

 


 

Practice .tf code

 

 

variable.tf

variable "environment" {
  description = "The environment for the infrastructure (e.g., development, staging, production)"
  type        = string
  default     = "dev" # Optional: Provide a default value if desired
}

variable "project" {
  description = "This resource means that it was created with terraform (e.g., development, staging, production)"
  type        = string
  default     = "project1" # Optional: Provide a default value if desired
}

 

main.tf

locals {
  company = "somaz"
  database_subnet_group_name = coalesce(
    var.database_subnet_group_name,
    format(
      "%s-%s-%s-rds-subnets-group",
      var. company,
      var. environment,
      var. project,
    )
  )
}
...
database_subnet_group_name             = local.database_subnet_group_name

 

 

Result

# 1. terraform.tvars에 파일이 정의되있는 경우

## terraform.tvars
database_subnet_group_name = somaz-rds-subnets-group

## result = somaz-rds-subnets-group

# 2. terraform.tvars에 파일이 정의되있지 않는 경우

## result = somaz-dev-project1-rds-subnets-group
  • var.database_subnet_group_name이 terraform.tfvars 파일에 이미 정의된 경우 coalesce 함수는 var.database_subnet_group_name의 값을 반환한다. 
  • terraform.tvars 파일에 var.database_subnet_group_name가 정의되어 있지않다면 "somaz-dev-project1-rds-subnets-group"을 반환한다.
  • 지난시간에 배웠지만 저렇게 local변수로 지정하면, 아래의 local.database_subnet_group_name으로 사용할 수 있다.

 

 


 

2.  merge(Collection Functions)

임의의 수의 map 또는 object를 취하고 모든 인수에서 병합된 요소 집합을 포함하는 single map 또는 object를 반환한다.

둘 이상의 지정된 맵 또는 객체가 동일한 키 또는 속성을 정의하는 경우 인수 시퀀스에서 나중에 있는 것이 우선한다.

 


Syntax

 

> merge({a="b", c="d"}, {e="f", c="z"})
{
  "a" = "b"
  "c" = "z"
  "e" = "f"
}

> merge({a="b"}, {a=[1,2], c="z"}, {d=3})
{
  "a" = [
    1,
    2,
  ]
  "c" = "z"
  "d" = 3
}

 


 

Practice .tf code

 

 

variable.tf

variable "environment" {
  description = "The environment for the infrastructure (e.g., development, staging, production)"
  type        = string
  default     = "dev" # Optional: Provide a default value if desired
}

variable "project" {
  description = "This resource means that it was created with terraform (e.g., development, staging, production)"
  type        = string
  default     = "project1" # Optional: Provide a default value if desired
}

variable "terraform" {
  description = "This resource means that it was created with terraform (e.g., development, staging, production)"
  type        = string
  default     = "true" # Optional: Provide a default value if desired
}

 

main.tf

locals {
  company = "somaz"
  
  default_tags = {
    Terraform   = var.terraform
    Environment = var.environment
  }
  
  database_subnet_group_tags = merge(
    local.default_tags,
    {
      Name = format(
        "%s-%s-%s-rds-subnets-group",
        var.company,
        var.environment,
        var.project,
      )
    }
  )
}

 

Result

따라서 결과 database_subnet_group_tags map은 아래와 같습니다.

{
  "Terraform": true,
  "Environment": "dev",
  "Name": "somaz-dev-project1-rds-subnets-group"
}
  • map(or object): 와 같이 명명된 레이블로 식별되는 값 그룹이다 {name = "Mabel", age = 52}.
  • map은 key = value 값으로 되어있고 Terraform의 type 중 하나이다.

 


 

3.  substr(String Functions) / length(Collection Functions)

 

 

substr

주어진 문자열에서 오프셋 및 (최대) 길이로 하위 문자열을 추출한다.

substr(string, offset, length)

 

 

length

주어진 목록, 맵 또는 문자열의 길이를 결정한다.

list나 map이 제공되면 결과는 해당 컬렉션의 요소 수이다. 문자열이 주어지면 결과는 문자열의 문자 수이다.

 


Syntax

 

 

substr

> substr("hello world", 1, 4)
ello

> substr("🤔🤷", 0, 1)
🤔

> substr("hello world", -5, -1)
world

 

 

length

> length([])
0
> length(["a", "b"])
2
> length({"a" = "b"})
1
> length("hello")
5

> length("👾🕹️")
2

 


 

Practice .tf code

아래의 코드는 지난번 변수파트에서 설명했던 코드이다.

2023.04.10 - [Hashicorp] - 3. Terraform 다양한 변수(variable, local, data...output, input)

 

 

variable.tf

variable "image_id" {
  type        = string
  description = "The id of the machine image (AMI) to use for the server."

  validation {
    condition     = length(var.image_id) > 4 && substr(var.image_id, 0, 4) == "ami-"
    error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"."
  }
}
  • image id를 확인하여 문자열 길이가 4개이상이고 substr function으로 4번째 문자열까지 검사하여 결과가 "ami-" 가 맞는지 확인하는 validation이다.

 

Result

먼저 validation은 해당 블록 내에 블록을 추가하여 특정 변수에 대한 사용자 지정 유효성 검사 규칙을 만들 수 있다.

condition은 유효성 검사를 통과하려면 true로 평가되어야 하는 bool 표현식이다.

length function을 보면 var.image_id의 길이는 4보다 커야한다. 그리고 substr function으로 0번째 문자열부터 4개를 검사하여 image id가 "ami-"로 확인한 후 true면 유효성 검사가 통과되는 것이고 false면 error_message가 나오는 조건문이다.


4. format(String Functions)

format 함수는 사양 문자열에 따라 여러 다른 값의 형식을 지정하여 문자열을 생성한다. printfC의 함수 및 다른 프로그래밍 언어의 다른 유사한 함수와 유사하다.

format(spec, values...)

 


Syntax

 

> format("Hello, %s!", "Ander")
Hello, Ander!
> format("There are %d lights", 4)
There are 4 lights

 


Practice .tf code

 

variable.tf

variable "environment" {
  description = "The environment for the infrastructure (e.g., development, staging, production)"
  type        = string
  default     = "dev" # Optional: Provide a default value if desired
}

variable "project" {
  description = "This resource means that it was created with terraform (e.g., development, staging, production)"
  type        = string
  default     = "project1" # Optional: Provide a default value if desired
}

variable "company" {
  description = "This resource means that it was created with terraform (e.g., development, staging, production)"
  type        = string
  default     = "somaz" # Optional: Provide a default value if desired
}

 

 

main.tf

resource "aws_eip" "this" {
  instance = aws_instance.this.id
  vpc      = true
  tags = {
    Name = format(
      "%s-%s-%s-eip-bastion",
      var.company,
      var.environment,
      var.project,
    )
  }
}

 

Result

반복되는 문자열을 variable.tf 파일에 지정하여 변수로 지정한 후 반복사용이 용이하게 만들어준다.

{
  "Name": "somaz-dev-project1-eip-bastion"
}

5. lookup(Collection Functions) / element(Collection Functions) 

 

lookup

lookup주어진 키로 맵에서 단일 요소의 값을 검색합니다. 주어진 키가 존재하지 않으면 주어진 기본값이 대신 반환된다.

lookup(map, key, default)

 

element

element목록에서 단일 요소를 검색한다. 인덱스는 0부터 시작한다. 이 함수는 빈 목록과 함께 사용하면 오류를 생성한다. 인덱스는 음수가 아닌 정수여야 한다.

element(list, index)

 

 


Syntax

 

 

lookup

> lookup({a="ay", b="bee"}, "a", "what?")
ay
> lookup({a="ay", b="bee"}, "c", "what?")
what?

 

element

> element(["a", "b", "c"], 1)
b

> element(["a", "b", "c"], 3)
a

> element(["a", "b", "c"], length(["a", "b", "c"])-1)
c

 


Practice .tf code

 

variable.tf

variable "origin" {
  description = "One or more origins for this distribution (multiples allowed)."
  type        = any
  default     = null
}

variable "origin_group" {
  description = "One or more origin_group for this distribution (multiples allowed)."
  type        = any
  default     = {}
}
  • Terraform에서 'any' 유형은 변수가 string, number, bool, list, map, object, 등과 같은 모든 유형의 값을 허용할 수 있는 특수 유형 제약 조건이다.

 

main.tf

  dynamic "origin" {
    for_each = var.origin

    content {
      domain_name         = origin.value.domain_name
      origin_id           = lookup(origin.value, "origin_id", origin.key)
      origin_path         = lookup(origin.value, "origin_path", "")
      origin_path         = element(var.origin_paths, index(var.origin, origin.key)) # Use the element function here
      connection_attempts = lookup(origin.value, "connection_attempts", null)
      connection_timeout  = lookup(origin.value, "connection_timeout", null)

      dynamic "s3_origin_config" {
        for_each = length(keys(lookup(origin.value, "s3_origin_config", {}))) == 0 ? [] : [lookup(origin.value, "s3_origin_config", {})]

        content {
          origin_access_identity = lookup(s3_origin_config.value, "cloudfront_access_identity_path", lookup(lookup(aws_cloudfront_origin_access_identity.this, lookup(s3_origin_config.value, "origin_access_identity", ""), {}), "cloudfront_access_identity_path", null))
        }
      }
    }
  }

 

  • for_each = var.origin : 변수 자체가 list 또는 map 이 될 것으로 예상한다.
  • for_each = [var.origin] : 변수 자체가 list가 아니더라도 for_each 루프의 입력이 항상 list가 된다.
  • index(list, value)list 내에서 주어진 value가 처음 나타나는 인덱스(0 기반)를 반환하는 Terraform 함수이다.

 

Result

 

먼저 origin_path에는 동적 "origin" 블록의 for_each 루프에 있는 현재 인덱스를 기반으로 var.origin_paths list의 값이 할당이 된다. element 함수는 지정된 인덱스의 목록에서 값을 가져오는 데 사용된다.

 

블록은 오리진 구성의 list 또는 map이 될 것으로 예상되는 var.origin 변수를 반복한다.

dynamic "origin" 블록 내에서 다음 속성을 사용하여 var.origin  list 또는 map의 각 항목에 대해 중첩된 "Content" 블록이 생성된다.

  • domain_name: origin.value 객체에서 domain_name 속성을 직접 설정한다.
  • origin_id: 조회 기능을 사용하여 "origin_id" 속성 값을 검색한다. 찾을 수 없으면 origin.key가 기본값으로 사용된다.
  • origin_path: 조회 기능을 사용하여 "origin_path" 속성에 대한 값을 검색한다. 찾을 수 없으면 빈 문자열이 기본값으로 사용된다.
  • connection_attempts: 조회 기능을 사용하여 "connection_attempts" 속성 값을 검색한다. 찾을 수 없는 경우 기본값은 null로 설정된다.
  • connection_timeout: 조회 기능을 사용하여 "connection_timeout" 속성에 대한 값을 검색한다. 찾을 수 없는 경우 기본값은 null로 설정된다.

 

"content" 블록 내부에는 for_each 루프가 있는 중첩된 동적 "s3_origin_config" 블록이 있다. 루프는 조건식을 기반으로 생성된 목록을 반복한다.

  • 현재 origin.value 개체의 "s3_origin_config" 속성에 있는 키 길이가 0인 경우 빈 목록 []이 사용된다.
  • 그렇지 않으면 조회 기능을 사용하여 "s3_origin_config" 개체를 포함하는 단일 요소가 있는 목록이 생성된다.

 

이 조건식은 "s3_origin_config" 속성이 정의되어 있는지 여부를 확인한다. 정의된 경우 for_each 루프가 한 번 반복되어 단일 "s3_origin_config" 블록을 생성한다. 정의되지 않은 경우 루프가 반복되지 않고 "s3_origin_config" 블록이 생성되지 않는다.

 

동적 "s3_origin_config" 블록 내에서 중첩된 "content" 블록이 다음 속성으로 생성된다.

 

origin_access_identity: 조회 기능을 사용하여 "cloudfront_access_identity_path" 속성에 대한 값을 검색한다. 찾을 수 없는 경우 "s3_origin_config" 객체에서 "origin_access_identity" 속성을 조회한 다음 "aws_cloudfront_origin_access_identity.this" 객체에서 조회를 시도한다. 그래도 찾을 수 없으면 기본값은 null로 설정됩니다.

 

요약하자면 이 코드는 var.origin list 또는 map의 각 항목에 대해 "origin" 블록을 생성하여 변수에 지정된 값에 따라 속성을 구성한다. 또한 특정 오리진에 대해 "s3_origin_config" 속성이 정의된 경우 해당 오리진 액세스 ID 구성으로 중첩된 "s3_origin_config" 블록이 생성된다

 

 

Dynamic 블록 / Content 블록

간단히 Dynamic 블록에 대해 설명하자면, dynamic 블록은 'dynamic' 키워드, 블록 유형 이름 및 "Content"라는 중첩된 구성 블록을 사용하여 정의된다. dynamic 블록 내에서 일반적으로 for_each 루프를 사용하여 list 또는 map 반복하여 각 요소에 대한 중첩 블록을 생성한다.

Content 블록은 Dynamic 블록과 함께 사용되어 list 또는 map 변수를 기반으로 여러 중첩 블록을 생성한다.

 


6. index(Collection Functions)

 

index목록에서 주어진 값에 대한 요소 인덱스를 찾는다.

index(list, value)
  • 반환된 인덱스는 0부터 시작한다. 이 함수는 주어진 값이 목록에 없으면 오류를 생성한다.

Syntax

 

> index(["a", "b", "c"], "b")
1

Reference

 

terraform function 공식사이트

 

terraform value and type

 

 

 

 

728x90
반응형