Tès enfrastrikti kòm Kòd ak Pulumi. Pati 1

Bon apremidi zanmim yo. Nan patisipe nan kòmansman an nan yon nouvo koule nan pousantaj la "Prattik ak zouti DevOps" Nou ap pataje avèk ou yon nouvo tradiksyon. Ale.

Tès enfrastrikti kòm Kòd ak Pulumi. Pati 1

Sèvi ak Pulumi ak langaj pwogram jeneral pou kòd enfrastrikti (Enfrastrikti kòm Kòd) bay anpil avantaj: disponiblite ladrès ak konesans, eliminasyon boilerplate nan kòd la atravè abstraksyon, zouti abitye nan ekip ou a, tankou IDE ak linters. Tout zouti jeni lojisyèl sa yo pa sèlman fè nou pi pwodiktif, men tou, amelyore kalite kòd nou an. Se poutèt sa, li se sèlman natirèl ke itilizasyon langaj pwogramasyon jeneral pèmèt nou prezante yon lòt pratik devlopman lojisyèl enpòtan - tès.

Nan atik sa a, nou pral gade ki jan Pulumi ede nou teste enfrastrikti-kòm-kòd nou an.

Tès enfrastrikti kòm Kòd ak Pulumi. Pati 1

Poukisa tès enfrastrikti?

Anvan ou antre nan detay, li vo poze kesyon an: "Poukisa tès enfrastrikti ditou?" Gen anpil rezon pou sa e isit la se kèk nan yo:

  • Tès inite fonksyon endividyèl oswa fragman nan lojik pwogram ou an
  • Verifye eta a vle nan enfrastrikti a kont kontrent sèten.
  • Deteksyon erè komen, tankou yon mank de chifreman nan yon bokit depo oswa san pwoteksyon, aksè louvri soti nan entènèt la nan machin vityèl.
  • Tcheke aplikasyon an nan pwovizyon enfrastrikti.
  • Egzekite tès lojik aplikasyon an kouri andedan enfrastrikti "pwograme" ou a pou tcheke fonksyonalite apre pwovizyon.
  • Kòm nou ka wè, gen yon pakèt opsyon tès enfrastrikti. Polumi gen mekanis pou fè tès nan chak pwen sou spectre sa a. Ann kòmanse ak wè ki jan li fonksyone.

Tès inite

Pwogram Pulumi yo ekri nan langaj pwogram jeneral tankou JavaScript, Python, TypeScript oswa Go. Se poutèt sa, tout pouvwa a nan lang sa yo, ki gen ladan zouti yo ak bibliyotèk yo, ki gen ladan kad tès, disponib pou yo. Pulumi se milti-nwaj, ki vle di li ka itilize pou tès nan nenpòt founisè nwaj.

(Nan atik sa a, malgre yo se plizyè lang ak multicloud, nou itilize JavaScript ak Mocha epi konsantre sou AWS. Ou ka itilize Python unittest, Ale tès kad, oswa nenpòt lòt kad tès ou renmen. Epi, nan kou, Pulumi travay byen ak Azure, Google Cloud, Kubernetes.)

Kòm nou te wè, gen plizyè rezon ki fè ou ta vle teste kòd enfrastrikti ou a. Youn nan yo se tès inite konvansyonèl yo. Paske kòd ou a ka gen fonksyon - pou egzanp, kalkile CIDR, dinamik kalkile non, tags, elatriye. - ou pral pwobableman vle teste yo. Sa a se menm jan ak ekri tès inite regilye pou aplikasyon nan lang pwogramasyon ou pi renmen.
Pou jwenn yon ti kras pi konplike, ou ka tcheke ki jan pwogram ou a asiyen resous yo. Pou ilistre, ann imajine ke nou bezwen kreye yon sèvè EC2 senp epi nou vle asire w de sa ki annapre yo:

  • Enstans yo gen yon tag Name.
  • Enstans yo pa ta dwe itilize script inline userData - nou dwe itilize yon AMI (imaj).
  • Pa ta dwe gen okenn SSH ekspoze a entènèt la.

Egzanp sa a baze sou egzanp mwen an 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;

Sa a se pwogram Pulumi debaz la: li tou senpleman asiyen yon gwoup sekirite EC2 ak yon egzanp. Sepandan, li ta dwe remake ke isit la nou ap kraze tout twa règ ki endike anwo a. Ann ekri tès yo!

Tès ekriti

Estrikti jeneral tès nou yo ap sanble ak tès Mocha regilye yo:

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

Koulye a, ann ekri premye tès nou an: asire w ke ka yo gen tag la Name. Pou tcheke sa a nou tou senpleman jwenn objè a egzanp EC2 epi tcheke pwopriyete ki koresponn lan 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();
                }
            });
        });

