ื˜ืขืกื˜ื™ื ื’ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ ื•ื•ื™ ืงืึธื“ ืžื™ื˜ Pulumi. ื˜ื™ื™ืœ 1

ื’ื•ื˜ ื ืึธื›ืžื™ื˜ืึธื’ ืคืจื™ื™ื ื˜. ืื™ืŸ ืึทื ื˜ื™ืกืึทืคึผื™ื™ืฉืึทืŸ ืคื•ืŸ ื“ื™ ืึธื ื”ื™ื™ื‘ ืคื•ืŸ ืึท ื ื™ื™ึท ืœื•ื™ืคืŸ ืื™ืŸ ื“ืขื ืงื•ืจืก "DevOps ืคึผืจืึทืงื˜ื™ืกื™ื– ืื•ืŸ ืžื›ืฉื™ืจื™ื" ืžื™ืจ ื˜ื™ื™ืœืŸ ืžื™ื˜ ืื™ืจ ืึท ื ื™ื™ึทืข ืื™ื‘ืขืจื–ืขืฆื•ื ื’. ื’ื™ื™.

ื˜ืขืกื˜ื™ื ื’ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ ื•ื•ื™ ืงืึธื“ ืžื™ื˜ Pulumi. ื˜ื™ื™ืœ 1

ื ื™ืฆืŸ Pulumi ืื•ืŸ ื’ืขื ืขืจืึทืœ-ืฆื•ื•ืขืง ืคึผืจืึธื’ืจืึทืžืžื™ื ื’ ืฉืคึผืจืึทื›ืŸ ืคึฟืึทืจ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ ืงืึธื“ (ื™ื ืคืจืึทืกื˜ื˜ืจืึทืงื˜ืฉืขืจ ื•ื•ื™ ืงืึธื“) ื’ื™ื˜ ืคื™ืœืข ืึทื“ื•ื•ืึทื ื˜ื™ื“ื–ืฉื™ื–: ื“ื™ ืึทื•ื•ื™ื™ืœืึทื‘ื™ืœืึทื˜ื™ ืคื•ืŸ ืกืงื™ืœื– ืื•ืŸ ื•ื•ื™ืกืŸ, ื™ืœื™ืžืึทื ื™ื™ืฉืึทืŸ ืคื•ืŸ ืงืขืกืœ ืคึผืœืึทื˜ืข ืื™ืŸ ื“ื™ ืงืึธื“ ื“ื•ืจืš ืึทื‘ืกื˜ืจืึทืงืฆื™ืข, ืžื›ืฉื™ืจื™ื ื‘ืึทืงืึทื ื˜ ืฆื• ื“ื™ื™ืŸ ืžืึทื ืฉืึทืคึฟื˜, ืึทื–ืึท ื•ื•ื™ IDE ืื•ืŸ ืœื™ื˜ืขืจื–. ืึทืœืข ื“ื™ ื•ื•ื™ื™ื›ื•ื•ืืจื’ ื™ื ื–ืฉืขื ื™ืขืจื™ืข ืžื›ืฉื™ืจื™ื ืžืึทื›ืŸ ืื•ื ื“ื– ื ื™ื˜ ื‘ืœื•ื™ื– ืžืขืจ ืคึผืจืึธื“ื•ืงื˜ื™ื•ื•, ืึธื‘ืขืจ ืื•ื™ืš ืคึฟืึทืจื‘ืขืกืขืจืŸ ื“ื™ ืงื•ื•ืึทืœื™ื˜ืขื˜ ืคื•ืŸ ืื•ื ื“ื–ืขืจ ืงืึธื“. ื“ืขืจื™ื‘ืขืจ, ืขืก ืื™ื– ื ืึธืจ ื ืึทื˜ื™ืจืœืขืš ืึทื– ื“ื™ ื ื•ืฆืŸ ืคื•ืŸ ื’ืขื ืขืจืึทืœ-ืฆื™ืœ ืคึผืจืึธื’ืจืึทืžืžื™ื ื’ ืฉืคึผืจืึทื›ืŸ ืึทืœืึทื•ื– ืื•ื ื“ื– ืฆื• ื‘ืึทืงืขื ืขืŸ ืืŸ ืื ื“ืขืจ ื•ื•ื™ื›ื˜ื™ืง ื•ื•ื™ื™ื›ื•ื•ืืจื’ ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคื™ืจ - ื˜ืขืกื˜ื™ื ื’.

