#terraform #terraform-provider-azure #terraform0.12 #vnet
#terraform #terraform-provider-azure #terraform0.12 #виртуальная сеть
Вопрос:
TL; DR: JSON Terraform Azure Vnet требует, чтобы вложенные подсети имели идентификатор, но при указании идентификатора возникают ошибки
Предыстория
У меня есть учетная запись Azure, в которой есть куча ресурсов, созданных вне диапазона, но теперь клиент хочет, чтобы мы управляли всеми ресурсами в terraform. К счастью, у terraform есть способ импорта ресурсов, и даже прекрасный учебник демонстрирует, как импортировать ресурсы и сгенерировать необходимую конфигурацию (https://learn.hashicorp.com/tutorials/terraform/state-import ).
После того, как я импортировал ресурсы, я запускаю команду tf show -no-color -json > main.tf.json
для создания тела конфигурации. Я выгружаю его в JSON, потому что после tf show
запуска вам нужно затем изменить некоторые выходные данные, чтобы результаты были действительным файлом конфигурации terraform.
После tf show
запуска у меня есть скрипт, который обрабатывает данные, внося некоторые изменения в структуру JSON и устраняя атрибуты, которые необходимо удалить или изменить.
Проблема
Проблема, с которой я сталкиваюсь, заключается в том, что после очистки выходных данных, сгенерированных tf show
when I run, tf validate
или любой другой командой, требующей проверки, я получаю сообщение об ошибке, в котором говорится, что id
атрибут требуется для элементов в массиве subnet JSON в объекте azurerm_virtual_network
JSON. Однако, когда я добавляю идентификатор, я получаю сообщение об ошибке, в котором говорится, что an id
не может быть указан для объекта JSON подсети Azure.
Важно отметить, что это происходит только тогда, когда я использую .tf.json
файл, если я использую обычный tf
файл, никаких проблем не возникает.
Код
Версия Terraform: Terraform v0.13.5
Версия поставщика: azurerm v2.38.0
Вот конфигурация terraform JSON, которая демонстрирует проблему
{
"resource": {
"azurerm_virtual_network": {
"gork_vnet": {
"address_space": [
"10.0.0.0/16"
],
"location": "westus2",
"name": "gork_vnet",
"resource_group_name": "mork_rg",
"subnet": [
{
"address_prefix": "10.0.0.0/24",
"name": "cunning_brutality",
"security_group": ""
}
]
}
}
}
}
Ошибка:
Error: Incorrect attribute value type
on main.tf.json line 22, in [1].resource.azurerm_virtual_network.gork_vnet:
22: "subnet": [
23: {
24: "address_prefix": "10.0.0.0/24",
25: "name": "cunning_brutality",
26: "security_group": ""
27: }
28: ]
Inappropriate value for attribute "subnet": element 0: attribute "id" is
required.
Если я добавлю идентификатор, я получу эту ошибку
Error: "subnet.0.id": this field cannot be set
on main.tf.json line 30, in [1].resource.azurerm_virtual_network.gork_vnet:
30: }
Кроме того, следует отметить, что согласно документам TF, JSON фактически должен быть структурирован как
"subnet": [
{
"cunning_brutality": {
"address_prefix": "10.0.0.0/24",
"name": "cunning_brutality",
"security_group": ""
}
}
]
Но это приводит к ошибке
Inappropriate value for attribute "subnet": element 0: attributes
"address_prefix", "id", "name", and "security_group" are required.
Заключение
К сожалению, моя проверка кода не дала ничего особенно полезного, согласно всей документации, это должно работать. Поэтому любые указания или рекомендации будут высоко оценены.
Ответ №1:
После моей проверки я также сталкиваюсь с тем же результатом. В качестве обходного пути вы можете создать подсеть как отдельный блок вместо вложенного аргумента в файле JSON.
Например,
{
"resource": {
"azurerm_virtual_network":{
"example":{
"address_space": [
"10.0.0.0/16"
],
"dns_servers": [],
"location": "eastus",
"name": "wer5rnis6vnet",
"resource_group_name": "nancyarm"
}
},
"azurerm_subnet":{
"example":{
"name": "wer5rnis6subnet",
"resource_group_name": "nancyarm",
"virtual_network_name" : "wer5rnis6vnet",
"address_prefixes": ["10.0.0.0/24"]
}
}
}
}
Из Terraform docs о Terraform 0.12 и более поздних версиях. Все, что может быть выражено в собственном синтаксисе, также может быть выражено в синтаксисе JSON, но некоторые конструкции сложнее представить в JSON из-за ограничений грамматики JSON. Прочитайте спецификацию синтаксиса HCL JSON.
В этом случае вы также можете выбрать конфигурацию выбора вишни. Вы можете добавить отсутствующие обязательные атрибуты, которые вызвали ошибки в вашем плане, в соответствии с выводом terraform show.
Например,
resource "azurerm_virtual_network" "example" {
address_space = [
"10.0.0.0/16",
]
location = "eastus"
name = "gork_vnet"
resource_group_name = "mork_rg"
subnet {
address_prefix = "10.0.0.0/24"
name = "cunning_brutality"
security_group = ""
}
}
Комментарии:
1. Привет, спасибо за ввод. Я рад знать, что это не только я схожу с ума. Я решил, что постараюсь не извлекать подсеть в ее собственный блок, поскольку это значительно увеличивает сложность моего скрипта. Причина, по которой я не хочу работать с выбором вишни, заключается в том, что объем ресурсов, которые необходимо импортировать, огромен, и это сведет на нет многое из того, что я надеялся выполнить с помощью скрипта. Тем не менее, спасибо за дополнительную информацию и проверку. Приветствую, приятель!
2. Привет, если эта проблема устранена, вы можете принять один ответ.
Ответ №2:
Если конфигурация не будет поддерживаться автоматизированными системами на постоянной основе, я бы предупредил, что кто-то, запрашивающий что-то для поддержки с помощью Terraform, вероятно, ожидает собственный синтаксис Terraform, а не JSON, поскольку этот синтаксис часто считается более простым для чтения и поддержки людьми в будущем.
С учетом сказанного, если вы собираетесь использовать JSON, то существуют различные правила соответствия альтернативного синтаксиса JSON собственному синтаксису, поскольку JSON имеет меньше конструкций, и поэтому конкретная структура JSON может интерпретироваться как одна из множества различных собственных синтаксических структур в зависимости от контекста.
К сожалению, в этом случае кажется, что документация для azurerm_virtual_network
неверна или, по крайней мере, неполная. Из ссылки на реализацию этого типа ресурса я вижу, что в этом subnet
аргументе включен специальный устаревший режим «Атрибуты как блоки», который заставляет Terraform интерпретировать его по-другому, что обратно совместимо с некоторыми неожиданными шаблонами из старых версий Terraform.
Поскольку вы используете синтаксис JSON, атрибуты подраздела как блоки в синтаксисе JSON актуальны в вашем случае. Мы можем видеть, что атрибуты с этим устаревшим режимом обработки представлены в JSON с использованием правил сопоставления выражений JSON, а не правил сопоставления блоков, что означает, что каждый объект в вашем массиве JSON должен иметь допустимое значение типа объекта, выбранного поставщиком для этого блока. Схема для этого типа объекта включает вызываемый атрибут id
, который обычно может быть опущен в собственном синтаксисе, но должен быть явно установлен null
в синтаксисе JSON, чтобы результирующее значение имело правильный тип:
{
...
"subnet": [
{
"address_prefix": "10.0.0.0/24",
"name": "cunning_brutality",
"security_group": "",
"id": null
}
]
...
}
В документации поставщика должно быть указано, когда аргумент использует устаревший режим синтаксического анализа, и ссылка на соответствующую документацию, поэтому отсутствие упоминания об этом, возможно, является ошибкой в azurerm_virtual_network
документации, о которой вы могли бы сообщить разработчикам поставщика в репозитории GitHub поставщика. Но это в стороне, я надеюсь, что этот дополнительный совет выше поможет заставить это работать, если вы не можете использовать более распространенный собственный синтаксис, где эта особая особенность не применяется.