Profi Isadeiledd fel Cod gyda Pulumi. Rhan 1

Prynhawn da ffrindiau. Gan ragweld cychwyn llif newydd ar y gyfradd "Arferion ac offer DevOps" Rydym yn rhannu cyfieithiad newydd gyda chi. Ewch.

Profi Isadeiledd fel Cod gyda Pulumi. Rhan 1

Mae defnyddio Pulumi ac ieithoedd rhaglennu pwrpas cyffredinol ar gyfer cod seilwaith (Isadeiledd fel Cod) yn darparu llawer o fanteision: argaeledd sgiliau a gwybodaeth, dileu plât boeler yn y cod trwy dynnu, offer sy'n gyfarwydd i'ch tîm, megis IDEs a linters. Mae'r holl offer peirianneg meddalwedd hyn nid yn unig yn ein gwneud ni'n fwy cynhyrchiol, ond hefyd yn gwella ansawdd ein cod. Felly, nid yw ond yn naturiol bod y defnydd o ieithoedd rhaglennu pwrpas cyffredinol yn caniatáu inni gyflwyno arfer datblygu meddalwedd pwysig arall - profi.

Yn yr erthygl hon, byddwn yn edrych ar sut mae Pulumi yn ein helpu i brofi ein seilwaith-fel-god.

Profi Isadeiledd fel Cod gyda Pulumi. Rhan 1

Pam profi seilwaith?

Cyn mynd i fanylder, mae'n werth gofyn y cwestiwn: "Pam profi seilwaith o gwbl?" Mae llawer o resymau am hyn a dyma rai ohonynt:

  • Profi uned o swyddogaethau unigol neu ddarnau o resymeg eich rhaglen
  • Yn gwirio cyflwr dymunol y seilwaith yn erbyn rhai cyfyngiadau.
  • Canfod gwallau cyffredin, megis diffyg amgryptio bwced storio neu heb ddiogelwch, mynediad agored o'r Rhyngrwyd i beiriannau rhithwir.
  • Gwirio gweithrediad y ddarpariaeth seilwaith.
  • Perfformio profion amser rhedeg ar resymeg cymhwysiad sy'n rhedeg y tu mewn i'ch seilwaith “rhaglennu” i wirio ymarferoldeb ar ôl darparu.
  • Fel y gallwn weld, mae ystod eang o opsiynau profi seilwaith. Mae gan Polumi fecanweithiau ar gyfer profi ar bob pwynt ar y sbectrwm hwn. Gadewch i ni ddechrau a gweld sut mae'n gweithio.

Profi uned

Mae rhaglenni Pulumi wedi'u hysgrifennu mewn ieithoedd rhaglennu pwrpas cyffredinol fel JavaScript, Python, TypeScript neu Go. Felly, mae pŵer llawn yr ieithoedd hyn, gan gynnwys eu hoffer a'u llyfrgelloedd, gan gynnwys fframweithiau prawf, ar gael iddynt. Mae Pulumi yn aml-gwmwl, sy'n golygu y gellir ei ddefnyddio ar gyfer profi gan unrhyw ddarparwr cwmwl.

(Yn yr erthygl hon, er ein bod yn amlieithog ac amlgwmwl, rydym yn defnyddio JavaScript a Mocha ac yn canolbwyntio ar AWS. Gallwch ddefnyddio Python unittest, Ewch fframwaith prawf, neu unrhyw fframwaith prawf arall yr ydych yn hoffi. Ac, wrth gwrs, mae Pulumi yn gweithio'n wych gydag Azure, Google Cloud, Kubernetes.)

Fel y gwelsom, mae sawl rheswm pam y gallech fod am brofi eich cod seilwaith. Un ohonynt yw profi uned confensiynol. Oherwydd efallai bod gan eich cod swyddogaethau - er enghraifft, i gyfrifo CIDR, cyfrifo enwau, tagiau, ac ati yn ddeinamig. - mae'n debyg y byddwch am eu profi. Mae hyn yr un peth ag ysgrifennu profion uned rheolaidd ar gyfer cymwysiadau yn eich hoff iaith raglennu.
I fynd ychydig yn fwy cymhleth, gallwch wirio sut mae'ch rhaglen yn dyrannu adnoddau. I ddangos, gadewch i ni ddychmygu bod angen i ni greu gweinydd EC2 syml ac rydym am fod yn sicr o'r canlynol:

  • Mae gan enghreifftiau dag Name.
  • Ni ddylai enghreifftiau ddefnyddio sgript fewnol userData - rhaid i ni ddefnyddio AMI (delwedd).
  • Ni ddylai unrhyw SSH fod yn agored i'r Rhyngrwyd.

Mae'r enghraifft hon yn seiliedig ar fy enghraifft aws-js-webserver:

mynegai.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;

Dyma'r rhaglen Pulumi sylfaenol: yn syml, mae'n dyrannu grŵp diogelwch EC2 ac enghraifft. Fodd bynnag, dylid nodi ein bod yn torri pob un o'r tair rheol a nodir uchod yma. Gadewch i ni ysgrifennu profion!

Profion ysgrifennu

Bydd strwythur cyffredinol ein profion yn edrych fel profion Mocha rheolaidd:

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

Nawr, gadewch i ni ysgrifennu ein prawf cyntaf: gwnewch yn siŵr bod gan yr achosion y tag Name. I wirio hyn, yn syml, rydym yn cael y gwrthrych enghraifft EC2 a gwirio'r eiddo cyfatebol 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();
                }
            });
        });

