반복문과 조건문을 같이 사용하는 CASE
테라폼에서 사용할 수 있는 조건문의 구성은 아래와 같습니다.
- count parameter : 조건부 리소스에서 사용
- for_each, for expressions : 리소스 내의 조건부 리소스 및 인라인 블록에서 사용
- if string directive(문자열 지시어) : 문자열 내 조건문에 사용
count + if
모듈의 오토스케일링 사용 여부를 특정 환경에 따라 조건부로 지정해야하는 경우
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# modules/services/webserver-cluster/variables.tf
variable "enable_autoscaling" {
description = "If set to true, enable auto scaling"
type = bool
}
# stage/services/webserver-cluster/main.tf
module "webserver_cluster" {
source = "../../../modules/services/webserver-cluster"
env = "stage"
instance_type = "t2.micro"
min_size = 1
max_size = 1
enable_autoscaling = false
}
# modules/services/webserver-cluster/main.tf
resource "aws_autoscaling_schedule" "scale_out_during_business_hours" {
count = var.enable_autoscaling ? 1 : 0
scheduled_action_name = "scale-out-during-business-hours"
min_size = 2
max_size = 2
desired_capacity = 2
recurrence = "0 9 * * *"
autoscaling_group_name = module.webserver_cluster.asg_name
}
resource "aws_autoscaling_schedule" "scale_in_at_night" {
count = var.enable_autoscaling ? 1 : 0
scheduled_action_name = "scale-in-at-night"
min_size = 0
max_size = 2
desired_capacity = 0
recurrence = "0 18 * * *"
autoscaling_group_name = module.webserver_cluster.asg_name
}
- 입력 변수 enable_autoscaling의 값이 1(True)인 경우, 1번 반복하므로 리소스가 각각 한개씩 생성됩니다.
- 입력 변수 enable_autoscaling의 값이 0(False)인 경우, 반복하지 않으므로 리소스가 생성되지 않습니다.
count + if-else
IAM User 생성 시 특정 AWS 서비스 Full Access 적용 여부를 결정해야 하는 경우
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
variable "give_cloudwatch_full_access" {
description = "If true, gets full access to CloudWatch"
type = bool
}
resource "aws_iam_user_policy_attachment" "cloudwatch_full_access" {
count = var.give_cloudwatch_full_access ? 1 : 0
user = aws_iam_user.example[0].name
policy_arn = aws_iam_policy.cloudwatch_full_access.arn
}
resource "aws_iam_user_policy_attachment" "cloudwatch_read_only" {
count = var.give_cloudwatch_full_access ? 0 : 1
user = aws_iam_user.example[0].name
policy_arn = aws_iam_policy.cloudwatch_read_only.arn
}
- resource에서 생성되는 출력 값(속성)들은 참조할 수 없는 단점이 존재합니다.
for_each, for expresstion + if
1
2
3
4
5
6
7
8
9
dynamic "tag" {
for_each = { for key, value in var.custom_tags: key => upper(value) if key != "Name" }
content {
key = tag.key
value = tag.value
propagate_at_launch = true
}
}
- 리소스를 조건부로 생성할 때는 count 를 사용할 수 있지만, 그 외 모든 유형의 반복문 또는 조건문에는 for_each 를 사용합니다.
- 리소스의 복사본을 여러 개 만들 때는 count 보다 for_each 를 사용
- 조건 논리의 경우 비어 있지 않은 컬렉션에 for_each 를 설정하는 것보다 count 를 0 또는 1로 설정하는 것이 간단
string directive + if
1
2
3
4
%{ if <CONDITION> }<TRUEVAL>%{ endif }
#else
%{ if <CONDITION> }<TRUEVAL>%{ else }<FALSEVAL>%{ endif }
- CONDITION은 boolean 으로 평가되는 표현식이고, TRUEVAL은 CONDITION이 True로 평가되면 렌더링할 표현식입니다.
사용 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
variable "users" {
description = "users to render"
type = list(string)
default = ["aaa", "bbb", "ccc"]
}
output "for_directive" {
value = "%{ for name in var.users }\${name}, %{ endfor }"
}
output "for_directive_index" {
value = "%{ for i, name in var.users }(\${i}) \${name}, %{ endfor }"
}
output "for_directive_index_if" {
value = %{ for i, name in var.users }${name}%{ if i < length(var.users) - 1 }, %{ endif }%{ endfor }
}
output "for_directive_index_if_strip" {
value = <<EOF
%{~ for i, name in var.names ~}
\${name}%{ if i < length(var.names) - 1 }, %{ endif }
%{~ endfor ~}
EOF
}
output "for_directive_index_if_else_strip" {
value = <<EOF
%{~ for i, name in var.names ~}
\${name}%{ if i < length(var.names) - 1 }, %{ else }.%{ endif }
%{~ endfor ~}
EOF
}
# output
Outputs:
for_directive_index_if = <<EOT
gasida,
akbun,
fullmoon
EOT
for_directive_index_if_strip = " aaa, bbb, ccc"
for_directive_index_if_else_strip = " aaa, bbb, ccc."
- 줄 바꿈, 스페이스 같은 공백을 없애기 위해 문자열 지시자의 앞이나 뒤에 물결표(~)를 사용할 수 있습니다.
- else를 활용하여 출력 마지막에 .를 찍어보기
참고
- Terraform DocsㅣFunction
- Terraform DocsㅣExpressions
- 가시다님 스터디 자료
- 악분님 Youtube