UNPKG

@studion/infra-code-blocks

Version:
172 lines (171 loc) 8.71 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Project = exports.MissingEcsCluster = void 0; const pulumi = require("@pulumi/pulumi"); const aws = require("@pulumi/aws"); const awsx = require("@pulumi/awsx"); const upstash = require("@upstash/pulumi"); const database_1 = require("./database"); const web_server_1 = require("./web-server"); const mongo_1 = require("./mongo"); const redis_1 = require("./redis"); const static_site_1 = require("./static-site"); const ec2_ssm_connect_1 = require("./ec2-ssm-connect"); const constants_1 = require("../constants"); const ecs_service_1 = require("./ecs-service"); const nuxt_ssr_1 = require("./nuxt-ssr"); class MissingEcsCluster extends Error { constructor() { super('Ecs Cluster does not exist'); this.name = this.constructor.name; } } exports.MissingEcsCluster = MissingEcsCluster; class Project extends pulumi.ComponentResource { constructor(name, args, opts = {}) { super('studion:Project', name, {}, opts); this.services = {}; this.name = name; this.vpc = this.createVpc(args.numberOfAvailabilityZones); this.createServices(args.services); if (args.enableSSMConnect) { this.ec2SSMConnect = new ec2_ssm_connect_1.Ec2SSMConnect(`${name}-ssm-connect`, { vpcId: this.vpc.vpcId, privateSubnetId: this.vpc.privateSubnetIds.apply(ids => ids[0]), vpcCidrBlock: this.vpc.vpc.cidrBlock, }); } this.registerOutputs(); } createVpc(numberOfAvailabilityZones = 2) { const vpc = new awsx.ec2.Vpc(`${this.name}-vpc`, { numberOfAvailabilityZones, enableDnsHostnames: true, enableDnsSupport: true, subnetSpecs: [ { type: awsx.ec2.SubnetType.Public, cidrMask: 24 }, { type: awsx.ec2.SubnetType.Private, cidrMask: 24 }, { type: awsx.ec2.SubnetType.Isolated, cidrMask: 24 }, ], tags: constants_1.commonTags, }, { parent: this }); return vpc; } createServices(services) { const hasRedisService = services.some(it => it.type === 'REDIS'); const shouldCreateEcsCluster = services.some(it => it.type === 'WEB_SERVER' || it.type === 'NUXT_SSR' || it.type === 'MONGO' || it.type === 'ECS_SERVICE') && !this.cluster; if (hasRedisService) this.createRedisPrerequisites(); if (shouldCreateEcsCluster) this.createEcsCluster(); services.forEach(it => { if (it.type === 'DATABASE') this.createDatabaseService(it); if (it.type === 'REDIS') this.createRedisService(it); if (it.type === 'STATIC_SITE') this.createStaticSiteService(it); if (it.type === 'WEB_SERVER') this.createWebServerService(it); if (it.type === 'NUXT_SSR') this.createNuxtSSRService(it); if (it.type === 'MONGO') this.createMongoService(it); if (it.type === 'ECS_SERVICE') this.createEcsService(it); }); } createRedisPrerequisites() { const upstashConfig = new pulumi.Config('upstash'); this.upstashProvider = new upstash.Provider('upstash', { email: upstashConfig.requireSecret('email'), apiKey: upstashConfig.requireSecret('apiKey'), }); } createEcsCluster() { const stack = pulumi.getStack(); this.cluster = new aws.ecs.Cluster(`${this.name}-cluster`, { name: `${this.name}-${stack}`, tags: constants_1.commonTags, }, { parent: this }); } createDatabaseService(options) { const { serviceName, type } = options, databaseOptions = __rest(options, ["serviceName", "type"]); const service = new database_1.Database(serviceName, Object.assign(Object.assign({}, databaseOptions), { vpcId: this.vpc.vpcId, isolatedSubnetIds: this.vpc.isolatedSubnetIds, vpcCidrBlock: this.vpc.vpc.cidrBlock }), { parent: this }); this.services[serviceName] = service; } createRedisService(options) { if (!this.upstashProvider) return; const { serviceName } = options, redisOptions = __rest(options, ["serviceName"]); const service = new redis_1.Redis(serviceName, redisOptions, { parent: this, provider: this.upstashProvider, }); this.services[options.serviceName] = service; } createStaticSiteService(options) { const { serviceName } = options, staticSiteOptions = __rest(options, ["serviceName"]); const service = new static_site_1.StaticSite(serviceName, staticSiteOptions, { parent: this, }); this.services[serviceName] = service; } createWebServerService(options) { if (!this.cluster) throw new MissingEcsCluster(); const { serviceName, environment, secrets } = options, ecsOptions = __rest(options, ["serviceName", "environment", "secrets"]); const parsedEnv = typeof environment === 'function' ? environment(this.services) : environment; const parsedSecrets = typeof secrets === 'function' ? secrets(this.services) : secrets; const service = new web_server_1.WebServer(serviceName, Object.assign(Object.assign({}, ecsOptions), { clusterId: this.cluster.id, clusterName: this.cluster.name, vpcId: this.vpc.vpcId, vpcCidrBlock: this.vpc.vpc.cidrBlock, publicSubnetIds: this.vpc.publicSubnetIds, environment: parsedEnv, secrets: parsedSecrets }), { parent: this }); this.services[options.serviceName] = service; } createNuxtSSRService(options) { if (!this.cluster) throw new MissingEcsCluster(); const { serviceName, environment, secrets } = options, ecsOptions = __rest(options, ["serviceName", "environment", "secrets"]); const parsedEnv = typeof environment === 'function' ? environment(this.services) : environment; const parsedSecrets = typeof secrets === 'function' ? secrets(this.services) : secrets; const service = new nuxt_ssr_1.NuxtSSR(serviceName, Object.assign(Object.assign({}, ecsOptions), { clusterId: this.cluster.id, clusterName: this.cluster.name, vpcId: this.vpc.vpcId, vpcCidrBlock: this.vpc.vpc.cidrBlock, publicSubnetIds: this.vpc.publicSubnetIds, environment: parsedEnv, secrets: parsedSecrets }), { parent: this }); this.services[options.serviceName] = service; } createMongoService(options) { if (!this.cluster) throw new MissingEcsCluster(); const { serviceName } = options, mongoOptions = __rest(options, ["serviceName"]); const service = new mongo_1.Mongo(serviceName, Object.assign(Object.assign({}, mongoOptions), { clusterId: this.cluster.id, clusterName: this.cluster.name, vpcId: this.vpc.vpcId, vpcCidrBlock: this.vpc.vpc.cidrBlock, privateSubnetIds: this.vpc.privateSubnetIds }), { parent: this }); this.services[options.serviceName] = service; } createEcsService(options) { if (!this.cluster) throw new MissingEcsCluster(); const { serviceName, environment, secrets } = options, ecsOptions = __rest(options, ["serviceName", "environment", "secrets"]); const parsedEnv = typeof environment === 'function' ? environment(this.services) : environment; const parsedSecrets = typeof secrets === 'function' ? secrets(this.services) : secrets; const service = new ecs_service_1.EcsService(serviceName, Object.assign(Object.assign({}, ecsOptions), { clusterId: this.cluster.id, clusterName: this.cluster.name, vpcId: this.vpc.vpcId, vpcCidrBlock: this.vpc.vpc.cidrBlock, subnetIds: ecsOptions.assignPublicIp ? this.vpc.publicSubnetIds : this.vpc.privateSubnetIds, environment: parsedEnv, secrets: parsedSecrets }), { parent: this }); this.services[options.serviceName] = service; } } exports.Project = Project;