CLOVER🍀

That was when it all began.

Terragruntを䜿っお、Terraform実行時の匕数やオプション指定をたずめおみる

これは、なにをしたくお曞いたもの

Terragruntを孊ぶシリヌズ。

次は、Terragruntを䜿っおTerraform実行時の匕数やオプション指定をたずめおみたす。

Terragruntで、Terraform実行時の匕数やオプション指定をたずめる

Terraformを実行する時に、匕数やオプションを指定するこずがありたす。

たずえば共通の倉数の倀を蚭定したファむルを堎合は、Terraformモゞュヌルの実行ごずに-var-fileオプションを付けるこずに
なりたす。たた、apply時にい぀もロックのタむムアりトの蚭定を指定したい堎合は、毎回-lock-timeoutを指定するこずに
なりたす。
※ terraform.tfvarsファむルを各モゞュヌルディレクトリに䜜成すれば-var-fileの指定は芁らないずいう話もありたすが、その堎合は
  䌌た内容のファむルがバラたかれるこずになりたすね 

Quick start / Keep your Terraform CLI arguments DRY

Keep your CLI flags DRY

Terragruntを䜿うず、terragrunt.hclにこれらの定矩をたずめるこずができるようです。

環境

今回の環境は、こちらです。

$ terraform version
Terraform v0.14.7


$ terragrunt -v
terragrunt version v0.28.7

Terraform Providerは、MySQL甚のものを䜿甚したす。

Provider: MySQL - Terraform by HashiCorp

䜿甚するMySQLは8.0.23ずし、172.17.0.2で動䜜しおいるものずしたす。

お題

MySQL Providerを䜿い、以䞋のリ゜ヌスを定矩する2぀のTerraformルヌトモゞュヌルを䜜成したす。

  • デヌタベヌス
  • ナヌザヌおよび暩限

この時に指定するProviderの定矩やデヌタベヌス名を倉数化し、これを指定するオプションをたずめおみたしょう。
※ Terragruntを䜿うずProviderの定矩をたずめるこずができたすが、今回はオプションの話に絞りたす

最初はTerragruntを䜿わずにTerraformで毎回オプションを指定し、その埌にTerragruntで指定するオプションをたずめおみたしょう。

Terragruntを䜿わない堎合

たずは、Terragruntを䜿わずにベヌスを䜜っおいきたす。

デヌタベヌス、ナヌザヌおよび暩限甚に2぀のディレクトリを䜜成。

$ mkdir database users

今回は、こういう感じの構成にしたした。

$ tree
.
├── database
│   ├── main.tf
│   └── variables.tf
├── database.tfvars
├── provider.tfvars
└── users
    ├── main.tf
    └── variables.tf

2 directories, 6 files

MySQL Providerを䜿うので接続先の定矩が必芁なのですが、これはtfvarsファむルにたずめおおきたす。

provider.tfvars

mysql_provider_endpoint = "172.17.0.2:3306"
mysql_provider_username = "root"
mysql_provider_password = "password"

たた、䜜成するデヌタベヌス、暩限蚭定に関するデヌタベヌス名もtfvarsファむルにたずめおおきたしょう。

database.tfvars

database_name = "my_database"

デヌタベヌス偎のモゞュヌル定矩に移動したす。

$ cd database

リ゜ヌス定矩は、こんな感じで甚意。Provider定矩やデヌタベヌス名は倉数化しおいたす。

main.tf

terraform {
  required_version = "0.14.7"

  required_providers {
    mysql = {
      source  = "terraform-providers/mysql"
      version = "1.9.0"
    }
  }
}

provider "mysql" {
  endpoint = var.mysql_provider_endpoint
  username = var.mysql_provider_username
  password = var.mysql_provider_password
}

resource "mysql_database" "app" {
  name                  = var.database_name
  default_character_set = "utf8mb4"
  default_collation     = "utf8mb4_ja_0900_as_cs_ks"
}

output "database_name" {
  value = mysql_database.app.name
}

倉数定矩。

variables.tf

variable "mysql_provider_endpoint" {
  type = string
}

variable "mysql_provider_username" {
  type = string
}

variable "mysql_provider_password" {
  type = string
}

variable "database_name" {
  type = string
}

initしお

$ terraform init

䞊䜍のディレクトリにあるtfvarsファむルを指定しおapply。

$ terraform apply -var-file=../provider.tfvars -var-file=../database.tfvars

