Что такое HCL
HCL расшифровывается как HashiCorp Configuration Language, язык, придуманный компанией HashiCorp специально для описания инфраструктуры. На нём вы пишете «я хочу один S3-бакет с такими-то тегами и один EC2-инстанс рядом», а Terraform превращает это в API-вызовы к облаку.
HCL не язык программирования в полном смысле. Это декларативный язык: вы описываете желаемое состояние, а не последовательность шагов. В этом главное отличие от Python или bash.
Из чего состоит файл .tf
HCL-файл, это набор блоков. Каждый блок описывает одну сущность: ресурс, переменную, провайдер, output. Базовая структура блока:
тип_блока "первая_метка" "вторая_метка" {аргумент_один = "значение"
аргумент_два = 42
вложенный_блок {под_аргумент = true
}
}
Конкретный пример, описание S3-бакета:
resource "aws_s3_bucket" "demo" {bucket = "my-unique-name-12345"
tags = {Owner = "student"
Project = "terraform-hello"
}
}
Здесь:
resource, тип блока (мы создаём ресурс)."aws_s3_bucket", первая метка, говорит что именно за ресурс."demo", вторая метка, наше внутреннее имя для этого бакета. Внутри файла его можно зватьaws_s3_bucket.demo.bucket,tags, аргументы блока.
Типы блоков, которые встречаются чаще всего
resource, создать что-то в облаке (бакет, виртуалку, базу).data, прочитать что-то из облака (узнать ID существующей подсети). См. tf-resource-block и tf-data-source позже.variable, входной параметр конфигурации (имя бакета снаружи).output, что вернуть наружу (ID созданного бакета).provider, какой провайдер используется и с какими настройками (AWS, GCP, Azure).terraform, мета-блок с настройками самого Terraform: какие версии провайдеров, где хранить state.locals, вычисляемые внутренние значения.module, подключить переиспользуемый модуль (в beginner-треке не используется).
Выражения и интерполяция
Значения в HCL не обязательно строки. Можно ссылаться на другие ресурсы, вызывать функции, считать арифметику:
resource "aws_s3_bucket" "logs" { bucket = "${aws_s3_bucket.demo.bucket}-logs"# читай так: «возьми атрибут bucket у ресурса aws_s3_bucket.demo и добавь -logs»
}
output "bucket_count" {value = length(aws_s3_bucket.demo.tags)
# length, встроенная функция, считает элементы списка/map
}
Конструкция ${...} называется interpolation, подстановка. В современном HCL её часто можно опускать, если выражение. Это единственное содержимое строки: bucket = aws_s3_bucket.demo.id работает так же, как bucket = "${aws_s3_bucket.demo.id}".
Комментарии
В HCL три способа закомментировать:
# однострочный (самый частый)
// тоже однострочный (наследие C-стиля)
/*
многострочный
блок-комментарий
*/
Используйте #, это конвенция HashiCorp.
Чем HCL отличается от JSON
JSON тоже валидный формат для Terraform, называется JSON syntax (.tf.json). Но в реальной работе никто его не пишет руками. Причины:
- В HCL можно писать комментарии. В JSON, нельзя.
- В HCL не нужны кавычки вокруг ключей и запятые в конце списков.
- В HCL читаемые многострочные строки через
heredoc(<<EOF ... EOF). - В HCL легче ссылаться на другие ресурсы, без вложенных кавычек.
JSON-формат полезен только если HCL-файл генерируется другой программой.
Подводные камни
- Метки блоков чувствительны к регистру.
ResourceилиRESOURCE, невалидно, толькоresource. - Имена ресурсов внутри одного типа должны быть уникальными. Два
resource "aws_s3_bucket" "demo", ошибка, даже если bucket-name разный. - Запятая после последнего элемента списка/map, необязательна, но не запрещена. В отличие от JSON.
- Heredoc сохраняет переводы строк. Если в строке нужны переносы, используйте
<<-EOF(с дефисом): он убирает лидирующие отступы.