Nguji Infrastruktur salaku Kode sareng Pulumi. Bagian 1

Wilujeng siang rerencangan. Dina antisipasi mimiti aliran anyar dina laju "Praktik sareng alat DevOps" Kami babagi sareng anjeun tarjamahan anyar. indit.

Nguji Infrastruktur salaku Kode sareng Pulumi. Bagian 1

Ngagunakeun Pulumi sareng basa pamrograman tujuan umum pikeun kode infrastruktur (Infrastruktur salaku Kode) nyayogikeun seueur kauntungan: kasadiaan kaahlian sareng pangaweruh, ngaleungitkeun boilerplate dina kode ngaliwatan abstraksi, alat anu wawuh ka tim anjeun, sapertos IDE sareng linters. Sadaya alat rékayasa parangkat lunak ieu henteu ngan ukur ngajantenkeun urang langkung produktif, tapi ogé ningkatkeun kualitas kode urang. Ku sabab éta, wajar waé yén panggunaan basa pamrograman tujuan umum ngamungkinkeun urang ngenalkeun prakték pamekaran parangkat lunak anu penting - tés.

Dina tulisan ieu, urang bakal ningali kumaha Pulumi ngabantosan urang nguji infrastruktur-sakumaha-kode urang.

Nguji Infrastruktur salaku Kode sareng Pulumi. Bagian 1

Naha nguji infrastruktur?

Sateuacan nuju rinci, éta patut naroskeun patarosan: "Naha nguji infrastruktur pisan?" Aya seueur alesan pikeun ieu sareng ieu sababaraha diantarana:

  • Unit nguji fungsi individu atawa fragmen logika program Anjeun
  • Verifies kaayaan dipikahoyong tina infrastruktur ngalawan konstrain tangtu.
  • Deteksi kasalahan umum, sapertos kurangna énkripsi ember panyimpen atanapi henteu dijagi, muka aksés tina Internét ka mesin virtual.
  • Mariksa palaksanaan penyediaan infrastruktur.
  • Ngalaksanakeun uji runtime tina logika aplikasi anu ngajalankeun di jero infrastruktur "diprogram" anjeun pikeun mariksa fungsionalitas saatos nyayogikeun.
  • Sakumaha anu urang tingali, aya rupa-rupa pilihan uji infrastruktur. Polumi boga mékanisme pikeun nguji dina unggal titik dina spéktrum ieu. Hayu urang ngamimitian tur tingal kumaha gawéna.

Unit nguji

Program Pulumi ditulis dina basa program tujuan umum sapertos JavaScript, Python, TypeScript atanapi Go. Ku alatan éta, kakuatan pinuh tina basa ieu, kaasup parabot jeung perpustakaan maranéhanana, kaasup kerangka test, sadia pikeun aranjeunna. Pulumi mangrupikeun multi-awan, anu hartosna tiasa dianggo pikeun nguji ti panyadia awan.

(Dina tulisan ieu, sanaos multibasa sareng multicloud, kami nganggo JavaScript sareng Mocha sareng fokus kana AWS. Anjeun tiasa nganggo Python. unittest, Kerangka tés Go, atanapi kerangka tés sanés anu anjeun resep. Sareng, tangtosna, Pulumi tiasa dianggo sareng Azure, Google Cloud, Kubernetes.)

Sakumaha urang tingali, aya sababaraha alesan kunaon anjeun hoyong nguji kode infrastruktur anjeun. Salah sahijina nyaéta uji unit konvensional. Kusabab kode anjeun tiasa gaduh fungsi - contona, ngitung CIDR, ngitung nami sacara dinamis, tag, jsb. - Anjeun meureun bakal hoyong nguji aranjeunna. Ieu sami sareng nyerat tés unit biasa pikeun aplikasi dina basa pamrograman karesep anjeun.
Pikeun meunang saeutik leuwih pajeulit, anjeun tiasa pariksa kumaha program Anjeun allocates sumberdaya. Pikeun ngagambarkeun, hayu urang bayangkeun yén urang kedah nyiptakeun server EC2 saderhana sareng urang hoyong mastikeun ieu:

  • Instans gaduh tag Name.
  • Instance teu kedah nganggo skrip inline userData - urang kedah nganggo AMI (gambar).
  • Henteu kedah aya SSH anu kakeunaan Internét.

Conto ieu dumasar kana conto abdi 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;

Ieu mangrupikeun program Pulumi dasar: éta ngan ukur nyayogikeun grup kaamanan EC2 sareng conto. Nanging, kedah diperhatoskeun yén di dieu urang ngalanggar sadayana tilu aturan anu dinyatakeun di luhur. Hayu urang nulis tés!

Tés nulis

Struktur umum tés kami bakal katingali sapertos tés Mocha biasa:

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

Ayeuna hayu urang nulis tés munggaran urang: pastikeun yén instansi boga tag Name. Pikeun mariksa ieu kami ngan ukur kéngingkeun obyék conto EC2 sareng pariksa harta anu aya 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();
                }
            });
        });

