広告

Terraform-input変数

GCP

Terraformには、内部で変数を定義し、外部から変数を渡すことが可能です。

変数の定義

input変数の定義は、variableブロックで定義します。

書き方:

variable "<変数名>" {
  # ...
}
  • <変数名>は以下の文字列以外、任意の文字列が使用可能です。
    • source
    • version
    • providers
    • count
    • for_each
    • lifecycle
    • depends_on
    • locals

input変数使用例

terraform applyを実行するための準備をし、以下の設定ファイルを用意します。

# image_name変数の定義。"image_name"は変数名
# 変数のデータ型はstring
# デフォルト値は"debian-cloud/debian-9"
variable "image_name" {
  type        = string
  default     = "debian-cloud/debian-9"
  description = "the image name"
}

provider "google" {
    project = "test-project"
    region = "asia-northeast1"
    zone = "asia-northeast1-a"
}

resource "google_compute_instance" "vm_instance" {
    name = "terraform-instance"
    machine_type = "f1-micro"

    boot_disk {
        initialize_params {
            image = var.image_name  # 変数の呼び出し
        }
    }

    network_interface {
        network = "default"
        access_config {
        }
    }
}

コマンドで変数を代入して、terraform applyを実行:
※他に代入する方法もあります、後程ご紹介します。

terraform apply -var="image_name=centos-cloud/centos-7"

これで、centos-7のGCEが作成されます。

変数のデータ型

Terraformは以下のデータ型の変数を定義可能

  • 単純なデータ型
    • string:文字列
    • number:数値
    • bool:True/False
  • 複雑なデータ型
    • list(<TYPE>):配列
      • 例:list(string)
    • set(<TYPE>)
    • map(<TYPE>)
    • object({<ATTR NAME> = <TYPE>, ... }):辞書型(key-value形式のデータ)
      • 例:object({foo = "hello", bar = "world"})
      • key-valueが改行で記述する場合、,は省略可能
    • tuple([<TYPE>, ...])

変数の呼び出し

モジュール(tfファイル)内で、変数を定義すると、定義した変数が呼び出し可能です。
使用時はvar.<変数名>で変数を呼び出します。

例:

resource "google_compute_instance" "vm_instance" {
    name = "terraform-instance"
    machine_type = "f1-micro"

    boot_disk {
        initialize_params {
            image = var.image_name  # 変数の呼び出し
        }
    }

    network_interface {
        network = "default"
        access_config {
        }
    }
}

変数のデフォルト値(option)

変数の定義で、変数のデフォルト値を設定することが可能です。
デフォルト値は、変数が外部からinputされなかった場合使用される値です。

例:

variable "image_name" {
  type        = string
  default     = "debian-cloud/debian-9"  # 変数imange_nameのデフォルト値は"debian-cloud/debian-9"
  description = "the image name"
}

変数の注釈(option)

変数の定義で、注釈を入れることが可能です。
variableブロック内に、descriptionを使って、記述します。また、変数の注釈はなくても問題ありません。

例:

variable "image_name" {
  type        = string
  default     = "debian-cloud/debian-9"
  description = "the image name"  # 注釈
}

変数チェック(option)

変数の定義で、変数値のチェックを定義することも可能です。
variableブロック内に、validationを使って、記述します。

  • 定義内容は以下2つです。
    • condition:ルール。
      • 条件合致の場合、trueを返します。
      • 条件満たさないの場合、falseを返します。同時に、tfチェックがエラーになります。
    • error_message:ルールに満たせなかった場合のエラーメッセージ
      • conditionがfalseの場合の出力内容

例:

variable "image_name" {
  type        = string
  description = "the image name"

  # 変数チェック
  validation {
    # 条件:image_nameの長さが4桁以上、かつ最初の7桁が"debian-"であること
    condition     = length(var.image_name) > 7 && substr(var.image_name, 0, 7) == "debian-"
    error_message = "The image_name value must be a valid name, starting with \"debian-\"."  # ここのエスケープにご注意
  }
}

変数チェックの使用条件

This is an experimental language feature that currently requires an explicit opt-in using the experiment keyword variable_validation:

変数チェックはデフォルトでは使用不可です。使用するには、terraformブロックにて、以下の内容を記述する必要があります。

terraform {
  experiments = [variable_validation]
}

can()とregex():正規表現の使用

can() evaluates the given expression and returns a boolean value indicating whether the expression produced a result without any errors.

can()は、()内の処理がエラーが返したらfalse、正常終了したらtrueが返すfunctionです。
regex()は、正規表現を使用ためのfunctionです。

例:

variable "image_name" {
  type        = string
  description = "the image name"

  # 変数チェック
  validation {
    # 正規表現で変数チェックを行う
    condition     = can(regex("debian-", var.image_name))
    error_message = "The image_name value must be a valid name, starting with \"debian-\"."  # ここのエスケープにご注意
  }
}

