Local Valuesとは
公式によると、
- local values というものを普通のプログラミング言語に照らし合わせて考えると、、、
-
variableが関数のargumentに相当 -
outputが関数のreturn valueに相当 - では
locals(=local variables)は・・・というと関数内スコープの変数に相当
-
・・・だそうですがよくわからなかったのでいろいろ検証したり調べたりしてみました。
ちなみに Local Values であり、 Local Variables ではありません。
検証したりドキュメントを読んで理解したこと
(自身が理解した内容の範囲ですが)結論から書くと、
- variableブロックのdefault値には Interpolation Syntax が使えないが、localsブロックではそれが可能
- 影響範囲/利用範囲がモジュール内のスコープにとどまる
- 例えば作業ディレクトリのtfファイル間では共用可能だが、moduleに同名の変数が合ってもそれは利用できない・・・というような
-
-var等により外部から与えることは出来ない
では、1つずつ見ていきます。
1. localsでは Interpolation Syntax が使える
local values を使った場合
例えば、以下のような内容は成立します。
main.tf
variable "is_prod" {
type = "string"
default = "false"
}
locals {
keyname = "${var.is_prod ? "prod-key": "stage-key"}"
}
resource "ecl_compute_keypair_v2" "keypair_1" {
name = "${local.keyname}-1"
}
この状態で、 is_prod を true にするとこうなります。
% terraform apply -var 'is_prod=true'
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:
+ ecl_compute_keypair_v2.keypair_1
id: <computed>
fingerprint: <computed>
name: "prod-key-1"
private_key: <computed>
public_key: <computed>
region: <computed>
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:
逆に、 is_prod を false にする(というか与えない)とこうなります。
% terraform apply
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:
+ ecl_compute_keypair_v2.keypair_1
id: <computed>
fingerprint: <computed>
name: "stage-key-1"
private_key: <computed>
public_key: <computed>
region: <computed>
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:
localsに書いた3項演算子が正しく動作していることがわかると思います。
variableを使った場合
もしこれと同じことをvariableでやるとエラーになります。
variable "is_prod" {
type = "string"
default = "false"
}
variable "keyname" {
type = "string"
default = "${var.is_prod ? "prod-key": "stage-key"}"
}
resource "ecl_compute_keypair_v2" "keypair_1" {
name = "${local.keyname}-1"
}
上記の様なtfファイルを利用して terraform apply すると以下のようなエラーとなります。
% terraform apply
Error: variable "keyname": default may not contain interpolations
2. 影響範囲がモジュールスコープにとどまる
以下のようなディレクトリ構造を考えます。
.
├── main.tf
├── modules
│ └── main.tf
└── provider.tf <-- 認証系の情報はココに書いてあると仮定して説明は割愛
ファイルの内容は以下のようになっています。
main.tf
module "keypair" {
source = "./modules"
is_prod = "${var.is_prod}"
}
variable "is_prod" {
type = "string"
default = "false"
}
locals {
"keyname" = "${var.is_prod ? "prod-key-main" : "stage-key-main"}"
}
resource "ecl_compute_keypair_v2" "keypair_1_main" {
name = "${local.keyname}"
}
modules/main.tf
variable "is_prod" {
type = "string"
default = "false"
}
locals {
"keyname" = "${var.is_prod ? "prod-key-module" : "stage-key-module"}"
}
resource "ecl_compute_keypair_v2" "keypair_1_module" {
name = "${local.keyname}"
}
ポイントは、
-
main.tfにも、modules/main.tfにも、同名のlocals.keynameが存在し、以下のように挙動に差分がある-
main.tfの方は、var.is_prodの値に応じて、prod-key-mainorstage-key-mainを返す処理が書いてある -
modules/main.tfの方は、var.is_prodの値に応じて、prod-key-moduleorstage-key-moduleを返す処理が書いてある -
is_prodはmain.tfからmodules/main.tfに伝搬するようになっている
-
です。
この状態で、 terraform apply します。
is_prod が false の場合の terraform apply 結果
% terraform apply -var 'is_prod=false'
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:
+ ecl_compute_keypair_v2.keypair_1_main
id: <computed>
fingerprint: <computed>
name: "stage-key-main" <-- main.tf側のlocals.keynameの処理結果になっている
private_key: <computed>
public_key: <computed>
region: <computed>
+ module.keypair.ecl_compute_keypair_v2.keypair_1_module
id: <computed>
fingerprint: <computed>
name: "stage-key-module" <-- module/main.tf側のlocals.keynameの処理結果になっている
private_key: <computed>
public_key: <computed>
region: <computed>
Plan: 2 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:
is_prod が true の場合の terraform apply 結果
% terraform apply -var 'is_prod=true'
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:
+ ecl_compute_keypair_v2.keypair_1_main
id: <computed>
fingerprint: <computed>
name: "prod-key-main" <-- main.tf側のlocals.keynameの処理結果になっている
private_key: <computed>
public_key: <computed>
region: <computed>
+ module.keypair.ecl_compute_keypair_v2.keypair_1_module
id: <computed>
fingerprint: <computed>
name: "prod-key-module" <-- module/main.tf側のlocals.keynameの処理結果になっている
private_key: <computed>
public_key: <computed>
region: <computed>
Plan: 2 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:
このようにmodule側に同名の関数が存在しても、処理が独立して行われているのがわかります。
まさにlocalスコープの関数のようなイメージですね。
3. -var 等により外部から与えることは出来ない
言わずもがなですがやってみます。 ![]()
今度は main.tf 単体で事が足ります。
locals {
keyname = ""
}
resource "ecl_compute_keypair_v2" "keypair_1_main" {
name = "${local.keyname == "" ? "empty" : "specified" }"
}
ここで terraform apply 。
% terraform apply -var 'keyname=localkeyname'
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:
+ ecl_compute_keypair_v2.keypair_1_main
id: <computed>
fingerprint: <computed>
name: "empty" <-- 付与された扱いになっていない
private_key: <computed>
public_key: <computed>
region: <computed>
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:
ということで外から与えられませんよーということですね。
以上、 local values について調べてみました。