Тестування інфраструктури як код за допомогою Pulumi. Частина 2

Всім привіт. Сьогодні ділимося з вами заключною частиною статті "Тестування інфраструктури як код за допомогою Pulumi", переклад якої підготовлено спеціально для студентів курсу «DevOps практики та інструменти».

Тестування інфраструктури як код за допомогою Pulumi. Частина 2

Тестування розгортання

Розглянутий стиль тестування - це потужний підхід, він дозволяє нам проводити тестування білої скриньки для перевірки нутрощів роботи нашого інфраструктурного коду. Однак він дещо обмежує те, що ми можемо перевірити. Тести виконуються на основі in-memory плану розгортання, створеного Pulumi перед безпосереднім розгортанням і тому розгортання саме не протестувати. Для таких випадків у Pulumi є фреймворк інтеграційних тестів. І ці два підходи чудово працюють разом!

Фреймворк інтеграційного тестування Pulumi написано на Go, і саме з його допомогою ми тестуємо більшу частину нашого внутрішнього коду. Якщо розглянутий раніше підхід модульного тестування був більше схожий на тестування білої скриньки, то інтеграційне тестування – це чорна скринька. (Є також варіанти ретельного внутрішнього тестування.) Цей фреймворк був створений для того, щоб взяти повну Pulumi-програму та виконати для неї різні операції життєвого циклу, такі як розгортання нового стека з нуля, його оновлення з варіаціями та видалення можливо кілька разів. Ми запускаємо їх регулярно (наприклад, вночі) і як стрес-тести.

(Ми працюємо над тимщоб аналогічні можливості інтеграційного тестування були в рідній мові SDK. Ви можете використовувати фреймворк інтеграційного тестування Go незалежно від мови, якою написана ваша Pulumi-програма).

Запустивши програму за допомогою цього фреймворку, ви можете перевірити наступне:

  • Код вашого проекту синтаксично правильний та працює без помилок.
  • Налаштування конфігурації стека та секретів працюють та інтерпретуються правильно.
  • Ваш проект може бути успішно розгорнутий у вибраному вами хмарному провайдері.
  • Ваш проект може бути успішно оновлений з початкового стану до інших станів.
  • Ваш проект може бути успішно знищений та видалений з вашого хмарного провайдера.

Як ми незабаром побачимо, цей фреймворк можна також використовувати для виконання runtime-валідації.

Простий інтеграційний тест

Щоб побачити це у дії, ми подивимося на репозиторій pulumi/examples, оскільки наша команда та спільнота Pulumi, використовує його для тестування власних пул реквестів, коммітів та нічних збірок.

Нижче наведено спрощений тест нашого приклад, який робить провіженінг S3 bucket та деяких інших об'єктів:

example_test.go:

package test
 
import (
    "os"
    "path"
    "testing"
 
    "github.com/pulumi/pulumi/pkg/testing/integration"
)
 
func TestExamples(t *testing.T) {
    awsRegion := os.Getenv("AWS_REGION")
    if awsRegion == "" {
        awsRegion = "us-west-1"
    }
    cwd, _ := os.Getwd()
    integration.ProgramTest(t, &integration.ProgramTestOptions{
        Quick:       true,
        SkipRefresh: true,
        Dir:         path.Join(cwd, "..", "..", "aws-js-s3-folder"),
        Config: map[string]string{
            "aws:region": awsRegion,
        },
    })
}

Цей тест проходить через базовий життєвий цикл створення, зміни та знищення стека для папки. aws-js-s3-folder. Він займе близько хвилини, щоб повідомити про пройдений тест:

$ go test .
PASS
ok      ... 43.993s

Існує багато параметрів для налаштування поведінки цих тестів. Повний список опцій див. у структурі ProgramTestOptions. Наприклад, ви можете налаштувати Jaeger endpoint для трасування (Tracing), вказати, що очікуєте падіння тесту при негативному тестуванні (ExpectFailure), застосувати серію "правок" до програми для послідовного переходу станів (EditDirs) і багато іншого. Давайте подивимося, як використовувати їх для перевірки розгортання програми.

Перевірка властивостей ресурсів

Інтеграція, про яку говорили вище, гарантує, що наша програма працює, вона не падає. Але що, якщо хочемо, перевірити властивості отриманого стека? Наприклад, певні види ресурсів були (або не були) підготовлені і що вони мають певні атрибути.

Параметр ExtraRuntimeValidation для ProgramTestOptions дозволяє нам переглянути стан, зафіксований Pulumi після розгортання (post-deployment state), щоб ми могли зробити додаткові перевірки. Сюди входить повний знімок стану результуючого стека, включаючи конфігурацію, вихідні значення, що експортуються, всі ресурси і значення їх властивостей, а також всі залежності між ресурсами.

Щоб побачити базовий приклад цього, перевіримо, що наша програма створює один S3 Ківш:

  integration.ProgramTest(t, &integration.ProgramTestOptions{
        // as before...
        ExtraRuntimeValidation: func(t *testing.T, stack integration.RuntimeValidationStackInfo) {
            var foundBuckets int
            for _, res := range stack.Deployment.Resources {
                if res.Type == "aws:s3/bucket:Bucket" {
                    foundBuckets++
                }
            }
            assert.Equal(t, 1, foundBuckets, "Expected to find a single AWS S3 Bucket")
        },
    })