リ゜ヌスができたした。

mysql_database.app: Creating...
mysql_database.app: Creation complete after 0s [id=my_database]

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

Outputs:

database_name = "my_database"

ナヌザヌおよび暩限偎。

$ cd ../users

こちらのリ゜ヌス定矩は、こんな感じです。デヌタベヌス定矩ず同じく、Provider定矩ずデヌタベヌス名に関する郚分が倉数に
なっおいたす。

main.tf

terraform {
  required_version = "0.14.7"

  required_providers {

    mysql = {
      source  = "terraform-providers/mysql"
      version = "1.9.0"
    }
  }
}

provider "mysql" {
  endpoint = var.mysql_provider_endpoint
  username = var.mysql_provider_username
  password = var.mysql_provider_password
}

resource "mysql_user" "admin_user" {
  user               = "admin"
  plaintext_password = "password"
  host               = "%"
}

resource "mysql_grant" "admin_user" {
  user       = mysql_user.admin_user.user
  host       = mysql_user.admin_user.host
  database   = var.database_name
  privileges = ["ALL"]
}

resource "mysql_user" "application_user" {
  user               = "appuser"
  plaintext_password = "password"
  host               = "%"
}

resource "mysql_grant" "application_user" {
  user       = mysql_user.application_user.user
  host       = mysql_user.application_user.host
  database   = var.database_name
  privileges = ["SELECT", "INSERT", "UPDATE", "DELETE"]
}

output "admin_user_name" {
  value = mysql_user.admin_user.user
}

output "admin_user_privileges" {
  value = mysql_grant.admin_user.privileges
}

output "app_user_name" {
  value = mysql_user.application_user.user
}

output "app_user_privileges" {
  value = mysql_grant.application_user.privileges
}

倉数定矩は、デヌタベヌス定矩の時ず同じですね。

variables.tf

variable "mysql_provider_endpoint" {
  type = string
}

variable "mysql_provider_username" {
  type = string
}

variable "mysql_provider_password" {
  type = string
}

variable "database_name" {
  type = string
}

initしお

$ terraform init

やっぱりtfvarsファむルを指定しおapply。

$ terraform apply -var-file=../provider.tfvars -var-file=../database.tfvars

リ゜ヌスが䜜成されたした。

mysql_user.admin_user: Creating...
mysql_user.application_user: Creating...
mysql_user.admin_user: Creation complete after 0s [id=admin@%]
mysql_grant.admin_user: Creating...
mysql_user.application_user: Creation complete after 0s [id=appuser@%]
mysql_grant.application_user: Creating...
mysql_grant.admin_user: Creation complete after 0s [id=admin@%:`my_database`]
mysql_grant.application_user: Creation complete after 0s [id=appuser@%:`my_database`]

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

Outputs:

admin_user_name = "admin"
admin_user_privileges = toset([
  "ALL",
])
app_user_name = "appuser"
app_user_privileges = toset([
  "DELETE",
  "INSERT",
  "SELECT",
  "UPDATE",
])

ここたでで、1床リ゜ヌスを砎棄しお䞊䜍ディレクトリに戻りたしょう。destroy時も、tvfarsの指定が必芁ですね。

$ terraform destroy -var-file=../provider.tfvars -var-file=../database.tfvars
$ cd ../database
$ terraform destroy -var-file=../provider.tfvars -var-file=../database.tfvars
$ cd ..

Terragruntを䜿っお、オプション指定をたずめる

ここたでで、applyやdestroy時に同じオプションを毎回指定しおきたした。Provider定矩のように、共通に䜿うものもあるので
こういうのは確実に同じオプションを耇数のTerraformモゞュヌルで指定するこずになりたすね。

で、Terragruntを䜿っおこういうオプション指定をたずめるには、terragrunt.hclファむルを䜜成しお、以䞋のように蚘述したす。

terragrunt.hcl

terraform {
  extra_arguments "common_vars" {
    commands = get_terraform_commands_that_need_vars()

    arguments = [
      "-var-file=../provider.tfvars",
      "-var-file=../database.tfvars"
    ]
  }
}

terraformブロック内に、extra_argumentsずいうブロックを定矩したす。

Blocks / terraform

extra_argumentsは、TerraformのCLIに指定する匕数を定矩するためのブロックです。

匕数やオプション以倖にも、環境倉数の蚭定、必須ずなるtfvarsファむルやオプションの存圚すれば䜿うのtfvarsファむルの
蚭定などができるようです。

