- OpenTofu内部構造
- 機械可読UI
機械可読UI
デフォルトでは、多くのOpenTofuコマンドは、端末エミュレータを介してユーザーが読むことを目的とした、非構造化テキストとしてUI出力を表示します。このテキストストリームは、統合のための安定したインターフェースではありません。一部のコマンドは、定義されたインターフェースを持つ構造化JSON出力モードを有効にする-jsonフラグをサポートしています。
plan、apply、refreshなどの長時間実行コマンドの場合、-jsonフラグは1行につき1つのJSON UIメッセージのストリームを出力します。これらは、統合ソフトウェアがフィルタリング、結合、または必要に応じて出力を変更することで、1つのメッセージずつ処理できます。
最初の出力メッセージのタイプはversionで、uiキーが含まれており、値は"1.0"です。このバージョンの意味は
- 下位互換性のある変更または追加に対しては、マイナーバージョン(例:
"1.1")を増分します。将来のマイナーバージョンとの下位互換性を維持するために、認識できない名前を持つオブジェクトプロパティは無視してください。 - 上位互換性のない変更に対しては、メジャーバージョン(例:
"2.0")を増分します。サポートされていないメジャーバージョンを報告する入力は拒否します。
OpenTofu 1.0互換性に関する約束の範囲内でのみ、新しいメジャーバージョンを導入します。
サンプルJSON出力
以下は、tofu apply -jsonを実行した際のサンプル出力です。
{"@level":"info","@message":"OpenTofu 1.6.0","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.275359-04:00","tofu":"0.15.4","type":"version","ui":"0.1.0"}
{"@level":"info","@message":"random_pet.animal: Plan to create","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.705503-04:00","change":{"resource":{"addr":"random_pet.animal","module":"","resource":"random_pet.animal","implied_provider":"random","resource_type":"random_pet","resource_name":"animal","resource_key":null},"action":"create"},"type":"planned_change"}
{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.705638-04:00","changes":{"add":1,"change":0,"remove":0,"operation":"plan"},"type":"change_summary"}
{"@level":"info","@message":"random_pet.animal: Creating...","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.825308-04:00","hook":{"resource":{"addr":"random_pet.animal","module":"","resource":"random_pet.animal","implied_provider":"random","resource_type":"random_pet","resource_name":"animal","resource_key":null},"action":"create"},"type":"apply_start"}
{"@level":"info","@message":"random_pet.animal: Creation complete after 0s [id=smart-lizard]","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.826179-04:00","hook":{"resource":{"addr":"random_pet.animal","module":"","resource":"random_pet.animal","implied_provider":"random","resource_type":"random_pet","resource_name":"animal","resource_key":null},"action":"create","id_key":"id","id_value":"smart-lizard","elapsed_seconds":0},"type":"apply_complete"}
{"@level":"info","@message":"Apply complete! Resources: 1 added, 0 changed, 0 destroyed.","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.869168-04:00","changes":{"add":1,"change":0,"remove":0,"operation":"apply"},"type":"change_summary"}
{"@level":"info","@message":"Outputs: 1","@module":"tofu.ui","@timestamp":"2021-05-25T13:32:41.869280-04:00","outputs":{"pets":{"sensitive":false,"type":"string","value":"smart-lizard"}},"type":"outputs"}
各行は、すべてのメッセージに共通するいくつかのキーを持つJSONオブジェクトで構成されています。それらは
@level:通常は「info」ですが、診断を表示する場合は「error」または「warn」になる場合があります。@message:このメッセージの内容に関する人間が読める要約。@module:UI出力をレンダリングする場合は常に「tofu.ui」。@timestamp:メッセージが出力された時刻のRFC3339タイムスタンプ。type:このメッセージの種類を定義し、存在する可能性のある他のキーの解釈方法を決定します。
ログをユーザーインターフェースとして表示するクライアントは、予期しないメッセージタイプを処理するために、少なくとも@messageフィールドをユーザーに提示する必要があります。
メッセージは、トリガーが発生したときにイベントとして出力されます。これは、OpenTofuが(1を超える)並行処理で実行されている場合、複数のリソースに関連するメッセージがインターリーブされる可能性があることを意味します。resourceオブジェクトの値を使用して、単一のリソースに関する複数のメッセージをリンクできます。
メッセージタイプ
次のメッセージタイプがサポートされています。
汎用メッセージ
version:OpenTofuのバージョンと、次のメッセージに使用されるスキーマのバージョンに関する情報。log:非構造化の人間が読めるログライン。diagnostic:診断の警告またはエラーメッセージ。tofu validateドキュメントの形式の詳細については、こちらを参照してください。
操作結果
resource_drift:OpenTofu以外で行われた単一のリソースに対する検出された変更について説明します。planned_change:単一のリソースに対する計画された変更について説明します。change_summary:計画された、または適用されたすべての変更の要約。outputs:すべてのルートモジュール出力のリスト。
リソースの進捗状況
apply_start、apply_progress、apply_complete、apply_errored:適用処理における単一のリソースの進捗状況を示すメッセージのシーケンス。provision_start、provision_progress、provision_complete、provision_errored:単一のプロビジョナー手順の進捗状況を示すメッセージのシーケンス。refresh_start、refresh_complete:更新処理における単一のリソースの進捗状況を示すメッセージのシーケンス。
バージョンメッセージ
機械可読UIコマンド出力は、常にversionメッセージで始まります。次のメッセージ固有のキーが定義されています。
tofu:このメッセージを出力したOpenTofuのバージョン。ui:次のメッセージの意味を定義する機械可読UIスキーマのバージョン。
例
{
"@level": "info",
"@message": "OpenTofu 0.15.4",
"@module": "tofu.ui",
"@timestamp": "2021-05-25T13:32:41.275359-04:00",
"tofu": "0.15.4",
"type": "version",
"ui": "0.1.0"
}
リソースドリフト
プランニング中にドリフトが検出された場合、OpenTofuはOpenTofuの外部で変更されたリソースごとにresource_driftメッセージを出力します。このメッセージには、次のキーを持つ埋め込みchangeオブジェクトが含まれています。
resource: 変更されるリソースのアドレスを記述するオブジェクト。詳細は下記のリソースオブジェクトを参照してください。action: リソースに対して実行される予定のアクション。値:update、delete。
このメッセージには、変更が計画された原因となった正確な変更に関する詳細は含まれていません。その情報はJSONプラン出力で確認できます。
例
{
"@level": "info",
"@message": "random_pet.animal: Drift detected (update)",
"@module": "tofu.ui",
"@timestamp": "2021-05-25T13:32:41.705503-04:00",
"change": {
"resource": {
"addr": "random_pet.animal",
"module": "",
"resource": "random_pet.animal",
"implied_provider": "random",
"resource_type": "random_pet",
"resource_name": "animal",
"resource_key": null
},
"action": "update"
},
"type": "resource_drift"
}
計画された変更
プランの終了時または適用前に、OpenTofuは変更を適用する必要がある各リソースに対してplanned_changeメッセージを出力します。このメッセージには、次のキーを持つ埋め込みchangeオブジェクトが含まれています。
resource: 変更されるリソースのアドレスを記述するオブジェクト。詳細は下記のリソースオブジェクトを参照してください。previous_resource: この変更に構成駆動型の移動が含まれる場合、リソースの以前のアドレスを記述するオブジェクト。action: リソースに対して実行される予定のアクション。値:noop、create、read、update、replace、delete、move。reason: 変更の任意の理由。アクションがreplaceまたはdeleteの場合にのみ使用されます。値:tainted: リソースが汚染済みとしてマークされました。requested: 例えば-replaceプランフラグを介して、ユーザーがリソースの置換を要求しました。cannot_update: 構成の変更により、リソースが更新されるのではなく削除および作成されることを強制します。delete_because_no_resource_config: 構成に一致するリソースがありません。delete_because_wrong_repetition: リソースインスタンスキーに、構成内で対応するcountまたはfor_eachがありません。delete_because_count_index: リソースインスタンスキーがcount引数の範囲外です。delete_because_each_key: リソースインスタンスキーがfor_each引数に含まれていません。delete_because_no_module: 囲んでいるモジュールインスタンスが構成にありません。
このメッセージには、変更が計画された原因となった正確な変更に関する詳細は含まれていません。その情報はJSONプラン出力で確認できます。
例
{
"@level": "info",
"@message": "random_pet.animal: Plan to create",
"@module": "tofu.ui",
"@timestamp": "2021-05-25T13:32:41.705503-04:00",
"change": {
"resource": {
"addr": "random_pet.animal",
"module": "",
"resource": "random_pet.animal",
"implied_provider": "random",
"resource_type": "random_pet",
"resource_name": "animal",
"resource_key": null
},
"action": "create"
},
"type": "planned_change"
}
変更サマリー
OpenTofuは、プランまたは適用操作が完了すると変更サマリーを出力します。両方のメッセージタイプにはchangesオブジェクトが含まれており、次のキーがあります。
add: 作成されるリソースの数(置換の一部として含まれるものも含む)。change: その場で変更されるリソースの数。remove: 破棄されるリソースの数(置換の一部として含まれるものも含む)。operation:plan、apply、またはdestroyのいずれか。
例
{
"@level": "info",
"@message": "Apply complete! Resources: 1 added, 0 changed, 0 destroyed.",
"@module": "tofu.ui",
"@timestamp": "2021-05-25T13:32:41.869168-04:00",
"changes": {
"add": 1,
"change": 0,
"remove": 0,
"operation": "apply"
},
"type": "change_summary"
}
出力
プランまたは適用が成功した後、タイプoutputsのメッセージには、すべてのルートモジュール出力値が含まれています。このメッセージにはoutputsオブジェクトが含まれており、そのキーは出力名です。出力値は次のキーを持つオブジェクトです。
action: 計画された出力の場合、出力に対して実行されるアクション。値:noop、create、update、delete。value: 適用された出力の場合、JSONでエンコードされた出力の値。type: 適用された出力の場合、検出された出力値のHCLタイプ。sensitive: ブール値。出力が機密情報であり、デフォルトでUIに非表示にする必要がある場合はtrue。
sensitiveな出力にはvalueフィールドが含まれ続けており、統合ソフトウェアは、特定のユースケースに適した方法で機密性値を尊重する必要があります。
例
{
"@level": "info",
"@message": "Outputs: 1",
"@module": "tofu.ui",
"@timestamp": "2021-05-25T13:32:41.869280-04:00",
"outputs": {
"pets": {
"sensitive": false,
"type": "string",
"value": "smart-lizard"
}
},
"type": "outputs"
}
操作メッセージ
リソースに対するOpenTofu操作を実行すると、多くの場合、いくつかのメッセージが出力されます。メッセージタイプには以下が含まれます。
apply_start: リソースの変更の適用を開始するとき。apply_progress: 定期的に、経過時間出力を表示します。apply_complete: 操作が正常に完了したとき。apply_errored: 操作中にエラーが発生したとき。provision_start: プロビジョナー手順を開始するとき。provision_progress: プロビジョナー出力時。provision_complete: プロビジョニングが成功したとき。provision_errored: プロビジョニング中にエラーが発生したとき。refresh_start: 更新中にリソースを読み取るとき。refresh_complete: 更新が成功したとき。
これらのメッセージにはそれぞれhookオブジェクトが含まれており、タイプごとに異なるフィールドがあります。すべてのフックには、操作の対象となるリソースを識別するresourceオブジェクトがあります。
適用開始
apply_startメッセージのhookオブジェクトには、次のキーがあります。
resource: リソースを識別するresourceオブジェクト。action: リソースに対して実行されるアクション。値:noop、create、read、update、replace、delete。id_keyとid_value: リソースのこのインスタンスを識別するために使用されるキーと値のペア。不明な場合は省略されます。
例
{
"@level": "info",
"@message": "random_pet.animal: Creating...",
"@module": "tofu.ui",
"@timestamp": "2021-05-25T13:32:41.825308-04:00",
"hook": {
"resource": {
"addr": "random_pet.animal",
"module": "",
"resource": "random_pet.animal",
"implied_provider": "random",
"resource_type": "random_pet",
"resource_name": "animal",
"resource_key": null
},
"action": "create"
},
"type": "apply_start"
}
適用進行状況
apply_progressメッセージのhookオブジェクトには、次のキーがあります。
resource: リソースを識別するresourceオブジェクト。action: リソースに対して実行されているアクション。値:noop、create、read、update、replace、delete。elapsed_seconds: 適用操作の開始からの経過時間(秒単位の整数)。
例
{
"@level": "info",
"@message": "null_resource.none[4]: Still creating... [30s elapsed]",
"@module": "tofu.ui",
"@timestamp": "2021-03-17T09:34:26.222465-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[4]",
"module": "",
"resource": "null_resource.none[4]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 4
},
"action": "create",
"elapsed_seconds": 30
},
"type": "apply_progress"
}
適用完了
apply_completeメッセージのhookオブジェクトには、次のキーがあります。
resource: リソースを識別するresourceオブジェクト。action: リソースに対して実行されたアクション。値:noop、create、read、update、replace、delete。id_keyとid_value: リソースのこのインスタンスを識別するために使用されるキーと値のペア。不明な場合は省略されます。elapsed_seconds: 適用操作の開始からの経過時間(秒単位の整数)。
例
{
"@level": "info",
"@message": "random_pet.animal: Creation complete after 0s [id=smart-lizard]",
"@module": "tofu.ui",
"@timestamp": "2021-05-25T13:32:41.826179-04:00",
"hook": {
"resource": {
"addr": "random_pet.animal",
"module": "",
"resource": "random_pet.animal",
"implied_provider": "random",
"resource_type": "random_pet",
"resource_name": "animal",
"resource_key": null
},
"action": "create",
"id_key": "id",
"id_value": "smart-lizard",
"elapsed_seconds": 0
},
"type": "apply_complete"
}
適用エラー
apply_completeメッセージのhookオブジェクトには、次のキーがあります。
resource: リソースを識別するresourceオブジェクト。action: リソースに対して実行されたアクション。値:noop、create、read、update、replace、delete。elapsed_seconds: 適用操作の開始からの経過時間(秒単位の整数)。
エラーの正確な詳細は、別のdiagnosticメッセージとしてレンダリングされます。
例
{
"@level": "info",
"@message": "null_resource.none[0]: Creation errored after 10s",
"@module": "tofu.ui",
"@timestamp": "2021-03-26T16:38:54.013910-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[0]",
"module": "",
"resource": "null_resource.none[0]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 0
},
"action": "create",
"elapsed_seconds": 10
},
"type": "apply_errored"
}
プロビジョニング開始
provision_startメッセージのhookオブジェクトには、次のキーがあります。
resource: リソースを識別するresourceオブジェクト。provisioner: プロビジョナーの種類。
例
{
"@level": "info",
"@message": "null_resource.none[0]: Provisioning with 'local-exec'...",
"@module": "tofu.ui",
"@timestamp": "2021-03-26T16:38:43.997431-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[0]",
"module": "",
"resource": "null_resource.none[0]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 0
},
"provisioner": "local-exec"
},
"type": "provision_start"
}
プロビジョニング進行状況
provision_progressメッセージのhookオブジェクトには、次のキーがあります。
resource: リソースを識別するresourceオブジェクト。provisioner: プロビジョナーの種類。output: プロビジョナーからの出力ログ。
プロビジョナーから受信したログ行ごとに、1つのprovision_progressメッセージが出力されます。
例
{
"@level": "info",
"@message": "null_resource.none[0]: (local-exec): Executing: [\"/bin/sh\" \"-c\" \"sleep 10 && exit 1\"]",
"@module": "tofu.ui",
"@timestamp": "2021-03-26T16:38:43.997869-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[0]",
"module": "",
"resource": "null_resource.none[0]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 0
},
"provisioner": "local-exec",
"output": "Executing: [\"/bin/sh\" \"-c\" \"sleep 10 && exit 1\"]"
},
"type": "provision_progress"
}
プロビジョニング完了
provision_completeメッセージのhookオブジェクトには、次のキーがあります。
resource: リソースを識別するresourceオブジェクト。provisioner: プロビジョナーの種類。
例
{
"@level": "info",
"@message": "null_resource.none[0]: (local-exec) Provisioning complete",
"@module": "tofu.ui",
"@timestamp": "2021-03-17T09:34:06.239043-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[0]",
"module": "",
"resource": "null_resource.none[0]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 0
},
"provisioner": "local-exec"
},
"type": "provision_complete"
}
プロビジョニングエラー
provision_erroredメッセージのhookオブジェクトには、次のキーがあります。
resource: リソースを識別するresourceオブジェクト。provisioner: プロビジョナーの種類。
例
{
"@level": "info",
"@message": "null_resource.none[0]: (local-exec) Provisioning errored",
"@module": "tofu.ui",
"@timestamp": "2021-03-26T16:38:54.013572-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[0]",
"module": "",
"resource": "null_resource.none[0]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 0
},
"provisioner": "local-exec"
},
"type": "provision_errored"
}
リフレッシュ開始
refresh_startメッセージのhookオブジェクトには、次のキーがあります。
resource: リソースを識別するresourceオブジェクト。id_keyとid_value: リソースのこのインスタンスを識別するために使用されるキーと値のペア。
例
{
"@level": "info",
"@message": "null_resource.none[0]: Refreshing state... [id=1971614370559474622]",
"@module": "tofu.ui",
"@timestamp": "2021-03-26T14:18:06.508915-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[0]",
"module": "",
"resource": "null_resource.none[0]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 0
},
"id_key": "id",
"id_value": "1971614370559474622"
},
"type": "refresh_start"
}
リフレッシュ完了
refresh_completeメッセージのhookオブジェクトには、次のキーがあります。
resource: リソースを識別するresourceオブジェクト。id_keyとid_value: リソースのこのインスタンスを識別するために使用されるキーと値のペア。
例
{
"@level": "info",
"@message": "null_resource.none[0]: Refresh complete [id=1971614370559474622]",
"@module": "tofu.ui",
"@timestamp": "2021-03-26T14:18:06.509371-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[0]",
"module": "",
"resource": "null_resource.none[0]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 0
},
"id_key": "id",
"id_value": "1971614370559474622"
},
"type": "refresh_complete"
}
リソースオブジェクト
resourceオブジェクトは、構成内のリソースアドレスを表す分解された構造体であり、特定のメッセージが関連付けられているリソースを識別するために使用されます。このオブジェクトには、次のキーがあります。
addr: 文字列としてのリソースの完全な一意アドレス。module: リソースを含むモジュールのアドレス。module.foo.module.bar形式、またはルートモジュールリソースの場合は空文字列。resource: モジュール相対アドレス。ルートモジュールリソースの場合はaddrと同じ。resource_type: アドレス指定されているリソースの種類。resource_name: リソースの名前ラベル。resource_key: アドレスキー(countまたはfor_each値)、またはどちらも使用されていない場合はnull。implied_provider: リソースの種類によって暗黙的に指定されるプロバイダーの種類。プロバイダーエイリアスが使用されている場合、リソースのプロバイダーを反映していない可能性があります。
例
{
"addr": "module.pets.random_pet.pet[\"friend\"]",
"module": "module.pets",
"resource": "random_pet.pet[\"friend\"]",
"implied_provider": "random",
"resource_type": "random_pet",
"resource_name": "pet",
"resource_key": "friend"
}
テストメッセージ
OpenTofuテストを実行すると、いくつかのメッセージが出力されます。メッセージタイプには以下が含まれます。
test_abstract: テストファイルと検出されたテストのサマリー。test_file: テストファイル実行のサマリー。test_run: テスト実行のサマリー。test_summary: テストファイル実行の全体的なステータスと統計のサマリー。
テスト概要
test_abstractメッセージのtest_abstractオブジェクトには、テストファイル名で構成される動的なキーが含まれています。
main.tftest.hcl: テストファイル内で検出されたテストのリスト。
例
{
"@level": "info",
"@message": "Found 1 file and 1 run block",
"@module": "tofu.ui",
"@timestamp": "2024-04-20T17:24:48.418126+10:00",
"test_abstract": {
"main.tftest.hcl": [
"test"
]
},
"type": "test_abstract"
}
テストファイル
test_fileメッセージのtest_fileオブジェクトには、次のキーがあります。
path: テストファイルの相対パス。status: テスト実行の全体的なステータス。
例
{
"@level": "info",
"@message": "main.tftest.hcl... pass",
"@module": "tofu.ui",
"@testfile": "main.tftest.hcl",
"@timestamp": "2024-04-20T17:24:48.588473+10:00",
"test_file": {
"path": "main.tftest.hcl",
"status": "pass"
},
"type": "test_file"
}
テスト実行
test_runメッセージのtest_runオブジェクトには、次のキーがあります。
path: テストファイルの相対パス。run: 実行されたテストの名前。status: テスト実行の全体的なステータス。
例
{
"@level": "info",
"@message": " \"test\"... pass",
"@module": "tofu.ui",
"@testfile": "main.tftest.hcl",
"@testrun": "test",
"@timestamp": "2024-04-20T17:24:48.588519+10:00",
"test_run": {
"path": "main.tftest.hcl",
"run": "test",
"status": "pass"
},
"type": "test_run"
}
テストサマリー
test_summary メッセージオブジェクトtest_summaryには、以下のキーが含まれています。
status: 実行されたすべてのテストの全体的なステータスpassed: 成功したテストの総数failed: 失敗したテストの総数errored: エラーが発生したテストの総数skipped: スキップされたテストの総数
例
{
"@level": "info",
"@message": "Success! 1 passed, 0 failed.",
"@module": "tofu.ui",
"@timestamp": "2024-04-20T17:24:48.716977+10:00",
"test_summary": {
"status": "pass",
"passed": 1,
"failed": 0,
"errored": 0,
"skipped": 0
},
"type": "test_summary"
}