αα½ααααΈαα·ααααααααα·α αα
αααα»αααΆαααααΉααα»αααααΆαα
αΆααααααΎαααααα αΌαααααΈαα½ααα
αααα»αα’ααααΆ
ααΆαααααΎααααΆαα Pulumi αα·αααΆααΆααααααααααα·ααΈαααααΆααααααααααΌαα
αααααΆααααΌαα αααααΆαα
ααΆαααααααα (Infrastructure as Code) αααααααΌαα’αααααααααααααΆα
αααΎαα ααΆαα’αΆα
ααααΆαααααααΆα αα·αα
ααααααΉα ααΆααα»αααααΆαα boilerplate αα
αααα»αααΌαααΆαααα abstraction α§αααααααααααΆαααΉααααα»αααααα’ααα ααΌα
ααΆ IDEs αα·α lintersα α§ααααααα·αααααααααΌα αααααααΆααα’ααααααα·αααααΉαααααααΎα±ααααΎαααΆααααααΆαααα·αααΆαααα»ααααααα ααα»αααααααααΆααααααΎα’αααα»αααΆαααααΌαααααααΎαααΆαααααααααΎαα‘αΎααααααα ααΌα
αααα ααΆααααΆααααααΆααΏαααααααΆαααααΆαααααΎααααΆααααΆααΆααααααααααα·ααΈαααααΆααααααααααΌαα
α’αα»ααααΆαα±ααααΎαααααΆαααΆαα’αα»ααααααΆαα’αα·αααααααααααα·ααΈααααΆαααα½αααα - ααΆαααααΎααααα.
αα αααα»αα’αααααααα ααΎαααΉααα·αα·αααααΎαααΈααααααα Pulumi αα½αααΎαααΆαααααα αααααΆαα ααΆααααααααααΌα ααΌαααααααΎαα
α ααα»α’αααΈααααΌαααΆαααααα αααααΆαα ααΆαααααααα?
αα»αβααΉαβαα·ααΆαβαααα’α·α ααΆβαα½αβαα½αβαααα½αβααΆ "α ααα»α’αααΈβααΆαβααΆβααΆαααααβα αααααΆαα ααΆααααααααβααΆααα’αα?" ααΆαα ααα»ααααΆα αααΎααααααΆααααΏαααα α αΎααααααΊααΆαα½αα ααα½ααααα½αααα
- ααΆαααααΎαααααα―αααΆαααα»αααΆαααΈαα½αα α¬ααααααααααααα·ααααΆαααααα·ααΈααααα’αααα
- αααααααααΆααααααΆαααΆααααα ααααΆαααα αααααΆαα ααΆαααααααααααααΆααααΉαα§αααααααΆααααΆααα
- ααΆαααααΎαααα α»αααΌαα ααΌα ααΆαααααααΆαα’αα·αααααΈααα»ααααα»α α¬αα·αααΆαααΆαααΆαααΆα ααΆαα αΌαααααΎααΈα’ααΈαααΊαα·ααα αααΆαααΈααα·αααα·αα
- αα·αα·αααααΆαα’αα»ααααααΆααααααα αααααΆαα ααΆααααααααα
- α’αα»ααααααΆαααΆααααααααααααΎαααΆααααααααα·ααααΆαααααα·ααΈααααααα»αααααΎαααΆααα αααα»αα αααααΆαα ααΆαααααααα "αααααα·ααΈ" ααααα’ααα ααΎααααΈαα·αα·αααααΎααα»αααΆααααααΆααααΈααΆααααααα
- ααΌα αααααΎαα’αΆα ααΎαααΆααααααΎαααΆα αααΎαααααΆαααααΎαααααα αααααΆαα ααΆααααααααα Polumi ααΆαααααααΆααααααΆααααΆαααααΎααααααα αααααα ααα»α αα ααΎαα·ααΆααααααα αααα αΆααααααΎα α αΎαααΎαααΈαααααααααΆααααΎαααΆαα
ααΆαααααΎαααααα―αααΆ
αααααα·ααΈ Pulumi ααααΌαααΆααααααααΆααΆααΆααααααααααα·ααΈαααααΆααααααααααΌαα ααΌα ααΆ JavaScript, Python, TypeScript α¬ Go α ααΌα ααααα αΎα ααΆαααααααααααααΆααΆααΆααααα αα½αααΆααα§ααααα αα·ααααααΆααααααααα½ααα αα½αααΆαααααααααααααΆααααα ααΆααααααΆαααα½αααα Pulumi ααΊααΆαα α»ααα αααααΆααααααΆααΆα’αΆα ααααΌαααΆαααααΎαααααΆααααΆαααααΎαααααααΈα’ααααααααααααΆαααααΆαα½αα
(αα
αααα»αα’αααααααα αααααΈααΆααΆααα α»ααΆααΆ αα·ααα α»αααααααα ααΎαααααΎ JavaScript αα·α Mocha α αΎααααααααΎ AWS α α’αααα’αΆα
ααααΎ Python unittest
α
αΌααα
ααΆαααααααααααααΆααααα α¬αααααααααααΆααααααααααααααααα’αααα
αΌαα
α·αααα α αΎαααΆααΆααα·αααΆαα 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 αα·αα§ααΆα ααααα½αα αααααΆαααΆαααΆααααααα½ααααααααΆααααΆαα ααΈαααααΎααααα»αααααΆαα αααΆααααΆααααΈαααααΆαα ααααΆαααΎα αααααΆαααααααααα!
ααΆαααααΎαααααααααα
αα ααΆααααααααααΌαα ααααΆαααααΎαααααααααααΎαααΉαααΎααα ααΌα ααΆααΆαααααΎααααα 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
ααΎααααΈαααααα½αααΆα - ααΆα
α»αααααα αααααΆααααααααΆαααααααααΌαααΆαααααΆαααα’ααααΆα ααΎαααααΌαααααΎαα»αααΆαα α
αααα‘αααααα·α async αααααΆαααααΆαααααα 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 ααΆαααααΆα’αααΈαααα’αααααααΌαααΆα α’αααα’αΆα ααα‘αΎαααΆαα
PULUMI_TEST_MODE
Π²true
.αααααααΆααΎαααααΌααααααΆααααααααααααααα αααα»α
my-ws
, ααααααααdev
αα·αααααα AWSus-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)
α’αααΈαααααΎαααΆαααα’... α ααΊ! βββ
αααα αΎαααΆααΆααα’αααααααΆααααααααα ααα»ααααααΎαααΉααα·ααΆαα’αααΈααΆαααααΎαααααααΆαααααααΆααα αααα»ααααααααΈααΈαααααΆααααααα π
ααααα: www.habr.com