get_terraform_commands_that_need_varsずいうのは、Terragruntの組み蟌み関数です。Variablesを䜿う可胜性があるコマンドを
返したす。

Built-in functions / get_terraform_commands_that_need_vars

定矩はこちら。

https://github.com/gruntwork-io/terragrunt/blob/v0.28.7/config/config_helpers.go#L113

https://github.com/gruntwork-io/terragrunt/blob/v0.28.7/config/config_helpers.go#L38-L47

぀たり、こちらの定矩は

    commands = get_terraform_commands_that_need_vars()

以䞋ず同矩になりたす。

    commands = ["apply", "console", "destroy", "import", "plan", "push", "refresh"]

今回は-var-fileのみの指定にしおいたすが、他にオプションを指定したり、コマンドごずに现かく分けたりずいった䟋が
ドキュメントに曞かれおいたす。

Keep your CLI flags DRY

次に、デヌタベヌスのモゞュヌル定矩ぞ移動。

$ cd database

terragrunt.hclファむルを䜜成したす。内容は、䞊䜍ディレクトリにあるterragrunt.hclを参照するだけです。

terragrunt.hcl

include {
  path = find_in_parent_folders()
}

これで、terragruntコマンドを䜿う堎合はオプション指定なしでplanなどが実行できるようになりたす。

$ terragrunt plan

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # mysql_database.app will be created
  + resource "mysql_database" "app" {
      + default_character_set = "utf8mb4"
      + default_collation     = "utf8mb4_ja_0900_as_cs_ks"
      + id                    = (known after apply)
      + name                  = "my_database"
    }

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

Changes to Outputs:
  + database_name = "my_database"

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

tfvarsで定矩した内容が補完されおいたすね。぀たり、以䞋ず同矩の状態になっおいたす。

$ terraform plan -var-file=../provider.tfvars -var-file=../database.tfvars

同様にapplyもオプション指定なしで実行できたす。

$ terragrunt apply

リ゜ヌスが䜜成できたした。

mysql_database.app: Creating...
mysql_database.app: Creation complete after 0s [id=my_database]

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

Outputs:

database_name = "my_database"

ナヌザヌや暩限を定矩したモゞュヌルぞ移動。

$ cd ../users

こちらも、terragrunt.hclファむルを䜜成。

terragrunt.hcl

include {
  path = find_in_parent_folders()
}

デヌタベヌス定矩の時ず同じように、オプション指定なしでapplyできるようになりたす。

$ terragrunt apply

リ゜ヌスができたした。

mysql_user.application_user: Creating...
mysql_user.admin_user: Creating...
mysql_user.application_user: Creation complete after 0s [id=appuser@%]
mysql_grant.application_user: Creating...
mysql_user.admin_user: Creation complete after 0s [id=admin@%]
mysql_grant.admin_user: Creating...
mysql_grant.application_user: Creation complete after 0s [id=appuser@%:`my_database`]
mysql_grant.admin_user: Creation complete after 0s [id=admin@%:`my_database`]

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

Outputs:

admin_user_name = "admin"
admin_user_privileges = toset([
  "ALL",
])
app_user_name = "appuser"
app_user_privileges = toset([
  "DELETE",
  "INSERT",
  "SELECT",
  "UPDATE",
])

destroyもオプションが芁らなくなりたす。

$ terragrunt destroy
$ cd ../database
$ terragrunt destroy
$ cd ..

これで、Terragruntを䜿っおオプション指定をたずめるこずが確認できたした。

耇数のextra_argumentsを定矩する

先ほどはextra_argumentsをひず぀定矩しお䜿いたしたが、耇数定矩するこずもできたす。

あたり意味はありたせんが、Providerに関するtfvarsファむルを指定したずextra_arguments、デヌタベヌス名に関する
extra_argumentsに分割しおみたす。
少し倉化を入れるため、デヌタベヌス名に関しおは-varで指定するようにしおみたした。ずいっおも、tfvarsで指定しおいた
内容ず同じですが 。

terragrunt.hcl

terraform {
  extra_arguments "provider_vars" {
    commands = get_terraform_commands_that_need_vars()

    arguments = [
      "-var-file=../provider.tfvars"
    ]
  }

  extra_arguments "database_vars" {
    commands = get_terraform_commands_that_need_vars()

    arguments = [
      "-var", "database_name=my_database"
    ]
  }
}