Li sanble ak yon tès regilye, men ak kèk karakteristik vo anyen:

  • Paske nou mande eta a nan yon resous anvan deplwaman, tès nou yo toujou kouri nan "plan" (oswa "aperçu") mòd. Kidonk, gen anpil pwopriyete ki gen valè tou senpleman pa pral rekipere oswa yo pa pral defini. Sa a gen ladan tout pwopriyete pwodiksyon ki kalkile pa founisè nwaj ou a. Sa a nòmal pou tès nou yo - nou sèlman tcheke done yo antre. Nou pral retounen sou pwoblèm sa a pita, lè li rive tès entegrasyon.
  • Depi tout pwopriyete resous Pulumi yo se rezilta, ak anpil nan yo evalye asynchrone, nou bezwen sèvi ak metòd aplike pou jwenn aksè nan valè yo. Sa a se trè menm jan ak pwomès ak yon fonksyon then .
  • Depi nou ap itilize plizyè pwopriyete pou montre IRN resous la nan mesaj erè a, nou bezwen sèvi ak fonksyon an pulumi.allpou konbine yo.
  • Finalman, depi valè sa yo kalkile asynchrone, nou bezwen sèvi ak karakteristik async callback entegre Mocha a. done oswa retounen yon pwomès.

Yon fwa nou te mete tout bagay kanpe, nou pral gen aksè a antre yo kòm valè JavaScript senp. Pwopriyete tags se yon kat (etalaj asosyasyon), kidonk nou pral jis asire w li (1) pa fo, epi (2) gen yon kle pou Name. Li trè senp epi kounye a nou ka teste anyen!

Koulye a, an n ekri dezyèm chèk nou an. Li se menm pi senp:

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

Epi finalman, ann ekri twazyèm tès la. Sa a pral yon ti kras pi konplike paske nou ap chèche pou règ yo konekte ki asosye ak gwoup la sekirite, nan ki ka gen anpil, ak chenn yo CIDR nan règ sa yo, nan ki kapab genyen tou anpil. Men, nou jere:

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

Se tout. Koulye a, ann kouri tès yo!

Kouri tès yo

Nan pifò ka yo, ou ka fè tès yo nan fason nòmal la, lè l sèvi avèk fondasyon tès ou chwazi a. Men, gen yon karakteristik nan Pulumi ki vo peye atansyon sou.
Tipikman, pou kouri pwogram Pulumi, yo itilize pulimi CLI (koòdone liy kòmand), ki configured tan langaj la, kontwole lansman motè Pulumi pou operasyon ak resous yo ka anrejistre epi enkli nan plan an, elatriye. Sepandan, gen yon pwoblèm. Lè w ap kouri anba kontwòl fondasyon tès ou a, pa pral gen okenn kominikasyon ant CLI a ak motè Pulumi a.

Pou rezoud pwoblèm sa a, nou jis bezwen presize bagay sa yo:

  • Non pwojè, ki genyen nan varyab anviwònman an PULUMI_NODEJS_PROJECT (oswa, pi jeneralman, PULUMI__PROJECT для других языков).
    Non pil la ki espesifye nan varyab anviwònman an PULUMI_NODEJS_STACK (oswa, pi jeneralman, PULUMI__ STACK).
    Varyab konfigirasyon pil ou a. Yo ka jwenn lè l sèvi avèk yon varyab anviwònman PULUMI_CONFIG ak fòma yo se kat JSON ak pè kle/valè.

    Pwogram nan pral bay avètisman ki endike ke koneksyon an nan CLI/motè a pa disponib pandan ekzekisyon an. Sa a enpòtan paske pwogram ou a pa pral aktyèlman ap deplwaye anyen epi li ka vini kòm yon sipriz si se pa sa ou gen entansyon fè! Pou di Pulumi ke sa a se egzakteman sa ou bezwen, ou ka enstale PULUMI_TEST_MODE в true.

    Imajine nou bezwen presize non pwojè a nan my-ws, pile non dev, ak AWS Rejyon us-west-2. Liy lòd pou kouri tès Mocha yo pral sanble sa a:

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

    Lè w fè sa, jan nou espere, sa pral montre nou ke nou gen twa tès echwe!

    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

    Ann ranje pwogram nou an:

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

    Apre sa, fè tès yo ankò:

    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)

    Tout bagay ale byen... Hurray! ✓✓✓

    Se tout pou jodi a, men nou pral pale sou tès deplwaman nan dezyèm pati tradiksyon an 😉

Sous: www.habr.com

Add nouvo kòmantè