Selamat petang kawan-kawan. Dalam jangkaan permulaan aliran baharu pada kadar
Menggunakan Pulumi dan bahasa pengaturcaraan tujuan umum untuk kod infrastruktur (Infrastruktur sebagai Kod) memberikan banyak kelebihan: ketersediaan kemahiran dan pengetahuan, penghapusan boilerplate dalam kod melalui abstraksi, alat yang biasa digunakan oleh pasukan anda, seperti IDE dan linter. Semua alat kejuruteraan perisian ini bukan sahaja menjadikan kami lebih produktif, tetapi juga meningkatkan kualiti kod kami. Oleh itu, adalah wajar bahawa penggunaan bahasa pengaturcaraan tujuan umum membolehkan kami memperkenalkan satu lagi amalan pembangunan perisian penting - ujian.
Dalam artikel ini, kami akan melihat cara Pulumi membantu kami menguji infrastruktur-sebagai-kod kami.
Mengapa menguji infrastruktur?
Sebelum terperinci, patut ditanya soalan: "Mengapa menguji infrastruktur sama sekali?" Terdapat banyak sebab untuk ini dan berikut adalah beberapa daripadanya:
- Ujian unit fungsi individu atau serpihan logik program anda
- Mengesahkan keadaan infrastruktur yang dikehendaki terhadap kekangan tertentu.
- Pengesanan ralat biasa, seperti kekurangan penyulitan baldi storan atau tidak dilindungi, membuka akses dari Internet ke mesin maya.
- Menyemak pelaksanaan penyediaan infrastruktur.
- Menjalankan ujian masa jalan bagi logik aplikasi yang berjalan di dalam infrastruktur "diprogramkan" anda untuk menyemak kefungsian selepas peruntukan.
- Seperti yang kita lihat, terdapat pelbagai pilihan ujian infrastruktur. Polumi mempunyai mekanisme untuk ujian pada setiap titik pada spektrum ini. Mari mulakan dan lihat cara ia berfungsi.
Ujian unit
Program Pulumi ditulis dalam bahasa pengaturcaraan tujuan umum seperti JavaScript, Python, TypeScript atau Go. Oleh itu, kuasa penuh bahasa ini, termasuk alatan dan perpustakaan mereka, termasuk rangka kerja ujian, tersedia untuk mereka. Pulumi adalah berbilang awan, yang bermaksud ia boleh digunakan untuk ujian daripada mana-mana pembekal awan.
(Dalam artikel ini, walaupun berbilang bahasa dan multicloud, kami menggunakan JavaScript dan Mocha dan menumpukan pada AWS. Anda boleh menggunakan Python unittest
, Rangka kerja ujian Go atau mana-mana rangka kerja ujian lain yang anda suka. Dan, sudah tentu, Pulumi berfungsi hebat dengan Azure, Google Cloud, Kubernetes.)
Seperti yang telah kita lihat, terdapat beberapa sebab mengapa anda mungkin ingin menguji kod infrastruktur anda. Salah satunya adalah ujian unit konvensional. Kerana kod anda mungkin mempunyai fungsi - contohnya, untuk mengira CIDR, mengira nama, teg, dsb. - anda mungkin mahu mengujinya. Ini adalah sama seperti menulis ujian unit biasa untuk aplikasi dalam bahasa pengaturcaraan kegemaran anda.
Untuk menjadi lebih rumit, anda boleh menyemak cara program anda memperuntukkan sumber. Untuk menggambarkan, mari bayangkan bahawa kita perlu mencipta pelayan EC2 yang mudah dan kami ingin memastikan perkara berikut:
- Kejadian mempunyai teg
Name
. - Kejadian tidak boleh menggunakan skrip sebaris
userData
- kita mesti menggunakan AMI (imej). - Seharusnya tiada SSH yang terdedah kepada Internet.
Contoh ini berdasarkan
index.js:
"use strict";
let aws = require("@pulumi/aws");
let group = new aws.ec2.SecurityGroup("web-secgrp", {
ingress: [
{ protocol: "tcp", fromPort: 22, toPort: 22, cidrBlocks: ["0.0.0.0/0"] },
{ protocol: "tcp", fromPort: 80, toPort: 80, cidrBlocks: ["0.0.0.0/0"] },
],
});
let userData =
`#!/bin/bash
echo "Hello, World!" > index.html
nohup python -m SimpleHTTPServer 80 &`;
let server = new aws.ec2.Instance("web-server-www", {
instanceType: "t2.micro",
securityGroups: [ group.name ], // reference the group object above
ami: "ami-c55673a0" // AMI for us-east-2 (Ohio),
userData: userData // start a simple web server
});
exports.group = group;
exports.server = server;
exports.publicIp = server.publicIp;
exports.publicHostName = server.publicDns;
Ini ialah program Pulumi asas: ia hanya memperuntukkan kumpulan keselamatan EC2 dan contoh. Walau bagaimanapun, perlu diingatkan bahawa di sini kita melanggar ketiga-tiga peraturan yang dinyatakan di atas. Mari tulis ujian!
Ujian menulis
Struktur umum ujian kami akan kelihatan seperti ujian Mocha biasa:
ec2tests.js
test.js:
let assert = require("assert");
let mocha = require("mocha");
let pulumi = require("@pulumi/pulumi");
let infra = require("./index");
describe("Infrastructure", function() {
let server = infra.server;
describe("#server", function() {
// TODO(check 1): ΠΠΎΠ»ΠΆΠ΅Π½ Π±ΡΡΡ ΡΡΠ³ Name.
// TODO(check 2): ΠΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±ΡΡΡ inline-ΡΠΊΡΠΈΠΏΡΠ° userData.
});
let group = infra.group;
describe("#group", function() {
// TODO(check 3): ΠΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±ΡΡΡ SSH, ΠΎΡΠΊΡΡΡΠΎΠ³ΠΎ Π² ΠΠ½ΡΠ΅ΡΠ½Π΅Ρ.
});
});
Sekarang mari tulis ujian pertama kami: pastikan kejadian mempunyai teg Name
. Untuk menyemak ini, kami hanya mendapatkan objek contoh EC2 dan semak sifat yang sepadan tags
:
// check 1: ΠΠΎΠ»ΠΆΠ΅Π½ Π±ΡΡΡ ΡΡΠ³ Name.
it("must have a name tag", function(done) {
pulumi.all([server.urn, server.tags]).apply(([urn, tags]) => {
if (!tags || !tags["Name"]) {
done(new Error(`Missing a name tag on server ${urn}`));
} else {
done();
}
});
});
Ia kelihatan seperti ujian biasa, tetapi dengan beberapa ciri yang perlu diberi perhatian:
- Kerana kami menanyakan keadaan sumber sebelum penggunaan, ujian kami sentiasa dijalankan dalam mod "pelan" (atau "pratonton"). Oleh itu, terdapat banyak sifat yang nilainya tidak akan diambil atau tidak akan ditakrifkan. Ini termasuk semua sifat output yang dikira oleh pembekal awan anda. Ini adalah perkara biasa untuk ujian kami - kami hanya menyemak data input. Kami akan kembali kepada isu ini kemudian, apabila ia datang kepada ujian penyepaduan.
- Memandangkan semua sifat sumber Pulumi adalah output, dan kebanyakannya dinilai secara tak segerak, kita perlu menggunakan kaedah guna untuk mengakses nilai. Ini sangat serupa dengan janji dan fungsi
then
. - Memandangkan kami menggunakan beberapa sifat untuk menunjukkan URN sumber dalam mesej ralat, kami perlu menggunakan fungsi tersebut
pulumi.all
untuk menggabungkan mereka. - Akhir sekali, memandangkan nilai ini dikira secara tak segerak, kita perlu menggunakan ciri panggil balik async terbina dalam Mocha
done
atau membalas janji.
Setelah kami menyediakan segala-galanya, kami akan mempunyai akses kepada input sebagai nilai JavaScript yang mudah. Harta benda tags
ialah peta (tatasusunan bersekutu), jadi kami hanya akan memastikan ia (1) tidak palsu, dan (2) terdapat kunci untuk Name
. Ia sangat mudah dan kini kami boleh menguji apa sahaja!
Sekarang mari kita tulis cek kedua kita. Ia lebih mudah:
// check 2: ΠΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±ΡΡΡ inline-ΡΠΊΡΠΈΠΏΡΠ° userData.
it("must not use userData (use an AMI instead)", function(done) {
pulumi.all([server.urn, server.userData]).apply(([urn, userData]) => {
if (userData) {
done(new Error(`Illegal use of userData on server ${urn}`));
} else {
done();
}
});
});
Dan akhirnya, mari kita tulis ujian ketiga. Ini akan menjadi lebih rumit sedikit kerana kami sedang mencari peraturan log masuk yang dikaitkan dengan kumpulan keselamatan, yang mungkin terdapat banyak, dan julat CIDR dalam peraturan tersebut, yang boleh juga banyak. Tetapi kami berjaya:
// check 3: ΠΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±ΡΡΡ SSH, ΠΎΡΠΊΡΡΡΠΎΠ³ΠΎ Π² ΠΠ½ΡΠ΅ΡΠ½Π΅Ρ.
it("must not open port 22 (SSH) to the Internet", function(done) {
pulumi.all([ group.urn, group.ingress ]).apply(([ urn, ingress ]) => {
if (ingress.find(rule =>
rule.fromPort == 22 && rule.cidrBlocks.find(block =>
block === "0.0.0.0/0"))) {
done(new Error(`Illegal SSH port 22 open to the Internet (CIDR 0.0.0.0/0) on group ${urn}`));
} else {
done();
}
});
});
Itu sahaja. Sekarang mari jalankan ujian!
Menjalankan ujian
Dalam kebanyakan kes, anda boleh menjalankan ujian dengan cara biasa, menggunakan rangka kerja ujian pilihan anda. Tetapi ada satu ciri Pulumi yang patut diberi perhatian.
Biasanya, untuk menjalankan program Pulumi, CLI (antara muka Talian Perintah) cili digunakan, yang mengkonfigurasi masa jalan bahasa, mengawal pelancaran enjin Pulumi supaya operasi dengan sumber boleh direkodkan dan dimasukkan ke dalam pelan, dsb. Walau bagaimanapun, terdapat satu masalah. Apabila berjalan di bawah kawalan rangka kerja ujian anda, tidak akan ada komunikasi antara CLI dan enjin Pulumi.
Untuk mengatasi masalah ini, kami hanya perlu menentukan perkara berikut:
- Nama projek, yang terkandung dalam pembolehubah persekitaran
PULUMI_NODEJS_PROJECT
(atau, lebih umum,PULUMI__PROJECT Π΄Π»Ρ Π΄ΡΡΠ³ΠΈΡ ΡΠ·ΡΠΊΠΎΠ²).
Nama timbunan yang dinyatakan dalam pembolehubah persekitaranPULUMI_NODEJS_STACK
(atau, lebih umum,PULUMI__ STACK).
Pembolehubah konfigurasi tindanan anda. Mereka boleh didapati menggunakan pembolehubah persekitaranPULUMI_CONFIG
dan formatnya ialah peta JSON dengan pasangan kunci/nilai.Program ini akan mengeluarkan amaran yang menunjukkan bahawa sambungan kepada CLI/enjin tidak tersedia semasa pelaksanaan. Ini penting kerana program anda sebenarnya tidak akan menggunakan apa-apa dan ia mungkin mengejutkan jika bukan itu yang anda ingin lakukan! Untuk memberitahu Pulumi bahawa ini adalah apa yang anda perlukan, anda boleh memasang
PULUMI_TEST_MODE
Π²true
.Bayangkan kita perlu menentukan nama projek dalam
my-ws
, nama timbunandev
, dan Wilayah AWSus-west-2
. Baris arahan untuk menjalankan ujian Mocha akan kelihatan seperti ini:$ PULUMI_TEST_MODE=true PULUMI_NODEJS_STACK="my-ws" PULUMI_NODEJS_PROJECT="dev" PULUMI_CONFIG='{ "aws:region": "us-west-2" }' mocha tests.js
Melakukan ini, seperti yang dijangka, akan menunjukkan kepada kita bahawa kita mempunyai tiga ujian yang gagal!
Infrastructure #server 1) must have a name tag 2) must not use userData (use an AMI instead) #group 3) must not open port 22 (SSH) to the Internet 0 passing (17ms) 3 failing 1) Infrastructure #server must have a name tag: Error: Missing a name tag on server urn:pulumi:my-ws::my-dev::aws:ec2/instance:Instance::web-server-www 2) Infrastructure #server must not use userData (use an AMI instead): Error: Illegal use of userData on server urn:pulumi:my-ws::my-dev::aws:ec2/instance:Instance::web-server-www 3) Infrastructure #group must not open port 22 (SSH) to the Internet: Error: Illegal SSH port 22 open to the Internet (CIDR 0.0.0.0/0) on group
Mari kita betulkan program kami:
"use strict"; let aws = require("@pulumi/aws"); let group = new aws.ec2.SecurityGroup("web-secgrp", { ingress: [ { protocol: "tcp", fromPort: 80, toPort: 80, cidrBlocks: ["0.0.0.0/0"] }, ], }); let server = new aws.ec2.Instance("web-server-www", { tags: { "Name": "web-server-www" }, instanceType: "t2.micro", securityGroups: [ group.name ], // reference the group object above ami: "ami-c55673a0" // AMI for us-east-2 (Ohio), }); exports.group = group; exports.server = server; exports.publicIp = server.publicIp; exports.publicHostName = server.publicDns;
Dan kemudian jalankan ujian sekali lagi:
Infrastructure #server β must have a name tag β must not use userData (use an AMI instead) #group β must not open port 22 (SSH) to the Internet 3 passing (16ms)
Semuanya berjalan lancar... Hore! βββ
Itu sahaja untuk hari ini, tetapi kita akan bercakap tentang ujian penggunaan dalam bahagian kedua terjemahan π
Sumber: www.habr.com