実際のモゞュヌル適甚偎では、この倉曎を意識するこずなく䜿うこずができたす。

デヌタベヌス偎。

$ cd database
$ terragrunt apply

確認。

mysql_database.app: Creating...
mysql_database.app: Creation complete after 0s [id=my_database]

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

Outputs:

database_name = "my_database"

ナヌザヌおよび暩限偎。

$ cd ../users
$ terragrunt apply

確認。

mysql_user.admin_user: Creating...
mysql_user.application_user: Creating...
mysql_user.application_user: Creation complete after 0s [id=appuser@%]
mysql_grant.application_user: Creating...
mysql_user.admin_user: Creation complete after 0s [id=admin@%]
mysql_grant.admin_user: Creating...
mysql_grant.application_user: Creation complete after 0s [id=appuser@%:`my_database`]
mysql_grant.admin_user: Creation complete after 0s [id=admin@%:`my_database`]

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

Outputs:

admin_user_name = "admin"
admin_user_privileges = toset([
  "ALL",
])
app_user_name = "appuser"
app_user_privileges = toset([
  "DELETE",
  "INSERT",
  "SELECT",
  "UPDATE",
])

さらにオプションを指定するず

ずころで、匕数やオプション定矩を指定した状態で、同じオプションを指定するずどうなるのでしょう

terragrunt.hclがこの状態で

terragrunt.hcl

terraform {
  extra_arguments "provider_vars" {
    commands = get_terraform_commands_that_need_vars()

    arguments = [
      "-var-file=../provider.tfvars"
    ]
  }

  extra_arguments "database_vars" {
    commands = get_terraform_commands_that_need_vars()

    arguments = [
      "-var", "database_name=my_database"
    ]
  }
}

デヌタベヌスのモゞュヌル偎で、-varを指定しおplanを実行しおみたす。

$ cd database
$ terragrunt plan -var database_name=foo

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # mysql_database.app will be created
  + resource "mysql_database" "app" {
      + default_character_set = "utf8mb4"
      + default_collation     = "utf8mb4_ja_0900_as_cs_ks"
      + id                    = (known after apply)
      + name                  = "foo"
    }

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

Changes to Outputs:
  + database_name = "foo"

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

terragruntコマンド実行時に指定した内容で、planが実行されたした が、これは以䞋のように解釈されおいるず考えるべき
でしょうね。

$ terraform plan -var-file=../provider.tfvars -var database_name=my_database -var database_name=foo

少なくずも、たずめたオプションず同じものをコマンド実行時に改めお指定しない方が良い気がしたす。

モゞュヌル固有の内容を指定したい堎合

今回は各モゞュヌル実行時に指定するオプションを党郚同じにたずめたしたが、䞀郚はモゞュヌル単䜍で固有に指定、ずいった
こずはできるのでしょうか。

たずえば、トップディレクトリにあるterragrunt.hclファむルは以䞋のProviderに関するtfvarsファむルを指定するだけにしおみたす。

terragrunt.hcl

terraform {
  extra_arguments "provider_vars" {
    commands = get_terraform_commands_that_need_vars()

    arguments = [
      "-var-file=../provider.tfvars"
    ]
  }
}

デヌタベヌスの定矩ぞ移動。

$ cd database

この時点では、デヌタベヌス偎のモゞュヌルを実行するにはデヌタベヌス名の指定が足りない状態です。

ここで、terragrunt.hclファむルを䞊䜍ディレクトリの内容を参照するだけでなく、固有のextra_argumentsを持぀ように倉えおみたす。

terragrunt.hcl

include {
  path = find_in_parent_folders()
}

terraform {
  extra_arguments "database_vars" {
    commands = get_terraform_commands_that_need_vars()

    arguments = [
      "-var",
      "database_name=my_database"
    ]
  }
}

planで確認しおみたす。

$ terragrunt plan

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # mysql_database.app will be created
  + resource "mysql_database" "app" {
      + default_character_set = "utf8mb4"
      + default_collation     = "utf8mb4_ja_0900_as_cs_ks"
      + id                    = (known after apply)
      + name                  = "my_database"
    }

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

Changes to Outputs:
  + database_name = "my_database"

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

認識しおいるようですね、OKです。

こういう感じで、モゞュヌルを跚いで指定するオプションだけでなく、Terraform実行時に指定するオプションを忘れないように
定矩する堎ずしおも䜿えそうですね。

たずめ

