@studion/infra-code-blocks 0.0.6 → 0.0.8
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 +22 -34
- package/dist/components/database.js +1 -0
- package/dist/components/ec2-ssm-connect.d.ts +0 -2
- package/dist/components/ec2-ssm-connect.js +0 -4
- package/dist/components/project.d.ts +3 -7
- package/dist/components/project.js +4 -22
- package/dist/constants.d.ts +0 -4
- package/dist/constants.js +1 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,7 +30,6 @@ import * as studion from '@studion/infra-code-blocks';
|
|
|
30
30
|
import * as studion from '@studion/infra-code-blocks';
|
|
31
31
|
|
|
32
32
|
const project = new studion.Project('demo-project', {
|
|
33
|
-
environment: 'DEVELOPMENT',
|
|
34
33
|
services: [
|
|
35
34
|
{
|
|
36
35
|
type: 'REDIS',
|
|
@@ -76,7 +75,6 @@ type ProjectArgs = {
|
|
|
76
75
|
| StaticSiteService
|
|
77
76
|
| WebServerService
|
|
78
77
|
)[];
|
|
79
|
-
environment: Environment;
|
|
80
78
|
hostedZoneId?: pulumi.Input<string>;
|
|
81
79
|
enableSSMConnect?: pulumi.Input<boolean>;
|
|
82
80
|
};
|
|
@@ -85,7 +83,6 @@ type ProjectArgs = {
|
|
|
85
83
|
| Argument | Description |
|
|
86
84
|
| :--------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------: |
|
|
87
85
|
| services \* | Service list. |
|
|
88
|
-
| environment \* | Environment name. |
|
|
89
86
|
| hostedZoneId | Route53 hosted zone ID responsible for managing records for the domain. |
|
|
90
87
|
| 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. |
|
|
91
88
|
|
|
@@ -101,6 +98,9 @@ type DatabaseService = {
|
|
|
101
98
|
allocatedStorage?: pulumi.Input<number>;
|
|
102
99
|
maxAllocatedStorage?: pulumi.Input<number>;
|
|
103
100
|
instanceClass?: pulumi.Input<string>;
|
|
101
|
+
tags?: pulumi.Input<{
|
|
102
|
+
[key: string]: pulumi.Input<string>;
|
|
103
|
+
}>;
|
|
104
104
|
};
|
|
105
105
|
```
|
|
106
106
|
|
|
@@ -118,6 +118,9 @@ export type StaticSiteService = {
|
|
|
118
118
|
type: 'STATIC_SITE';
|
|
119
119
|
serviceName: string;
|
|
120
120
|
domain: pulumi.Input<string>;
|
|
121
|
+
tags?: pulumi.Input<{
|
|
122
|
+
[key: string]: pulumi.Input<string>;
|
|
123
|
+
}>;
|
|
121
124
|
};
|
|
122
125
|
```
|
|
123
126
|
|
|
@@ -140,6 +143,9 @@ export type WebServerService = {
|
|
|
140
143
|
pulumi.Input<RoleInlinePolicy>[]
|
|
141
144
|
>;
|
|
142
145
|
taskRoleInlinePolicies?: pulumi.Input<pulumi.Input<RoleInlinePolicy>[]>;
|
|
146
|
+
tags?: pulumi.Input<{
|
|
147
|
+
[key: string]: pulumi.Input<string>;
|
|
148
|
+
}>;
|
|
143
149
|
};
|
|
144
150
|
```
|
|
145
151
|
|
|
@@ -370,11 +376,12 @@ The [Database](#database) component deploys a database instance inside a private
|
|
|
370
376
|
and it's not publicly accessible from outside of VPC.
|
|
371
377
|
<br>
|
|
372
378
|
In order to connect to the database we need to deploy the ec2 instance which will be used
|
|
373
|
-
to
|
|
379
|
+
to forward traffic to the database instance.
|
|
374
380
|
<br>
|
|
375
|
-
Because of security reasons, ec2 instance is also deployed inside private subnet
|
|
381
|
+
Because of security reasons, the ec2 instance is also deployed inside a private subnet
|
|
376
382
|
which means we can't directly connect to it. For that purpose, we use AWS System Manager
|
|
377
|
-
which enables us to connect to the ec2 instance even though it's inside private subnet.
|
|
383
|
+
which enables us to connect to the ec2 instance even though it's inside a private subnet.
|
|
384
|
+
The benefit of using AWS SSM is that we don't need a ssh key pair.
|
|
378
385
|
|
|
379
386
|

|
|
380
387
|
|
|
@@ -386,18 +393,6 @@ which enables us to connect to the ec2 instance even though it's inside private
|
|
|
386
393
|
$ brew install --cask session-manager-plugin
|
|
387
394
|
```
|
|
388
395
|
|
|
389
|
-
2. Generate a new ssh key pair or use the existing one.
|
|
390
|
-
|
|
391
|
-
```bash
|
|
392
|
-
$ ssh-keygen -f my_rsa
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
3. Set stack config property by running:
|
|
396
|
-
|
|
397
|
-
```bash
|
|
398
|
-
$ pulumi config set ssh:publicKey "ssh-rsa Z...9= mymac@Studions-MBP.localdomain"
|
|
399
|
-
```
|
|
400
|
-
|
|
401
396
|
SSM Connect can be enabled by setting `enableSSMConnect` property to `true`.
|
|
402
397
|
|
|
403
398
|
```ts
|
|
@@ -412,20 +407,13 @@ export const ec2InstanceId = project.ec2SSMConnect?.ec2.id;
|
|
|
412
407
|
Open up your terminal and run the following command:
|
|
413
408
|
|
|
414
409
|
```bash
|
|
415
|
-
$ aws ssm start-session --target EC2_INSTANCE_ID --document-name AWS-
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
Where `EC2_INSTANCE_ID` is an ID of the EC2 instance that is created for you. ID can be
|
|
419
|
-
obtained by exporting it from the stack.
|
|
420
|
-
|
|
421
|
-
Next, open another terminal window and run the following command:
|
|
422
|
-
|
|
423
|
-
```bash
|
|
424
|
-
$ ssh ec2-user@localhost -p 9999 -N -L 5555:DATABASE_ADDRESS:DATABASE_PORT -i SSH_PRIVATE_KEY
|
|
410
|
+
$ aws ssm start-session --target EC2_INSTANCE_ID --document-name AWS-StartPortForwardingSessionToRemoteHost --parameters '{"host": ["DATABASE_ADDRESS"], "portNumber":["DATABASE_PORT"], "localPortNumber":["5555"]}'
|
|
425
411
|
```
|
|
426
412
|
|
|
427
|
-
Where `
|
|
428
|
-
|
|
413
|
+
Where `EC2_INSTANCE_ID` is an ID of the EC2 instance that is created for you
|
|
414
|
+
(ID can be obtained by exporting it from the stack), and
|
|
415
|
+
`DATABASE_ADDRESS` and `DATABASE_PORT` are the address and port of the
|
|
416
|
+
database instance.
|
|
429
417
|
|
|
430
418
|
And that is it! 🥳
|
|
431
419
|
Now you can use your favorite database client to connect to the database.
|
|
@@ -433,9 +421,9 @@ Now you can use your favorite database client to connect to the database.
|
|
|
433
421
|

|
|
434
422
|
|
|
435
423
|
It is important that for the host you set `localhost` and for the port you set `5555`
|
|
436
|
-
because we
|
|
437
|
-
DATABASE_ADDRESS:DATABASE_PORT.
|
|
438
|
-
which are set in the `Project`.
|
|
424
|
+
because we are port forwarding traffic from
|
|
425
|
+
localhost:5555 to DATABASE_ADDRESS:DATABASE_PORT.
|
|
426
|
+
For the user, password, and database field, set values which are set in the `Project`.
|
|
439
427
|
|
|
440
428
|
```ts
|
|
441
429
|
const project = new studion.Project('demo-project', {
|
|
@@ -455,4 +443,4 @@ const project = new studion.Project('demo-project', {
|
|
|
455
443
|
## 🚧 TODO
|
|
456
444
|
|
|
457
445
|
- [ ] Add worker service for executing tasks
|
|
458
|
-
- [ ]
|
|
446
|
+
- [ ] Add MongoDB service
|
|
@@ -29,6 +29,7 @@ class Database extends pulumi.ComponentResource {
|
|
|
29
29
|
],
|
|
30
30
|
}, { parent: this });
|
|
31
31
|
this.kms = new aws.kms.Key(`${name}-rds-key`, {
|
|
32
|
+
description: `${name} RDS encryption key`,
|
|
32
33
|
customerMasterKeySpec: 'SYMMETRIC_DEFAULT',
|
|
33
34
|
isEnabled: true,
|
|
34
35
|
keyUsage: 'ENCRYPT_DECRYPT',
|
|
@@ -3,7 +3,6 @@ import * as aws from '@pulumi/aws';
|
|
|
3
3
|
import * as awsx from '@pulumi/awsx';
|
|
4
4
|
export type Ec2SSMConnectArgs = {
|
|
5
5
|
vpc: awsx.ec2.Vpc;
|
|
6
|
-
sshPublicKey: pulumi.Input<string>;
|
|
7
6
|
tags?: pulumi.Input<{
|
|
8
7
|
[key: string]: pulumi.Input<string>;
|
|
9
8
|
}>;
|
|
@@ -14,6 +13,5 @@ export declare class Ec2SSMConnect extends pulumi.ComponentResource {
|
|
|
14
13
|
ec2MessagesVpcEndpoint: aws.ec2.VpcEndpoint;
|
|
15
14
|
ssmMessagesVpcEndpoint: aws.ec2.VpcEndpoint;
|
|
16
15
|
ec2: aws.ec2.Instance;
|
|
17
|
-
sshKeyPair: aws.ec2.KeyPair;
|
|
18
16
|
constructor(name: string, args: Ec2SSMConnectArgs, opts?: pulumi.ComponentResourceOptions);
|
|
19
17
|
}
|
|
@@ -56,14 +56,10 @@ class Ec2SSMConnect extends pulumi.ComponentResource {
|
|
|
56
56
|
const ssmProfile = new aws.iam.InstanceProfile(`${name}-ssm-profile`, {
|
|
57
57
|
role: role.name,
|
|
58
58
|
}, { parent: this, dependsOn: [ssmPolicyAttachment] });
|
|
59
|
-
this.sshKeyPair = new aws.ec2.KeyPair(`${name}-ec2-keypair`, {
|
|
60
|
-
publicKey: args.sshPublicKey,
|
|
61
|
-
}, { parent: this });
|
|
62
59
|
this.ec2 = new aws.ec2.Instance(`${name}-ec2`, {
|
|
63
60
|
ami: 'ami-067d1e60475437da2',
|
|
64
61
|
associatePublicIpAddress: false,
|
|
65
62
|
instanceType: 't2.micro',
|
|
66
|
-
keyName: this.sshKeyPair.keyName,
|
|
67
63
|
iamInstanceProfile: ssmProfile.name,
|
|
68
64
|
subnetId,
|
|
69
65
|
vpcSecurityGroupIds: [this.ec2SecurityGroup.id],
|
|
@@ -6,7 +6,6 @@ import { Database, DatabaseArgs } from './database';
|
|
|
6
6
|
import { WebServer, WebServerArgs } from './web-server';
|
|
7
7
|
import { Redis, RedisArgs } from './redis';
|
|
8
8
|
import { StaticSite, StaticSiteArgs } from './static-site';
|
|
9
|
-
import { Environment } from '../constants';
|
|
10
9
|
import { Ec2SSMConnect } from './ec2-ssm-connect';
|
|
11
10
|
export type Service = Database | Redis | StaticSite | WebServer;
|
|
12
11
|
export type Services = Record<string, Service>;
|
|
@@ -18,21 +17,19 @@ type ServiceArgs = {
|
|
|
18
17
|
};
|
|
19
18
|
export type DatabaseService = {
|
|
20
19
|
type: 'DATABASE';
|
|
21
|
-
} & ServiceArgs & Omit<DatabaseArgs, 'vpc'
|
|
20
|
+
} & ServiceArgs & Omit<DatabaseArgs, 'vpc'>;
|
|
22
21
|
export type RedisService = {
|
|
23
22
|
type: 'REDIS';
|
|
24
23
|
} & ServiceArgs & Pick<RedisArgs, 'dbName' | 'region'>;
|
|
25
24
|
export type StaticSiteService = {
|
|
26
25
|
type: 'STATIC_SITE';
|
|
27
|
-
} & ServiceArgs & Omit<StaticSiteArgs, 'hostedZoneId'
|
|
26
|
+
} & ServiceArgs & Omit<StaticSiteArgs, 'hostedZoneId'>;
|
|
28
27
|
export type WebServerService = {
|
|
29
28
|
type: 'WEB_SERVER';
|
|
30
29
|
environment?: aws.ecs.KeyValuePair[] | ((services: Services) => aws.ecs.KeyValuePair[]);
|
|
31
|
-
} & ServiceArgs & Omit<WebServerArgs, 'cluster' | 'vpc' | 'hostedZoneId' | 'environment'
|
|
32
|
-
export type Environment = (typeof Environment)[keyof typeof Environment];
|
|
30
|
+
} & ServiceArgs & Omit<WebServerArgs, 'cluster' | 'vpc' | 'hostedZoneId' | 'environment'>;
|
|
33
31
|
export type ProjectArgs = {
|
|
34
32
|
services: (DatabaseService | RedisService | StaticSiteService | WebServerService)[];
|
|
35
|
-
environment: Environment;
|
|
36
33
|
hostedZoneId?: pulumi.Input<string>;
|
|
37
34
|
enableSSMConnect?: pulumi.Input<boolean>;
|
|
38
35
|
};
|
|
@@ -41,7 +38,6 @@ export declare class MissingHostedZoneId extends Error {
|
|
|
41
38
|
}
|
|
42
39
|
export declare class Project extends pulumi.ComponentResource {
|
|
43
40
|
name: string;
|
|
44
|
-
environment: Environment;
|
|
45
41
|
vpc: awsx.ec2.Vpc;
|
|
46
42
|
cluster?: aws.ecs.Cluster;
|
|
47
43
|
hostedZoneId?: pulumi.Input<string>;
|
|
@@ -33,20 +33,14 @@ class Project extends pulumi.ComponentResource {
|
|
|
33
33
|
constructor(name, args, opts = {}) {
|
|
34
34
|
super('studion:Project', name, {}, opts);
|
|
35
35
|
this.services = {};
|
|
36
|
-
const { services,
|
|
36
|
+
const { services, hostedZoneId } = args;
|
|
37
37
|
this.name = name;
|
|
38
38
|
this.hostedZoneId = hostedZoneId;
|
|
39
|
-
this.environment = environment;
|
|
40
39
|
this.vpc = this.createVpc();
|
|
41
40
|
this.createServices(services);
|
|
42
41
|
if (args.enableSSMConnect) {
|
|
43
|
-
const sshConfig = new pulumi.Config('ssh');
|
|
44
42
|
this.ec2SSMConnect = new ec2_ssm_connect_1.Ec2SSMConnect(`${name}-ssm-connect`, {
|
|
45
43
|
vpc: this.vpc,
|
|
46
|
-
sshPublicKey: sshConfig.require('publicKey'),
|
|
47
|
-
tags: {
|
|
48
|
-
Env: this.environment,
|
|
49
|
-
},
|
|
50
44
|
});
|
|
51
45
|
}
|
|
52
46
|
this.registerOutputs();
|
|
@@ -56,9 +50,6 @@ class Project extends pulumi.ComponentResource {
|
|
|
56
50
|
numberOfAvailabilityZones: 2,
|
|
57
51
|
enableDnsHostnames: true,
|
|
58
52
|
enableDnsSupport: true,
|
|
59
|
-
tags: {
|
|
60
|
-
Env: this.environment,
|
|
61
|
-
},
|
|
62
53
|
}, { parent: this });
|
|
63
54
|
return vpc;
|
|
64
55
|
}
|
|
@@ -90,16 +81,11 @@ class Project extends pulumi.ComponentResource {
|
|
|
90
81
|
createWebServerPrerequisites() {
|
|
91
82
|
this.cluster = new aws.ecs.Cluster(`${this.name}-cluster`, {
|
|
92
83
|
name: this.name,
|
|
93
|
-
tags: {
|
|
94
|
-
Env: this.environment,
|
|
95
|
-
},
|
|
96
84
|
}, { parent: this });
|
|
97
85
|
}
|
|
98
86
|
createDatabaseService(options) {
|
|
99
87
|
const { serviceName, type } = options, databaseOptions = __rest(options, ["serviceName", "type"]);
|
|
100
|
-
const service = new database_1.Database(serviceName, Object.assign(Object.assign({}, databaseOptions), { vpc: this.vpc,
|
|
101
|
-
Env: this.environment,
|
|
102
|
-
} }), { parent: this });
|
|
88
|
+
const service = new database_1.Database(serviceName, Object.assign(Object.assign({}, databaseOptions), { vpc: this.vpc }), { parent: this });
|
|
103
89
|
this.services[serviceName] = service;
|
|
104
90
|
}
|
|
105
91
|
createRedisService(options) {
|
|
@@ -116,9 +102,7 @@ class Project extends pulumi.ComponentResource {
|
|
|
116
102
|
const { serviceName } = options, staticSiteOptions = __rest(options, ["serviceName"]);
|
|
117
103
|
if (!this.hostedZoneId)
|
|
118
104
|
throw new MissingHostedZoneId(options.type);
|
|
119
|
-
const service = new static_site_1.StaticSite(serviceName, Object.assign(Object.assign({}, staticSiteOptions), { hostedZoneId: this.hostedZoneId,
|
|
120
|
-
Env: this.environment,
|
|
121
|
-
} }), { parent: this });
|
|
105
|
+
const service = new static_site_1.StaticSite(serviceName, Object.assign(Object.assign({}, staticSiteOptions), { hostedZoneId: this.hostedZoneId }), { parent: this });
|
|
122
106
|
this.services[serviceName] = service;
|
|
123
107
|
}
|
|
124
108
|
createWebServerService(options) {
|
|
@@ -130,9 +114,7 @@ class Project extends pulumi.ComponentResource {
|
|
|
130
114
|
const parsedEnv = typeof environment === 'function'
|
|
131
115
|
? environment(this.services)
|
|
132
116
|
: environment;
|
|
133
|
-
const service = new web_server_1.WebServer(serviceName, Object.assign(Object.assign({}, ecsOptions), { cluster: this.cluster, vpc: this.vpc, hostedZoneId: this.hostedZoneId, environment: parsedEnv,
|
|
134
|
-
Env: this.environment,
|
|
135
|
-
} }), { parent: this });
|
|
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 });
|
|
136
118
|
this.services[options.serviceName] = service;
|
|
137
119
|
}
|
|
138
120
|
}
|
package/dist/constants.d.ts
CHANGED
package/dist/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.PredefinedSize = void 0;
|
|
4
4
|
const CPU_1_VCPU = 1024;
|
|
5
5
|
const MEMORY_1GB = 1024;
|
|
6
6
|
exports.PredefinedSize = {
|
|
@@ -21,7 +21,3 @@ exports.PredefinedSize = {
|
|
|
21
21
|
memory: MEMORY_1GB * 4, // 4 GB memory
|
|
22
22
|
},
|
|
23
23
|
};
|
|
24
|
-
exports.Environment = {
|
|
25
|
-
DEVELOPMENT: 'DEVELOPMENT',
|
|
26
|
-
PRODUCTION: 'PRODUCTION',
|
|
27
|
-
};
|