3장 기본 사용법 (1)

김진원·2023년 7월 5일

IaC

목록 보기
3/10

"테라폼으로 시작하는 IaC"책을 기준으로 1주차 정리 내용입니다.


3.1 주요 커맨드


주요 커맨드를 익히기 위해 아래의 간단한 실습 코드를 활용하여 알아보자.
resource = "local_file" "abc" {
content = "abc!"
filename = "${path.module}/abc.txt"
}

📄1. help

보조 명령에 대해 더 알아보기 위해서 서브커맨드와 함께 입력한다.

terraform console -help
terraform plan -help
terraform apply -help

📄2. init

테라폼 구성 파일이 있는 작업 디렉토리를 초기화한다. 작업을 실행하는 디렉토리를 루트 모듈이라 부릅니다. 또한, 테라폼 시작의 첫 번째 명령어로 필수적으로 요청되는 명령어 입니다.

아래 예시는 init을 입력할 시 나오는 문구들입니다.

/mnt/c/Users/User/Desktop/T201/workspaces/03.start$ terraform init

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/local from the dependency lock file
- Using previously-installed hashicorp/local v2.4.0

Terraform has been successfully initialized!
...생략...

# -upgrade

0.14 버전 이후부터 프로바이더 종속성을 고정시키는 .terraform.lock.hcl이 추가되었
는데, 지속적인 업그레이드로 각 모듈이 변경될 가능성으로 인해 명시된 버전으로 init을
수행하기에 다른 버전을 사용하려면 terraform init -upgrade를 수행합니다.

📄3. plan & apply

  • "plan"은 테라폼으로 적용할 인프라의 변경 사항에 관한 실행 계획을 생성하는 동작이다.
    변경 사항을 실제로 적용하진 않으며, 적용 전에 예상한 구성이 맞는지 검토 하는 데 이용한다.

  • "apply"은 계획을 기반으로 작업을 실행한다.


💻Plan

/mnt/c/Users/Pro/Desktop/T201/workspaces/03.start$ terraform plan

