@studion/infra-code-blocks 0.0.9 → 0.0.11

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>;
@@ -131,7 +131,7 @@ export type WebServerService = {
131
131
  environment?:
132
132
  | aws.ecs.KeyValuePair[]
133
133
  | ((services: Services) => aws.ecs.KeyValuePair[]);
134
- secrets?: aws.ecs.Secret[];
134
+ secrets?: aws.ecs.Secret[] | ((services: Services) => aws.ecs.Secret[]);
135
135
  image: pulumi.Input<string>;
136
136
  port: pulumi.Input<number>;
137
137
  domain: pulumi.Input<string>;
@@ -203,6 +203,33 @@ const project = new studion.Project('demo-project', {
203
203
  });
204
204
  ```
205
205
 
206
+ ```ts
207
+ const project = new studion.Project('demo-project', {
208
+ environment: 'DEVELOPMENT',
209
+ services: [
210
+ {
211
+ type: 'REDIS',
212
+ serviceName: 'redis',
213
+ dbName: 'test-db',
214
+ },
215
+ {
216
+ type: 'WEB_SERVER',
217
+ serviceName: 'api',
218
+ image: imageUri,
219
+ port: 3000,
220
+ domain: 'api.my-domain.com',
221
+ secrets: (services: Services) => {
222
+ const redisServiceName = 'redis';
223
+ const redis = services[redisServiceName];
224
+ return [
225
+ { name: 'REDIS_PASSWORD', valueFrom: redis.passwordSecret.arn },
226
+ ];
227
+ },
228
+ },
229
+ ],
230
+ });
231
+ ```
232
+
206
233
  ### Database
207
234
 
208
235
  AWS RDS Postgres instance.
@@ -229,8 +256,8 @@ new Database(name: string, args: DatabaseArgs, opts?: pulumi.CustomResourceOptio
229
256
  type DatabaseArgs = {
230
257
  dbName: pulumi.Input<string>;
231
258
  username: pulumi.Input<string>;
232
- password: pulumi.Input<string>;
233
259
  vpc: awsx.ec2.Vpc;
260
+ password?: pulumi.Input<string>;
234
261
  applyImmediately?: pulumi.Input<boolean>;
235
262
  skipFinalSnapshot?: pulumi.Input<boolean>;
236
263
  allocatedStorage?: pulumi.Input<number>;
@@ -242,6 +269,10 @@ type DatabaseArgs = {
242
269
  };
243
270
  ```
244
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`.
275
+
245
276
  ### Redis
246
277
 
247
278
  [Upstash](https://upstash.com) Redis instance.
@@ -283,6 +314,9 @@ interface RedisOptions extends pulumi.ComponentResourceOptions {
283
314
  }
284
315
  ```
285
316
 
317
+ After creating the Redis resource, the `passwordSecret` AWS Secret Manager Secret
318
+ will exist on the resource.
319
+
286
320
  ### Static Site
287
321
 
288
322
  AWS S3 + Cloudfront static site.
@@ -467,4 +501,3 @@ const project = new studion.Project('demo-project', {
467
501
 
468
502
  - [ ] Add worker service for executing tasks
469
503
  - [ ] Add MongoDB service
470
- - [ ] Make db username & password fields optional and autogenerate db username & password if they are not provided
@@ -10,14 +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
- */
16
- password: pulumi.Input<string>;
17
13
  /**
18
14
  * The awsx.ec2.Vpc resource.
19
15
  */
20
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>;
21
22
  /**
22
23
  * Specifies whether any database modifications are applied immediately, or during the next maintenance window. Default is false.
23
24
  */
@@ -50,5 +51,6 @@ export declare class Database extends pulumi.ComponentResource {
50
51
  kms: aws.kms.Key;
51
52
  dbSubnetGroup: aws.rds.SubnetGroup;
52
53
  dbSecurityGroup: aws.ec2.SecurityGroup;
54
+ passwordSecret: aws.secretsmanager.Secret;
53
55
  constructor(name: string, args: DatabaseArgs, opts?: pulumi.ComponentResourceOptions);
54
56
  }
@@ -13,6 +13,8 @@ const defaults = {
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();
16
18
  const argsWithDefaults = Object.assign({}, defaults, args);
17
19
  this.dbSubnetGroup = new aws.rds.SubnetGroup(`${name}-subnet-group`, {
18
20
  subnetIds: argsWithDefaults.vpc.privateSubnetIds,
@@ -36,6 +38,17 @@ class Database extends pulumi.ComponentResource {
36
38
  multiRegion: false,
37
39
  enableKeyRotation: true,
38
40
  }, { 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`,
47
+ }, { parent: this });
48
+ const passwordSecretValue = new aws.secretsmanager.SecretVersion(`${name}-password-secret-value`, {
49
+ secretId: this.passwordSecret.id,
50
+ secretString: password,
51
+ }, { parent: this, dependsOn: [this.passwordSecret] });
39
52
  this.instance = new aws.rds.Instance(`${name}-rds`, {
40
53
  identifier: name,
41
54
  engine: 'postgres',
@@ -45,7 +58,7 @@ class Database extends pulumi.ComponentResource {
45
58
  instanceClass: argsWithDefaults.instanceClass,
46
59
  dbName: argsWithDefaults.dbName,
47
60
  username: argsWithDefaults.username,
48
- password: argsWithDefaults.password,
61
+ password,
49
62
  dbSubnetGroupName: this.dbSubnetGroup.name,
50
63
  vpcSecurityGroupIds: [this.dbSecurityGroup.id],
51
64
  storageEncrypted: true,
@@ -27,7 +27,8 @@ export type StaticSiteService = {
27
27
  export type WebServerService = {
28
28
  type: 'WEB_SERVER';
29
29
  environment?: aws.ecs.KeyValuePair[] | ((services: Services) => aws.ecs.KeyValuePair[]);
30
- } & ServiceArgs & Omit<WebServerArgs, 'cluster' | 'vpc' | 'hostedZoneId' | 'environment'>;
30
+ secrets?: aws.ecs.Secret[] | ((services: Services) => aws.ecs.Secret[]);
31
+ } & ServiceArgs & Omit<WebServerArgs, 'cluster' | 'vpc' | 'hostedZoneId' | 'environment' | 'secrets'>;
31
32
  export type ProjectArgs = {
32
33
  services: (DatabaseService | RedisService | StaticSiteService | WebServerService)[];
33
34
  hostedZoneId?: pulumi.Input<string>;
@@ -110,11 +110,12 @@ class Project extends pulumi.ComponentResource {
110
110
  return;
111
111
  if (!this.hostedZoneId)
112
112
  throw new MissingHostedZoneId(options.type);
113
- const { serviceName, environment } = options, ecsOptions = __rest(options, ["serviceName", "environment"]);
113
+ const { serviceName, environment, secrets } = options, ecsOptions = __rest(options, ["serviceName", "environment", "secrets"]);
114
114
  const parsedEnv = typeof environment === 'function'
115
115
  ? environment(this.services)
116
116
  : environment;
117
- const service = new web_server_1.WebServer(serviceName, Object.assign(Object.assign({}, ecsOptions), { cluster: this.cluster, vpc: this.vpc, hostedZoneId: this.hostedZoneId, environment: parsedEnv }), { parent: this });
117
+ const parsedSecrets = typeof secrets === 'function' ? secrets(this.services) : secrets;
118
+ 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 });
118
119
  this.services[options.serviceName] = service;
119
120
  }
120
121
  }
@@ -1,5 +1,6 @@
1
1
  import * as pulumi from '@pulumi/pulumi';
2
2
  import * as upstash from '@upstash/pulumi';
3
+ import * as aws from '@pulumi/aws';
3
4
  export type RedisArgs = {
4
5
  /**
5
6
  * Redis database name.
@@ -15,5 +16,7 @@ export interface RedisOptions extends pulumi.ComponentResourceOptions {
15
16
  }
16
17
  export declare class Redis extends pulumi.ComponentResource {
17
18
  instance: upstash.RedisDatabase;
19
+ passwordSecret: aws.secretsmanager.Secret;
20
+ username: string;
18
21
  constructor(name: string, args: RedisArgs, opts: RedisOptions);
19
22
  }
@@ -3,12 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Redis = void 0;
4
4
  const pulumi = require("@pulumi/pulumi");
5
5
  const upstash = require("@upstash/pulumi");
6
+ const aws = require("@pulumi/aws");
6
7
  const defaults = {
7
8
  region: 'us-east-1',
8
9
  };
9
10
  class Redis extends pulumi.ComponentResource {
10
11
  constructor(name, args, opts) {
11
12
  super('studion:Redis', name, {}, opts);
13
+ this.username = 'default';
14
+ const project = pulumi.getProject();
15
+ const stack = pulumi.getStack();
12
16
  const argsWithDefaults = Object.assign({}, defaults, args);
13
17
  this.instance = new upstash.RedisDatabase(name, {
14
18
  databaseName: argsWithDefaults.dbName,
@@ -16,6 +20,13 @@ class Redis extends pulumi.ComponentResource {
16
20
  eviction: true,
17
21
  tls: true,
18
22
  }, { provider: opts.provider, parent: this });
23
+ this.passwordSecret = new aws.secretsmanager.Secret(`${name}-password-secret`, {
24
+ name: `${stack}/${project}/RedisPassword`,
25
+ }, { parent: this, dependsOn: [this.instance] });
26
+ const passwordSecretValue = new aws.secretsmanager.SecretVersion(`${name}-password-secret-value`, {
27
+ secretId: this.passwordSecret.id,
28
+ secretString: this.instance.password,
29
+ }, { parent: this, dependsOn: [this.passwordSecret] });
19
30
  this.registerOutputs();
20
31
  }
21
32
  }
@@ -12,7 +12,6 @@ class StaticSite extends pulumi.ComponentResource {
12
12
  hostedZoneId: args.hostedZoneId,
13
13
  }, { parent: this });
14
14
  const bucket = new aws.s3.Bucket(`${name}-bucket`, {
15
- bucket: name,
16
15
  website: {
17
16
  indexDocument: 'index.html',
18
17
  errorDocument: 'index.html',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studion/infra-code-blocks",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "description": "Studion common infra components",
5
5
  "keywords": [
6
6
  "infrastructure",