18
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

TerraformのLocal Valuesについてよくわからなかったので検証してみた

Last updated at Posted at 2019-05-27

Local Valuesとは

公式によると、

  • local values というものを普通のプログラミング言語に照らし合わせて考えると、、、
    • variable が関数のargumentに相当
    • output が関数のreturn valueに相当
    • では locals(=local variables) は・・・というと関数内スコープの変数に相当

・・・だそうですがよくわからなかったのでいろいろ検証したり調べたりしてみました。

ちなみに Local Values であり、 Local Variables ではありません。

検証したりドキュメントを読んで理解したこと

(自身が理解した内容の範囲ですが)結論から書くと、

  1. variableブロックのdefault値には Interpolation Syntax が使えないが、localsブロックではそれが可能
  2. 影響範囲/利用範囲がモジュール内のスコープにとどまる
    • 例えば作業ディレクトリのtfファイル間では共用可能だが、moduleに同名の変数が合ってもそれは利用できない・・・というような
  3. -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_prodtrue にするとこうなります。

% 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_prodfalse にする(というか与えない)とこうなります。

% 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-main or stage-key-main を返す処理が書いてある
    • modules/main.tf の方は、 var.is_prod の値に応じて、 prod-key-module or stage-key-module を返す処理が書いてある
    • is_prodmain.tf から modules/main.tf に伝搬するようになっている

です。

この状態で、 terraform apply します。

is_prodfalse の場合の 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_prodtrue の場合の 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 等により外部から与えることは出来ない

言わずもがなですがやってみます。 :sweat:

今度は 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 について調べてみました。

18
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?