Testing Infrastruttura cum'è Codice cù Pulumi. Parte 1

Bona sera amichi. In anticipazione di l'iniziu di un novu flussu à a tarifa "Pratiche è strumenti DevOps" Avemu sparte cun voi una nova traduzzione. Vai.

Testing Infrastruttura cum'è Codice cù Pulumi. Parte 1

Utilizà Pulumi è linguaggi di prugrammazione generale per u codice di l'infrastruttura (Infrastructure as Code) furnisce assai vantaghji: a dispunibilità di cumpetenze è cunniscenze, eliminazione di boilerplate in u codice per astrazione, arnesi familiari à a vostra squadra, cum'è IDE è linters. Tutti issi arnesi di ingegneria di software ùn solu ci facenu più pruduttivi, ma ancu migliurà a qualità di u nostru codice. Per quessa, hè solu naturali chì l'usu di linguaggi di prugrammazione generale ci permette di intruduce una altra pratica impurtante di sviluppu di software - prova.

In issu articulu, avemu Mulateri Di L'guardà cumu Pulumi ci aiuta à pruvà a nostra infrastruttura-as-code.

Testing Infrastruttura cum'è Codice cù Pulumi. Parte 1

Perchè pruvà l'infrastruttura?

Prima di andà in i dettagli, vale a pena dumandà a quistione: "Perchè pruvà l'infrastruttura in tuttu?" Ci hè parechje ragioni per questu è quì sò alcuni di elli:

  • Test di unità di funzioni individuali o frammenti di a logica di u vostru prugramma
  • Verifica u statu desideratu di l'infrastruttura contru à certe limitazioni.
  • A rilevazione di l'errori cumuni, cum'è a mancanza di criptografia di un bucket d'almacenamiento o senza prutezzione, accessu apertu da Internet à e macchine virtuali.
  • Verificazione di l'implementazione di a pruvista di l'infrastruttura.
  • Realizà a prova di runtime di a logica di l'applicazione in esecuzione in a vostra infrastruttura "programata" per verificà a funziunalità dopu l'approvvigionamentu.
  • Comu pudemu vede, ci hè una larga gamma di opzioni di teste di infrastruttura. Polumi hà miccanismi per pruvà in ogni puntu di stu spettru. Accuminciamu è vede cumu funziona.

Test di unità

I prugrammi Pulumi sò scritti in linguaggi di prugrammazione generale cum'è JavaScript, Python, TypeScript o Go. Dunque, tuttu u putere di queste lingue, cumpresi i so arnesi è e librerie, cumpresi i quadri di teste, hè dispunibule per elli. Pulumi hè multi-nuvola, chì significa chì pò esse usatu per pruvà da qualsiasi fornitore di nuvola.

(In questu articulu, malgradu esse multilingue è multicloud, usemu JavaScript è Mocha è fucalizza nantu à AWS. Pudete aduprà Python unittest, Vai quadru di prova, o qualsiasi altru quadru di prova chì ti piace. E, sicuru, Pulumi funziona bè cù Azure, Google Cloud, Kubernetes.)

Comu avemu vistu, ci sò parechje ragioni per quessa chì pudete vulete pruvà u vostru codice di infrastruttura. Unu di elli hè a prova di unità cunvinziunali. Perchè u vostru codice pò avè funzioni - per esempiu, per calculà CIDR, calculà dinamicamente nomi, tag, etc. - Probabilmente vi vulete pruvà. Questu hè u listessu cum'è scrive test di unità regulare per l'applicazioni in a vostra lingua di prugrammazione preferita.
Per fà un pocu più cumplicatu, pudete verificà cumu u vostru prugramma attribuisce risorse. Per illustrà, imaginemu chì avemu bisognu di creà un servitore EC2 simplice è vulemu esse sicuru di e seguenti:

  • L'istanze anu un tag Name.
  • L'istanze ùn deve micca aduprà script inline userData - duvemu aduprà una AMI (imagine).
  • Ùn deve esse micca SSH esposti à Internet.

Stu esempiu hè basatu nantu u mo esempiu 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;

Questu hè u prugramma Pulumi di basa: simpricimenti allocate un gruppu di sicurità EC2 è una istanza. Tuttavia, deve esse nutatu chì quì avemu rumpitu tutte e trè regule dichjarate sopra. Scrivemu testi !

Testi di scrittura

A struttura generale di e nostre teste serà cum'è e teste Mocha regulare:

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

Avà scrivemu a nostra prima prova: assicuratevi chì l'istanze anu u tag Name. Per verificà questu avemu solu ottene l'ughjettu di l'istanza EC2 è verificate a pruprietà currispundente 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();
                }
            });
        });

