@studion/infra-code-blocks 0.0.11 → 0.1.0

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.
package/README.md CHANGED
@@ -92,7 +92,7 @@ type DatabaseService = {
92
92
  serviceName: string;
93
93
  dbName: pulumi.Input<string>;
94
94
  username: pulumi.Input<string>;
95
- password?: pulumi.Input<string>;
95
+ password: pulumi.Input<string>;
96
96
  applyImmediately?: pulumi.Input<boolean>;
97
97
  skipFinalSnapshot?: pulumi.Input<boolean>;
98
98
  allocatedStorage?: pulumi.Input<number>;
@@ -237,7 +237,7 @@ AWS RDS Postgres instance.
237
237
  Features:
238
238
 
239
239
  - enabled encryption with a symmetric encryption key
240
- - deployed inside a private subnet
240
+ - deployed inside an isolated subnet
241
241
  - backup enabled with retention period set to 14 days
242
242
 
243
243
  <br>
@@ -256,8 +256,8 @@ new Database(name: string, args: DatabaseArgs, opts?: pulumi.CustomResourceOptio
256
256
  type DatabaseArgs = {
257
257
  dbName: pulumi.Input<string>;
258
258
  username: pulumi.Input<string>;
259
+ password: pulumi.Input<string>;
259
260
  vpc: awsx.ec2.Vpc;
260
- password?: pulumi.Input<string>;
261
261
  applyImmediately?: pulumi.Input<boolean>;
262
262
  skipFinalSnapshot?: pulumi.Input<boolean>;
263
263
  allocatedStorage?: pulumi.Input<number>;
@@ -269,9 +269,8 @@ type DatabaseArgs = {
269
269
  };
270
270
  ```
271
271
 
272
- If a password is not specified, it will be autogenerated and stored as a secret
273
- inside AWS Secret Manager. The secret will be available on the `Database` resource
274
- as `passwordSecret`.
272
+ The database password is stored as a secret inside AWS Secret Manager.
273
+ The secret will be available on the `Database` resource as `passwordSecret`.
275
274
 
276
275
  ### Redis
277
276
 
@@ -429,16 +428,16 @@ Where `CLUSTER_NAME` is the name of the ECS cluster and `TASK_FAMILY_NAME` is th
429
428
 
430
429
  ## SSM Connect
431
430
 
432
- The [Database](#database) component deploys a database instance inside a private subnet,
431
+ The [Database](#database) component deploys a database instance inside a isolated subnet,
433
432
  and it's not publicly accessible from outside of VPC.
434
433
  <br>
435
434
  In order to connect to the database we need to deploy the ec2 instance which will be used
436
435
  to forward traffic to the database instance.
437
436
  <br>
438
- Because of security reasons, the ec2 instance is also deployed inside a private subnet
437
+ Because of security reasons, the ec2 instance is deployed inside a private subnet
439
438
  which means we can't directly connect to it. For that purpose, we use AWS System Manager
440
439
  which enables us to connect to the ec2 instance even though it's inside a private subnet.
441
- The benefit of using AWS SSM is that we don't need a ssh key pair.
440
+ Another benefit of using AWS SSM is that we don't need a ssh key pair.
442
441
 
443
442
  ![AWS RDS connection schema](/assets/images/ssm-rds.png)
444
443
 
@@ -501,3 +500,9 @@ const project = new studion.Project('demo-project', {
501
500
 
502
501
  - [ ] Add worker service for executing tasks
503
502
  - [ ] Add MongoDB service
503
+ - [x] reduce ec2 security group rules and change cidr block to be within VPC
504
+ - [x] change db private subnet ids to isolated subnet ids
505
+ - [x] change default instance classes to t4g
506
+ - [x] extract ami images/ instance classes, etc...
507
+ - [x] remove duplicated types
508
+ - [ ] extract constructor code to private methods...
@@ -11,14 +11,14 @@ export type DatabaseArgs = {
11
11
  */
12
12
  username: pulumi.Input<string>;
13
13
  /**
14
- * The awsx.ec2.Vpc resource.
14
+ * Password for the master DB user.
15
+ * The value will be stored as a secret in AWS Secret Manager.
15
16
  */
16
- vpc: awsx.ec2.Vpc;
17
+ password: pulumi.Input<string>;
17
18
  /**
18
- * Password for the master DB user. If not specified, it will be autogenerated.
19
- * The value will be stored as a secret in AWS Secret Manager.
19
+ * The awsx.ec2.Vpc resource.
20
20
  */
21
- password?: pulumi.Input<string>;
21
+ vpc: awsx.ec2.Vpc;
22
22
  /**
23
23
  * Specifies whether any database modifications are applied immediately, or during the next maintenance window. Default is false.
24
24
  */
@@ -47,10 +47,16 @@ export type DatabaseArgs = {
47
47
  }>;
48
48
  };
49
49
  export declare class Database extends pulumi.ComponentResource {
50
+ name: string;
50
51
  instance: aws.rds.Instance;
51
52
  kms: aws.kms.Key;
52
53
  dbSubnetGroup: aws.rds.SubnetGroup;
53
54
  dbSecurityGroup: aws.ec2.SecurityGroup;
54
55
  passwordSecret: aws.secretsmanager.Secret;
55
56
  constructor(name: string, args: DatabaseArgs, opts?: pulumi.ComponentResourceOptions);
57
+ private createSubnetGroup;
58
+ private createSecurityGroup;
59
+ private createEncryptionKey;
60
+ private createPasswordSecret;
61
+ private createDatabaseInstance;
56
62
  }
@@ -8,49 +8,67 @@ const defaults = {
8
8
  skipFinalSnapshot: false,
9
9
  allocatedStorage: 20,
10
10
  maxAllocatedStorage: 100,
11
- instanceClass: 'db.t3.micro',
11
+ instanceClass: 'db.t4g.micro',
12
12
  };
13
13
  class Database extends pulumi.ComponentResource {
14
14
  constructor(name, args, opts = {}) {
15
15
  super('studion:Database', name, {}, opts);
16
- const project = pulumi.getProject();
17
- const stack = pulumi.getStack();
18
- const argsWithDefaults = Object.assign({}, defaults, args);
19
- this.dbSubnetGroup = new aws.rds.SubnetGroup(`${name}-subnet-group`, {
20
- subnetIds: argsWithDefaults.vpc.privateSubnetIds,
16
+ this.name = name;
17
+ const { vpc, password } = args;
18
+ this.dbSubnetGroup = this.createSubnetGroup({ vpc });
19
+ this.dbSecurityGroup = this.createSecurityGroup({ vpc });
20
+ this.kms = this.createEncryptionKey();
21
+ this.passwordSecret = this.createPasswordSecret({ password });
22
+ this.instance = this.createDatabaseInstance(args);
23
+ this.registerOutputs();
24
+ }
25
+ createSubnetGroup({ vpc }) {
26
+ const dbSubnetGroup = new aws.rds.SubnetGroup(`${this.name}-subnet-group`, {
27
+ subnetIds: vpc.isolatedSubnetIds,
21
28
  }, { parent: this });
22
- this.dbSecurityGroup = new aws.ec2.SecurityGroup(`${name}-security-group`, {
23
- vpcId: argsWithDefaults.vpc.vpcId,
29
+ return dbSubnetGroup;
30
+ }
31
+ createSecurityGroup({ vpc }) {
32
+ const dbSecurityGroup = new aws.ec2.SecurityGroup(`${this.name}-security-group`, {
33
+ vpcId: vpc.vpcId,
24
34
  ingress: [
25
35
  {
26
36
  protocol: 'tcp',
27
37
  fromPort: 5432,
28
38
  toPort: 5432,
29
- cidrBlocks: [argsWithDefaults.vpc.vpc.cidrBlock],
39
+ cidrBlocks: [vpc.vpc.cidrBlock],
30
40
  },
31
41
  ],
32
42
  }, { parent: this });
33
- this.kms = new aws.kms.Key(`${name}-rds-key`, {
34
- description: `${name} RDS encryption key`,
43
+ return dbSecurityGroup;
44
+ }
45
+ createEncryptionKey() {
46
+ const kms = new aws.kms.Key(`${this.name}-rds-key`, {
47
+ description: `${this.name} RDS encryption key`,
35
48
  customerMasterKeySpec: 'SYMMETRIC_DEFAULT',
36
49
  isEnabled: true,
37
50
  keyUsage: 'ENCRYPT_DECRYPT',
38
51
  multiRegion: false,
39
52
  enableKeyRotation: true,
40
53
  }, { parent: this });
41
- const password = argsWithDefaults.password ||
42
- aws.secretsmanager
43
- .getRandomPasswordOutput()
44
- .apply(res => res.randomPassword);
45
- this.passwordSecret = new aws.secretsmanager.Secret(`${name}-password-secret`, {
46
- name: `${stack}/${project}/DatabasePassword`,
54
+ return kms;
55
+ }
56
+ createPasswordSecret({ password }) {
57
+ const project = pulumi.getProject();
58
+ const stack = pulumi.getStack();
59
+ const passwordSecret = new aws.secretsmanager.Secret(`${this.name}-password-secret`, {
60
+ namePrefix: `${stack}/${project}/DatabasePassword-`,
47
61
  }, { parent: this });
48
- const passwordSecretValue = new aws.secretsmanager.SecretVersion(`${name}-password-secret-value`, {
49
- secretId: this.passwordSecret.id,
62
+ const passwordSecretValue = new aws.secretsmanager.SecretVersion(`${this.name}-password-secret-value`, {
63
+ secretId: passwordSecret.id,
50
64
  secretString: password,
51
- }, { parent: this, dependsOn: [this.passwordSecret] });
52
- this.instance = new aws.rds.Instance(`${name}-rds`, {
53
- identifier: name,
65
+ }, { parent: this, dependsOn: [passwordSecret] });
66
+ return passwordSecret;
67
+ }
68
+ createDatabaseInstance(args) {
69
+ const argsWithDefaults = Object.assign({}, defaults, args);
70
+ const instance = new aws.rds.Instance(`${this.name}-rds`, {
71
+ identifierPrefix: `${this.name}-`,
54
72
  engine: 'postgres',
55
73
  engineVersion: '14.9',
56
74
  allocatedStorage: argsWithDefaults.allocatedStorage,
@@ -58,7 +76,7 @@ class Database extends pulumi.ComponentResource {
58
76
  instanceClass: argsWithDefaults.instanceClass,
59
77
  dbName: argsWithDefaults.dbName,
60
78
  username: argsWithDefaults.username,
61
- password,
79
+ password: argsWithDefaults.password,
62
80
  dbSubnetGroupName: this.dbSubnetGroup.name,
63
81
  vpcSecurityGroupIds: [this.dbSecurityGroup.id],
64
82
  storageEncrypted: true,
@@ -68,12 +86,12 @@ class Database extends pulumi.ComponentResource {
68
86
  applyImmediately: argsWithDefaults.applyImmediately,
69
87
  autoMinorVersionUpgrade: true,
70
88
  maintenanceWindow: 'Mon:07:00-Mon:07:30',
71
- finalSnapshotIdentifier: `${name}-final-snapshot`,
89
+ finalSnapshotIdentifier: `${this.name}-final-snapshot`,
72
90
  backupWindow: '06:00-06:30',
73
91
  backupRetentionPeriod: 14,
74
92
  tags: argsWithDefaults.tags,
75
93
  }, { parent: this });
76
- this.registerOutputs();
94
+ return instance;
77
95
  }
78
96
  }
79
97
  exports.Database = Database;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Ec2SSMConnect = void 0;
4
4
  const pulumi = require("@pulumi/pulumi");
5
5
  const aws = require("@pulumi/aws");
6
+ const constants_1 = require("../constants");
6
7
  const config = new pulumi.Config('aws');
7
8
  const awsRegion = config.require('region');
8
9
  class Ec2SSMConnect extends pulumi.ComponentResource {
@@ -15,19 +16,13 @@ class Ec2SSMConnect extends pulumi.ComponentResource {
15
16
  protocol: 'tcp',
16
17
  fromPort: 22,
17
18
  toPort: 22,
18
- cidrBlocks: ['0.0.0.0/0'],
19
- },
20
- {
21
- protocol: 'tcp',
22
- fromPort: 80,
23
- toPort: 80,
24
- cidrBlocks: ['0.0.0.0/0'],
19
+ cidrBlocks: [args.vpc.vpc.cidrBlock],
25
20
  },
26
21
  {
27
22
  protocol: 'tcp',
28
23
  fromPort: 443,
29
24
  toPort: 443,
30
- cidrBlocks: ['0.0.0.0/0'],
25
+ cidrBlocks: [args.vpc.vpc.cidrBlock],
31
26
  },
32
27
  ],
33
28
  egress: [
@@ -57,9 +52,9 @@ class Ec2SSMConnect extends pulumi.ComponentResource {
57
52
  role: role.name,
58
53
  }, { parent: this, dependsOn: [ssmPolicyAttachment] });
59
54
  this.ec2 = new aws.ec2.Instance(`${name}-ec2`, {
60
- ami: 'ami-067d1e60475437da2',
55
+ ami: constants_1.Ec2AMI.AmazonLinux2023.ARM,
61
56
  associatePublicIpAddress: false,
62
- instanceType: 't2.micro',
57
+ instanceType: 't4g.nano',
63
58
  iamInstanceProfile: ssmProfile.name,
64
59
  subnetId,
65
60
  vpcSecurityGroupIds: [this.ec2SecurityGroup.id],
@@ -50,6 +50,11 @@ class Project extends pulumi.ComponentResource {
50
50
  numberOfAvailabilityZones: 2,
51
51
  enableDnsHostnames: true,
52
52
  enableDnsSupport: true,
53
+ subnetSpecs: [
54
+ { type: awsx.ec2.SubnetType.Public, cidrMask: 24 },
55
+ { type: awsx.ec2.SubnetType.Private, cidrMask: 24 },
56
+ { type: awsx.ec2.SubnetType.Isolated, cidrMask: 24 },
57
+ ],
53
58
  }, { parent: this });
54
59
  return vpc;
55
60
  }
@@ -21,7 +21,7 @@ class Redis extends pulumi.ComponentResource {
21
21
  tls: true,
22
22
  }, { provider: opts.provider, parent: this });
23
23
  this.passwordSecret = new aws.secretsmanager.Secret(`${name}-password-secret`, {
24
- name: `${stack}/${project}/RedisPassword`,
24
+ namePrefix: `${stack}/${project}/RedisPassword-`,
25
25
  }, { parent: this, dependsOn: [this.instance] });
26
26
  const passwordSecretValue = new aws.secretsmanager.SecretVersion(`${name}-password-secret-value`, {
27
27
  secretId: this.passwordSecret.id,
@@ -19,8 +19,13 @@ export type StaticSiteArgs = {
19
19
  }>;
20
20
  };
21
21
  export declare class StaticSite extends pulumi.ComponentResource {
22
+ name: string;
22
23
  certificate: AcmCertificate;
23
24
  bucket: aws.s3.Bucket;
24
25
  cloudfront: aws.cloudfront.Distribution;
25
26
  constructor(name: string, args: StaticSiteArgs, opts?: pulumi.ComponentResourceOptions);
27
+ private createTlsCertificate;
28
+ private createPublicBucket;
29
+ private createCloudfrontDistribution;
30
+ private createDnsRecord;
26
31
  }
@@ -7,25 +7,38 @@ const acm_certificate_1 = require("./acm-certificate");
7
7
  class StaticSite extends pulumi.ComponentResource {
8
8
  constructor(name, args, opts = {}) {
9
9
  super('studion:StaticSite', name, {}, opts);
10
- const certificate = new acm_certificate_1.AcmCertificate(`${args.domain}-acm-certificate`, {
11
- domain: args.domain,
12
- hostedZoneId: args.hostedZoneId,
10
+ this.name = name;
11
+ const { domain, hostedZoneId, tags } = args;
12
+ this.certificate = this.createTlsCertificate({ domain, hostedZoneId });
13
+ this.bucket = this.createPublicBucket({ tags });
14
+ this.cloudfront = this.createCloudfrontDistribution({ domain, tags });
15
+ this.createDnsRecord({ domain, hostedZoneId });
16
+ this.registerOutputs();
17
+ }
18
+ createTlsCertificate({ domain, hostedZoneId, }) {
19
+ const certificate = new acm_certificate_1.AcmCertificate(`${domain}-acm-certificate`, {
20
+ domain,
21
+ hostedZoneId,
13
22
  }, { parent: this });
14
- const bucket = new aws.s3.Bucket(`${name}-bucket`, {
23
+ return certificate;
24
+ }
25
+ createPublicBucket({ tags }) {
26
+ const bucket = new aws.s3.Bucket(`${this.name}-bucket`, {
27
+ bucketPrefix: `${this.name}-`,
15
28
  website: {
16
29
  indexDocument: 'index.html',
17
30
  errorDocument: 'index.html',
18
31
  },
19
- tags: args.tags,
32
+ tags,
20
33
  }, { parent: this });
21
- const bucketPublicAccessBlock = new aws.s3.BucketPublicAccessBlock(`${name}-bucket-access-block`, {
34
+ const bucketPublicAccessBlock = new aws.s3.BucketPublicAccessBlock(`${this.name}-bucket-access-block`, {
22
35
  bucket: bucket.id,
23
36
  blockPublicAcls: false,
24
37
  blockPublicPolicy: false,
25
38
  ignorePublicAcls: false,
26
39
  restrictPublicBuckets: false,
27
40
  }, { parent: this });
28
- const siteBucketPolicy = new aws.s3.BucketPolicy(`${name}-bucket-policy`, {
41
+ const siteBucketPolicy = new aws.s3.BucketPolicy(`${this.name}-bucket-policy`, {
29
42
  bucket: bucket.bucket,
30
43
  policy: bucket.bucket.apply(publicReadPolicy),
31
44
  }, { parent: this, dependsOn: [bucketPublicAccessBlock] });
@@ -42,22 +55,25 @@ class StaticSite extends pulumi.ComponentResource {
42
55
  ],
43
56
  };
44
57
  }
45
- const cloudfront = new aws.cloudfront.Distribution(`${name}-cloudfront`, {
58
+ return bucket;
59
+ }
60
+ createCloudfrontDistribution({ domain, tags, }) {
61
+ const cloudfront = new aws.cloudfront.Distribution(`${this.name}-cloudfront`, {
46
62
  enabled: true,
47
63
  defaultRootObject: 'index.html',
48
- aliases: [args.domain],
64
+ aliases: [domain],
49
65
  isIpv6Enabled: true,
50
66
  waitForDeployment: true,
51
67
  httpVersion: 'http2and3',
52
68
  viewerCertificate: {
53
- acmCertificateArn: certificate.certificate.arn,
69
+ acmCertificateArn: this.certificate.certificate.arn,
54
70
  sslSupportMethod: 'sni-only',
55
71
  minimumProtocolVersion: 'TLSv1.2_2021',
56
72
  },
57
73
  origins: [
58
74
  {
59
- originId: bucket.arn,
60
- domainName: bucket.websiteEndpoint,
75
+ originId: this.bucket.arn,
76
+ domainName: this.bucket.websiteEndpoint,
61
77
  connectionAttempts: 3,
62
78
  connectionTimeout: 10,
63
79
  customOriginConfig: {
@@ -69,7 +85,7 @@ class StaticSite extends pulumi.ComponentResource {
69
85
  },
70
86
  ],
71
87
  defaultCacheBehavior: {
72
- targetOriginId: bucket.arn,
88
+ targetOriginId: this.bucket.arn,
73
89
  viewerProtocolPolicy: 'redirect-to-https',
74
90
  allowedMethods: ['GET', 'HEAD', 'OPTIONS'],
75
91
  cachedMethods: ['GET', 'HEAD', 'OPTIONS'],
@@ -86,24 +102,24 @@ class StaticSite extends pulumi.ComponentResource {
86
102
  restrictions: {
87
103
  geoRestriction: { restrictionType: 'none' },
88
104
  },
89
- tags: args.tags,
105
+ tags,
90
106
  }, { parent: this });
91
- const cdnAliasRecord = new aws.route53.Record(`${name}-cdn-route53-record`, {
107
+ return cloudfront;
108
+ }
109
+ createDnsRecord({ domain, hostedZoneId, }) {
110
+ const cdnAliasRecord = new aws.route53.Record(`${this.name}-cdn-route53-record`, {
92
111
  type: 'A',
93
- name: args.domain,
94
- zoneId: args.hostedZoneId,
112
+ name: domain,
113
+ zoneId: hostedZoneId,
95
114
  aliases: [
96
115
  {
97
- name: cloudfront.domainName,
98
- zoneId: cloudfront.hostedZoneId,
116
+ name: this.cloudfront.domainName,
117
+ zoneId: this.cloudfront.hostedZoneId,
99
118
  evaluateTargetHealth: true,
100
119
  },
101
120
  ],
102
121
  }, { parent: this });
103
- this.certificate = certificate;
104
- this.bucket = bucket;
105
- this.cloudfront = cloudfront;
106
- this.registerOutputs();
122
+ return cdnAliasRecord;
107
123
  }
108
124
  }
109
125
  exports.StaticSite = StaticSite;
@@ -1,7 +1,7 @@
1
1
  import * as pulumi from '@pulumi/pulumi';
2
2
  import * as aws from '@pulumi/aws';
3
3
  import * as awsx from '@pulumi/awsx';
4
- import { Size } from './types';
4
+ import { Size } from '../types/size';
5
5
  import { AcmCertificate } from './acm-certificate';
6
6
  export type RoleInlinePolicy = {
7
7
  /**
@@ -85,6 +85,7 @@ export type WebServerArgs = {
85
85
  }>;
86
86
  };
87
87
  export declare class WebServer extends pulumi.ComponentResource {
88
+ name: string;
88
89
  certificate: AcmCertificate;
89
90
  logGroup: aws.cloudwatch.LogGroup;
90
91
  lbSecurityGroup: aws.ec2.SecurityGroup;
@@ -92,8 +93,14 @@ export declare class WebServer extends pulumi.ComponentResource {
92
93
  lbTargetGroup: aws.lb.TargetGroup;
93
94
  lbHttpListener: aws.lb.Listener;
94
95
  lbTlsListener: aws.lb.Listener;
95
- serviceSecurityGroup: aws.ec2.SecurityGroup;
96
96
  taskDefinition: aws.ecs.TaskDefinition;
97
97
  service: aws.ecs.Service;
98
98
  constructor(name: string, args: WebServerArgs, opts?: pulumi.ComponentResourceOptions);
99
+ private createTlsCertificate;
100
+ private createLogGroup;
101
+ private createLoadBalancer;
102
+ private createTaskDefinition;
103
+ private createEcsService;
104
+ private createDnsRecord;
105
+ private enableAutoscaling;
99
106
  }
@@ -34,17 +34,39 @@ const defaults = {
34
34
  class WebServer extends pulumi.ComponentResource {
35
35
  constructor(name, args, opts = {}) {
36
36
  super('studion:WebServer', name, {}, opts);
37
- const argsWithDefaults = Object.assign({}, defaults, args);
38
- this.certificate = new acm_certificate_1.AcmCertificate(`${argsWithDefaults.domain}-acm-certificate`, {
39
- domain: argsWithDefaults.domain,
40
- hostedZoneId: argsWithDefaults.hostedZoneId,
37
+ this.name = name;
38
+ const { domain, hostedZoneId, vpc, port, healtCheckPath } = args;
39
+ this.certificate = this.createTlsCertificate({ domain, hostedZoneId });
40
+ this.logGroup = this.createLogGroup();
41
+ const { lb, lbTargetGroup, lbHttpListener, lbTlsListener, lbSecurityGroup, } = this.createLoadBalancer({ vpc, port, healtCheckPath });
42
+ this.lb = lb;
43
+ this.lbTargetGroup = lbTargetGroup;
44
+ this.lbHttpListener = lbHttpListener;
45
+ this.lbTlsListener = lbTlsListener;
46
+ this.lbSecurityGroup = lbSecurityGroup;
47
+ this.taskDefinition = this.createTaskDefinition(args);
48
+ this.service = this.createEcsService(args);
49
+ this.createDnsRecord({ domain, hostedZoneId });
50
+ this.enableAutoscaling(args);
51
+ this.registerOutputs();
52
+ }
53
+ createTlsCertificate({ domain, hostedZoneId, }) {
54
+ const certificate = new acm_certificate_1.AcmCertificate(`${domain}-acm-certificate`, {
55
+ domain,
56
+ hostedZoneId,
41
57
  }, { parent: this });
42
- this.logGroup = new aws.cloudwatch.LogGroup(`${name}-log-group`, {
58
+ return certificate;
59
+ }
60
+ createLogGroup() {
61
+ const logGroup = new aws.cloudwatch.LogGroup(`${this.name}-log-group`, {
43
62
  retentionInDays: 14,
44
- name: `/ecs/${name}`,
63
+ namePrefix: `/ecs/${this.name}-`,
45
64
  }, { parent: this });
46
- this.lbSecurityGroup = new aws.ec2.SecurityGroup(`${name}-lb-security-group`, {
47
- vpcId: argsWithDefaults.vpc.vpcId,
65
+ return logGroup;
66
+ }
67
+ createLoadBalancer({ vpc, port, healtCheckPath, }) {
68
+ const lbSecurityGroup = new aws.ec2.SecurityGroup(`${this.name}-lb-security-group`, {
69
+ vpcId: vpc.vpcId,
48
70
  ingress: [
49
71
  {
50
72
  protocol: 'tcp',
@@ -68,29 +90,29 @@ class WebServer extends pulumi.ComponentResource {
68
90
  },
69
91
  ],
70
92
  }, { parent: this });
71
- this.lb = new aws.lb.LoadBalancer(`${name}-lb`, {
72
- name: `${name}-lb`,
93
+ const lb = new aws.lb.LoadBalancer(`${this.name}-lb`, {
94
+ namePrefix: `${this.name}-lb-`,
73
95
  loadBalancerType: 'application',
74
- subnets: argsWithDefaults.vpc.publicSubnetIds,
75
- securityGroups: [this.lbSecurityGroup.id],
96
+ subnets: vpc.publicSubnetIds,
97
+ securityGroups: [lbSecurityGroup.id],
76
98
  internal: false,
77
99
  ipAddressType: 'ipv4',
78
100
  }, { parent: this });
79
- this.lbTargetGroup = new aws.lb.TargetGroup(`${name}-lb-tg`, {
80
- name: `${name}-lb-tg`,
81
- port: argsWithDefaults.port,
101
+ const lbTargetGroup = new aws.lb.TargetGroup(`${this.name}-lb-tg`, {
102
+ namePrefix: `${this.name}-lb-tg-`,
103
+ port,
82
104
  protocol: 'HTTP',
83
105
  targetType: 'ip',
84
- vpcId: argsWithDefaults.vpc.vpcId,
106
+ vpcId: vpc.vpcId,
85
107
  healthCheck: {
86
108
  healthyThreshold: 3,
87
109
  unhealthyThreshold: 2,
88
110
  interval: 60,
89
111
  timeout: 5,
90
- path: argsWithDefaults.healtCheckPath,
112
+ path: healtCheckPath || defaults.healtCheckPath,
91
113
  },
92
114
  }, { parent: this, dependsOn: [this.lb] });
93
- this.lbHttpListener = new aws.lb.Listener(`${name}-lb-listener-80`, {
115
+ const lbHttpListener = new aws.lb.Listener(`${this.name}-lb-listener-80`, {
94
116
  loadBalancerArn: this.lb.arn,
95
117
  port: 80,
96
118
  defaultActions: [
@@ -104,7 +126,7 @@ class WebServer extends pulumi.ComponentResource {
104
126
  },
105
127
  ],
106
128
  }, { parent: this });
107
- this.lbTlsListener = new aws.lb.Listener(`${name}-lb-listener-443`, {
129
+ const lbTlsListener = new aws.lb.Listener(`${this.name}-lb-listener-443`, {
108
130
  loadBalancerArn: this.lb.arn,
109
131
  port: 443,
110
132
  protocol: 'HTTPS',
@@ -117,20 +139,18 @@ class WebServer extends pulumi.ComponentResource {
117
139
  },
118
140
  ],
119
141
  }, { parent: this });
120
- const albAliasRecord = new aws.route53.Record(`${name}-route53-record`, {
121
- type: 'A',
122
- name: argsWithDefaults.domain,
123
- zoneId: argsWithDefaults.hostedZoneId,
124
- aliases: [
125
- {
126
- name: this.lb.dnsName,
127
- zoneId: this.lb.zoneId,
128
- evaluateTargetHealth: true,
129
- },
130
- ],
131
- }, { parent: this });
142
+ return {
143
+ lb,
144
+ lbTargetGroup,
145
+ lbHttpListener,
146
+ lbTlsListener,
147
+ lbSecurityGroup,
148
+ };
149
+ }
150
+ createTaskDefinition(args) {
151
+ const argsWithDefaults = Object.assign({}, defaults, args);
132
152
  const secretManagerSecretsInlinePolicy = {
133
- name: `${name}-secret-manager-access`,
153
+ name: `${this.name}-secret-manager-access`,
134
154
  policy: JSON.stringify({
135
155
  Version: '2012-10-17',
136
156
  Statement: [
@@ -143,8 +163,8 @@ class WebServer extends pulumi.ComponentResource {
143
163
  ],
144
164
  }),
145
165
  };
146
- const taskExecutionRole = new aws.iam.Role(`${name}-ecs-task-exec-role`, {
147
- name: `${name}-ecs-task-exec-role`,
166
+ const taskExecutionRole = new aws.iam.Role(`${this.name}-ecs-task-exec-role`, {
167
+ namePrefix: `${this.name}-ecs-task-exec-role-`,
148
168
  assumeRolePolicy,
149
169
  managedPolicyArns: [
150
170
  'arn:aws:iam::aws:policy/CloudWatchFullAccess',
@@ -156,7 +176,7 @@ class WebServer extends pulumi.ComponentResource {
156
176
  ],
157
177
  }, { parent: this });
158
178
  const execCmdInlinePolicy = {
159
- name: `${name}-ecs-exec`,
179
+ name: `${this.name}-ecs-exec`,
160
180
  policy: JSON.stringify({
161
181
  Version: '2012-10-17',
162
182
  Statement: [
@@ -174,8 +194,8 @@ class WebServer extends pulumi.ComponentResource {
174
194
  ],
175
195
  }),
176
196
  };
177
- const taskRole = new aws.iam.Role(`${name}-ecs-task-role`, {
178
- name: `${name}-ecs-task-role`,
197
+ const taskRole = new aws.iam.Role(`${this.name}-ecs-task-role`, {
198
+ namePrefix: `${this.name}-ecs-task-role-`,
179
199
  assumeRolePolicy,
180
200
  inlinePolicies: [
181
201
  execCmdInlinePolicy,
@@ -195,8 +215,8 @@ class WebServer extends pulumi.ComponentResource {
195
215
  }
196
216
  throw Error('Incorrect EcsService size argument');
197
217
  });
198
- this.taskDefinition = new aws.ecs.TaskDefinition(`${name}-task-definition`, {
199
- family: `${name}-task-definition`,
218
+ const taskDefinition = new aws.ecs.TaskDefinition(`${this.name}-task-definition`, {
219
+ family: `${this.name}-task-definition`,
200
220
  networkMode: 'awsvpc',
201
221
  executionRoleArn: taskExecutionRole.arn,
202
222
  taskRoleArn: taskRole.arn,
@@ -205,7 +225,7 @@ class WebServer extends pulumi.ComponentResource {
205
225
  requiresCompatibilities: ['FARGATE'],
206
226
  containerDefinitions: pulumi
207
227
  .all([
208
- name,
228
+ this.name,
209
229
  argsWithDefaults.image,
210
230
  argsWithDefaults.port,
211
231
  argsWithDefaults.environment,
@@ -241,7 +261,11 @@ class WebServer extends pulumi.ComponentResource {
241
261
  }),
242
262
  tags: argsWithDefaults.tags,
243
263
  }, { parent: this });
244
- this.serviceSecurityGroup = new aws.ec2.SecurityGroup(`${name}-security-group`, {
264
+ return taskDefinition;
265
+ }
266
+ createEcsService(args) {
267
+ const argsWithDefaults = Object.assign({}, defaults, args);
268
+ const serviceSecurityGroup = new aws.ec2.SecurityGroup(`${this.name}-security-group`, {
245
269
  vpcId: argsWithDefaults.vpc.vpcId,
246
270
  ingress: [
247
271
  {
@@ -260,8 +284,8 @@ class WebServer extends pulumi.ComponentResource {
260
284
  },
261
285
  ],
262
286
  }, { parent: this });
263
- this.service = new aws.ecs.Service(`${name}-service`, {
264
- name,
287
+ const service = new aws.ecs.Service(`${this.name}-service`, {
288
+ name: this.name,
265
289
  cluster: argsWithDefaults.cluster.id,
266
290
  launchType: 'FARGATE',
267
291
  desiredCount: argsWithDefaults.desiredCount,
@@ -269,7 +293,7 @@ class WebServer extends pulumi.ComponentResource {
269
293
  enableExecuteCommand: true,
270
294
  loadBalancers: [
271
295
  {
272
- containerName: name,
296
+ containerName: this.name,
273
297
  containerPort: argsWithDefaults.port,
274
298
  targetGroupArn: this.lbTargetGroup.arn,
275
299
  },
@@ -277,7 +301,7 @@ class WebServer extends pulumi.ComponentResource {
277
301
  networkConfiguration: {
278
302
  assignPublicIp: true,
279
303
  subnets: argsWithDefaults.vpc.publicSubnetIds,
280
- securityGroups: [this.serviceSecurityGroup.id],
304
+ securityGroups: [serviceSecurityGroup.id],
281
305
  },
282
306
  tags: argsWithDefaults.tags,
283
307
  }, {
@@ -289,14 +313,32 @@ class WebServer extends pulumi.ComponentResource {
289
313
  this.lbTlsListener,
290
314
  ],
291
315
  });
292
- const autoscalingTarget = new aws.appautoscaling.Target(`${name}-autoscale-target`, {
316
+ return service;
317
+ }
318
+ createDnsRecord({ domain, hostedZoneId, }) {
319
+ const albAliasRecord = new aws.route53.Record(`${this.name}-route53-record`, {
320
+ type: 'A',
321
+ name: domain,
322
+ zoneId: hostedZoneId,
323
+ aliases: [
324
+ {
325
+ name: this.lb.dnsName,
326
+ zoneId: this.lb.zoneId,
327
+ evaluateTargetHealth: true,
328
+ },
329
+ ],
330
+ }, { parent: this });
331
+ }
332
+ enableAutoscaling(args) {
333
+ const argsWithDefaults = Object.assign({}, defaults, args);
334
+ const autoscalingTarget = new aws.appautoscaling.Target(`${this.name}-autoscale-target`, {
293
335
  minCapacity: argsWithDefaults.minCount,
294
336
  maxCapacity: argsWithDefaults.maxCount,
295
337
  resourceId: pulumi.interpolate `service/${argsWithDefaults.cluster.name}/${this.service.name}`,
296
338
  serviceNamespace: 'ecs',
297
339
  scalableDimension: 'ecs:service:DesiredCount',
298
340
  }, { parent: this });
299
- const memoryAutoscalingPolicy = new aws.appautoscaling.Policy(`${name}-memory-autoscale-policy`, {
341
+ const memoryAutoscalingPolicy = new aws.appautoscaling.Policy(`${this.name}-memory-autoscale-policy`, {
300
342
  policyType: 'TargetTrackingScaling',
301
343
  resourceId: autoscalingTarget.resourceId,
302
344
  scalableDimension: autoscalingTarget.scalableDimension,
@@ -308,7 +350,7 @@ class WebServer extends pulumi.ComponentResource {
308
350
  targetValue: 80,
309
351
  },
310
352
  }, { parent: this });
311
- const cpuAutoscalingPolicy = new aws.appautoscaling.Policy(`${name}-cpu-autoscale-policy`, {
353
+ const cpuAutoscalingPolicy = new aws.appautoscaling.Policy(`${this.name}-cpu-autoscale-policy`, {
312
354
  policyType: 'TargetTrackingScaling',
313
355
  resourceId: autoscalingTarget.resourceId,
314
356
  scalableDimension: autoscalingTarget.scalableDimension,
@@ -320,7 +362,6 @@ class WebServer extends pulumi.ComponentResource {
320
362
  targetValue: 60,
321
363
  },
322
364
  }, { parent: this });
323
- this.registerOutputs();
324
365
  }
325
366
  }
326
367
  exports.WebServer = WebServer;
@@ -16,3 +16,8 @@ export declare const PredefinedSize: {
16
16
  readonly memory: number;
17
17
  };
18
18
  };
19
+ export declare const Ec2AMI: {
20
+ AmazonLinux2023: {
21
+ ARM: string;
22
+ };
23
+ };
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PredefinedSize = void 0;
3
+ exports.Ec2AMI = exports.PredefinedSize = void 0;
4
4
  const CPU_1_VCPU = 1024;
5
5
  const MEMORY_1GB = 1024;
6
6
  exports.PredefinedSize = {
@@ -21,3 +21,8 @@ exports.PredefinedSize = {
21
21
  memory: MEMORY_1GB * 4, // 4 GB memory
22
22
  },
23
23
  };
24
+ exports.Ec2AMI = {
25
+ AmazonLinux2023: {
26
+ ARM: 'ami-0b40baa8c6b882e6c',
27
+ },
28
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studion/infra-code-blocks",
3
- "version": "0.0.11",
3
+ "version": "0.1.0",
4
4
  "description": "Studion common infra components",
5
5
  "keywords": [
6
6
  "infrastructure",
File without changes
File without changes