ืื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ, ืžื™ืจ ื•ื•ืขืœืŸ ืงื•ืงืŸ ื•ื•ื™ Pulumi ื”ืขืœืคึผืก ืื•ื ื“ื– ืคึผืจื•ื‘ื™ืจืŸ ืื•ื ื“ื–ืขืจ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ-ื•ื•ื™-ืงืึธื“.

ื˜ืขืกื˜ื™ื ื’ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ ื•ื•ื™ ืงืึธื“ ืžื™ื˜ Pulumi. ื˜ื™ื™ืœ 1

ืคืืจื•ื•ืืก ืคึผืจื•ื‘ื™ืจืŸ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ?

ืื™ื™ื“ืขืจ ืื™ืจ ื’ื™ื™ืŸ ืื™ืŸ ื“ืขื˜ืึทืœ, ืขืก ืื™ื– ื•ื•ืขืจื˜ ืฆื• ืคืจืขื’ืŸ ื“ื™ ืงืฉื™ื: "ืคืืจื•ื•ืืก ืคึผืจื•ื‘ื™ืจืŸ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ ืื™ืŸ ืึทืœืข?" ืขืก ื–ืขื ืขืŸ ืคื™ืœืข ืกื™ื‘ื•ืช ืคึฟืึทืจ ื“ืขื ืื•ืŸ ื“ืึธ ื–ืขื ืขืŸ ืขื˜ืœืขื›ืข ืคื•ืŸ โ€‹โ€‹ื–ื™ื™:

  • ืึทืคึผืึทืจืึทื˜ ื˜ืขืกื˜ื™ื ื’ ืคื•ืŸ ื™ื—ื™ื“ ืคืึทื ื’ืงืฉืึทื ื– ืึธื“ืขืจ ืคืจืึทื’ืžืึทื ืฅ ืคื•ืŸ ื“ื™ื™ืŸ ืคึผืจืึธื’ืจืึทื ืœืึธื’ื™ืง
  • ื•ื•ืขืจืึทืคื™ื™ื– ื“ื™ ื’ืขื•ื•ืืœื˜ ืฉื˜ืึทื˜ ืคื•ืŸ ื“ื™ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ ืงืขื’ืŸ ื–ื™ื›ืขืจ ืงืึทื ืกื˜ืจื™ื™ื ืฅ.
  • ื“ื™ื˜ืขืงืฉืึทืŸ ืคื•ืŸ ืคึผืจืึธืกื˜ ืขืจืจืึธืจืก, ืึทื–ืึท ื•ื•ื™ ืึท ืคืขืœืŸ ืคื•ืŸ ืขื ืงืจื™ืคึผืฉืึทืŸ ืคื•ืŸ ืึท ืกื˜ืึธืจื™ื“ื–ืฉ ืขืžืขืจ ืึธื“ืขืจ ืึทื ืคึผืจืึทื˜ืขืงื˜ื™ื“, ืขืคืขื ืขืŸ ืึทืงืกืขืก ืคื•ืŸ ื“ื™ ืื™ื ื˜ืขืจื ืขื˜ ืฆื• ื•ื•ื™ืจื˜ื•ืึทืœ ืžืืฉื™ื ืขืŸ.
  • ืงืึธื ื˜ืจืึธืœื™ืจื•ื ื’ ื“ื™ ื™ืžืคึผืœืึทืžืขื ื˜ื™ื™ืฉืึทืŸ ืคื•ืŸ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ ืคึผืจืึทื•ื•ื™ื–ืฉืึทื ื–.
  • ืคึผืขืจืคืึธืจืžื™ื ื’ ืจื•ื ื˜ื™ืžืข ื˜ืขืกื˜ื™ื ื’ ืคื•ืŸ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืœืึธื’ื™ืง ืคืœื™ืกื ื“ื™ืง ืื™ืŸ ื“ื™ื™ืŸ "ืคึผืจืึธื•ื’ืจืึทืžื“" ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ ืฆื• ืงืึธื ื˜ืจืึธืœื™ืจืŸ ื“ื™ ืคืึทื ื’ืงืฉืึทื ืึทืœื™ื˜ื™ ื ืึธืš ืคึผืจืึทื•ื•ื™ื–ืฉืึทื ื–.
  • ื•ื•ื™ ืžื™ืจ ืงืขื ืขืŸ ื–ืขืŸ, ืขืก ืื™ื– ืึท ื‘ืจื™ื™ื˜ ืงื™ื™ื˜ ืคื•ืŸ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ ื˜ืขืกื˜ื™ื ื’ ืึธืคึผืฆื™ืขืก. Polumi ื”ืื˜ ืžืขืงืึทื ื™ื–ืึทืžื– ืคึฟืึทืจ ื˜ืขืกื˜ื™ื ื’ ืื™ืŸ ื™ืขื“ืขืจ ืคื•ื ื˜ ืื•ื™ืฃ ื“ืขื ืกืคึผืขืงื˜ืจื•ื. ื–ืืœ ืก ืึธื ื”ื™ื™ื‘ืŸ ืื•ืŸ ื–ืขืŸ ื•ื•ื™ ืขืก ืึทืจื‘ืขื˜.

