ecs_deploy_cli 0.2.2 → 0.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c4714117729290e91e7d5869862246b6aee1d023bbeca7681b92620f18dd03e
4
- data.tar.gz: e6ddab9870c19af272723491398afd4ca49bf8f647182270ac71c0c3b08aa578
3
+ metadata.gz: 36c1f26447ccb1748f1c064fbee8c5417502162d564e43b697148f0c9b399a12
4
+ data.tar.gz: d2571aff0f5ae5dcdf556a3b3cdeb9177310bcbb230a0817d92c7d276d8fcd30
5
5
  SHA512:
6
- metadata.gz: 7dc1d20820ebf9f6d9c300b8f0f31df44ca256b379d6e84ca10e0c48f120ea566e94a61cb25694462fe03f67ae35b8658e64e0af4d5253ee14a9717c614b2377
7
- data.tar.gz: 903942389ab805b9201c46d55562994648bc8102b5ad6bed62770674cc115f39127d482fa8afd405dde058372413ef684d33e52af6509b4e0d4e4f4eab3b07bd
6
+ metadata.gz: 71e0f4b2ac6191c6bc8194f07a352ddb51056caa1b30071e7a92a108ca22b0a2d6fe0fa4b5e92e7793a0df13c0260b96c1d0748939816014254bf4027afd524a
7
+ data.tar.gz: c40587c040e0077860b3cf573b8d03b31a189ec931143612de2f1184b72379562ff8cc03fe14da6415713cd230edf854ced7844c7b611435c1caa1f0b71021ab
@@ -26,6 +26,7 @@ end
26
26
 
27
27
  require 'ecs_deploy_cli/version'
28
28
  require 'ecs_deploy_cli/dsl/auto_options'
29
+ require 'ecs_deploy_cli/dsl/cluster'
29
30
  require 'ecs_deploy_cli/dsl/container'
30
31
  require 'ecs_deploy_cli/dsl/task'
31
32
  require 'ecs_deploy_cli/dsl/cron'
@@ -26,6 +26,13 @@ module EcsDeployCli
26
26
  puts "ECS Deploy CLI Version #{EcsDeployCli::VERSION}."
27
27
  end
28
28
 
29
+ desc 'setup', 'Creates the cluster and relative services'
30
+ option :file, default: 'ECSFile'
31
+ def setup
32
+ @parser = load(options[:file])
33
+ runner.setup!
34
+ end
35
+
29
36
  desc 'deploy-scheduled-tasks', 'Updates all scheduled tasks defined in your ECSFile'
30
37
  option :file, default: 'ECSFile'
31
38
  def deploy_scheduled_tasks
