@studion/infra-code-blocks 0.1.8 → 0.1.9

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
@@ -4,9 +4,15 @@ Studion Platform common infra components.
4
4
 
5
5
  ## Table of Contents
6
6
 
7
- 1. [Installation](#installation)
8
- 2. [Usage](#usage)
9
- 3. [API](#api)
7
+ 1. [Prerequisites](#prerequisites)
8
+ 2. [Installation](#installation)
9
+ 3. [Usage](#usage)
10
+ 4. [API](#api)
11
+
12
+ ## Prerequisites
13
+
14
+ - Working [Pulumi](https://www.pulumi.com/docs/clouds/aws/get-started/begin/#pulumi-aws-before-you-begin) project
15
+ - AWS account with neccessary permissions for each studion component
10
16
 
11
17
  ## Installation
12
18
 
@@ -42,6 +48,12 @@ const project = new studion.Project('demo-project', {
42
48
  export const projectName = project.name;
43
49
  ```
44
50
 
51
+ - Deploy pulumi stack
52
+
53
+ ```bash
54
+ $ pulumi up
55
+ ```
56
+
45
57
  ## API
46
58
 
47
59
  1. [Project](#project)
@@ -83,7 +95,7 @@ type ProjectArgs = {
83
95
  | Argument | Description |
84
96
  | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------: |
85
97
  | services \* | Service list. |
86
- | hostedZoneId | Route53 hosted zone ID responsible for managing records for the domain. |
98
+ | hostedZoneId | Route53 hosted zone ID responsible for managing records for the domain. Required for 'STATIC_SITE' and 'WEB_SERVER' |
87
99
  | enableSSMConnect | Setup ec2 instance and SSM in order to connect to the database in the private subnet. Please refer to the [SSM Connect](#ssm-connect) section for more info. |
88
100
 
89
101
  ```ts
@@ -92,7 +104,7 @@ type DatabaseService = {
92
104
  serviceName: string;
93
105
  dbName: pulumi.Input<string>;
94
106
  username: pulumi.Input<string>;
95
- password: pulumi.Input<string>;
107
+ password?: pulumi.Input<string>;
96
108
  applyImmediately?: pulumi.Input<boolean>;
97
109
  skipFinalSnapshot?: pulumi.Input<boolean>;
98
110
  allocatedStorage?: pulumi.Input<number>;
@@ -117,7 +129,7 @@ export type RedisService = {
117
129
  export type StaticSiteService = {
118
130
  type: 'STATIC_SITE';
119
131
  serviceName: string;
120
- domain: pulumi.Input<string>;
132
+ domain?: pulumi.Input<string>;
121
133
  tags?: pulumi.Input<{
122
134
  [key: string]: pulumi.Input<string>;
123
135
  }>;
@@ -256,8 +268,8 @@ new Database(name: string, args: DatabaseArgs, opts?: pulumi.CustomResourceOptio
256
268
  type DatabaseArgs = {
257
269
  dbName: pulumi.Input<string>;
258
270
  username: pulumi.Input<string>;
259
- password: pulumi.Input<string>;
260
271
  vpc: awsx.ec2.Vpc;
272
+ password?: pulumi.Input<string>;
261
273
  applyImmediately?: pulumi.Input<boolean>;
262
274
  skipFinalSnapshot?: pulumi.Input<boolean>;
263
275
  allocatedStorage?: pulumi.Input<number>;
@@ -269,6 +281,7 @@ type DatabaseArgs = {
269
281
  };
270
282
  ```
271
283
 
284
+ If the password is not specified it will be autogenerated.
272
285
  The database password is stored as a secret inside AWS Secret Manager.
273
286
  The secret will be available on the `Database` resource as `passwordSecret`.
274
287
 
@@ -341,8 +354,8 @@ new StaticSite(name: string, args: StaticSiteArgs, opts?: pulumi.ComponentResour
341
354
 
342
355
  ```ts
343
356
  type StaticSiteArgs = {
344
- domain: pulumi.Input<string>;
345
- hostedZoneId: pulumi.Input<string>;
357
+ domain?: pulumi.Input<string>;
358
+ hostedZoneId?: pulumi.Input<string>;
346
359
  tags?: pulumi.Input<{
347
360
  [key: string]: pulumi.Input<string>;
348
361
  }>;
@@ -10,15 +10,15 @@ export type DatabaseArgs = {
10
10
  * Username for the master DB user.
11
11
  */
12
12
  username: pulumi.Input<string>;
13
- /**
14
- * Password for the master DB user.
15
- * The value will be stored as a secret in AWS Secret Manager.
16
- */
17
- password: pulumi.Input<string>;
18
13
  /**
19
14
  * The awsx.ec2.Vpc resource.
20
15
  */
21
16
  vpc: awsx.ec2.Vpc;
17
+ /**
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.
20
+ */
21
+ password?: pulumi.Input<string>;
22
22
  /**
23
23
  * Specifies whether any database modifications are applied immediately, or during the next maintenance window. Default is false.
24
24
  */
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Database = void 0;
4
4
  const aws = require("@pulumi/aws");
5
5
  const pulumi = require("@pulumi/pulumi");
6
+ const random = require("@pulumi/random");
6
7
  const constants_1 = require("../constants");
7
8
  const defaults = {
8
9
  applyImmediately: false,
@@ -15,12 +16,13 @@ class Database extends pulumi.ComponentResource {
15
16
  constructor(name, args, opts = {}) {
16
17
  super('studion:Database', name, {}, opts);
17
18
  this.name = name;
18
- const { vpc, password } = args;
19
+ const { vpc } = args;
19
20
  this.dbSubnetGroup = this.createSubnetGroup({ vpc });
20
21
  this.dbSecurityGroup = this.createSecurityGroup({ vpc });
21
22
  this.kms = this.createEncryptionKey();
22
- this.passwordSecret = this.createPasswordSecret({ password });
23
- this.instance = this.createDatabaseInstance(args);
23
+ const { instance, passwordSecret } = this.createDatabaseInstance(args);
24
+ this.instance = instance;
25
+ this.passwordSecret = passwordSecret;
24
26
  this.registerOutputs();
25
27
  }
26
28
  createSubnetGroup({ vpc }) {
@@ -73,16 +75,23 @@ class Database extends pulumi.ComponentResource {
73
75
  createDatabaseInstance(args) {
74
76
  const argsWithDefaults = Object.assign({}, defaults, args);
75
77
  const stack = pulumi.getStack();
78
+ const password = argsWithDefaults.password ||
79
+ new random.RandomPassword(`${this.name}-db-password`, {
80
+ length: 16,
81
+ overrideSpecial: '_%$',
82
+ special: true,
83
+ }).result;
84
+ const passwordSecret = this.createPasswordSecret({ password });
76
85
  const instance = new aws.rds.Instance(`${this.name}-rds`, {
77
86
  identifierPrefix: `${this.name}-`,
78
87
  engine: 'postgres',
79
- engineVersion: '14.9',
88
+ engineVersion: '15.3',
80
89
  allocatedStorage: argsWithDefaults.allocatedStorage,
81
90
  maxAllocatedStorage: argsWithDefaults.maxAllocatedStorage,
82
91
  instanceClass: argsWithDefaults.instanceClass,
83
92
  dbName: argsWithDefaults.dbName,
84
93
  username: argsWithDefaults.username,
85
- password: argsWithDefaults.password,
94
+ password,
86
95
  dbSubnetGroupName: this.dbSubnetGroup.name,
87
96
  vpcSecurityGroupIds: [this.dbSecurityGroup.id],
88
97
  storageEncrypted: true,
@@ -97,7 +106,7 @@ class Database extends pulumi.ComponentResource {
97
106
  backupRetentionPeriod: 14,
98
107
  tags: Object.assign(Object.assign({}, constants_1.commonTags), argsWithDefaults.tags),
99
108
  }, { parent: this });
100
- return instance;
109
+ return { instance, passwordSecret };
101
110
  }
102
111
  }
103
112
  exports.Database = Database;
@@ -6,6 +6,17 @@ const aws = require("@pulumi/aws");
6
6
  const constants_1 = require("../constants");
7
7
  const config = new pulumi.Config('aws');
8
8
  const awsRegion = config.require('region');
9
+ const AmazonLinux2023_ARM_EC2_AMI = aws.ec2.getAmiOutput({
10
+ filters: [
11
+ { name: 'architecture', values: ['arm64'] },
12
+ { name: 'root-device-type', values: ['ebs'] },
13
+ { name: 'virtualization-type', values: ['hvm'] },
14
+ { name: 'ena-support', values: ['true'] },
15
+ ],
16
+ owners: ['amazon'],
17
+ nameRegex: 'al2023-ami-2023.2.20231030.1-kernel-6.1-arm64',
18
+ mostRecent: true,
19
+ });
9
20
  class Ec2SSMConnect extends pulumi.ComponentResource {
10
21
  constructor(name, args, opts = {}) {
11
22
  super('studion:Ec2BastionSSMConnect', name, {}, opts);
@@ -55,7 +66,7 @@ class Ec2SSMConnect extends pulumi.ComponentResource {
55
66
  tags: constants_1.commonTags,
56
67
  }, { parent: this, dependsOn: [ssmPolicyAttachment] });
57
68
  this.ec2 = new aws.ec2.Instance(`${name}-ec2`, {
58
- ami: constants_1.Ec2AMI.AmazonLinux2023.ARM,
69
+ ami: AmazonLinux2023_ARM_EC2_AMI.id,
59
70
  associatePublicIpAddress: false,
60
71
  instanceType: 't4g.nano',
61
72
  iamInstanceProfile: ssmProfile.name,
@@ -109,8 +109,6 @@ class Project extends pulumi.ComponentResource {
109
109
  }
110
110
  createStaticSiteService(options) {
111
111
  const { serviceName } = options, staticSiteOptions = __rest(options, ["serviceName"]);
112
- if (!this.hostedZoneId)
113
- throw new MissingHostedZoneId(options.type);
114
112
  const service = new static_site_1.StaticSite(serviceName, Object.assign(Object.assign({}, staticSiteOptions), { hostedZoneId: this.hostedZoneId }), { parent: this });
115
113
  this.services[serviceName] = service;
116
114
  }
@@ -6,11 +6,11 @@ export type StaticSiteArgs = {
6
6
  * The domain which will be used to access the static site.
7
7
  * The domain or subdomain must belong to the provided hostedZone.
8
8
  */
9
- domain: pulumi.Input<string>;
9
+ domain?: pulumi.Input<string>;
10
10
  /**
11
11
  * The ID of the hosted zone.
12
12
  */
13
- hostedZoneId: pulumi.Input<string>;
13
+ hostedZoneId?: pulumi.Input<string>;
14
14
  /**
15
15
  * A map of tags to assign to the resource.
16
16
  */
@@ -20,7 +20,7 @@ export type StaticSiteArgs = {
20
20
  };
21
21
  export declare class StaticSite extends pulumi.ComponentResource {
22
22
  name: string;
23
- certificate: AcmCertificate;
23
+ certificate?: AcmCertificate;
24
24
  bucket: aws.s3.Bucket;
25
25
  cloudfront: aws.cloudfront.Distribution;
26
26
  constructor(name: string, args: StaticSiteArgs, opts?: pulumi.ComponentResourceOptions);
@@ -10,10 +10,18 @@ class StaticSite extends pulumi.ComponentResource {
10
10
  super('studion:StaticSite', name, {}, opts);
11
11
  this.name = name;
12
12
  const { domain, hostedZoneId, tags } = args;
13
- this.certificate = this.createTlsCertificate({ domain, hostedZoneId });
13
+ const hasCustomDomain = domain && hostedZoneId;
14
+ if (domain && !hostedZoneId) {
15
+ throw new Error('StaticSite:hostedZoneId must be provided when the domain is specified');
16
+ }
17
+ if (hasCustomDomain) {
18
+ this.certificate = this.createTlsCertificate({ domain, hostedZoneId });
19
+ }
14
20
  this.bucket = this.createPublicBucket({ tags });
15
21
  this.cloudfront = this.createCloudfrontDistribution({ domain, tags });
16
- this.createDnsRecord({ domain, hostedZoneId });
22
+ if (hasCustomDomain) {
23
+ this.createDnsRecord({ domain, hostedZoneId });
24
+ }
17
25
  this.registerOutputs();
18
26
  }
19
27
  createTlsCertificate({ domain, hostedZoneId, }) {
@@ -59,19 +67,15 @@ class StaticSite extends pulumi.ComponentResource {
59
67
  return bucket;
60
68
  }
61
69
  createCloudfrontDistribution({ domain, tags, }) {
62
- const cloudfront = new aws.cloudfront.Distribution(`${this.name}-cloudfront`, {
63
- enabled: true,
64
- defaultRootObject: 'index.html',
65
- aliases: [domain],
66
- isIpv6Enabled: true,
67
- waitForDeployment: true,
68
- httpVersion: 'http2and3',
69
- viewerCertificate: {
70
- acmCertificateArn: this.certificate.certificate.arn,
71
- sslSupportMethod: 'sni-only',
72
- minimumProtocolVersion: 'TLSv1.2_2021',
73
- },
74
- origins: [
70
+ const cloudfront = new aws.cloudfront.Distribution(`${this.name}-cloudfront`, Object.assign(Object.assign({ enabled: true, defaultRootObject: 'index.html' }, (domain && { aliases: [domain] })), { isIpv6Enabled: true, waitForDeployment: true, httpVersion: 'http2and3', viewerCertificate: Object.assign({}, (this.certificate
71
+ ? {
72
+ acmCertificateArn: this.certificate.certificate.arn,
73
+ sslSupportMethod: 'sni-only',
74
+ minimumProtocolVersion: 'TLSv1.2_2021',
75
+ }
76
+ : {
77
+ cloudfrontDefaultCertificate: true,
78
+ })), origins: [
75
79
  {
76
80
  originId: this.bucket.arn,
77
81
  domainName: this.bucket.websiteEndpoint,
@@ -84,8 +88,7 @@ class StaticSite extends pulumi.ComponentResource {
84
88
  originSslProtocols: ['TLSv1.2'],
85
89
  },
86
90
  },
87
- ],
88
- defaultCacheBehavior: {
91
+ ], defaultCacheBehavior: {
89
92
  targetOriginId: this.bucket.arn,
90
93
  viewerProtocolPolicy: 'redirect-to-https',
91
94
  allowedMethods: ['GET', 'HEAD', 'OPTIONS'],
@@ -98,13 +101,9 @@ class StaticSite extends pulumi.ComponentResource {
98
101
  cookies: { forward: 'none' },
99
102
  queryString: false,
100
103
  },
101
- },
102
- priceClass: 'PriceClass_100',
103
- restrictions: {
104
+ }, priceClass: 'PriceClass_100', restrictions: {
104
105
  geoRestriction: { restrictionType: 'none' },
105
- },
106
- tags: Object.assign(Object.assign({}, constants_1.commonTags), tags),
107
- }, { parent: this });
106
+ }, tags: Object.assign(Object.assign({}, constants_1.commonTags), tags) }), { parent: this });
108
107
  return cloudfront;
109
108
  }
110
109
  createDnsRecord({ domain, hostedZoneId, }) {
@@ -16,11 +16,6 @@ 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
- };
24
19
  export declare const commonTags: {
25
20
  Env: string;
26
21
  Project: string;
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.commonTags = exports.Ec2AMI = exports.PredefinedSize = void 0;
3
+ exports.commonTags = exports.PredefinedSize = void 0;
4
4
  const pulumi = require("@pulumi/pulumi");
5
5
  const CPU_1_VCPU = 1024;
6
6
  const MEMORY_1GB = 1024;
@@ -22,11 +22,6 @@ exports.PredefinedSize = {
22
22
  memory: MEMORY_1GB * 4, // 4 GB memory
23
23
  },
24
24
  };
25
- exports.Ec2AMI = {
26
- AmazonLinux2023: {
27
- ARM: 'ami-0b40baa8c6b882e6c',
28
- },
29
- };
30
25
  exports.commonTags = {
31
26
  Env: pulumi.getStack(),
32
27
  Project: pulumi.getProject(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studion/infra-code-blocks",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Studion common infra components",
5
5
  "keywords": [
6
6
  "infrastructure",
@@ -35,6 +35,7 @@
35
35
  "@pulumi/aws": "^5.0.0",
36
36
  "@pulumi/awsx": "^1.0.0",
37
37
  "@pulumi/pulumi": "^3.0.0",
38
+ "@pulumi/random": "^4.14.0",
38
39
  "@upstash/pulumi": "^0.2.0"
39
40
  },
40
41
  "devDependencies": {