Salam, dostlar. Yeni tədris dönəmimizin başlamasına az qaldı. Sizinlə yeni tərcüməni paylaşırıq. Başlayaq.

Pulumi istifadə edərək və ümumi məqsədli proqramlaşdırma dillərini İnfrastruktur Kodu (Infrastructure as Code) üçün istifadə etmək bir çox üstünlük gətirir: bacarıq və biliklərin olması, kodda boilerplate-i abtraksiya ilə aradan qaldırmaq, komandaya tanış olan alətlər, məsələn, IDE və linters. Bütün bu proqram mühəndisliyi alətləri, bizi daha məhsuldar edir, həmçinin kodun keyfiyyətini artırır. Buna görə də, ümumi məqsədli proqramlaşdırma dillərinin istifadəsi, proqram təminatı inkişafının digər mühüm praktikalarını tətbiq etməyə imkan verir — test.
Bu məqalədə, Pulumi-nin bizə "infrastruktur kodu"nu sınaqdan keçirməkdə necə kömək etdiyini müzakirə edəcəyik.

İnfrastrukturun nə üçün sınaqdan keçirilməsi vacibdir?
Detallara getməzdən əvvəl, sual vermək yerinə düşər: "İnfrastrukturun sınaqdan keçirilməsi niyə vacibdir?" Bunun bir çox səbəbi var və bunlardan bəziləri:
- Proqramınızın ayrı-ayrı funksiyalarının və ya məntiq hissələrinin modulyar testləşdirilməsi.
- İnfrastrukturun arzu olunan vəziyyətinin müəyyən məhdudiyetlərlə uyğunluğunu yoxlamaq.
- Məsələn, storage bucket-in şifrələnməməsi və ya virtual maşınların İnternetdən açıq bir şəkildə müdafiəsizdən keçməsi kimi yaygın xətaların aşkar edilməsi.
- İnfrastrukturun provizionlaşdırılması prosesi zamanı yoxlanılması.
- Maruz qalan "proqramlaşdırılmış" infrastruktura daxil edilmiş tətbiqin məntiqinin runtime-testləşdirilməsi, provizionlaşdırmadan sonra işlədiyinə əmin olmaq üçün.
- Gördüyümüz kimi, infrastrukturun sınaqdan keçirilməsi üçün geniş çeşidli variantlar var. Pulumi, bunun hər bir mərhələsi üçün test mexanizmlərinə malikdir. Gəlin başlayaq və bunun necə işlədiyinə baxaq.
Modulyar testləşdirmə
Pulumi proqramları JavaScript, Python, TypeScript və ya Go kimi ümumi məqsədli proqramlaşdırma dillərində yaradılır. Buna görə də, bu dillərin tam gücünü, o cümlədən onların vasitə və kitabxanalarını, o cümlədən test çərçivələrini əldə edirlər. Pulumi multi-cloud-dur, bu da testlər üçün istənilən bulud provayderindən istifadə etməyə imkan verir.
(Bu məqalədə, çoxdilli və multi-cloud olması vəziyyətində, JavaScript və Mocha istifadə edirik və AWS-yə yönəlirik. Python da istifadə oluna bilər. unittest, test çərçivəsi Go və ya sevdiyiniz başqa bir test çərçivəsi. Və əlbəttə ki, Pulumi Azure, Google Cloud, Kubernetes ilə mükəmməl işləyir.)
Gördüyümüz kimi, infrastruktur kodunuzu test etməyin bir neçə səbəbi var. Bunlardan biri adətən modul testidir. Kodunuz CIDR hesablama, dinamik adlar, etiketlər və s. kimi funksiyalara malik ola bilər — ehtimal ki, onları test etmək istəyəcəksiniz. Bu, sevdiyiniz proqramlaşdırma dilində standart modul testlərinin yazılmasına bənzəyir.
Biraz çətinləşdirərək, proqramınızın resursları necə payladığını yoxlaya bilərik. Nümunə olaraq, gəlin sadə bir EC2-server yaratmalı olduğumuzu və aşağıdakılara əmin olmaq istədiyimizi təsəvvür edək:
- İnstantların etiketi var
Ad. - İnstantlar inline-skriptdən istifadə etməməlidir
userData— biz AMI (şəkil) istifadə etməliyik. - İnternetdə açıq olan SSH olmamalıdır.
Bu nümunə :
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 ], // yuxarıda qeyd olunan qrup obyekti
ami: "ami-c55673a0" // biz-east-2 (Ohio) üçün AMI,
userData: userData // sadə bir veb server başlayın
});
exports.group = group;
exports.server = server;
exports.publicIp = server.publicIp;
exports.publicHostName = server.publicDns;
Bu, Pulumi-nin əsas proqramıdır: yalnız EC2 təhlükəsizlik qrupunu və instansını ayırır. Lakin qeyd etmək lazımdır ki, burada yuxarıda qeyd olunan üç qaydanı pozuruq. Gəlin test yazmaya başlayaq!
Test yazırıq
Testlərimizin ümumi strukturu adi Mocha testləri kimi görünəcək:
ec2tests.js
test.js:
let assert = require("assert");
let mocha = require("mocha");
let pulumi = require("@pulumi/pulumi");
let infra = require("./index");
describe("İnfrastruktur", function() {
let server = infra.server;
describe("#server", function() {
// TODO(check 1): Name etiketi olmalıdır.
// TODO(check 2): userData-dan inline-skript olmamalıdır.
});
let group = infra.group;
describe("#group", function() {
// TODO(check 3): İnternetdə açıq olan SSH olmamalıdır.
});
}); İndi gəlin ilk testimizi yazıq: instansiyaların etiketə sahib olduğunu yoxlayaq Ad. Bunu yoxlamaq üçün, sadəcə EC2 instansiya obyektini əldə edirik və müvafiq xüsusiyyəti yoxlayırıq. etiketlər:
// 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();
}
});
});Adi bir testə bənzəyir, lakin diqqəti çəkən bir neçə xüsusiyyəti var:
- Resursun vəziyyətini yaymadan əvvəl soruşduğumuz üçün testlərimiz həmişə "plan" (ya da "preview") rejimində həyata keçirilir. Beləliklə, dəyərini əldə etməyəcəyimiz və ya müəyyən edilməyəcəyi bir çox xüsusiyyət var. Bunlara bulud provayderiniz tərəfindən hesablanmış bütün çıxış xüsusiyyətləri daxildir. Bizim testlərimiz üçün bu, düzgün deyil — biz yalnız giriş məlumatlarını yoxlayırıq. Bu məsələyə daha sonra inteqrasiya testlərinə keçərkən yenidən qayıdacağıq.
- Pulumi resurslarının bütün xüsusiyyətləri "çıxışlar" olduğundan və onların bir çoxu asinxron şəkildə hesablandığından, dəyərlərə daxil olmaq üçün apply metodundan istifadə etməliyik. Bu, vədlərə və birfunksiyaya çox bənzəyir.
onda. - Xəta mesajında resursun URN-ni göstərmək üçün bir neçə xüsusiyyətdən istifadə etdiyimiz üçün, funksiyadan istifadə etməliyik.
pulumi.all, onları birləşdirmək üçün. - Nəhayət, bu dəyərlərin asinxron şəkildə hesablandığını nəzərə alaraq, geri çağırma ilə Mocha-nın daxili asinxron imkanını istifadə etməliyik.
doneya da vəd qaytarma.
Hər şeyi düzəltdikdən sonra, giriş məlumatlarına sadə JavaScript dəyərləri kimi daxil ola biləcəyik. Xüsusiyyət etiketlər map (assosiasiya massivi) olduğundan, sadəcə olaraq bunun (1) false olmadığını və (2) üçün açar olduğunu təsdiqləyəcəyik. Ad. Bu çox asandır və indi hər şeyi yoxlaya bilirik!
İndi ikinci yoxlamamızın kodunu yazaq. Bu daha da asandır:
// 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();
}
});
});Və nəhayət, üçüncü testi yazaq. Bu biraz çətin olacaq, çünki bir çox ola biləcək təhlükəsizlik qrupları ilə əlaqəli giriş qaydalarını axtarırıq və bu qaydalardakı CIDR aralıkları da bir çox ola bilər. Amma biz üstəsindən gəldik:
// 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();
}
});
});Və bu qədər. İndi testləri işə salaq!
Testləri işə salmaq
Testləri işə salmaq, əksər hallarda, seçdiyiniz test çərçivəsindən istifadə edərək adi qaydada mümkündür. Lakin Pulumi-nin diqqət yetirilməyə dəyər bir xüsusiyyəti var.
Adətən Pulumi proqramlarını işə salmaq üçün pulimi CLI (Command Line Interface, komanda sətri interfeysi) istifadə olunur. Bu, dilin runtime-nı təşkil edir, Pulumi mühərrikinin işini idarə edir ki, resurslarla əməliyyatları qeydə almaq və onları planınıza daxil etmək mümkün olsun və sair. Lakin burada bir problem var. Test çərçivənizin nəzarəti altında işə salındıqda, CLI ilə Pulumi mühərriki arasında əlaqə olmayacaq.
Bu problemi aşmaq üçün biz sadəcə aşağıdakılara diqqət yetirməliyik:
- Layihə adı, bu, mühit dəyişənində yerləşir
PULUMI_NODEJS_PROJECT(yaxud, daha ümumi vəziyyətdə,PULUMI__PROJECT digər dillər üçün).
Yığın adını, bu, mühit dəyişənində qeyd olunurPULUMI_NODEJS_STACK(yaxud, daha ümumi vəziyyətdə,PULUMI__STACK).
Yığın konfiqurasiya dəyişənləriniz. Onlar mühit dəyişəni vasitəsilə əldə edilə bilərPULUMI_CONFIGvə onların forması JSON xəritədir, açar/dəyər cütləri ilə.Proqram icra zamanı CLI/mühərrik ilə əlaqənin mövcud olmadığını bildirən xəbərdarlıqlar verəcək. Bu vacibdir, çünki əslində, proqramınız heç bir şey yayımlamayacaq və bu, əgər istədiyiniz bu deyilsə, sizə sürpriz ola bilər! Pulumi-yə bunun sizə lazım olduğunu demək üçün siz
PULUMI_TEST_MODEdaxilindədir.true.təyin etməlisiniz. Təsəvvür edin ki, layihə adını qeyd etməliyik
my-ws, yığın adınıdev, və AWS bölgəsinius-west-2. Mocha testlərini yerinə yetirmək üçün əmrlər aşağıdakı kimi olacaq:$ PULUMI_TEST_MODE=true PULUMI_NODEJS_STACK="my-ws" PULUMI_NODEJS_PROJECT="dev" PULUMI_CONFIG='{ "aws:region": "us-west-2" }' mocha tests.jsBunu yerinə yetirmək, gözlənildiyi kimi, bizə üç düşən test olduğunu göstərəcək!
Infrastructure #server 1) ad etiketi olmalıdır 2) userData istifadə etməməlidir (bunun əvəzinə bir AMI istifadə edin) #group 3) 22 (SSH) portunu internetə açmamalıdır 0 keçən (17ms) 3 düşən 1) Infrastructure #server ad etiketi olmalıdır: Xəta: Serverdə ad etiketi yoxdur urn:pulumi:my-ws::my-dev::aws:ec2/instance:Instance::web-server-www 2) Infrastructure #server userData istifadə etməməlidir (bunun əvəzinə bir AMI istifadə edin): Xəta: Serverdə userData-nın qeyri-qanuni istifadəsi urn:pulumi:my-ws::my-dev::aws:ec2/instance:Instance::web-server-www 3) Infrastructure #group 22 (SSH) portunu internetə açmamalıdır: Xəta: 22 (SSH) portunun internetə açılması (CIDR 0.0.0.0/0) qrup üzərində qeyri-qanuniGəlin proqramımızı düzəldək:
"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 ], // yuxarıdakı qrup obyektinə istinad edir ami: "ami-c55673a0" // us-east-2 (Ohio) üçün AMI, }); exports.group = group; exports.server = server; exports.publicIp = server.publicIp; exports.publicHostName = server.publicDns;Və sonra testləri yenidən yerinə yetirək:
Infrastruktur #server ✓ ad tagı olmalıdır ✓ userData istifadə etməməlidir (bunun əvəzinə AMI istifadə edin) #qrup ✓ port 22 (SSH) İnternete açılmamalıdır 3 müsbət (16ms)Hər şey uğurla keçdi… Ura! ✓✓✓
Bugünkü bu qədər, və yerləşdirmə testindən ikinci hissədə danışacağıq 😉
Mənbə: habr.com