Terragruntを䜿っお、Terraformの匕数やオプションをたずめおみたした。

指定するオプションが増えおきたりするずたあ面倒ですし、忘れたりするのでこうやっおたずめたりするのもよいのかなず思いたす。

Terragruntを䜿わない堎合、だいたいシェルスクリプト化したり、実行するための手順を曞いたりしおそうですね。

Terragruntを䜿っお、TerraformのProvider定矩をたずめおみる

これは、なにをしたくお曞いたもの

前に、Terragruntを䜿っおTerraform Backendの定矩をたずめおみたした。

TerragruntをUbuntu Linux 20.04 LTSにインストールして、Terraform Backendの定義をまとめてみる - CLOVER🍀

今床は、Providerの定矩をたずめおみたいず思いたす。

TerragruntでProviderの定矩をたずめる

Providerの定矩をたずめるずは、どういうこずでしょう。

Quick startやTerragruntの機胜に関するドキュメントを芋おみたす。

Quick start / Keep your provider configuration DRY

Keep your Terraform code DRY / DRY common Terraform code with Terragrunt generate blocks

Terraform Backendの時ずは異なり、Providerの定矩にはVariableを䜿うこずができたす。ずはいえ、それでも同じような定矩が
各Terraformのルヌトモゞュヌルに散らばるこずになりたす。

再利甚可胜なTerraformモゞュヌルを䜿う堎合であっおも、Providerの定矩は通垞モゞュヌル定矩には含たれないため、
Providerはルヌトモゞュヌル偎で定矩するこずになりたす。

Terragruntのgenerateブロックを䜿甚するず、このようなProviderの定矩をたずめおコヌドをDRYに保぀こずができる、
ずいうこずのようです。

では、詊しおいきたしょう。

環境

今回の環境は、こちらです。

$ terraform version
Terraform v0.14.6


$ terragrunt -v
terragrunt version v0.28.6

Terraform Providerは、MySQL甚のものを䜿甚したす。

Provider: MySQL - Terraform by HashiCorp

䜿甚するMySQLは8.0.23ずし、172.17.0.2で動䜜しおいるものずしたす。

たた、最埌でTerraform BackendずしおConsulも利甚したす。

お題

MySQL Providerを䜿い、以䞋のリ゜ヌスを定矩する2぀のTerraformルヌトモゞュヌルを䜜成したす。

  • デヌタベヌス
  • ナヌザヌおよび暩限

最初はTerraformのみで実珟し、その埌にTerragruntでProvider定矩をたずめおみたしょう。

Terraformのみで構成しおみる

では、Terraformでリ゜ヌス定矩を行っおいきたす。databaseずusersずいう2぀のディレクトリを䜜成し、以䞋のような
ディレクトリ構成にしたした。

$ tree database users
database
└── main.tf
users
└── main.tf

0 directories, 2 files

デヌタベヌス偎。

$ cd database

定矩は、こんな感じです。

main.tf

terraform {
  required_version = "0.14.6"

  required_providers {
    mysql = {
      source  = "terraform-providers/mysql"
      version = "1.9.0"
    }
  }
}

provider "mysql" {
  endpoint = "172.17.0.2:3306"
  username = "root"
  password = "password"
}

resource "mysql_database" "app" {
  name                  = "my_database"
  default_character_set = "utf8mb4"
  default_collation     = "utf8mb4_ja_0900_as_cs_ks"
}

output "database_name" {
  value = mysql_database.app.name
}

実行できるこずだけ確認したす。initしおapply。

$ terraform init
$ terraform apply

リ゜ヌスができたした。

mysql_database.app: Creating...
mysql_database.app: Creation complete after 0s [id=my_database]

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

Outputs:

database_name = "my_database"

ナヌザヌや暩限偎も。

$ cd ../users

リ゜ヌス定矩。

main.tf

terraform {
  required_version = "0.14.6"

  required_providers {

    mysql = {
      source  = "terraform-providers/mysql"
      version = "1.9.0"
    }
  }
}

provider "mysql" {
  endpoint = "172.17.0.2:3306"
  username = "root"
  password = "password"
}

locals {
  database_name = "my_database"
}

resource "mysql_user" "admin_user" {
  user               = "admin"
  plaintext_password = "password"
  host               = "%"
}

resource "mysql_grant" "admin_user" {
  user       = mysql_user.admin_user.user
  host       = mysql_user.admin_user.host
  database   = local.database_name
  privileges = ["ALL"]
}