Sembra una prova regulare, ma cù uni pochi di funziunalità degne di nutà:

  • Perchè dumandemu u statu di una risorsa prima di implementazione, i nostri testi sò sempre eseguiti in modu "pianu" (o "anteprima"). Cusì, ci sò parechje proprietà chì i valori ùn saranu micca ricuperati o ùn saranu micca definiti. Questu include tutte e proprietà di output calculate da u vostru fornitore di nuvola. Questu hè normale per i nostri testi - cuntrollemu solu i dati di input. Riturneremu à sta questione dopu, quandu si tratta di testi di integrazione.
  • Dapoi tutti i pruprietà risorsa Pulumi sò outputs, è parechji di elli sò evaluati asynchronously, avemu bisognu à aduprà u metudu applicàrisi à accede à i valori. Questu hè assai simili à e prumesse è a funzione then .
  • Siccomu avemu aduprà parechje pruprietà per vede u URN di risorsa in u messagiu d'errore, avemu bisognu di utilizà a funzione pulumi.allper cumminà elli.
  • Infine, postu chì sti valori sò calculati in modu asincronu, avemu bisognu di utilizà a funzione di callback async integrata di Mocha. done o rinvià una prumessa.

Una volta avemu stabilitu tuttu, averemu accessu à l'inputs cum'è valori JavaScript simplici. Pruprietà tags hè una mappa (array associative), cusì avemu da assicurassi chì (1) ùn hè micca falsu, è (2) ci hè una chjave per Name. Hè assai simplice è avà pudemu pruvà qualcosa!

Avà scrivemu u nostru secondu cuntrollu. Hè ancu più simplice:

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

È infine, scrivemu a terza prova. Questu serà un pocu più cumplicatu perchè avemu cercatu i reguli di login assuciati cù u gruppu di sicurità, di quale ci ponu esse assai, è u CIDR varieghja in quelli reguli, di quale ci ponu ancu esse assai. Ma avemu riisciutu:

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

Eccu tuttu. Avà andemu à e teste !

Testi in esecuzione

In a maiò parte di i casi, pudete eseguisce e teste in u modu di solitu, utilizendu u quadru di teste di a vostra scelta. Ma ci hè una caratteristica di Pulumi chì vale a pena attenti.
Tipicamenti, à curriri prugrammi Pulumi, veni usatu u pulimi CLI (interfaccia Command Line), chì cunfigurà u runtime lingua, cuntrolla u lanciamentu di u mutore Pulumi cusì chì l'operazioni cù risorse pò esse arregistrata è inclusa in u pianu, etc. Tuttavia, ci hè un prublema. Quandu curriri sottu u cuntrollu di u vostru quadru testu, ùn ci sarà micca cumunicazione trà u CLI è u mutore Pulumi.

Per risolve stu prublema, avemu solu bisognu di specificà i seguenti:

  • U nome di u prughjettu, chì hè cuntenutu in a variabile di l'ambiente PULUMI_NODEJS_PROJECT (o, più in generale, PULUMI__PROJECT для других языков).
    U nome di a pila chì hè specificatu in a variabile d'ambiente PULUMI_NODEJS_STACK (o, più in generale, PULUMI__ STACK).
    E vostre variabili di cunfigurazione di stack. Puderanu esse ottenuti usendu una variabile ambientale PULUMI_CONFIG è u so furmatu hè a mappa JSON cù coppie chjave / valore.

    U prugramma emette avvirtimenti chì indicanu chì a cunnessione à u CLI / motore ùn hè micca dispunibule durante l'esekzione. Questu hè impurtante perchè u vostru prugramma ùn hà micca implementatu nunda è pò esse una sorpresa s'ellu ùn hè micca ciò chì vulete fà! Per dì à Pulumi chì questu hè esattamente ciò chì avete bisognu, pudete installà PULUMI_TEST_MODE в true.

    Imagine chì avemu bisognu di specificà u nome di u prugettu my-ws, nome di pila dev, è a regione AWS us-west-2. A linea di cumanda per eseguisce e teste Mocha sarà cusì:

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

    Fendu questu, cum'è previstu, ci mostrarà chì avemu trè teste falluti!

    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

    Fixemu u nostru prugramma:

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

    E poi eseguite i testi di novu:

    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)

    Tuttu s'hè andatu bè... Hurrah ! ✓✓✓

    Hè tuttu per oghje, ma parlemu di teste di implementazione in a seconda parte di a traduzzione 😉

Source: www.habr.com

Add a comment