ืึทืคึผืึทืจืึทื˜ ื˜ืขืกื˜ื™ื ื’

ืคึผื•ืœื•ืžื™ ืžื’ื™ืœื” ื–ืขื ืขืŸ ื’ืขืฉืจื™ื‘ืŸ ืื™ืŸ ืึทืœื’ืขืžื™ื™ืŸ-ืฆื•ื•ืขืง ืคึผืจืึธื’ืจืึทืžืžื™ื ื’ ืฉืคึผืจืึทื›ืŸ ืึทื–ืึท ื•ื•ื™ ื“ื–ืฉืึทื•ื•ืึทืกืงืจื™ืคึผื˜, ืคึผื™ื˜ื”ืึธืŸ, ื˜ื™ืคึผืกืงืจื™ืคึผื˜ ืึธื“ืขืจ ื’ื™ื™ืŸ. ื“ืขืจื™ื‘ืขืจ, ื“ื™ ืคื•ืœ ืžืึทื›ื˜ ืคื•ืŸ ื“ื™ ืฉืคึผืจืึทื›ืŸ, ืึทืจื™ื™ึทื ื’ืขืจืขื›ื ื˜ ื–ื™ื™ืขืจ ืžื›ืฉื™ืจื™ื ืื•ืŸ ืœื™ื™ื‘ืจืขืจื™ื–, ืึทืจื™ื™ึทื ื’ืขืจืขื›ื ื˜ ืคึผืจืึธื‘ืข ืคืจืึทืžืขื•ื•ืึธืจืงืก, ืื™ื– ื‘ืืจืขื›ื˜ื™ื’ื˜ ืคึฟืึทืจ ื–ื™ื™. Pulumi ืื™ื– ืžืึทืœื˜ื™-ื•ื•ืึธืœืงืŸ, ื•ื•ืึธืก ืžื™ื˜ืœ ืขืก ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขื•ื•ื™ื™ื ื˜ ืคึฟืึทืจ ื˜ืขืกื˜ื™ื ื’ ืคื•ืŸ ืงื™ื™ืŸ ื•ื•ืึธืœืงืŸ ืฉืคึผื™ื™ึทื–ืขืจ.

(ืื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ, ื˜ืจืึธืฅ ื–ื™ื™ืŸ ืžืึทืœื˜ื™ื™ืœื™ื ื’ื•ื•ืึทืœ ืื•ืŸ ืžื•ืœื˜ื™ืงืœืึธื•ื“, ืžื™ืจ ื ื•ืฆืŸ ื“ื–ืฉืึทื•ื•ืึทืกืงืจื™ืคึผื˜ ืื•ืŸ ืžืึธื˜ืฉืึท ืื•ืŸ ืคืึธืงื•ืก ืื•ื™ืฃ AWS. ืื™ืจ ืงืขื ืขืŸ ื ื•ืฆืŸ ืคึผื™ื˜ื”ืึธืŸ unittest, ื’ื™ื™ืŸ ืคึผืจื•ื‘ื™ืจืŸ ืคืจื™ื™ืžื•ื•ืขืจืง ืึธื“ืขืจ ืงื™ื™ืŸ ืื ื“ืขืจืข ืคึผืจื•ื‘ื™ืจืŸ ืคืจื™ื™ืžื•ื•ืขืจืง ืื™ืจ ื•ื•ื™. ืื•ืŸ, ืคื•ืŸ ืงื•ืจืก, Pulumi ืึทืจื‘ืขื˜ ื’ืจื•ื™ืก ืžื™ื˜ Azure, Google Cloud, Kubernetes.)

