- OpenTofu 内部
- 机器可读 UI
机器可读 UI
默认情况下,许多 OpenTofu 命令将 UI 输出显示为非结构化文本,旨在通过终端模拟器供用户阅读。此文本流不是集成稳定接口。一些命令支持 -json
标志,该标志启用具有已定义接口的结构化 JSON 输出模式。
对于诸如 plan
、apply
和 refresh
之类的长时间运行的命令,-json
标志输出 JSON UI 消息流,每行一条。这些可以一次处理一条消息,集成软件可以根据需要过滤、组合或修改输出。
第一个输出的消息类型为 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
:供应程序的输出日志
从供应程序接收到的每个日志行都会输出一条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"
}