Infrastruktuuri testimine kui kood Pulumi abil. Osa 1

Tere päevast, sõbrad. Uue koolituse voolu alguses jagame teiega uut tõlget. Alustame. „DevOps praktikas ja tööriistades“ Kasutades Pulumit ja üldkasutatavaid programmeerimiskeeli infrastruktuuri kodeerimiseks (Infrastructure as Code), on palju eeliseid: oskuste ja teadmiste olemasolu, koodis boilerplate'i kõrvaldamine abstraktsiooni kaudu, tuttavad teie meeskonnale tööriistad, nagu IDE ja linterid. Kõik need tarkvaraarenduse tööriistad mitte ainult ei muuda meid tootlikumaks, vaid parandavad ka koodi kvaliteeti. Seetõttu on täiesti loomulik, et üldkasutatavate programmeerimiskeelte kasutamine võimaldab rakendada veel ühte olulist tarkvaraarenduse praktikat —

Infrastruktuuri testimine kui kood Pulumi abil. Osa 1

Selles artiklis uurime, kuidas Pulumi aitab testida meie "infrastruktuuri nagu koodi". testimine.

Miks testida infrastruktuuri?

Infrastruktuuri testimine kui kood Pulumi abil. Osa 1

Enne kui sukelduda üksikasjadesse, on oluline esitada küsimus: "Miks üldse infrastruktuuri testida?" Selleks on palju põhjuseid ja mõned neist on:

Üksikute funktsioonide või loogika fragmentide moodulite testimine teie programmis

  • Moodultestimine teie programmi üksikute funktsioonide või loogika fragmentide jaoks
  • Soovitud infrastruktuuri seisundi kontrollimine vastavuses kehtestatud piirangutega.
  • Levinud vigade tuvastamine, näiteks salvestuse konteineri krüpteerimise puudumine või kaitsmata avatud juurdepääs virtuaalmasinatele Internetis.
  • Infrastruktuuri proviisioonimise täitmise kontrollimine.
  • Rakenduse loogika runtime-testimine, mis töötatakse teie 'programmeeritud' infrastruktuuri sees, et kontrollida töökindlust pärast proviisioonimist.
  • Nagu näeme, on infrastruktuuri testimiseks lai valik võimalusi. Pulumis on igas selle ulatuses testimiseks mehhanismid. Alustame ja vaatame, kuidas see töötab.

Moodulite testimine

Pulumi programmid luuakse üldotstarbelistes programmeerimiskeeltes, nagu JavaScript, Python, TypeScript või Go. Seetõttu on nende jaoks saadaval nende keelte täiskatse, sealhulgas nende tööriistade ja raamatute, sealhulgas testimisraamistike täiendavad võimalused. Pulumi on multicloud, mis tähendab, et testimiseks saab kasutada kõiki pilveteenuse pakkujaid.

(Selles artiklis, hoolimata mitmekeelsusest ja pilvepõhisest lähenemisest, kasutame JavaScripti ja Mocha ning keskendume AWS-ile. Võib kasutada ka Pythonit, unittest, Go testimisraamatukogu või mõnda muud teile meelepärast testimisraamatukogu. Ja loomulikult töötab Pulumi suurepäraselt Azure'i, Google Cloudi ja Kubernetesega.)

Nagu oleme näinud, on mitu põhjust, miks võib olla vajalik testida oma infrastruktuuri koodi. Üks neist on tavapärane moodulitestimine. Kuna teie koodil võivad olla funktsioonid – näiteks CIDR-i arvutamine, dünaamiline nimede arvutamine, sildid jms – soovite tõenäoliselt need testida. See on sama, mis tavaliste moodulitestide kirjutamine teie lemmik programmeerimiskeeles.
Kui asju veidi keerulisemaks teha, saame kontrollida, kuidas teie programm ressursse jaotab. Näitena kujutame ette, et peame looma lihtsa EC2-serveri ja tahame veenduda, et:

  • Instantsidel on silt Nimi.
  • Instantsid ei tohiks kasutada inline-skripti userData — peame kasutama AMI (pildi).
  • SSH-d ei tohiks olla avatud internetile.

See näide on kirjutatud inspiratsiooniks minu näide 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 ], // viidake ülalmainitud grupi objektile
    ami: "ami-c55673a0"             // AMI us-east-2 (Ohio) jaoks,
    userData: userData              // käivitada lihtne veebiserver
});
 
exports.group = group;
exports.server = server;
exports.publicIp = server.publicIp;
exports.publicHostName = server.publicDns;

See on Pulumi väärtusprogramm: see eraldab lihtsalt EC2 turvagruppi ja instantsi. Siiski tuleb märkida, et siin rikume kõiki kolme ülaltoodud reeglit. Hakakem testima!

Kirjutame teste

Meie testide üldine struktuur näeb välja nagu tavapärased Mocha-testid:

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): Nimi silt peaks olema olemas.
        // TODO(check 2): Inline userData skripti ei tohi olla.
    });
    let group = infra.group;
    describe("#group", function() {
        // TODO(check 3): SSH ei tohi olla avatud Internetile.
    });
});

Nüüd kirjutame meie esimese testi: veendume, et eksemplaril on silt Nimi. Selle kontrollimiseks saame lihtsalt EC2-investeeringu objekti ja kontrollime vastavat omadust 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();
                }
            });
        });

