Azpiegitura probatzea kode gisa Pulumirekin. 1. zatia

Arratsalde on lagunak. Erritmoan fluxu berri baten hasieraren esperoan "DevOps praktikak eta tresnak" Itzulpen berri bat partekatzen ari gara zurekin. Zoaz.

Azpiegitura probatzea kode gisa Pulumirekin. 1. zatia

Pulumi eta erabilera orokorreko programazio-lengoaiak azpiegitura-koderako (Infrastructure as Code) erabiltzeak abantaila ugari eskaintzen ditu: trebetasun eta ezagutzaren eskuragarritasuna, abstrakzio bidez kodean ezabatzea, zure taldearentzat ezagunak diren tresnak, hala nola IDEak eta linters. Software-ingeniaritza-tresna hauek guztiek produktiboagoak izateaz gain, gure kodearen kalitatea hobetzen gaituzte. Hori dela eta, naturala da helburu orokorreko programazio lengoaiak erabiltzeak software garatzeko beste praktika garrantzitsu bat sartzea ahalbidetzea - probak.

Artikulu honetan, Pulumi-k gure azpiegitura-kode gisa probatzen nola laguntzen digun ikusiko dugu.

Azpiegitura probatzea kode gisa Pulumirekin. 1. zatia

Zergatik probatu azpiegitura?

Xehetasunetan sartu aurretik, merezi du galdera hau egitea: "Zergatik probatu azpiegitura?" Horretarako arrazoi asko daude eta hona hemen horietako batzuk:

  • Funtzio indibidualen edo zure programaren logikaren zatien proba unitatea
  • Murrizketa batzuen aurrean azpiegituraren nahi den egoera egiaztatzen du.
  • Ohiko erroreak hautematea, hala nola biltegiratze-ontzi baten enkriptatze falta edo babesik gabe, Internetetik makina birtualetarako sarbide irekia.
  • Azpiegituren horniduraren ezarpena egiaztatzea.
  • Zure "programatutako" azpiegituraren barruan exekutatzen ari den aplikazio-logikaren exekuzio-probak egitea hornitu ondoren funtzionalitatea egiaztatzeko.
  • Ikus dezakegunez, azpiegitura probatzeko aukera zabala dago. Polumi-k espektro honetako puntu guztietan probatzeko mekanismoak ditu. Has gaitezen eta ikus dezagun nola funtzionatzen duen.

Unitate-probak

Pulumi programak helburu orokorreko programazio lengoaietan idazten dira, hala nola JavaScript, Python, TypeScript edo Go. Hori dela eta, hizkuntza hauen botere osoa, haien tresnak eta liburutegiak barne, proba-esparruak barne, eskuragarri dute. Pulumi hodei anitzekoa da, hau da, edozein hodeiko hornitzaileren probak egiteko erabil daiteke.

(Artikulu honetan, eleanitza eta hodei anitzekoa izan arren, JavaScript eta Mocha erabiltzen ditugu eta AWSn zentratzen gara. Python erabil dezakezu unittest, Go proba-esparrua edo nahi duzun beste edozein proba-esparru. Eta, noski, Pulumi bikain funtzionatzen du Azure, Google Cloud, Kubernetes-ekin.)

Ikusi dugunez, hainbat arrazoi daude zure azpiegitura kodea probatu nahi duzulako. Horietako bat unitate-proba konbentzionalak dira. Zure kodeak funtzioak izan ditzakeelako, adibidez, CIDR kalkulatzeko, izenak, etiketak eta abar dinamikoki kalkulatzeko. - Ziurrenik probatu nahi izango dituzu. Hau da zure programazio-lengoaia gogokoko aplikazioetarako unitate-probak idaztearen berdina.
Apur bat konplikatuagoa izateko, zure programak baliabideak nola esleitzen dituen egiaztatu dezakezu. Ilustratzeko, pentsa dezagun EC2 zerbitzari soil bat sortu behar dugula eta honako hau ziurtatu nahi dugula:

  • Instantziak etiketa bat dute Name.
  • Instantziek ez dute lineako script-a erabili behar userData - AMI bat (irudia) erabili behar dugu.
  • Ez luke SSHrik egon behar Internetera.

Adibide hau oinarritzen da nire adibidea aws-js-webserver:

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;

Hau da Pulumi oinarrizko programa: EC2 segurtasun talde bat eta instantzia bat esleitzen ditu. Hala ere, kontuan izan behar da hemen goian adierazitako hiru arauak hausten ari garela. Idatz ditzagun probak!

Idazketa probak

Gure proben egitura orokorrak Mocha proba arrunten itxura izango du:

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, открытого в Интернет.
    });
});

Orain idatz dezagun gure lehen proba: ziurtatu instantziek etiketa dutela Name. Hau egiaztatzeko, besterik gabe, EC2 instantzia objektua lortu eta dagokion propietatea egiaztatuko dugu 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();
                }
            });
        });