Terraform used the selected providers to generate the following execution plan. 
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # local_file.abc will be created
  + resource "local_file" "abc" {
      + content              = "abc!"
      + content_base64sha256 = (known after apply)
      + content_base64sha512 = (known after apply)
      + content_md5          = (known after apply)
      + content_sha1         = (known after apply)
      + content_sha256       = (known after apply)
      + content_sha512       = (known after apply)
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "./abc.txt"
      + id                   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

위의 코드는 plan을 실행한 결과로 1개의 리소스가 추가되고 변경과 삭제는 없다고 알려줍니다.

또한, 구성 내용을 바탕으로 어떤 리소스가 생성되는지 상세 내역을 보여줍니다. 필수 요소인 content와 filename만 선언했지만, 다른 옵션과 기본값이 자동으로 적용된 것을 볼 수 있습니다.

  • -detailed-exitcode
    동작의 결과를 숫자 코드로 제공하는데, 자동화 설계할 때 활용합니다.

    0 : 변경 사항이 없는 성공
    1 : 오류가 있음
    2 : 변경 사항이 있는 성공


💻 apply

이번에는 apply를 실행합니다.

/mnt/c/Users/Pro/Desktop/T201/workspaces/03.start$ terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # local_file.abc will be created
  + resource "local_file" "abc" {
      + content              = "abc!"
      + content_base64sha256 = (known after apply)
      + content_base64sha512 = (known after apply)
      + content_md5          = (known after apply)
      + content_sha1         = (known after apply)
      + content_sha256       = (known after apply)
      + content_sha512       = (known after apply)
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "./abc.txt"
      + id                   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:    

plan 명령과 같은 동작 계획을 보여준 후에 적용 여부를 묻는데, yes가 아니면 모두 취소하는 것으로 간주한다.

실행 계획 파일을 별도로 작성하여 다른 이름의 계획을 가지고 동작시킬 수도 있다. 명령어는 -out="임의"를 추가한다.

/mnt/c/Users/Pro/Desktop/T201/workspaces/03.start$ terraform plan -out=tfplan
...
Saved the plan to: tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "tfplan"

생성된 파일은 terraform apply tfplan으로 실행할 수 있다.

  • -replace
    특정 리소스를 다시 생성해야 하는 경우 대상을 삭제 후 생성하는 실행 계획이 발생합니다.
    plan, apply 모두 적용 가능하며, 여러 번도 가능합니다.

📄 4. destroy

테라폼 구성에서 관리하는 모든 개체를 제거하는 명령어입니다.

/mnt/c/Users/Pro/Desktop/T201/workspaces/03.start$ terraform destroy
local_file.abc: Refreshing state... [id=5678fb68a642f3c6c8004c1bdc21e7142087287b]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # local_file.abc will be destroyed
  - resource "local_file" "abc" {
      - content              = "abc!" -> null
      - content_base64sha256 = "U+Dv8yBGJvPiVspjZXLXzN+OtaGQyd76P6VnvGOGa3Y=" -> null
      - content_base64sha512 = "J873Ugx5HyDEnYsjdX8iMBjn4I3gft82udsl3lNeWEoqwmNE3mvUZNNz4QRqQ3iaT5SW1y9p3e1Xn2txEBapKg==" -> null
      - content_md5          = "4edb03f55c86d5e0a76f5627fa506bbf" -> null
      - content_sha1         = "5678fb68a642f3c6c8004c1bdc21e7142087287b" -> null
      - content_sha256       = "53e0eff3204626f3e256ca636572d7ccdf8eb5a190c9defa3fa567bc63866b76" -> null
      - content_sha512       = "27cef7520c791f20c49d8b23757f223018e7e08de07edf36b9db25de535e584a2ac26344de6bd464d373e1046a43789a4f9496d72f69dded579f6b711016a92a" -> null
      - directory_permission = "0777" -> null
      - file_permission      = "0777" -> null
      - filename             = "./abc.txt" -> null
      - id                   = "5678fb68a642f3c6c8004c1bdc21e7142087287b" -> null
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

local_file.abc: Destroying... [id=5678fb68a642f3c6c8004c1bdc21e7142087287b]
local_file.abc: Destruction complete after 0s

Destroy complete! Resources: 1 destroyed.

해당 명령어는 모든 개체를 제거하는 명령어이며, 만약 일부분 리소스를 제거하려면 삭제하려는 항목을 코드에서 제거한다. 삭제할 여부도 묻기에 yes가 아니면 적용되지 않으며, plan을 같이 사용하여 삭제 계획을 출력할 수 있다.

  • -auto-approve
    자동 승인 기능을 부여하는 옵션으로 apply, destroy 작업 시에 계획을 예상할 수 있어 승인 절차 없이 실행할 때 사용한다.


3.2 HCL

HCL (HashiCorp configuration language)은 하시코프사에서 IaC와 구성 정보를 명시하기 위해 개발된 오픈 소스 도구이다.

  • 소스 코드는 GitHub URL에서 확인이 가능하다.
  • IaC는 수동 프로세스가 아닌 코드를 통해 인프라를 관리하고 프로비저닝 하는 것을 말합니다.
  • 테라폼에서 HCL이 코드의 영역을 담당한다. HCL은 쉽게 읽을 수 있고 빠르게 배울 수 있는 언어의 특징을 가진다.
  • 인프라가 코드로 표현되고, 이 코드는 곧 인프라이기 때문에 선언적 특성을 갖게 되고 튜링 완전한 Turing-complete 언어적 특성을 갖는다.
  • 즉, 일반적인 프로그래밍 언어의 조건문 처리 같은 동작이 가능하다. 자동화와 더불어, 쉽게 버저닝해 히스토리를 관리하고 함께 작업 할 수 있는 기반을 제공합니다.
## HCL을 이용한 테라폼 구성
resource "local_file" "abc" {
  content = "abc!"
  filename = "${path.module}/abc.txt"
}
## JSON을 이용한 CloudFormation 구성
{
  "resource": [
  {
    "local_file": [
      {
        "abc": [
          {
            "content":"abc!",
            "filenale":"${path.module}/abc.txt"
          }
        ]
     }
   ]
  }
 ]
} 

HCL을 사용하면 동일한 내용을 JSON으로 표현한 것보다 더 간결하고 읽기 쉽게 작성할 수 있습니다.


3.3 테라폼 블록

테라폼 블록은 테라폼의 구성을 명시하는 데 사용됩니다. 테라폼 버전이나 프로바이더 버전과 같은 값들은 자동으로 설정되지만, 함께 작업할 때는 버전을 명시적으로 선언하고 필요한 조건을 입력하여 실행 오류를 최소화 할 것을 권장한다.

  • 테라폼 설정 블록의 구조
terraform {
  required_version = "~> 1.3.0" # 테라폼 버전

  required_providers { # 프로바이더 버전을 나열
    random = {
      version = ">= 3.0.0, < 3.1.0"
    }
    aws = {
      version = "4.2.0"
    }
  }

  cloud { # Cloud/Enterprise 같은 원격 실행을 위한 정보
    organization = "<MY_ORG_NAME>"
    workspaces {
      name = "my-first-workspace"
    }
  }

  backend "local" { # state를 보관하는 위치를 지정
    path = "relative/path/to/terraform.tfstate"
  }
}

  • 버전 체계는 Semantic Versioning 방식을 따릅니다.
# version = Major.Minor.Patch
version = 1.3.4

  • 시맨틱 버전 관리 방식
    Major : 내부 동작의 API가 변경 또는 삭제되거나 하위 호환이 되지 않는 버전
    Minor : 신규 기능이 추가되거나 개선되고 하위 호환이 가능한 버전
    Patch : 버그 및 일부 기능이 개선된 하위 호환이 가능한 버전

  • 테라폼 버전 관리로 비유된 선언 방식의 의미
선언된 버전의미고려 사항
1.0.0테라폼 v1.0.0만을 허용한다테라폼을 업그레이드하기 위해서는 선언된 버전을 변경해야만 한다
>= 1.0.0테라폼 v1.0.0 이상의 모든 버전을 허용한다v1.0.0 버전을 포함해 그 이상의 모든 버전을 허용해 실행된다
~> 1.0.0.테라폼 v1.0.0을 포함한 v1.0.x 버전을 하용하고 v1.x는 허용하지 않는다부버전에 대한 업데이트는 무중단으로 이루어진다
>= 1.0, < 2.0.0테라폼 v1.0.0 이상 v2.0.0 미만인 버전을 허용한다주버전에 대한 업데이트를 방지한다

📖 Provider 버전

0.13 버전 이전에는 provider 블록에 함께 버전을 명시했지만 이후에는 terraform 블록에서 required_providers에 정의한다.

# v0.13 이전
provider "aws" {
  version = "~> 4.2.0"
  region = "ap-northeast-2"
}

provider "azurerm" {
  version = ">= 2.99.0"
  features {}
}


# v0.13 부터
terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "~> 4.2.0"
    }
    azurerm = {
      source = "hashicorp/azurerm"
      version = ">= 2.99.0"
    }
  }
}

