- Предварительные условия
- Шаг 1 — структура папки модуля репо
- Шаг 2 — Типы тестирования
- Шаг 3 — Статический анализ
- Шаг 4 — модульное тестирование
- Шаг 5 — Интеграционное тестирование
- Шаг 6-сквозное тестирование
- Вывод
В разработке программного обеспечения код тестирования является обычной практикой. Разработчики программного обеспечения должны иметь возможность проверять части своего кода, чтобы убедиться, что он работает автоматизированным образом. Сфера разработки инфраструктуры принимает лучшие практики программного обеспечения для создания и управления кодом инфраструктуры, а также с этим тестирование. Вы должны писать тесты для вашего кода Terraform.
Письменные тесты для Terraform обеспечивают много преимуществ, которые облегчают жизнь как разработчика инфраструктуры. Автоматизированные тесты обеспечивают более быструю обратную связь. Больше не нужно вносить изменения в конфигурацию терраформ и вручную запустить терраформ применить
и затем проверить портал Azure, чтобы убедиться, что изменение существует. Вместо этого мы можем использовать такие инструменты, как Terratest, чтобы выполнить эти шаги для нас и позволить нам проверять наши модули намного быстрее, чем мы могли бы вручную. Мы не только получаем более быстрые отзывы, но и меньше ошибок. Автоматизация тестов для каждого возможного сценария в конфигурации Terraform обеспечивает лучшее покрытие кода и может быть намного быстрее улавливать ошибки. Тесты придают нам повышенную уверенность в наших изменениях и обеспечивают большую предсказуемость для наших изменений. Теперь мы можем точно предсказать, что наш код развертывает то, что мы разработали его для развертывания, не уничтожая другие ресурсы.
Одно распространенное заблуждение заключается в том, что, поскольку терраформ является декларативным, нам не нужно писать для этого тесты. Мы уже объявляем ресурс, который должен существовать. Если есть проблема с предоставлением этого ресурса, Terraform автоматически предоставляет ошибку. Это действительный момент, поэтому, когда мы говорим о тестировании нашего кода Terraform, мы хотим написать тесты на проверки здравомыслия, условную логику и результаты переменной в нашем коде. Например, написание теста для следующего кода для создания группы ресурсов добавит минимальную выгоду:
resource "azurerm_resource_group" "rg" { name = "rg-myrg" location = var.location }
Если бы мы написали в чеке, чтобы убедиться, что группа ресурсов развернется в соответствующем месте, это будет избыточная проверка. Группа ресурсов будет автоматически встроена в определенное место, которое мы указываем, и, если она не успешной, событие ошибки происходит изначально через Terraform. Написание сотен тестов таким образом может стать более нагрузкой на обслуживание, поскольку нам придется постоянно изменять тест, чтобы не отставать от изменений в модуле.
С другой стороны, написание теста для примера ниже будет более полезным, поскольку он содержит большую дисперсию в результате и потенциально может быть изменено, когда изменения вносятся в модуль:
resource "azurerm_resource_group" "rg" { name = "rg-myrg" location = var.environment != "Production" ? "southcentralus" : "northcentralus" }
В этом руководстве мы собираемся клонировать репозиторий модуля и пройтись по написанию и проведению тестов для него.
Предварительные условия
Прежде чем начать, вам нужно настроить следующее:
- Azure Подписка Анкет
Поскольку мы будем писать тесты в Go, нам понадобится среда, настроенная для написания этих тестов. Мы собираемся использовать кодексы Visual Studio для прохождения этого руководства. Visual Studio Codespaces — это онлайн -версия кода Visual Studio. Это позволяет нам автоматически развернуть среду с помощью репозитория кода, чтобы мы могли погрузиться в создание тестов с минимальной настройкой.
Примечание: Мы будем использовать среду базового размера для нашего Visual Studio Codespace. Вычисление для этой услуги будет размещен в вашем арендаторе Azure, поэтому будут связаны некоторые обвинения. Средняя стоимость базовой среды составляет около 0,08 доллара в час. Кроме того, среда может находиться в «приостановленном» и «активном» состоянии, которое еще больше снижает цены. Для получения дополнительной информации о выставлении VSC, ознакомьтесь с ценовая страница Анкет
Чтобы создать среду Codespaces, перейдите к Visual Studio Codespaces Входите в систему и войдите в свои учетные данные Azure. Обязательно используйте Google Chrome, так как Firefox и Edge еще не поддерживаются. После входа в систему нам будет представлена следующая страница ниже. Выберите Создать Codespace :
Далее нам нужно создать план выставления счетов. План выставления счетов соединяет среду Visual Studio Codespace с нашей подпиской Azure. Выберите место, которое имеет смысл для вас. Кроме того, вы можете ввести имя плана в соответствии с вашими стандартами именования Azure. Имя плана — это имя ресурса Azure, который развертывает вашу подписку. Далее нам нужно указать группу ресурсов для размещения ресурса Visual Studio Codespace. Когда закончите настройку этих настроек выберите Создать :
Теперь мы можем настроить наше кодексы; Это среда Visual Studio. В нашем плане мы могли бы иметь несколько кодексов, если хотим. Введите Имя кода для кода. Под GIT Repository Вставьте в следующем GitHub Repo:
https://github.com/allanore/terraform-azure-testing
Repo Github содержит код для модуля Terraform, для которого мы создадим тесты в этом руководстве. Есть также post-create.sh Скрипт в этом репо, который автоматически устанавливает нужные инструменты для нашей среды, такие как Go и Terraform. Под Тип экземпляра , выберите основной тип. Далее, выберите Создать Чтобы наконец создать нашу среду VSC:
Мы должны увидеть, как наша среда начинает строить, а сценарий Post-create.sh автоматически выполняет и устанавливает наши инструменты и расширения. Мы устанавливаем Go, Terraform и несколько других инструментов:
Примечание: Возможно, вам придется обновить браузер в какой -то момент, чтобы получить этот экран.
Однажды Настройка Codespace Раздел показывает завершенное, мы готовы перейти к просмотру структуры папок этого репозитория:
Шаг 1 — структура папки модуля репо
Прежде чем мы сможем написать наши тесты, нам нужно знать немного больше о том, что делает этот модуль и структуру репо. Функция этого модуля Terraform состоит в том, чтобы развернуть виртуальную сеть. Существуют также подмодули для создания группы сетевой безопасности и виртуальной сети. В Visual Studio Codespaces вы должны увидеть следующую структуру папок с левой стороны:
В основе этого репо мы можем увидеть несколько файлов, у нас есть наши .gitignore
Файл, который содержит список типов файлов, которые мы не хотим сохранять в управлении источником, например .tfstate. Далее у нас есть наш .pre-commit-config.yaml
Файл, который содержит список инструментов для выполнения на каждом коммите GIT. Мы углубимся в это на более позднем шаге. Наконец, у нас есть наши файлы конфигурации Terraform main.tf
, output.tf
и переменные.tf
. Это корневые файлы Terraform и выполняют базовую функцию нашего модуля, который состоит в том, чтобы создать виртуальную сеть и подсети.
Теперь, когда мы прошли через файлы в корневой папке этого модуля, давайте пройдемся по каждой папке, чтобы у нас было лучшее понимание:
- .devcontainer — Эта папка используется только для автоматизации среды Visual Studio Codespace. Это не влияет на наш модуль Terraform.
- .AsureDevops — Содержит наш конвейер CI для Azure DevOps. В этом руководстве мы не будем переходить через Azure DevOps, но если вы хотите сделать это руководство дальше и добавить этот репозиторий в трубопровод Azure DevOps, это файл YML со всеми необходимыми шагами.
- Примеры — Папка примеров служит двум целям. Во -первых, это служит документацией о том, как использовать модуль. Во -вторых, это служит кодом Terraform, который мы можем использовать для тестирования. Мы можем выполнить эти примеры в наших тестовых файлах, чтобы выдержать ресурсы, с которыми мы можем проверить. В папке примеров есть две подпапки. У каждого есть код для выполнения различных задач модуля. Сеть Папка содержит код для стояния в виде виртуальной сети и группы безопасности сети. Vnet-Peering Папка содержит код для стояния две виртуальные сети, а затем взорвать их вместе.
- модули — Папка модулей содержит наши подмодулы или Помощные модули которые предоставляют дополнительные функции, такие как создание группы сетевой безопасности или однорангога виртуальной сети. Это дополнительные модули, которые обеспечивают большую гибкость и опции для тех, кто использует модуль.
- тест — Здесь будут жить наши тестовые файлы.
Лучшая практика в Terraform — разделить задачи или услуги на модули. Мы хотим использовать наши модули в качестве строительных блоков для создания инфраструктуры по одному элементу за раз. С точки зрения разработчика можно подумать о таких функциях. Где каждый модуль выполняет тяжелую работу определенной задачи:
Наша инфраструктура встроена в небольшие единицы, такие как модули, позволяет нам писать для них тесты. Вы не можете написать тест на конфигурацию Terraform, которая составляет тысячи строк кода. Это также дает нам меньший радиус взрыва при внесении изменений в код. Если я внесу изменения в свой модуль веб -приложений, я не подвергаю риску всего приложения.
Несмотря на то, что существует меньший радиус взрыва, все еще существует потенциал для разрушения инфраструктуры при внесении изменений в модули, поэтому должен быть тщательный автоматический способ проверить наши модули и часто их проверять. Затем мы рассмотрим различные типы тестов, которые мы можем написать.
Шаг 2 — Типы тестирования
Есть четыре основных типа тестирования. Эти термины свободно классифицируются в инфраструктуре как мир кода. Мы все еще находимся в детских этапах, и не было стандартизированного определения для каждой категории. Мы будем идти по тому, как Gruntwork определяет тестирование в Terraform Анкет Gruntwork — это компания, которая предоставляет Terraform модули компаниям, которые хотят иметь IAC в своей среде, но не имеют навыков или времени для создания своих собственных. Они имеют многолетний опыт разработки инфраструктуры в Terraform, а также являются создателями Terratest, который является инструментом, который мы будем использовать для некоторых из наших тестов.
Это четыре основных типа тестов:
- Статический анализ — Код тестирования без его запуска.
- ЕДИНЦИОННЫЕ Тестирование — Тестирование одного блока.
- Интеграционное тестирование — Тестирование функциональности между двумя или более единиц.
- Тонкое тестирование — Тестирование всей инфраструктуры приложения с нуля.
Ниже приведена диаграмма, демонстрирующая стоимость каждого теста. Мы хотим запустить большую часть наших тестов внизу, потому что это самое быстрое и наименее дорогое запуска. Каждый тест также поймает разные типы ошибок. Если мы стремимся поймать большинство ошибок со статическим анализом и модульными тестами, мы получим гораздо большую скорость в разработке, чем если бы мы тестировали ту же ошибку в сквозном тесте.
Шаг 3 — Статический анализ
Статические тесты анализа включают тестирование нашего кода без его запуска. Мы хотим запустить инструмент, который может посмотреть на наш код и проанализировать, есть ли в нем ошибка. Отличный способ провести статическое тестирование анализа-это использование инструмента под названием Pre-Commit. Предварительные пакеты объединяют крючки, чтобы позволить инструментам работать после каждого коммита. Если мы посмотрим на содержимое .pre-commit-config.yaml
Файл в нашем репо, мы видим, что он настроен на запуск нескольких крючков. Мы также можем увидеть URL -адрес репозитория, который содержит все сценарии Git Hook для этих крючков. Это позволяет нам управлять нашими крючками и распространять их среди членов команды гораздо более управляемым. Этот предварительный репо является Gruntwork, они проделали всю работу, чтобы создать крючки и объединить их в предварительный репозиторий для использования сообществом:
repos: - repo: https://github.com/gruntwork-io/pre-commit rev: v0.1.4 hooks: - id: terraform-fmt - id: terraform-validate - id: gofmt - id: golint
В .precommit-config.yaml
, Есть два крючка для Terraform и два для Go. Terraform-fmt это крюк, который запускает Terraform fmt
Команда, которая автоматически форматирует код, чтобы выглядеть красиво с помощью надлежащего расстояния. Terraform-Validate управляет Terraform Validate
командование против нашего кода, чтобы убедиться, что он синтаксически правильный, проверяя без неуместных {}
или неверный синтаксис терраформ.
Давайте дадим этим двум крючкам тест, изменяя некоторый код Terraform. Откройте переменные.tf
Файл в корне репо и добавьте описание в системную переменную. Давайте намеренно использовать аргумент Описания
вместо описание
В нашей переменной, чтобы поймать ошибку в крючке перед набором. Скопируйте фрагмент ниже и перезаписывайте контент в настоящее время для система
переменная:
variable "system" { type = string descriptions = "Name of the system or environment" default = "terratest" }
Сохраните изменения, введя Ctrl + S на клавиатуре. Перед тем, как запустить предварительную работу, нам нужно настроить крючки для этого репозитория. Откройте терминал, введя Ctrl + ~ На клавиатуре и запустите следующую команду:
pre-commit install
Теперь давайте попробуем совершить наши изменения, которые мы внесли в системную переменную в переменные.tf
файл. Когда мы запускаем наш коммит, предварительные крючки для Terraform fmt
и Terraform Validate
запускаются:
git add . git commit -m "this is a test commit to trigger our pre-commit hooks"
Мы должны увидеть на выводе, который Terraform Validate
пробежал и потерпел неудачу. Мы также должны увидеть сообщение об ошибке, описывающее, почему оно не удалось, потому что мы использовали аргумент Описания
вместо Описание
который является правильным аргументом:
Terraform has installed the required providers to support the configuration upgrade process. To begin upgrading your configuration, run the following: terraform 0.12upgrade To see the full set of errors that led to this message, run: terraform validate Error: Unsupported argument on variables.tf line 3, in variable "system": 3: descriptions = "Name of the system or environment" An argument named "descriptions" is not expected here. Did you mean "description"?
Чтобы исправить изменение, переименовать описания
Аргумент Описание
, что должно очистить нашу ошибку неверной синтаксиса. Но на этот раз добавьте большое количество пробелов в по умолчанию
аргумент Это неприглядное форматирование запустит наше Terraform fmt
Предварительный крюк:
variable "system" { type = string description = "Name of the system or environment" default = "terratest" }
Теперь давайте добавим и снова сделаем изменения в GIT:
git add . git commit -m "this is a test commit to trigger our pre-commit hooks"
На этот раз мы видим это Terraform fmt
не удалось. Мы добавили, что там дополнительные места, которые подняли форматирование в нашем коде. Terraform fmt
Автоматически запускает и исправляет эти изменения, когда запускается передний крюк, если он обнаруживает любые внесенные изменения в форматирование, он вызовет сбой, такой как SO:
Примечание: GOFMT
и Golint
Крюки отображаются как пропущенные. Это потому, что мы не изменяли никаких файлов GO. Крюки предварительной коммиты работают только против файлов, которые были изменены, и будут запускаться только по сравнению с каждым типом файла.
Terraform fmt............................................................Failed - hook id: terraform-fmt - files were modified by this hook variables.tf Terraform validate.......................................................Passed gofmt................................................(no files to check)Skipped golint...............................................(no files to check)Skipped
Если мы посмотрим на наш переменные.tf
Файл, мы видим, что Terraform fmt
исправил наши пространства. Теперь мы можем запустить наше добавление и снова посвятить себя, чтобы наконец сохранить все наши изменения. На выводе мы видим, что оба чека проходят на этот раз:
vsonline:~/workspace/terraform-azure-testing$ git add . vsonline:~/workspace/terraform-azure-testing$ git commit -m "this is a test commit to trigger our pre-commit hooks" Terraform fmt............................................................Passed Terraform validate.......................................................Passed gofmt................................................(no files to check)Skipped golint...............................................(no files to check)Skipped [master 9b67894] this is a test commit to trigger our pre-commit hooks 1 file changed, 3 insertions(+), 2 deletions(-)
Теперь наш коммит завершен. Благодаря крючкам с предварительной коммитацией мы можем поймать ошибки, прежде чем они будут привержены коду. Этот процесс делает наши коммиты намного чище и мешает глупым ошибкам быть совершенным контролю источника. Это также помогает с обзорами кода, заполнив синтаксические ошибки. Мы можем быстрее улавливать ошибки в разработке, где, если мы только что внесем изменения, и запустить Terraform для тестирования, нам придется ждать начала этого процесса, прежде чем мы поняли, что наша конфигурация не является синтаксически правильной. Мы можем быстрее выполнять наш код, что ускоряет разработку. Мы также могли бы провести статическое тестирование анализа в трубопроводе CI/CD для анализа нашего плана Terraform.
Terraform Validate
является основным статическим анализом, который мы можем выполнить. В сообществе есть много других инструментов статического анализа, которые обеспечивают большие преимущества. Ниже приведены некоторые из них, чтобы отметить:
Tflint — Поймайте конкретные ошибки поставщика, такие как неправильные размеры виртуальных машин Azure.
Conftest — Проанализируйте файлы плана TF и обеспечивает соблюдение определенных политик и управления.
Чеквов — Безопасность и соответствие на уровне конфигурации Terraform.
Шаг 4 — модульное тестирование
Единый тест включает в себя тестирование одного блока или отдельного компонента. Это самый маленький тестируемый кусок кода, который может быть достигнут. В Terraform мы могли бы написать тесты, которые проверяют блоки ресурсов в нашей конфигурации Terraform, однако многие в сообществе Terraform согласны с тем, что он предлагает очень небольшую ценность. Чтобы написать ценный модульный тест, нам необходимо общаться с поставщиком и встать на инфраструктуру, которая в соответствии с стандартами тестирования программного обеспечения технически не является настоящим модульным тестом. Это интеграционный тест. В разработке инфраструктуры с Terraform Gruntwork определяет модульный тест как тестирование одного модуля сам по себе.
Мы собираемся написать модульный тест для нашего сетевого модуля. Мы создадим тест, который использует Terratest. Terratest — это библиотека GO, построенная Gruntwork, для тестирования Terraform. Наш модульный тест автоматически развернется код Terraform из Примеры/Сеть
Папка, проверка, чтобы гарантировать, что желаемый результат достигнут в Azure с помощью Azure API, затем запустите Terraform Drouss
и снести нашу тестовую инфраструктуру в конце. Процесс такой же, как если бы мы тестировали модуль вручную, за исключением того, что мы его автоматизируем.
Во -первых, нам нужно создать тестовый файл GO под названием terraform_azure_network_test.go
Анкет Чтобы сделать этот файл, щелкните правой кнопкой мыши на тест
Папка в Visual Studio Codespace и выберите новый файл . Затем назовите файл terraform_azure_network_test.go
. Обратите внимание, что файл заканчивается в _test.go
Анкет Этот формат указывает на то, что файл является тестовым файлом GO. Go автоматически рассматривает этот файл как тестовый файл и выполнит его, когда мы запустим нашу тестовую команду позже. Теперь мы создадим основополагающий код для нашего модульного теста.
Базовая установка
Ниже приведен код для настройки базовых тестов. Обычно я использую это в качестве отправной точки для создания теста, а затем расширяюсь оттуда. Скопируйте этот код в terraform_azure_network_test.go
файл:
package test import ( "github.com/gruntwork-io/terratest/modules/terraform" "testing" ) func TestTerraformAzureNetworkingExample(t *testing.T) { t.Parallel() terraformOptions := &terraform.Options{ } // At the end of the test, run `terraform destroy` to clean up any resources that were created defer terraform.Destroy(t, terraformOptions) // This will run `terraform init` and `terraform apply` and fail the test if there are any errors terraform.InitAndApply(t, terraformOptions) }
Давайте рассмотрим все части и части кода. Начиная с вершины, у нас есть Пакет Тест
объявляя, что название нашего пакета — тест (который описывает цель нашего пакета):
package test
Далее у нас есть наш Импорт
декларация. Импорт
Объявление содержит библиотеки или пакеты, используемые в коде Голанга. В Голанге библиотеки и пакеты похожи на модули в PowerShell. Мы можем ссылаться на пакеты, родственные для перемещения, или мы можем ссылаться на те из источника, таких как GitHub. Мы будем добавлять больше библиотек, поскольку мы создаем наш модульный тест, пока мы используем тестирование
Go Package и github.com/gruntwork-io/terratest/modules/terraform
Библиотека, созданная Gruntwork, которая позволяет нам автоматизировать код развертывания с Terraform во время теста:
import ( "github.com/gruntwork-io/terratest/modules/terraform" "testing" )
После нашего Импорт
Объявление, у нас есть наша функция тестирования, которую мы позвонили TestterraformazurenetworkingExample
Анкет Функции тестирования в GO имеют следующий формат; Они также должны начать со слова Тест
с капиталом T
Затем последовало заглавное письмо после Тест
. Мы также используем t.parallel ()
что указывает на то, что мы хотим провести этот тест параллельно с другими тестами. Это параллельное утверждение имеет большое значение, потому что мы можем запустить несколько тестов одновременно, чтобы проверить наш модуль несколькими различными способами:
func TestTerraformAzureNetworkingExample(t *testing.T) { t.Parallel()
Внутри нашей функции находится переменная, называемая Terraformoptions
Анкет В Go мы можем объявить переменные, используя : =
, что отличается от PowerShell, где мы будем использовать $ переменные объявить переменную. Внутри нашего объявления переменной мы используем github.com/gruntwork-io/terratest/modules/terraform
Библиотека, ссылаясь на имя пакета нашей библиотеки терраформ
. Затем мы ссылаемся на объект внутри библиотеки под названием Параметры
Анкет Этот объект называется struct в Голанге. A структура похож на объект в PowerShell. По сути, мы делаем объект «Параметры», который мы можем добавить коллекцию настроек и передать их в Terraform. На данный момент у нас нет вариантов, определенных в нашей структуре, но на следующем шаге мы добавим их:
terraformOptions := &terraform.Options{ }
Чтобы завершить нашу функцию тестирования, у нас есть еще две строки кода. Мы снова используем терратскую библиотеку, ссылаясь на терраформ
. Однако на этот раз мы используем Разрушать
и InitandApply
функции из Terratest Library Чтобы выполнить стандартные команды Terraform, применить и уничтожить команды, используя наши определенные параметры в Terraformoptions
переменные. Примечание, отсрочка
В Go похож на Наконец в PowerShell. Отказ означает, что GO будет выполнять эту функцию в конце и всегда будет запускать ее, даже если тест должен был ошибаться:
defer terraform.Destroy(t, terraformOptions) terraform.InitAndApply(t, terraformOptions)
Настройте параметры Terraform
Давайте добавим некоторые параметры в нашем Terraformoptions
переменная. Наш код Terraform в Примеры/Сеть
Папка имеет переменные.tf
Файл, который позволяет нам вводить несколько параметров и настраивать нашу сетевую инфраструктуру при развертывании:
variable "system" { type = string description = "Name of the system or environment" default = "terratest" } variable "location" { type = string description = "Azure location of terraform server environment" default = "westus2" } variable "vnet_address_space" { description = "Address space for Virtual Network" } variable "subnet_prefix" { type = string description = "Prefix of subnet address" }
Нам нужно определить значения для этих переменных в нашем модульном тесте, а затем передать их в Terraform, используя Terraformoptions
переменная.
Если вы заметили в нашем переменные.tf
Файл, у нас есть переменная для Место
Анкет Для Место
переменная ценность, мы хотим иметь возможность случайным образом тестировать развертывание в разных регионах, которые могут быть для нас возможности. Эта рандомизация позволяет нам пройти тщательный тест, поскольку каждый тест может развернуть инфраструктуру в одну из перечисленных регионов. Мы сделаем это, предоставив список возможных регионов для развертывания в нашем тесте, а затем случайным образом выбрать один при запуске теста. Это также может помочь вырубить любые инциденты с конкретными регионами, возникающие в Azure, когда мы запускаем наши тесты.
Чтобы создать список регионов, мы объявляем переменную под названием регионы
и установить тип переменной на [] строка
который означает список строк. Затем мы заполняем этот список различными регионами в Azure, в которых мы хотим проверить:
var regions = []string{ "centralus", "eastus", "eastus2", "northcentralus", "southcentralus", "westcentralus", "westus", "westus2", }
Далее мы создаем переменную для нашего регионы
который использует функцию RandomString
Чтобы выбрать регион из нашего списка регионов случайным образом:
azureRegion := random.RandomString(regions)
Теперь, когда у нас есть переменная, созданная для входной переменной местоположения Terraform, мы можем настроить значения для остальных входных переменных. Для система
Переменная, мы собираемся использовать аналогичную концепцию, которую мы использовали для области Azure. Мы собираемся генерировать случайное имя для имени системы.
systemName := strings.ToLower(random.UniqueId())
Эта случайная генерация имен позволяет нам запустить этот тест несколько раз одновременно без перекрытия в одном имени ресурса. Это полезно, когда несколько человек добавляют функции в модуль в своих ветвях и выполняют тесты. Далее у нас есть жесткие значения для нашего виртуального сетевого адреса и префикса подсети:
vnetAddress := "10.0.0.0/16" subnetPrefix := "10.0.0.0/24"
Теперь, когда у нас есть значения для наших входных переменных, мы должны передать их в Terraformoptions
Анкет Добавляем Terraformdir
Аргумент для указания каталога кода, который мы хотим выполнить, является кодом в Примеры/Сеть
Папка нашего репо. Далее мы импортируем карту переменных, которая позволяет нам передавать значения в Terraform, как если бы мы использовали -Вар
опция в командной строке. Мы проходим через все четыре переменные, которые мы только что настроили:
terraformOptions := &terraform.Options{ TerraformDir: "../examples/network", Vars: map[string]interface{}{ "system": systemName, "location": azureRegion, "vnet_address_space": vnetAddress, "subnet_prefix": subnetPrefix, }, }
Нам нужно добавить еще два пакета и библиотеки в нашем Импорт
Объявление, так как мы сейчас используем их для создания случайной строки для имени системы и случайным образом выбрать нашу область Azure:
import ( "strings" "testing" "github.com/gruntwork-io/terratest/modules/random" "github.com/gruntwork-io/terratest/modules/terraform" )
Теперь у нас есть наш тест, настроенный для запуска нашего кода Terraform в Примеры/Сеть
Папка со значениями для переменные.tf
файл. На этом этапе наш модульный тест в terraform_azure_network_test.go
должен выглядеть следующим образом:
package test import ( "strings" "testing" "github.com/gruntwork-io/terratest/modules/random" "github.com/gruntwork-io/terratest/modules/terraform" ) // An example of how to test the Terraform module in examples/terraform-azure-example using Terratest. func TestTerraformAzureNetworkingExample(t *testing.T) { t.Parallel() var regions = []string{ "centralus", "eastus", "eastus2", "northcentralus", "southcentralus", "westcentralus", "westus", "westus2", } // Pick a random Azure region to test in. azureRegion := random.RandomString(regions) // Network Settings for Vnet and Subnet systemName := strings.ToLower(random.UniqueId()) vnetAddress := "10.0.0.0/16" subnetPrefix := "10.0.0.0/24" terraformOptions := &terraform.Options{ // The path to where our Terraform code is located TerraformDir: "../examples/network", // Variables to pass to our Terraform code using -var options Vars: map[string]interface{}{ "system": systemName, "location": azureRegion, "vnet_address_space": vnetAddress, "subnet_prefix": subnetPrefix, }, } // At the end of the test, run `terraform destroy` to clean up any resources that were created defer terraform.Destroy(t, terraformOptions) // This will run `terraform init` and `terraform apply` and fail the test if there are any errors terraform.InitAndApply(t, terraformOptions) }
Добавить тесты
Теперь мы готовы добавить некоторые тесты. Мы хотим написать тесты, которые являются значимыми и не хотим, чтобы процесс стал бременем для поддержания. Определение того, имеет ли значение тест, зависит от ситуации и окружающей среды. Значительный тест для кого -то другого не означает, что он имеет значение для вашего дела. Для этого примера мы будем держать вещи простыми. Мы хотим проверить, что наша подсеть виртуальной сети действительно связана с NSG после того, как наш пример Terraform будет развернут. Этот тест гарантирует, что любое изменение нашего модуля в будущем не прервет этот желаемый результат, что может привести к потенциальному риску безопасности, если NSG не будет назначен подсети.
Наш код Terraform в Примеры/Сеть
Папка содержит следующее в output.tf
файл. Это значения, которые мы хотим использовать для выполнения наших тестов:
output "vnet_rg" { description = "Location of vnet" value = module.vnet.vnet_rg } output "subnet_id" { description = "Subnet ID" value = module.vnet.subnet_id } output "nsg_name" { description = "Name of vnet Security Group" value = module.nsg.nsg_name }
Примечание: Мы хотим убедиться, что наши модули не слишком велики, чтобы проходить тестирование. Мы не хотим модуля 10 000 линий, потому что его невозможно провести модульный тест. Чем больше вы пишете тесты для своих модулей, тем больше структурированы ваши модули для тестирования. Эта практика становится большим преимуществом, поскольку она позволяет получить более стабильный и лучший структурированный код терраформ.
терраформ. Вывод
Функция позволяет нам собирать выходные значения из нашего развертывания Terraform после init
и применить
завершен. Мы ссылаемся на Terraformoptions
переменная, которая содержит наши настройки среды Terraform. Также мы включаем каждое выходное значение из output.tf
. Затем мы сохраняем каждое выходное значение в переменную в Go:
vnetRG := terraform.Output(t, terraformOptions, "vnet_rg") subnetID := terraform.Output(t, terraformOptions, "subnet_id") nsgName := terraform.Output(t, terraformOptions, "nsg_name")
Теперь мы будем использовать выходные переменные, которые мы создали, чтобы непосредственно проверить нашу среду Azure, используя API Azure, и подтвердим, что NSG, который мы создаем, присваивается подсети. Мы выполняем поиск всех идентификаторов подсети, назначенных NSG, используя Лазур. Getassociationsfornsg
Функция, которая требует группы виртуальных сетевых ресурсов и имя NSG. Затем мы запускаем тест, используя утверждение
Go Package, который позволяет нам сравнивать все идентификаторы ресурсов в нашем NSGassocations
переменная с subnetid
переменная, которая содержит выходную информацию из нашего кода Terraform. Это сравнение позволяет нам взять вывод идентификатора подсети из Terraform и заглянуть в Azure, используя API, и убедиться, что он назначен созданным нами NSG:
// Look up Subnet and NIC ID associations of NSG nsgAssociations := azure.GetAssociationsforNSG(t, vnetRG, nsgName, "") //Check if subnet is associated with NSG assert.Contains(t, nsgAssociations, subnetID)
Если идентификатор подсети находится в списке ассоциаций NSG, наш тест пройдет, если он отсутствует, тест не удастся.
Наконец, нам нужно будет добавить еще две библиотеки в нашем Импорт
декларация. Мы используем утверждать
Для выполнения сравнения и проверки нашего идентификатора подсеть связан с NSG, и мы используем функцию Лазур. Getassociationsfornsg
Из библиотеки GO Aztest. Лазур. Getassociationsfornsg
Функция позволяет нам быстро аутентифицировать в нашей среде Azure и искать назначенные ресурсы в NSG. Это просто вспомогательная функция для работы с Azure Go Sdk который общается с Azure API:
Примечание: Библиотека испытаний Azure В Terratest прямо сейчас довольно ограничено по сравнению с AWS Анкет Gruntwork была в значительной степени сосредоточена на создании модулей AWS и GCP. В текущем штате большинство компаний просто создают свои собственные частные библиотеки для тестирования своих ресурсов в Azure. Чтобы помочь людям начать писать тесты на код Terraform в Azure, я расширил функции Terratest Azure Testing и создал публичную библиотеку Go под названием Aztest , не стесняйтесь использовать его.
import ( "strings" "testing" "github.com/allanore/aztest/modules/azure" "github.com/gruntwork-io/terratest/modules/random" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" )
Теперь, когда у нас написано наш тест, весь наш модульный тест заключается в следующем. Скопируйте следующее в terraform_azure_network_test.go
:
package test import ( "strings" "testing" "github.com/allanore/aztest/modules/azure" "github.com/gruntwork-io/terratest/modules/random" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" ) // An example of how to test the Terraform module in examples/terraform-azure-example using Terratest. func TestTerraformAzureNetworkingExample(t *testing.T) { t.Parallel() var regions = []string{ "centralus", "eastus", "eastus2", "northcentralus", "southcentralus", "westcentralus", "westus", "westus2", } // Pick a random Azure region to test in. azureRegion := random.RandomString(regions) // Network Settings for Vnet and Subnet systemName := strings.ToLower(random.UniqueId()) vnetAddress := "10.0.0.0/16" subnetPrefix := "10.0.0.0/24" terraformOptions := &terraform.Options{ // The path to where our Terraform code is located TerraformDir: "../examples/network", // Variables to pass to our Terraform code using -var options Vars: map[string]interface{}{ "system": systemName, "location": azureRegion, "vnet_address_space": vnetAddress, "subnet_prefix": subnetPrefix, }, } // At the end of the test, run `terraform destroy` to clean up any resources that were created defer terraform.Destroy(t, terraformOptions) // This will run `terraform init` and `terraform apply` and fail the test if there are any errors terraform.InitAndApply(t, terraformOptions) // Run `terraform output` to get the value of an output variable vnetRG := terraform.Output(t, terraformOptions, "vnet_rg") subnetID := terraform.Output(t, terraformOptions, "subnet_id") nsgName := terraform.Output(t, terraformOptions, "nsg_name") // Look up Subnet and NIC ID associations of NSG nsgAssociations := azure.GetAssociationsforNSG(t, vnetRG, nsgName, "") //Check if subnet is associated with NSG assert.Contains(t, nsgAssociations, subnetID) }
Вот, как будто! Мы только что построили наш первый модульный тест в Go. Теперь давайте запустим это. Во -первых, нам нужно аутентифицировать в Azure. Самый простой способ — использовать Azure CLI. Введите следующую команду в терминале, находясь в ~/рабочее пространство/terraform-azure-testing/test
каталог. Войдите в систему с учетной записью Azure:
az login
Теперь нам нужно установить Arm_subscription_id
Переменная среда, которая используется для нескольких функций в терраттере при развертывании в Azure:
export ARM_SUBSCRIPTION_ID=$(az account show | jq '.id' -r)
После входа в систему с Azure CLI нам нужно загрузить все наши зависимости для наших тестов. Зависимости включают пакеты, которые мы указали во время заявления импорта. Эта концепция похожа на бег Установка модуля в PowerShell для установки всех внешних модулей, используемых в сценарии. Введите следующую команду, используя Получите
в то время как в тест
каталог:
go get -t -v
Мы видим загрузку библиотеки и пакеты. Этот процесс может занять минуту. После завершения мы готовы провести наш тест. Чтобы начать тест, введите следующую команду. Мы используем Перейти тест
команда с -v
Чтобы указать известный выход. Кроме того, мы указываем файл тестирования GO, который мы только что создали:
go test -v terraform_azure_network_test.go
Мы начнем видеть Terraform, выполняющий наш пример кода на выводе:
=== RUN TestTerraformAzureNetworkingExample === PAUSE TestTerraformAzureNetworkingExample === CONT TestTerraformAzureNetworkingExample TestTerraformAzureNetworkingExample 2020-05-09T14:30:17Z retry.go:72: terraform [init -upgrade=false] TestTerraformAzureNetworkingExample 2020-05-09T14:30:17Z command.go:86: Running command terraform with args [init -upgrade=false] TestTerraformAzureNetworkingExample 2020-05-09T14:30:17Z command.go:168: Initializing modules... TestTerraformAzureNetworkingExample 2020-05-09T14:30:17Z command.go:168: TestTerraformAzureNetworkingExample 2020-05-09T14:30:17Z command.go:168: Initializing the backend... TestTerraformAzureNetworkingExample 2020-05-09T14:30:17Z command.go:168: TestTerraformAzureNetworkingExample 2020-05-09T14:30:17Z command.go:168: Initializing provider plugins... TestTerraformAzureNetworkingExample 2020-05-09T14:30:19Z command.go:168: TestTerraformAzureNetworkingExample 2020-05-09T14:30:19Z command.go:168: Terraform has been successfully initialized! TestTerraformAzureNetworkingExample 2020-05-09T14:30:19Z command.go:168:
Не нажимайте Ctrl + C во время теста; Это предотвратит очистку ресурсов в Azure. Если тест должен ошибиться, этап отсрочки работает и выполняет Terraform Dissome, чтобы удалить все, что было предоставлено.
Тест выполняет код Terraform в Примеры/Сеть
Папка, запустив тест, чтобы гарантировать, что NSG связан с подсети, и запуск Terraform в конце. Как только тестовый запуск завершится, мы видим результат, как ниже:
TestTerraformAzureNetworkingExample 2020-05-09T14:32:01Z command.go:168: azurerm_resource_group.rg: Destruction complete after 47s TestTerraformAzureNetworkingExample 2020-05-09T14:32:01Z command.go:168: TestTerraformAzureNetworkingExample 2020-05-09T14:32:01Z command.go:168: Destroy complete! Resources: 7 destroyed. --- PASS: TestTerraformAzureNetworkingExample (103.78s) PASS ok command-line-arguments 103.783s
Теперь наш модульный тест завершен! На следующем шаге мы добавим интеграционный тест.
Шаг 5 — Интеграционное тестирование
Интеграционный тест с кодом инфраструктуры определяется как тестирование функциональности двух компонентов, взаимодействующих вместе. Это может быть веб -приложение с базой данных SQL или двумя микросервисами, взаимодействующими друг с другом. Для демонстрационных целей мы будем держать его очень простым, встать на две виртуальные сети и проверить, что мы сможем их вместе. Пример кода для каждого Vnet находится в Примеры/Vnet-Peering
каталог. Наш тест интеграции выполнит код Terraform в Vnet1
Развернуть первую виртуальную сеть. После завершения тест выполнит код в Vnet2
Развернуть вторую виртуальную сеть и заправить их вместе. Затем мы напишем тест, который подтверждает, что пиринг был успешным:
examples └──networking └──vnet-peering └─vnet1 └─main.tf └─output.tf └─variables.tf └─vnet2 └─main.tf └─output.tf └─variables.tf
В нашем тест
каталог, давайте создадим еще один тестовый файл GO под названием terraform_azure_network_peering_test.go
.
Базовый тест
Мы скопируем следующий код ниже и вставим его в качестве наша конфигурация базового теста. Заметьте, у нас теперь есть два набора Terraform.options
а также два набора шагов уничтожения и применить:
package test import ( "testing" "github.com/gruntwork-io/terratest/modules/terraform" ) // An example of how to test the Terraform module in examples/terraform-azure-example using Terratest. func TestTerraformAzureNetworkingPeeringExample(t *testing.T) { t.Parallel() vnet1Opts := &terraform.Options{ } // Deploy VNet1 defer terraform.Destroy(t, vnet1Opts) terraform.InitAndApply(t, vnet1Opts) vnet2Opts := &terraform.Options{ } // Deploy VNet2 defer terraform.Destroy(t, vnet2Opts) terraform.InitAndApply(t, vnet2Opts) }
Добавить варианты Terraform
Далее мы добавим варианты Terraform. Мы включаем шаги для рандомизированных областей Azure, а также использование случайных имен систем для наших виртуальных сетей. Большая разница от нашего модульного теста заключается в том, что мы передаем выходные значения Terraform после развертывания Vnet1 в Terraform.options
Vnet2, это позволяет нам настроить взорвание между ними:
package test import ( "strings" "testing" "github.com/gruntwork-io/terratest/modules/random" "github.com/gruntwork-io/terratest/modules/terraform" ) // An example of how to test the Terraform module in examples/terraform-azure-example using Terratest. func TestTerraformAzureNetworkingPeeringExample(t *testing.T) { t.Parallel() var regions = []string{ "centralus", "eastus", "eastus2", "northcentralus", "southcentralus", "westcentralus", "westus", "westus2", } // Pick a random Azure region to test in. azureRegion := random.RandomString(regions) // Network Settings for Vnet and Subnet vnet1Sysname := strings.ToLower(random.UniqueId()) vnet1Address := "10.0.0.0/16" vnet1SubnetPrefix := "10.0.0.0/24" vnet2Sysname := strings.ToLower(random.UniqueId()) vnet2Address := "10.1.0.0/16" vnet2SubnetPrefix := "10.1.0.0/24" vnet1Opts := &terraform.Options{ // The path to where our Terraform code is located TerraformDir: "../examples/vnet-peering/vnet1", // Variables to pass to our Terraform code using -var options Vars: map[string]interface{}{ "system": vnet1Sysname, "location": azureRegion, "vnet_address_space": vnet1Address, "subnet_prefix": vnet1SubnetPrefix, }, } // Deploy VNet1 defer terraform.Destroy(t, vnet1Opts) terraform.InitAndApply(t, vnet1Opts) vnetOutRG := terraform.Output(t, vnet1Opts, "vnet_rg") vnetOutName := terraform.Output(t, vnet1Opts, "vnet_name") vnet2Opts := &terraform.Options{ // The path to where our Terraform code is located TerraformDir: "../examples/vnet-peering/vnet2", // Variables to pass to our Terraform code using -var options Vars: map[string]interface{}{ "system": vnet2Sysname, "location": azureRegion, "vnet_address_space": vnet2Address, "subnet_prefix": vnet2SubnetPrefix, "peer_vnet_rg": vnetOutRG, "peer_vnet_name": vnetOutName, }, } // Deploy VNet2 defer terraform.Destroy(t, vnet2Opts) terraform.InitAndApply(t, vnet2Opts) }
Добавить тесты
Далее мы добавим в тесты. Мы собираем группу ресурсов и имя виртуальной сети с вывода развертывания Vnet2. Тогда мы используем эти значения, чтобы найти виртуальную сеть с Лазур. GetVnetbyName
Функция и хранение их в Vnet2properties
переменная. Мы принимаем виртуальную сеть вставленных свойств из Vnet2properties
переменная и использование для
Цикл, чтобы перейти, чтобы пройти через все значения в рамках Virtualnetworkpeerings
Свойство, которое содержит список всех пэров, сделанных в виртуальной сети. Затем мы подтверждаем, что все сверстники в этом свойстве находятся в Добился успеха
Государство, гарантируя, что они правильно смотрели:
// Collect RG and Virtual Network name from VNet2 Output vnet2RG := terraform.Output(t, vnet2Opts, "vnet_rg") vnet2Name := terraform.Output(t, vnet2Opts, "vnet_name") // Look up Virtual Network 2 by Name vnet2Properties := azure.GetVnetbyName(t, vnet2RG, vnet2Name, "") //Check if VNet Peering in VNet2 Provisioned Successfully for _, vnet := range *vnet2Properties.VirtualNetworkPeerings { assert.Equal(t, "Succeeded", string(vnet.VirtualNetworkPeeringPropertiesFormat.ProvisioningState), "Check if Peerings provisioned successfully") }
Наш окончательный файл тестирования интеграции должен выглядеть следующим образом:
package test import ( "strings" "testing" "github.com/allanore/aztest/modules/azure" "github.com/gruntwork-io/terratest/modules/random" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" ) // An example of how to test the Terraform module in examples/terraform-azure-example using Terratest. func TestTerraformAzureNetworkingPeeringExample(t *testing.T) { t.Parallel() var regions = []string{ "centralus", "eastus", "eastus2", "northcentralus", "southcentralus", "westcentralus", "westus", "westus2", } // Pick a random Azure region to test in. azureRegion := random.RandomString(regions) // Network Settings for Vnet and Subnet vnet1Sysname := strings.ToLower(random.UniqueId()) vnet1Address := "10.0.0.0/16" vnet1SubnetPrefix := "10.0.0.0/24" vnet2Sysname := strings.ToLower(random.UniqueId()) vnet2Address := "10.1.0.0/16" vnet2SubnetPrefix := "10.1.0.0/24" vnet1Opts := &terraform.Options{ // The path to where our Terraform code is located TerraformDir: "../examples/vnet-peering/vnet1", // Variables to pass to our Terraform code using -var options Vars: map[string]interface{}{ "system": vnet1Sysname, "location": azureRegion, "vnet_address_space": vnet1Address, "subnet_prefix": vnet1SubnetPrefix, }, } // Deploy VNet1 defer terraform.Destroy(t, vnet1Opts) terraform.InitAndApply(t, vnet1Opts) vnetOutRG := terraform.Output(t, vnet1Opts, "vnet_rg") vnetOutName := terraform.Output(t, vnet1Opts, "vnet_name") vnet2Opts := &terraform.Options{ // The path to where our Terraform code is located TerraformDir: "../examples/vnet-peering/vnet2", // Variables to pass to our Terraform code using -var options Vars: map[string]interface{}{ "system": vnet2Sysname, "location": azureRegion, "vnet_address_space": vnet2Address, "subnet_prefix": vnet2SubnetPrefix, "peer_vnet_rg": vnetOutRG, "peer_vnet_name": vnetOutName, }, } // Deploy VNet2 defer terraform.Destroy(t, vnet2Opts) terraform.InitAndApply(t, vnet2Opts) // Collect RG and Virtual Network name from VNet2 Output vnet2RG := terraform.Output(t, vnet2Opts, "vnet_rg") vnet2Name := terraform.Output(t, vnet2Opts, "vnet_name") // Look up Virtual Network 2 by Name vnet2Properties := azure.GetVnetbyName(t, vnet2RG, vnet2Name, "") //Check if VNet Peering in VNet2 Provisioned Successfully for _, vnet := range *vnet2Properties.VirtualNetworkPeerings { assert.Equal(t, "Succeeded", string(vnet.VirtualNetworkPeeringPropertiesFormat.ProvisioningState), "Check if Peerings provisioned successfully") } }
Теперь давайте запустим наш интеграционный тест. Не нужно загружать зависимости, потому что мы уже загружали их, когда запустили модульный тест. Запустите следующую команду в терминале с указанием terraform_azure_network_peering_test.go
файл:
go test -v terraform_azure_network_peering_test.go
Мы должны увидеть, как обе виртуальные сети развернуты, после чего следуют наш тест, чтобы проверить состояние запрашивания между ними. Тогда a Terraform Drouss
забежал, чтобы снести нашу тестовую инфраструктуру. В конце мы должны увидеть, что наш тест прошел:
TestTerraformAzureNetworkingPeeringExample 2020-05-10T13:22:40Z command.go:168: azurerm_resource_group.rg: Destruction complete after 48s TestTerraformAzureNetworkingPeeringExample 2020-05-10T13:22:41Z command.go:168: TestTerraformAzureNetworkingPeeringExample 2020-05-10T13:22:41Z command.go:168: Destroy complete! Resources: 7 destroyed. --- PASS: TestTerraformAzureNetworkingPeeringExample (347.89s) PASS ok command-line-arguments 347.890s
Для дополнительной задачи мы могли бы одновременно запустить оба теста, используя следующую команду. Потому что у нас есть t.parallel ()
В наших тестовых функциях каждый тест может быть запущен параллельно. Это невероятно мощно, потому что мы можем проверить наши модули несколькими различными способами одновременно:
Примечание: В типичной конвейере непрерывной интеграции для нашего модуля мы в идеале запустили все тесты в нашей тестовой папке одновременно, когда мы совершаем наши изменения в репо модуле. Это позволяет нам получить полное количество тестового покрытия против нашего модуля.
go test -v
На следующем шаге мы рассмотрим, как выполнить конечное тестирование.
Шаг 6-сквозное тестирование
Тестирование сквозного включает в себя все приложение, состоящее из нескольких модулей. Это может занять часы, в зависимости от того, насколько большое приложение, что может сделать невероятно трудоемким для проведения сквозных тестов. Если приложение требуется значительное количество времени для развертывания, рекомендуется развернуть копию всего приложения в отдельной тестовой среде и поддерживать ее в течение определенного количества времени. Затем, когда мы вносим изменение в любое из модулей в приложении, мы можем повторно развернуть этот модуль в приложение, а затем проверить функциональность приложения в целом с помощью автоматических тестов.
Вывод
Как видите, написание тестов может занять немного работы. Поскольку IAC является такой недавно принятой концепцией, инструмент и концепции для написания тестов могут быть неловкими и сложными. Однако награды того стоят. Модуль с тщательными тестами будет иметь гораздо большую стабильность и обеспечит большую уверенность, когда команды выполняют этот код.
Код инфраструктуры обычно «быстро гниет». Постоянно новые обновления, внесенные в Azure, поставщики терраформ и саму терраформ, которые могут сделать полную задачу для обеспечения того, чтобы модули всегда работали, как и должно. Чтобы помочь с этим, рассмотрите возможность планирования тестов для работы по ночам, чтобы как можно раньше поймать эти типы ошибок.
Настоятельно рекомендуется провести ваши тесты в подписке Azure, отдельной от производства и даже развития. При разработке и тестировании модулей всегда существует риск уничтожения других ресурсов. Кроме того, это позволяет безопасно настроить автоматическую очистку на подписке на тестирование, чтобы гарантировать, что любые испытания, которые разбомбили, не оставляют остатки инфраструктуры.
Существует также концепция разработки на основе тестирования (TDD), которая представляет собой практику разработки программного обеспечения, где тесты написаны первыми до написания кода. Это не очень распространено в мире развития инфраструктуры из -за стадии младенчества. Тем не менее, ветераны IAC любят Киф Моррис являются огромными сторонниками TDD и описывают, что выполнение TDD для кода инфраструктуры повышает дизайн, поскольку требуется, чтобы он продумал результаты и функцию своей инфраструктуры при разработке.
Тесты на код инфраструктуры имеют решающее значение для стабильности инфраструктуры. Джейкоб Каплан-Мосс, разработчик программного обеспечения и соавтор Django, сказал, что это лучше всего: «Код без тестов нарушается в соответствии с разработкой». Письменные тесты для МАК могут быть трудоемкими и трудными из-за незрелости инструментов; Тем не менее, это важная часть развития инфраструктуры, которую нельзя упускать из виду.
В следующей статье мы завершим эту серию, рассмотрев передовые практики при использовании Terraform.
Оригинал: «https://dev.to/cloudskills/getting-started-with-terraform-on-azure-testing-1a16»