@@ -0,0 +1,412 @@
1
+ AWSTemplateFormatVersion: '2010-09-09'
2
+ Description: >
3
+ AWS CloudFormation template to create a new VPC
4
+ or use an existing VPC for ECS deployment
5
+ in Create Cluster Wizard. Requires exactly 1
6
+ Instance Types for a Spot Request.
7
+ Parameters:
8
+ EcsClusterName:
9
+ Type: String
10
+ Description: >
11
+ Specifies the ECS Cluster Name with which the resources would be
12
+ associated
13
+ Default: default
14
+ EcsAmiId:
15
+ Type: String
16
+ Description: Specifies the AMI ID for your container instances.
17
+ EcsInstanceType:
18
+ Type: CommaDelimitedList
19
+ Description: >
20
+ Specifies the EC2 instance type for your container instances.
21
+ Defaults to m4.large
22
+ Default: m4.large
23
+ ConstraintDescription: must be a valid EC2 instance type.
24
+ KeyName:
25
+ Type: String
26
+ Description: >
27
+ Optional - Specifies the name of an existing Amazon EC2 key pair
28
+ to enable SSH access to the EC2 instances in your cluster.
29
+ Default: ''
30
+ VpcId:
31
+ Type: String
32
+ Description: >
33
+ Optional - Specifies the ID of an existing VPC in which to launch
34
+ your container instances. If you specify a VPC ID, you must specify a list of
35
+ existing subnets in that VPC. If you do not specify a VPC ID, a new VPC is created
36
+ with atleast 1 subnet.
37
+ Default: ''
38
+ ConstraintDescription: >
39
+ VPC Id must begin with 'vpc-' or leave blank to have a
40
+ new VPC created
41
+ SubnetIds:
42
+ Type: CommaDelimitedList
43
+ Description: >
44
+ Optional - Specifies the Comma separated list of existing VPC Subnet
45
+ Ids where ECS instances will run
46
+ Default: ''
47
+ SecurityGroupId:
48
+ Type: String
49
+ Description: >
50
+ Optional - Specifies the Security Group Id of an existing Security
51
+ Group. Leave blank to have a new Security Group created
52
+ Default: ''
53
+ VpcCidr:
54
+ Type: String
55
+ Description: Optional - Specifies the CIDR Block of VPC
56
+ Default: ''
57
+ SubnetCidr1:
58
+ Type: String
59
+ Description: Specifies the CIDR Block of Subnet 1
60
+ Default: ''
61
+ SubnetCidr2:
62
+ Type: String
63
+ Description: Specifies the CIDR Block of Subnet 2
64
+ Default: ''
65
+ SubnetCidr3:
66
+ Type: String
67
+ Description: Specifies the CIDR Block of Subnet 3
68
+ Default: ''
69
+ AsgMaxSize:
70
+ Type: Number
71
+ Description: >
72
+ Specifies the number of instances to launch and register to the cluster.
73
+ Defaults to 1.
74
+ Default: '1'
75
+ IamRoleInstanceProfile:
76
+ Type: String
77
+ Description: >
78
+ Specifies the Name or the Amazon Resource Name (ARN) of the instance
79
+ profile associated with the IAM role for the instance
80
+ SecurityIngressFromPort:
81
+ Type: Number
82
+ Description: >
83
+ Optional - Specifies the Start of Security Group port to open on
84
+ ECS instances - defaults to port 0
85
+ Default: '0'
86
+ SecurityIngressToPort:
87
+ Type: Number
88
+ Description: >
89
+ Optional - Specifies the End of Security Group port to open on ECS
90
+ instances - defaults to port 65535
91
+ Default: '65535'
92
+ SecurityIngressCidrIp:
93
+ Type: String
94
+ Description: >
95
+ Optional - Specifies the CIDR/IP range for Security Ports - defaults
96
+ to 0.0.0.0/0
97
+ Default: 0.0.0.0/0
98
+ EcsEndpoint:
99
+ Type: String
100
+ Description: >
101
+ Optional - Specifies the ECS Endpoint for the ECS Agent to connect to
102
+ Default: ''
103
+ VpcAvailabilityZones:
104
+ Type: CommaDelimitedList
105
+ Description: >
106
+ Specifies a comma-separated list of 3 VPC Availability Zones for
107
+ the creation of new subnets. These zones must have the available status.
108
+ Default: ''
109
+ RootEbsVolumeSize:
110
+ Type: Number
111
+ Description: >
112
+ Optional - Specifies the Size in GBs of the root EBS volume
113
+ Default: 30
114
+ EbsVolumeSize:
115
+ Type: Number
116
+ Description: >
117
+ Optional - Specifies the Size in GBs of the data storage EBS volume used by the Docker in the AL1 ECS-optimized AMI
118
+ Default: 22
119
+ EbsVolumeType:
120
+ Type: String
121
+ Description: Optional - Specifies the Type of (Amazon EBS) volume
122
+ Default: ''
123
+ AllowedValues:
124
+ - ''
125
+ - standard
126
+ - io1
127
+ - gp2
128
+ - sc1
129
+ - st1
130
+ ConstraintDescription: Must be a valid EC2 volume type.
131
+ RootDeviceName:
132
+ Type: String
133
+ Description: Optional - Specifies the device mapping for the root EBS volume.
134
+ Default: /dev/xvda
135
+ DeviceName:
136
+ Type: String
137
+ Description: Optional - Specifies the device mapping for the EBS volume used for data storage. Only applicable to AL1.
138
+ UseSpot:
139
+ Type: String
140
+ Default: 'false'
141
+ IamSpotFleetRoleArn:
142
+ Type: String
143
+ Default: ''
144
+ SpotPrice:
145
+ Type: String
146
+ Default: ''
147
+ SpotAllocationStrategy:
148
+ Type: String
149
+ Default: 'diversified'
150
+ AllowedValues:
151
+ - 'lowestPrice'
152
+ - 'diversified'
153
+ UserData:
154
+ Type: String
155
+ IsWindows:
156
+ Type: String
157
+ Default: 'false'
158
+ ConfigureRootVolume:
159
+ Type: String
160
+ Description: Optional - Specifies if there should be customization of the root volume
161
+ Default: 'false'
162
+ ConfigureDataVolume:
163
+ Type: String
164
+ Description: Optional - Specifies if there should be customization of the data volume
165
+ Default: 'true'
166
+ AutoAssignPublicIp:
167
+ Type: String
168
+ Default: 'INHERIT'
169
+ Conditions:
170
+ CreateEC2LCWithKeyPair:
171
+ !Not [!Equals [!Ref KeyName, '']]
172
+ SetEndpointToECSAgent:
173
+ !Not [!Equals [!Ref EcsEndpoint, '']]
174
+ CreateNewSecurityGroup:
175
+ !Equals [!Ref SecurityGroupId, '']
176
+ CreateNewVpc:
177
+ !Equals [!Ref VpcId, '']
178
+ CreateSubnet1: !And
179
+ - !Not [!Equals [!Ref SubnetCidr1, '']]
180
+ - !Condition CreateNewVpc
181
+ CreateSubnet2: !And
182
+ - !Not [!Equals [!Ref SubnetCidr2, '']]
183
+ - !Condition CreateSubnet1
184
+ CreateSubnet3: !And
185
+ - !Not [!Equals [!Ref SubnetCidr3, '']]
186
+ - !Condition CreateSubnet2
187
+ CreateWithSpot: !Equals [!Ref UseSpot, 'true']
188
+ CreateWithASG: !Not [!Condition CreateWithSpot]
189
+ CreateWithSpotPrice: !Not [!Equals [!Ref SpotPrice, '']]
190
+ IsConfiguringRootVolume: !Equals [!Ref ConfigureRootVolume, 'true']
191
+ IsConfiguringDataVolume: !Equals [!Ref ConfigureDataVolume, 'true']
192
+ IsInheritPublicIp: !Equals [!Ref AutoAssignPublicIp, 'INHERIT']
193
+ Resources:
194
+ Vpc:
195
+ Condition: CreateSubnet1
196
+ Type: AWS::EC2::VPC
197
+ Properties:
198
+ CidrBlock: !Ref VpcCidr
199
+ EnableDnsSupport: true
200
+ EnableDnsHostnames: true
201
+ PubSubnetAz1:
202
+ Condition: CreateSubnet1
203
+ Type: AWS::EC2::Subnet
204
+ Properties:
205
+ VpcId: !Ref Vpc
206
+ CidrBlock: !Ref SubnetCidr1
207
+ AvailabilityZone: !Select [ 0, !Ref VpcAvailabilityZones ]
208
+ MapPublicIpOnLaunch: true
209
+ PubSubnetAz2:
210
+ Condition: CreateSubnet2
211
+ Type: AWS::EC2::Subnet
212
+ Properties:
213
+ VpcId: !Ref Vpc
214
+ CidrBlock: !Ref SubnetCidr2
215
+ AvailabilityZone: !Select [ 1, !Ref VpcAvailabilityZones ]
216
+ MapPublicIpOnLaunch: true
217
+ PubSubnetAz3:
218
+ Condition: CreateSubnet3
219
+ Type: AWS::EC2::Subnet
220
+ Properties:
221
+ VpcId: !Ref Vpc
222
+ CidrBlock: !Ref SubnetCidr3
223
+ AvailabilityZone: !Select [ 2, !Ref VpcAvailabilityZones ]
224
+ MapPublicIpOnLaunch: true
225
+ InternetGateway:
226
+ Condition: CreateSubnet1
227
+ Type: AWS::EC2::InternetGateway
228
+ AttachGateway:
229
+ Condition: CreateSubnet1
230
+ Type: AWS::EC2::VPCGatewayAttachment
231
+ Properties:
232
+ VpcId: !Ref Vpc
233
+ InternetGatewayId: !Ref InternetGateway
234
+ RouteViaIgw:
235
+ Condition: CreateSubnet1
236
+ Type: AWS::EC2::RouteTable
237
+ Properties:
238
+ VpcId: !Ref Vpc
239
+ PublicRouteViaIgw:
240
+ Condition: CreateSubnet1
241
+ Type: AWS::EC2::Route
242
+ DependsOn: AttachGateway
243
+ Properties:
244
+ RouteTableId: !Ref RouteViaIgw
245
+ DestinationCidrBlock: 0.0.0.0/0
246
+ GatewayId: !Ref InternetGateway
247
+ PubSubnet1RouteTableAssociation:
248
+ Condition: CreateSubnet1
249
+ Type: AWS::EC2::SubnetRouteTableAssociation
250
+ Properties:
251
+ SubnetId: !Ref PubSubnetAz1
252
+ RouteTableId: !Ref RouteViaIgw
253
+ PubSubnet2RouteTableAssociation:
254
+ Condition: CreateSubnet2
255
+ Type: AWS::EC2::SubnetRouteTableAssociation
256
+ Properties:
257
+ SubnetId: !Ref PubSubnetAz2
258
+ RouteTableId: !Ref RouteViaIgw
259
+ PubSubnet3RouteTableAssociation:
260
+ Condition: CreateSubnet3
261
+ Type: AWS::EC2::SubnetRouteTableAssociation
262
+ Properties:
263
+ SubnetId: !Ref PubSubnetAz3
264
+ RouteTableId: !Ref RouteViaIgw
265
+ EcsSecurityGroup:
266
+ Condition: CreateNewSecurityGroup
267
+ Type: AWS::EC2::SecurityGroup
268
+ Properties:
269
+ GroupDescription: ECS Allowed Ports
270
+ VpcId: !If [ CreateSubnet1, !Ref Vpc, !Ref VpcId ]
271
+ SecurityGroupIngress:
272
+ IpProtocol: tcp
273
+ FromPort: !Ref SecurityIngressFromPort
274
+ ToPort: !Ref SecurityIngressToPort
275
+ CidrIp: !Ref SecurityIngressCidrIp
276
+
277
+
278
+ ## TODO: FINISH
279
+ # ALBSecurityGroup:
280
+ # Condition: CreateNewLoadBalancer
281
+ # Type: AWS::EC2::SecurityGroup
282
+ # Properties:
283
+ # GroupDescription: ECS Allowed Ports
284
+ # VpcId: !If [ CreateSubnet1, !Ref Vpc, !Ref VpcId ]
285
+ # SecurityGroupIngress:
286
+ # IpProtocol: tcp
287
+ # FromPort: !Ref SecurityIngressFromPort
288
+ # ToPort: !Ref SecurityIngressToPort
289
+ # CidrIp: !Ref SecurityIngressCidrIp
290
+
291
+ # EcsLoadBalancer:
292
+ # Condition: CreateNewLoadBalancer
293
+ # Type: AWS::ElasticLoadBalancing::LoadBalancer
294
+ # Properties:
295
+ # LoadBalancerName: !Ref LoadBalancer
296
+ # AvailabilityZones:
297
+ # - !Select [ 0, !Ref VpcAvailabilityZones ]
298
+ # - !Select [ 1, !Ref VpcAvailabilityZones ]
299
+ # - !Select [ 2, !Ref VpcAvailabilityZones ]
300
+ # SecurityGroups:
301
+ # - !Select [ 0, !Ref VpcAvailabilityZones ]
302
+ # Subnets:
303
+ # -
304
+ ## /TODO: FINISH
305
+
306
+ EcsInstanceLc:
307
+ Type: AWS::AutoScaling::LaunchConfiguration
308
+ Condition: CreateWithASG
309
+ Properties:
310
+ ImageId: !Ref EcsAmiId
311
+ InstanceType: !Select [ 0, !Ref EcsInstanceType ]
312
+ AssociatePublicIpAddress: !If [ IsInheritPublicIp, !Ref "AWS::NoValue", !Ref AutoAssignPublicIp ]
313
+ IamInstanceProfile: !Ref IamRoleInstanceProfile
314
+ KeyName: !If [ CreateEC2LCWithKeyPair, !Ref KeyName, !Ref "AWS::NoValue" ]
315
+ SecurityGroups: [ !If [ CreateNewSecurityGroup, !Ref EcsSecurityGroup, !Ref SecurityGroupId ] ]
316
+ BlockDeviceMappings:
317
+ - !If
318
+ - IsConfiguringRootVolume
319
+ - DeviceName: !Ref RootDeviceName
320
+ Ebs:
321
+ VolumeSize: !Ref RootEbsVolumeSize
322
+ VolumeType: !Ref EbsVolumeType
323
+ - !Ref AWS::NoValue
324
+ - !If
325
+ - IsConfiguringDataVolume
326
+ - DeviceName: !Ref DeviceName
327
+ Ebs:
328
+ VolumeSize: !Ref EbsVolumeSize
329
+ VolumeType: !Ref EbsVolumeType
330
+ - !Ref AWS::NoValue
331
+ UserData:
332
+ Fn::Base64: !Ref UserData
333
+ EcsInstanceAsg:
334
+ Type: AWS::AutoScaling::AutoScalingGroup
335
+ Condition: CreateWithASG
336
+ Properties:
337
+ VPCZoneIdentifier: !If
338
+ - CreateSubnet1
339
+ - !If
340
+ - CreateSubnet2
341
+ - !If
342
+ - CreateSubnet3
343
+ - [ !Sub "${PubSubnetAz1}, ${PubSubnetAz2}, ${PubSubnetAz3}" ]
344
+ - [ !Sub "${PubSubnetAz1}, ${PubSubnetAz2}" ]
345
+ - [ !Sub "${PubSubnetAz1}" ]
346
+ - !Ref SubnetIds
347
+ LaunchConfigurationName: !Ref EcsInstanceLc
348
+ MinSize: '0'
349
+ MaxSize: !Ref AsgMaxSize
350
+ DesiredCapacity: !Ref AsgMaxSize
351
+ Tags:
352
+ -
353
+ Key: Name
354
+ Value: !Sub "ECS Instance - ${AWS::StackName}"
355
+ PropagateAtLaunch: true
356
+ -
357
+ Key: Description
358
+ Value: "This instance is the part of the Auto Scaling group which was created through ECS Console"
359
+ PropagateAtLaunch: true
360
+ EcsSpotFleet:
361
+ Condition: CreateWithSpot
362
+ Type: AWS::EC2::SpotFleet
363
+ Properties:
364
+ SpotFleetRequestConfigData:
365
+ AllocationStrategy: !Ref SpotAllocationStrategy
366
+ IamFleetRole: !Ref IamSpotFleetRoleArn
367
+ TargetCapacity: !Ref AsgMaxSize
368
+ SpotPrice: !If [ CreateWithSpotPrice, !Ref SpotPrice, !Ref 'AWS::NoValue' ]
369
+ TerminateInstancesWithExpiration: true
370
+ LaunchSpecifications:
371
+ -
372
+ IamInstanceProfile:
373
+ Arn: !Ref IamRoleInstanceProfile
374
+ ImageId: !Ref EcsAmiId
375
+ InstanceType: !Select [ 0, !Ref EcsInstanceType ]
376
+ KeyName: !If [ CreateEC2LCWithKeyPair, !Ref KeyName, !Ref "AWS::NoValue" ]
377
+ Monitoring:
378
+ Enabled: true
379
+ SecurityGroups:
380
+ - GroupId: !If [ CreateNewSecurityGroup, !Ref EcsSecurityGroup, !Ref SecurityGroupId ]
381
+ SubnetId: !If
382
+ - CreateSubnet1
383
+ - !If
384
+ - CreateSubnet2
385
+ - !If
386
+ - CreateSubnet3
387
+ - !Join [ "," , [ !Ref PubSubnetAz1, !Ref PubSubnetAz2, !Ref PubSubnetAz3 ] ]
388
+ - !Join [ "," , [ !Ref PubSubnetAz1, !Ref PubSubnetAz2 ] ]
389
+ - !Ref PubSubnetAz1
390
+ - !Join [ "," , !Ref SubnetIds ]
391
+ BlockDeviceMappings:
392
+ - DeviceName: !Ref DeviceName
393
+ Ebs:
394
+ VolumeSize: !Ref EbsVolumeSize
395
+ VolumeType: !Ref EbsVolumeType
396
+ UserData:
397
+ Fn::Base64: !Ref UserData
398
+ Outputs:
399
+ EcsInstanceAsgName:
400
+ Condition: CreateWithASG
401
+ Description: Auto Scaling Group Name for ECS Instances
402
+ Value: !Ref EcsInstanceAsg
403
+ EcsSpotFleetRequestId:
404
+ Condition: CreateWithSpot
405
+ Description: Spot Fleet Request for ECS Instances
406
+ Value: !Ref EcsSpotFleet
407
+ UsedByECSCreateCluster:
408
+ Description: Flag used by ECS Create Cluster Wizard
409
+ Value: 'true'
410
+ TemplateVersion:
411
+ Description: The version of the template used by Create Cluster Wizard
412
+ Value: '2.0.0'
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EcsDeployCli
4
+ module DSL
5
+ class Cluster
6
+ include AutoOptions
7
+
8
+ allowed_options :instances_count, :instance_type, :ebs_volume_size, :keypair_name
9
+
10
+ def initialize(name, config)
11
+ @config = config
12
+ _options[:name] = name.to_s
13
+ end
14
+
15
+ def vpc(id = nil, &block)
16
+ @vpc = VPC.new(id)
17
+ @vpc.instance_exec(&block)
18
+ end
19
+
20
+ def as_definition
21
+ {
22
+ instances_count: 1,
23
+
24
+ device_name: '/dev/xvda',
25
+ ebs_volume_size: 22,
26
+ ebs_volume_type: 'gp2',
27
+
28
+ root_device_name: '/dev/xvdcz',
29
+ root_ebs_volume_size: 30,
30
+
31
+ vpc: @vpc&.as_definition
32
+ }.merge(_options)
33
+ end
34
+
35
+ class VPC
36
+ include AutoOptions
37
+ allowed_options :cidr, :subnet1, :subnet2, :subnet3
38
+
39
+ def initialize(id)
40
+ _options[:id] = id
41
+ end
42
+
43
+ def availability_zones(*values)
44
+ _options[:availability_zones] = values.join(',')
45
+ end
46
+
47
+ def subnet_ids(*values)
48
+ _options[:subnet_ids] = values.join(',')
49
+ end
50
+
51
+ def as_definition
52
+ validate! if _options[:id]
53
+
54
+ {
55
+ cidr: '10.0.0.0/16',
56
+ subnet1: '10.0.0.0/24',
57
+ subnet2: '10.0.1.0/24',
58
+ subnet3: '10.0.2.0/24'
59
+ }.merge(_options)
60
+ end
61
+
62
+ def validate!
63
+ [
64
+ :subnet1, :subnet_ids, :availability_zones
65
+ ].each { |key| raise "Missing required parameter #{key}" unless _options[key] }
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -40,8 +40,11 @@ module EcsDeployCli
40
40
  @crons[name].instance_exec(&block)
