linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • База знаний
  • Шпаргалка
  • Capstone
  • Собеседование
home/terraform/kb/Провайдеры/tf-archive-external-http

kb/providers ── Провайдеры ── intermediate

archive, external, http: данные снаружи в HCL

Три провайдера для получения данных снаружи Terraform. `archive`, упаковка файлов в zip (lambda code, layers). `external`, вызов любого скрипта с JSON I/O. `http`. GET-запрос к URL, парс ответа. Все три, data sources, читают, не пишут. Полезны где declarative HCL не доходит.

view as markdownaka: terraform-archive, terraform-external, terraform-http-data

Зачем

HCL, декларативный. Иногда нужно что-то построить: упаковать директорию в zip, прочитать JSON из CI-secret-store, спросить current IP у ifconfig.io. Три data-провайдера закрывают этот gap, оставаясь в парадигме «всё описано в HCL».

archive_file

Упаковка локальных файлов в zip. Главный кейс, aws_lambda_function.filename.

hcl
terraform {
  required_providers {
    archive = {
      source  = "hashicorp/archive"
      version = "~> 2.6"
    }
  }
}
data "archive_file" "lambda" {
  type        = "zip"
  source_file = "${path.module}/lambda/handler.py"
  output_path = "${path.module}/lambda.zip"
}
resource "aws_lambda_function" "demo" {
  function_name    = "demo"
  filename         = data.archive_file.lambda.output_path
  source_code_hash = data.archive_file.lambda.output_base64sha256
  handler          = "handler.main"
  runtime          = "python3.12"
  role             = aws_iam_role.lambda.arn
}

Главное:

  • output_base64sha256, хэш zip-содержимого. Передаётся в Lambda как source_code_hash. Если код поменялся → хэш меняется → Lambda замечает → перевыкатывает. Без этого Terraform не увидит изменения в исходниках и не обновит лямбду.

Целая директория

hcl
data "archive_file" "lambda" {
  type        = "zip"
  source_dir  = "${path.module}/lambda/"
  output_path = "${path.module}/lambda.zip"
  excludes = [
    "__pycache__",
    "*.pyc",
    "tests/**",
  ]
}

Удобно для лямбд с requirements/node_modules.

Inline-источник

hcl
data "archive_file" "config" {
  type        = "zip"
  output_path = "${path.module}/config.zip"
  source {
    content  = jsonencode({ feature_flags = { ... } })
    filename = "config.json"
  }
}

Файл генерируется из HCL значения. Полезно для config-payload'ов которые считаются динамически.

external

Вызов произвольного скрипта. Скрипт принимает JSON в stdin, отдаёт JSON в stdout.

hcl
terraform {
  required_providers {
    external = {
      source  = "hashicorp/external"
      version = "~> 2.3"
    }
  }
}
data "external" "git_info" {
  program = ["bash", "${path.module}/scripts/git-info.sh"]
  query = {
    repo = path.cwd
  }
}
output "git_commit" {
  value = data.external.git_info.result.commit
}

scripts/git-info.sh:

bash
#!/usr/bin/env bash
set -euo pipefail
eval "$(jq -r '@sh "REPO=\(.repo)"')"
COMMIT=$(git -C "$REPO" rev-parse HEAD)
BRANCH=$(git -C "$REPO" rev-parse --abbrev-ref HEAD)
jq -n --arg c "$COMMIT" --arg b "$BRANCH" '{commit:$c, branch:$b}'

Что важно:

  • Скрипт должен вернуть JSON-объект, где все значения, строки. Нельзя число, нельзя nested object. Это ограничение API.
  • Скрипт должен быть idempotent. Terraform может вызвать его на каждом plan. Если скрипт меняет состояние мира, плохо.
  • Скрипт работает с правами того, кто запустил terraform.

Используется когда:

  • Нужно прочитать значение из vault/CI secret manager у которого нет Terraform-provider'а.
  • Нужно вычислить значение через сложную логику (curl + jq + sed).
  • Build-time integration: «вытащи docker tag из CI».

Анти-кейс: не делай external для side-effects. Это data source, не ресурс.

http

GET-запрос к URL, ответ в data source.

hcl
terraform {
  required_providers {
    http = {
      source  = "hashicorp/http"
      version = "~> 3.4"
    }
  }
}
data "http" "my_ip" {
  url = "https://ifconfig.io"
}
resource "aws_security_group_rule" "allow_my_ip" {
  type              = "ingress"
  from_port         = 22
  to_port           = 22
  protocol          = "tcp"
  cidr_blocks       = ["${chomp(data.http.my_ip.response_body)}/32"]
  security_group_id = aws_security_group.bastion.id
}