각 Provider의 이름에 소스 경로와 버전을 명시하며, 테라폼 레지스트리 공식 페이지에서 원하는 Provider를 선택한 다음 화면에서 우측 상단의 [USE PROVIDER]를 클릭하면 테라폼 코드에 해당 버전을 사용하는 샘플 코드가 표기된다.
테라폼 레지스트리 Link(Click)

📖 Backend 블록

백엔드 블록의 구성은 테라폼 실행 시 저장되는 State(상태 파일)저장 위치를 선언한다. 주의할 점은 하나의 백엔드만 허용한다는 점이다. 테라폼은 State의 데이터를 사용해 코드로 관리된 리소스를 탐색하고 추적한다. 작업자 간의 협업을 고려한다면 테라폼으로 생성한 리소스의 상태 저장 파일을 공유할 수 있는 외부 백엔드 저장소가 필요하다. 그리고 State에는 외부로 노출되면 안 되는 패스워드 또는 인증서 정보 같은 민감한 데이터들이 포함될 수 있으므로 State의 접근 제어가 필요하다.


🔎 State 잠금 동작

  • 기본적으로 활성화되는 백엔드local이다.
  • 상태를 작업자의 로컬 환경저장하고 관리하는 방식이다.
  • 이 밖의 다른 백엔드 구성은 동시에 여러 작업자가 접근해 사용할 수 있도록 공유 스토리지 같은 개념을 갖는다.
  • 공유되는 백엔드에 State가 관리되면 테라폼이 실행되는 동안 .terraform.tfstate.lock.info 파일이 생성되면서 해당 State를 동시에 사용하지 못하도록 잠금 처리를 한다.
  • 파일 생성을 확인하고 싶다면 terraform apply를 실행하고 생성되는 잠금 파일을 확인해보자. 잠금 파일 내의 정보는 다음과 같다.
