ecs_deploy_cli 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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