Mirëdita miq. Në pritje të fillimit të një fluksi të ri në normë
Përdorimi i Pulumi dhe gjuhëve të programimit për qëllime të përgjithshme për kodin e infrastrukturës (Infrastruktura si kod) ofron shumë përparësi: disponueshmërinë e aftësive dhe njohurive, eliminimin e bojlerplate në kod përmes abstraksionit, mjete të njohura për ekipin tuaj, të tilla si IDE dhe linter. Të gjitha këto mjete inxhinierike softuerike jo vetëm që na bëjnë më produktivë, por edhe përmirësojnë cilësinë e kodit tonë. Prandaj, është e natyrshme që përdorimi i gjuhëve programuese për qëllime të përgjithshme na lejon të prezantojmë një praktikë tjetër të rëndësishme të zhvillimit të softuerit - duke testuar.
Në këtë artikull, ne do të shohim se si Pulumi na ndihmon të testojmë infrastrukturën tonë si kod.
Pse të testoni infrastrukturën?
Para se të hyni në detaje, ia vlen të bëni pyetjen: "Pse të testohet fare infrastrukturë?" Ka shumë arsye për këtë dhe këtu janë disa prej tyre:
- Testimi i njësive i funksioneve individuale ose fragmenteve të logjikës së programit tuaj
- Verifikon gjendjen e dëshiruar të infrastrukturës kundrejt kufizimeve të caktuara.
- Zbulimi i gabimeve të zakonshme, të tilla si mungesa e kriptimit të një kovë ruajtjeje ose aksesi i hapur dhe i pambrojtur nga interneti në makinat virtuale.
- Kontrollimi i zbatimit të ofrimit të infrastrukturës.
- Kryerja e testimit të kohës së ekzekutimit të logjikës së aplikacionit që funksionon brenda infrastrukturës tuaj të "programuar" për të kontrolluar funksionalitetin pas sigurimit.
- Siç mund ta shohim, ekziston një gamë e gjerë opsionesh të testimit të infrastrukturës. Polumi ka mekanizma për testim në çdo pikë të këtij spektri. Le të fillojmë dhe të shohim se si funksionon.
Testimi i njësisë
Programet Pulumi janë shkruar në gjuhë programimi për qëllime të përgjithshme si JavaScript, Python, TypeScript ose Go. Prandaj, fuqia e plotë e këtyre gjuhëve, duke përfshirë mjetet dhe bibliotekat e tyre, duke përfshirë kornizat e testimit, është në dispozicion të tyre. Pulumi është me shumë re, që do të thotë se mund të përdoret për testim nga çdo ofrues i reve kompjuterike.
(Në këtë artikull, pavarësisht se jemi shumëgjuhësh dhe me shumë re, ne përdorim JavaScript dhe Mocha dhe fokusohemi në AWS. Ju mund të përdorni Python unittest
, Shkoni në kuadrin e testimit ose ndonjë kornizë tjetër testimi që ju pëlqen. Dhe, sigurisht, Pulumi funksionon shkëlqyeshëm me Azure, Google Cloud, Kubernetes.)
Siç e kemi parë, ka disa arsye pse mund të dëshironi të testoni kodin tuaj të infrastrukturës. Një prej tyre është testimi i njësive konvencionale. Sepse kodi juaj mund të ketë funksione - për shembull, për të llogaritur CIDR, për të llogaritur në mënyrë dinamike emrat, etiketat, etj. - ndoshta do të dëshironi t'i provoni ato. Kjo është e njëjtë me shkrimin e testeve të rregullta të njësive për aplikacione në gjuhën tuaj të preferuar të programimit.
Për t'u bërë pak më i ndërlikuar, mund të kontrolloni se si programi juaj i shpërndan burimet. Për ta ilustruar, le të imagjinojmë se duhet të krijojmë një server të thjeshtë EC2 dhe duam të jemi të sigurt për sa vijon:
- Rastet kanë një etiketë
Name
. - Instancat nuk duhet të përdorin skript inline
userData
- duhet të përdorim një AMI (imazh). - Nuk duhet të ketë asnjë SSH të ekspozuar në internet.
Ky shembull bazohet në
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;
Ky është programi bazë Pulumi: ai thjesht cakton një grup sigurie EC2 dhe një shembull. Megjithatë, duhet theksuar se këtu ne po i thyejmë të tre rregullat e lartpërmendura. Le të shkruajmë teste!
Teste me shkrim
Struktura e përgjithshme e testeve tona do të duket si testet e rregullta Mocha:
ec2testet.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, открытого в Интернет.
});
});
Tani le të shkruajmë testin tonë të parë: sigurohuni që instancat të kenë etiketën Name
. Për ta kontrolluar këtë ne thjesht marrim objektin e shembullit EC2 dhe kontrollojmë vetinë përkatëse 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();
}
});
});
Duket si një test i rregullt, por me disa veçori që ia vlen të përmenden:
- Për shkak se ne kërkojmë gjendjen e një burimi përpara vendosjes, testet tona ekzekutohen gjithmonë në modalitetin "plan" (ose "parapamje"). Kështu, ka shumë prona, vlerat e të cilave thjesht nuk do të merren ose nuk do të përcaktohen. Kjo përfshin të gjitha vetitë e daljes të llogaritura nga ofruesi juaj i resë kompjuterike. Kjo është normale për testet tona - ne kontrollojmë vetëm të dhënat hyrëse. Ne do t'i kthehemi kësaj çështje më vonë, kur bëhet fjalë për testet e integrimit.
- Meqenëse të gjitha vetitë e burimeve Pulumi janë rezultate dhe shumë prej tyre vlerësohen në mënyrë asinkrone, ne duhet të përdorim metodën e aplikimit për të aksesuar vlerat. Kjo është shumë e ngjashme me premtimet dhe funksionet
then
. - Meqenëse po përdorim disa veti për të treguar URN-në e burimit në mesazhin e gabimit, duhet të përdorim funksionin
pulumi.all
për t'i kombinuar ato. - Së fundi, meqenëse këto vlera llogariten në mënyrë asinkrone, ne duhet të përdorim veçorinë e integruar të kthimit të thirrjes asinkronike të Mocha
done
ose kthimi i një premtimi.
Pasi të kemi vendosur gjithçka, do të kemi akses në hyrjet si vlera të thjeshta JavaScript. Prona tags
është një hartë (grup shoqërues), kështu që ne thjesht do të sigurohemi që (1) të mos jetë false, dhe (2) ka një çelës për Name
. Është shumë e thjeshtë dhe tani mund të testojmë gjithçka!
Tani le të shkruajmë kontrollin tonë të dytë. Është edhe më e thjeshtë:
// 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();
}
});
});
Dhe së fundi, le të shkruajmë testin e tretë. Kjo do të jetë pak më e komplikuar sepse ne po kërkojmë rregullat e hyrjes që lidhen me grupin e sigurisë, nga të cilat mund të ketë shumë, dhe CIDR varion në ato rregulla, nga të cilat mund të ketë edhe shumë. Por ne ia dolëm:
// 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();
}
});
});
Kjo eshte e gjitha. Tani le të bëjmë testet!
Vrapimi i testeve
Në shumicën e rasteve, ju mund të kryeni teste në mënyrën e zakonshme, duke përdorur kornizën e testimit të zgjedhjes suaj. Por ka një veçori të Pulumit që ia vlen t'i kushtohet vëmendje.
Në mënyrë tipike, për të ekzekutuar programet Pulumi, përdoret pulimi CLI (ndërfaqja e linjës së komandës), e cila konfiguron kohën e ekzekutimit të gjuhës, kontrollon nisjen e motorit Pulumi në mënyrë që operacionet me burime të mund të regjistrohen dhe përfshihen në plan, etj. Megjithatë, ka një problem. Kur punoni nën kontrollin e kornizës suaj të testimit, nuk do të ketë asnjë komunikim midis CLI dhe motorit Pulumi.
Për të kapërcyer këtë problem, ne vetëm duhet të specifikojmë sa vijon:
- Emri i projektit, i cili gjendet në variablin e mjedisit
PULUMI_NODEJS_PROJECT
(ose, në përgjithësi,PULUMI__PROJECT для других языков).
Emri i pirgut që është specifikuar në variablin e mjedisitPULUMI_NODEJS_STACK
(ose, në përgjithësi,PULUMI__ STACK).
Variablat tuaja të konfigurimit të pirgut. Ato mund të merren duke përdorur një variabël mjedisorPULUMI_CONFIG
dhe formati i tyre është harta JSON me çifte çelës/vlerë.Programi do të lëshojë paralajmërime që tregojnë se lidhja me CLI/motorin nuk është e disponueshme gjatë ekzekutimit. Kjo është e rëndësishme sepse programi juaj në të vërtetë nuk do të vendosë asgjë dhe mund të jetë befasi nëse nuk është ajo çfarë keni menduar të bëni! Për t'i thënë Pulumit se kjo është pikërisht ajo që ju nevojitet, mund ta instaloni
PULUMI_TEST_MODE
вtrue
.Imagjinoni se duhet të specifikojmë emrin e projektit
my-ws
, emri i stivësdev
, dhe Rajoni AWSus-west-2
. Linja e komandës për ekzekutimin e testeve Mocha do të duket si kjo:$ PULUMI_TEST_MODE=true PULUMI_NODEJS_STACK="my-ws" PULUMI_NODEJS_PROJECT="dev" PULUMI_CONFIG='{ "aws:region": "us-west-2" }' mocha tests.js
Bërja e kësaj, siç pritej, do të na tregojë se kemi tre teste të dështuara!
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
Le të rregullojmë programin tonë:
"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;
Dhe pastaj kryeni përsëri testet:
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)
Gjithçka shkoi mirë... Urra! ✓✓✓
Kjo është e gjitha për sot, por ne do të flasim për testimin e vendosjes në pjesën e dytë të përkthimit 😉
Burimi: www.habr.com