変数の代入方法

This section does not apply to child modules, where values for input variables are instead assigned in the configuration of their parent module, as described in Modules.
上記引用の通り、変数のinputはrootモジュールのみに行えるので、注意していください。

  • 変数の値をroot モジュールに入れる場合、以下の方法があります
    • -varオプションで個別指定
    • .tfvarsファイルを使って一括導入
      • -var-fileオプションで指定
      • 固定ファイル名を指定
    • 環境変数で導入
    • *In a Terraform Cloud workspace

-varオプションで個別指定

terraform planterraform applyコマンドの実行時に指定します。
例:

# image_nameの値をcentos-cloud/centos-7に指定
terraform apply -var="image_name=centos-cloud/centos-7"

# image_name_listの値を["centos-cloud/centos-7","centos-cloud/centos-8"]に指定
terraform apply -var='image_name_list=["centos-cloud/centos-7","centos-cloud/centos-8"]'

# image_name_mapの値を{"centos7":"centos-cloud/centos-7","centos8":"centos-cloud/centos-8"}に指定
terraform apply -var='image_name_map={"centos7":"centos-cloud/centos-7","centos8":"centos-cloud/centos-8"}'

.tfvarsファイルを使って一括導入

ファイルの拡張子が.tfvars.tfvars.jsonのファイルが変数定義用ファイルとなります。
基本的に、terraform planterraform applyコマンドの実行時に-var-fileオプションでファイルを指定します。
例:

terraform apply -var-file="test.tfvars"

test.tfvarsファイルの中身:

# image_nameの変数値、object型
image_name = {
    centos = "centos-cloud/centos-7"
    debian = "debian-cloud/debian-9"
}
# availability_zone_namesの変数値、list型
availability_zone_names = [
  "asia-northeast1-a",
  "asia-northeast1-b",
]

terraformの設定ファイルの中身:

# 変数の定義:object型
variable "image_name" {
  type        = object({
      centos = string
      debian = string
  })
  default     = {
      centos = "centos-cloud/centos-8"
      debian = "debian-cloud/debian-10"
  }
  description = "the image name"
}

# 変数の定義:list型
variable "availability_zone_names" {
  type        = list(string)
  default     = ["asia-northeast1-a"]
  description = "description"
}

provider "google" {
    project = "test-project"
    region = "asia-northeast1"
    zone = "asia-northeast1-a"
}

resource "google_compute_instance" "vm_instance" {
    name = "terraform-instance"
    machine_type = "f1-micro"
    zone = var.availability_zone_names[0]  # 変数の呼び出し

    boot_disk {
        initialize_params {
            image = var.image_name.centos  # 変数の呼び出し
        }
    }

    network_interface {
        network = "default"
        access_config {
        }
    }
}

resource "google_compute_instance" "vm_instance_test" {
    name = "terraform-instance-test"
    machine_type = "f1-micro"
    zone = var.availability_zone_names[1]  # 変数の呼び出し

    boot_disk {
        initialize_params {
            image = var.image_name.debian  # 変数の呼び出し
        }
    }

    network_interface {
        network = "default"
        access_config {
        }
    }
}

また、terraformは自動的に以下のファイル名のファイルをロードするようになっています。

  • terraform.tfvars または terraform.tfvars.json
  • 任意の拡張子が .auto.tfvars または .auto.tfvars.jsonのファイル

Files whose names end with .json are parsed instead as JSON objects, with the root object properties corresponding to variable names
拡張子が.jsonで終わるファイルは、json形式で書く必要があります。

環境変数で導入

環境変数で導入する場合、環境変数の変数名はTF_VAR_<Terraform変数名>の形式になります。

例えば、image_name変数に値を渡す場合、環境変数名はTF_VAR_image_nameにすればいいです。

使用例:

# 環境変数を定義
export TF_VAR_image_name=centos-cloud/centos-7
# terraform planを実行
terraform plan
...

複雑なデータ型の環境変数

上記例の通り、環境変数で定義する場合、string型の値は特に''""なしでも問題ありませんでした。
これはシンプルなデータ型(string,number,bool)は全部同じです。

ただ、複雑なデータ型(list,set,map,object,tuple)の場合は''""が必要です。
この場合、値は.tfvarsのファイル内容として解析しますので、エスケープについて注意が必要です。

例:

export TF_VAR_availability_zone_names='["asia-northeast1-a","asia-northeast1-b"]'

For readability, and to avoid the need to worry about shell escaping, we recommend always setting complex variable values via variable definitions files.
エスケープなどで意図しない動作を避けるために、.tfvarsファイルを使用するのを推奨されています。

コメント

タイトルとURLをコピーしました