@studion/infra-code-blocks 0.1.9 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,277 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NuxtSSR = void 0;
4
+ const pulumi = require("@pulumi/pulumi");
5
+ const aws = require("@pulumi/aws");
6
+ const random = require("@pulumi/random");
7
+ const constants_1 = require("../constants");
8
+ const acm_certificate_1 = require("./acm-certificate");
9
+ const ecs_service_1 = require("./ecs-service");
10
+ const defaults = {
11
+ healthCheckPath: '/',
12
+ };
13
+ class NuxtSSR extends pulumi.ComponentResource {
14
+ constructor(name, args, opts = {}) {
15
+ super('studion:NuxtSSR', name, args, opts);
16
+ const { vpcId, domain, hostedZoneId, tags } = args;
17
+ const hasCustomDomain = domain && hostedZoneId;
18
+ if (domain && !hostedZoneId) {
19
+ throw new Error('NuxtSSR:hostedZoneId must be provided when the domain is specified');
20
+ }
21
+ this.name = name;
22
+ if (hasCustomDomain) {
23
+ this.certificate = this.createTlsCertificate({ domain, hostedZoneId });
24
+ }
25
+ this.customCFHeader = this.createCustomCFHeader();
26
+ const { lb, lbTargetGroup, lbHttpListener, lbSecurityGroup } = this.createLoadBalancer(args);
27
+ this.lb = lb;
28
+ this.lbTargetGroup = lbTargetGroup;
29
+ this.lbHttpListener = lbHttpListener;
30
+ this.lbSecurityGroup = lbSecurityGroup;
31
+ this.serviceSecurityGroup = this.createSecurityGroup(vpcId);
32
+ this.service = this.createEcsService(args);
33
+ this.cloudfront = this.createCloudfrontDistribution({ domain, tags });
34
+ if (hasCustomDomain) {
35
+ this.createDnsRecord({ domain, hostedZoneId });
36
+ }
37
+ this.registerOutputs();
38
+ }
39
+ createTlsCertificate({ domain, hostedZoneId, }) {
40
+ const certificate = new acm_certificate_1.AcmCertificate(`${domain}-acm-certificate`, {
41
+ domain,
42
+ hostedZoneId,
43
+ }, { parent: this });
44
+ return certificate;
45
+ }
46
+ createCustomCFHeader() {
47
+ const headerNameOpts = {
48
+ length: 4,
49
+ special: false,
50
+ numeric: false,
51
+ lower: false,
52
+ upper: true,
53
+ };
54
+ const headerNameSegment1 = new random.RandomString(`${this.name}-cf-header-name-segment1`, headerNameOpts, { parent: this });
55
+ const headerNameSegment2 = new random.RandomString(`${this.name}-cf-header-name-segment2`, headerNameOpts, { parent: this });
56
+ const headerValue = new random.RandomString(`${this.name}-cf-header-value`, {
57
+ length: 36,
58
+ special: false,
59
+ numeric: true,
60
+ lower: true,
61
+ upper: true,
62
+ }, { parent: this });
63
+ const headerName = pulumi
64
+ .all([headerNameSegment1.result, headerNameSegment2.result])
65
+ .apply(([segment1, segment2]) => {
66
+ return `X-${segment1}-${segment2}`;
67
+ });
68
+ return { name: headerName, value: headerValue.result };
69
+ }
70
+ createLoadBalancer({ vpcId, publicSubnetIds, port, healthCheckPath, }) {
71
+ const lbSecurityGroup = new aws.ec2.SecurityGroup(`${this.name}-lb-security-group`, {
72
+ vpcId,
73
+ ingress: [
74
+ {
75
+ protocol: 'tcp',
76
+ fromPort: 80,
77
+ toPort: 80,
78
+ cidrBlocks: ['0.0.0.0/0'],
79
+ },
80
+ ],
81
+ egress: [
82
+ {
83
+ fromPort: 0,
84
+ toPort: 0,
85
+ protocol: '-1',
86
+ cidrBlocks: ['0.0.0.0/0'],
87
+ },
88
+ ],
89
+ tags: constants_1.commonTags,
90
+ }, { parent: this });
91
+ const lb = new aws.lb.LoadBalancer(`${this.name}-lb`, {
92
+ namePrefix: 'lb-',
93
+ loadBalancerType: 'application',
94
+ subnets: publicSubnetIds,
95
+ securityGroups: [lbSecurityGroup.id],
96
+ internal: false,
97
+ ipAddressType: 'ipv4',
98
+ tags: Object.assign(Object.assign({}, constants_1.commonTags), { Name: `${this.name}-lb` }),
99
+ }, { parent: this });
100
+ const lbTargetGroup = new aws.lb.TargetGroup(`${this.name}-lb-tg`, {
101
+ namePrefix: 'lb-tg-',
102
+ port,
103
+ protocol: 'HTTP',
104
+ targetType: 'ip',
105
+ vpcId,
106
+ healthCheck: {
107
+ healthyThreshold: 3,
108
+ unhealthyThreshold: 2,
109
+ interval: 60,
110
+ timeout: 5,
111
+ path: healthCheckPath || defaults.healthCheckPath,
112
+ },
113
+ tags: Object.assign(Object.assign({}, constants_1.commonTags), { Name: `${this.name}-lb-target-group` }),
114
+ }, { parent: this, dependsOn: [this.lb] });
115
+ const lbHttpListener = new aws.lb.Listener(`${this.name}-lb-listener-80`, {
116
+ loadBalancerArn: lb.arn,
117
+ port: 80,
118
+ defaultActions: [
119
+ {
120
+ type: 'fixed-response',
121
+ fixedResponse: {
122
+ statusCode: '403',
123
+ messageBody: 'Not Allowed',
124
+ contentType: 'text/plain',
125
+ },
126
+ },
127
+ ],
128
+ tags: constants_1.commonTags,
129
+ }, { parent: this });
130
+ const lbHttpListenerRule = new aws.lb.ListenerRule(`${this.name}-lb-listener-rule`, {
131
+ listenerArn: lbHttpListener.arn,
132
+ priority: 1,
133
+ actions: [
134
+ {
135
+ type: 'forward',
136
+ targetGroupArn: lbTargetGroup.arn,
137
+ },
138
+ ],
139
+ conditions: [
140
+ {
141
+ httpHeader: {
142
+ httpHeaderName: this.customCFHeader.name,
143
+ values: [this.customCFHeader.value],
144
+ },
145
+ },
146
+ ],
147
+ }, { parent: this });
148
+ return {
149
+ lb,
150
+ lbTargetGroup,
151
+ lbHttpListener,
152
+ lbSecurityGroup,
153
+ };
154
+ }
155
+ createSecurityGroup(vpcId) {
156
+ const securityGroup = new aws.ec2.SecurityGroup(`${this.name}-security-group`, {
157
+ vpcId,
158
+ ingress: [
159
+ {
160
+ fromPort: 0,
161
+ toPort: 0,
162
+ protocol: '-1',
163
+ securityGroups: [this.lbSecurityGroup.id],
164
+ },
165
+ ],
166
+ egress: [
167
+ {
168
+ fromPort: 0,
169
+ toPort: 0,
170
+ protocol: '-1',
171
+ cidrBlocks: ['0.0.0.0/0'],
172
+ },
173
+ ],
174
+ tags: constants_1.commonTags,
175
+ }, { parent: this });
176
+ return securityGroup;
177
+ }
178
+ createEcsService(args) {
179
+ 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 }), {
180
+ parent: this,
181
+ dependsOn: [this.lb, this.lbTargetGroup, this.lbHttpListener],
182
+ });
183
+ return service;
184
+ }
185
+ createCloudfrontDistribution({ domain, tags, }) {
186
+ const cachePolicy = new aws.cloudfront.CachePolicy(`${this.name}-cf-cache-policy`, {
187
+ comment: 'This cache policy is managed by Pulumi, changing its values will impact multiple services.',
188
+ defaultTtl: 0,
189
+ maxTtl: 31536000,
190
+ minTtl: 0,
191
+ parametersInCacheKeyAndForwardedToOrigin: {
192
+ cookiesConfig: {
193
+ cookieBehavior: 'none',
194
+ },
195
+ headersConfig: {
196
+ headerBehavior: 'none',
197
+ },
198
+ queryStringsConfig: {
199
+ queryStringBehavior: 'all',
200
+ },
201
+ },
202
+ }, { parent: this });
203
+ const originRequestPolicyId = aws.cloudfront
204
+ .getOriginRequestPolicyOutput({
205
+ name: 'Managed-AllViewer',
206
+ })
207
+ .apply(policy => policy.id);
208
+ const responseHeadersPolicyId = aws.cloudfront
209
+ .getResponseHeadersPolicyOutput({
210
+ name: 'Managed-SecurityHeadersPolicy',
211
+ })
212
+ .apply(policy => policy.id);
213
+ const cloudfront = new aws.cloudfront.Distribution(`${this.name}-cloudfront`, Object.assign(Object.assign({ enabled: true }, (domain && { aliases: [domain] })), { isIpv6Enabled: true, waitForDeployment: true, httpVersion: 'http2and3', viewerCertificate: Object.assign({}, (this.certificate
214
+ ? {
215
+ acmCertificateArn: this.certificate.certificate.arn,
216
+ sslSupportMethod: 'sni-only',
217
+ minimumProtocolVersion: 'TLSv1.2_2021',
218
+ }
219
+ : {
220
+ cloudfrontDefaultCertificate: true,
221
+ })), origins: [
222
+ {
223
+ originId: this.lb.arn,
224
+ domainName: this.lb.dnsName,
225
+ connectionAttempts: 3,
226
+ connectionTimeout: 10,
227
+ customOriginConfig: {
228
+ originProtocolPolicy: 'http-only',
229
+ httpPort: 80,
230
+ httpsPort: 443,
231
+ originSslProtocols: ['SSLv3'],
232
+ },
233
+ customHeaders: [
234
+ { name: 'X-Forwarded-Port', value: '443' },
235
+ { name: 'X-Forwarded-Ssl', value: 'on' },
236
+ this.customCFHeader,
237
+ ],
238
+ },
239
+ ], defaultCacheBehavior: {
240
+ targetOriginId: this.lb.arn,
241
+ viewerProtocolPolicy: 'redirect-to-https',
242
+ allowedMethods: [
243
+ 'GET',
244
+ 'HEAD',
245
+ 'OPTIONS',
246
+ 'PUT',
247
+ 'POST',
248
+ 'PATCH',
249
+ 'DELETE',
250
+ ],
251
+ cachedMethods: ['GET', 'HEAD'],
252
+ compress: true,
253
+ cachePolicyId: cachePolicy.id,
254
+ originRequestPolicyId,
255
+ responseHeadersPolicyId,
256
+ }, priceClass: 'PriceClass_100', restrictions: {
257
+ geoRestriction: { restrictionType: 'none' },
258
+ }, tags: Object.assign(Object.assign({}, constants_1.commonTags), tags) }), { parent: this });
259
+ return cloudfront;
260
+ }
261
+ createDnsRecord({ domain, hostedZoneId, }) {
262
+ const cdnAliasRecord = new aws.route53.Record(`${this.name}-cdn-route53-record`, {
263
+ type: 'A',
264
+ name: domain,
265
+ zoneId: hostedZoneId,
266
+ aliases: [
267
+ {
268
+ name: this.cloudfront.domainName,
269
+ zoneId: this.cloudfront.hostedZoneId,
270
+ evaluateTargetHealth: true,
271
+ },
272
+ ],
273
+ }, { parent: this });
274
+ return cdnAliasRecord;
275
+ }
276
+ }
277
+ exports.NuxtSSR = NuxtSSR;
@@ -4,10 +4,13 @@ import * as awsx from '@pulumi/awsx';
4
4
  import * as upstash from '@upstash/pulumi';
