cloudmason 0.0.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,224 @@
1
+ AWSTemplateFormatVersion: '2010-09-09'
2
+ Description: ASG Cloudformation Template
3
+
4
+
5
+ Parameters:
6
+ InstanceRootDomain:
7
+ Type: AWS::Route53::HostedZone::Id
8
+ Description: Hosted Zone
9
+ InstanceDomain:
10
+ Type: String
11
+ Description: Full domain/subdomain name to associate with the ALB
12
+ ACMDomainCert:
13
+ Type: String
14
+ Description: ARN of AWS ACM Certificate
15
+ VpcId:
16
+ Type: AWS::EC2::VPC::Id
17
+ Description: Org VPC
18
+ InstanceSubnets:
19
+ Type: List<AWS::EC2::Subnet::Id>
20
+ Description: Subnets to deploy in
21
+ MaxEc2Instances:
22
+ Type: Number
23
+ Description: Max number of Ec2 instances
24
+ AmiId:
25
+ Type: AWS::EC2::Image::Id
26
+ Description: Max number of Ec2 instances
27
+
28
+
29
+ Resources:
30
+ # ALB
31
+ AppALB:
32
+ Type: AWS::ElasticLoadBalancingV2::LoadBalancer
33
+ Properties:
34
+ Scheme: internet-facing
35
+ Type: application
36
+ IpAddressType: ipv4
37
+ SecurityGroups:
38
+ - !GetAtt AppALBSecurityGroup.GroupId
39
+ Subnets: !Ref InstanceSubnets
40
+ AppALBHTTPSListener:
41
+ Type: AWS::ElasticLoadBalancingV2::Listener
42
+ Properties:
43
+ Certificates:
44
+ - CertificateArn: !Ref ACMDomainCert
45
+ DefaultActions:
46
+ - Type: forward
47
+ ForwardConfig:
48
+ TargetGroups:
49
+ - TargetGroupArn: !Ref AppALBTargetGroup
50
+ Weight: 999
51
+ TargetGroupStickinessConfig:
52
+ DurationSeconds: 900
53
+ Enabled: false
54
+ LoadBalancerArn: !Ref AppALB
55
+ Port: 443
56
+ Protocol: HTTPS
57
+ AppALBHTTPRedirectListener:
58
+ Type: AWS::ElasticLoadBalancingV2::Listener
59
+ Properties:
60
+ DefaultActions:
61
+ - RedirectConfig:
62
+ Port: "443"
63
+ Protocol: HTTPS
64
+ StatusCode: HTTP_301
65
+ Type: redirect
66
+ LoadBalancerArn: !Ref AppALB
67
+ Port: 80
68
+ Protocol: HTTP
69
+ AppALBSecurityGroup:
70
+ Type: AWS::EC2::SecurityGroup
71
+ Properties:
72
+ VpcId: !Ref VpcId
73
+ GroupDescription: Allow http to client host
74
+ SecurityGroupIngress:
75
+ - IpProtocol: tcp
76
+ FromPort: 80
77
+ ToPort: 80
78
+ CidrIp: 0.0.0.0/0
79
+ - IpProtocol: tcp
80
+ FromPort: 443
81
+ ToPort: 443
82
+ CidrIp: 0.0.0.0/0
83
+ AppALBSecurityGroupEgress:
84
+ Type: AWS::EC2::SecurityGroupEgress
85
+ Properties:
86
+ GroupId: !Ref AppALBSecurityGroup
87
+ Description: Allow ALB to communicate with Ec2
88
+ IpProtocol: tcp
89
+ FromPort: 8080
90
+ ToPort: 8080
91
+ DestinationSecurityGroupId: !Ref AppEc2SecurityGroup
92
+ AppALBRouteRecord:
93
+ Type: AWS::Route53::RecordSet
94
+ Properties:
95
+ Type: A
96
+ Name: !Ref InstanceDomain
97
+ AliasTarget:
98
+ DNSName: !GetAtt AppALB.DNSName
99
+ EvaluateTargetHealth: true
100
+ HostedZoneId: !GetAtt AppALB.CanonicalHostedZoneID
101
+ HostedZoneId: !Ref InstanceRootDomain
102
+ Region: !Ref AWS::Region
103
+ SetIdentifier: !Ref AWS::Region
104
+ # Autoscaling Group
105
+ AppASG:
106
+ Type: AWS::AutoScaling::AutoScalingGroup
107
+ Properties:
108
+ AvailabilityZones:
109
+ Fn::GetAZs: ""
110
+ DesiredCapacity: '1'
111
+ MinSize: '1'
112
+ MaxSize: !Ref MaxEc2Instances
113
+ TargetGroupARNs:
114
+ - !Ref AppALBTargetGroup
115
+ LaunchTemplate:
116
+ LaunchTemplateId: !Ref AppEc2LaunchTemplate
117
+ Version: !GetAtt AppEc2LaunchTemplate.LatestVersionNumber
118
+ AppALBTargetGroup:
119
+ Type: AWS::ElasticLoadBalancingV2::TargetGroup
120
+ Properties:
121
+ HealthCheckIntervalSeconds: 30
122
+ HealthCheckPath: /
123
+ HealthCheckTimeoutSeconds: 5
124
+ HealthyThresholdCount: 3
125
+ Matcher:
126
+ HttpCode: 200,300,302
127
+ Port: 8080
128
+ Protocol: HTTP
129
+ TargetType: instance
130
+ UnhealthyThresholdCount: 2
131
+ VpcId: !Ref VpcId
132
+ ASGCPUPolicy:
133
+ Type: AWS::AutoScaling::ScalingPolicy
134
+ Properties:
135
+ AutoScalingGroupName: !Ref AppASG
136
+ PolicyType: TargetTrackingScaling
137
+ TargetTrackingConfiguration:
138
+ PredefinedMetricSpecification:
139
+ PredefinedMetricType: ASGAverageCPUUtilization
140
+ TargetValue: '70'
141
+ AppEc2LaunchTemplate:
142
+ Type: AWS::EC2::LaunchTemplate
143
+ Properties:
144
+ LaunchTemplateName: !Sub '${AWS::StackName}_LaunchTemplate'
145
+ LaunchTemplateData:
146
+ IamInstanceProfile:
147
+ Name:
148
+ Ref: AppEc2Profile
149
+ UserData: {{user_data}}
150
+ ImageId: !Ref AmiId
151
+ DisableApiTermination: "true"
152
+ InstanceType: t2.small
153
+ SecurityGroupIds:
154
+ - !Ref AppEc2SecurityGroup
155
+ AppEc2SecurityGroup:
156
+ Type: AWS::EC2::SecurityGroup
157
+ Properties:
158
+ VpcId: !Ref VpcId
159
+ GroupDescription: Allow http to client host
160
+ SecurityGroupEgress:
161
+ - IpProtocol: "-1"
162
+ CidrIp: 0.0.0.0/0
163
+ AppEc2SecurityGroupIngress:
164
+ Type: AWS::EC2::SecurityGroupIngress
165
+ Properties:
166
+ GroupId: !Ref AppEc2SecurityGroup
167
+ Description: Allow 8080 from ALB
168
+ IpProtocol: "-1"
169
+ SourceSecurityGroupId: !Ref AppALBSecurityGroup
170
+ # S3 App Bucket
171
+ AppBucket:
172
+ Type: AWS::S3::Bucket
173
+ Properties:
174
+ BucketName: !Ref InstanceDomain
175
+ VersioningConfiguration:
176
+ Status: Enabled
177
+ AppBucketPolicy:
178
+ Type: AWS::S3::BucketPolicy
179
+ Properties:
180
+ Bucket: !Ref AppBucket
181
+ PolicyDocument:
182
+ Version: '2012-10-17'
183
+ Statement:
184
+ - Effect: Allow
185
+ Principal:
186
+ AWS:
187
+ - !GetAtt AppEc2Role.Arn
188
+ Action:
189
+ - 's3:GetObject'
190
+ Resource:
191
+ - !Sub arn:aws:s3:::${AppBucket}
192
+ - !Sub arn:aws:s3:::${AppBucket}/*
193
+ # IAM
194
+ AppEc2Role:
195
+ Type: 'AWS::IAM::Role'
196
+ Properties:
197
+ AssumeRolePolicyDocument:
198
+ Version: "2012-10-17"
199
+ Statement:
200
+ - Effect: Allow
201
+ Principal:
202
+ Service:
203
+ - ec2.amazonaws.com
204
+ Action:
205
+ - 'sts:AssumeRole'
206
+ Path: !Sub '/apps/${AWS::StackName}/'
207
+ Policies:
208
+ - PolicyName: root
209
+ PolicyDocument:
210
+ Version: "2012-10-17"
211
+ Statement:
212
+ - Effect: Allow
213
+ Action:
214
+ - s3:GetObject
215
+ - s3:ListBucket
216
+ Resource:
217
+ - !Sub arn:aws:s3:::${AppBucket}
218
+ - !Sub arn:aws:s3:::${AppBucket}/*
219
+ AppEc2Profile:
220
+ Type: AWS::IAM::InstanceProfile
221
+ Properties:
222
+ Path: !Sub '/apps/${AWS::StackName}/'
223
+ Roles:
224
+ - !Ref AppEc2Role
@@ -0,0 +1,321 @@
1
+ {
2
+ "AWSTemplateFormatVersion": "2010-09-09",
3
+ "Description": "ASG Cloudformation Template",
4
+ "Parameters": {
5
+ "AppName": {
6
+ "Type": "String",
7
+ "Description": "Application Name"
8
+ },
9
+ "InstanceName": {
10
+ "Type": "String",
11
+ "Description": "Application Name"
12
+ },
13
+ "InstanceRootDomain": {
14
+ "Type": "AWS::Route53::HostedZone::Id",
15
+ "Description": "Hosted Zone"
16
+ },
17
+ "InstanceDomain": {
18
+ "Type": "String",
19
+ "Description": "Full domain/subdomain name to associate with the ALB"
20
+ },
21
+ "ACMDomainCert": {
22
+ "Type": "String",
23
+ "Description": "ARN of AWS ACM Certificate"
24
+ },
25
+ "VpcId": {
26
+ "Type": "AWS::EC2::VPC::Id",
27
+ "Description": "Org VPC"
28
+ },
29
+ "InstanceSubnets": {
30
+ "Type": "List<AWS::EC2::Subnet::Id>",
31
+ "Description": "Subnets to deploy in"
32
+ },
33
+ "MinEc2Instances": {
34
+ "Type": "Number",
35
+ "Description": "Minimum number of Ec2 instances"
36
+ },
37
+ "MaxEc2Instances": {
38
+ "Type": "Number",
39
+ "Description": "Max number of Ec2 instances"
40
+ }
41
+ },
42
+ "Resources": {
43
+ "AppALB": {
44
+ "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
45
+ "Properties": {
46
+ "Name": "${AppName}-${InstanceName}",
47
+ "Scheme": "internet-facing",
48
+ "Type": "application",
49
+ "IpAddressType": "ipv4",
50
+ "SecurityGroups": "AppALBSecurityGroup",
51
+ "Subnets": "InstanceSubnets"
52
+ }
53
+ },
54
+ "AppALBHTTPSListener": {
55
+ "Type": "AWS::ElasticLoadBalancingV2::Listener",
56
+ "Properties": {
57
+ "Certificates": [
58
+ {
59
+ "CertificateArn": "ACMDomainCert"
60
+ }
61
+ ],
62
+ "DefaultActions": [
63
+ {
64
+ "Type": "forward",
65
+ "ForwardConfig": {
66
+ "TargetGroups": [
67
+ {
68
+ "TargetGroupArn": "AppALBTargetGroup",
69
+ "Weight": 999
70
+ }
71
+ ],
72
+ "TargetGroupStickinessConfig": {
73
+ "DurationSeconds": 900,
74
+ "Enabled": false
75
+ }
76
+ }
77
+ }
78
+ ],
79
+ "LoadBalancerArn": "AppALB",
80
+ "Port": 443,
81
+ "Protocol": "HTTPS"
82
+ }
83
+ },
84
+ "AppALBHTTPRedirectListener": {
85
+ "Type": "AWS::ElasticLoadBalancingV2::Listener",
86
+ "Properties": {
87
+ "DefaultActions": [
88
+ {
89
+ "RedirectConfig": {
90
+ "Port": "443",
91
+ "Protocol": "HTTPS",
92
+ "StatusCode": "HTTP_301"
93
+ },
94
+ "Type": "redirect"
95
+ }
96
+ ],
97
+ "LoadBalancerArn": "AppALB",
98
+ "Port": 80,
99
+ "Protocol": "HTTP"
100
+ }
101
+ },
102
+ "AppALBSecurityGroup": {
103
+ "Type": "AWS::EC2::SecurityGroup",
104
+ "Properties": {
105
+ "VpcId": "VpcId",
106
+ "GroupName": "AppALBSecurityGroup",
107
+ "GroupDescription": "Allow http to client host",
108
+ "SecurityGroupIngress": [
109
+ {
110
+ "IpProtocol": "tcp",
111
+ "FromPort": 80,
112
+ "ToPort": 80,
113
+ "CidrIp": "0.0.0.0/0"
114
+ },
115
+ {
116
+ "IpProtocol": "tcp",
117
+ "FromPort": 443,
118
+ "ToPort": 443,
119
+ "CidrIp": "0.0.0.0/0"
120
+ }
121
+ ]
122
+ }
123
+ },
124
+ "AppALBSecurityGroupEgress": {
125
+ "Type": "AWS::EC2::SecurityGroupEgress",
126
+ "Properties": {
127
+ "GroupId": "AppALBSecurityGroup",
128
+ "Description": "Allow ALB to communicate with Ec2",
129
+ "IpProtocol": "tcp",
130
+ "FromPort": 8080,
131
+ "ToPort": 8080,
132
+ "DestinationSecurityGroupId": "AppEc2SecurityGroup"
133
+ }
134
+ },
135
+ "AppALBRouteRecord": {
136
+ "Type": "AWS::Route53::RecordSet",
137
+ "Properties": {
138
+ "Type": "A",
139
+ "Name": "InstanceDomain",
140
+ "AliasTarget": {
141
+ "DNSName": "AppALB.DNSName",
142
+ "EvaluateTargetHealth": true,
143
+ "HostedZoneId": "AppALB.CanonicalHostedZoneID"
144
+ },
145
+ "HostedZoneName": "${InstanceRootDomain}.",
146
+ "Region": "AWS::Region",
147
+ "SetIdentifier": "AWS::Region"
148
+ }
149
+ },
150
+ "AppASG": {
151
+ "Type": "AWS::AutoScaling::AutoScalingGroup",
152
+ "Properties": {
153
+ "AutoScalingGroupName": "AppASG",
154
+ "AvailabilityZones": {
155
+ "Fn::GetAZs": ""
156
+ },
157
+ "DesiredCapacity": "MinEc2Instances",
158
+ "MinSize": "MinEc2Instances",
159
+ "MaxSize": "MaxEc2Instances",
160
+ "TargetGroupARNs": "AppALBTargetGroup",
161
+ "LaunchTemplate": {
162
+ "LaunchTemplateId": "AppEc2LaunchTemplate",
163
+ "Version": "AppEc2LaunchTemplate.LatestVersionNumber"
164
+ }
165
+ },
166
+ "UpdatePolicy": {
167
+ "AutoScalingRollingUpdate": {
168
+ "MinInstancesInService": "1",
169
+ "MaxBatchSize": "1",
170
+ "PauseTime": "PT15M",
171
+ "WaitOnResourceSignals": "true"
172
+ }
173
+ }
174
+ },
175
+ "AppALBTargetGroup": {
176
+ "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
177
+ "Properties": {
178
+ "Name": "${AppName}-TargetGroup",
179
+ "HealthCheckIntervalSeconds": 30,
180
+ "HealthCheckPath": "/",
181
+ "HealthCheckTimeoutSeconds": 5,
182
+ "HealthyThresholdCount": 3,
183
+ "Matcher": {
184
+ "HttpCode": "200,300,302"
185
+ },
186
+ "Port": 8080,
187
+ "Protocol": "HTTP",
188
+ "TargetType": "instance",
189
+ "UnhealthyThresholdCount": 2,
190
+ "VpcId": "VpcId"
191
+ }
192
+ },
193
+ "AppEc2LaunchTemplate": {
194
+ "Type": "AWS::EC2::LaunchTemplate",
195
+ "Properties": {
196
+ "LaunchTemplateName": "AppEc2LaunchTemplate",
197
+ "LaunchTemplateData": {
198
+ "IamInstanceProfile": {
199
+ "Name": {
200
+ "Ref": "AppEc2Profile"
201
+ }
202
+ },
203
+ "UserData": "Y2QgL2hvbWUvZWMyLXVzZXIKbnBtIHJ1biBzdGFydCAu",
204
+ "ImageId": "ami-0f46d2cab016f434b",
205
+ "DisableApiTermination": "true",
206
+ "InstanceType": "t2.small",
207
+ "SecurityGroupIds": "AppEc2SecurityGroup"
208
+ }
209
+ }
210
+ },
211
+ "AppEc2SecurityGroup": {
212
+ "Type": "AWS::EC2::SecurityGroup",
213
+ "Properties": {
214
+ "VpcId": "VpcId",
215
+ "GroupName": "AppEc2SecurityGroup",
216
+ "GroupDescription": "Allow http to client host",
217
+ "SecurityGroupEgress": [
218
+ {
219
+ "IpProtocol": "-1",
220
+ "CidrIp": "0.0.0.0/0"
221
+ }
222
+ ]
223
+ }
224
+ },
225
+ "AppEc2SecurityGroupIngress": {
226
+ "Type": "AWS::EC2::SecurityGroupIngress",
227
+ "Properties": {
228
+ "GroupId": "AppEc2SecurityGroup",
229
+ "Description": "Allow 8080 from ALB",
230
+ "IpProtocol": "-1",
231
+ "SourceSecurityGroupId": "AppALBSecurityGroup"
232
+ }
233
+ },
234
+ "AppBucket": {
235
+ "Type": "AWS::S3::Bucket",
236
+ "Properties": {
237
+ "BucketName": "InstanceDomain",
238
+ "VersioningConfiguration": {
239
+ "Status": "Enabled"
240
+ }
241
+ }
242
+ },
243
+ "AppBucketPolicy": {
244
+ "Type": "AWS::S3::BucketPolicy",
245
+ "Properties": {
246
+ "Bucket": "AppBucket",
247
+ "PolicyDocument": {
248
+ "Version": "2012-10-17",
249
+ "Statement": [
250
+ {
251
+ "Effect": "Allow",
252
+ "Principal": {
253
+ "AWS": [
254
+ "AppEc2Role.Arn"
255
+ ]
256
+ },
257
+ "Action": [
258
+ "s3:GetObject"
259
+ ],
260
+ "Resource": [
261
+ "arn:aws:s3:::${AppBucket}",
262
+ "arn:aws:s3:::${AppBucket}/*"
263
+ ]
264
+ }
265
+ ]
266
+ }
267
+ }
268
+ },
269
+ "AppEc2Role": {
270
+ "Type": "AWS::IAM::Role",
271
+ "Properties": {
272
+ "AssumeRolePolicyDocument": {
273
+ "Version": "2012-10-17",
274
+ "Statement": [
275
+ {
276
+ "Effect": "Allow",
277
+ "Principal": {
278
+ "Service": [
279
+ "ec2.amazonaws.com"
280
+ ]
281
+ },
282
+ "Action": [
283
+ "sts:AssumeRole"
284
+ ]
285
+ }
286
+ ]
287
+ },
288
+ "Path": "/${AppName}",
289
+ "Policies": [
290
+ {
291
+ "PolicyName": "root",
292
+ "PolicyDocument": {
293
+ "Version": "2012-10-17",
294
+ "Statement": [
295
+ {
296
+ "Effect": "Allow",
297
+ "Action": [
298
+ "s3:GetObject",
299
+ "s3:ListBucket"
300
+ ],
301
+ "Resource": [
302
+ "arn:aws:s3:::${AppBucket}",
303
+ "arn:aws:s3:::${AppBucket}/*"
304
+ ]
305
+ }
306
+ ]
307
+ }
308
+ }
309
+ ]
310
+ }
311
+ },
312
+ "AppEc2Profile": {
313
+ "Type": "AWS::IAM::InstanceProfile",
314
+ "Properties": {
315
+ "InstanceProfileName": "AppEc2Profile",
316
+ "Path": "/${AppName}",
317
+ "Roles": "AppEc2Role"
318
+ }
319
+ }
320
+ }
321
+ }
@@ -0,0 +1,106 @@
1
+ AWSTemplateFormatVersion: '2010-09-09'
2
+ Description: Org Cloudformation Template
3
+
4
+ Parameters:
5
+ orgName:
6
+ Type: String
7
+ Description: Unique name of organization
8
+ orgDomain:
9
+ Type: String
10
+ Description: Organization domain name
11
+ VpcId:
12
+ Type: String
13
+ Description: Org VPC
14
+
15
+
16
+ Resources:
17
+ # S3 Bucket
18
+ InfraBucket:
19
+ Type: AWS::S3::Bucket
20
+ Properties:
21
+ BucketName: !Sub 'infra.${orgDomain}'
22
+ VersioningConfiguration:
23
+ Status: Enabled
24
+ # IAM Policies for Ec2 Build Access
25
+ InfraBuildRole:
26
+ Type: 'AWS::IAM::Role'
27
+ Properties:
28
+ AssumeRolePolicyDocument:
29
+ Version: "2012-10-17"
30
+ Statement:
31
+ - Effect: Allow
32
+ Principal:
33
+ Service:
34
+ - ec2.amazonaws.com
35
+ Action:
36
+ - 'sts:AssumeRole'
37
+ Path: /infra/
38
+ Policies:
39
+ - PolicyName: root
40
+ PolicyDocument:
41
+ Version: "2012-10-17"
42
+ Statement:
43
+ - Effect: Allow
44
+ Action:
45
+ - s3:GetObject
46
+ - s3:ListBucket
47
+ Resource:
48
+ - !Sub arn:aws:s3:::${InfraBucket}
49
+ - !Sub arn:aws:s3:::${InfraBucket}/*
50
+ InfraInstanceProfile:
51
+ Type: 'AWS::IAM::InstanceProfile'
52
+ Properties:
53
+ Path: /infra/
54
+ Roles:
55
+ - !Ref InfraBuildRole
56
+ # Ec2 security group
57
+ BuildSecGroup:
58
+ Type: 'AWS::EC2::SecurityGroup'
59
+ Properties:
60
+ GroupDescription: Security group for build AMI
61
+ SecurityGroupEgress:
62
+ - IpProtocol: '-1'
63
+ CidrIp: '0.0.0.0/0'
64
+ VpcId: !Ref VpcId
65
+ # Bucket Policy
66
+ InfraBucketPolicy:
67
+ Type: AWS::S3::BucketPolicy
68
+ Properties:
69
+ Bucket: !Ref InfraBucket
70
+ PolicyDocument:
71
+ Version: '2012-10-17'
72
+ Statement:
73
+ - Effect: Allow
74
+ Principal:
75
+ AWS:
76
+ - !GetAtt InfraBuildRole.Arn
77
+ Action:
78
+ - 's3:GetObject'
79
+ Resource:
80
+ - !Sub arn:aws:s3:::${InfraBucket}
81
+ - !Sub arn:aws:s3:::${InfraBucket}/*
82
+ # Org Params
83
+ ParamOrgInfo:
84
+ Type: 'AWS::SSM::Parameter'
85
+ Properties:
86
+ Name: '/infra/orgName'
87
+ Type: 'String'
88
+ Value: !Ref orgName
89
+ ParamOrgDomain:
90
+ Type: 'AWS::SSM::Parameter'
91
+ Properties:
92
+ Name: '/infra/orgDomain'
93
+ Type: 'String'
94
+ Value: !Ref orgDomain
95
+ ParamInstanceProfile:
96
+ Type: 'AWS::SSM::Parameter'
97
+ Properties:
98
+ Name: '/infra/buildInstanceProfile'
99
+ Type: 'String'
100
+ Value: !GetAtt InfraInstanceProfile.Arn
101
+ ParamIAM:
102
+ Type: 'AWS::SSM::Parameter'
103
+ Properties:
104
+ Name: '/infra/buildSecGroup'
105
+ Type: 'String'
106
+ Value: !GetAtt buildSecGroup.GroupId
@@ -0,0 +1,26 @@
1
+ const path = require('path');
2
+ const fs = require('fs');
3
+
4
+ const Stacks = {};
5
+
6
+ exports.get = function(stackType,params){
7
+ const stackPath = path.resolve(__dirname, 'stacks', `${stackType}.yaml`);
8
+
9
+ if (!fs.existsSync(stackPath)){ throw new Error('Invalid stack ' + stackType); }
10
+
11
+ const stackText = fs.readFileSync(stackPath, 'utf-8');
12
+ return Stacks[stackType](stackText,params)
13
+ }
14
+
15
+ Stacks.asg = function(stackText,params){
16
+ let bootScript = `#!/bin/bash -xe\ncd /home/ec2-user/app\n`;
17
+ if (params.lang == 'py'){
18
+ bootScript += 'py start .'
19
+ } else {
20
+ bootScript += `npm run start .`
21
+ }
22
+
23
+ const b64Script = Buffer.from(bootScript, 'utf8').toString('base64');
24
+ stackText = stackText.replace(/{{user_data}}/, b64Script);
25
+ return stackText;
26
+ }