728x90
의도
[테라폼으로 시작하는 IaC] 책의 246페이지 실습에 대한 내용이다.
한 가지 변수 값만 다른 instance를 반복문을 사용해 3개 생성해야 한다.
모듈을 쓰자니 너무 복잡하고 count를 쓰자니 instance 참조 방식을 인덱스로 하는게 맘에 안 들어서 for_each를 택했다.
# aws_instance.hashicat["kitten"] will be created
+ resource "aws_instance" "hashicat" {
이런 식으로 aws_instance.hashicat["kitten"] 형태로 참조하고 싶었다.
count를 사용하면 aws_instance.hashicat[0] 의 형태로 참조해야 한다.
결과
코드
locals {
map_placeholder = {
"kitten" = "placekitten.com",
"bear" = "placebear.com",
"dog" = "placedog.net"
}
}
resource "aws_instance" "hashicat" {
for_each = local.map_placeholder
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
key_name = aws_key_pair.hashicat.key_name
associate_public_ip_address = true
subnet_id = aws_subnet.hashicat.id
vpc_security_group_ids = [aws_security_group.hashicat.id]
tags = {
Name = "${var.prefix}-hashicat-instance"
}
}
resource "null_resource" "configure-cat-app" {
for_each = local.map_placeholder
provisioner "file" {
source = "files/"
destination = "/home/ubuntu/"
connection {
type = "ssh"
user = "ubuntu"
private_key = tls_private_key.hashicat.private_key_pem
host = aws_instance.hashicat[each.key].public_ip
}
}
provisioner "remote-exec" {
inline = [
"sudo apt -y update",
"sleep 15",
"sudo apt -y update",
"sudo apt -y install apache2",
"sudo systemctl start apache2",
"sudo chown -R ubuntu:ubuntu /var/www/html",
"chmod +x *.sh",
"PLACEHOLDER=${each.value} WIDTH=${var.width} HEIGHT=${var.height} PREFIX=${var.prefix} ./deploy_app.sh",
"sudo apt -y install cowsay",
"cowsay Mooooooooooo!",
]
connection {
type = "ssh"
user = "ubuntu"
private_key = tls_private_key.hashicat.private_key_pem
host = aws_instance.hashicat[each.key].public_ip
}
}
}
- locals 생성
- aws_instance, null_resource에
for_each = local.map_placeholder
추가 - remote-exec의
PLACEHOLDER=${each.value}
로 변경 - connection에서
host=aws_instance.hashicat[each.key].public_ip
로 변경
output "catapp_url" {
value = {for k, v in local.map_placeholder: k => aws_instance.hashicat["${k}"].public_dns}
}
output "catapp_ip" {
value = {for k, v in local.map_placeholder: k => aws_instance.hashicat["${k}"].public_ip}
}
- output에서 value에 for사용 ⇒ output에서 for_each, count.index 사용이 불가하기 때문
- local에서 키 값을 불러와 인스턴스를 하나씩 불러오고자 함
어려웠던 점
output "catapp_url" {
# value = {for k in local.map_placeholder: k => aws_instance.hashicat["${k}"].public_dns}
# value = {for k in local.map_placeholder: k => k}
# value = {for k, v in local.map_placeholder: k => v}
value = {for k, v in local.map_placeholder: k => aws_sinstance.hashicat["${k}"].public_dns}
# value = "http://${aws_instance.hashicat[each.key].public_dns}"
}
- output에서 인스턴스의 값을 불러오기 위한 과정이 어려웠음
- for_each, count.index는 사용이 안 되어 local.map_placeholder의 키를 사용해 값을 불러오고자 함
처음에 for k in local.map_placeholder를 사용하였는데, 이때 주어진 키로 해당 배열의 값을 찾을 수 없다는 오류가 발생함
# value = {for k in local.map_placeholder: k => aws_instance.hashicat["${k}"].public_dns}
│ Error: Invalid index
│
│ on outputs.tf line 2, in output "catapp_url":
│ 2: value = {for k in local.map_placeholder: k => aws_instance.hashicat["${k}"].public_dns}
│ ├────────────────
│ │ aws_instance.hashicat is object with 3 attributes
│
│ The given key does not identify an element in this collection value.
k의 값을 확인해봄
# value = {for k in local.map_placeholder: k => k}
Changes to Outputs:
+ catapp_url = {
+ "placebear.com" = "placebear.com"
+ "placedog.net" = "placedog.net"
+ "placekitten.com" = "placekitten.com"
}
- k의 값이 key가 아니라 value의 값을 불러오고 있음을 확인함
입력 값을 두 개(k, v)로 사용할 때의 값을 확인해봄
# value = {for k, v in local.map_placeholder: k => v}
Changes to Outputs:
+ catapp_url = {
+ bear = "placebear.com"
+ dog = "placedog.net"
+ kitten = "placekitten.com"
}
- 원하는 대로 key와 value를 불러오게 됨
입력 값을 두 개로 주어 코드를 작성함
# value = {for k, v in local.map_placeholder: k => aws_sinstance.hashicat["${k}"].public_dns}
- 알게된 점 ⇒ for 구문 동작 시에 map 형태에서 입력 값을 한 개로 두면 value만 불러옴
- docs 찾아보니 list, map 형태 상관 없이 입력받는 값이 한 개일 경우 무조건 value를 반환한다고 되어 있음. 책이 틀림(p.126 map 유형의 경우~)
-
https://developer.hashicorp.com/terraform/language/expressions/for#input-typesThe index or key symbol is always optional. If you specify only a single symbol after the for keyword then that symbol will always represent the value of each element of the input collection. 인덱스 또는 키 기호는 항상 선택적입니다. for 키워드 뒤에 단일 기호만 지정하면 해당 기호는 항상 입력 모음의 각 요소의 값을 나타냅니다.
728x90