5
5
  import { Database, DatabaseArgs } from './database';
6
6
  import { WebServer, WebServerArgs } from './web-server';
7
+ import { Mongo, MongoArgs } from './mongo';
7
8
  import { Redis, RedisArgs } from './redis';
8
9
  import { StaticSite, StaticSiteArgs } from './static-site';
9
10
  import { Ec2SSMConnect } from './ec2-ssm-connect';
10
- export type Service = Database | Redis | StaticSite | WebServer;
11
+ import { EcsService, EcsServiceArgs } from './ecs-service';
12
+ import { NuxtSSR, NuxtSSRArgs } from './nuxt-ssr';
13
+ export type Service = Database | Redis | StaticSite | WebServer | NuxtSSR | Mongo | EcsService;
11
14
  export type Services = Record<string, Service>;
12
15
  type ServiceArgs = {
13
16
  /**
@@ -15,33 +18,44 @@ type ServiceArgs = {
15
18
  */
16
19
  serviceName: string;
17
20
  };
18
- export type DatabaseService = {
21
+ export type DatabaseServiceOptions = {
19
22
  type: 'DATABASE';
20
- } & ServiceArgs & Omit<DatabaseArgs, 'vpc'>;
21
- export type RedisService = {
23
+ } & ServiceArgs & Omit<DatabaseArgs, 'vpcId' | 'vpcCidrBlock' | 'isolatedSubnetIds'>;
24
+ export type RedisServiceOptions = {
22
25
  type: 'REDIS';
23
- } & ServiceArgs & Pick<RedisArgs, 'dbName' | 'region'>;
24
- export type StaticSiteService = {
26
+ } & ServiceArgs & RedisArgs;
27
+ export type StaticSiteServiceOptions = {
25
28
  type: 'STATIC_SITE';
26
- } & ServiceArgs & Omit<StaticSiteArgs, 'hostedZoneId'>;
27
- export type WebServerService = {
29
+ } & ServiceArgs & StaticSiteArgs;
30
+ export type WebServerServiceOptions = {
28
31
  type: 'WEB_SERVER';
29
32
  environment?: aws.ecs.KeyValuePair[] | ((services: Services) => aws.ecs.KeyValuePair[]);
30
33
  secrets?: aws.ecs.Secret[] | ((services: Services) => aws.ecs.Secret[]);
31
- } & ServiceArgs & Omit<WebServerArgs, 'cluster' | 'vpc' | 'hostedZoneId' | 'environment' | 'secrets'>;
34
+ } & ServiceArgs & Omit<WebServerArgs, 'cluster' | 'vpcId' | 'vpcCidrBlock' | 'publicSubnetIds' | 'environment' | 'secrets'>;
35
+ export type NuxtSSRServiceOptions = {
36
+ type: 'NUXT_SSR';
37
+ environment?: aws.ecs.KeyValuePair[] | ((services: Services) => aws.ecs.KeyValuePair[]);
38
+ secrets?: aws.ecs.Secret[] | ((services: Services) => aws.ecs.Secret[]);
39
+ } & ServiceArgs & Omit<NuxtSSRArgs, 'cluster' | 'vpcId' | 'vpcCidrBlock' | 'publicSubnetIds' | 'environment' | 'secrets'>;
40
+ export type MongoServiceOptions = {
41
+ type: 'MONGO';
42
+ } & ServiceArgs & Omit<MongoArgs, 'cluster' | 'vpcId' | 'vpcCidrBlock' | 'privateSubnetIds' | 'environment' | 'secrets'>;
43
+ export type EcsServiceOptions = {
44
+ type: 'ECS_SERVICE';
45
+ environment?: aws.ecs.KeyValuePair[] | ((services: Services) => aws.ecs.KeyValuePair[]);
46
+ secrets?: aws.ecs.Secret[] | ((services: Services) => aws.ecs.Secret[]);
47
+ } & ServiceArgs & Omit<EcsServiceArgs, 'cluster' | 'vpcId' | 'vpcCidrBlock' | 'subnetIds' | 'environment' | 'secrets'>;
32
48
  export type ProjectArgs = {
33
- services: (DatabaseService | RedisService | StaticSiteService | WebServerService)[];
34
- hostedZoneId?: pulumi.Input<string>;
49
+ services: (DatabaseServiceOptions | RedisServiceOptions | StaticSiteServiceOptions | WebServerServiceOptions | NuxtSSRServiceOptions | MongoServiceOptions | EcsServiceOptions)[];
35
50
  enableSSMConnect?: pulumi.Input<boolean>;
36
51
  };
