ืฆืืจืืื ืืืืื ืืืจืื. ืืงืจืืช ืชืืืืช ืืจืืื ืืืฉื ืืงืฆื
ืฉืืืืฉ ื-Pulumi ืืฉืคืืช ืชืื ืืช ืืืืจืืช ืืืืืืช ืืงืื ืชืฉืชืืช (Infrastructure as Code) ืืกืคืง ืืชืจืื ืืช ืจืืื: ืืืื ืืช ืฉื ืืืืื ืืืืช ืืืืข, ืืืืื ื-boilerplate ืืงืื ืืืืฆืขืืช ืืคืฉืื, ืืืื ืืืืืจืื ืืฆืืืช ืฉืื, ืืืื IDEs ื-linters. ืื ืืื ืื ืืกืช ืืชืืื ื ืืืื ืื ืจืง ืืืคืืื ืืืชื ื ืืืืชืจ ืคืจืืืืงืืืืืื, ืืื ืื ืืฉืคืจืื ืืช ืืืืืช ืืงืื ืฉืื ื. ืืื, ืื ืื ืืืขื ืฉืืฉืืืืฉ ืืฉืคืืช ืชืื ืืช ืืืืจืืช ืืืืืืช ืืืคืฉืจ ืื ื ืืืฆืื ืคืจืงืืืงื ืืฉืืื ื ืืกืคืช ืฉื ืคืืชืื ืชืืื ื - ืืืืงืืช.
ืืืืืจ ืื, ื ืจืื ืืืฆื Pulumi ืขืืืจืช ืื ื ืืืืืง ืืช ืืชืฉืชืืช ืฉืื ื ืืงืื.
ืืื ืืืืืง ืชืฉืชืืช?
ืืคื ื ืฉื ืื ืก ืืคืจืืื, ืืืื ืืฉืืื ืืช ืืฉืืื: "ืืื ืืืื ืืืืืง ืชืฉืชืืช?" ืืฉ ืืื ืกืืืืช ืจืืืช ืืื ื ืืื ืืื:
- ืืืืงืช ืืืืืืช ืฉื ืคืื ืงืฆืืืช ืืืืืืช ืื ืงืืขืื ืืืืืืืงื ืฉื ืืชืืื ืืช ืฉืื
- ืืืืช ืืช ืืืฆื ืืจืฆืื ืฉื ืืชืฉืชืืช ืืื ืืืืืฆืื ืืกืืืืื.
- ืืืืื ืฉืืืืืช ื ืคืืฆืืช, ืืืื ืืืกืจ ืืฆืคื ื ืฉื ืืื ืืืกืื ืื ืืืฉื ืื ืืืื ืช, ืคืชืืื ืืืืื ืืจื ื ืืืืื ืืช ืืืจืืืืืืืช.
- ืืืืงืช ืืืฉืื ืืกืคืงืช ืชืฉืชืืช.
- ืืืฆืืข ืืืืงืช ืืื ืจืืฆื ืฉื ืืืืืงื ืฉื ืืคืืืงืฆืื ืืคืืขืืช ืืชืื ืืชืฉืชืืช ื"ืืชืืื ืชืช" ืฉืื ืืื ืืืืืง ืคืื ืงืฆืืื ืืืืช ืืืืจ ืืงืฆืื.
- ืืคื ืฉืื ื ืืืืืื ืืจืืืช, ืืฉ ืืืืื ืจืื ืฉื ืืคืฉืจืืืืช ืืืืืงืช ืชืฉืชืืช. ื-Polumi ืืฉ ืื ืื ืื ืื ืืืืืงื ืืื ื ืงืืื ืืกืคืงืืจืื ืืื. ืืืื ื ืชืืื ืื ืจืื ืืื ืื ืขืืื.
ืืืืงืช ืืืืื
ืชืืื ืืืช Pulumi ืืชืืืืช ืืฉืคืืช ืชืื ืืช ืืืืจืืช ืืืืืืช ืืื JavaScript, Python, TypeScript ืื Go. ืืื, ืืืื ืืืื ืฉื ืฉืคืืช ืืื, ืืจืืืช ืืืืื ืืืกืคืจืืืช ืฉืืื, ืืจืืืช ืืกืืจืืช ืืืืงื, ืขืืื ืืจืฉืืชื. Pulumi ืืื ืจื ืขื ื, ืื ืฉืืืืจ ืฉื ืืชื ืืืฉืชืืฉ ืื ืืืืืงืืช ืืื ืกืคืง ืขื ื.
(ืืืืืจ ืื, ืืืจืืช ืืืืชื ืจื ืืฉืื ื ืืจื ืขื ื, ืื ื ืืฉืชืืฉืื ื-JavaScript ืื-Mocha ืืืชืืงืืื ื-AWS. ืืชื ืืืื ืืืฉืชืืฉ ื-Python unittest
, Go test framework, ืื ืื ืืกืืจืช ืืืืงื ืืืจืช ืฉืชืจืฆื. ืืืืืื, Pulumi ืขืืื ืืฆืืื ืขื Azure, Google Cloud, Kubernetes.)
ืืคื ืฉืจืืื ื, ืืฉ ืืื ืกืืืืช ืฉืืืืื ืืืื ืชืจืฆื ืืืืืง ืืช ืงืื ืืชืฉืชืืช ืฉืื. ืืื ืืื ืืื ืืืืงืืช ืืืืืืช ืงืื ืื ืฆืืื ืืืืช. ืื ืืงืื ืฉืื ืขืฉืืืืช ืืืืืช ืคืื ืงืฆืืืช - ืืืฉื, ืืืืฉืื CIDR, ืืืฉืื ืืื ืื ืฉื ืฉืืืช, ืชืืื ืืื'. - ืื ืจืื ืฉืชืจืฆื ืืืืืง ืืืชื. ืื ืืื ืืืชืืืช ืืืื ื ืืืืื ืจืืืืื ืขืืืจ ืืืฉืืืื ืืฉืคืช ืืชืื ืืช ืืืืขืืคืช ืขืืื.
ืืื ืืืืืช ืงืฆืช ืืืชืจ ืืกืืื, ืืชื ืืืื ืืืืืง ืืื ืืชืืื ืืช ืฉืื ืืงืฆื ืืฉืืืื. ืืฉื ืืืืฉื, ืืืื ื ืืืืื ืฉืขืืื ื ืืืฆืืจ ืฉืจืช EC2 ืคืฉืื ืืื ื ืจืืฆืื ืืืืืช ืืืืืื ืืืืจืื ืืืืื:
- ืืืืคืขืื ืืฉ ืชื
Name
. - ืืืคืขืื ืื ืฆืจืืืื ืืืฉืชืืฉ ืืกืงืจืืคื ืืืืืข
userData
- ืขืืื ื ืืืฉืชืืฉ ื-AMI (ืชืืื ื). - ืื ืืืืจ ืืืืืช SSH ืืฉืืฃ ืืืื ืืจื ื.
ืืืืื ืื ืืืืกืกืช ืขื
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
ืื ืืืืจืช ืืืืื.
ืืืืจ ืฉืืืืจื ื ืืื, ืชืืื ืื ื ืืืฉื ืืื ืืกืืช ืืขืจืืื ืคืฉืืืื ืฉื 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 ืฉืืืื ืืฉืื ืืืื ืื.
ืืืจื ืืื, ืืื ืืืคืขืื ืชืืื ืืืช ืฉื Pulumi, ื ืขืฉื ืฉืืืืฉ ื-pulimi CLI (ืืืฉืง ืงื ืคืงืืื), ืฉืืืืืจ ืืช ืืื ืืจืืฆื ืฉื ืืฉืคื, ืฉืืื ืืืฉืงื ืฉื ืื ืืข ื-Pulumi ืื ืฉื ืืชื ืืืงืืื ืคืขืืืืช ืขื ืืฉืืืื ืืืืืื ืืืชื ืืชืืื ืืช ืืื'. ืขื ืืืช, ืืฉ ืืขืื ืืืช. ืืืฉืจ ืคืืขื ืชืืช ืฉืืืื ืฉื โโืืกืืจืช ืืืืืงื ืฉืื, ืื ืชืืื ืชืงืฉืืจืช ืืื ื-CLI ืืื ืืข Pulumi.
ืืื ืืขืงืืฃ ืืช ืืืขืื ืืื, ืื ืื ื ืจืง ืฆืจืืืื ืืฆืืื ืืช ืืืืจืื ืืืืื:
- ืฉื ืืคืจืืืงื, ืืืืื ืืืฉืชื ื ืืกืืืื
PULUMI_NODEJS_PROJECT
(ืื, ืืืืคื ืืืื ืืืชืจ,PULUMI__PROJECT ะดะปั ะดััะณะธั ัะทัะบะพะฒ).
ืฉื ืืืืกื ืืช ืฉืฆืืื ืืืฉืชื ื ืืกืืืืPULUMI_NODEJS_STACK
(ืื, ืืืืคื ืืืื ืืืชืจ,PULUMI__ STACK).
ืืฉืชื ื ืชืฆืืจืช ืืืืกื ืืช ืฉืื. ื ืืชื ืืืฉืื ืืืชื ืืืืฆืขืืช ืืฉืชื ื ืกืืืืPULUMI_CONFIG
ืืืคืืจืื ืฉืืื ืืื ืืคืช JSON ืขื ืฆืืื ืืคืชื/ืขืจื.ืืชืืื ืืช ืชืืฆืื ืืืืจืืช ืืืฆืืืขืืช ืขื ืื ืฉืืืืืืจ ื-CLI/ืื ืืข ืืื ื ืืืื ืืืืื ืืืืฆืืข. ืื ืืฉืื ืื ืืชืืื ืืช ืฉืื ืื ืชืคืจืืก ืฉืื ืืืจ ืืื ืขืฉืื ืืืคืชืืข ืื ืื ืื ืื ืฉืืชืืืื ืช ืืขืฉืืช! ืืื ืืืืจ ืืคืืืืื ืฉืื ืืืืืง ืื ืฉืืชื ืฆืจืื, ืืชื ืืืื ืืืชืงืื
PULUMI_TEST_MODE
ะฒtrue
.ืชืืจ ืืขืฆืื ืฉืื ืื ื ืฆืจืืืื ืืฆืืื ืืช ืฉื ืืคืจืืืงื ื
my-ws
, ืฉื ืืืกื ืืชdev
, ืืืืืจ AWSus-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