UNPKG

@studion/infra-code-blocks

Version:
224 lines (223 loc) 8.65 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebServer = void 0; const pulumi = require("@pulumi/pulumi"); const aws = require("@pulumi/aws"); const common_tags_1 = require("../../shared/common-tags"); const acm_certificate_1 = require("../acm-certificate"); const ecs_service_1 = require("../ecs-service"); const load_balancer_1 = require("./load-balancer"); class WebServer extends pulumi.ComponentResource { name; container; ecsConfig; service; serviceSecurityGroup; lb; initContainers; sidecarContainers; volumes; acmCertificate; dnsRecords; constructor(name, args, opts = {}) { super('studion:web-server:WebServer', name, {}, { ...opts, aliases: [...(opts.aliases || []), { type: 'studion:WebServer' }], }); const { vpc, domain, hostedZoneId, certificate } = args; const hasCustomDomain = !!domain || !!certificate; if (hasCustomDomain && !hostedZoneId) { throw new Error('Provide `hostedZoneId` alongside `domain` and/or `certificate`.'); } if (domain && hostedZoneId && !certificate) { this.acmCertificate = this.createTlsCertificate({ domain, hostedZoneId }); } this.name = name; this.lb = new load_balancer_1.WebServerLoadBalancer(`${this.name}-lb`, { vpc, port: args.port, certificate: certificate ?? this.acmCertificate?.certificate, healthCheckPath: args.healthCheckPath, healthCheckConfig: args.healthCheckConfig, loadBalancingAlgorithmType: args.loadBalancingAlgorithmType, }, { parent: this, ...(this.acmCertificate ? { dependsOn: [this.acmCertificate.certificateValidation] } : undefined), }); this.serviceSecurityGroup = this.createSecurityGroup(vpc); this.initContainers = this.getInitContainers(args); this.sidecarContainers = this.getSidecarContainers(args); this.container = this.createWebServerContainer(args); this.ecsConfig = this.createEcsConfig(args); this.volumes = this.getVolumes(args); this.service = this.createEcsService(this.container, this.lb, this.ecsConfig, this.volumes, this.initContainers, this.sidecarContainers); if (hasCustomDomain && hostedZoneId) { this.dnsRecords = this.createDnsRecords(certificate ?? this.acmCertificate.certificate, hostedZoneId, domain); } this.registerOutputs(); } getVolumes(args) { return pulumi .all([pulumi.output(args.volumes), args.otelCollector]) .apply(([passedVolumes, otelCollector]) => { const volumes = []; if (passedVolumes) volumes.push(...passedVolumes); if (otelCollector) volumes.push({ name: otelCollector.configVolume }); return volumes; }); } getInitContainers(args) { return pulumi .all([pulumi.output(args.initContainers), args.otelCollector]) .apply(([passedInits, otelCollector]) => { const containers = []; if (passedInits) containers.push(...passedInits); if (otelCollector) containers.push(otelCollector.configContainer); return containers.map(container => ({ ...container, essential: false, })); }); } getSidecarContainers(args) { return pulumi .all([pulumi.output(args.sidecarContainers), args.otelCollector]) .apply(([passedSidecars, otelCollector]) => { const containers = []; if (passedSidecars) containers.push(...passedSidecars); if (otelCollector) containers.push(otelCollector.container); return containers.map(container => ({ ...container, essential: true })); }); } getTaskRoleInlinePolicies(args) { return pulumi .all([pulumi.output(args.taskRoleInlinePolicies), args.otelCollector]) .apply(([passedTaskRoleInlinePolicies, otelCollector]) => { const inlinePolicies = []; if (passedTaskRoleInlinePolicies) inlinePolicies.push(...passedTaskRoleInlinePolicies); if (otelCollector && otelCollector.taskRoleInlinePolicies) { inlinePolicies.push(...otelCollector.taskRoleInlinePolicies); } return inlinePolicies; }); } createEcsConfig(args) { return { vpc: args.vpc, cluster: args.cluster, name: args.name, deploymentController: args.deploymentController, desiredCount: args.desiredCount, autoscaling: args.autoscaling, family: args.family, size: args.size, logGroupNamePrefix: args.logGroupNamePrefix, taskExecutionRoleInlinePolicies: args.taskExecutionRoleInlinePolicies, taskRoleInlinePolicies: this.getTaskRoleInlinePolicies(args), tags: args.tags, }; } createWebServerContainer(args) { return { image: args.image, mountPoints: args.mountPoints, environment: args.environment, secrets: args.secrets, port: args.port, }; } createTlsCertificate({ domain, hostedZoneId, }) { return new acm_certificate_1.AcmCertificate(`${domain}-acm-certificate`, { domain, hostedZoneId, }, { parent: this }); } createSecurityGroup(vpc) { const vpcId = pulumi.output(vpc).vpcId; return new aws.ec2.SecurityGroup(`${this.name}-security-group`, { vpcId, ingress: [ { fromPort: 0, toPort: 0, protocol: '-1', securityGroups: [this.lb.securityGroup.id], }, ], egress: [ { fromPort: 0, toPort: 0, protocol: '-1', cidrBlocks: ['0.0.0.0/0'], }, ], tags: common_tags_1.commonTags, }, { parent: this }); } createEcsService(webServerContainer, lb, ecsConfig, volumes, initContainers, sidecarContainers) { return pulumi .all([ initContainers || pulumi.output([]), sidecarContainers || pulumi.output([]), ]) .apply(([inits, sidecars]) => { return new ecs_service_1.EcsService(`${this.name}-ecs`, { ...ecsConfig, volumes, containers: [ { ...webServerContainer, name: this.name, portMappings: [ ecs_service_1.EcsService.createTcpPortMapping(webServerContainer.port), ], essential: true, }, ...inits, ...sidecars, ], enableServiceAutoDiscovery: false, loadBalancers: [ { containerName: this.name, containerPort: webServerContainer.port, targetGroupArn: lb.targetGroup.arn, }, ], assignPublicIp: true, securityGroup: this.serviceSecurityGroup, }, { parent: this, dependsOn: [lb, lb.targetGroup], }); }); } createDnsRecords(certificate, hostedZoneId, domain) { const certOutput = pulumi.output(certificate); return pulumi .all([domain, certOutput.domainName, certOutput.subjectAlternativeNames]) .apply(([domain, certDomain, certSans = []]) => (domain ? [domain] : [...new Set([certDomain, ...certSans])]).map((alias, index) => new aws.route53.Record(`${this.name}-dns-a-record-${index}`, { type: 'A', name: alias, zoneId: hostedZoneId, aliases: [ { name: this.lb.lb.dnsName, zoneId: this.lb.lb.zoneId, evaluateTargetHealth: true, }, ], }, { parent: this }))); } } exports.WebServer = WebServer;