@studion/infra-code-blocks
Version:
Studion common infra components
172 lines (171 loc) • 8.71 kB
JavaScript
"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;