41
41
  end
42
42
 
43
- def cluster(name)
43
+ def cluster(name, &block)
44
44
  config[:cluster] = name
45
+ @cluster ||= {}.with_indifferent_access
46
+ @cluster = Cluster.new(name, config)
47
+ @cluster.instance_exec(&block) if block
45
48
  end
46
49
 
47
50
  def config
@@ -58,7 +61,8 @@ module EcsDeployCli
58
61
  resolved_containers = (@containers || {}).transform_values(&:as_definition)
59
62
  resolved_tasks = (@tasks || {}).transform_values { |t| t.as_definition(resolved_containers) }
60
63
  resolved_crons = (@crons || {}).transform_values { |t| t.as_definition(resolved_tasks) }
61
- [@services, resolved_tasks, resolved_crons]
64
+ resolved_cluster = @cluster.as_definition
65
+ [@services, resolved_tasks, resolved_crons, resolved_cluster]
62
66
  end
63
67
 
64
68
  def self.load(file)
@@ -18,13 +18,42 @@ module EcsDeployCli
18
18
  _options
19
19
  end
20
20
 
21
+ def load_balancer(name, &block)
22
+ @load_balancers ||= []
23
+
24
+ load_balancer = LoadBalancer.new(name, @config)
25
+ load_balancer.instance_exec(&block)
26
+
27
+ @load_balancers << load_balancer
28
+ end
29
+
21
30
  def as_definition(task)
