Spec-Zone.ru › OpenTofu 1.9

Синтаксис конфигурации JSON

Большинство конфигураций OpenTofu написаны с использованием собственного синтаксиса языка OpenTofu, который разработан так, чтобы его было относительно легко читать и изменять.

OpenTofu также поддерживает альтернативный синтаксис, совместимый с JSON. Этот синтаксис полезен при программном создании частей конфигурации, поскольку для подготовки сгенерированных файлов конфигурации можно использовать существующие библиотеки JSON.

Синтаксис JSON определяется в терминах собственного синтаксиса. Всё, что можно выразить с помощью собственного синтаксиса, можно выразить и с помощью синтаксиса JSON, однако некоторые конструкции сложнее представить в JSON из-за ограничений грамматики JSON.

OpenTofu ожидает собственный синтаксис в файлах с суффиксом .tf или .tofu, а синтаксис JSON — в файлах с суффиксом .tf.json или .tofu.json.

Низкоуровневый синтаксис JSON, как и собственный синтаксис, определяется спецификацией под названием HCL. Для работы с OpenTofu не обязательно знать все подробности синтаксиса HCL или его отображения в JSON, поэтому на этой странице кратко описаны наиболее важные различия между собственным синтаксисом и синтаксисом JSON. Если вас интересуют подробности, полное описание синтаксиса JSON для HCL можно найти в его спецификации.

Приоритет расширений​

Если в каталоге присутствуют файлы .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-файла​

В корне любой конфигурации OpenTofu на основе JSON находится объект JSON. Его свойства соответствуют типам блоков верхнего уровня языка OpenTofu. Например:

Блок кода
{
  "variable": {
    "example": {
      "default": "hello"
    }
  }
}

Каждое свойство объекта верхнего уровня должно соответствовать имени одного из ожидаемых типов блоков верхнего уровня. Типы блоков, для которых требуются метки, например variable выше, представлены одним вложенным объектом для каждого уровня меток. Для блоков resource требуются две метки, поэтому необходимы два уровня вложенности:

Блок кода
{
  "resource": {
    "aws_instance": {
      "example": {
        "instance_type": "t2.micro",
        "ami": "ami-abc123"
      }
    }
  }
}

После всех вложенных объектов, представляющих метки, ещё один вложенный объект представляет тело самого блока. В приведённых выше примерах указаны аргумент default для variable "example", а также аргументы instance_type и ami для resource "aws_instance" "example".

Вместе две приведённые выше конфигурации эквивалентны следующим блокам в собственном синтаксисе:

Блок кода
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 встречается в месте, где ожидаются произвольные выражения, её значение сначала разбирается как [шаблон строки][], а затем вычисляется для получения окончательного результата.

Если заданный шаблон состоит только из одной последовательности интерполяции, результат его выражения используется напрямую, без предварительного преобразования в строку. Это позволяет использовать в синтаксисе JSON выражения, результатом которых являются значения не строкового типа:

Блок кода
{
  "output": {
    "example": {
      "value": "${aws_instance.example}"
    }
  }
}

У объявленного выше output "example" в качестве значения используется объект, представляющий заданный блок ресурса aws_instance, а не строковое значение. Это особое поведение не применяется, если шаблон содержит какие-либо литеральные последовательности или управляющие последовательности; в таких случаях всегда создаётся строковое значение.

Отображение вложенных блоков​

Если свойство объекта JSON имеет имя вложенного типа блока, его значение представляет один или несколько блоков этого типа. Значением свойства должен быть объект JSON или массив JSON.

Самый простой случай — представление одного блока заданного типа, если этому типу не требуются метки, как в случае вложенного блока lifecycle, используемого в блоках resource:

Блок кода
{
  "resource": {
    "aws_instance": {
      "example": {
        "lifecycle": {
          "create_before_destroy": true
        }
      }
    }
  }
}

Приведённый выше пример эквивалентен следующей конфигурации в собственном синтаксисе:

Блок кода
resource "aws_instance" "example" {
  lifecycle {
    create_before_destroy = true
  }
}

Если для вложенного типа блока требуется одна или несколько меток либо можно указать несколько блоков одного типа, отображение становится немного сложнее. Например, для вложенного типа блока provisioner, используемого в блоках resource, требуется метка с указанием используемого средства подготовки, а порядок блоков средств подготовки важен для определения порядка операций.

В следующем примере на собственном синтаксисе показан блок 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:

Блок кода
{
  "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"].
  • ignore_changes в блоке lifecycle: если задано значение all, необходимо указать одну строку "all". В противном случае следует использовать массив строк JSON, содержащих ссылки на свойства, например ["ami"].

Специальная обработка также применяется к аргументу type любых блоков connection, расположенных непосредственно внутри блока resource или вложенных в блоки provisioner: заданная строка интерпретируется буквально, а не разбирается и вычисляется как шаблон строки.

Блоки 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​

Значением свойства объекта JSON, представляющего тип блока locals, должен быть объект JSON, имена свойств которого — это имена объявляемых локальных значений:

Блок кода
{
  "locals": {
    "greeting": "Hello, ${var.name}"
  }
}

Значение каждого из этих вложенных свойств интерпретируется как выражение.

Блоки module​

Метааргумент 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 обычно интерпретируются буквально, за исключением блока backend, который поддерживает выражения. Остальные параметры не принимают ссылки на именованные объекты или вызовы функций, поэтому значения строк не рассматриваются как шаблоны строк.

Поскольку в каждом блоке terraform разрешён только один блок backend, для его представления можно использовать компактное отображение блока: вложенный объект с одним свойством, имя которого соответствует типу бэкенда.

Блок кода
{
  "terraform": {
    "required_version": ">= 0.12.0",
    "backend": {
      "s3": {
        "region": "us-west-2",
        "bucket": "acme-tofu-states"
      }
    }
  }
}

Copyright (c) The OpenTofu Authors
Copyright (c) 2014 HashiCorp, Inc.
Mozilla Public License, version 2.0
https://opentofu.org/docs/v1.9/language/syntax/json/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API