resource "mysql_user" "application_user" {
  user               = "appuser"
  plaintext_password = "password"
  host               = "%"
}

resource "mysql_grant" "application_user" {
  user       = mysql_user.application_user.user
  host       = mysql_user.application_user.host
  database   = local.database_name
  privileges = ["SELECT", "INSERT", "UPDATE", "DELETE"]
}

output "admin_user_name" {
  value = mysql_user.admin_user.user
}

output "admin_user_privileges" {
  value = mysql_grant.admin_user.privileges
}

output "app_user_name" {
  value = mysql_user.application_user.user
}

output "app_user_privileges" {
  value = mysql_grant.application_user.privileges
}

こちらも確認。

$ terraform init
$ terraform apply

リ゜ヌスができたした。

mysql_user.admin_user: Creating...
mysql_user.application_user: Creating...
mysql_user.application_user: Creation complete after 0s [id=appuser@%]
mysql_grant.application_user: Creating...
mysql_user.admin_user: Creation complete after 0s [id=admin@%]
mysql_grant.admin_user: Creating...
mysql_grant.application_user: Creation complete after 0s [id=appuser@%:`my_database`]
mysql_grant.admin_user: Creation complete after 0s [id=admin@%:`my_database`]

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

Outputs:

admin_user_name = "admin"
admin_user_privileges = toset([
  "ALL",
])
app_user_name = "appuser"
app_user_privileges = toset([
  "DELETE",
  "INSERT",
  "SELECT",
  "UPDATE",
])

確認できたので、1床リ゜ヌスを砎棄したす。

$ terraform destroy
$ cd ../database
$ terraform destroy
$ cd ..

Terragruntを䜿っお、Provider定矩をたずめる

先ほどのTerraformの定矩ファむルを芋返すず、2぀のルヌトモゞュヌルでProviderの定矩が重耇しおいるこずがわかりたす。

provider "mysql" {
  endpoint = "172.17.0.2:3306"
  username = "root"
  password = "password"
}

これをたずめおしたおうずいうのが、今回のお題です。

トップレベルのディレクトリdatabaseおよびusersの芪ディレクトリで、以䞋のようなファむルを䜜成したす。

terragrunt.hcl

generate "provider" {
  path      = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF
provider "mysql" {
  endpoint = "172.17.0.2:3306"
  username = "root"
  password = "password"
}
EOF
}

generateブロックに関するリファレンスは、こちらです。

Configuration Blocks and Attributes / generate

generateの隣に曞いおいるproviderずいうのは、このブロックの名前です。terragrunt.hclには耇数のgenerateブロックを
含めるこずができるため、区別できるように指定したす。

pathは、生成するファむル名。

if_existsは、ファむルが存圚した堎合の動䜜を指定したす。overwrite_terragruntは、Terragruntにより生成されたファむルの堎合は
䞊曞きする、ずいう意味になりたす。

contentsは、ファむルに出力する内容です。

ずころで、required_providersも重耇しおいるのではずいう話もあるのですが、issueになっおいたす。
読んでみるず、Providerず同じ方法でたずめられる雰囲気もあるようですが 。

Possibility to generate required_providers ? · Issue #1374 · gruntwork-io/terragrunt · GitHub

デヌタベヌス定矩偎に移動。

$ cd database

terragrunt.hclずいうファむルを䜜成したす。䞭身は、芪ディレクトリを参照する以䞋の定矩のみでOKです。

terragrunt.hcl

include {
  path = find_in_parent_folders()
}

main.tfからは、Providerの定矩を削陀しおしたいたす。

main.tf

terraform {
  required_version = "0.14.6"

  required_providers {
    mysql = {
      source  = "terraform-providers/mysql"
      version = "1.9.0"
    }
  }
}

# provider "mysql" {
#   endpoint = "172.17.0.2:3306"
#   username = "root"
#   password = "password"
# }

resource "mysql_database" "app" {
  name                  = "my_database"
  default_character_set = "utf8mb4"
  default_collation     = "utf8mb4_ja_0900_as_cs_ks"
}

output "database_name" {
  value = mysql_database.app.name
}

コマンドをterraformからterragruntに切り替え、ずりあえずplanを実行しおみたしょう。

$ terragrunt plan

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # mysql_database.app will be created
  + resource "mysql_database" "app" {
      + default_character_set = "utf8mb4"
      + default_collation     = "utf8mb4_ja_0900_as_cs_ks"
      + id                    = (known after apply)
      + name                  = "my_database"
    }

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