22
31
  {
23
32
  cluster: @config[:cluster],
24
- service: service_name,
25
- task_definition: task
33
+ service: _options[:service],
34
+ task_definition: task,
35
+ load_balancers: @load_balancers&.map(&:as_definition) || []
26
36
  }
27
37
  end
38
+
39
+ class LoadBalancer
40
+ include AutoOptions
41
+ allowed_options :container_name, :container_port
42
+
43
+ def initialize(name, config)
44
+ _options[:load_balancer_name] = name
45
+ @config = config
46
+ end
47
+
48
+ def target_group_arn(value)
49
+ _options[:target_group_arn] = "arn:aws:elasticloadbalancing:#{@config[:aws_region]}:#{@config[:aws_profile_id]}:targetgroup/#{value}"
50
+ _options.delete(:load_balancer_name)
51
+ end
52
+
53
+ def as_definition
54
+ _options
55
+ end
56
+ end
28
57
  end
29
58
  end
30
59
  end
@@ -7,6 +7,7 @@ require 'ecs_deploy_cli/runners/diff'
7
7
  require 'ecs_deploy_cli/runners/update_crons'
8
8
  require 'ecs_deploy_cli/runners/update_services'
9
9
  require 'ecs_deploy_cli/runners/run_task'
10
+ require 'ecs_deploy_cli/runners/setup'
10
11
 
11
12
  module EcsDeployCli
12
13
  class Runner
@@ -14,6 +15,10 @@ module EcsDeployCli
14
15
  @parser = parser
15
16
  end
16
17
 
18
+ def setup!
19
+ EcsDeployCli::Runners::Setup.new(@parser).run!
20
+ end
21
+
17
22
  def validate!
