Փորձարկման ենթակառուցվածքը որպես ծածկագիր Pulumi-ի հետ: Մաս 1

Բարի երեկո ընկերներ: տոկոսադրույքով նոր հոսքի մեկնարկի ակնկալիքով «DevOps պրակտիկա և գործիքներ» Մենք ձեզ հետ կիսվում ենք նոր թարգմանությամբ։ Գնա։

Փորձարկման ենթակառուցվածքը որպես ծածկագիր Pulumi-ի հետ: Մաս 1

Ենթակառուցվածքի կոդի համար Pulumi-ի և ընդհանուր նշանակության ծրագրավորման լեզուների օգտագործումը (Ենթակառուցվածքը որպես կոդ) տալիս է բազմաթիվ առավելություններ՝ հմտությունների և գիտելիքների առկայություն, աբստրակցիայի միջոցով կոդի մեջ կաթսայի վերացում, ձեր թիմին ծանոթ գործիքներ, ինչպիսիք են IDE-ները և linters-երը: Ծրագրային ինժեներական այս բոլոր գործիքները ոչ միայն մեզ ավելի արդյունավետ են դարձնում, այլև բարելավում են մեր կոդի որակը: Հետևաբար, բնական է, որ ընդհանուր նշանակության ծրագրավորման լեզուների օգտագործումը թույլ է տալիս մեզ ներկայացնել ծրագրային ապահովման մշակման ևս մեկ կարևոր պրակտիկա. փորձարկում.

Այս հոդվածում մենք կնայենք, թե ինչպես է Pulumi-ն օգնում մեզ փորձարկել մեր ենթակառուցվածքը որպես կոդ:

Փորձարկման ենթակառուցվածքը որպես ծածկագիր Pulumi-ի հետ: Մաս 1

Ինչու՞ փորձարկել ենթակառուցվածքը:

Նախքան մանրամասնելը, արժե հարց տալ. «Ինչո՞ւ ընդհանրապես փորձարկել ենթակառուցվածքը»: Դրա համար շատ պատճառներ կան, և ահա դրանցից մի քանիսը.

  • Ձեր ծրագրի տրամաբանության առանձին ֆունկցիաների կամ դրվագների միավորի փորձարկում
  • Ստուգում է ենթակառուցվածքի ցանկալի վիճակը՝ ընդդեմ որոշակի սահմանափակումների:
  • Ընդհանուր սխալների հայտնաբերում, ինչպիսիք են պահեստավորման դույլի գաղտնագրման բացակայությունը կամ անապահով, բաց մուտքը ինտերնետից դեպի վիրտուալ մեքենաներ:
  • Ենթակառուցվածքների ապահովման իրականացման ստուգում:
  • Ձեր «ծրագրավորված» ենթակառուցվածքի ներսում գործարկվող կիրառական տրամաբանության գործարկման ժամանակի թեստավորում՝ տրամադրումից հետո ֆունկցիոնալությունը ստուգելու համար:
  • Ինչպես տեսնում ենք, ենթակառուցվածքի փորձարկման տարբերակների լայն շրջանակ կա: Polumi-ն ունի այս սպեկտրի յուրաքանչյուր կետում փորձարկման մեխանիզմներ: Եկեք սկսենք և տեսնենք, թե ինչպես է այն աշխատում:

Միավորի փորձարկում

Pulumi ծրագրերը գրված են ընդհանուր նշանակության ծրագրավորման լեզուներով, ինչպիսիք են JavaScript, Python, TypeScript կամ Go: Հետևաբար, այս լեզուների ողջ հզորությունը, ներառյալ դրանց գործիքներն ու գրադարանները, ներառյալ թեստային շրջանակները, հասանելի են նրանց համար: Pulumi-ն բազմաբնույթ ամպ է, ինչը նշանակում է, որ այն կարող է օգտագործվել ցանկացած ամպային մատակարարի փորձարկման համար:

(Այս հոդվածում, չնայած բազմալեզու և բազմալեզու լինելուն, մենք օգտագործում ենք JavaScript և Mocha և կենտրոնանում ենք AWS-ի վրա: Կարող եք օգտագործել Python-ը unittest, Գնացեք թեստային շրջանակ կամ ցանկացած այլ թեստային շրջանակ, որը Ձեզ դուր է գալիս: Եվ, իհարկե, Pulumi-ն հիանալի է աշխատում Azure-ի, Google Cloud-ի, Kubernetes-ի հետ:)