Ohiko proba bat dirudi, baina aipatzeko moduko ezaugarri batzuk ditu:

  • Inplementatu aurretik baliabide baten egoera galdetzen dugunez, gure probak "plan" (edo "aurrebista") moduan exekutatzen dira beti. Horrela, propietate asko daude haien balioak besterik gabe berreskuratuko ez diren edo definituko ez diren. Honek zure hodeiko hornitzaileak kalkulatutako irteerako propietate guztiak barne hartzen ditu. Hau normala da gure probetarako - sarrerako datuak soilik egiaztatzen ditugu. Aurrerago itzuliko gara gai honi, integrazio probei dagokienez.
  • Pulumi baliabideen propietate guztiak irteerak direnez eta horietako asko modu asinkronoan ebaluatzen direnez, aplikatu metodoa erabili behar dugu balioetara sartzeko. Hau promesen eta funtzioaren oso antzekoa da then .
  • Errore mezuan baliabide URN erakusteko hainbat propietate erabiltzen ari garenez, funtzioa erabili behar dugu pulumi.allhoriek konbinatzeko.
  • Azkenik, balio hauek modu asinkronoan kalkulatzen direnez, Mocha-ren itzulera asinkronikoen funtzioa erabili behar dugu. done edo promesa bat itzultzea.

Dena konfiguratu ondoren, sarrerak JavaScript balio soil gisa izango ditugu sarbidea. Jabetza tags mapa bat da (matrize elkartua), beraz (1) faltsua ez dela eta (2) gako bat dagoela ziurtatuko dugu. Name. Oso erraza da eta orain edozer proba dezakegu!

Orain idatz dezagun gure bigarren egiaztapena. Are sinpleagoa da:

 // 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();
                }
            });
        });

Eta azkenik, idatzi dezagun hirugarren proba. Hau apur bat konplikatuagoa izango da segurtasun-taldeari lotutako saio-hasiera-arauak bilatzen ari garelako, asko egon daitezkeenak, eta arau horietan CIDR barrutiak, asko ere egon daitezkeenak. Baina lortu dugu:

    // 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();
                }
            });
        });

Hori da dena. Orain egin ditzagun probak!

Korrika probak

Kasu gehienetan, probak ohiko moduan exekutatu ditzakezu, nahi duzun proba-esparrua erabiliz. Baina bada Pulumiren ezaugarri bat arreta jartzea merezi duena.
Normalean, Pulumi programak exekutatzeko, pulimi CLI (Komando Lerroko interfazea) erabiltzen da, hizkuntzaren exekuzio-denbora konfiguratzen duena, Pulumi motorra abiaraztea kontrolatzen duena, baliabideekin eragiketak grabatu eta planean sartu ahal izateko, etab. Hala ere, arazo bat dago. Zure proba-esparruaren kontrolpean exekutatzen ari zarenean, ez da CLI eta Pulumi motorra arteko komunikaziorik egongo.

Arazo honi aurre egiteko, honako hau zehaztu besterik ez dugu egin behar:

  • Proiektuaren izena, ingurune-aldagaian dagoena PULUMI_NODEJS_PROJECT (edo, oro har, PULUMI__PROJECT для других языков).
    Inguruko aldagaian zehazten den pilaren izena PULUMI_NODEJS_STACK (edo, oro har, PULUMI__ STACK).
    Zure pilaren konfigurazio-aldagaiak. Inguruko aldagai bat erabiliz lor daitezke PULUMI_CONFIG eta haien formatua JSON mapa da gako/balio bikoteekin.

    Programak abisuak emango ditu CLI/motorrarekin konexioa erabilgarri ez dagoela exekutatzen ari den bitartean. Garrantzitsua da zure programak ez duelako ezer zabalduko eta ezustekoa izan daiteke hori egin nahi duzuna ez bada! Pulumi hori behar duzuna dela esateko, instala dezakezu PULUMI_TEST_MODE в true.

    Imajinatu proiektuaren izena zehaztu behar dugula my-ws, pilaren izena deveta AWS eskualdea us-west-2. Mocha probak exekutatzeko komando-lerroa honela izango da:

    $ PULUMI_TEST_MODE=true 
        PULUMI_NODEJS_STACK="my-ws" 
        PULUMI_NODEJS_PROJECT="dev" 
        PULUMI_CONFIG='{ "aws:region": "us-west-2" }' 
        mocha tests.js

    Hau egiteak, espero bezala, hiru proba huts ditugula erakutsiko digu!

    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

    Konpon dezagun gure programa:

    "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;
    

    Eta gero berriro exekutatu probak:

    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)

    Dena ondo atera zen... Aupa! ✓✓✓

    Hori da gaurko guztia, baina itzulpenaren bigarren zatian inplementazio probei buruz hitz egingo dugu 😉

Iturria: www.habr.com

Gehitu iruzkin berria