18
23
  EcsDeployCli::Runners::Validate.new(@parser).run!
19
24
  end
@@ -11,14 +11,35 @@ module EcsDeployCli
11
11
  raise NotImplementedError, 'abstract method'
12
12
  end
13
13
 
14
+ def update_task(definition)
15
+ _update_task(definition)
16
+ end
17
+
14
18
  protected
15
19
 
16
20
  def _update_task(definition)
21
+ definition[:container_definitions].each do |container|
22
+ next unless container.dig(:log_configuration, :log_driver) == 'awslogs'
23
+
24
+ _create_cloudwatch_logs_if_needed(container.dig(:log_configuration, :options, 'awslogs-group'))
25
+ end
26
+
17
27
  ecs_client.register_task_definition(
18
28
  definition
19
29
  ).to_h[:task_definition]
20
30
  end
21
31
 
32
+ def _create_cloudwatch_logs_if_needed(prefix)
33
+ log_group = cwl_client.describe_log_groups(log_group_name_prefix: prefix, limit: 1).to_h[:log_groups]
34
+ return if log_group.any?
35
+
36
+ cwl_client.create_log_group(log_group_name: prefix)
37
+ cwl_client.put_retention_policy(
38
+ log_group_name: prefix,
39
+ retention_in_days: 14
40
+ )
41
+ end
42
+
22
43
  def ec2_client
23
44
  @ec2_client ||= begin
24
45
  require 'aws-sdk-ec2'
@@ -46,6 +67,36 @@ module EcsDeployCli
46
67
  end
47
68
  end
48
69
 
70
+ def ssm_client
71
+ @cwl_client ||= begin
72
+ require 'aws-sdk-ssm'
73
+ Aws::SSM::Client.new(
74
+ profile: ENV.fetch('AWS_PROFILE', 'default'),
75
+ region: config[:aws_region]
76
+ )
77
+ end
78
+ end
79
+
80
+ def cwl_client
81
+ @cwl_client ||= begin
82
+ require 'aws-sdk-cloudwatchlogs'
83
+ Aws::CloudWatchLogs::Client.new(
84
+ profile: ENV.fetch('AWS_PROFILE', 'default'),
85
+ region: config[:aws_region]
86
+ )
87
+ end
88
+ end
89
+
90
+ def cf_client
91
+ @cl_client ||= begin
92
+ require 'aws-sdk-cloudformation'
93
+ Aws::CloudFormation::Client.new(
94
+ profile: ENV.fetch('AWS_PROFILE', 'default'),
95
+ region: config[:aws_region]
96
+ )
97
+ end
98
+ end
99
+
49
100
  def config
50
101
  @parser.config
51
102
  end
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EcsDeployCli
4
+ module Runners
5
+ class Setup < Base
6
+ def run!
7
+ services, resolved_tasks, _, cluster_options = @parser.resolve
8
+
9
+ setup_cluster! cluster_options
10
+ setup_services! services, resolved_tasks: resolved_tasks
11
+ end
12
+
13
+ private
14
+
15
+ def setup_cluster!(cluster_options)
16
+ clusters = ecs_client.describe_clusters(clusters: [config[:cluster]]).to_h[:clusters]
17
+ if clusters.length == 1
18
+ EcsDeployCli.logger.info 'Cluster already created, skipping.'
19
+ return
20
+ end
21
+
22
+ EcsDeployCli.logger.info "Creating cluster #{config[:cluster]}..."
23
+
24
+ params = create_params(cluster_options)
25
+
26
+ ecs_client.create_cluster(
27
+ cluster_name: config[:cluster]
28
+ )
29
+
30
+ stack_name = "EC2ContainerService-#{config[:cluster]}"
31
+
32
+
33
+ cf_client.create_stack(
34
+ stack_name: stack_name,
35
+ template_body: File.read(File.join(__dir__, '..', 'cloudformation', 'default.yml')),
36
+ on_failure: 'ROLLBACK',
37
+ parameters: format_cloudformation_params(params)
38
+ )
39
+
40
+ cf_client.wait_until(:stack_create_complete, { stack_name: stack_name }, delay: 30, max_attempts: 120)
41
+ EcsDeployCli.logger.info "Cluster #{config[:cluster]} created!"
42
+ end
43
+
44
+ def setup_services!(services, resolved_tasks:)
45
+ services.each do |service_name, service_definition|
46
+ if ecs_client.describe_services(cluster: config[:cluster], services: [service_name]).to_h[:services].any?
47
+ EcsDeployCli.logger.info "Service #{service_name} already created, skipping."
48
+ next
49
+ end
50
+
51
+ EcsDeployCli.logger.info "Creating service #{service_name}..."
52
+ task_definition = _update_task resolved_tasks[service_definition.options[:task]]
53
+ task_name = "#{task_definition[:family]}:#{task_definition[:revision]}"
54
+
55
+ ecs_client.create_service(
56
+ cluster: config[:cluster],
57
+ desired_count: 1,
58
+ load_balancers: service_definition.as_definition(task_definition)[:load_balancers],
59
+ service_name: service_name,
60
+ task_definition: task_name
61
+ )
62
+ EcsDeployCli.logger.info "Service #{service_name} created!"
63
+ end
64
+ end
65
+
66
+ def create_params(cluster_options)
67
+ raise ArgumentError, 'Missing vpc configuration' unless cluster_options[:vpc]
68
+
69
+ {
70
+ 'AsgMaxSize' => cluster_options[:instances_count],
71
+ 'AutoAssignPublicIp' => 'INHERIT',
72
+ 'ConfigureDataVolume' => false,
73
+ 'ConfigureRootVolume' => true,
74
+ 'DeviceName' => cluster_options[:device_name],
75
+ 'EbsVolumeSize' => cluster_options[:ebs_volume_size],
76
+ 'EbsVolumeType' => cluster_options[:ebs_volume_type],
77
+ 'EcsAmiId' => load_ami_id,
78
+ 'EcsClusterName' => config[:cluster],
79
+ 'EcsEndpoint' => nil,
80
+ 'EcsInstanceType' => cluster_options[:instance_type],
81
+ 'IamRoleInstanceProfile' => "arn:aws:iam::#{config[:aws_profile_id]}:instance-profile/ecsInstanceRole",
82
+ 'IamSpotFleetRoleArn' => nil,
83
+ 'IsWindows' => false,
84
+ 'KeyName' => cluster_options[:keypair_name],
85
+ 'RootDeviceName' => cluster_options[:root_device_name],
86
+ 'RootEbsVolumeSize' => cluster_options[:root_ebs_volume_size],
87
+
88
+ ##### TODO: Implement this feature
89
+ 'SecurityGroupId' => nil,
90
+ 'SecurityIngressCidrIp' => '0.0.0.0/0',
91
+ 'SecurityIngressFromPort' => 80,
92
+ 'SecurityIngressToPort' => 80,
93
+ #####
94
+
95
+ ##### TODO: Implement this feature
96
+ 'SpotAllocationStrategy' => 'diversified',
97
+ 'SpotPrice' => nil,
98
+ 'UseSpot' => false,
99
+ #####
100
+
101
+ 'UserData' => "#!/bin/bash\necho ECS_CLUSTER=#{config[:cluster]} >> /etc/ecs/ecs.config;echo ECS_BACKEND_HOST= >> /etc/ecs/ecs.config;",
102
+ 'VpcAvailabilityZones' => cluster_options.dig(:vpc, :availability_zones),
103
+ 'VpcCidr' => cluster_options.dig(:vpc, :cidr),
104
+ 'SubnetCidr1' => cluster_options.dig(:vpc, :subnet1),
105
+ 'SubnetCidr2' => cluster_options.dig(:vpc, :subnet2),
106
+ 'SubnetCidr3' => cluster_options.dig(:vpc, :subnet3),
107
+
108
+ 'VpcId' => cluster_options.dig(:vpc, :id),
109
+ 'SubnetIds' => cluster_options.dig(:vpc, :subnet_ids)
110
+ }
111
+ end
112
+
113
+ def format_cloudformation_params(params)
114
+ params.map { |k, v| { parameter_key: k, parameter_value: v.to_s } }
115
+ end
116
+
117
+ def load_ami_id
118
+ ami_data = ssm_client.get_parameter(
119
+ name: '/aws/service/ecs/optimized-ami/amazon-linux-2/recommended'
120
+ ).to_h[:parameter]
121
+
122
+ ami_details = JSON.parse(ami_data[:value]).with_indifferent_access
123
+
124
+ ami_details[:image_id]
125
+ end
126
+ end
127
+ end
128
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EcsDeployCli
4
- VERSION = '0.2.2'
4
+ VERSION = '0.3.0'
5
5
  end