ID:        30773305-a78d-49f1-8f3f-5604d742b66f
Operation: OperationTypeApply                      # 어떤 동작으로 인해 해당 
잠금 파일이 생성되었는지 명기
Info:
Who:       gasida@seojonghoui-MacBookPro.local     # 작업자 정보
Version:   1.5.1                                   # 실행한 테라폼 버전
Created:   2023-06-28 12:23:59.113608 +0000 UTC
Path:      state/terraform.tfstate                 # 잠긴 state 파일의 위치

3.4 리소스(resource)

리소스는 테라폼이 프로비저닝 도구라는 측면에서 가장 중요한 요소이다. 리소스 블록은 선언된 항목을 생성하는 동작을 수행한다.

  • 리소스 선언 방식
resource "<리소스 유형>" "<이름>" {
  <인수> = <>
}

resource "local_file" "abc" {
  content  = "123"
  filename = "${path.module}/abc.txt"
}
  • 리소스로 시작하고 리소스 유형을 정의한다.

  • 리소스 선언은 리소스 유형(Provider이름_제공 리소스 유형), 동일한 유형에 대한 식별자 역할로 고유한 이름, 구성 인수들이 이름 뒤에 중괄호 내에 선언됩니다.

  • 리소스에서 사용되는 유형들은 Provider에 종속성을 갖는다. 특정 Provider의 유형만 추가해도 init 수행 시 해당 Provider를 설치한다.

resource "local_file" "abc" {
  content  = "123"
  filename = "${path.module}/abc.txt"
}

resource "aws_instance" "web" {
  ami = "ami-a1b2c3d4"
  instance_type = "t2.micro"  
}

🖥️ 종속성

테라폼 종속성은 resource, module 선언으로 프로비저인되는 각 요소의 생성 순서를 구분짓는다. 기본적으로 다른 리소스에서 값을 참조해 불러올 경우 생성 선후 관계에 따라 작업자가 의도하지는 않았지만 자동으로 연관 관계가 정의되는 암시적 종속성을 갖게 되고, 강제로 리소스 간 명시적 종속성을 부여할 경우에는 메타인수인 depends_on을 활용한다.

  • 두 개의 병렬 리소스 요소 선언
resource "local_file" "abc" {
  content  = "123!"
  filename = "${path.module}/abc.txt"
}

resource "local_file" "def" {
  content  = "456!"
  filename = "${path.module}/def.txt"
}

해당 두 리소스는 서로 관계가 없는 동일한 수준으로 테라폼의 병렬 실행 방식에 따라 terraform apply를 수행하면 동시에 진행된다.

terraform apply
...
Plan: 2 to add, 0 to change, 0 to destroy.
local_file.def: Creating...
local_file.abc: Creating...
local_file.def: Creation complete after 0s [id=5f30576af23a25b7f44fa7f5fdf70325ee389155]
local_file.abc: Creation complete after 0s [id=b9fbde4d33ab9c450a7ce303fb4788c9d2db9aed]

  • 리소스 참조값으로 리소스 간 암시적 종속성 부여
resource "local_file" "abc" {
  content  = "123!"
  filename = "${path.module}/abc.txt"
}