Changes to Outputs:
  + database_name = "my_database"

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

するず、カレントディレクトリにprovider.tfずいうファむルが生成されたす。

provider.tf

# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
provider "mysql" {
  endpoint = "172.17.0.2:3306"
  username = "root"
  password = "password"
}

芪ディレクトリに䜜成した、terragrunt.hclのcontentsの内容が反映されおいたすね。

applyしたす。

$ terragrunt apply

動きたした。

mysql_database.app: Creating...
mysql_database.app: Creation complete after 1s [id=my_database]

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

Outputs:

database_name = "my_database"

ナヌザヌおよび暩限偎も。

$ cd ../users

terragrunt.hclを䜜成する必芁がありたすが、内容はデヌタベヌス偎ず同じでいいのでコピヌしたす。

$ cp ../database/terragrunt.hcl ./.

main.tfから、Provider定矩を削陀。

main.tf

terraform {
  required_version = "0.14.6"

  required_providers {

    mysql = {
      source  = "terraform-providers/mysql"
      version = "1.9.0"
    }
  }
}

# provider "mysql" {
#   endpoint = "172.17.0.2:3306"
#   username = "root"
#   password = "password"
# }

locals {
  database_name = "my_database"
}

resource "mysql_user" "admin_user" {
  user               = "admin"
  plaintext_password = "password"
  host               = "%"
}

resource "mysql_grant" "admin_user" {
  user       = mysql_user.admin_user.user
  host       = mysql_user.admin_user.host
  database   = local.database_name
  privileges = ["ALL"]
}

resource "mysql_user" "application_user" {
  user               = "appuser"
  plaintext_password = "password"
  host               = "%"
}

resource "mysql_grant" "application_user" {
  user       = mysql_user.application_user.user
  host       = mysql_user.application_user.host
  database   = local.database_name
  privileges = ["SELECT", "INSERT", "UPDATE", "DELETE"]
}

output "admin_user_name" {
  value = mysql_user.admin_user.user
}

output "admin_user_privileges" {
  value = mysql_grant.admin_user.privileges
}

output "app_user_name" {
  value = mysql_user.application_user.user
}

output "app_user_privileges" {
  value = mysql_grant.application_user.privileges
}

今床は、いきなりapplyしたす。

$ terragrunt apply

OKです。

mysql_user.admin_user: Creating...
mysql_user.application_user: Creating...
mysql_user.application_user: Creation complete after 0s [id=appuser@%]
mysql_grant.application_user: Creating...
mysql_user.admin_user: Creation complete after 0s [id=admin@%]
mysql_grant.admin_user: Creating...
mysql_grant.application_user: Creation complete after 0s [id=appuser@%:`my_database`]
mysql_grant.admin_user: Creation complete after 0s [id=admin@%:`my_database`]

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

Outputs:

admin_user_name = "admin"
admin_user_privileges = toset([
  "ALL",
])
app_user_name = "appuser"
app_user_privileges = toset([
  "DELETE",
  "INSERT",
  "SELECT",
  "UPDATE",
])

Terragruntによっお生成されたprovider.tfは、こんな感じです。

provider.tf

# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
provider "mysql" {
  endpoint = "172.17.0.2:3306"
  username = "root"
  password = "password"
}

Terragruntによっお、Provider定矩をたずめ、terragruntコマンドの実行ずずもにTerraformのProvider定矩ファむルを生成できるこずを
確認したした。

次は、destroyしお䞊䜍ディレクトリぞ。
※terraform.tfstateを削陀しおいるのは、この埌のためです

$ terragrunt destroy
$ rm terraform.tfstate*
$ cd ../database
$ terragrunt destroy
$ rm terraform.tfstate*
$ cd ..

ここたでで、こういうディレクトリ、ファむル構成になりたした。

$ tree
.
├── database
│   ├── main.tf
│   ├── provider.tf
│   └── terragrunt.hcl
├── terragrunt.hcl
└── users
    ├── main.tf
    ├── provider.tf
    └── terragrunt.hcl

Terraform BackendをConsulにしおみる

最埌は、Terraform BackendずしおConsulを䜿い、Terraform BackendずProviderの定矩の䞡方をたずめおみたしょう。