@@ -48,6 +48,14 @@ describe EcsDeployCli::CLI do
48
48
  described_class.start(['run-task', 'yourproject', '--subnets', 'subnet-123123', '--file', 'spec/support/ECSFile'])
49
49
  end
50
50
 
51
+ it 'runs setup' do
52
+ expect(runner).to receive(:setup!)
53
+ described_class.no_commands do
54
+ expect_any_instance_of(described_class).to receive(:runner).at_least(:once).and_return(runner)
55
+ end
56
+ expect { described_class.start(['setup', '--file', 'spec/support/ECSFile']) }.to output(/[WARNING]/).to_stdout
57
+ end
58
+
51
59
  it 'runs deploy' do
52
60
  expect(runner).to receive(:update_crons!)
53
61
  expect(runner).to receive(:update_services!).with(timeout: 500)
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe EcsDeployCli::DSL::Cluster do
6
+ context 'defines cluster data' do
7
+ subject { described_class.new('mydata-cluster', { aws_profile_id: '123123', aws_region: 'eu-central-1' }) }
8
+
9
+ it '#vpc' do
10
+ subject.instances_count 1
11
+ subject.instance_type 't2.small'
12
+ subject.keypair_name 'test'
13
+
14
+ subject.vpc do
15
+ cidr '11.0.0.0/16'
16
+ subnet1 '11.0.0.0/24'
17
+ subnet2 '11.0.1.0/24'
18
+ subnet3 '11.0.2.0/24'
19
+ subnet_ids 'subnet-123', 'subnet-321', 'subnet-333'
20
+
21
+ availability_zones 'eu-central-1a', 'eu-central-1b', 'eu-central-1c'
22
+ end
23
+
24
+ expect(subject.as_definition).to eq(
25
+ {
26
+ device_name: '/dev/xvda',
27
+ ebs_volume_size: 22,
28
+ ebs_volume_type: 'gp2',
29
+ instances_count: 1,
30
+ instance_type: 't2.small',
31
+ keypair_name: 'test',
32
+ name: 'mydata-cluster',
33
+ root_device_name: '/dev/xvdcz',
34
+ root_ebs_volume_size: 30,
35
+ vpc: {
36
+ availability_zones: 'eu-central-1a,eu-central-1b,eu-central-1c',
37
+ cidr: '11.0.0.0/16',
38
+ id: nil,
39
+ subnet1: '11.0.0.0/24',
40
+ subnet2: '11.0.1.0/24',
41
+ subnet3: '11.0.2.0/24',
42
+ subnet_ids: 'subnet-123,subnet-321,subnet-333'
43
+ }
44
+ }
45
+ )
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe EcsDeployCli::DSL::Service do
6
+ context 'defines service data' do
7
+ subject { described_class.new('test', { aws_profile_id: '123123', aws_region: 'eu-central-1' }) }
8
+
9
+ it 'has the correct name' do
10
+ expect(subject.as_definition({})[:service]).to eq('test')
11
+ end
12
+
13
+ it '#load_balancer' do
14
+ subject.load_balancer :'yourproject-load-balancer' do
15
+ target_group_arn 'loader-target-group/123abc'
16
+ container_name :web
17
+ container_port 80
18
+ end
19
+
20
+ expect(subject.as_definition({})[:load_balancers]).to eq(
21
+ [
22
+ {
23
+ container_name: :web,
24
+ container_port: 80,
25
+ target_group_arn: 'arn:aws:elasticloadbalancing:eu-central-1:123123:targetgroup/loader-target-group/123abc'
26
+ }
27
+ ]
28
+ )
29
+ end
30
+ end
31
+ end
@@ -2,14 +2,20 @@
2
2
 
3
3
  require 'spec_helper'
4
4
  require 'aws-sdk-cloudwatchevents'
5
+ require 'aws-sdk-cloudwatchlogs'
5
6
  require 'aws-sdk-ec2'
7
+ require 'aws-sdk-ssm'
8
+ require 'aws-sdk-cloudformation'
6
9
 
7
10
  describe EcsDeployCli::Runner do
8
11
  context 'defines task data' do
9
12
  let(:parser) { EcsDeployCli::DSL::Parser.load('spec/support/ECSFile') }
10
13
  subject { described_class.new(parser) }
14
+ let(:mock_cf_client) { Aws::CloudFormation::Client.new(stub_responses: true) }
15
+ let(:mock_ssm_client) { Aws::SSM::Client.new(stub_responses: true) }
11
16
  let(:mock_ecs_client) { Aws::ECS::Client.new(stub_responses: true) }
12
17
  let(:mock_ec2_client) { Aws::EC2::Client.new(stub_responses: true) }