Аргументы:

  • url, endpoint.
  • request_headers, map, для auth/User-Agent.
  • method, по умолчанию GET, можно POST/PUT/DELETE.
  • request_body, body для POST.

Атрибуты:

  • response_body, текст ответа.
  • status_code. HTTP-код.
  • response_headers, map.

Валидация status_code:

hcl
data "http" "config" {
  url = "https://config.example.com/feature-flags"
  lifecycle {
    postcondition {
      condition     = self.status_code == 200
      error_message = "Config server returned ${self.status_code}, expected 200"
    }
  }
}

Если упало, apply остановится с понятным сообщением. См. Урок про precondition/postcondition.

Когда что использовать

ЗадачаProvider
Упаковать lambda-код в ziparchive_file
Прочитать значение из произвольного источника (vault, CLI)external
Получить JSON от REST APIhttp (или external + curl)
Прочитать что-то из git/AWS CLIexternal
Динамически узнать current public IPhttp
Сгенерить файл из переменнойarchive_file с source.content

Подводные камни

  • Все три, data источники. Вычисляются на каждом plan. Если external зовёт долгий скрипт / http ходит на медленный endpoint, плата на каждом plan. Кэшируй на стороне самого скрипта/API.

  • external-скрипт ловит всё что не int/string. Возвращает 42 как число. Terraform упадёт. Превращай в строку: {"count":"42"}. Парсить число обратно, через tonumber(data.external.x.result.count).

  • http не следует за redirect-ами по умолчанию. Включается follow_redirects = true. Чтобы поймать первый 301, оставь дефолт.

  • archive_file использует mtime, не content-hash для idempotency. Точнее, использует hash содержимого внутри. Это правильно, terraform plan стабилен. Но если в zip попадают файлы которые меняются на каждом билде (timestamps в byte-code): на каждом plan будет diff. Чисти такие файлы через excludes.

  • http без auth, для public endpoints. Если endpoint требует bearer-token, передавай через request_headers = { Authorization = "Bearer ${var.token}" }. Токен попадает в state, пометь как sensitive.

  • external, security risk. Скрипт исполняется с правами terraform-юзера. Если HCL приходит из недоверенного источника, это remote code execution. Не используй external в reusable модулях, которые качают чужие.

  • http.response_body всегда строка. JSON-ответ нужно парсить jsondecode(data.http.x.response_body). Не пытайся писать data.http.x.response_body.field, это string indexing, не object access.

  • LocalStack не нужен для этих провайдеров. Все три не ходят в AWS. Тесты с ними, чистый HCL.

§ команды

bash
terraform plan

archive_file пересоберёт zip если файлы поменялись. external/http запустятся заново. Видишь чтения в начале plan.

bash
terraform refresh

Перечитать все data sources. Полезно когда внешний источник изменился, а apply ты делать не готов.

bash
terraform console

Можно вытащить data.archive_file.x.output_base64sha256 и сравнить с предыдущим. Дебаг 'почему лямбда пересоздаётся'.

§ см. также

  • tf-data-sourcedata-блок: читаем то, что уже есть в облакеdata, это блок, который запрашивает существующую инфру и отдаёт её атрибуты в HCL. Terraform ничего не создаёт; он только читает. Используется чтобы привязаться к ресурсам, которые сделаны не Terraform'ом или живут в другом проекте.
  • tf-utility-providersУтилитарные провайдеры: random, time, null, terraform_dataПровайдеры, которые не управляют облаком, а помогают HCL. `random`, генерация ID/паролей. `time`, задержки и timestamp-метки. `null`, устаревший «нерессурс» для триггеров. `terraform_data`, современная замена `null_resource`, встроена в Terraform. Каждый снимает конкретное ограничение деклеаративного подхода.
  • tf-cloudinit-providercloudinit provider: user_data для EC2 и не толькоProvider `cloudinit` собирает multi-part MIME для `user_data` EC2. `data "cloudinit_config"` принимает несколько `part` (cloud-config YAML, shell-script, jinja и т.п.) и упаковывает их в один blob. Заменяет ручной base64-encoding одной строки и позволяет компоновать конфиг из кусков.
  • tf-resource-blockБлок resource: главный кирпич Terraformresource, это блок, который говорит Terraform «создай мне такую штуку в облаке». У него три части: тип ресурса (что это), имя (как зовём внутри), и аргументы (как настроить). 90% времени в Terraform, это написание таких блоков.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки