Машиночитаемый интерфейс
По умолчанию многие команды OpenTofu выводят данные интерфейса в виде неструктурированного текста, предназначенного для чтения пользователем в эмуляторе терминала. Этот поток текста не является стабильным интерфейсом для интеграций. Некоторые команды поддерживают флаг -json, который включает режим структурированного вывода в формате JSON с определённым интерфейсом.
Для длительно выполняющихся команд, таких как plan, apply и refresh, флаг -json выводит поток сообщений интерфейса в формате JSON, по одному сообщению в строке. Их можно обрабатывать по одному сообщению за раз, при этом интегрирующее программное обеспечение может фильтровать, объединять или изменять вывод по своему усмотрению.
Первое выводимое сообщение имеет тип 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: всегда имеет значение "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: последовательность сообщений, показывающих ход выполнения операции apply для отдельного ресурса -
provision_start,provision_progress,provision_complete,provision_errored: последовательность сообщений, показывающих ход выполнения отдельного шага провижионера -
refresh_start,refresh_complete: последовательность сообщений, показывающих ход обновления состояния отдельного ресурса
Сообщение о версии
Вывод команды с машиночитаемым интерфейсом всегда начинается с сообщения version. Определены следующие ключи, специфичные для этого сообщения:
-
tofu: версия OpenTofu, создавшая это сообщение -
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 выдаст сообщение resource_drift для каждого ресурса, изменённого вне OpenTofu. Это сообщение содержит встроенный объект 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"
}Запланированное изменение
В конце планирования или перед выполнением apply 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: логическое значение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, указывающий, к какому ресурсу относится операция.
Начало применения
Объект hook сообщения apply_start имеет следующие ключи:
-
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"
}Ход применения
Объект hook сообщения apply_progress имеет следующие ключи:
-
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"
}Применение завершено
Объект hook сообщения apply_complete имеет следующие ключи:
-
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"
}Ошибка при применении
Объект hook сообщения apply_complete имеет следующие ключи:
-
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"
}Начало провижининга
Объект hook сообщения provision_start имеет следующие ключи:
-
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"
}Ход провижининга
Объект hook сообщения provision_progress имеет следующие ключи:
-
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"
}Провижининг завершён
Объект hook сообщения provision_complete имеет следующие ключи:
-
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"
}Ошибка при провижининге
Объект hook сообщения provision_errored имеет следующие ключи:
-
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"
}Начало обновления состояния
Объект hook сообщения refresh_start имеет следующие ключи:
-
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"
}Обновление состояния завершено
Объект hook сообщения refresh_complete имеет следующие ключи:
-
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"
}
Copyright (c) The OpenTofu Authors
Copyright (c) 2014 HashiCorp, Inc.
Mozilla Public License, version 2.0
https://opentofu.org/docs/v1.9/internals/machine-readable-ui/