1. 반복문
for_each 기본
Terraform의 for_each는 선언된 key 값 개수만큼 리소스를 생성하는 반복문입니다.
- each object는 key, value 2개의 속성을 가지고 있습니다.
- for_each는 모든 타입에 대해 each object로 접근할 수 없고 map, set타입만 허용합니다.
- map, set타입이 아닌 expression은 map 또는 set으로 타입변환(toset 등)을 해야 합니다.
- count와 비교했을 때, for_each는 항목 추가나 삭제 시 다른 리소스에 영향을 미치지 않는다는 장점이 있습니다.
예시: 기본 사용법
이 예시에서는 names 변수 목록의 각 항목에 대해 로컬파일을 생성합니다.
# 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"
}
# 확인
terraform apply -auto-approve
terraform state list
terraform state show 'local_file.abc["a"]'
terraform state show 'local_file.def["a"]'
ls *.txt
abc-a.txt abc-b.txt abc-c.txt def-a.txt def-b.txt def-c.txt
for_each 데이터 유형
- 기본 유형
- string : 글자 유형
- number : 숫자 유형
- bool : true 또는 false
- any : 명시적으로 모든 유형이 허용됨을 표시
- 집합 유형
- list [<유형>]: 인덱스 기반 집합
- map (<유형>): 값 = 속성 기반 집합이며 키값 기준 정렬
- set (<유형>): 값 기반 집합이며 정렬 키값 기준 정렬
- object ({<인수 이름>=<유형>, …})
- tuple ([<유형>, …])
list와 set은 선언하는 형태가 비슷하지만 참조 방식이 인덱스와 키로 각각 차이가 있고, map와 set의 경우 선언된 값이 정렬되는 특징을 가진다.
다양한 데이터 유형 실습
main.tf 파일 작성
variable "string_a" {
default = "myString"
}
variable "string_b" {
type = string
default = "myString"
}
# variable "string_c" {
# type = string
# default = myString
# }
variable "number_a" {
default = 123
}
variable "number_b" {
type = number
default = 123
}
variable "number_c" {
default = "123"
}
variable "boolean" {
default = true
}
# (Array) list , set , tuple - value , [ ] 사용
variable "list_set_tuple_a" {
default = ["aaa", "bbb", "ccc"]
}
variable "list_set_tuple_b" {
type = list(string)
default = ["bbb", "ccc", "aaa"]
}
variable "list_set_tuple_c" {
type = set(string)
default = ["bbb", "ccc", "aaa"]
}
variable "list_set_tuple_d" {
default = ["aaa", 1, false]
}
variable "list_set_tuple_e" {
type = tuple([string, number, bool])
default = ["aaa", 1, false]
}
# (Object) map , object - key : value , { } 사용
variable "map_object_a" {
default = {"a" : "aaa", "b" : "bbb" , "c" : "ccc"}
}
variable "map_object_b" {
type = map(string)
default = {"b" : "bbb" , "c" : "ccc", "a" : "aaa"}
}
variable "map_object_c" {
default = {"name" : "gasida", "age" : 27 }
}
variable "map_object_d" {
type = object({ name = string, age = number })
default = {"name" : "gasida", "age" : 27 }
}
실행 및 확인
terraform console 통해 결과를 확인합니다.
#
terraform plan
#
terraform console
-----------------
# 기본
type(12)
type("12")
type(a)
type("a")
type(true)
type("true")
# string
var.string_a
var.string_b
type(var.string_a)
type(var.string_b)
# number
var.number_a
var.number_b
var.number_c
type(var.number_a)
type(var.number_b)
type(var.number_c)
# boolean
var.boolean
type(var.boolean)
# list , set , tuple - 'value'
var.list_set_tuple_a
var.list_set_tuple_b
var.list_set_tuple_c
var.list_set_tuple_d
var.list_set_tuple_e
type(var.list_set_tuple_a)
type(var.list_set_tuple_b)
type(var.list_set_tuple_c)
type(var.list_set_tuple_d)
type(var.list_set_tuple_e)
var.list_set_tuple_a[0]
type(var.list_set_tuple_a[0])
var.list_set_tuple_b[0]
type(var.list_set_tuple_b[0])
var.list_set_tuple_d[0]
var.list_set_tuple_d[1]
var.list_set_tuple_d[2]
type(var.list_set_tuple_d[0])
type(var.list_set_tuple_d[1])
type(var.list_set_tuple_d[2])
var.list_set_tuple_e[0]
type(var.list_set_tuple_e[0])
# map , object - 'key : value'
var.map_object_a
var.map_object_b
var.map_object_c
var.map_object_d
type(var.map_object_a)
type(var.map_object_b)
type(var.map_object_c)
type(var.map_object_d)
var.map_object_a["a"]
type(var.map_object_a["a"])
var.map_object_b["a"]
type(var.map_object_b["a"])
var.map_object_c["name"]
type(var.map_object_c["name"])
var.map_object_d["age"]
type(var.map_object_d["age"])
# tuple > list > set
type(["a","b"])
type(tolist(["a","b"]))
type(toset(["a","b"]))
# object > map
type({a="a", b="b"})
type({a="a", b=1})
type(tomap({a="a", b="b"}))
type(tomap({a="a", b=1}))
exit
-----------------
for Expressions
for_each와 다르게, 반복해서 변환 작업에 사용할 수 있습니다(복합 형식 값의 형태를 변환).
예를 들어 list 값의 포맷을 변경하거나 특정 접두사 prefix를 추가할 수도 있고, output에 원하는 형태로 반복적인 결과를 표현할 수 도 있다
- list 타입의 경우 값 또는 인덱스와 값을 반환
- map 타입의 경우 키 또는 키와 값에 대해 반환
- set 타입의 경우 키 값에 대해 반환
main.tf 작성
list의 내용을 담는 리소스를 생성하고, var.name의 내용이 결과 파일에 content로 기록됩니다.
variable "names" {
default = ["a", "b", "c"]
}
resource "local_file" "abc" {
content = jsonencode(var.names) # 결과 : ["a", "b", "c"]
filename = "${path.module}/abc.txt"
}
output "file_content" {
value = local_file.abc.content
}
실행 및 확인
json형태로 변환된 내용의 로컬파일을 확인할 수 있습니다.
terraform apply -auto-approve
terraform state list
terraform output --raw file_content | jq
ls *.txt
cat abc.txt ;echo
# 참고 jsonencode Function
terraform console
-----------------
var.names
type(var.names)
jsonencode(var.names)
jsonencode({"hello"="world"})
dynamic
count 나 for_each 구문을 사용한 리소스 전체를 여러 개 생성하는 것 이외도 리소스 내에 선언되는 구성 블록을 다중으로 작성해야 하는 경우가 있습니다. 이때, dynamic 블록은 리소스 내 부 속성블록을 동적인 블록으로 생성할 수 있습니다.
main.tf 파일 작성
archive_file에 source 블록 선언을 반복을 dynamic 블록을 통해 동적으로 블록을 생성하여 코드를 최소화합니다.
# 일반적인 블록 사용
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"
}
}
# 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"
}
}
}
2. 조건문(Conditional Expressions)
Terraform의 조건문은 인프라 구성을 동적으로 제어할 수 있도록 하는 강력한 도구입니다. 조건문을 사용하면 변수의 값에 따라 리소스를 생성하거나 설정을 변경할 수 있습니다. Terraform에서 조건문은 주로 삼항 연산자(ternary operator)를 통해 사용됩니다.
삼항 연산자 (Ternary Operator)
Terraform의 삼항 연산자는 다음과 아래 형식으로 사용됩니다. 조건이 참일 때 true_value를 반환하고, 거짓일 때 false_value를 반환합니다.
# <조건 정의> ? <옳은 경우> : <틀린 경우>
condition ? true_value : false_value
조건식의 비교 대상의 형태가 다를 경우에는 테라폼 실행 시, 추론하여 자동으로 변환하지만 명시적인 형태 작성을 권장합니다.
# 조건식 형태 권장 사항
var.example ? 12 : "hello" # 비권장
var.example ? "12" : "hello" # 권장
var.example ? tostring(12) : "hello" # 권장
조건문 활용
- 조건식은 특정 속성 정의, 로컬 변수 재정의, 출력 값 조건 설정 외에도 리소스 생성 여부를 제어하는 데 사용할 수 있습니다
- 조건식을 count와 결합하면 특정 조건에 따라 리소스 생성 여부를 결정할 수 있습니다.
main.tf 작성
variable "enable_file" {
default = true
}
resource "local_file" "foo" {
count = var.enable_file ? 1 : 0
content = "foo!"
filename = "${path.module}/foo.bar"
}
output "content" {
value = var.enable_file ? local_file.foo[0].content : ""
}
실행 및 확인
- TF_VAR 변수를 활용할 수 있습니다.
- count에 조건식을 결합한 경우 다음과 같이 특정 조건에 따라 리소스 생성 여부를 선택할 수 있습니다.
# 변수 우선순위3 : 환경 변수 (TF_VAR 변수 이름)
export TF_VAR_enable_file=false
export | grep TF_VAR_enable_file
#
terraform init && terraform plan && terraform apply -auto-approve
terraform state list
echo "var.enable_file ? 1 : 0" | terraform console
0
# 환경 변수 삭제
unset TF_VAR_enable_file
export | grep TF_VAR_enable_file
# 재실행
terraform plan && terraform apply -auto-approve
terraform state list
#
echo "local_file.foo[0]" | terraform console
echo "local_file.foo[0].content" | terraform console
echo "var.enable_file ? 1 : 0" | terraform console
1
3. 함수(Function)
Terraform에는 다양한 내장 함수가 있어, 인프라 코드 작성 시 다양한 작업을 수행할 수 있습니다. 이들 함수는 문자열 조작, 컬렉션 조작, 숫자 연산, 날짜 및 시간 처리, 파일 읽기, 리소스 참조 등 다양한 용도로 사용됩니다. 하지만, 내장된 함수 외에는 사용자가 구현하는 별도의 사용자 정의 함수를 지원하지는 않습니다.
문자열 함수
terraform console을 통해서 함수 결과를 확인합니다.
- upper(): 문자열을 소문자를 대문자로 변환합니다.
- format(): 문자열을 지정된 형식으로 포맷합니다.
- join(): 문자열 목록을 특정 구분자로 결합합니다.
> upper("foo!")
"FOO!"
> format("Hello, %s!", "Terraform")
"Hello, Terraform!"
> join(", ", ["a", "b", "c"])
"a, b, c"
컬렉션 함수
- length(): 목록이나 맵의 길이를 반환합니다.
- merge(): 여러 맵을 하나로 병합합니다.
> length(["a", "b", "c"])
3
> merge({a = 1, b = 2}, {c = 3, d = 4})
{
"a" = 1
"b" = 2
"c" = 3
"d" = 4
}
숫자함수
- max(): 주어진 숫자 중 가장 큰 값을 반환합니다.
- min(): 주어진 숫자 중 가장 작은 값을 반환합니다.
> max(1, 2, 3)
3
> min(1, 2, 3)
1
날짜 및 시간 함수
- timestamp(): 현재 시간을 ISO 8601 형식으로 반환합니다
- timeadd(): 주어진 시간에 특정 기간을 더합니다
> timestamp()
"2024-06-29T11:39:19Z"
> timeadd(timestamp(), "30m")
"2024-06-29T12:09:21Z"
파일함수
- file(): 파일의 내용을 읽어 문자열로 반환합니다
- fileexists(): 파일의 존재 여부를 반환합니다
> file("${path.module}/example.txt")
""
> fileexists("${path.module}/example.txt")
true
네트워크 함수
- cidrnetmask() : 주어진 IP 대역의 넷마스크를 반환합니다.
- cidrsubnet(): 주어진 IP 대역의 서브넷 마스크를 반환합니다.
> cidrnetmask("172.16.0.0/12")
"255.240.0.0"
> cidrsubnet("1.1.1.0/24", 1, 0)
"1.1.1.0/25"
4. 프로비저너
Terraform의 프로비 저 너(Provisioner)는 리소스를 생성한 후 초기 설정이나 배포 작업을 수행하는 데 사용됩니다. 주로 서버 구성이나 초기화 작업에 사용되며, Terraform의 리소스 블록 내에서 정의할 수 있습니다. 프로비저너는 로컬 및 원격에서 스크립트를 실행하거나 파일을 복사하는 등 다양한 작업을 수행할 수 있습니다.
프로비저너는 상태를 변경하지 않습니다. 리소스 생성 후 수행되는 작업은 Terraform 상태 파일에 반영되지 않습니다. 즉 프로비저너는 선언적(Declarative) 상태를 보장하지 않을 수 있으므로, 사용을 최소화하는 것을 추천하고, 복잡한 구성 작업이나 배포 작업에는 Terraform 프로비저너 대신 Ansible, Chef, Puppet 등의 오케스트레이션 도구를 사용하는 것이 좋습니다.
프로비저너의 종류는 다음과 같습니다.
- local-exec 프로비저너
- remote-exec 프로비저너
- file 프로비저너
local-exec 프로비저너
- 로컬 머신에서 명령을 실행합니다.
- Terraform을 실행하는 머신에서 스크립트나 명령을 실행할 때 사용됩니다.
main.tf 작성
- command의 << 연산자를 통해 다중 라인의 명령을 수행하여 각 환경에 맞는 인터프리터를 지정해 해당 명령을 수행합니다.
- command(필수) : 실행할 명령줄을 입력하며 << 연산자를 통해 여러 줄의 커맨드 입력 가능
- working_dir(선택) : command의 명령을 실행할 디렉터리를 지정해야 하고 상대/절대 경로로 설정
- interpreter(선택) : 명령을 실행하는 데 필요한 인터프리터를 지정하며, 첫 번째 인수로 인터프리터 이름이고 두 번째부터는 인터프리터 인수 값
- environment(선택) : 실행 시 환경 변수는 실행 환경의 값을 상속받으면, 추가 또는 재할당하려는 경우 해당 인수에 key = value 형태로 설정
# Unix/Linux/Mac
resource "null_resource" "example1" {
provisioner "local-exec" {
command = <<EOF
echo Hello!! > file.txt
echo $ENV >> file.txt
EOF
interpreter = [ "bash" , "-c" ]
working_dir = "/tmp"
environment = {
ENV = "world!!"
}
}
}
# Window
resource "null_resource" "example1" {
provisioner "local-exec" {
command = <<EOF
Hello!! > file.txt
Get-ChildItem Env:ENV >> file.txt
EOF
interpreter = [ "PowerShell" , "-Command" ]
working_dir = "C:\\windows\temp"
environment = {
ENV = "world!!"
}
}
}
remote-exec 프로비저너
- 원격 머신에서 명령을 실행합니다.
- SSH나 WinRM을 통해 원격 서버에 접속하여 명령을 실행합니다.
resource "aws_instance" "example" {
ami = "ami-12345678"
instance_type = "t2.micro"
connection {
type = "ssh"
user = "ubuntu"
private_key = file("~/.ssh/id_rsa")
host = self.public_ip
}
provisioner "remote-exec" {
inline = [
"sudo apt-get update",
"sudo apt-get install -y nginx"
]
}
}
file 프로비저너
- 로컬 머신에서 원격 머신으로 파일을 복사합니다.
main.tf 작성
- source : 소스 파일 또는 디렉터리로, 현재 작업 중인 디렉터리에 대한 상태 경로 또는 절대 경로로 지정할 수 있다. content와 함께 사용할 수 없습니다.
- content : 연결 대상에 복사할 내용을 정의하며 대상이 디렉터리인 경우 tf-file-content 파일이 생성되고, 파일인 경우 해당 파일에 내용이 기록된다. source와 함께 사용할 수 없습니다.
- destination : 필수 항목으로 항상 절대 경로로 지정되어야 하며, 파일 또는 디렉터리입니다.
resource "aws_instance" "example" {
ami = "ami-12345678"
instance_type = "t2.micro"
connection {
type = "ssh"
user = "ubuntu"
private_key = file("~/.ssh/id_rsa")
host = self.public_ip
}
provisioner "file" {
source = "index.html"
destination = "/tmp/index.html"
}
}
5. null_resource와 terraform_data
테라폼 1.4 버전이 릴리즈 되면서 기존 null_resource 리소스를 대체하는 terraform_data 리소스가 추가되었습니다.
( 하지만, 아직까지도 null_resource가 종종 사용됨 )
null_resource
null_resource는 실제 리소스를 생성하지 않지만, 트리거(trigger)를 설정하여 특정 작업을 수행할 수 있도록 하는 리소스입니다. 특정 조건이 만족될 때 명령을 실행하거나 스크립트를 수행할 수 있습니다. 주로 프로비 저 너와 함께 사용되거나 프로비저닝 수행 과정에서 명령어 실행으로 많이 활용됩니다.
main.tf 작성
- AWS EC2 인스턴스를 프로비저닝 하면서 웹서비스를 실행시키기 위한 코드입니다.
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_security_group" "instance" {
name = "t101sg"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "example" {
ami = "ami-0c9c942bd7bf113a2"
instance_type = "t2.micro"
subnet_id = "subnet-dbc571b0" # 각자 default VPC에 subnet ID 아무거나
private_ip = "172.31.1.100"
vpc_security_group_ids = [aws_security_group.instance.id]
user_data = <<-EOF
#!/bin/bash
echo "Hello, T101 Study" > index.html
nohup busybox httpd -f -p 80 &
EOF
tags = {
Name = "Single-WebSrv"
}
provisioner "remote-exec" {
inline = [
"echo ${aws_eip.myeip.public_ip}"
]
}
}
resource "aws_eip" "myeip" {
#vpc = true
instance = aws_instance.example.id
associate_with_private_ip = "172.31.1.100"
}
output "public_ip" {
value = aws_instance.example.public_ip
description = "The public IP of the Instance"
}
실행 및 결과를 확인해 보면, 다음과 같은 오류가 발생하고 아래 속성 값들이 필요함을 알 수 있습니다.
- aws_eip가 생성되는 고정된 IP를 할당하기 위해서는 대상인 aws_instance의 id값이 필요합니다.
- aws_instance의 프로비 저 너 동작에서는 aws_eip가 생성하는 속성 값인 public_ip가 필요합니다.
main.tf 파일 수정
- 실제 리소스와는 무관한 동작을 수행하기 위해 null_resource를 활용합니다.
- public_ip가 프로비저닝 될 수 있도록 실행에 간격을 추가합니다.
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_security_group" "instance" {
name = "t101sg"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "example" {
ami = "ami-0c9c942bd7bf113a2"
instance_type = "t2.micro"
subnet_id = "subnet-dbc571b0"
private_ip = "172.31.0.100"
key_name = "kp-gasida" # 각자 자신의 EC2 SSH Keypair 이름 지정
vpc_security_group_ids = [aws_security_group.instance.id]
user_data = <<-EOF
#!/bin/bash
echo "Hello, T101 Study" > index.html
nohup busybox httpd -f -p 80 &
EOF
tags = {
Name = "Single-WebSrv"
}
}
resource "aws_eip" "myeip" {
#vpc = true
instance = aws_instance.example.id
associate_with_private_ip = "172.31.0.100"
}
resource "null_resource" "echomyeip" {
provisioner "remote-exec" {
connection {
host = aws_eip.myeip.public_ip
type = "ssh"
user = "ubuntu"
private_key = file("/Users/gasida/.ssh/kp-gasida.pem") # 각자 자신의 EC2 SSH Keypair 파일 위치 지정
#password = "qwe123"
}
inline = [
"echo ${aws_eip.myeip.public_ip}"
]
}
}
output "public_ip" {
value = aws_instance.example.public_ip
description = "The public IP of the Instance"
}
output "eip" {
value = aws_eip.myeip.public_ip
description = "The EIP of the Instance"
}
terraform_data
이 리소스 또한 자체적으로 아무것도 수행하지 않지만 null_resource는 별도의 프로바이더 구성이 필요하다는 점과 비교하여 추가 프로바이더 없이 테라폼 자체에 포함된 기본 수명주기 관리자가 제공된다는 것이 장점입니다.
main.tf 작성
- null_resource와 동일한 코드 예시입니다.
- 강제 재실행을 위한 trigger_replace와 상태 저장을 위한 input 인수와 input에 저장된 값을 출력하는 output 속성이 제공됩니다.
- triggers_replace에 정의되는 값이 기존 map 형태에서 tuple로 변경되어 쓰임이 더 간단합니다.
# terraform_data
resource "aws_instance" "web" {
# ...
}
resource "aws_instance" "database" {
# ...
}
# A use-case for terraform_data is as a do-nothing container
# for arbitrary actions taken by a provisioner.
resource "terraform_data" "bootstrap" {
triggers_replace = [
aws_instance.web.id,
aws_instance.database.id
]
provisioner "local-exec" {
command = "bootstrap-hosts.sh"
}
}
# trigger_replace
resource "terraform_data" "foo" {
triggers_replace = [
aws_instance.foo.id,
aws_instance.bar.id
]
input = "world"
}
output "terraform_data_output" {
value = terraform_data.foo.output # 출력 결과는 "world"
}
6. moved 블록
테라폼은 State에(terraform.tfstate) 기록되는 리소스 주소의 이름이 변경되면 기존 리소스는 삭제되고 새로운 리소스가 생성됩니다.
Terraform의 moved 블록은 리소스나 모듈을 변경할 때 사용되는 블록입니다. 예를 들어 리소스의 이름이 변경되지만 이미 프로비저닝 된 환경을 그대로 유지하고자 하는 경우에 사용할 수 있습니다.
아래와 같이 이름을 변경해야 하는 상황에 주로 사용됩니다.
- 리소스 이름을 변경
- count로 처리하던 반복문을 for_each로 변경
- 리소스가 모듈로 이동하여 참조되는 주소가 변경
main.tf 작성
foo!라는 내용의 로컬 파일을 만드는 테라폼 코드를 실행시키고 terraform.tfstate 파일을 확인합니다.
# main.tf
resource "local_file" "a" {
content = "foo!"
filename = "${path.module}/foo.bar"
}
output "file_content" {
value = local_file.a.content
}
# 실행 및 확인
terraform init && terraform plan && terraform apply -auto-approve
cat foo.bar ; echo
#
terraform state list
echo "local_file.a" | terraform console
echo "local_file.a.id" | terraform console
"4bf3e335199107182c6f7638efaad377acc7f452"
이때, local_file 이름을 a-> b로 변경하고 terraform plan 명령어로 다시 확인해 보면, 기존 리소스를 제거하고 새로운 리소스를 생성하려는 것을 볼 수 있습니다.
# 로컬파일 이름 수정: a -> b
resource "local_file" "b" {
content = "foo!"
filename = "${path.module}/foo.bar"
}
output "file_content" {
value = local_file.b.content
}
# 확인
terraform plan
Terraform will perform the following actions:
# local_file.a will be destroyed
# (because local_file.a is not in configuration)
- resource "local_file" "a" {
- content = "foo!" -> null
- content_base64sha256 = "wOCqrqBQvPO+JsDCPVj6iQwN+3nIojAWtKhs0oym6nE=" -> null
- content_base64sha512 = "TSCmPxazw2YStHurNILfRykjK/J4evgArH/2KnQuzQZodz4cq1f/ig2GeQO7mBI+Qx5jkTQEZxLCGs3mPtsB3Q==" -> null
- content_md5 = "35af8b7a9490467f75f19c1e5459f7e7" -> null
- content_sha1 = "4bf3e335199107182c6f7638efaad377acc7f452" -> null
- content_sha256 = "c0e0aaaea050bcf3be26c0c23d58fa890c0dfb79c8a23016b4a86cd28ca6ea71" -> null
- content_sha512 = "4d20a63f16b3c36612b47bab3482df4729232bf2787af800ac7ff62a742ecd0668773e1cab57ff8a0d867903bb98123e431e639134046712c21acde63edb01dd" -> null
- directory_permission = "0777" -> null
- file_permission = "0777" -> null
- filename = "./foo.bar" -> null
- id = "4bf3e335199107182c6f7638efaad377acc7f452" -> null
}
main.tf 파일 수정
local_file.a의 프로비저닝 결과를 유지한 채 이름을 변경하기 위해 moved 블록을 활용합니다.
# main.tf
resource "local_file" "b" {
content = "foo!"
filename = "${path.module}/foo.bar"
}
moved {
from = local_file.a
to = local_file.b
}
output "file_content" {
value = local_file.b.content
}
# 확인
terraform plan
local_file.b: Refreshing state... [id=4bf3e335199107182c6f7638efaad377acc7f452]
Terraform will perform the following actions:
# local_file.a has moved to local_file.b
resource "local_file" "b" {
id = "4bf3e335199107182c6f7638efaad377acc7f452"
# (10 unchanged attributes hidden)
}
Plan: 0 to add, 0 to change, 0 to destroy.
'Automation > Terraform' 카테고리의 다른 글
테라폼으로 AWS EKS 배포 - T101 7주차 (0) | 2024.07.27 |
---|---|
Terraform Module & Runner - T101 5주차 (2) | 2024.07.14 |
Terraform Provider & State - T101 4주차 (0) | 2024.07.06 |
Terraform 기본사용 2 - T101 2주차 (0) | 2024.06.23 |
Terraform 기본사용 1 - T101 1주차 (0) | 2024.06.16 |