ื•ื•ื™ ืžื™ืจ ื”ืึธื‘ืŸ ื’ืขื–ืขืŸ, ืขืก ื–ืขื ืขืŸ ืขื˜ืœืขื›ืข ืกื™ื‘ื•ืช ื•ื•ืึธืก ืื™ืจ ื–ืืœ ื•ื•ืขืœืŸ ืฆื• ืคึผืจื•ื‘ื™ืจืŸ ื“ื™ื™ืŸ ื™ื ืคืจืึทืกื˜ืจืึทืงื˜ืฉืขืจ ืงืึธื“. ืื™ื™ื ืขืจ ืคื•ืŸ ื–ื™ื™ ืื™ื– ืงืึทื ื•ื•ืขื ืฉืึทื ืึทืœ ืึทืคึผืึทืจืึทื˜ ื˜ืขืกื˜ื™ื ื’. ื•ื•ื™ื™ึทืœ ื“ื™ื™ืŸ ืงืึธื“ ืงืขืŸ ื”ืึธื‘ืŸ ืคืึทื ื’ืงืฉืึทื ื– - ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืฆื• ืจืขื›ืขื ืขืŸ CIDR, ื“ื™ื ืึทืžื™ืงืึทืœืœื™ ืจืขื›ืขื ืขืŸ ื ืขืžืขืŸ, ื˜ืึทื’ืก, ืขื˜ืง. - ืื™ืจ ื•ื•ืขื˜ ืžื™ืกื˜ืึธืžืข ื•ื•ื™ืœืŸ ืฆื• ืคึผืจื•ื‘ื™ืจืŸ ื–ื™ื™. ื“ืึธืก ืื™ื– ื“ื™ ื–ืขืœื‘ืข ื•ื•ื™ ืฉืจื™ื™ื‘ืŸ ืจืขื’ื•ืœืขืจ ืึทืคึผืึทืจืึทื˜ ื˜ืขืกืฅ ืคึฟืึทืจ ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืื™ืŸ ื“ื™ื™ืŸ ื‘ืึทืœื™ื‘ืกื˜ืข ืคึผืจืึธื’ืจืึทืžืžื™ื ื’ ืฉืคึผืจืึทืš.
ืฆื• ื‘ืึทืงื•ืžืขืŸ ืึท ื‘ื™ืกืœ ืžืขืจ ืงืึธืžืคึผืœื™ืฆื™ืจื˜, ืื™ืจ ืงืขื ืขืŸ ืงืึธื ื˜ืจืึธืœื™ืจืŸ ื•ื•ื™ ื“ื™ื™ืŸ ืคึผืจืึธื’ืจืึทื ืึทืœืึทืงื™ื™ืฅ ืจืขืกื•ืจืกืŸ. ืฆื• ืื™ืœื•ืกื˜ืจื™ืจืŸ, ืœืึธืžื™ืจ ื™ืžืึทื“ื–ืฉืึทืŸ ืึทื– ืžื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืฉืึทืคึฟืŸ ืึท ืคึผืฉื•ื˜ EC2 ืกืขืจื•ื•ืขืจ ืื•ืŸ ืžื™ืจ ื•ื•ืขืœืŸ ื–ื™ื™ืŸ ื–ื™ื›ืขืจ ืคื•ืŸ ื“ื™ ืคืืœื’ืขื ื“ืข:

  • ื™ื ืกื˜ืึทื ืกื™ื– ื”ืึธื‘ืŸ ืึท ืงื•ื•ื™ื˜ืœ Name.
  • ื™ื ืกื˜ืึทื ืกื™ื– ื–ืึธืœ ื ื™ืฉื˜ ื ื•ืฆืŸ ื™ื ืœื™ื ืข ืฉืจื™ืคื˜ userData - ืžื™ืจ ืžื•ื–ืŸ ื ื•ืฆืŸ ืึท ืึทืžื™ (ื‘ื™ืœื“).
  • ืขืก ื–ืึธืœ ื–ื™ื™ืŸ ืงื™ื™ืŸ SSH ื™ืงืกืคึผืึธื•ื–ื“ ืฆื• ื“ื™ ืื™ื ื˜ืขืจื ืขื˜.