Mae'n edrych fel prawf rheolaidd, ond gydag ychydig o nodweddion sy'n werth eu nodi:

  • Oherwydd ein bod yn cwestiynu cyflwr adnodd cyn ei ddefnyddio, mae ein profion bob amser yn cael eu rhedeg yn y modd “cynllun” (neu “rhagolwg”). Felly, mae yna lawer o eiddo na fydd eu gwerthoedd yn cael eu hadalw neu na fyddant yn cael eu diffinio. Mae hyn yn cynnwys yr holl briodweddau allbwn a gyfrifwyd gan eich darparwr cwmwl. Mae hyn yn arferol ar gyfer ein profion - dim ond y data mewnbwn rydyn ni'n ei wirio. Byddwn yn dychwelyd at y mater hwn yn ddiweddarach, pan ddaw i brofion integreiddio.
  • Gan fod holl briodweddau adnoddau Pulumi yn allbynnau, a bod llawer ohonynt yn cael eu gwerthuso'n anghydamserol, mae angen i ni ddefnyddio'r dull cymhwyso i gael mynediad at y gwerthoedd. Mae hyn yn debyg iawn i addewidion a swyddogaeth then .
  • Gan ein bod yn defnyddio sawl priodwedd i ddangos yr URN adnodd yn y neges gwall, mae angen i ni ddefnyddio'r ffwythiant pulumi.alli'w cyfuno.
  • Yn olaf, gan fod y gwerthoedd hyn yn cael eu cyfrifo'n anghydamserol, mae angen i ni ddefnyddio nodwedd galw yn ôl async adeiledig Mocha done neu ddychwelyd addewid.

Unwaith y byddwn wedi sefydlu popeth, bydd gennym fynediad at y mewnbynnau fel gwerthoedd JavaScript syml. Eiddo tags yn fap (arae cysylltiadol), felly byddwn yn gwneud yn siŵr ei fod (1) ddim yn ffug, a (2) mae allwedd ar gyfer Name. Mae'n syml iawn a nawr gallwn brofi unrhyw beth!

Nawr gadewch i ni ysgrifennu ein hail siec. Mae hyd yn oed yn symlach:

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

Ac yn olaf, gadewch i ni ysgrifennu'r trydydd prawf. Bydd hyn ychydig yn fwy cymhleth oherwydd ein bod yn chwilio am y rheolau mewngofnodi sy'n gysylltiedig â'r grŵp diogelwch, y gall fod llawer ohonynt, ac mae'r amrediadau CIDR yn y rheolau hynny, a gall fod llawer ohonynt hefyd. Ond fe wnaethon ni reoli:

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

Dyna i gyd. Nawr gadewch i ni redeg y profion!

Rhedeg profion

Yn y rhan fwyaf o achosion, gallwch chi gynnal profion yn y ffordd arferol, gan ddefnyddio'r fframwaith prawf o'ch dewis. Ond mae un nodwedd o Pulumi y mae'n werth talu sylw iddi.
Yn nodweddiadol, i redeg rhaglenni Pulumi, defnyddir y CLI pulimi (rhyngwyneb Llinell Orchymyn), sy'n ffurfweddu'r amser rhedeg iaith, yn rheoli lansiad yr injan Pulumi fel y gellir cofnodi gweithrediadau gydag adnoddau a'u cynnwys yn y cynllun, ac ati. Fodd bynnag, mae un broblem. Wrth redeg o dan reolaeth eich fframwaith prawf, ni fydd unrhyw gyfathrebu rhwng y CLI a'r injan Pulumi.

I fynd o gwmpas y mater hwn, does ond angen i ni nodi'r canlynol:

  • Enw'r prosiect, sydd wedi'i gynnwys yn y newidyn amgylchedd PULUMI_NODEJS_PROJECT (neu, yn fwy cyffredinol, PULUMI__PROJECT для других языков).
    Enw'r pentwr a nodir yn y newidyn amgylchedd PULUMI_NODEJS_STACK (neu, yn fwy cyffredinol, PULUMI__ STACK).
    Eich newidynnau cyfluniad pentwr. Gellir eu cael gan ddefnyddio newidyn amgylchedd PULUMI_CONFIG a'u fformat yw map JSON gyda pharau allwedd/gwerth.

    Bydd y rhaglen yn cyhoeddi rhybuddion yn nodi nad yw'r cysylltiad â'r CLI/injan ar gael yn ystod y cyfnod gweithredu. Mae hyn yn bwysig oherwydd ni fydd eich rhaglen yn defnyddio unrhyw beth mewn gwirionedd a gallai fod yn syndod os nad dyna'r hyn yr oeddech yn bwriadu ei wneud! I ddweud wrth Pulumi mai dyma'r union beth sydd ei angen arnoch chi, gallwch chi osod PULUMI_TEST_MODE в true.

    Dychmygwch fod angen i ni nodi enw'r prosiect yn my-ws, enw pentwr dev, a Rhanbarth AWS us-west-2. Bydd y llinell orchymyn ar gyfer rhedeg profion Mocha yn edrych fel hyn:

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

    Bydd gwneud hyn, yn ôl y disgwyl, yn dangos i ni fod tri phrawf wedi methu!

    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

    Gadewch i ni drwsio ein rhaglen:

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

    Ac yna rhedeg y profion eto:

    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)

    Aeth popeth yn iawn... Hurray! ✓✓✓

    Dyna i gyd ar gyfer heddiw, ond byddwn yn siarad am brofi lleoli yn ail ran y cyfieithiad 😉

Ffynhonnell: hab.com

Ychwanegu sylw