Адаптация Terraform AWS Provider от HashiCorp под Rockit Cloud.
Upstream Name | Upstream Version |
---|---|
Terraform AWS Provider | 4.14.0 |
- Требования
- Общая информация
- Начало работы
- aws-sdk-go
- Тесты
- Документация
- Выпуск релиза
- Публикация провайдера в официальном terraform registry
- Публикация провайдера в private terraform registry
- Использование провайдера
- TODO
- Terraform 0.13+ (запуск приемочных тестов)
- Go 1.21 (сборка провайдера)
- Docker (запуск линтеров для документации)
Провайдер - это плагин для Terraform, который реализует возможность управления ресурсами некоего сервиса (например, облака или БД) через его API. Для каждого ресурса в провайдер добавляется схема и CRUD операции. Информация об API предоставляется в виде отдельного модуля.
Terraform Rockit Cloud Provider реализуется на базе Terraform AWS Provider. Также создан форк модуля с AWS API: C2Devel/aws-sdk-go.
Для публикации провайдера в официальном terraform registry под новым именем
(ранее - aws) форк переименован в
terraform-provider-rockitcloud.
Опубликованный провайдер: https://registry.terraform.io/providers/C2Devel/rockitcloud
Для работы с провайдером требуется установка go (см. требования).
Клонирование репозитория и сборка провайдера:
$ git clone [email protected]:C2Devel/terraform-provider-rockitcloud.git && cd terraform-provider-rockitcloud
...
$ make build
После сборки артефакт terraform-provider-aws
будет доступен в директории $GOPATH/bin
.
Установка переменной окружения $GOPATH
:
$ export GOPATH=$(go env GOPATH)
$ ls $GOPATH/bin/terraform-provider-aws
...
Важно! make build
использует команду go install
, которая не позволяет изменить
имя артефакта - terraform-provider-aws
. Используется только для dev сборок.
Для сборки проекта также можно использовать команду:
$ go build -o terraform-provider-rockitcloud
Артефакт terraform-provider-rockitcloud
будет создан в директории запуска.
Опционально. Установка дополнительных библиотек (линтеры, форматтеры и т.д.): make tools
Артефакты также будут находиться в $GOPATH/bin
.
Важно! Для запуска связанных make
таргетов требуется добавить путь $GOPATH/bin
в $PATH
.
Таргеты для запуска линтеров для кода:
$ make lint
$ make semgrep
Важно! make lint
может выполняться очень долго, тк линтеры анализируют директорию internal/service
целиком.
Можно запускать линтеры по отдельности и на конкретной директории:
$ golangci-lint run -v ./internal/service/paas/...
# в команде нужно будет укзаать все игнорируемые проверки
$ providerlint -c 1 -XS001=false ./internal/service/paas/...
$ make importlint
Обращения к модулю aws-sdk-go (AWS API) перенаправлены на форк
с помощью директивы replace
в go.mod
.
Для локальной разработки можно указать в правой части директивы путь к директории с исходным кодом модуля.
# go.mod
...
replace github.com/aws/aws-sdk-go => <path-to-aws-sdk-go>
Важно! Можно тэггировать изменения модуля и обновлять в go.mod
тэг, но его нельзя будет повторно использовать,
т.к. go не позволяет изменять версии после их публикации.
Важно! Форк aws-sdk-go нельзя вытянуть через go get github.com/C2Devel/[email protected]
.
-
Обновление тега
github.com/C2Devel/aws-sdk-go
:# go.mod ... replace github.com/aws/aws-sdk-go => github.com/C2Devel/aws-sdk-go v1.44.10-new
-
Опционально. Если изменилась upstream версия: обновление тега
github.com/aws/aws-sdk-go
в блокеrequire
.
Не влияет на сборку. -
Обновление зависимостей:
go mod tidy
Важно! go mod tidy
актуализирует все зависимости в go.mod
, т.е. итоговые изменения могут касаться
не только aws-sdk-go.
В проекте есть два типа тестов: unit и acceptance. Они лежат рядом с функционалом (файлы: *_test.go).
Тесты написаны с помощью go testing, для приемочных дополнительно используется пакет acctest.
Запуск unit тестов: make test
Для запуска приемочных тестов требуется установка Terraform (см. требования).
Важно! Тесты используют реальные облачные ресурсы. Требуется доработка тестов для запуска на C2.
Важно! Перед запуском тестов требуется добавить настройки для доступа к API облака в переменные окружения.
Команды:
- запуск всех тестов:
make testacc
. Сейчас запуск приведет к ошибке, тк большинство тестов еще не адаптировано для запуска вне AWS. - запуск конкретного теста:
make testacc TESTS=TestAccEC2EBSVolume_basic PKG=ec2
По запуску и написанию приемочных тестов есть документация.
Информация о провайдере расположена в директориях:
docs/
- инструкции для разработки, roadmap;website/
- документация к провайдеру, которая публикуется в официальном terraform registry (инструкция по документированию от Terraform).
Структура директории website:
website/
|-- docs/
| |-- d/ # набор описаний для terraform data sources
| | |-- <data source>.md
| | |-- ...
| |-- r/ # набор описаний для terraform resources
| | |-- <resource>.md
| | |-- ...
| |
| |-- index.md # стартовая страница
|-- allowed-subcategories.txt # разделы документации
Важно! allowed-subcategories.txt
генерируется при запуске таргета make gen
и содержит информацию обо всех доступных разделах документации. После публикации отображаться будут только непустые разделы.
Опубликованная документация: https://registry.terraform.io/providers/C2Devel/rockitcloud/latest/docs
Для запуска линтеров требуется установка Docker и собственно линтеров (см. установка линтеров).
docs/
: проверяется форматирование markdown файлов и ошибки в тексте (English).
$ make docs-lint
website/
: проверяется форматирование .md файлов, ошибки в тексте (English)
и соответствие документации спецификации terraform registry.
$ make website-lint
$ make docscheck
В website_unsupported/
перенесены гайды и документация для ресурсов, которые не поддерживаются Rockit Cloud API.
Для публикации требуется перенести нужную страницу в соответствующую директорию в website/
.
Для выпуска внутренней документации нужно удостовериться, что все страницы из website/docs/r
и website/docs/d
добавлены в секцию nav:
файла docs/c2/mkdocs.yml
и проставлены в соответствующие разделы. Например, ресурс aws_autoscaling_policy в раздел Auto Scaling.
Релиз провайдера формируется в соответствии с требованиями к публикации в terraform registry.
Подготовка релизных артефактов (сборка под разные архитектуры и ОС, подпись, архивация и т.д.) описана
в .goreleaser.yml
Дополнительная информация: инструкция по созданию релиза провайдера на github от Terraform.
-
Установка goreleaser
- Важно! Для корректной работы утилиты goreleaser должен быть установлен Git как минимум 2.3 версии
$ go install github.com/goreleaser/goreleaser@latest ... $ export GOBIN=$(go env GOPATH)/bin $ $GOBIN/goreleaser -v ...
-
Создание GPG ключа (инструкция от Hashicorp)
- Важно! Требования к ключу:
- Ключ должен быть без пароля
- Тип ключа должен быть RSA
- Размер ключа 4096
- Ключ не должен иметь срока годности
- Название и почта, которые указываются в описании ключа, должны быть обсуждены с ответственными людьми
- Опционально. Привязка ключа к github аккаунту
- Важно! Требования к ключу:
-
Установка переменной
GPG_FINGERPRINT
$ gpg --list-secret-keys --keyid-format LONG ... sec rsa4096/<id> 2022-04-19 [SC] ... $ gpg --list-secret-keys --with-colons --fingerprint <id> | grep fpr | cut -f 10 -d : <fingerprint> $ export GPG_FINGERPRINT=<fingerprint>
-
Создание Personal Access Token с разрешением public_repo (инструкция от github)
- Важно! Скопировать сгенерированный токен можно только сразу после создания
-
Установка переменной
GITHUB_TOKEN
$ export GITHUB_TOKEN=<generated token by github>
Версии провайдера должны соответствовать спецификации Semantic Version и начинаться с v (например, v1.2.3 или v1.2.3-pre). Версия провайдера фиксируется только в виде тэга.
Важно! Не допускается обновление уже выпущенных версий, т.к. могут возникнуть проблемы со скачиванием провайдера из terraform registry.
Стартовая версия: v24.1.0
Важно! Релизы провайдера выпускаются с ветки develop (установлена дефолтной). Ветка main используется для получения обновлений с upstream.
-
Создание релизного PR'а в ветку develop (пример: v24.1.0)
- Опционально. Обновление версии aws-sdk-go, если требуется (см. изменение версии aws-sdk-go)
- Обновление CHANGELOG.md
-
Локальный запуск линтеров и unit тестов на ветке develop + релизный PR
$ make lint $ make docs-lint $ make website-lint $ make test
-
Мердж релизного PR'а
-
Опционально. Включение автопубликации релиза в github (флаг
release.draft
в.goreleaser.yml
)# .goreleaser.yml ... release: draft: false
По умолчанию релиз будет опубликован в origin.
-
Подготовка репозитория: на релизной ветке не должно быть незакоммиченных изменений, untracked файлов
-
Установка релизного тега с версией (см. версионирование) и его публикация
$ git tag v1.2.3 $ git push <remote> v1.2.3
-
Сборка и подпись релизных артефактов. Артефакты будут размещены в директории
dist/
$ $GOBIN/goreleaser release --clean --timeout 180m # Для версий goreleaser выше v1.15.0 $ $GOBIN/goreleaser release --rm-dist --timeout 180m # Для версий goreleaser ниже v1.15.0
-
Опционально. Если на шаге 2 не была включена автопубликация (
release.draft: true
): создание релиза на github и загрузка артефактов:dist/terraform-provider-rockitcloud_{VERSION}_{OS}_{ARCH}.zip
- Для всех архитектур и ОС.
dist/terraform-provider-rockitcloud_{VERSION}_SHA256SUMS
dist/terraform-provider-rockitcloud_{VERSION}_SHA256SUMS.sig
terraform-provider-rockitcloud_{VERSION}_manifest.json
- Файл создается вручную:
cp terraform-registry-manifest.json terraform-provider-rockitcloud_{VERSION}_manifest.json
В описание дублируется запись из CHANGELOG.md.
-
Публикация в приватный реджистри (см. Публикация провайдера в private terraform registry)
-
Выпуск внутренней документации (см. Выпуск внутренней документации)
Дополнительная информация: инструкция по публикации от Terraform.
Важно! Для публикации провайдера в terraform registry требуется хотя бы одна выпущенная версия.
Порядок публикации:
-
Регистрация в terraform registry с помощью github аккаунта
-
Добавление GPG ключа, который использовался для подписи релиза (см. настройка окружения, шаг 2) в настройках профиля
$ gpg --list-secret-keys --keyid-format LONG ... sec rsa4096/<id> 2022-04-19 [SC] ... $ gpg --armor --export <id> -----BEGIN PGP PUBLIC KEY BLOCK----- ...
-
Выбор провайдера в меню Publish -> Provider и публикация
После публикации провайдера для репозитория будет создан webhook на события из группы Releases
.
Новые релизы будут автоматически подтянуты в registry.
Важно! Terraform не позволяет самостоятельно удалять опубликованный провайдер или одну из его версий. Не допускается обновление уже выпущенных версий.
Опубликованный провайдер: https://registry.terraform.io/providers/C2Devel/rockitcloud
Terraform registry может быть организован в виде s3 бакета.
Важно! У бакета должен быть настроен доступ по https
(инструкция).
При включении web-доступа в качестве индексной страницы требуется указать index.json
.
Согласно описанию протокола, terraform registry содержит в себе файлы с версиями провайдеров и метаинформацией для каждой сборки, в которой указаны ссылки на конкретные артефакты.
.well-known/
|-- terraform.json # служебный файл
providers/
|-- c2devel/ # разработчик
|-- rockitcloud/ # имя провайдера
|-- 1.0.0/
| |-- download/
| |-- linux/
| | |-- amd64/
| | | |-- index.json # метаинформация для сборки 1.0.0_linux_amd64
| | |-- ...
| |-- ...
|
|-- versions/
|-- index.json # версии провайдера
.well-known/terraform.json
используется при первом обращении к registry для проверки доступности.
Также в нем указывается базовый url для всех провайдеров.
# .well-known/terraform.json
{
"providers.v1": "/providers/"
}
Исходный вид файла с версиями провайдера:
# providers/c2devel/rockitcloud/versions/index.json
{
"id": "c2devel/rockitcloud",
"versions": [],
"warnings": null
}
После релиза новой версии провайдера (см. релиз) артефакты будут доступны в директории dist/
.
Для загрузки версии в s3 бакет требуется сформировать файлы с версиями и метаинформацией. Их можно получить из официального terraform registry, если провайдер уже опубликован, или сделать самостоятельно в соответствии с протоколом.
Если требуется создание s3 бакета и директорий, см. структура s3 бакета.
Порядок загрузки:
-
Получение версий провайдера. В файле должна присутствовать загружаемая версия
$ curl https://registry.terraform.io/v1/providers/c2devel/rockitcloud/versions --output versions.json
В блоке
versions.<version>.platforms
указаны архитектуры и ОС, под которые версия собиралась. -
Получение метаинформации для выбранных сборок провайдера
$ curl https://registry.terraform.io/v1/providers/c2devel/rockitcloud/<version>/download/<os>/<arch> --output <version>_<os>_<arch>.json
-
Опционально. Сохранение артефактов в собственное хранилище. Артефакты можно скачать по ссылкам в метаинформации или скопировать из директории
dist/
:dist/terraform-provider-rockitcloud_{VERSION}_{OS}_{ARCH}.zip
- Для всех архитектур и ОС.
dist/terraform-provider-rockitcloud_{VERSION}_SHA256SUMS
dist/terraform-provider-rockitcloud_{VERSION}_SHA256SUMS.sig
-
Опционально. Если был выполнен шаг 3: обновление ссылок в метаинформации
-
Обновление s3 бакета:
- обновление файла с версиями:
version.json
->providers/c2devel/rockitcloud/versions/index.json
- загрузка метаинформации для сборок версии:
<version>_<os>_<arch>.json
->providers/c2devel/rockitcloud/<version>/download/<os>/<arch>/index.json
Важно! Файлы должны быть загружены с mime-типом "application/json". Для файлов должен быть открыт доступ на чтение без аутентификации.
- обновление файла с версиями:
Для автоматизации процесса загрузки новых версий в s3 бакет из официального terraform registry можно использовать bash скрипт.
Скрипт анализирует файлы с версиями провайдера в s3 бакете и в официальном registry и для всех версий, которые отсутствуют в бакете, загружает из официального registry файлы с метаинформацией для сборок.
Важно! Файл с версиями в s3 бакете будет приведен к виду официального registry.
Для запуска скрипта требуется установка и настройка утилиты s3cmd (инструкция) и созданный s3 бакет (см. структура s3 бакета).
Переменные окружения скрипта:
TF_REGISTRY_URL
- url terraform registry, по умолчанию:"https://registry.terraform.io/"
S3_REGISTRY_URL
- url s3 registry, обязательноS3_BUCKET_NAME
- имя бакета, обязательноPROVIDER_NAME
- имя провайдера, по умолчанию:"c2devel/rockitcloud"
S3_BACKUP_DIR
- директория для бэкапа бакета, опционально. Если директория не указана, бэкап сделан не будет
Запуск скрипта:
$ cd scripts
$ ./update-s3-registry.sh
...
Для выпуска внутренней документации требуется установка и настройка утилиты s3cmd (инструкция).
Документация публикуется в указанный бакет с помощью скрипта scripts/build-docs.sh
. Перед запуском нужно задать переменную окружения S3_DOCS_BUCKET_NAME
(документация публикуется в бакет docs.tf.k2.cloud
):
$ export S3_DOCS_BUCKET_NAME="docs.tf.k2.cloud"
$ scripts/build-docs.sh
Провайдер в terraform registry: https://registry.terraform.io/providers/C2Devel/rockitcloud
Примеры использования Terraform для C2: C2Devel/terraform-examples
Конфигурация провайдера C2Devel/rockitcloud после его публикации в официальном terraform registry:
# provider.tf
terraform {
required_providers {
aws = {
# case-insensistive
source = "c2devel/rockitcloud"
version = "24.1.0"
}
}
}
provider "aws" {
# Configuration options
}
Важно! В конфигурации в качестве имени провадйера используется aws
, т.к. сохранена схема
именования terraform ресурсов: aws_*. Если используется другое имя (например, rockitcloud
),
Terraform автоматически попытается загрузить провайдер hashicorp/aws.
Если провайдер опубликован в s3 бакете, в поле source
добавляется url бакета без схемы. Например,
tf-registry.rockitcloud.ru/c2devel/rockitcloud
.
Также можно локально собрать артефакт, выполнив команду go build -o terraform-provider-<name>
, и настроить Terraform (v0.14+)
на его использование.
По умолчанию конфигурация Terraform находится в файле ~/.terraformrc
.
Для разработки можно создать отдельную конфигурацию.
Пример dev конфигурации dev.tfrc
, в которой обращение к провайдеру c2devel/<name>
перенаправлено в директорию,
в которой находится артефакт terraform-provider-<name>
:
# dev.tfrc
provider_installation {
dev_overrides {
"c2devel/<name>" = "<absolute-path-to-artifact-dir>"
}
direct {}
}
Установка dev.tfrc
в качестве Terraform конфигурации:
$ export TF_CLI_CONFIG_FILE=<path-to-dev.tfrc>
Важно! Сначала для проекта должен быть выполнен terraform init
(установлены провайдеры, сформирован lock файл),
а потом уже добавлено перенаправление на свой артефакт. Повторно запускать terraform init
не требуется и
не рекомендуется, т.к. Terraform будет пытаться установить все провайдеры из официального registry, в том числе и
переопределенный. Это может привести к ошибкам.
- Настройка github actions: прогон тестов, прогон линтеров, сообщения в PR
- Доработка acceptance тестов для запуска на C2
- Использовать в
make build
командуgo build
вместоgo install
для того, чтобы иметь возможность задать имя артефакта - Обновить схему именования ресурсов: aws_* -> rockitcloud_*,
чтобы иметь возможность использовать в конфигурации в качестве имени провайдера
rockitcloud
. Потребуется проверка совместимости с aws конфигурациями