ื“ืขื ื‘ื™ื™ึทืฉืคึผื™ืœ ืื™ื– ื‘ืื–ื™ืจื˜ ืื•ื™ืฃ ืžื™ื™ืŸ ื‘ื™ื™ืฉืคึผื™ืœ aws-js-ื•ื•ืขื‘ืกืขืจื•ื•ืขืจ:

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 ื–ื™ื›ืขืจื”ื™ื™ื˜ ื’ืจื•ืคึผืข ืื•ืŸ ืึท ื‘ื™ื™ึทืฉืคึผื™ืœ. ืึธื‘ืขืจ, ืขืก ื–ืึธืœ ื–ื™ื™ืŸ ืื ื’ืขื•ื•ื™ื–ืŸ ืึทื– ื“ืึธ ืžื™ืจ ื‘ืจื™ื™ืงื™ื ื’ ืึทืœืข ื“ืจื™ื™ ื›ึผืœืœื™ื ืกื˜ื™ื™ื˜ื™ื“ ืื•ื™ื‘ืŸ. ื–ืืœ ืก ืฉืจื™ื™ึทื‘ืŸ ื˜ืขืกืฅ!

ืฉืจื™ื™ื‘ืŸ ื˜ืขืกืฅ

ื“ื™ ืึทืœื’ืขืžื™ื™ื ืข ืกื˜ืจื•ืงื˜ื•ืจ ืคื•ืŸ ืื•ื ื“ื–ืขืจ ื˜ืขืกืฅ ื•ื•ืขื˜ ืงื•ืงืŸ ื•ื•ื™ ืจืขื’ื•ืœืขืจ ืžืึธื˜ืฉืึท ื˜ืขืกืฅ:

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 ืึธื“ืขืจ ืฆื•ืจื™ืงืงื•ืžืขืŸ ืึท ืฆื•ื–ืึธื’.

ืึทืžืึธืœ ืžื™ืจ ื”ืึธื‘ืŸ ื‘ืึทืฉื˜ืขื˜ื™ืงื˜ ืึทืœืฅ, ืžื™ืจ ื”ืึธื‘ืŸ ืึทืงืกืขืก ืฆื• ื“ื™ ื™ื ืคึผื•ืฅ ื•ื•ื™ ืคึผืฉื•ื˜ ื“ื–ืฉืึทื•ื•ืึทืกืงืจื™ืคึผื˜ ื•ื•ืึทืœื•ืขืก. ืคืึทืจืžืึธื’ 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 ื•ื•ืึธืก ืื™ื– ื•ื•ืขืจื˜ ืฆื• ื‘ืึทืฆืึธืœืŸ ื•ืคืžืขืจืงื–ืึทืžืงื™ื™ื˜ ืฆื•.
ื˜ื™ืคึผื™ืงืึทืœืœื™, ืฆื• ืœื•ื™ืคืŸ 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. ื“ื™ ื‘ืึทืคึฟืขืœืŸ ืฉื•ืจื” ืคึฟืึทืจ ืคืœื™ืกื ื“ื™ืง ืžืึธื˜ืฉืึท ื˜ืขืกืฅ ื•ื•ืขื˜ ืงื•ืงืŸ ื•ื•ื™ ื“ืึธืก:

    $ 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)

    ืึทืœืฅ ืื™ื– ื’ืขื•ื•ืขืŸ ื’ื•ื˜... ื”ื•ืจ! โœ“โœ“โœ“

    ื“ืึธืก ืื™ื– ืึทืœืข ืคึฟืึทืจ ื”ื™ื™ึทื ื˜, ืึธื‘ืขืจ ืžื™ืจ ื•ื•ืขืœืŸ ืจืขื“ืŸ ื•ื•ืขื’ืŸ ื“ื™ืคึผืœื•ื™ืžืึทื ื˜ ื˜ืขืกื˜ื™ื ื’ ืื™ืŸ ื“ื™ ืจื’ืข ื˜ื™ื™ืœ ืคื•ืŸ ื“ื™ ืื™ื‘ืขืจื–ืขืฆื•ื ื’ ๐Ÿ˜‰

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’