@studion/infra-code-blocks
Version:
Studion common infra components
185 lines (184 loc) • 6.89 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebServer = void 0;
const pulumi = require("@pulumi/pulumi");
const aws = require("@pulumi/aws");
const constants_1 = require("../constants");
const acm_certificate_1 = require("./acm-certificate");
const ecs_service_1 = require("./ecs-service");
const defaults = {
healthCheckPath: '/healthcheck',
};
class WebServer extends pulumi.ComponentResource {
constructor(name, args, opts = {}) {
super('studion:WebServer', name, args, opts);
const { vpcId, domain, hostedZoneId } = args;
const hasCustomDomain = !!domain && !!hostedZoneId;
if (domain && !hostedZoneId) {
throw new Error('WebServer:hostedZoneId must be provided when the domain is specified');
}
this.name = name;
if (hasCustomDomain) {
this.certificate = this.createTlsCertificate({ domain, hostedZoneId });
}
const { lb, lbTargetGroup, lbHttpListener, lbTlsListener, lbSecurityGroup, } = this.createLoadBalancer(args);
this.lb = lb;
this.lbTargetGroup = lbTargetGroup;
this.lbHttpListener = lbHttpListener;
this.lbTlsListener = lbTlsListener;
this.lbSecurityGroup = lbSecurityGroup;
this.serviceSecurityGroup = this.createSecurityGroup(vpcId);
this.service = this.createEcsService(args);
if (hasCustomDomain) {
this.createDnsRecord({ domain, hostedZoneId });
}
this.registerOutputs();
}
createTlsCertificate({ domain, hostedZoneId, }) {
const certificate = new acm_certificate_1.AcmCertificate(`${domain}-acm-certificate`, {
domain,
hostedZoneId,
}, { parent: this });
return certificate;
}
createLoadBalancer({ vpcId, publicSubnetIds, port, healthCheckPath, }) {
const lbSecurityGroup = new aws.ec2.SecurityGroup(`${this.name}-lb-security-group`, {
vpcId,
ingress: [
{
protocol: 'tcp',
fromPort: 80,
toPort: 80,
cidrBlocks: ['0.0.0.0/0'],
},
{
protocol: 'tcp',
fromPort: 443,
toPort: 443,
cidrBlocks: ['0.0.0.0/0'],
},
],
egress: [
{
fromPort: 0,
toPort: 0,
protocol: '-1',
cidrBlocks: ['0.0.0.0/0'],
},
],
tags: constants_1.commonTags,
}, { parent: this });
const lb = new aws.lb.LoadBalancer(`${this.name}-lb`, {
namePrefix: 'lb-',
loadBalancerType: 'application',
subnets: publicSubnetIds,
securityGroups: [lbSecurityGroup.id],
internal: false,
ipAddressType: 'ipv4',
tags: Object.assign(Object.assign({}, constants_1.commonTags), { Name: `${this.name}-lb` }),
}, { parent: this });
const lbTargetGroup = new aws.lb.TargetGroup(`${this.name}-lb-tg`, {
namePrefix: 'lb-tg-',
port,
protocol: 'HTTP',
targetType: 'ip',
vpcId,
healthCheck: {
healthyThreshold: 3,
unhealthyThreshold: 2,
interval: 60,
timeout: 5,
path: healthCheckPath || defaults.healthCheckPath,
},
tags: Object.assign(Object.assign({}, constants_1.commonTags), { Name: `${this.name}-lb-target-group` }),
}, { parent: this, dependsOn: [this.lb] });
const defaultAction = this.certificate
? {
type: 'redirect',
redirect: {
port: '443',
protocol: 'HTTPS',
statusCode: 'HTTP_301',
},
}
: {
type: 'forward',
targetGroupArn: lbTargetGroup.arn,
};
const lbHttpListener = new aws.lb.Listener(`${this.name}-lb-listener-80`, {
loadBalancerArn: lb.arn,
port: 80,
defaultActions: [defaultAction],
tags: constants_1.commonTags,
}, { parent: this });
let lbTlsListener = undefined;
if (this.certificate) {
lbTlsListener = new aws.lb.Listener(`${this.name}-lb-listener-443`, {
loadBalancerArn: lb.arn,
port: 443,
protocol: 'HTTPS',
sslPolicy: 'ELBSecurityPolicy-2016-08',
certificateArn: this.certificate.certificate.arn,
defaultActions: [
{
type: 'forward',
targetGroupArn: lbTargetGroup.arn,
},
],
tags: constants_1.commonTags,
}, { parent: this, dependsOn: [this.certificate] });
}
return {
lb,
lbTargetGroup,
lbHttpListener,
lbTlsListener,
lbSecurityGroup,
};
}
createSecurityGroup(vpcId) {
const securityGroup = new aws.ec2.SecurityGroup(`${this.name}-security-group`, {
vpcId,
ingress: [
{
fromPort: 0,
toPort: 0,
protocol: '-1',
securityGroups: [this.lbSecurityGroup.id],
},
],
egress: [
{
fromPort: 0,
toPort: 0,
protocol: '-1',
cidrBlocks: ['0.0.0.0/0'],
},
],
tags: constants_1.commonTags,
}, { parent: this });
return securityGroup;
}
createEcsService(args) {
const service = new ecs_service_1.EcsService(this.name, Object.assign(Object.assign({}, args), { enableServiceAutoDiscovery: false, lbTargetGroupArn: this.lbTargetGroup.arn, assignPublicIp: true, subnetIds: args.publicSubnetIds, securityGroup: this.serviceSecurityGroup }), {
parent: this,
dependsOn: [this.lb, this.lbTargetGroup],
});
return service;
}
createDnsRecord({ domain, hostedZoneId, }) {
const albAliasRecord = new aws.route53.Record(`${this.name}-route53-record`, {
type: 'A',
name: domain,
zoneId: hostedZoneId,
aliases: [
{
name: this.lb.dnsName,
zoneId: this.lb.zoneId,
evaluateTargetHealth: true,
},
],
}, { parent: this });
}
}
exports.WebServer = WebServer;