Sigana mah tés biasa, tapi kalayan sababaraha fitur anu kedah diperhatoskeun:

  • Kusabab kami naroskeun kaayaan sumberdaya sateuacan nyebarkeun, tés kami salawasna dijalankeun dina mode "rencana" (atanapi "sawangan"). Ku kituna, aya loba pasipatan anu nilaina ngan saukur moal bisa dicokot atawa moal dihartikeun. Ieu kalebet sadaya sipat kaluaran anu diitung ku panyadia awan anjeun. Ieu normal pikeun tés urang - urang ukur pariksa data input. Urang bakal balik deui ka masalah ieu engké, lamun datang ka tés integrasi.
  • Kusabab sakabeh sipat sumberdaya Pulumi mangrupakeun outputs, sarta loba di antarana anu dievaluasi asynchronously, urang kudu make metoda nerapkeun pikeun ngakses nilai. Ieu pisan sarupa janji jeung afunction then .
  • Kusabab kami nganggo sababaraha sipat pikeun nunjukkeun sumberdaya URN dina pesen kasalahan, urang kedah nganggo fungsina pulumi.allpikeun ngagabungkeun aranjeunna.
  • Tungtungna, kumargi nilai-nilai ieu diitung sacara asinkron, urang kedah nganggo fitur callback async diwangun-di Mocha. done atawa ngabalikeun jangji.

Sakali kami geus nyetél sagalana nepi, urang bakal boga aksés ka inputs salaku nilai JavaScript basajan. Harta tags nyaéta peta (array asosiatif), ku kituna urang ngan ukur mastikeun yén éta (1) henteu palsu, sareng (2) aya konci pikeun Name. Éta saderhana pisan sareng ayeuna urang tiasa nguji naon waé!

Ayeuna hayu urang nulis cek kadua urang. Éta langkung saderhana:

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

Sarta pamustunganana, hayu urang nulis test katilu. Ieu bakal saeutik leuwih pajeulit sabab urang pilari aturan login pakait sareng grup kaamanan, nu aya bisa jadi loba, sarta rentang CIDR dina aturan eta, nu aya ogé bisa jadi loba. Tapi kami junun:

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

Éta hungkul. Ayeuna hayu urang ngajalankeun tés!

Ngajalankeun tés

Dina kalolobaan kasus, anjeun tiasa ngajalankeun tés dina cara biasa, ngagunakeun kerangka test pilihan Anjeun. Tapi aya hiji fitur Pulumi anu patut nengetan.
Ilaharna, pikeun ngajalankeun program Pulumi, CLI (antarmuka Command Line) dipaké, nu ngonpigurasikeun runtime basa, ngadalikeun peluncuran mesin Pulumi ku kituna operasi kalawan sumberdaya bisa dirékam tur kaasup kana rencana, jsb. Sanajan kitu, aya hiji masalah. Nalika ngajalankeun dina kadali kerangka tés anjeun, moal aya komunikasi antara CLI sareng mesin Pulumi.

Pikeun ngabéréskeun masalah ieu, urang ngan ukur kedah netepkeun ieu:

  • Ngaran proyék, anu dikandung dina variabel lingkungan PULUMI_NODEJS_PROJECT (atawa, leuwih umum, PULUMI__PROJECT для других языков).
    Ngaran tumpukan anu dieusian dina variabel lingkungan PULUMI_NODEJS_STACK (atawa, leuwih umum, PULUMI__ STACK).
    Variabel konfigurasi tumpukan anjeun. Éta tiasa didapet nganggo variabel lingkungan PULUMI_CONFIG sareng formatna nyaéta peta JSON sareng pasangan konci / nilai.

    Program bakal ngaluarkeun peringatan anu nunjukkeun yén sambungan ka CLI / mesin henteu sayogi nalika palaksanaan. Ieu penting sabab program anjeun moal sabenerna jadi deploying nanaon jeung bisa datang salaku kejutan lamun éta teu naon dimaksudkeun pikeun ngalakukeun! Pikeun ngabejaan Pulumi yén ieu téh kahayang nu peryogi, anjeun tiasa install PULUMI_TEST_MODE в true.

    Bayangkeun urang kedah netepkeun nami proyék di my-ws, ngaran tumpukan dev, jeung AWS Region us-west-2. Garis paréntah pikeun ngajalankeun tés Mocha bakal katingali sapertos kieu:

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

    Ngalakukeun ieu, sapertos anu diharapkeun, bakal nunjukkeun yén urang ngagaduhan tilu tés gagal!

    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

    Hayu urang ngalereskeun program urang:

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

    Teras ngajalankeun tés deui:

    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)

    Sagalana lancar... Hurray! ✓✓✓

    Éta sadayana kanggo dinten ayeuna, tapi urang bakal ngobrol ngeunaan tés penyebaran dina bagian kadua tarjamahan 😉

sumber: www.habr.com

Tambahkeun komentar