18
+ let(:mock_cwl_client) { Aws::CloudWatchLogs::Client.new(stub_responses: true) }
13
19
  let(:mock_cwe_client) do
14
20
  Aws::CloudWatchEvents::Client.new(stub_responses: true)
15
21
  end
@@ -84,6 +90,26 @@ describe EcsDeployCli::Runner do
84
90
  ENV['AWS_REGION'] = nil
85
91
  end
86
92
 
93
+ it '#setup!' do
94
+ mock_ssm_client.stub_responses(:get_parameter, {
95
+ parameter: {
96
+ name: '/aws/service/ecs/optimized-ami/amazon-linux-2/recommended',
97
+ type: 'String',
98
+ value: '{"schema_version":1,"image_name":"amzn2-ami-ecs-hvm-2.0.20210331-x86_64-ebs","image_id":"ami-03bbf53329af34379","os":"Amazon Linux 2","ecs_runtime_version":"Docker version 19.03.13-ce","ecs_agent_version":"1.51.0"}'
99
+ }
100
+ })
101
+
102
+ expect(mock_cf_client).to receive(:wait_until)
103
+ expect(mock_ecs_client).to receive(:create_service)
104
+
105
+ expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:cwl_client).at_least(:once).and_return(mock_cwl_client)
106
+ expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:ecs_client).at_least(:once).and_return(mock_ecs_client)
107
+ expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:ssm_client).at_least(:once).and_return(mock_ssm_client)
108
+ expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:cf_client).at_least(:once).and_return(mock_cf_client)
109
+
110
+ subject.setup!
111
+ end
112
+
87
113
  it '#ssh' do
88
114
  expect(mock_ecs_client).to receive(:list_container_instances).and_return({ container_instance_arns: ['arn:123123'] })
89
115
  expect(mock_ecs_client).to receive(:describe_container_instances).and_return(double(container_instances: [double(ec2_instance_id: 'i-123123')]))
@@ -124,6 +150,7 @@ describe EcsDeployCli::Runner do
124
150
 
125
151
  mock_cwe_client.stub_responses(:run_task)
126
152
 
153
+ expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:cwl_client).at_least(:once).and_return(mock_cwl_client)
127
154
  expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:ecs_client).at_least(:once).and_return(mock_ecs_client)
128
155
 
129
156
  subject.run_task!('yourproject-cron', launch_type: 'FARGATE', security_groups: [], subnets: [])
@@ -134,6 +161,7 @@ describe EcsDeployCli::Runner do
134
161
 
135
162
  mock_cwe_client.stub_responses(:list_targets_by_rule, { targets: [{ id: '123', arn: 'arn:123' }] })
136
163
 
164
+ expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:cwl_client).at_least(:once).and_return(mock_cwl_client)
137
165
  expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:ecs_client).at_least(:once).and_return(mock_ecs_client)
138
166
  expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:cwe_client).at_least(:once).and_return(mock_cwe_client)
139
167
 
@@ -149,6 +177,7 @@ describe EcsDeployCli::Runner do
149
177
  )
150
178
  expect(mock_ecs_client).to receive(:wait_until)
151
179
 
180
+ expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:cwl_client).at_least(:once).and_return(mock_cwl_client)
152
181
  expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:ecs_client).at_least(:once).and_return(mock_ecs_client)
153
182
 
154
183
  subject.update_services!
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'aws-sdk-cloudwatchevents'
5
+ require 'aws-sdk-cloudwatchlogs'
6
+ require 'aws-sdk-ec2'
7
+ require 'aws-sdk-ssm'
8
+ require 'aws-sdk-cloudformation'
9
+
10
+ describe EcsDeployCli::Runners::Base do
11
+ let(:parser) { EcsDeployCli::DSL::Parser.load('spec/support/ECSFile') }
12
+ subject { described_class.new(parser) }
13
+ let(:mock_cf_client) { Aws::CloudFormation::Client.new(stub_responses: true) }
14
+ let(:mock_ssm_client) { Aws::SSM::Client.new(stub_responses: true) }
15
+ let(:mock_ecs_client) { Aws::ECS::Client.new(stub_responses: true) }
16
+ let(:mock_ec2_client) { Aws::EC2::Client.new(stub_responses: true) }
17
+ let(:mock_cwl_client) { Aws::CloudWatchLogs::Client.new(stub_responses: true) }
18
+ let(:mock_cwe_client) do
19
+ Aws::CloudWatchEvents::Client.new(stub_responses: true)
20
+ end
21
+
22
+ around(:each) do |example|
23
+ ENV['AWS_PROFILE_ID'] = '123123123'
24
+ ENV['AWS_REGION'] = 'us-east-1'
25
+ example.run
26
+ ENV['AWS_PROFILE_ID'] = nil
27
+ ENV['AWS_REGION'] = nil
28
+ end
29
+
30
+ context '#update_task' do
31
+ it 'creates cloud watch logs if missing' do
32
+ _, tasks, = parser.resolve
33
+
34
+ expect(mock_cwl_client).to receive(:describe_log_groups).at_least(:once).and_return({ log_groups: [] })
35
+ expect(mock_cwl_client).to receive(:create_log_group).at_least(:once)
36
+ expect(mock_ecs_client).to receive(:register_task_definition).at_least(:once).and_return({ task_definition: { family: 'some', revision: '1' } })
37
+
38
+ expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:cwl_client).at_least(:once).and_return(mock_cwl_client)
39
+ expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:ecs_client).at_least(:once).and_return(mock_ecs_client)
40
+
41
+ subject.update_task(tasks.values.first)
42
+ end
43
+
44
+ it 'creates no cloudwatch log group if is already there' do
45
+ _, tasks, = parser.resolve
46
+
47
+ expect(mock_cwl_client).to receive(:describe_log_groups).at_least(:once).and_return({ log_groups: [{}] })
48
+ expect(mock_cwl_client).not_to receive(:create_log_group)
49
+ expect(mock_ecs_client).to receive(:register_task_definition).at_least(:once).and_return({ task_definition: { family: 'some', revision: '1' } })
50
+
51
+ expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:cwl_client).at_least(:once).and_return(mock_cwl_client)
52
+ expect_any_instance_of(EcsDeployCli::Runners::Base).to receive(:ecs_client).at_least(:once).and_return(mock_ecs_client)
53
+
54
+ subject.update_task(tasks.values.first)
55
+ end
56
+ end
57
+ end
data/spec/support/ECSFile CHANGED
@@ -4,7 +4,14 @@ aws_region ENV.fetch('AWS_REGION', 'eu-central-1')
4
4
  aws_profile_id ENV['AWS_PROFILE_ID']
5
5
 
6
6
  # Defining the cluster name