Tundub nagu tavaline test, kuid sellel on mõned tähelepanuväärsed eripärad:

  • Kuna küsime ressursi olekut enne juurutamist, siis meie testid käivad alati "plaani" (või "eelvaate") režiimis. Seetõttu on palju omadusi, mille väärtusi lihtsalt ei saada või need jäävad määratlemata. Siia kuuluvad kõik väljundomadused, mida teie pilveteenuse pakkuja arvutab. Meie testide jaoks on see täiesti normaalne — me kontrollime vaid sisendeid. Selle küsimuse juurde tuleme tagasi hiljem, kui jõuame integratsioonitestide juurde.
  • Kuna kõik Pulumi ressursside omadused on "väljundid" ja paljusid neist arvutatakse asünkroonselt, peame väärtuste kätte saamiseks kasutama meetodit apply. See on väga sarnaselt lubadustele ja afunktsioonidele. then .
  • Kuna kasutame mitmeid omadusi, et näidata ressursi URN-i veateates, peame kasutama funktsiooni pulumi.all, et neid kokku viia.
  • Lõpuks, kuna need väärtused arvutatakse asünkroonselt, peame kasutama Mocha sisseehitatud asünkroonset funktsionaalsust tagasisidest või lubadusest. done või lubaduse tagastamist.

Pärast kõike seadistamist saame sisendandmetele juurdepääsu nagu lihtsatele JavaScripti väärtustele. Atribuut tags on kaardina (assotsiatiivne massiiv), seega kontrollime lihtsalt, et see (1) ei ole vale ja (2) on võti. Nimi. See on väga lihtne ja nüüd saame kõik, mida iganes, kontrollida!

Nüüd kirjutame meie teise testi. See on veelgi lihtsam:

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

Ja lõpuks kirjutame kolmanda testi. See on natuke keerulisem, sest otsime sisendreegleid, mis on seotud turvagruppidega, mida võib olla palju, ja CIDRi vahemikke nendes reeglites, mida võib samuti olla palju. Kuid me saime hakkama:

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

See on kõik. Nüüd käivitame testid!

Testide käitamine

Testide käitamine on enamasti tavaline, kasutades teie valitud testiraami. Kuid Pulumi puhul on üks eripära, millele tasub tähelepanu pöörata.
Tavaliselt kasutatakse Pulumi programmide käivitamiseks pulumi CLI (Command Line Interface, käsurealiides), mis seadistab keele jooksutarkvara, kontrollib Pulumi mootori käivitusi, et saaks salvestada ressursi operatsioone ja kaasata need plaani jne. Kuid on üks probleem. Kui käivitate oma testiraami kontrolli all, ei toimu CLI ja Pulumi mootori vahel sidet.

Selle probleemi lahendamiseks peame lihtsalt määrama järgmised asjad:

  • Projektinimi, mis on salvestatud keskkonnamuutujas PULUMI_NODEJS_PROJECT (või, üldisemalt, PULUMI__PROJECT teistele keeltele).
    Stacki nimi, mis on määratud keskkonnamuutujas PULUMI_NODEJS_STACK (või, üldisemalt, PULUMI__STACK).
    Teie stacki konfiguratsioonimuutujad. Need saab hankida keskkonnamuutujast PULUMI_CONFIG ja nende formaat on JSON kaardina võtme/väärtuse paaridega.

    Programm annab hoiatuse, et CLI/engine'iga ühendus pole täitmise ajal saadaval. See on oluline, kuna teie programm ei suuda midagi üles laadida, ja see võib olla üllatus, kui see polnud teie kavatsus! Pulumile öelda, et see on just see, mida vajate, saate seada PULUMI_TEST_MODE ühes true.

    Kujutage ette, et peame määrama projekti nime my-ws, korruse nime dev, ja AWS piirkonna us-west-2. Mocha testide tegemise käsk näeb välja järgmine:

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

    Selle teostamine, nagu oodata oli, näitab meile, et meil on kolm ebaõnnestunud testi!

    Infrastruktuur
        #server
          1) peab olema nime silt
     	 2) ei tohi kasutada userData (kasutage asemel AMI-d)
        #group
          3) ei tohi avada porti 22 (SSH) Interneti jaoks
    
      0 möödas (17ms)
      3 ebaõnnestunud
     
     1) Infrastruktuur
           #server
             peab olema nime silt:
         Viga: Serveril puudub nime silt
            urn:pulumi:my-ws::my-dev::aws:ec2/instance:Instance::web-server-www
    
     2) Infrastruktuur
           #server
             ei tohi kasutada userData (kasutage AMI-d asemel):
         Viga: Ebaseaduslik userData kasutamine serveris
            urn:pulumi:my-ws::my-dev::aws:ec2/instance:Instance::web-server-www
    
     3) Infrastruktuur
           #group
             ei tohi avada porti 22 (SSH) Interneti jaoks:
         Viga: Ebaseaduslik SSH port 22 avatud Internetis (CIDR 0.0.0.0/0) grupi jaoks

    Parandame meie programmi:

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

    Ja siis käivitame testid uuesti:

    Infrastruktuur
        #server
          ✓ peab olema nime silt
          ✓ ei tohi kasutada userData (kasuta selle asemel AMI)
        #group
          ✓ ei tohi avada porti 22 (SSH) Interneti jaoks
     
     
     3 läbis (16ms)

    Kõik läks hästi... Hoooray! ✓✓✓

    Täna on kõik, aga arutame juurutamise testimist teises osa tõlkes 😉

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster