저번 시간에는 Terraform Registry에 있는 모듈을 가져다가 사용하는 것 까지는 해봤다. 이번에는 내가 스스로 모듈을 만들어서 그 모듈을 사용해보자.
Directory path
우선, 나의 모듈을 가지고 사용하는 테라폼 소스 코드의 구조는 다음과 같다.
account 라는 폴더가 하나의 모듈로서 기능을 할 것이고 그 모듈을 루트 디렉토리에 있는 main.tf 에서 사용할 것이다. 그럼 account 디렉토리에 각각의 파일을 하나씩 알아보자.
참고로 파일명은 정해져 있는게 아니라 관습적으로 사용되는 명칭이다. 그니까 꼭 저것을 따르지 않아도 되지만 관습이니 안 따라야할 이유도 없다.
versions.tf
이 파일은 테라폼과 프로바이더의 버전을 명시한 파일이다. 소스 코드는 다음과 같다.
terraform {
required_version = ">= 0.15"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.45"
}
}
}
variables.tf
이 파일은 모듈에서 사용하는 변수를 정의한 파일이다. 소스 코드는 다음과 같다.
variable "name" {
description = "The name for the AWS account. Used for the account alias."
type = string
}
variable "password_policy" {
description = "Password Policy for the AWS account."
type = object({
minimum_password_length = number
require_numbers = bool
require_symbols = bool
require_lowercase_characters = bool
require_uppercase_characters = bool
allow_users_to_change_password = bool
hard_expiry = bool
max_password_age = number
password_reuse_prevention = number
})
default = {
minimum_password_length = 8
require_numbers = true
require_symbols = true
require_lowercase_characters = true
require_uppercase_characters = true
allow_users_to_change_password = true
hard_expiry = false
max_password_age = 0
password_reuse_prevention = 0
}
}
outputs.tf
이 파일은 모듈에서 만들어내는 outputs을 정의한 파일이다. 특정 테라폼 소스에서 어떤 모듈을 가져다가 사용할 때 모듈이 내뱉는 attribute를 참조해야 하는 경우가 많은데 그 참조할 수 있는 값들은 모듈에서 뱉어내는 output 뿐이다. 그래서 적절한 output이 중요하다.
소스 코드는 다음과 같다.
output "id" {
description = "The AWS Account ID"
value = data.aws_caller_identity.this.account_id
}
output "name" {
description = "Name of the AWS account. The account alias."
value = aws_iam_account_alias.this.account_alias
}
output "signin_url" {
description = "The URL to signin for the AWS account."
value = "https://${var.name}.signin.aws.amazon.com/console"
}
output "password_policy" {
description = "Password Policy for the AWS Account. `expire_passwords` indicates whether passwords in the account expire. Returns `true` if `max_password_age` contains a value greater than 0."
value = aws_iam_account_password_policy.this
}
main.tf
모듈의 main.tf 파일이다. 소스 코드는 다음과 같다.
data "aws_caller_identity" "this" {}
resource "aws_iam_account_alias" "this" {
account_alias = var.name
}
resource "aws_iam_account_password_policy" "this" {
minimum_password_length = var.password_policy.minimum_password_length
require_numbers = var.password_policy.require_numbers
require_symbols = var.password_policy.require_symbols
require_lowercase_characters = var.password_policy.require_lowercase_characters
require_uppercase_characters = var.password_policy.require_uppercase_characters
allow_users_to_change_password = var.password_policy.allow_users_to_change_password
hard_expiry = var.password_policy.hard_expiry
max_password_age = var.password_policy.max_password_age
password_reuse_prevention = var.password_policy.password_reuse_prevention
}
README.md
이 파일은 이 모듈이 어떤 형식으로 만들어지고 무엇이 필수값이고 아닌지 또는 버전은 어떻게 되는지 이 모듈의 outputs은 무엇인지를 명시한 파일이다. 그리고 이 파일은 직접 작성한 게 아니고 terraform-docs 라는 툴을 사용했다.
이 녀석을 다운받고 시키는 대로 하면 다음과 같이 날 위해 README 파일을 만들어준다.
$ terraform-docs markdown path/to/module
## Requirements
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.15 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.45 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.45 |
## Modules
No modules.
## Resources
| Name | Type |
|------|------|
| [aws_iam_account_alias.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_account_alias) | resource |
| [aws_iam_account_password_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_account_password_policy) | resource |
| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
## Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_name"></a> [name](#input\_name) | The name for the AWS account. Used for the account alias. | `string` | n/a | yes |
| <a name="input_password_policy"></a> [password\_policy](#input\_password\_policy) | Password Policy for the AWS account. | <pre>object({<br> minimum_password_length = number<br> require_numbers = bool<br> require_symbols = bool<br> require_lowercase_characters = bool<br> require_uppercase_characters = bool<br> allow_users_to_change_password = bool<br> hard_expiry = bool<br> max_password_age = number<br> password_reuse_prevention = number<br> })</pre> | <pre>{<br> "allow_users_to_change_password": true,<br> "hard_expiry": false,<br> "max_password_age": 0,<br> "minimum_password_length": 8,<br> "password_reuse_prevention": 0,<br> "require_lowercase_characters": true,<br> "require_numbers": true,<br> "require_symbols": true,<br> "require_uppercase_characters": true<br>}</pre> | no |
## Outputs
| Name | Description |
|------|-------------|
| <a name="output_id"></a> [id](#output\_id) | The AWS Account ID |
| <a name="output_name"></a> [name](#output\_name) | Name of the AWS account. The account alias. |
| <a name="output_password_policy"></a> [password\_policy](#output\_password\_policy) | Password Policy for the AWS Account. `expire_passwords` indicates whether passwords in the account expire. Returns `true` if `max_password_age` contains a value greater than 0. |
| <a name="output_signin_url"></a> [signin\_url](#output\_signin\_url) | The URL to signin for the AWS account. |
그리고 이제 모듈을 가져다가 사용하는 루트 디렉토리에 있는 main.tf 파일을 보자.
main.tf
하단 소스 코드를 보자.
provider "aws" {
region = "ap-northeast-2"
}
module "account" {
source = "./account"
name = "cwchoiit-terraform"
password_policy = {
minimum_password_length = 8
require_numbers = true
require_symbols = true
require_lowercase_characters = true
require_uppercase_characters = true
allow_users_to_change_password = true
hard_expiry = false
max_password_age = 0
password_reuse_prevention = 0
}
}
output "id" {
value = module.account.id
}
output "account_name" {
value = module.account.name
}
output "signin_url" {
value = module.account.signin_url
}
output "account_password_policy" {
value = module.account.password_policy
}
저번에는 Registry에 있는 module을 사용할 때 source 형태가 저런식이 아니었다. 그리고 이건 로컬에 있는 모듈을 사용할 때 쓰는 source 형식이다. 이 두 차이점을 잘 알아둬야한다.
그리고 account 라는 모듈이 필요한 속성인 name, password_policy 값을 작성한다.
output은 모듈이 주는 output을 그대로 가져다가 사용했다.
이 상태에서 Apply를 해보자. 다음과 같이 Apply는 정상적으로 됐다.
그럼 내 계정의 Alias가 저렇게 변경됐는지 확인해보자. 다음은 그 결과이다.
결론
이렇게 로컬에서 모듈을 직접 만들어보고 사용해보았다. 모듈은 이런식으로 로컬에서도 사용가능하고 Registry에서 가져다가 사용하는 것도 된다. 그리고 한 가지 더 유용한 `terraform-docs`도 사용해봤다.
'IaC(Infrastructure as Code)' 카테고리의 다른 글
Terraform Provisioner/EC2 Userdata (2) | 2024.03.11 |
---|---|
terraform_remote_state (0) | 2024.03.10 |
Terraform Cloud (0) | 2024.03.10 |
Terraform Workspace (0) | 2024.03.08 |
Terraform Commands (taint / untaint) (0) | 2024.03.08 |