aws-rails-provisioner 0.0.0.rc1
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.
- checksums.yaml +7 -0
- data/bin/aws-rails-provisioner +132 -0
- data/lib/aws-rails-provisioner.rb +42 -0
- data/lib/aws-rails-provisioner/build.rb +43 -0
- data/lib/aws-rails-provisioner/cdk_builder.rb +68 -0
- data/lib/aws-rails-provisioner/cdk_code_builder.rb +140 -0
- data/lib/aws-rails-provisioner/cdk_deployer.rb +62 -0
- data/lib/aws-rails-provisioner/code_build.rb +28 -0
- data/lib/aws-rails-provisioner/db_cluster.rb +299 -0
- data/lib/aws-rails-provisioner/errors.rb +24 -0
- data/lib/aws-rails-provisioner/fargate.rb +93 -0
- data/lib/aws-rails-provisioner/migration.rb +45 -0
- data/lib/aws-rails-provisioner/parser.rb +22 -0
- data/lib/aws-rails-provisioner/scaling.rb +448 -0
- data/lib/aws-rails-provisioner/service.rb +90 -0
- data/lib/aws-rails-provisioner/services.rb +44 -0
- data/lib/aws-rails-provisioner/subnet_selection.rb +20 -0
- data/lib/aws-rails-provisioner/utils.rb +89 -0
- data/lib/aws-rails-provisioner/version.rb +5 -0
- data/lib/aws-rails-provisioner/view.rb +29 -0
- data/lib/aws-rails-provisioner/views/fargate_stack.rb +100 -0
- data/lib/aws-rails-provisioner/views/init_stack.rb +35 -0
- data/lib/aws-rails-provisioner/views/pipeline_stack.rb +107 -0
- data/lib/aws-rails-provisioner/views/project.rb +33 -0
- data/lib/aws-rails-provisioner/vpc.rb +111 -0
- data/templates/fargate_stack.mustache +316 -0
- data/templates/init_stack.mustache +50 -0
- data/templates/pipeline_stack.mustache +156 -0
- data/templates/project.mustache +33 -0
- metadata +115 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
module Aws::RailsProvisioner
|
2
|
+
module Views
|
3
|
+
# @api private
|
4
|
+
class Project < View
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
@services = options[:services]
|
8
|
+
@stack_prefix = options[:stack_prefix]
|
9
|
+
@path_prefix = options[:path_prefix]
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [String]
|
13
|
+
attr_reader :stack_prefix
|
14
|
+
|
15
|
+
# @return [String]
|
16
|
+
attr_reader :path_prefix
|
17
|
+
|
18
|
+
def stacks
|
19
|
+
stacks = []
|
20
|
+
@services.each do |svc|
|
21
|
+
stacks << {
|
22
|
+
name: svc.name,
|
23
|
+
const_prefix: svc.const_prefix,
|
24
|
+
path_prefix: svc.path_prefix,
|
25
|
+
stack_prefix: svc.stack_prefix,
|
26
|
+
enable_cicd: svc.enable_cicd
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Aws::RailsProvisioner
|
2
|
+
class Vpc
|
3
|
+
|
4
|
+
SUBNETS_DEFAULTS = {
|
5
|
+
application: {
|
6
|
+
cidr_mask: 24,
|
7
|
+
type: 'private'
|
8
|
+
},
|
9
|
+
ingress: {
|
10
|
+
cidr_mask: 24,
|
11
|
+
type: 'public'
|
12
|
+
},
|
13
|
+
database: {
|
14
|
+
cidr_mask: 28,
|
15
|
+
type: 'isolated'
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
# Configuration value under :vpc
|
20
|
+
# @param [Hash] options
|
21
|
+
#
|
22
|
+
# @option options [Integer] :max_azs maximum number
|
23
|
+
# of AZs to use in this region, default to 3
|
24
|
+
#
|
25
|
+
# @option options [String] :cidr CIDR range to use for
|
26
|
+
# the VPC, default to '10.0.0.0/21'
|
27
|
+
#
|
28
|
+
# @option options [Hash] :subnets subnets configuration
|
29
|
+
# to build for each AZ, default to following example:
|
30
|
+
#
|
31
|
+
# @example: at `aws-rails-provisioner.yml`
|
32
|
+
# subnets:
|
33
|
+
# application:
|
34
|
+
# cidr_mask: 24
|
35
|
+
# type: private
|
36
|
+
# ingress:
|
37
|
+
# cidr_mask: 24
|
38
|
+
# type: public
|
39
|
+
# database:
|
40
|
+
# cidr_mask: 28
|
41
|
+
# type: isolate
|
42
|
+
#
|
43
|
+
# @option options [Boolean] :enable_dns whether the DNS
|
44
|
+
# resolution is supported for the VPC, default to `true`
|
45
|
+
#
|
46
|
+
# @option options [Integer] :nat_gateways number of NAT Gateways
|
47
|
+
# to create, default to :maxAz value
|
48
|
+
#
|
49
|
+
# @option options [Hash] :nat_gateway_subnets choose the subnets
|
50
|
+
# that will have NAT Gateway attached, default to public:
|
51
|
+
#
|
52
|
+
# @example: at `aws-rails-provisioner.yml`
|
53
|
+
# nat_gateway_subnets:
|
54
|
+
# type: public
|
55
|
+
#
|
56
|
+
# Note: Either subnet `:type` or `:name` can be provided
|
57
|
+
# @see {Aws::RailsProvisioner::SubnetSelection}
|
58
|
+
#
|
59
|
+
# @see AWS CDK VpcNetworkProps
|
60
|
+
def initialize(options = {})
|
61
|
+
@max_azs = options[:max_azs] || 3
|
62
|
+
@cidr = options[:cidr] || '10.0.0.0/21'
|
63
|
+
subnets_config = options[:subnets] || SUBNETS_DEFAULTS
|
64
|
+
@subnets = subnets_config.map do |name, config|
|
65
|
+
Subnet.new(
|
66
|
+
cidr_mask: config[:cidr_mask],
|
67
|
+
subnet_name: name,
|
68
|
+
type: config[:type]
|
69
|
+
)
|
70
|
+
end
|
71
|
+
@enable_dns = options[:enable_dns].nil? ? true : !!options[:enable_dns]
|
72
|
+
@nat_gateways = options[:nat_gateways] || @max_azs
|
73
|
+
@nat_gateway_subnets = Aws::RailsProvisioner::SubnetSelection.new(options[:nat_gateway_subnets]) if options[:nat_gateway_subnets]
|
74
|
+
end
|
75
|
+
|
76
|
+
# @return [Integer]
|
77
|
+
attr_reader :max_azs
|
78
|
+
|
79
|
+
# @return [Integer]
|
80
|
+
attr_reader :nat_gateways
|
81
|
+
|
82
|
+
# @return [Aws::RailsProvisioner::SubnetSelection | nil]
|
83
|
+
attr_reader :nat_gateway_subnets
|
84
|
+
|
85
|
+
# @return [String]
|
86
|
+
attr_reader :cidr
|
87
|
+
|
88
|
+
# @return [Boolean]
|
89
|
+
attr_reader :enable_dns
|
90
|
+
|
91
|
+
# @return [Array|nil]
|
92
|
+
attr_reader :subnets
|
93
|
+
|
94
|
+
class Subnet
|
95
|
+
|
96
|
+
def initialize(options)
|
97
|
+
@subnet_name = options.fetch(:subnet_name)
|
98
|
+
@cidr_mask = options.fetch(:cidr_mask)
|
99
|
+
@type = Aws::RailsProvisioner::Utils.subnet_type(options.fetch(:type))
|
100
|
+
end
|
101
|
+
|
102
|
+
attr_reader :subnet_name
|
103
|
+
|
104
|
+
attr_reader :cidr_mask
|
105
|
+
|
106
|
+
attr_reader :type
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,316 @@
|
|
1
|
+
import cdk = require('@aws-cdk/core');
|
2
|
+
{{#services}}
|
3
|
+
import {{abbr}} = require('@aws-cdk/aws-{{value}}');
|
4
|
+
{{/services}}
|
5
|
+
|
6
|
+
interface {{stack_prefix}}FargateStackProps {
|
7
|
+
vpc: ec2.IVpc,
|
8
|
+
cluster: ecs.ICluster,
|
9
|
+
}
|
10
|
+
|
11
|
+
export class {{stack_prefix}}FargateStack extends cdk.Stack {
|
12
|
+
public readonly service: ecs.FargateService;
|
13
|
+
public readonly repoName: string;
|
14
|
+
public readonly dbUrl: string;
|
15
|
+
public readonly db: rds.DatabaseCluster;
|
16
|
+
|
17
|
+
constructor(scope: cdk.App, id: string, props: {{stack_prefix}}FargateStackProps) {
|
18
|
+
super(scope, id);
|
19
|
+
|
20
|
+
// import resources
|
21
|
+
const cluster = props.cluster;
|
22
|
+
{{#db_cluster}}
|
23
|
+
const vpc = props.vpc;
|
24
|
+
|
25
|
+
// Create secret from SecretsManager
|
26
|
+
const username = '{{username}}';
|
27
|
+
const secret = new secretsmanager.Secret(this, 'Secret', {
|
28
|
+
generateSecretString: {
|
29
|
+
excludePunctuation: true
|
30
|
+
}
|
31
|
+
});
|
32
|
+
const password = secret.secretValue;
|
33
|
+
|
34
|
+
{{#parameter_group}}
|
35
|
+
{{#cfn}}
|
36
|
+
// Create DB Cluster ParameterGroup
|
37
|
+
const clusterParameterGroup = new rds.ClusterParameterGroup(this, 'DBClusterPG', {
|
38
|
+
description: '{{description}}',
|
39
|
+
family: '{{family}}',
|
40
|
+
parameters: {
|
41
|
+
{{#parameters}}
|
42
|
+
{{{.}}}
|
43
|
+
{{/parameters}}
|
44
|
+
}
|
45
|
+
});
|
46
|
+
{{/cfn}}
|
47
|
+
{{#name}}
|
48
|
+
// Import DB cluster ParameterGroup
|
49
|
+
const clusterParameterGroup = rds.ClusterParameterGroup.fromParameterGroupName(
|
50
|
+
this, 'DBClusterPG', '{{.}}');
|
51
|
+
{{/name}}
|
52
|
+
{{/parameter_group}}
|
53
|
+
// Create DB Cluster
|
54
|
+
const db = new rds.DatabaseCluster(this, 'DBCluster', {
|
55
|
+
engine: rds.DatabaseClusterEngine.{{engine}},
|
56
|
+
{{#engine_version}}
|
57
|
+
engineVersion: '{{.}}',
|
58
|
+
{{/engine_version}}
|
59
|
+
masterUser: {
|
60
|
+
username: username,
|
61
|
+
password: password
|
62
|
+
},
|
63
|
+
instanceProps: {
|
64
|
+
instanceType: new ec2.InstanceType('{{instance_type}}'),
|
65
|
+
vpc: vpc,
|
66
|
+
vpcSubnets: {
|
67
|
+
subnetType: ec2.SubnetType.{{instance_subnet}}
|
68
|
+
}
|
69
|
+
},
|
70
|
+
{{#kms_key}}
|
71
|
+
kmsKey: kms.Key.fromKeyArn(this, 'DBKMSKey', '{{.}}'),
|
72
|
+
{{/kms_key}}
|
73
|
+
{{#backup}}
|
74
|
+
backup: {
|
75
|
+
{{#retention_days}}
|
76
|
+
retentionDays: {{.}},
|
77
|
+
{{/retention_days}}
|
78
|
+
{{#preferred_window}}
|
79
|
+
preferred_window: '{{.}}',
|
80
|
+
{{/preferred_window}}
|
81
|
+
},
|
82
|
+
{{/backup}}
|
83
|
+
defaultDatabaseName: '{{db_name}}',
|
84
|
+
{{#cluster_identifier}}
|
85
|
+
clusterIdentifier: '{{.}}',
|
86
|
+
{{/cluster_identifier}}
|
87
|
+
{{#removal_policy}}
|
88
|
+
removalPolicy: cdk.RemovalPolicy.{{.}},
|
89
|
+
{{/removal_policy}}
|
90
|
+
{{#instance_identifier}}
|
91
|
+
instanceIdentifierBase: '{{.}}',
|
92
|
+
{{/instance_identifier}}
|
93
|
+
instances: {{instances}},
|
94
|
+
parameterGroup: clusterParameterGroup
|
95
|
+
});
|
96
|
+
const dbUrl = {{#postgres}}"postgres://"{{/postgres}}{{^postgres}}"mysql2://"{{/postgres}} + username + ":" + password + "@" + db.clusterEndpoint.socketAddress;
|
97
|
+
this.dbUrl = dbUrl;
|
98
|
+
{{/db_cluster}}
|
99
|
+
|
100
|
+
const asset = new ecr_assets.DockerImageAsset(this, 'ImageAssetBuild', {
|
101
|
+
directory: '{{source_path}}'
|
102
|
+
});
|
103
|
+
|
104
|
+
// compute repo name from asset image
|
105
|
+
const parts = asset.imageUri.split("@")[0].split("/");
|
106
|
+
const repoName = parts.slice(1, parts.length).join("/").split(":")[0];
|
107
|
+
this.repoName = repoName;
|
108
|
+
|
109
|
+
const ecrRepo = ecr.Repository.fromRepositoryName(this, 'EcrRepo', repoName);
|
110
|
+
const image = ecs.ContainerImage.fromEcrRepository(ecrRepo);
|
111
|
+
|
112
|
+
{{#fargate}}
|
113
|
+
// Fargate service
|
114
|
+
const lbFargate = new ecs_patterns.LoadBalancedFargateService(this, 'LBFargate', {
|
115
|
+
{{#service_name}}
|
116
|
+
serviceName: '{{.}}',
|
117
|
+
{{/service_name}}
|
118
|
+
cluster: cluster,
|
119
|
+
image: image,
|
120
|
+
containerName: '{{container_name}}',
|
121
|
+
containerPort: {{container_port}},
|
122
|
+
{{#certificate}}
|
123
|
+
certificate: certificatemanager.Certificate.fromCertificateArn(this, 'Certificate', '{{.}}'),
|
124
|
+
{{/certificate}}
|
125
|
+
{{#memory}}memoryLimitMiB: {{.}},{{/memory}}
|
126
|
+
{{#cpu}}cpu: {{.}},{{/cpu}}
|
127
|
+
environment: {
|
128
|
+
{{#has_db}}
|
129
|
+
'DATABASE_URL': dbUrl,
|
130
|
+
{{/has_db}}
|
131
|
+
{{#envs}}
|
132
|
+
{{{.}}}
|
133
|
+
{{/envs}}
|
134
|
+
},
|
135
|
+
enableLogging: true,
|
136
|
+
desiredCount: {{desired_count}},
|
137
|
+
{{#domain_name}}
|
138
|
+
domainName: '{{.}}',
|
139
|
+
{{/domain_name}}
|
140
|
+
{{#domain_zone}}
|
141
|
+
domainZone: '{{.}}',
|
142
|
+
{{/domain_zone}}
|
143
|
+
{{#public}}
|
144
|
+
publicLoadBalancer: true,
|
145
|
+
publicTasks: true
|
146
|
+
{{/public}}
|
147
|
+
});
|
148
|
+
{{#has_db}}
|
149
|
+
db.connections.allowDefaultPortFrom(lbFargate.service, 'From Fargate');
|
150
|
+
this.db = db;
|
151
|
+
{{/has_db}}
|
152
|
+
{{/fargate}}
|
153
|
+
{{#scaling}}
|
154
|
+
|
155
|
+
const scaling = lbFargate.service.autoScaleTaskCount({
|
156
|
+
maxCapacity: {{max_capacity}},
|
157
|
+
{{#min_capacity}}
|
158
|
+
minCapacity: {{.}}
|
159
|
+
{{/min_capacity}}
|
160
|
+
});
|
161
|
+
{{#on_cpu}}
|
162
|
+
scaling.scaleOnCpuUtilization('FargateScalingOnCpu', {
|
163
|
+
targetUtilizationPercent: {{target_util_percent}},
|
164
|
+
{{#disable_scale_in}}
|
165
|
+
disableScaleIn: true,
|
166
|
+
{{/disable_scale_in}}
|
167
|
+
{{#scale_in_cooldown}}
|
168
|
+
scaleInCooldownSec: {{.}},
|
169
|
+
{{/scale_in_cooldown}}
|
170
|
+
{{#scale_out_cooldown}}
|
171
|
+
scaleOutCooldownSec: {{.}},
|
172
|
+
{{/scale_out_cooldown}}
|
173
|
+
});
|
174
|
+
{{/on_cpu}}
|
175
|
+
{{#on_memory}}
|
176
|
+
scaling.scaleOnMemoryUtilization('FargateScalingOnMemory', {
|
177
|
+
targetUtilizationPercent: {{target_util_percent}},
|
178
|
+
{{#disable_scale_in}}
|
179
|
+
disableScaleIn: true,
|
180
|
+
{{/disable_scale_in}}
|
181
|
+
{{#scale_in_cooldown}}
|
182
|
+
scaleInCooldownSec: {{.}},
|
183
|
+
{{/scale_in_cooldown}}
|
184
|
+
{{#scale_out_cooldown}}
|
185
|
+
scaleOutCooldownSec: {{.}},
|
186
|
+
{{/scale_out_cooldown}}
|
187
|
+
});
|
188
|
+
{{/on_memory}}
|
189
|
+
{{#on_metric}}
|
190
|
+
{{#metric}}
|
191
|
+
const metric = new cloudwatch.Metric('Metric', {
|
192
|
+
metricName: {{name}},
|
193
|
+
metricNamespace: {{namespace}},
|
194
|
+
{{#color}}
|
195
|
+
color: '{{.}}',
|
196
|
+
{{/color}}
|
197
|
+
dimensions: {
|
198
|
+
{{#dimensions}}
|
199
|
+
{{{.}}}
|
200
|
+
{{/dimensions}}
|
201
|
+
}
|
202
|
+
{{#label}}
|
203
|
+
label: '{{.}}',
|
204
|
+
{{/label}}
|
205
|
+
{{#period_sec}}
|
206
|
+
periodSec: {{.}},
|
207
|
+
{{/period_sec}}
|
208
|
+
{{#statistic}}
|
209
|
+
statistic: {{.}},
|
210
|
+
{{/statistic}}
|
211
|
+
{{#unit}}
|
212
|
+
unit: cloudwatch.Unit.{{.}},
|
213
|
+
{{/unit}}
|
214
|
+
});
|
215
|
+
{{/metric}}
|
216
|
+
scaling.scaleOnMetric('FargateScalingOnMetric', {
|
217
|
+
metric: metric,
|
218
|
+
{{#scaling_steps?}}
|
219
|
+
scalingSteps: [
|
220
|
+
{{#scaling_steps}}
|
221
|
+
{
|
222
|
+
{{#change}}change: {{.}},{{/change}}
|
223
|
+
{{#lower}}lower: {{.}},{{/lower}}
|
224
|
+
{{#upper}}upper: {{.}}{{/upper}}
|
225
|
+
},
|
226
|
+
{{/scaling_steps}}
|
227
|
+
],
|
228
|
+
{{/scaling_steps?}}
|
229
|
+
{{#adjustment_type}}
|
230
|
+
adjustmentType: applicationautoscaling.{{.}},
|
231
|
+
{{/adjustment_type}}
|
232
|
+
{{#cooldown_sec}}
|
233
|
+
cooldownSec: {{.}},
|
234
|
+
{{/cooldown_sec}}
|
235
|
+
{{#min_adjustment_magnitude}}
|
236
|
+
minAdjustmentMagnitude: {{.}},
|
237
|
+
{{/min_adjustment_magnitude}}
|
238
|
+
});
|
239
|
+
{{/on_metric}}
|
240
|
+
{{#on_request}}
|
241
|
+
scaling.scaleOnRequestCount('FargateScalingOnRequest', {
|
242
|
+
requestsPerTarget: {{requests_per_target}},
|
243
|
+
targetGroup: target,
|
244
|
+
{{#disable_scale_in}}
|
245
|
+
disableScaleIn: true,
|
246
|
+
{{/disable_scale_in}}
|
247
|
+
{{#scale_in_cooldown}}
|
248
|
+
scaleInCooldownSec: {{.}},
|
249
|
+
{{/scale_in_cooldown}}
|
250
|
+
{{#scale_out_cooldown}}
|
251
|
+
scaleOutCooldownSec: {{.}},
|
252
|
+
{{/scale_out_cooldown}}
|
253
|
+
});
|
254
|
+
{{/on_request}}
|
255
|
+
{{#on_schedule}}
|
256
|
+
scaling.scaleOnSchedule('FargateScalingOnSchedule', {
|
257
|
+
schedule: {{{schedule}}},
|
258
|
+
{{#max_capacity}}
|
259
|
+
maxCapacity: {{.}},
|
260
|
+
{{/max_capacity}}
|
261
|
+
{{#min_capacity}}
|
262
|
+
minCapacity: {{.}},
|
263
|
+
{{/min_capacity}}
|
264
|
+
{{#start_time}}
|
265
|
+
startTime: new Date({{.}}),
|
266
|
+
{{/start_time}}
|
267
|
+
{{#end_time}}
|
268
|
+
endTime: new Date({{.}}),
|
269
|
+
{{/end_time}}
|
270
|
+
});
|
271
|
+
{{/on_schedule}}
|
272
|
+
{{#to_track_custom_metric}}
|
273
|
+
{{#metric}}
|
274
|
+
const custom_metric = new cloudwatch.Metric('CustomMetric', {
|
275
|
+
metricName: {{name}},
|
276
|
+
metricNamespace: {{namespace}},
|
277
|
+
{{#color}}
|
278
|
+
color: '{{.}}',
|
279
|
+
{{/color}}
|
280
|
+
dimensions: {
|
281
|
+
{{#dimensions}}
|
282
|
+
{{{.}}}
|
283
|
+
{{/dimensions}}
|
284
|
+
},
|
285
|
+
{{#label}}
|
286
|
+
label: '{{.}}',
|
287
|
+
{{/label}}
|
288
|
+
{{#period_sec}}
|
289
|
+
periodSec: {{.}},
|
290
|
+
{{/period_sec}}
|
291
|
+
{{#statistic}}
|
292
|
+
statistic: '{{.}}',
|
293
|
+
{{/statistic}}
|
294
|
+
{{#unit}}
|
295
|
+
unit: cloudwatch.Unit.{{.}},
|
296
|
+
{{/unit}}
|
297
|
+
});
|
298
|
+
{{/metric}}
|
299
|
+
scaling.scaleToTrackCustomMetric('FargateScalingOnCustomMetric', {
|
300
|
+
metric: custom_metric,
|
301
|
+
{{#disable_scale_in}}
|
302
|
+
disableScaleIn: true,
|
303
|
+
{{/disable_scale_in}}
|
304
|
+
{{#scale_in_cooldown}}
|
305
|
+
scaleInCooldownSec: {{.}},
|
306
|
+
{{/scale_in_cooldown}}
|
307
|
+
{{#scale_out_cooldown}}
|
308
|
+
scaleOutCooldownSec: {{.}},
|
309
|
+
{{/scale_out_cooldown}}
|
310
|
+
});
|
311
|
+
{{/to_track_custom_metric}}
|
312
|
+
|
313
|
+
{{/scaling}}
|
314
|
+
this.service = lbFargate.service;
|
315
|
+
}
|
316
|
+
}
|