はじめに
夢と発想と情熱の会社でSREやっている人です。
terragruntのビルトイン関数をなんとなーくで利用しているので、この際に動作を確認してみようという内容になります。
発想の会社なのにネタの発想がしょぼいとかは言ってはいけません
確認方法
terragruntではterraformのようにterraform consoleが使えないので、適当にterragrunt.hclを用意し
locals {
test_account_id = get_aws_account_id()
}
inputs = {
debug_output = local.test_account_id
}
のようなコードを書いてterragrunt render --format jsonを実行し、標準出力にjsonで出力して動きを確かめていきます。
確認してみた
find_in_parent_folders
実行
locals {
check = find_in_parent_folders("terragrunt.hcl")
}
inputs = {
debug_output = local.check
}
ディレクトリ構成は下記を想定し、dev/web配下でコマンドを実行します。
terragrunt_built_in_function
├── dev
│ └── web
│ └── terragrunt.hcl
└── terragrunt.hcl
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": /path/to/terragrunt_built_in_function/terragrunt.hcl"
}
指定した名前のファイルを親方向に遡って検索し、1番最初に見つかったファイルの絶対パスを返してくれます。
見つからない場合はエラーを返します。
path_relative_to_include
実行
include "root" {
path = find_in_parent_folders("root.hcl")
}
locals {
check = path_relative_to_include()
}
inputs = {
debug_output = local.check
}
ディレクトリ構成は下記を想定し、dev/web配下でコマンドを実行します。
terragrunt_built_in_function
├── dev
│ └── web
│ └── terragrunt.hcl
└── root.hcl
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "dev/web"
}
dev/web/terragrunt.hcl内でincludeされているroot.hclからinclude元のdev/web/terragrunt.hclへの相対パスを返してくれます。
path_relative_from_include
実行
include "root" {
path = find_in_parent_folders("root.hcl")
}
locals {
check = path_relative_from_include()
}
inputs = {
debug_output = local.check
}
ディレクトリ構成は下記を想定し、dev/web配下でコマンドを実行します。
terragrunt_built_in_function
├── dev
│ └── web
│ └── terragrunt.hcl
└── root.hcl
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "../.."
}
path_relative_to_includeと対になる関数です。
include元のdev/web/terragrunt.hclからinclude先のroot.hclへの相対パスを返してくれます。
get_env
実行
locals {
check = get_env("MY_ENV", "default")
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ export MY_ENV="test"
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "test"
}
❯ unset MY_ENV
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "default"
}
第一引数に指定した環境変数を返してくれます。
環境変数がない場合は、第二引数の値を返してくれます。
環境変数がない&第二引数の指定もない場合はエラーとなります。
get_platform
実行
locals {
check = get_platform()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "darwin"
}
関数名のとおり、実行環境のOSを返してくれます。
get_repo_root
実行
locals {
check = get_repo_root()
}
inputs = {
debug_output = local.check
}
ディレクトリ構成は下記を想定し、dev/web配下でコマンドを実行します。
terragrunt_built_in_function
├── dev
│ └── web
│ └── terragrunt.hcl
└── root.hcl
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "/path/to/terragrunt_built_in_function"
}
git管理している前提の関数です。
リポジトリルートの絶対パスを返してくれます。
get_path_from_repo_root
実行
locals {
check = get_path_from_repo_root()
}
inputs = {
debug_output = local.check
}
ディレクトリ構成は下記を想定し、dev/web配下でコマンドを実行します。
terragrunt_built_in_function
├── dev
│ └── web
│ └── terragrunt.hcl
└── root.hcl
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "dev/web"
}
こちらもgit管理している前提の関数です。
リポジトリルートから実行ディレクトリへの相対パスを返してくれます。
get_path_to_repo_root
実行
locals {
check = get_path_to_repo_root()
}
inputs = {
debug_output = local.check
}
ディレクトリ構成は下記を想定し、dev/web配下でコマンドを実行します。
terragrunt_built_in_function
├── dev
│ └── web
│ └── terragrunt.hcl
└── root.hcl
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "../.."
}
get_path_from_repo_rootの対になる関数です。
実行ディレクトリからリポジトリルートへの相対パスを返してくれます。
git管理している前提です。
get_terragrunt_dir
実行
locals {
check = get_terragrunt_dir()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "/path/to/terragrunt_built_in_function/dev/web"
}
実行しているterragrunt.hclのあるディレクトリへの絶対パスを返してくれます。
get_working_dir
実行
locals {
check = get_working_dir()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "/path/to/terragrunt_built_in_function/dev/web"
}
コマンドを実行しているディレクトリの絶対パスを返してくれます。
dev/webに移動してからコマンドを実行しているので、/path/to/terragrunt_built_in_function/dev/webが返されています。
get_parent_terragrunt_dir
実行
include "root" {
path = find_in_parent_folders("root.hcl")
}
locals {
check = get_parent_terragrunt_dir()
}
inputs = {
debug_output = local.check
}
ディレクトリ構成は下記を想定し、dev/web配下でコマンドを実行します。
terragrunt_built_in_function
├── dev
│ └── web
│ └── terragrunt.hcl
└── root.hcl
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "/path/to/terragrunt_built_in_function"
}
親設定ファイルがあるディレクトリの絶対パスを返してくれるようです。
includeしているファイルの存在するディレクトリの絶対パスといイメージでしょうか。
get_original_terragrunt_dir
実行
locals {
root_check = get_original_terragrunt_dir()
}
include "root" {
path = find_in_parent_folders("root.hcl")
expose = true
}
locals {
check = get_original_terragrunt_dir()
}
inputs = {
debug_output = local.check
debug_output2 = include.root.locals.root_check
}
ディレクトリ構成は下記を想定し、dev/web配下でコマンドを実行します。
terragrunt_built_in_function
├── dev
│ └── web
│ └── terragrunt.hcl
└── root.hcl
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "/path/to/terragrunt_built_in_function/dev/web",
"debug_output2": "/path/to/terragrunt_built_in_function/dev/web"
}
実行ファイルがあるディレクトリの絶対パスを返してくれます。
includeされているファイル内で関数を呼んでも、実行ファイルのあるディレクトリが返されています。
get_terraform_commands_that_need_vars
実行
locals {
check = get_terraform_commands_that_need_vars()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": [
"apply",
"console",
"destroy",
"import",
"plan",
"push",
"refresh"
]
}
terragruntでterraformブロック内のextra_argumetsブロックに-varや-var-fileを利用する場合に使えるようです。
-varや-var-fileを受け付けるコマンドのリストを返してくれます。
いちいち手書きせずに関数1つでかけるという感じでしょうか。
get_terraform_commands_that_need_input
実行
locals {
check = get_terraform_commands_that_need_input()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": [
"apply",
"import",
"init",
"plan",
"refresh"
]
}
こちらは get_terraform_commands_that_need_vars の-input版です。
-inputを受け付けるコマンドのリストを返してくれます。
get_terraform_commands_that_need_locking
実行
locals {
check = get_terraform_commands_that_need_locking()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": [
"apply",
"destroy",
"import",
"plan",
"refresh",
"taint",
"untaint"
]
}
こちらは get_terraform_commands_that_need_vars の-lock-timeout版です。
-lock-timeoutを受け付けるコマンドのリストを返してくれます。
get_terraform_commands_that_need_parallelism
実行
locals {
check = get_terraform_commands_that_need_parallelism()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": [
"apply",
"plan",
"destroy"
]
}
こちらは get_terraform_commands_that_need_vars の-parallelism版です。
-parallelismを受け付けるコマンドのリストを返してくれます。
get_aws_account_alias
実行
locals {
check = get_aws_account_alias()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "hogehoge"
}
現在設定されているAWSアカウントのエイリアス名を返してくれます。
get_aws_account_id
実行
locals {
check = get_aws_account_id()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "1234567890"
}
現在設定されているAWSアカウントのアカウントIDを返してくれます。
get_aws_caller_identity_arn
実行
locals {
check = get_aws_caller_identity_arn()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "arn:aws:sts::1234567890:assumed-role/hogeAccess/hoge"
}
現在設定されているアイデンティティのARNを返してくれます。
get_terraform_command
実行
locals {
check = get_terraform_command()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "render"
}
実行中のterraformコマンドを返してくれます。
get_terraform_cli_args
実行
locals {
check = get_terraform_cli_args()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": [
"render"
]
}
実行中のterraformコマンドのCLI引数を返してくれるそうです。
(よくわかってない...)
get_default_retryable_errors
実行
locals {
check = get_default_retryable_errors()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": [
"(?s).*Failed to load state.*tcp.*timeout.*",
"(?s).*Failed to load backend.*TLS handshake timeout.*",
"(?s).*Creating metric alarm failed.*request to update this alarm is in progress.*",
"(?s).*Error installing provider.*TLS handshake timeout.*",
"(?s).*Error configuring the backend.*TLS handshake timeout.*",
"(?s).*Error installing provider.*tcp.*timeout.*",
"(?s).*Error installing provider.*tcp.*connection reset by peer.*",
"NoSuchBucket: The specified bucket does not exist",
"(?s).*Error creating SSM parameter: TooManyUpdates:.*",
"(?s).*app.terraform.io.*: 429 Too Many Requests.*",
"(?s).*ssh_exchange_identification.*Connection closed by remote host.*",
"(?s).*Client\\.Timeout exceeded while awaiting headers.*",
"(?s).*Could not download module.*The requested URL returned error: 429.*",
"(?s).*net/http: TLS.*handshake timeout.*"
]
}
terragruntが再試行可能なエラーパターンのデフォルトのリストを返してくれるようです。
get_aws_caller_identity_user_id
実行
locals {
check = get_aws_caller_identity_user_id()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "hogefuga:piyo"
}
現在設定されているAWSアカウントのユーザーIDを返してくれます。
run_cmd
実行
locals {
check = run_cmd("./sample.sh", "sample dayo!!")
}
inputs = {
debug_output = local.check
}
dev/web/terragrunt.hclと同じディレクトリにsample.shを用意し、dev/web配下でjqを使用せずにterraform renderコマンドを実行します。
sample.shの中身は下記になります。
#!/bin/sh
echo "$1"
結果
❯ terragrunt render
sample dayo!!
locals {
check = "sample dayo!!"
}
inputs = {
debug_output = "sample dayo!!"
}
シェルコマンドを実行してくれます。
第二引数以降はシェルに渡す引数を指定できます。
jqを使用しなかったのは実行結果が標準出力されるからになります。
read_terragrunt_config
実行
locals {
common_vars = read_terragrunt_config(find_in_parent_folders("common.hcl"))
check = "hoge"
}
inputs = merge(
local.common_vars.inputs,
{
debug_output = local.check
}
)
追加でプロジェクトルートにcommon.hclを作成します。
中身は下記です。
inputs = {
arg1 = "hoge"
arg2 = "fuga"
}
ディレクトリ構成は下記を想定し、dev/web配下でコマンドを実行します。
terragrunt_built_in_function
├── dev
│ └── web
│ └── terragrunt.hcl
└── common.hcl
結果
❯ terragrunt render --format json | jq .inputs
{
"arg1": "hoge",
"arg2": "fuga",
"debug_output": "hoge"
}
指定したterragrunt設定を解析し、設定値を参照できるようにしてくれる関数です。
共通変数を設定したいときに便利そうなイメージです。
sops_decrypt_file
実行
locals {
check = yamldecode(sops_decrypt_file(find_in_parent_folders("secrets.yml")))
}
inputs = local.check
プロジェクトルートにsopsとKMSを利用して暗号化したyamlファイルを配置しておきます。
ディレクトリ構成は下記を想定し、dev/web配下でコマンドを実行します。
terragrunt_built_in_function
├── dev
│ └── web
│ └── terragrunt.hcl
├── secrets.yml
└── .sops.yaml
結果
❯ terragrunt render --format json | jq .inputs
{
"arg1": "hoge",
"arg2": "fuga"
}
sopsで暗号化されたyamlなどを復号化してくれます。
暗号化したい内容がある場合に利用できそうです。
get_terragrunt_source_cli_flag
実行
locals {
check = get_terragrunt_source_cli_flag()
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": ""
}
❯ export TG_SOURCE=debug
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "debug"
}
--sourceオプションか環境変数TG_SOURCEの値を返すようです。
ともに指定がない場合は空の文字列が返されます。
一時的なフラグ利用のような使い方を想定しているようです。
read_tfvars_file
実行
locals {
check = jsondecode(read_tfvars_file(find_in_parent_folders("common.tfvars")))
}
inputs = local.check
追加でプロジェクトルートにcommon.tfvarsを作成します。
中身は下記です。
arg1 = "hoge"
arg2 = "fuga"
ディレクトリ構成は下記を想定し、dev/web配下でコマンドを実行します。
terragrunt_built_in_function
├── dev
│ └── web
│ └── terragrunt.hcl
└── common.tfvars
結果
❯ terragrunt render --format json | jq .inputs
{
"arg1": "hoge",
"arg2": "fuga"
}
.tfvarsファイルを読み込み、変数のマップを返してくれます。
tfvarsを利用する場合に使う関数になりそうです。
mark_as_read
実行
locals {
check = mark_as_read("/path/to/terragrunt_built_in_function/read_file.txt")
}
inputs = {
debug_output = local.check
}
追加でプロジェクトルートにread_file.txtを作成します。
中身は空です。
ディレクトリ構成は下記を想定し、dev/web配下でコマンドを実行します。
terragrunt_built_in_function
├── dev
│ └── web
│ └── terragrunt.hcl
└── read_file.txt
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": "/path/to/terragrunt_built_in_function/read_file.txt"
}
初見でよくわからない関数でしたが、調べたところ依存関係を明示するための関数のようです。
指定したファイルが変更されたときに、変更されたことを検知できるように使用するみたいです。
constraint_check
実行
locals {
my_version = "1.0.0"
check = constraint_check(local.my_version, ">= 2.0.0")
}
inputs = {
debug_output = local.check
}
dev/web配下でコマンドを実行します。
結果
❯ terragrunt render --format json | jq .inputs
{
"debug_output": false
}
第一引数に指定した値が、第二引数に指定した条件を満たしているかチェックする関数のようです。
my_versionの値を2.0.1に変更するとtrueに変わります。
バージョンに応じて渡す変数を変化させたい、のようなときに使えるようです。
まとめ
ざっとterragruntの関数を試してみました。
便利そうなものから、どう使うんだ...まで色々あるなという印象を受けましたが、
terragruntの関数「完全に理解した」ぐらいになれればいいなと思います!
よいterragruntライフを!