Ինչպես տեսանք, կան մի քանի պատճառ, թե ինչու կարող եք փորձարկել ձեր ենթակառուցվածքի կոդը: Դրանցից մեկը սովորական միավորի փորձարկումն է: Քանի որ ձեր կոդը կարող է ունենալ գործառույթներ, օրինակ՝ CIDR-ը հաշվարկելու, անունների, պիտակների դինամիկ հաշվարկի համար և այլն: - Դուք հավանաբար կցանկանաք փորձարկել դրանք: Սա նույնն է, ինչ ձեր սիրած ծրագրավորման լեզվով հավելվածների համար սովորական միավորի թեստեր գրելը:
Մի փոքր ավելի բարդանալու համար կարող եք ստուգել, ​​թե ինչպես է ձեր ծրագիրը բաշխում ռեսուրսները: Պատկերացնելու համար եկեք պատկերացնենք, որ մենք պետք է ստեղծենք պարզ EC2 սերվեր և ցանկանում ենք վստահ լինել հետևյալում.

  • Օրինակներն ունեն պիտակ Name.
  • Օրինակները չպետք է օգտագործեն ներկառուցված սցենար userData - մենք պետք է օգտագործենք AMI (պատկեր):
  • Չպետք է լինի SSH, որը ենթարկվում է ինտերնետին:

Այս օրինակը հիմնված է իմ օրինակը 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;

Սա Pulumi-ի հիմնական ծրագիրն է. այն պարզապես հատկացնում է EC2 անվտանգության խումբ և օրինակ: Այնուամենայնիվ, հարկ է նշել, որ այստեղ մենք խախտում ենք վերը նշված բոլոր երեք կանոնները: Եկեք թեստեր գրենք:

Գրավոր թեստեր

Մեր թեստերի ընդհանուր կառուցվածքը նման կլինի սովորական Mocha թեստերին.

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

Հիմա եկեք գրենք մեր առաջին թեստը. համոզվեք, որ օրինակներն ունեն պիտակ Name. Սա ստուգելու համար մենք պարզապես ստանում ենք EC2 օրինակի օբյեկտը և ստուգում համապատասխան հատկությունը 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();
                }
            });
        });

Դա սովորական թեստ է թվում, բայց մի քանի առանձնահատկություններով, որոնք արժե ուշադրություն դարձնել.

  • Քանի որ մենք հարցնում ենք ռեսուրսի վիճակը նախքան տեղակայումը, մեր թեստերը միշտ գործարկվում են «պլան» (կամ «նախադիտում») ռեժիմում: Այսպիսով, կան բազմաթիվ հատկություններ, որոնց արժեքները պարզապես չեն վերականգնվի կամ չեն սահմանվի: Սա ներառում է ձեր ամպային մատակարարի կողմից հաշվարկված բոլոր ելքային հատկությունները: Սա նորմալ է մեր թեստերի համար. մենք ստուգում ենք միայն մուտքային տվյալները: Այս հարցին մենք կանդրադառնանք ավելի ուշ, երբ խոսքը վերաբերում է ինտեգրացիոն թեստերին:
  • Քանի որ Pulumi ռեսուրսի բոլոր հատկությունները ելքեր են, և դրանցից շատերը գնահատվում են ասինխրոն, մենք պետք է օգտագործենք կիրառել մեթոդը արժեքներին մուտք գործելու համար: Սա շատ նման է խոստումներին և գործառույթներին then .
  • Քանի որ մենք օգտագործում ենք մի քանի հատկություններ՝ ռեսուրսի URN-ը սխալի հաղորդագրության մեջ ցուցադրելու համար, մենք պետք է օգտագործենք ֆունկցիան pulumi.allդրանք համատեղելու համար:
  • Վերջապես, քանի որ այս արժեքները հաշվարկվում են ասինխրոն, մենք պետք է օգտագործենք Mocha-ի ներկառուցված ասինխրոն զանգի հնարավորությունը done կամ վերադարձնել խոստումը:

Ամեն ինչ կարգավորելուց հետո մենք մուտքեր կունենանք որպես JavaScript պարզ արժեքներ: Սեփականություն tags քարտեզ է (ասոցիատիվ զանգված), այնպես որ մենք պարզապես կհամոզվենք, որ այն (1) կեղծ չէ, և (2) կա բանալի Name. Դա շատ պարզ է, և այժմ մենք կարող ենք ամեն ինչ փորձարկել:

Հիմա գրենք մեր երկրորդ ստուգումը։ Նույնիսկ ավելի պարզ է.

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

Եվ վերջապես գրենք երրորդ թեստը։ Սա մի փոքր ավելի բարդ կլինի, քանի որ մենք փնտրում ենք մուտքի կանոններ՝ կապված անվտանգության խմբի հետ, որոնցից շատերը կարող են լինել, և CIDR-ի միջակայքերը այդ կանոններում, որոնցից կարող են նաև շատ լինել: Բայց մեզ հաջողվեց.

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

Այսքանը: Հիմա եկեք անցկացնենք թեստերը:

Վազքի թեստեր

Շատ դեպքերում դուք կարող եք թեստեր անցկացնել սովորական եղանակով՝ օգտագործելով ձեր ընտրած թեստային շրջանակը: Բայց կա Պուլումիի մեկ առանձնահատկություն, որի վրա արժե ուշադրություն դարձնել.
Սովորաբար, Pulumi ծրագրերը գործարկելու համար օգտագործվում է pulimi CLI (Command Line ինտերֆեյս), որը կարգավորում է լեզվի գործարկման ժամանակը, վերահսկում է Pulumi շարժիչի գործարկումը, որպեսզի ռեսուրսներով գործողությունները կարողանան գրանցվել և ներառվել պլանում և այլն: Այնուամենայնիվ, կա մեկ խնդիր. Երբ աշխատում եք ձեր փորձարկման շրջանակի հսկողության ներքո, CLI-ի և Pulumi շարժիչի միջև հաղորդակցություն չի լինի:

Այս խնդիրը շրջանցելու համար մենք պարզապես պետք է նշենք հետևյալը.

  • Ծրագրի անվանումը, որը պարունակվում է շրջակա միջավայրի փոփոխականում PULUMI_NODEJS_PROJECT (կամ, ավելի ընդհանուր, PULUMI__PROJECT для других языков).
    Դույլի անվանումը, որը նշված է շրջակա միջավայրի փոփոխականում PULUMI_NODEJS_STACK (կամ, ավելի ընդհանուր, PULUMI__ STACK).
    Ձեր բուրգի կազմաձևման փոփոխականները: Դրանք կարելի է ձեռք բերել՝ օգտագործելով շրջակա միջավայրի փոփոխական PULUMI_CONFIG և դրանց ձևաչափը JSON քարտեզ է՝ բանալին/արժեք զույգերով:

    Ծրագիրը կհրապարակի նախազգուշացումներ՝ նշելով, որ միացումը CLI/շարժիչին հասանելի չէ կատարման ընթացքում: Սա կարևոր է, քանի որ ձեր ծրագիրը իրականում ոչինչ չի տեղակայի և կարող է անակնկալ լինել, եթե դա այն չէ, ինչ դուք մտադիր էիք անել: Pulumi-ին ասելու համար, որ դա հենց այն է, ինչ ձեզ հարկավոր է, կարող եք տեղադրել PULUMI_TEST_MODE в true.

    Պատկերացրեք, որ մենք պետք է նշենք նախագծի անվանումը my-ws, բուրգի անվանումը dev, և AWS տարածաշրջան us-west-2. Mocha-ի թեստերը գործարկելու հրամանի տողը կունենա հետևյալ տեսքը.

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

    Դա անելը, ինչպես և սպասվում էր, մեզ ցույց կտա, որ մենք ունենք երեք անհաջող թեստ:

    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

    Եկեք շտկենք մեր ծրագիրը.

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

    Եվ հետո նորից կատարեք թեստերը.

    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)

    Ամեն ինչ լավ անցավ... Ուռա՜ ✓✓✓

    Այսօրվա համար այսքանն է, բայց թարգմանության երկրորդ մասում կխոսենք տեղակայման թեստավորման մասին 😉

Source: www.habr.com

Добавить комментарий