自由気ままに書いちゃおう

好きなことをつらつらと・・・

【Terraform】(初心者向け) values関数を使って値だけを取り出す

今回は、values式についてです。

values式について

https://developer.hashicorp.com/terraform/language/functions/values

values式は、マップやオブジェクトからその値を抽出し、リストとして返す関数です。

マップやオブジェクトのキーが不要で、値だけを使用したい場合に便利です。

以下に基本的な使用例を示します。

variable "map_variable" {
  default = {
    key1 = "value1"
    key2 = "value2"
    key3 = "value3"
  }
}

output "values_output" {
  value = values(var.map_variable)
}

上記のコードを実行すると、以下のような結果が得られます。

values_output = [
  "value1",
  "value2",
  "value3",
]

このようにvalues式はマップの値をリスト形式で取り出すことができます。

values関数とfor式の組み合わせについて

values関数とfor式を組み合わせると以下のようなことができます。

variable "instances" {
  default = {
    instance1 = "t3.micro"
    instance2 = "t3.small"
    instance3 = "t3.medium"
  }
}

locals {
  large_instances = [for v in values(var.instances) : v if v == "t3.medium"]
}

output "large_instances" {
  value = local.large_instances
}

このコードを実行すると、large_instancesの出力にはvar.instancesの中で"t3.medium"という値を持つ要素だけが含まれます。

つまり、この例では出力結果は["t3.medium"]となります。

このように、values関数とfor式を組み合わせることで、特定の条件を満たす値だけを選択的に操作することが可能になります。

以降はサンプルコードです。

1. EC2の作成

variable "instances" {
  default = {
    instance1 = "t3.micro"
    instance2 = "t3.small"
    instance3 = "t3.medium"
  }
}

resource "aws_instance" "example" {
  count = length(var.instances)
  instance_type = values(var.instances)[count.index]
  ami = "ami-0abcdef1234567890" # 適切なAMI IDを指定してください。

  tags = {
    Name = keys(var.instances)[count.index]
  }
}

上記のコードでは、マップ型の変数instancesにEC2インスタンスの名前とタイプを指定しています。

その後、values式とkeys式を用いてそれぞれインスタンスタイプ(values関数を利用。)とタグの名前(keys関数を利用。)を取り出しています。

2. Amazon S3バケットの作成

variable "buckets" {
  default = {
    bucket1 = "my-first-bucket"
    bucket3 = "my-second-bucket"
    bucket3 = "my-third-bucket"
  }
}

resource "aws_s3_bucket" "example" {
  count  = length(var.buckets)
  bucket = values(var.buckets)[count.index]

  tags = {
    Name = keys(var.buckets)[count.index]
  }
}

このコードを実行すると、my-first-bucketmy-second-bucketmy-third-bucketの名前を持つ3つのS3バケットが作成されます。

それぞれのバケットにはNameタグとしてbucket1bucket3bucket3が付与されます。

3. Amazon RDSデータベースの作成

variable "databases" {
  default = {
    db1 = "db.t3.micro"
    db2 = "db.t3.small"
    db3 = "db.t3.medium"
  }
}

resource "aws_db_instance" "example" {
  count                       = length(var.databases)
  identifier                  = keys(var.databases)[count.index]
  instance_class              = values(var.databases)[count.index]
  engine                      = "mysql"
  engine_version              = "5.7"
  allocated_storage           = 20
  username                    = "admin"
  password                    = "password"
  skip_final_snapshot         = true
}

このコードを実行すると、db.t3.microdb.t3.smalldb.t3.mediumのインスタンスクラスを持つ3つのRDSデータベースが作成されます。

4. サブネットの作成

variable "subnets" {
  default = {
    subnet1 = "10.0.1.0/24"
    subnet2 = "10.0.2.0/24"
    subnet3 = "10.0.3.0/24"
  }
}

resource "aws_subnet" "example" {
  count                   = length(var.subnets)
  vpc_id                  = aws_vpc.example.id
  cidr_block              = values(var.subnets)[count.index]

  tags = {
    Name = keys(var.subnets)[count.index]
  }
}

出力結果:

このコードを実行すると、10.0.1.0/2410.0.2.0/2410.0.3.0/24のCIDRブロックを持つ3つのサブネットが作成されます。

また、keys関数を利用し、それぞれのサブネットのNameタグにsubnet1subnet2subnet3が付与されます。

注意点

Terraformのvalues関数は非常に便利ですが、使用する際には以下の点に注意を記載いたします。

  1. 順序の保証: values関数はマップの値をリストとして返しますが、その順序はマップのキーの順序と一致するとは限りません。マップは順序を保持しないため、特定の順序で値を取り出す必要がある場合は、別の方法を考える必要があります。

  2. 適用可能なデータ型: values関数はマップまたはオブジェクトの値を返します。そのため、元のデータ構造がマップまたはオブジェクトでなければならないという制約があります。リストに対してvalues関数を使用することはできません。

  3. null値の取り扱い: Terraformのマップやオブジェクトにはnull値を含めることができますが、values関数を使用してその値を取り出すと、リストの中にnull値が含まれることになります。

補足

以下は関連記事です。

www.guri2o1667.work

以上です。