UNPKG

@studion/infra-code-blocks

Version:
185 lines (184 loc) 6.89 kB
"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;