Тепер, коли ми запустимо go test, він не тільки пройде через батарею тестів життєвого циклу, але також після успішного розгортання стека виконає додаткову перевірку результуючого стану.

Runtime-тести

Досі всі тести були виключно про поведінку при розгортанні та про модель ресурсів Pulumi. Що робити, якщо ви хочете перевірити, чи ваша підготовлена ​​інфраструктура дійсно працює? Наприклад, що віртуальна машина працює, S3 bucket містить те, що ми очікуємо, і таке інше.

Ви, можливо, вже здогадалися, як це зробити: опція ExtraRuntimeValidation для ProgramTestOptions - Це чудова можливість для цього. На цьому етапі ви запускаєте довільний тест Go з доступом до повного стану ресурсів програми. Цей стан включає таку інформацію, як IP-адреси віртуальних машин, URL-адреси та все, що необхідно для реальної взаємодії з отриманими хмарними програмами та інфраструктурою.

Наприклад, наша тестова програма експортує властивість webEndpoint bucket'а під назвою websiteUrl, яке являє собою повну URL-адресу, за якою ми можемо отримати налаштований index document. Хоча ми могли б покопатися у файлі стану, щоб знайти bucket і прочитати цю властивість безпосередньо, але в багатьох випадках наші стеки експортують корисні властивості, такі як це, які нам зручно використовувати для перевірки:

integration.ProgramTest(t, &integration.ProgramTestOptions{
            // as before ...
        ExtraRuntimeValidation: func(t *testing.T, stack integration.RuntimeValidationStackInfo) {
            url := "http://" + stack.Outputs["websiteUrl"].(string)
            resp, err := http.Get(url)
            if !assert.NoError(t, err) {
                return
            }
            if !assert.Equal(t, 200, resp.StatusCode) {
                return
            }
            defer resp.Body.Close()
            body, err := ioutil.ReadAll(resp.Body)
            if !assert.NoError(t, err) {
                return
            }
            assert.Contains(t, string(body), "Hello, Pulumi!")
        },
    })

Як і наші попередні runtime-перевірки, ця перевірка буде виконуватися відразу після підняття стека, і все це у відповідь на простий виклик go test. І це лише вершина айсберга – доступні всі тестові можливості Go, які ви можете написати у коді.

Безперервна інтеграція інфраструктури

Добре мати можливість запускати тести на ноутбуці, коли робиться багато змін в інфраструктурі для їх перевірки перед відправкою на рев'ю коду. Але ми та багато наших клієнтів тестуємо інфраструктуру на різних етапах життєвого циклу розробки:

  • У кожному відкритому пул реквесті для тесту перед злиттям.
  • У відповідь на кожен коміт, щоб перевірити ще раз, що злиття було виконано правильно.
  • Періодично, наприклад, уночі або щотижня для додаткового тестування.
  • В рамках тестування продуктивності або стрес-тестування, які зазвичай виконуються протягом тривалого періоду часу і запускають тести паралельно та/або розгортають ту саму програму кілька разів.

Для кожного з них Pulumi підтримує інтеграцію з улюбленою системою безперервної інтеграції. При безперервній інтеграції це дає вам таке покриття тестами для вашої інфраструктури, як і для прикладного програмного забезпечення.

У Pulumi є підтримка найпоширеніших CI-систем. Ось деякі з них:

Для отримання більш детальної інформації зверніться до документації щодо Безперервна доставка.

Ефемерні оточення

Дуже потужна можливість, що відкривається, - це можливість розгортати ефемерні оточення виключно для цілей приймального тестування. Концепція проектів та стеків Pulumi розроблена таким чином, щоб легко розгортати та зносити повністю ізольовані та незалежні оточення, все в декілька простих команд CLI або за допомогою фреймворку інтеграційного тестування.

Якщо ви використовуєте GitHub, Pulumi пропонує GitHub Appщо допоможе вам підключити приймальне тестування до пул реквестів усередині вашого CI-пайплайну. Просто встановіть додаток у репозиторій GitHub, а Pulumi до вашого CI і в пул реквести буде додаватися інформація про прев'ю інфраструктури, оновлення та результати тестування:

Тестування інфраструктури як код за допомогою Pulumi. Частина 2

При використанні Pulumi для ваших основних приймальних тестів, у вас з'являться нові можливості автоматизації, які покращать продуктивність команди та додадуть впевненості як зміни.

Підсумок

У цій статті ми побачили, що при використанні мов програмування загального призначення нам стають доступними багато методів розробки програмного забезпечення, які були корисні при розробці наших додатків. Вони включають модульне тестування, інтеграційне тестування, а також їх взаємодію для проведення великого runtime-тестування. Тести легко запускати на вимогу або у вашій CI-системі.

Пулумі — програмне забезпечення з відкритим вихідним кодом, воно безкоштовне для використання та працює з вашими улюбленими мовами програмування та хмарами. спробуйте його сьогодні!

Перша частина

Джерело: habr.com

Додати коментар або відгук