

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Terraform 関数、式、メタ引数について
<a name="functions-expressions"></a>

一般的なプログラミング言語ではなく宣言型設定ファイルを使用する IaC ツールの 1 つの批判は、カスタムプログラムロジックの実装が困難になることです。Terraform 設定では、この問題は関数、式、メタ引数を使用して対処されます。

## 関数
<a name="functions"></a>

コードを使用してインフラストラクチャをプロビジョニングする大きな利点の 1 つは、一般的なワークフローを保存 して繰り返し再利用し、多くの場合、毎回異なる引数を渡すことです。Terraform 関数は AWS CloudFormation [内部関数](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)に似ていますが、構文はプログラム言語で関数を呼び出す方法に似ています。このガイドの例では、[substr](https://developer.hashicorp.com/terraform/language/functions/substr)、[concat](https://developer.hashicorp.com/terraform/language/functions/concat)、[length](https://developer.hashicorp.com/terraform/language/functions/length)、[base64decode](https://developer.hashicorp.com/terraform/language/functions/base64decode) など、いくつかの Terraform 関数に既に気付いているかもしれません。組み込み関数を使用する CloudFormation と同様に、Terraform には設定で使用できる一連の[組み込み関数](https://developer.hashicorp.com/terraform/language/functions)があります。たとえば、特定のリソース属性がファイルに直接貼り付けるのが非効率な非常に大きな JSON オブジェクトを取る場合、そのオブジェクトを **.json** ファイルに配置し、Terraform 関数を使用してそれにアクセスできます。次の例では、 `file`関数はファイルの内容を文字列形式で返し、それをオブジェクトタイプ`jsondecode`に変換します。

```
resource "example_resource" "example_resource_name" {
  json_object = jsondecode(file("/path/to/file.json"))
}
```

## 表現
<a name="expressions"></a>

Terraform では、[条件式も許可されます。条件式](https://developer.hashicorp.com/terraform/language/expressions/conditionals)は CloudFormation `condition`関数に似ていますが、従来の [3 項演算子](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_operator)構文を使用する点が異なります。次の例では、2 つの式はまったく同じ結果を返します。2 番目の例は、Terraform が[スプラット式](https://developer.hashicorp.com/terraform/language/expressions/splat)を呼び出すものです。アスタリスクにより、Terraform はリストをループし、各項目の `id`プロパティのみを使用して新しいリストを作成します。

```
resource "example_resource" "example_resource_name" {
  boolean_value  = var.value ? true : false
  numeric_value  = var.value > 0 ? 1 : 0
  string_value   = var.value == "change_me" ? "New value" : var.value
  string_value_2 = var.value != "change_me" ? var.value : "New value"
}
There are two ways to express for loops in a Terraform configuration:
resource "example_resource" "example_resource_name" {
  list_value   = [for object in var.ids : object.id]
  list_value_2 = var.ids[*].id
}
```

## メタ引数
<a name="meta-arguments"></a>

前のコード例では、 `list_value`と `list_value_2`は引*数*と呼ばれます。これらのメタ引数の一部をすでに理解しているかもしれません。Terraform にはいくつかの*メタ引数*もあり、引数と同じように動作しますが、いくつかの追加機能があります。
+ [depends\$1on](https://developer.hashicorp.com/terraform/language/meta-arguments/depends_on) メタ引数は CloudFormation [DependsOn 属性](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html)と非常によく似ています。
+ [プロバイダー](https://developer.hashicorp.com/terraform/language/meta-arguments#provider)メタ引数を使用すると、複数のプロバイダー設定を一度に使用できます。
+ [ライフサイクル](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle)メタ引数を使用すると、CloudFormation [の削除](https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk/RemovalPolicy.html)および[削除](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html)ポリシーと同様に、リソース設定をカスタマイズできます。

他のメタ引数を使用すると、関数と式の機能をリソースに直接追加できます。たとえば、[カウント](https://developer.hashicorp.com/terraform/language/meta-arguments/count)メタ引数は、複数の類似リソースを同時に作成するための便利なメカニズムです。次の例は、メタ引数を使用せずに 2 つの Amazon Elastic Container Service (Amazon EKS) `count` クラスターを作成する方法を示しています。

```
resource "aws_eks_cluster" "example_0" {
  name     = "example_0"
  role_arn = aws_iam_role.cluster_role.arn
  vpc_config {
    endpoint_private_access = true
    endpoint_public_access  = true
    subnet_ids              = var.subnet_ids[0]
  }
}

resource "aws_eks_cluster" "example_1" {
  name     = "example_1"
  role_arn = aws_iam_role.cluster_role.arn
  vpc_config {
    endpoint_private_access = true
    endpoint_public_access  = true
    subnet_ids              = var.subnet_ids[1]
  }
}
```

次の例は、メタ引数を使用して 2 `count` つの Amazon EKS クラスターを作成する方法を示しています。

```
resource "aws_eks_cluster" "clusters" {
  count    = 2
  name     = "cluster_${count.index}"
  role_arn = aws_iam_role.cluster_role.arn
  vpc_config {
    endpoint_private_access = true
    endpoint_public_access  = true
    subnet_ids              = var.subnet_ids[count.index]
  }
}
```

各 にユニット名を付けるには、 のリソースブロック内のリストインデックスにアクセスできます`count.index`。ただし、より複雑な複数の類似リソースを作成する場合はどうなりますか? そこで [for\$1each](https://developer.hashicorp.com/terraform/language/meta-arguments/for_each) メタ引数が登場します。メタ引数は `for_each` と非常に似ていますが`count`、数値の代わりにリストまたはオブジェクトを渡す点が異なります。Terraform は、リストまたはオブジェクトのメンバーごとに新しいリソースを作成します。これは、ループインデックスではなくリストの内容にアクセスできる点を除いて`count = length(list)`、 を設定した場合と似ています。

これは、項目のリストまたは単一のオブジェクトの両方で機能します。次の例では、IDs `id-1`として `id-0`と を持つ 2 つのリソースを作成します。

```
variable "ids" {
  default = [
    { id = "id-0" },
    { id = "id-1" },
  ]
}

resource "example_resource" "example_resource_name" {
  # If your list fails, you might have to call "toset" on it to convert it to a set
  for_each = toset(var.ids)
  id       = each.value
}
```

次の例では、2 つのリソースも作成します。1 つは Sparky、 プードル、もう 1 つは Fluffy、 chihuahua です。

```
variable "dogs" {
  default = {
    poodle    = "Sparky"
    chihuahua = "Fluffy"
  }
}

resource "example_resource" "example_resource_name" {
  for_each = var.dogs
  breed    = each.key
  name     = each.value
}
```

count.index を使用してカウント単位でループインデックスにアクセスできるのと同様に、各オブジェクトを使用して for\$1each ループ内の各項目のキーと値にアクセスできます。for\$1each はリストとオブジェクトの両方を反復するため、各キーと値は少し混乱して追跡する可能性があります。次の表は、 for\$1each メタ引数を使用するさまざまな方法と、反復ごとに値を参照する方法を示しています。


****  

| 例 | `for_each` タイプ | 最初の反復 | 2 回目の反復 | 
| --- | --- | --- | --- | 
| A | <pre>["poodle", "chihuahua"]</pre> | <pre>each.key = "poodle"<br /><br />each.value = null</pre> | <pre>each.key = "chihuahua"<br /><br />each.value = null</pre> | 
| B | <pre>[<br /><br />{<br /><br />type = "poodle",<br /><br />name = "Sparky"<br /><br />},<br /><br />{<br /><br />type = "chihuahua",<br /><br />name = "Fluffy"<br /><br />}<br /><br />]</pre> | <pre>each.key = {<br /><br />type = "poodle",<br /><br />name = "Sparky"<br /><br />}<br /><br />each.value = null</pre> | <pre>each.key = {<br /><br />type = "chihuahua",<br /><br />name = "Fluffy"<br /><br />}<br /><br />each.value = null</pre> | 
| C | <pre>{<br /><br />poodle = "Sparky",<br /><br />chihuahua = "Fluffy"<br /><br />}</pre> | <pre>each.key = "poodle"<br /><br />each.value = "Sparky"</pre> | <pre>each.key = "chihuahua"<br /><br />each.value = "Fluffy"</pre> | 
| D | <pre>{<br /><br />dogs = {<br /><br />poodle = "Sparky",<br /><br />chihuahua = "Fluffy"<br /><br />},<br /><br />cats = {<br /><br />persian = "Felix",<br /><br />burmese = "Morris"<br /><br />}<br /><br />}</pre> | <pre>each.key = "dogs"<br /><br />each.value = {<br /><br />poodle = "Sparky",<br /><br />chihuahua = "Fluffy"<br /><br />}</pre> | <pre>each.key = "cats"<br /><br />each.value = {<br /><br />persian = "Felix",<br /><br />burmese = "Morris"<br /><br />}</pre> | 
| E | <pre>{<br /><br />dogs = [<br /><br />{<br /><br />type = "poodle",<br /><br />name = "Sparky"<br /><br />},<br /><br />{<br /><br />type = "chihuahua",<br /><br />name = "Fluffy"<br /><br />}<br /><br />],<br /><br />cats = [<br /><br />{<br /><br />type = "persian",<br /><br />name = "Felix"<br /><br />},<br /><br />{<br /><br />type = "burmese",<br /><br />name = "Morris"<br /><br />}<br /><br />]<br /><br />}</pre> | <pre>each.key = "dogs"<br /><br />each.value = [<br /><br />{<br /><br />type = "poodle",<br /><br />name = "Sparky"<br /><br />},<br /><br />{<br /><br />type = "chihuahua",<br /><br />name = "Fluffy"<br /><br />}<br /><br />]</pre> | <pre>each.key = "cats"<br /><br />each.value = [<br /><br />{<br /><br />type = "persian",<br /><br />name = "Felix"<br /><br />},<br /><br />{<br /><br />type = "burmese",<br /><br />name = "Morris"<br /><br />}<br /><br />]</pre> | 

 

したがって、 `var.animals`が行 E と等しい場合は、次のコードを使用して動物ごとに 1 つのリソースを作成できます。

```
resource "example_resource" "example_resource_name" {
  for_each = var.animals
  type     = each.key
  breeds   = each.value[*].type
  names    = each.value[*].name
}
```

または、次のコードを使用して、動物ごとに 2 つのリソースを作成することもできます。

```
resource "example_resource" "example_resource_name" {
  for_each = var.animals.dogs
  type     = "dogs"
  breeds   = each.value.type
  names    = each.value.name
}

resource "example_resource" "example_resource_name" {
  for_each = var.animals.cats
  type     = "cats"
  breeds   = each.value.type
  names    = each.value.name
}
```