2つの店、1つのレシピ
会社が駅前の店と丘の上の店を持っています。どちらも同じ設定が必要です。ファイルをコピーすれば動きますが、直すときは2回直すことになります。
モジュールは、1回だけ書いたレシピです。それぞれの店が自分の値を渡して呼び出します。
このレッスンのゴール
メモ
モジュールを2回呼び出し、それぞれのコピーが返す値を読める。
重要な言葉
| ことば | いみ | れい |
|---|---|---|
| モジュール | 再利用できるファイルの入ったフォルダ | |
| モジュール呼び出し | モジュールを使い、値を渡すブロック | module "hill" |
| 出力 | モジュールが返す値 | output |
| 検証 | 悪い入力を断るルール | validation |
| モジュールのアドレス | module で始まる、リソースの道筋 | module.hill.terraform_data.sign |
学生が入力するセルは、このプレビューでは空白です。
モジュールは呼び出すフォルダ
モジュールは、OpenTofu のファイルが入ったフォルダです。それを使う側のプロジェクトをルートと呼びます。ルートはモジュール呼び出しを書き、source にフォルダを指定し、入力に値を渡します。
2回呼び出すと、フォルダの中身が別々に2つ作られます。ここでは source がローカルの道筋なので、何もダウンロードしません。
フォルダを作って入る
mkdir -p ~/iac-demo/mods/modules/shop && cd ~/iac-demo/modsここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
モジュールを書く
printf '%s\n' 'variable "name" {' ' type = string' ' validation {' ' condition = length(var.name) >= 3 && length(var.name) <= 10' ' error_message = "名前は3文字から10文字にしてください。"' ' }' '}' '' 'resource "terraform_data" "sign" {' ' input = format("%s: 営業中", var.name)' '}' '' 'output "sign" {' ' value = terraform_data.sign.output' '}' > modules/shop/main.tfここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ルートを書く: 呼び出し2つと出力1つ
printf '%s\n' 'module "corner" {' ' source = "./modules/shop"' ' name = "Corner"' '}' '' 'module "hill" {' ' source = "./modules/shop"' ' name = "Hill"' '}' '' 'output "signs" {' ' value = [module.corner.sign, module.hill.sign]' '}' > main.tfここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
フォルダを準備する
tofu init -no-color | grep -E "Initializing modules|corner|hill|successfully"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
planを出してアドレスを見る
tofu plan -no-color | grep -E "will be created|^Plan"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
モジュールは出力で値を返す
モジュールの中のリソースには、module.hill.terraform_data.sign のような長いアドレスがつきます。ルートはそれを直接は読めません。
壁を越えられるのは出力だけです。ルートは module.hill.sign と読みます。呼び出しの名前、続けて出力の名前です。
applyして2つをstateに入れる
tofu apply -auto-approve -no-color | grep "Apply complete"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
stateのアドレスを一覧する
tofu state listここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ルートの出力を読む
tofu output signsここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
よくある間違い
注意
ルートはモジュール内のどのリソースでも読める、と考える人が多くいます。読めません。モジュールが共有するのは出力に書いた値だけです。外で使いたい値には output ブロックが必要です。
出力のないリソースを読む
printf '%s\n' 'output "bad" {' ' value = module.corner.terraform_data.sign' '}' > bad.tf; tofu validate -no-color 2>&1 | grep -E "Error|Unsupported"; rm bad.tfここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
検証は悪い入力を断る
validation ブロックには condition と error_message があります。条件が偽なら、OpenTofu は何も計画しないうちに止まり、メッセージを表示します。
このモジュールは3文字から10文字の名前を受け付けます。短すぎる名前を試しましょう。
丘の店に短い名前をつける
sed -i 's/"Hill"/"Hi"/' main.tf; tofu validate -no-color 2>&1 | grep -E "Error|文字から"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
名前を戻して確認する
sed -i 's/"Hi"/"Hill"/' main.tf; tofu validate -no-colorここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
2つの呼び出しをPythonで計算
# モジュールの呼び出しが作るアドレスを計算します。
resources = ["sign", "door"]
calls = {"corner": None, "hill": None}
for call in calls:
for name in resources:
print("module." + call + ".terraform_data." + name)
# "hill": None を "hill": ["a", "b"] に変えて、もう一度見てみましょう。
ラボでやってみる
Run では、練習用のフォルダにモジュールを作りました。ラボにもそのためのフォルダ ~/tofu-lab/shop があり、README (英語) のパート7に作るものが書かれています。同じモジュールではないので、見たものを写さず、直して作ります。
採点の仕組み
先生は、保存したラボに対してチェックを実行して採点します。チェックはあなたのプロジェクトを適用し、そのあと、あなたが一度も見ていない名前とステータスで、あなたのモジュールをもう一度呼び出します。答えを書き込んだモジュールには従えません。検証ルールのないモジュールも同じです。
さらに進む: countつきの呼び出し
hill の呼び出しに count = 2 を足し、出力の module.hill.sign を module.hill[0].sign に変えます。そして tofu plan -no-color | grep -E "will be|^Plan" を実行します。
planはどのアドレスを表示しますか。出力の行を変える必要があったのはなぜですか。