37
- export declare class MissingHostedZoneId extends Error {
38
- constructor(serviceType: string);
52
+ export declare class MissingEcsCluster extends Error {
53
+ constructor();
39
54
  }
40
55
  export declare class Project extends pulumi.ComponentResource {
41
56
  name: string;
42
57
  vpc: awsx.ec2.Vpc;
43
58
  cluster?: aws.ecs.Cluster;
44
- hostedZoneId?: pulumi.Input<string>;
45
59
  upstashProvider?: upstash.Provider;
46
60
  ec2SSMConnect?: Ec2SSMConnect;
47
61
  services: Services;
@@ -49,10 +63,13 @@ export declare class Project extends pulumi.ComponentResource {
49
63
  private createVpc;
50
64
  private createServices;
51
65
  private createRedisPrerequisites;
52
- private createWebServerPrerequisites;
66
+ private createEcsCluster;
53
67
  private createDatabaseService;
54
68
  private createRedisService;
55
69
  private createStaticSiteService;
56
70
  private createWebServerService;
71
+ private createNuxtSSRService;
72
+ private createMongoService;
73
+ private createEcsService;
57
74
  }
58
75
  export {};
@@ -11,37 +11,39 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  return t;
12
12
  };
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.Project = exports.MissingHostedZoneId = void 0;
14
+ exports.Project = exports.MissingEcsCluster = void 0;
15
15
  const pulumi = require("@pulumi/pulumi");
16
16
  const aws = require("@pulumi/aws");
17
17
  const awsx = require("@pulumi/awsx");
18
18
  const upstash = require("@upstash/pulumi");
19
19
  const database_1 = require("./database");
20
20
  const web_server_1 = require("./web-server");
21
+ const mongo_1 = require("./mongo");
21
22
  const redis_1 = require("./redis");
22
23
  const static_site_1 = require("./static-site");
23
24
  const ec2_ssm_connect_1 = require("./ec2-ssm-connect");
24
25
  const constants_1 = require("../constants");
25
- class MissingHostedZoneId extends Error {
26
- constructor(serviceType) {
27
- super(`Project::hostedZoneId argument must be provided
28
- in order to create ${serviceType} service`);
26
+ const ecs_service_1 = require("./ecs-service");
27
+ const nuxt_ssr_1 = require("./nuxt-ssr");
28
+ class MissingEcsCluster extends Error {
29
+ constructor() {
30
+ super('Ecs Cluster does not exist');
29
31
  this.name = this.constructor.name;
30
32
  }
31
33
  }
32
- exports.MissingHostedZoneId = MissingHostedZoneId;
34
+ exports.MissingEcsCluster = MissingEcsCluster;
33
35
  class Project extends pulumi.ComponentResource {
34
36
  constructor(name, args, opts = {}) {
35
37
  super('studion:Project', name, {}, opts);
36
38
  this.services = {};
37
- const { services, hostedZoneId } = args;
38
39
  this.name = name;
39
- this.hostedZoneId = hostedZoneId;
40
40
  this.vpc = this.createVpc();
41
- this.createServices(services);
41
+ this.createServices(args.services);
42
42
  if (args.enableSSMConnect) {
43
43
  this.ec2SSMConnect = new ec2_ssm_connect_1.Ec2SSMConnect(`${name}-ssm-connect`, {
44
- vpc: this.vpc,
44
+ vpcId: this.vpc.vpcId,
45
+ privateSubnetId: this.vpc.privateSubnetIds.apply(ids => ids[0]),
46
+ vpcCidrBlock: this.vpc.vpc.cidrBlock,
45
47
  });
46
48
  }
47
49
  this.registerOutputs();
@@ -62,11 +64,14 @@ class Project extends pulumi.ComponentResource {
62
64
  }
63
65
  createServices(services) {
64
66
  const hasRedisService = services.some(it => it.type === 'REDIS');
65
- const hasWebServerService = services.some(it => it.type === 'WEB_SERVER');
67
+ const shouldCreateEcsCluster = services.some(it => it.type === 'WEB_SERVER' ||
68
+ it.type === 'NUXT_SSR' ||
69
+ it.type === 'MONGO' ||
70
+ it.type === 'ECS_SERVICE') && !this.cluster;
66
71
  if (hasRedisService)
67
72
  this.createRedisPrerequisites();
68
- if (hasWebServerService)
69
- this.createWebServerPrerequisites();
73
+ if (shouldCreateEcsCluster)
74
+ this.createEcsCluster();
70
75
  services.forEach(it => {
71
76
  if (it.type === 'DATABASE')
72
77
  this.createDatabaseService(it);
@@ -76,6 +81,12 @@ class Project extends pulumi.ComponentResource {
76
81
  this.createStaticSiteService(it);
77
82
  if (it.type === 'WEB_SERVER')
78
83
  this.createWebServerService(it);
84
+ if (it.type === 'NUXT_SSR')
85
+ this.createNuxtSSRService(it);
86
+ if (it.type === 'MONGO')
87
+ this.createMongoService(it);
88
+ if (it.type === 'ECS_SERVICE')
89
+ this.createEcsService(it);
79
90
  });
80
91
  }
81
92
  createRedisPrerequisites() {
@@ -85,7 +96,7 @@ class Project extends pulumi.ComponentResource {
85
96
  apiKey: upstashConfig.requireSecret('apiKey'),
86
97
  });
87
98
  }
88
- createWebServerPrerequisites() {
99
+ createEcsCluster() {
89
100
  const stack = pulumi.getStack();
90
101
  this.cluster = new aws.ecs.Cluster(`${this.name}-cluster`, {
91
102
  name: `${this.name}-${stack}`,
@@ -94,7 +105,7 @@ class Project extends pulumi.ComponentResource {
94
105
  }
95
106
  createDatabaseService(options) {
96
107
  const { serviceName, type } = options, databaseOptions = __rest(options, ["serviceName", "type"]);
97
- const service = new database_1.Database(serviceName, Object.assign(Object.assign({}, databaseOptions), { vpc: this.vpc }), { parent: this });
108
+ 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 });
98
109
  this.services[serviceName] = service;
99
110
  }
100
111
  createRedisService(options) {
@@ -109,20 +120,51 @@ class Project extends pulumi.ComponentResource {
109
120
  }
110
121
  createStaticSiteService(options) {
111
122
  const { serviceName } = options, staticSiteOptions = __rest(options, ["serviceName"]);
112
- const service = new static_site_1.StaticSite(serviceName, Object.assign(Object.assign({}, staticSiteOptions), { hostedZoneId: this.hostedZoneId }), { parent: this });
123
+ const service = new static_site_1.StaticSite(serviceName, staticSiteOptions, {
124
+ parent: this,
125
+ });
113
126
  this.services[serviceName] = service;
114
127
  }
115
128
  createWebServerService(options) {
116
129
  if (!this.cluster)
117
- return;
118
- if (!this.hostedZoneId)
119
- throw new MissingHostedZoneId(options.type);
130
+ throw new MissingEcsCluster();
131
+ const { serviceName, environment, secrets } = options, ecsOptions = __rest(options, ["serviceName", "environment", "secrets"]);
132
+ const parsedEnv = typeof environment === 'function'
133
+ ? environment(this.services)
134
+ : environment;
135
+ const parsedSecrets = typeof secrets === 'function' ? secrets(this.services) : secrets;
136
+ const service = new web_server_1.WebServer(serviceName, Object.assign(Object.assign({}, ecsOptions), { cluster: this.cluster, vpcId: this.vpc.vpcId, vpcCidrBlock: this.vpc.vpc.cidrBlock, publicSubnetIds: this.vpc.publicSubnetIds, environment: parsedEnv, secrets: parsedSecrets }), { parent: this });
137
+ this.services[options.serviceName] = service;
138
+ }
139
+ createNuxtSSRService(options) {
140
+ if (!this.cluster)
141
+ throw new MissingEcsCluster();
142
+ const { serviceName, environment, secrets } = options, ecsOptions = __rest(options, ["serviceName", "environment", "secrets"]);
143
+ const parsedEnv = typeof environment === 'function'
144
+ ? environment(this.services)
145
+ : environment;
146
+ const parsedSecrets = typeof secrets === 'function' ? secrets(this.services) : secrets;
147
+ const service = new nuxt_ssr_1.NuxtSSR(serviceName, Object.assign(Object.assign({}, ecsOptions), { cluster: this.cluster, vpcId: this.vpc.vpcId, vpcCidrBlock: this.vpc.vpc.cidrBlock, publicSubnetIds: this.vpc.publicSubnetIds, environment: parsedEnv, secrets: parsedSecrets }), { parent: this });
148
+ this.services[options.serviceName] = service;
149
+ }
150
+ createMongoService(options) {
151
+ if (!this.cluster)
152
+ throw new MissingEcsCluster();
153
+ const { serviceName } = options, mongoOptions = __rest(options, ["serviceName"]);
154
+ const service = new mongo_1.Mongo(serviceName, Object.assign(Object.assign({}, mongoOptions), { cluster: this.cluster, vpcId: this.vpc.vpcId, vpcCidrBlock: this.vpc.vpc.cidrBlock, privateSubnetIds: this.vpc.privateSubnetIds }), { parent: this });
155
+ this.services[options.serviceName] = service;
156
+ }
157
+ createEcsService(options) {
158
+ if (!this.cluster)
159
+ throw new MissingEcsCluster();
120
160
  const { serviceName, environment, secrets } = options, ecsOptions = __rest(options, ["serviceName", "environment", "secrets"]);
121
161
  const parsedEnv = typeof environment === 'function'
122
162
  ? environment(this.services)
123
163
  : environment;
124
164
  const parsedSecrets = typeof secrets === 'function' ? secrets(this.services) : secrets;
125
- const service = new web_server_1.WebServer(serviceName, Object.assign(Object.assign({}, ecsOptions), { cluster: this.cluster, vpc: this.vpc, hostedZoneId: this.hostedZoneId, environment: parsedEnv, secrets: parsedSecrets }), { parent: this });
165
+ const service = new ecs_service_1.EcsService(serviceName, Object.assign(Object.assign({}, ecsOptions), { cluster: this.cluster, vpcId: this.vpc.vpcId, vpcCidrBlock: this.vpc.vpc.cidrBlock, subnetIds: ecsOptions.assignPublicIp
166
+ ? this.vpc.publicSubnetIds
167
+ : this.vpc.privateSubnetIds, environment: parsedEnv, secrets: parsedSecrets }), { parent: this });
126
168
  this.services[options.serviceName] = service;
127
169
  }
128
170
  }
@@ -1,106 +1,37 @@
1
1
  import * as pulumi from '@pulumi/pulumi';
2
2
  import * as aws from '@pulumi/aws';
3
- import * as awsx from '@pulumi/awsx';
4
- import { Size } from '../types/size';
5
3
  import { AcmCertificate } from './acm-certificate';
6
- export type RoleInlinePolicy = {
7
- /**
8
- * Name of the role policy.
9
- */
10
- name?: pulumi.Input<string>;
11
- /**
12
- * Policy document as a JSON formatted string.
13
- */
14
- policy?: pulumi.Input<string>;
15
- };
16
- export type WebServerArgs = {
17
- /**
18
- * The ECR image used to start a container.
19
- */
20
- image: pulumi.Input<string>;
21
- /**
22
- * Exposed service port.
23
- */
24
- port: pulumi.Input<number>;
4
+ import { EcsService, EcsServiceArgs } from './ecs-service';
5
+ export type WebServerArgs = Pick<EcsServiceArgs, 'image' | 'port' | 'cluster' | 'vpcId' | 'vpcCidrBlock' | 'desiredCount' | 'autoscaling' | 'size' | 'environment' | 'secrets' | 'taskExecutionRoleInlinePolicies' | 'taskRoleInlinePolicies' | 'tags'> & {
6
+ publicSubnetIds: pulumi.Input<pulumi.Input<string>[]>;
25
7
  /**
26
8
  * The domain which will be used to access the service.
27
9
  * The domain or subdomain must belong to the provided hostedZone.
28
10
  */
29
- domain: pulumi.Input<string>;
30
- /**
31
- * The aws.ecs.Cluster resource.
32
- */
33
- cluster: aws.ecs.Cluster;
11
+ domain?: pulumi.Input<string>;
34
12
  /**
35
13
  * The ID of the hosted zone.
36
14
  */
37
- hostedZoneId: pulumi.Input<string>;
38
- /**
39
- * The awsx.ec2.Vpc resource.
40
- */
41
- vpc: awsx.ec2.Vpc;
42
- /**
43
- * Number of instances of the task definition to place and keep running. Defaults to 1.
44
- */
45
- desiredCount?: pulumi.Input<number>;
46
- /**
47
- * Min capacity of the scalable target. Defaults to 1.
48
- */
49
- minCount?: pulumi.Input<number>;
50
- /**
51
- * Max capacity of the scalable target. Defaults to 10.
52
- */
53
- maxCount?: pulumi.Input<number>;
54
- /**
55
- * CPU and memory size used for running the container. Defaults to "small".
56
- * Available predefined options are:
57
- * - small (0.25 vCPU, 0.5 GB memory)
58
- * - medium (0.5 vCPU, 1 GB memory)
59
- * - large (1 vCPU memory, 2 GB memory)
60
- * - xlarge (2 vCPU, 4 GB memory)
61
- */
62
- size?: pulumi.Input<Size>;
63
- /**
64
- * The environment variables to pass to a container. Don't use this field for
65
- * sensitive information such as passwords, API keys, etc. For that purpose,
66
- * please use the `secrets` property.
67
- * Defaults to [].
68
- */
69
- environment?: aws.ecs.KeyValuePair[];
70
- /**
71
- * The secrets to pass to the container. Defaults to [].
72
- */
73
- secrets?: aws.ecs.Secret[];
74
- /**
75
- * Path for the health check request. Defaults to "/healtcheck".
76
- */
77
- healtCheckPath?: pulumi.Input<string>;
78
- taskExecutionRoleInlinePolicies?: pulumi.Input<pulumi.Input<RoleInlinePolicy>[]>;
79
- taskRoleInlinePolicies?: pulumi.Input<pulumi.Input<RoleInlinePolicy>[]>;
15
+ hostedZoneId?: pulumi.Input<string>;
80
16
  /**
81
- * A map of tags to assign to the resource.
17
+ * Path for the health check request. Defaults to "/healthcheck".
82
18
  */
83
- tags?: pulumi.Input<{
84
- [key: string]: pulumi.Input<string>;
85
- }>;
19
+ healthCheckPath?: pulumi.Input<string>;
86
20
  };
87
21
  export declare class WebServer extends pulumi.ComponentResource {
88
22
  name: string;
89
- certificate: AcmCertificate;
90
- logGroup: aws.cloudwatch.LogGroup;
23
+ service: EcsService;
91
24
  lbSecurityGroup: aws.ec2.SecurityGroup;
25
+ serviceSecurityGroup: aws.ec2.SecurityGroup;
92
26
  lb: aws.lb.LoadBalancer;
93
27
  lbTargetGroup: aws.lb.TargetGroup;
94
28
  lbHttpListener: aws.lb.Listener;
95
- lbTlsListener: aws.lb.Listener;
96
- taskDefinition: aws.ecs.TaskDefinition;
97
- service: aws.ecs.Service;
29
+ certificate?: AcmCertificate;
30
+ lbTlsListener?: aws.lb.Listener;
98
31
  constructor(name: string, args: WebServerArgs, opts?: pulumi.ComponentResourceOptions);
99
32
  private createTlsCertificate;
100
- private createLogGroup;
101
33
  private createLoadBalancer;
102
- private createTaskDefinition;
34
+ private createSecurityGroup;
103
35
  private createEcsService;
104
36
  private createDnsRecord;
105
- private enableAutoscaling;
106
37
  }