IT/Terraform

[Terraform] slice 사용하여 리스트의 startindex, endindex값 가져오기

반응형

Intro

테라폼 코딩을 하면서 count나 for_each로 여러개의 리소스를 생성하는 경우가 있습니다. 이 리소스는 output으로 출력할때 list가 됩니다. 리스트 값을 특정 범위에 있는 리스트만 가져올 수 있는 방법이 바로 slice function입니다.

python에서는 list의 값을 list[0:3] 이런식으로 리스트의 범위를 잡아줄 수 있기 때문에 당연히(?) 리스트의 인덱스 범위를 지정할 수 있을 줄 알았는데, python과 같이 범위설정이 되지 않았으며 이것도 안돼나? 싶어서 list[0-3] 이렇게 해도 먹히지 않았습니다.

앞서 설명드린 것과 같이 이 경우 slice 를 사용해야합니다.

slice 는?

리스트의 값들을 연속적인 값으로 추출할 수 있는 function 입니다.

slice(list, startindex, endindex)

아래 예시를 보면 알 수 있듯이 startindex 는 수학기호로 < 이며 endindex는 입니다.

> slice(["a", "b", "c", "d"], 1, 3)
[
  "b",
  "c",
]

slice 활용하기

리스트로 만들어지는 resource를 output으로 나누기

  • resource.tf
locals {
    private_app_subnet = slice(aws_subnet.private,0,2)
    private_mgmt_subnet = slice(aws_subnet.private,2,6)
    private_db_subnet = slice(aws_subnet.private,6,8)
}

resource "aws_subnet" "private" {
  count = length(var.private_cidr)

  vpc_id                          = data.terraform_remote_state.vpc.outputs.vpc_id
  cidr_block                      = element(var.private_cidr, count.index)
  availability_zone               = element(var.vpc_private_azs, count.index)
..... 생략
}
  • ouptputs.tf

위 로컬 변수에서 나누어놓은 값을 아래 outputs 의 value로 설정

outputs "private_app_subnet_id" {
    value = local.private_app_subnet.*.id
}

outputs "private_mgmt_subnet_id" {
    value = local.private_mgmt_subnet.*.id
}

outputs "private_db_subnet_id" {
    value = local.private_db_subnet.*.id
}

위에서 정의한 ouptut을 다른 리소스에서 remote state Data 로 사용 하기

  • data.tf

위에서 정의한 output값을 사용하기위해 terraform_remote_state로 private_subnet 상태값을 가져옵니다.

data "terraform_remote_state" "private_subnet" {
    backend = "s3"
    config = {
        bucket = var.remote_state_bucket_name
        key = "network/subnet/terraform.tfstate"
        region = var.region
  }   
}

data로 정의한 private_subnet 상태값에 있는 outputs 중에 필요한 서브넷만 지정할 수가 있게 되었습니다.

data.terraform_remote_state.private.outputs.private_app_subnet_id
data.terraform_remote_state.private.outputs.private_mgmt_subnet_id
data.terraform_remote_state.private.outputs.private_db_subnet_id

결론

테라폼은 java, python, golang등등 과 다르게 cofiguration Language이기 때문에 데이터를 다루는데 매우 복잡한 방법을 사용해야합니다.

그래서 필연적으로 코드가 매우 복잡해질 수 밖에 없는것 같습니다. 이는 terroform 모듈을 보면 알 수 있는데요. 그 예를 들어보자면 EKS모듈에서 아래와 같은 구문이 있습니다.

and , or 그리고 삼항연산자로 특정 조건이 맞는 값을 가져오는 부분입니다. 이 많은 and, or 때문에 학부때 디지털 논리회로 시간에 배운 부울대수를 다시 들여다 봐야했습니다.

int_linux_default_user_data = var.create && var.platform == "linux" && (var.enable_bootstrap_user_data
|| var.user_data_template_path != "") ? base64encode(templatefile(coalesce(var.user_data_template_path, "${path.module}/../../templates/linux_user_data.tpl"),.... 생략

HCL(hashcorp cofiguration Language) 언어의 제한적인 데이터처리 방법과 기능 때문에 예외처리를 하기 위해서 이렇게 복잡해질 수 밖에 없게 됩니다.

모든 코드는 간단하고 명료 해야한다고 생각합니다. java의 clean code가 있듯이 HCL에도 당연히 clean code가 필요하다고 생각합니다. 따라서 HCL(hashcorp cofiguration Language) 언어를 사용할때 모듈 사용을 최소화하고 너무 많은 예외 처리를 하려고 하지 않는것이 HCL에서 clean code 시작이 아닌가 생각을 해보면서 글을 마치도록 하겠습니다.

반응형