Перекрестная публикация из Средний , это пост, который я написал для блога моих работодателей — Пространство Ape Tech
Довольно распространенная задача в OPS состоит в том, чтобы выяснить, как программно управлять сервисом; Часто легко начать с службы с помощью пользовательского интерфейса, но это не масштабируется, и в конце концов мы захотим иметь больше контроля над конфигурацией услуги; Поставщик терраформ может быть инструментом, который дает вам этот контроль.
Чтобы создать поставщика Terraform, вам просто нужно написать логику для управления созданием, чтением, обновлением и удалением (CRUD) ресурса, а Terraform позаботится об остальных; Государство, блокировка, шаблон языка и управление жизненным циклом ресурсов.
Просто посмотрите на список Существующие поставщики Показывает вам, насколько универсальным может быть терраформ. В список входят облачные провайдеры, Kubernetes, DNS Services, GitHub, инструменты мониторинга и поставщики сертификатов TLS.
В Пространство Обезьяна Мы решили, что хотим начать управлять конфигурацией нашей службы метрик, Волновой фронт , программно. Мы все были готовы написать новый инструмент, который позволил бы нам принять предупреждения о шаблонах и панели панелей в YAML, а затем создать их на Wavefront через их API. Мы уже начали писать GO клиент Для API волнового фронта, когда Hashicorp объявил о Выпуск Terraform v0.10.0 , который разделил поставщиков из ядра Terraform, позволяя разрабатывать и выпускать каждого поставщика независимо от Terraform и для создания пользовательских поставщиков.
Итак, мы приступили к созданию Wavefront Terraform Provider Анкет
Как построить собственного поставщика
Чтобы избежать необходимости работать против настоящего API для этого сообщения в блоге, чтобы вы могли следовать, если хотите, я создал небольшой API, который хранит (образно) «предметы». API позволяет создавать, читать, обновлять и удалять элементы. У элемента есть имя, описание и список тегов. Имя предмета должно быть уникальным. Я не буду вдаваться в подробности о работе API, вы можете найти более подробное описание Здесь и код в Terraform-Provider-Items/API Анкет
Клиент, который поставщик Terraform будет использовать для взаимодействия с API, не должен быть реализован в самом поставщике, так как это будет преувеличивать поставщика и означать, что клиент не может использоваться для других целей. Итак, я также написал клиента в Пакет API Анкет
Полный исходный код примера поставщика и API доступен на GitHub Анкет
Начиная
Поставщик, который мы собираемся создать во время этого сообщения в блоге, позволит нам создать элемент на нашем сервере, используя следующий код Terraform:
Плагины Terraform — это двоичные файлы, с которыми Terraform общается через RPC. Можно написать поставщика на любом языке, но на самом деле вы захотите написать его в Go; Terraform предоставляет вспомогательные библиотеки в помощи в письменной форме и тестировании.
Имя хранилища (и, следовательно, каталога), в котором живет ваш поставщик, важно; Все поставщики начинаются с Terraform-Provider-
Все, что после этого представляет имя поставщика. В этом случае я собираюсь на очень творческий Terraform-Provider-Example
Анкет
Далее мы создадим ./main.go
который послужит точкой входа для нашего поставщика. main.go
просто используется, чтобы привести наш поставщик, который мы будем реализовать в отдельном пакете, в данном случае, называемом поставщик
Анкет
Теперь мы создадим пакет поставщиков, в рамках которого будет реализовать вашего поставщика. В пределах поставщик
Пакет, мы создадим Provider.go
и определить Поставщик
функция, которую наш main.go
называется.
Поставщик требует:
- A
Схема
который представляет различные атрибуты, которые мы можем предоставить нашему поставщику через блок поставщика файла Terraform. Обратите внимание, что если значение не будет предоставлено, мы проверим, установлены ли переменные среды. Это полезно, чтобы убедиться, что нам не нужно хранить секреты в блоке провайдера Terraform Files - A
Ресурс -символ
Определяет имена ресурсов, которые есть поставщик и где найти определение этих ресурсов. В этом случае вы можете видеть, что у нас естьexample_item
ресурс, Определение которого является*Схема. Ресурс
возвращенrespressceitem ()
функция, которую мы определим позже - A
ConfigureFunc
который может сделать любую настройку для нас. В этом случае у нас естьProviderConfigure
который беретадрес
,порт
итокен
и возвращает клиента, которого мы будем использовать для общения с API. Обратите внимание наProviderConfigure
возвращаетИнтерфейс {}
Так что мы можем хранить все, что нам здесь нравится
Определение нашего предмета ресурса
Прежде чем мы начнем определять наш ресурс, есть еще несколько соглашений об именах для покрытия:
- Файлы ресурсов названы
resource_ [resourceName] .go
, например,resource_item.go
- Тестовые файлы следуют обычным стандартам именования ресурса
_ [ResourceName] _test
, например,resource_item_test.go
- Мы также можем написать тесты на импорт, которые, согласно соглашению, находятся в файлах с именем
import_ [resourceName] _test.go
, напримерimport_item_test.go
. Хотя эти тесты могут сидеть в пределахresource_ [resourceName] _test.go
файл - Наконец, есть также определения источника данных, которые мы не будем реализовать здесь, но вы можете увидеть у других поставщиков. Они названы
data_source_ [resourceName] .go
Анкет Источники данных позволяют вам получать информацию из ресурсов, которые уже существуют, но вы не хотите управлять.
Начнем с создания resource_item.go
и определение respressceitem ()
функция, которую мы называем из Provider.go
Анкет Это возвращает *Схема. Ресурс
— Определение нашего предмета ресурса.
A схема. Ресурс
Нужна нам, чтобы настроить несколько вещей:
- A
Схема
— Приписывают ресурсы имеет - Ряд функций. Ранее я говорил, что вам просто нужно настроить функции создания, чтения, обновления и удаления для поставщика, есть еще два, существуют и импортируют, я расскажу об этом позже.
Давайте посмотрим на Схема
более детально. Элемент схемы — это _map [String]*схема. Схема
, где строка является именем атрибута и *Схема. Схема
Определяет, что такое атрибут. В этом случае атрибут имя
имеет тип Typestring
это требуется и имеет краткое описание. У него также есть FORCENEW
Постановка True, это потому, что API не позволяет вам изменить имя элемента после его создания, поэтому Terraform должен был уничтожить ресурс и создать его снова, чтобы это произошло.
Наконец, есть Validatefunc
что является функцией с подписью (v interface {}, k string) (ws [] string, es [] error)
Где V
Значение атрибута, которое вам нужно использовать для получения утверждения типа для извлечения фактического типа, k
Имя атрибута («Имя» в данном случае) и возвращает кусок предупреждений (струны) и кусок ошибок.
ValidationFunc
используется для имя
Атрибут — это validateName
Функция:
Он возвращает ошибку, если имя имеет какое -либо пробелое (API не разрешает пробел по именам). Это мешает нам делать звонки API, которые, как мы знаем, потерпит неудачу.
Описание
Атрибут аналогичен имени, но не заставляет новый ресурс и не имеет фан -проверки.
теги
Атрибут имеет несколько различий. Это типа Набранная
, что похоже на список, но где порядок не имеет значения. Вы можете использовать Typalist
Когда вы можете быть уверены, что API всегда вернет список в одном и том же порядке, в противном случае у вас всегда будут изменения для подачи заявления. Вы также заметите, что теги имеют Elem
Поле, которое позволяет нам определить тип, который хранится в наборе (или списке), в данном случае, строка.
В нашем случае API намеренно возвращает теги в случайном порядке. Вы можете попробовать изменить набранную на Typelist, чтобы увидеть, что (почти) всегда будут изменения, применяемые из -за переупорядочения тегов.
Также стоит отметить, что когда у вас есть Набранная
или Typelist
Elem
Поле может быть типа & схема. Ресурс
, что допускает более глубокую структуру ресурсов. Например, так блокирует слушатель Определены ресурс AWS_ELB .
Также обратите внимание, что теги не являются обязательным атрибутом, а вместо того, чтобы просто настраивать Требуется
Чтобы false (это значение по умолчанию), мы установили Необязательно
к истинному. Либо Требуется
или Необязательно
должно быть правдой
Функции
Функции создания, чтение, обновление и удаление — это функции с подписью (D *Схема. ResourceData, m интерфейс {})
ошибка. Где D
По сути, схема, которую мы определили выше, но с добавленными значениями, например, Атрибут «Имя» имеет значение, которое мы можем отправить в наш API.
m
это Интерфейс {}
вернулся из ConfigureFunc
в Provider.go
, что в нашем случае является нашим клиентом для беседы с сервером.
Каждая из функций CRUD по сути просто называют свои соответствующие методы в клиенте, но есть несколько вещей, которые следует отметить:
- Когда вы создаете ресурс, вам необходимо установить идентификатор ресурса Terraform, это делается с использованием
дюймовый SETID Метод
Анкет Идентификатор, как правило, является тем, что API использует, чтобы уникально идентифицировать элемент, в нашем случае имя является идентификатором, поэтому мы используем это —D.setid (пункт. Имя)
- Установка идентификатора на пустую строку указывает на Terraform, что элемент больше не существует. Итак, в
ResourceCeedEleteTem ()
Функция мы называемd.setid ("")
После удаления предмета. Мы также делаем это в ResourcereAditem Функция, если мы получим ошибку, и эта ошибка содержит «не найдена» - Для каждого из этих методов мы получаем клиента от
m
, поскольку это интерфейс, мы должны утверждать тип как тип клиента —Apiclient. (*Клиент. Клиент)
Как основная структура данных для D *Схема. Resourcedata
В конечном итоге становится интерфейсом, а не твердым типом, мы в конечном итоге делаем много утверждения типа. На небольшом ресурсе, подобном нашему элементу, достаточно легко сделать это в рамках функции, но для более крупных ресурсов, возможно, стоит разделить их на отдельные функции.
В resourcecreateitem
Функция, мы видим, что используем d. Получить
Чтобы получить значения из ресурса, который мы хотим передать API через клиент, и что мы должны выполнить утверждение типа в результате d.get ("имя"). (строка)
.
Function Function ( resourceExistsItem ()
) немного отличается тем, что не изменяет состояние терраформ и не обновляет какой -либо ресурс на сервере; Он просто используется, чтобы проверить, существует ли ресурс. Он имеет немного отличную подпись функции, чем функции CRUD в том смысле, что он также возвращает Bool, чтобы указать, существует ли ресурс — ResourceExistsItem (D *Schema. ResourceData, m интерфейс {}) (bool, ошибка)
Наконец, существует функция импорта, которая используется для импорта ресурса в Terraform, функция импорта — это реализация & схема. Resourceimporter
Анкет Terraform обеспечивает реализацию этого под названием схема. ImportStatePassThrough
, что, по -видимому, работает для большинства вариантов использования И вы всегда можете написать свою собственную реализацию, если вам нужно.
Конец части 1
На этом этапе у нас есть функциональный поставщик терраформ, вы можете собрать его и начать создавать Предметы с терраформ. Однако отсутствует важная часть — Тесты! Во второй части мы добавим тесты нашему поставщику и рассмотрим, как мы получаем Terraform, чтобы использовать поставщика.
Оригинал: «https://dev.to/nathmclean/creating-a-terraform-provider—part-1-3i28»