7
- cluster 'yourproject-cluster'
7
+ cluster 'yourproject-cluster' do
8
+ instance_type 't3.small'
9
+ keypair_name 'test'
10
+
11
+ vpc do
12
+ availability_zones 'eu-central-1a', 'eu-central-1b', 'eu-central-1c'
13
+ end
14
+ end
8
15
 
9
16
  # This is used as a template for the next two containers, it will not be used inside a task
10
17
  container :base_container do
@@ -49,6 +56,11 @@ end
49
56
  # The main service
50
57
  service :'yourproject-service' do
51
58
  task :yourproject
59
+ load_balancer :'yourproject-load-balancer' do
60
+ target_group_arn 'loader-target-group/123abc'
61
+ container_name :web
62
+ container_port 80
63
+ end
52
64
  end
53
65
 
54
66
  # A task for cron jobs
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ecs_deploy_cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mònade
8
8
  - ProGM
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
  date: 2021-03-31 00:00:00.000000000 Z
@@ -31,6 +31,20 @@ dependencies:
31
31
  - - "<"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '7'
34
+ - !ruby/object:Gem::Dependency
35
+ name: aws-sdk-cloudformation
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1'
41
+ type: :runtime
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1'
34
48
  - !ruby/object:Gem::Dependency
35
49
  name: aws-sdk-cloudwatchevents
36
50
  requirement: !ruby/object:Gem::Requirement
@@ -45,6 +59,20 @@ dependencies:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
61
  version: '1'
62
+ - !ruby/object:Gem::Dependency
63
+ name: aws-sdk-cloudwatchlogs
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1'
69
+ type: :runtime
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1'
48
76
  - !ruby/object:Gem::Dependency
49
77
  name: aws-sdk-ec2
50
78
  requirement: !ruby/object:Gem::Requirement
@@ -73,6 +101,20 @@ dependencies:
73
101
  - - "~>"
74
102
  - !ruby/object:Gem::Version
75
103
  version: '1'
104
+ - !ruby/object:Gem::Dependency
105
+ name: aws-sdk-ssm
106
+ requirement: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1'
111
+ type: :runtime
112
+ prerelease: false
113
+ version_requirements: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1'
76
118
  - !ruby/object:Gem::Dependency
77
119
  name: colorize
78
120
  requirement: !ruby/object:Gem::Requirement
@@ -155,7 +197,9 @@ files:
155
197
  - lib/ecs-deploy-cli.rb
156
198
  - lib/ecs_deploy_cli.rb
157
199
  - lib/ecs_deploy_cli/cli.rb
200
+ - lib/ecs_deploy_cli/cloudformation/default.yml
158
201
  - lib/ecs_deploy_cli/dsl/auto_options.rb
202
+ - lib/ecs_deploy_cli/dsl/cluster.rb
159
203
  - lib/ecs_deploy_cli/dsl/container.rb
160
204
  - lib/ecs_deploy_cli/dsl/cron.rb
161
205
  - lib/ecs_deploy_cli/dsl/parser.rb
@@ -166,6 +210,7 @@ files:
166
210
  - lib/ecs_deploy_cli/runners/diff.rb
167
211
  - lib/ecs_deploy_cli/runners/logs.rb
168
212
  - lib/ecs_deploy_cli/runners/run_task.rb
213
+ - lib/ecs_deploy_cli/runners/setup.rb
169
214
  - lib/ecs_deploy_cli/runners/ssh.rb
170
215
  - lib/ecs_deploy_cli/runners/status.rb
171
216
  - lib/ecs_deploy_cli/runners/update_crons.rb
@@ -173,11 +218,14 @@ files:
173
218
  - lib/ecs_deploy_cli/runners/validate.rb
174
219
  - lib/ecs_deploy_cli/version.rb
175
220
  - spec/ecs_deploy_cli/cli_spec.rb
221
+ - spec/ecs_deploy_cli/dsl/cluster_spec.rb
176
222
  - spec/ecs_deploy_cli/dsl/container_spec.rb
177
223
  - spec/ecs_deploy_cli/dsl/cron_spec.rb
178
224
  - spec/ecs_deploy_cli/dsl/parser_spec.rb
225
+ - spec/ecs_deploy_cli/dsl/service_spec.rb
179
226
  - spec/ecs_deploy_cli/dsl/task_spec.rb
180
227
  - spec/ecs_deploy_cli/runner_spec.rb
228
+ - spec/ecs_deploy_cli/runners/base_spec.rb
181
229
  - spec/spec_helper.rb
182
230
  - spec/support/ECSFile
183
231
  - spec/support/ECSFile.minimal
@@ -188,7 +236,7 @@ licenses:
188
236
  - MIT
189
237
  metadata:
190
238
  source_code_uri: https://github.com/monade/ecs-deploy-cli
191
- post_install_message:
239
+ post_install_message:
192
240
  rdoc_options: []
193
241
  require_paths:
194
242
  - lib
@@ -203,19 +251,22 @@ required_rubygems_version: !ruby/object:Gem::Requirement
203
251
  - !ruby/object:Gem::Version
204
252
  version: '0'
205
253
  requirements: []
206
- rubygems_version: 3.2.6
207
- signing_key:
254
+ rubygems_version: 3.2.8
255
+ signing_key:
208
256
  specification_version: 4
209
257
  summary: A command line interface to make ECS deployments easier
210
258
  test_files:
259
+ - spec/ecs_deploy_cli/cli_spec.rb
260
+ - spec/ecs_deploy_cli/dsl/cluster_spec.rb
261
+ - spec/ecs_deploy_cli/dsl/container_spec.rb
262
+ - spec/ecs_deploy_cli/dsl/cron_spec.rb
263
+ - spec/ecs_deploy_cli/dsl/parser_spec.rb
264
+ - spec/ecs_deploy_cli/dsl/service_spec.rb
265
+ - spec/ecs_deploy_cli/dsl/task_spec.rb
266
+ - spec/ecs_deploy_cli/runner_spec.rb
267
+ - spec/ecs_deploy_cli/runners/base_spec.rb
211
268
  - spec/spec_helper.rb
212
269
  - spec/support/ECSFile
213
270
  - spec/support/ECSFile.minimal
214
- - spec/support/env_file.yml
215
271
  - spec/support/env_file.ext.yml
216
- - spec/ecs_deploy_cli/runner_spec.rb
217
- - spec/ecs_deploy_cli/cli_spec.rb
218
- - spec/ecs_deploy_cli/dsl/task_spec.rb
219
- - spec/ecs_deploy_cli/dsl/parser_spec.rb
220
- - spec/ecs_deploy_cli/dsl/cron_spec.rb
221
- - spec/ecs_deploy_cli/dsl/container_spec.rb
272
+ - spec/support/env_file.yml