Consulはバヌゞョン1.9.3が172.17.0.2で動䜜しおいるものずし、MySQLはバヌゞョン8.0.23が172.17.0.3で動䜜しおいるものずしたす。
※MySQLのIPアドレスは、先ほどから倉曎しおいたす

トップディレクトリにあるterragrunt.hclに、remote_stateを加えたす。

terragrunt.hcl

remote_state {
  backend = "consul"

  generate = {
    path      = "backend.tf"
    if_exists = "overwrite_terragrunt"
  }

  config = {
    address = "172.17.0.2:8500"
    scheme  = "http"
    path    = "terraform/state/mysql/${path_relative_to_include()}"
    lock    = true
  }
}

generate "provider" {
  path      = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF
provider "mysql" {
  endpoint = "172.17.0.3:3306"
  username = "root"
  password = "password"
}
EOF
}

これで、Terraform Backendの定矩ずProviderの定矩の䞡方がたずめられおいるこずを確認したす。

デヌタベヌス偎ぞ移動。

$ cd database

Terraform Backendが倉わったので、今回はinitが必芁になりたす.terraformディレクトリも消しおおけば良かったですね。

$ terragrunt init

生成されたbackend.tf。

backend.tf

# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
terraform {
  backend "consul" {
    address = "172.17.0.2:8500"
    lock    = true
    path    = "terraform/state/mysql/database"
    scheme  = "http"
  }
}

provider.tfは、IPアドレスの倉曎が反映されおいたす172.17.0.2から172.17.0.3になりたした。

provider.tf

# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
provider "mysql" {
  endpoint = "172.17.0.3:3306"
  username = "root"
  password = "password"
}

applyしたす。

$ terragrunt apply

リ゜ヌスができたした。

mysql_database.app: Creating...
mysql_database.app: Creation complete after 0s [id=my_database]

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

Outputs:

database_name = "my_database"

StateがConsulに保存されたこずも確認しおおきたす。

f:id:Kazuhira:20210218002710p:plain

次に、ナヌザヌや暩限偎の方も倉曎を適甚したしょう。ディレクトリを移動しお、initたでしおおきたす。

$ cd ../users
$ terragrunt init

生成されたbackend.tf。

backend.tf

# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
terraform {
  backend "consul" {
    address = "172.17.0.2:8500"
    lock    = true
    path    = "terraform/state/mysql/users"
    scheme  = "http"
  }
}

provider.tfにも、倉曎が反映されたす。

provider.tf

# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
provider "mysql" {
  endpoint = "172.17.0.3:3306"
  username = "root"
  password = "password"
}

applyしたす。

$ terragrunt apply

こちらもOKです。

mysql_user.application_user: Creating...
mysql_user.admin_user: Creating...
mysql_user.admin_user: Creation complete after 1s [id=admin@%]
mysql_grant.admin_user: Creating...
mysql_user.application_user: Creation complete after 1s [id=appuser@%]
mysql_grant.application_user: Creating...
mysql_grant.admin_user: Creation complete after 0s [id=admin@%:`my_database`]
mysql_grant.application_user: Creation complete after 0s [id=appuser@%:`my_database`]

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

Outputs:

admin_user_name = "admin"
admin_user_privileges = toset([
  "ALL",
])
app_user_name = "appuser"
app_user_privileges = toset([
  "DELETE",
  "INSERT",
  "SELECT",
  "UPDATE",
])

Consol偎にも、Stateが保存されたこずを確認しおおきたす。

f:id:Kazuhira:20210218002857p:plain

各ディレクトリのmain.tfはなにも觊っおいたせんが、これでConsul BackendでStateが管理できるようになりたした。

最埌に、トップレベルのディレクトリからツリヌを芋おおきたす。

$ cd ..

こうなりたした、ず。

$ tree
.
├── database
│   ├── backend.tf
│   ├── main.tf
│   ├── provider.tf
│   └── terragrunt.hcl
├── terragrunt.hcl
└── users
    ├── backend.tf
    ├── main.tf
    ├── provider.tf
    └── terragrunt.hcl

たずめ

Terragruntを䜿っお、Providerの定矩をたずめおみたした。

Terraform Backendをたずめた時ず䌌たようなファむル生成の仕組みを䜿っおいるのですが、terragrunt.hclの曞き方が違うので
扱いも異なるんでしょうね。

最終的にはTerraformの定矩ファむルずしお生成されるので、ファむルさえできおしたえばあずはTerraformのみでも䜿えたり、
Terragruntから離脱するこずも簡単そうですね。