resource "local_file" "def" {
  content  = local_file.abc.content
  filename = "${path.module}/def.txt"
}
```bash
terraform apply
...
Plan: 2 to add, 0 to change, 0 to destroy.
local_file.abc: Creating... <- 먼저 만들고
local_file.abc: Creation complete after 0s [id=5f30576af23a25b7f44fa7f5fdf70325ee389155]
local_file.def: Creating... <- 그 다음 만듬
local_file.def: Creation complete after 0s [id=5f30576af23a25b7f44fa7f5fdf70325ee389155]

처음 실행 결과와 다른 점은 종속 우선 관계에 있는 리소스가 먼저 만들어지며, 완료 후 나머지 리소스가 만들어진다.


📄 수명 주기

lifecycle은 리소스의 기본 수명주기를 작업자가 의도적으로 변경하는 메타인수입니다. 메타인수 내에는 아래 선언이 가능합니다.

  • create_before_destroy (bool): 리소스 수정 시 신규 리소스를 우선 생성하고 기존 리소스를 삭제
  • prevent_destroy (bool): 해당 리소스를 삭제 Destroy 하려 할 때 명시적으로 거부
  • ignore_changes (list): 리소스 요소에 선언된 인수의 변경 사항을 테라폼 실행 시 무시
  • precondition: 리소스 요소에 선언해 인수의 조건을 검증
  • postcondition: Plan과 Apply 이후의 결과를 속성 값으로 검증

📖 create_before_destroy

리소스 특성에 따라 특정 인수 값을 수정하고 프로비저닝을 수행하면 대상을 삭제하고 다시 생성해야 하는 경우가 있다.

  • image 변경 되는 경우 해당 VM 리소스를 삭제하고 다시 생성
  • 테라폼의 기본 수명주기삭제 후 생성이기 때문에 작업자가 의도적으로 수정된 리소스를 먼저 생성하기를 원할 수 있다.
  • 이 경우 create_before_destroytrue로 선언되면 의도한 생성을 실행한 후 삭제로 동작한다.
  • 하지만 생성되는 리소스가 기존 리소스로 인해 생성이 실패되거나 삭제 시 함께 삭제될 수 있으니 주의해야 한다.

잘못된 사례 1 : 리소스의 명시적 구분이 사용자가 지정한 특정 이름이나 ID인 경우 기존 리소스에 할당되어 있기 때문에 생성 실패
잘못된 사례 2 : 생성 후 삭제 시 동일한 리소스에 대한 삭제 명령이 수행되어 리소스가 모두 삭제

  • false 코드
resource "local_file" "abc" {
  content  = "lifecycle - step 1"
  filename = "${path.module}/abc.txt"

  lifecycle {
    create_before_destroy = false
  }
}

content의 내용을 수정하고 create_before_destroy를 true로 선언해 다시 terraform apply를 실행한다.

  • true 코드
resource "local_file" "abc" {
  content  = "lifecycle - step 2"
  filename = "${path.module}/abc.txt"

  lifecycle {
    create_before_destroy = true
  }
}
  • 결과
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+/- create replacement and then destroy

Terraform will perform the following actions:

  # local_file.abc must be replaced
+/- resource "local_file" "abc" {
      ~ content              = "lifecycle - step 1" -> "lifecycle - step 2" # forces replacement
      ~ content_base64sha256 = 
        # (3 unchanged attributes hidden)
    }

Plan: 1 to add, 0 to change, 1 to destroy.

local_file.abc: Creating...
local_file.abc: Creation complete after 0s [id=43809e4e5139be51422bfdcb41cab0852741ec10]
local_file.abc (deposed object 16d4455e): Destr

content가 변경되는 동일한 파일 이름을 지정하여 파일 내용은 수정됐지만, 최종적으로 동일한 파일을 삭제하게 되어 설계에 유의해야한다.


📖 prevent_destroy

작업자가 의도적으로 특정 리소스의 삭제를 방지하고 싶은 경우에 사용한다.

resource "local_file" "abc" {
  content  = "lifecycle - step 3"
  filename = "${path.module}/abc.txt"

  lifecycle {
    prevent_destroy = true
  }
}
/mnt/c/Users/Pro/Desktop/T201/workspaces/03.lifecycle$ terraform apply
local_file.abc: Refreshing state... [id=43809e4e5139be51422bfdcb41cab0852741ec10]
╷
│ Error: Instance cannot be destroyed
│
│   on main.tf line 1:
│    1: resource "local_file" "abc" {
│
│ Resource local_file.abc has lifecycle.prevent_destroy set,
│ but the plan calls for this resource to be destroyed. To
│ avoid this error and continue with the plan, either disable
│ lifecycle.prevent_destroy or reduce the scope of the plan
│ using the -target flag.

테라폼 수명주기 (삭제->생성)에 따라 수행되는 리소스에 prevent_destroy가 활성화되어 삭제가 일어나지 않고 실패한다.


📖 ignore_changes

리소스 요소의 인수를 지정해 수정 계획에 변경 사항이 반영되지 않도록 하는 것이다.

  • step 4 -> 5로 수정 후 진행
resource "local_file" "abc" {
  content  = "lifecycle - step 5"
  filename = "${path.module}/abc.txt"

  lifecycle {
    ignore_changes = [ 
      content
     ]
  }
}
/mnt/c/Users/Pro/Desktop/T201/workspaces/03.lifecycle$ terraform apply
local_file.abc: Refreshing state... [id=43809e4e5139be51422bfdcb41cab0852741ec10]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

리소스 속성에 변경이 있었지만 ignore_changes의 대상으로 변경 사항이 plan에 포함되지 않아 변경이 되지 않았다.


📖 precondition

리소스 생성 이전에 입력된 인수 값을 검증하는 데 사용해 프로비저닝 이전에 미리 약속된 값 이외의 값 또는 필수로 명시해야 하는 인수 값을 검증할 수 있다. 간단하게 리소스 요소에 선언해 인수의 조건을 검증한다.

  • 리소스 생성 이전의 조건을 부여
variable "file_name" {
  default = "step0.txt"
}

resource "local_file" "abc" {
  content  = "lifecycle - step 6"
  filename = "${path.module}/${var.file_name}"

  lifecycle {
    precondition {
      condition     = var.file_name == "step6.txt"
      error_message = "file name is not \"step6.txt\""
    }
  }
}
  • 결과
skwwnl@skwwnl:/mnt/c/Users/Pro/Desktop/T201/workspaces/03.lifecycle$ terraform plan
local_file.abc: Refreshing state... [id=43809e4e5139be51422bfdcb41cab0852741ec10]

Planning failed. Terraform encountered an error while generating this plan.

╷
│ Error: Resource precondition failed
│
│   on main.tf line 11, in resource "local_file" "abc":11:       condition     = var.file_name == "step6.txt"
│     ├────────────────
│     │ var.file_name is "step0.txt"
│
│ file name is not "step6.txt"

precondition은 프로비저닝해야 하는 클라우드 인프라의 VM을 생성할 때 내부적으로 검증된 이미지 아이디를 사용하는지 등과 같은 구성을 미리 확인하고 사전에 잘못된 프로비저닝을 실행할 수 없도록 구성할 수 있다.


📖 postcondition

프로비저닝 변경 이후 결과를 검증함과 동시에 의존성을 갖는 다른 구성의 변경을 맞는 효과가 있다. plan과 apply 이후의 결과를 속성 값으로 검증한다.

  • 리소스 생성 이후의 조건을 부여
resource "local_file" "abc" {
  content  = ""
  filename = "${path.module}/step7.txt"

  lifecycle {
    postcondition {
      condition     = self.content != ""
      error_message = "content cannot empty"
    }
  }
}

output "step7_content" {
  value = local_file.abc.id
}
  • 결과
│ Error: Resource postcondition failed
│
│   on main.tf line 7, in resource "local_file" "abc":7:       condition     = self.content != ""
│     ├────────────────
│     │ self.content is ""
│
│ content cannot empty

종속성을 갖는 여러 리소스를 구성하는 경우, 리소스의 데이터가 다른 리소스 생성 시 활용될 때 원하는 속성이 정의되어야 하는 경우를 확인할 수 있다. 특히, 프로비저닝 이후에 생성되는 속성 값이 있으므로 영향을 받는 다른 리소스가 생성되기 전에 예상되지 않은 프로비저닝 작업을 방지할 수 있다.

0개의 댓글