- OpenTofu 言語
- 構文
- JSON 設定構文
JSON 設定構文
ほとんどの OpenTofu 設定は、人間が読みやすく更新しやすいように設計された OpenTofu 独自の言語構文 で記述されます。
OpenTofu は、JSON 互換の代替構文もサポートしています。この構文は、設定の一部をプログラムで生成する場合に役立ちます。既存の JSON ライブラリを使用して、生成された設定ファイルを準備できるためです。
JSON 構文は、独自の構文に基づいて定義されています。独自の構文で表現できるものはすべて JSON 構文でも表現できますが、JSON の文法の制限により、一部の構成は JSON で表現するのがより複雑になります。
OpenTofu は、.tf
または .tofu
拡張子のファイルには独自の構文を、.tf.json
または .tofu.json
拡張子のファイルには JSON 構文を使用します。
低レベルの JSON 構文は、独自の構文と同様に、*HCL* と呼ばれる仕様で定義されています。 OpenTofu を使用するために HCL 構文またはその JSON マッピングのすべての詳細を知る必要はありません。そのため、このページでは、独自の構文と JSON 構文の最も重要な違いをまとめています。興味がある場合は、HCL の仕様 で HCL の JSON 構文の完全な定義を見つけることができます。
拡張子の優先順位
同じベース名を持つ .tf.json
ファイルと .tofu.json
ファイルの両方がディレクトリに存在する場合、OpenTofu は .tofu.json
ファイルを優先し、.tf.json
ファイルを無視します。例えば
foo.tf.json
とfoo.tofu.json
の両方が同じディレクトリに存在する場合、OpenTofu はfoo.tofu.json
のみを読み込み、foo.tf.json
は無視します。
これにより、両方が利用可能な場合、.tofu.json
ファイルは常に .tf.json
ファイルよりも優先されます。このシナリオは、モジュール作成者が OpenTofu と Terraform の両方をサポートするモジュールを作成する場合に役立ちます。
JSON ファイル構造
JSON ベースの OpenTofu 設定のルートには JSON オブジェクトがあります。このオブジェクトのプロパティは、OpenTofu 言語のトップレベルブロックタイプに対応しています。例えば
{
"variable": {
"example": {
"default": "hello"
}
}
}
各トップレベルオブジェクトプロパティは、予期されるトップレベルブロックタイプのいずれかの名前に一致する必要があります。上記の variable
のようにラベルを必要とするブロックタイプは、ラベルのレベルごとに 1 つのネストされたオブジェクト値で表されます。 resource
ブロックは 2 つのラベルを必要とするため、2 レベルのネストが必要です。
{
"resource": {
"aws_instance": {
"example": {
"instance_type": "t2.micro",
"ami": "ami-abc123"
}
}
}
}
ラベルを表すネストされたオブジェクトの後、最後にさらに 1 つのネストされたオブジェクトがブロック自体の本体を表します。上記の例では、variable "example"
の default
引数と、resource "aws_instance" "example"
の instance_type
および ami
引数が指定されています。
上記の 2 つの設定ファイルを組み合わせると、独自の構文では次のブロックと同等になります。
variable "example" {
default = "hello"
}
resource "aws_instance" "example" {
instance_type = "t2.micro"
ami = "ami-abc123"
}
-
各トップレベルブロックタイプ内では、JSON へのマッピングのルールがわずかに異なります(以下のブロックタイプ固有の例外を参照)。ただし、ほとんどの場合、次の一般的なルールが適用されます。
-
ブロック本体を表す JSON オブジェクトには、引数名またはネストされたブロックタイプ名に対応するプロパティが含まれています。
-
プロパティが独自の構文で任意の式を受け入れる引数に対応する場合、プロパティ値は、以下の_式の対応付け_で説明するように式にマッピングされます。任意の式を受け入れない引数の場合、プロパティ値の解釈は、このページの後半で説明するブロックタイプ固有の例外で説明するように、引数によって異なります。
プロパティ名が予期されるネストされたブロックタイプ名に対応する場合、値は、以下の_ネストされたブロックのマッピング_で説明するように解釈されます。ただし、このページの後半で説明するブロックタイプ固有の例外で別途指定されている場合を除きます。
式の対応付け
JSON 文法は OpenTofu 言語のすべての式構文を表すことができないため、式として解釈される JSON 値は次のようにマッピングされます。 | JSON |
---|---|
OpenTofu 言語の解釈 | ブール値 |
リテラル bool 値。 | 数値 |
リテラル number 値。 | 文字列 |
文字列テンプレートとして解析され、以下で説明するように評価されます。 | オブジェクト |
各プロパティ値はこのテーブルに従ってマッピングされ、適切な属性タイプを持つ object(...) 値が生成されます。 | 配列 |
各要素はこのテーブルに従ってマッピングされ、適切な要素タイプを持つ tuple(...) 値が生成されます。 | Null |
リテラル null
。
任意の式が予期される場所で JSON 文字列が見つかった場合、その値は最初に [文字列テンプレート][] として解析され、最終結果を生成するために評価されます。
{
"output": {
"example": {
"value": "${aws_instance.example}"
}
}
}
指定されたテンプレートが*単一の*補間シーケンスのみで構成されている場合、その式の結果は、最初に文字列に変換することなく、直接取得されます。これにより、JSON 構文内で文字列以外の式を使用できます。
上記で宣言された output "example"
は、文字列値ではなく、指定された aws_instance
リソースブロックを表すオブジェクト値を持ちます。この特別な動作は、テンプレートにリテラルまたは制御シーケンスが表示される場合は適用されません。これらの他の状況では、常に文字列値が生成されます。
ネストされたブロックのマッピング
最も単純な状況は、resource
ブロック内で使用される lifecycle
ネストブロックのように、そのタイプがラベルを期待しない場合に、指定されたタイプの単一ブロックのみを表すことです。
{
"resource": {
"aws_instance": {
"example": {
"lifecycle": {
"create_before_destroy": true
}
}
}
}
}
上記は、以下のネイティブ構文設定と同等です。
resource "aws_instance" "example" {
lifecycle {
create_before_destroy = true
}
}
ネストされたブロックタイプが1つ以上のラベルを必要とする場合、または同じタイプの複数のブロックを指定できる場合、マッピングは少し複雑になります。たとえば、resource
ブロック内で使用される provisioner
ネストブロックタイプは、使用するプロビジョナーを示すラベルを期待し、プロビジョナーブロックの順序は操作の順序を決定するために重要です。
次のネイティブ構文の例は、異なるタイプの複数のプロビジョナーを持つ resource
ブロックを示しています。
resource "aws_instance" "example" {
# (resource configuration omitted for brevity)
provisioner "local-exec" {
command = "echo 'Hello World' >example.txt"
}
provisioner "file" {
source = "example.txt"
destination = "/tmp/example.txt"
}
provisioner "remote-exec" {
inline = [
"sudo install-something -f /tmp/example.txt",
]
}
}
これらのブロックの順序を保持するには、上記のJSONと同等のこのJSONのように、このブロックタイプを表すプロパティの直接値としてJSON配列を使用する必要があります。
{
"resource": {
"aws_instance": {
"example": {
"provisioner": [
{
"local-exec": {
"command": "echo 'Hello World' >example.txt"
}
},
{
"file": {
"source": "example.txt",
"destination": "/tmp/example.txt"
}
},
{
"remote-exec": {
"inline": ["sudo install-something -f /tmp/example.txt"]
}
}
]
}
}
}
}
provisioner
配列の各要素は、名前が各 provisioner
ブロックのラベルを表す単一のプロパティを持つオブジェクトです。複数のラベルを期待するブロックタイプの場合、この配列とオブジェクトのネストを交互に繰り返すパターンを追加のレベルごとに使用できます。
ネストされたブロックタイプがラベルを必要とするが、順序が重要*でない*場合、配列を省略し、プロパティ名が固有のブロックラベルに対応する単一のオブジェクトを提供することができます。これは、単純なケースでは上記を省略した表記法として許可されていますが、配列とオブジェクトを交互に使用するアプローチが最も一般的です。設定の意味が正確に保持されるように、ネイティブ構文からJSONに体系的に変換する場合は、最も一般的な形式を使用することをお勧めします。
コメントプロパティ
JSON構文設定ファイルの手動編集は推奨していませんが(この形式は主にプログラムによる生成と消費を目的としています)、ブロック本体を表すJSONオブジェクト内では、特別なプロパティ名を使用して限定的な形式の*コメント*が許可されています。
{
"resource": {
"aws_instance": {
"example": {
"//": "This instance runs the scheduled tasks for backup",
"instance_type": "t2.micro",
"ami": "ami-abc123"
}
}
}
}
ブロック本体を表すオブジェクトでは、"//"
という名前のプロパティはOpenTofuによって完全に無視されます。この例外は、式として解釈されているオブジェクトには適用されません。そこでは、これは "//"
という名前のオブジェクトタイプ属性として解釈されます。
この特別なプロパティ名は、JSONベースの設定ファイルのルートでも使用できます。これは、どのプログラムがファイルを作成したかをメモするのに役立ちます。
{
"//": "This file is generated by generate-outputs.py. DO NOT HAND-EDIT!",
"output": {
"example": {
"value": "${aws_instance.example}"
}
}
}
ブロックタイプ固有の例外
特定のブロックタイプ内の特定の引数は、OpenTofuによって特別な方法で処理されるため、JSON構文へのマッピングは上記で説明した一般的なルールに従いません。以下のサブセクションでは、各トップレベルブロックタイプに適用される特別なマッピングルールについて説明します。
resource
および data
ブロック
resource
および data
ブロックタイプのメタ引数の一部は、オブジェクトへの直接参照、またはリテラルキーワードを受け取ります。JSONで表される場合、参照またはキーワードは、追加の周囲のスペースや記号のないJSON文字列として指定されます。
たとえば、provider
メタ引数は、プロバイダー設定への <PROVIDER>.<ALIAS>
参照を受け取ります。これは、ネイティブ構文では引用符なしで表示されますが、JSON構文では文字列として表す必要があります。
{
"resource": {
"aws_instance": {
"example": {
"provider": "aws.foo"
}
}
}
}
この特別な処理は、以下のメタ引数に適用されます。
provider
:上記のように、単一の文字列。depends_on
:["aws_instance.example"]
のような、名前付きエンティティへの参照を含む文字列の配列。lifecycle
ブロック内のignore_changes
:all
に設定されている場合は、単一の文字列"all"
を指定する必要があります。それ以外の場合、["ami"]
のような、プロパティ参照を含むJSON文字列の配列を使用する必要があります。
特別な処理は、resource
ブロック内にあるか provisioner
ブロック内にネストされているかに関係なく、connection
ブロックの type
引数にも適用されます。指定された文字列は文字通りに解釈され、文字列テンプレートとして解析および評価されません。
variable
ブロック
variable
ブロック内のすべての引数は、JSONへの非標準マッピングを持ちます。
type
:"string"
や"list(string)"
のような、型式を含む文字列。default
:指定された型に変換できるリテラルJSON値。この値内の文字列は文字通りに解釈され、文字列テンプレートとしては解釈され*ません*。description
:テンプレートとして解釈されない、リテラルJSON文字列。
{
"variable": {
"example": {
"type": "string",
"default": "hello"
}
}
}
output
ブロック
description
および sensitive
引数は、リテラルJSON値として解釈されます。description
文字列は、文字列テンプレートとしては解釈されません。
value
引数は、式として解釈されます。
{
"output": {
"example": {
"value": "${aws_instance.example}"
}
}
}
locals
ブロック
localsブロックタイプを表すJSONオブジェクトプロパティの値は、プロパティ名が宣言するローカル値の名前であるJSONオブジェクトである必要があります。
{
"locals": {
"greeting": "Hello, ${var.name}"
}
}
これらのネストされたプロパティのそれぞれの値は、式として解釈されます。
module
ブロック
source
および version
メタ引数は、リテラル文字列として指定する必要があります。値は文字列テンプレートとしては解釈されません。
providers
メタ引数は、プロパティが子モジュールに公開するコンパクトプロバイダーアドレスであり、値が現在のモジュールから使用するプロバイダーアドレスであるJSONオブジェクトとして指定する必要があります。どちらもリテラル文字列として指定されます。
{
"module": {
"example": {
"source": "hashicorp/consul/azurerm",
"version": "= 1.0.0",
"providers": {
"aws": "aws.usw1"
}
}
}
}
provider
ブロック
alias
および version
メタ引数は、リテラル文字列として指定する必要があります。値は文字列テンプレートとしては解釈されません。
{
"provider": {
"aws": [
{
"region": "us-east-1"
},
{
"alias": "usw1",
"region": "us-west-1"
}
]
}
}
terraform
ブロック
terraform
ブロック内の設定は、名前付きオブジェクト参照または関数呼び出しを受け入れないため、すべての設定値は文字通りに解釈されます。文字列値は文字列テンプレートとしては解釈されません。
terraform
ブロックごとに1つの backend
ブロックのみが許可されているため、コンパクトブロックマッピングを使用して表すことができます。ネストされたオブジェクトには、名前がバックエンドタイプを表す単一のプロパティが含まれています。
{
"terraform": {
"required_version": ">= 0.12.0",
"backend": {
"s3": {
"region": "us-west-2",
"bucket": "acme-tofu-states"
}
}
}
}