ecs_deploy_cli 0.1.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ecs_deploy_cli.rb +5 -1
  3. data/lib/ecs_deploy_cli/cli.rb +40 -2
  4. data/lib/ecs_deploy_cli/cloudformation/default.yml +411 -0
  5. data/lib/ecs_deploy_cli/dsl/auto_options.rb +17 -1
  6. data/lib/ecs_deploy_cli/dsl/cluster.rb +70 -0
  7. data/lib/ecs_deploy_cli/dsl/container.rb +8 -10
  8. data/lib/ecs_deploy_cli/dsl/parser.rb +9 -5
  9. data/lib/ecs_deploy_cli/dsl/service.rb +31 -2
  10. data/lib/ecs_deploy_cli/dsl/task.rb +2 -0
  11. data/lib/ecs_deploy_cli/runner.rb +26 -125
  12. data/lib/ecs_deploy_cli/runners/base.rb +105 -0
  13. data/lib/ecs_deploy_cli/runners/diff.rb +74 -0
  14. data/lib/ecs_deploy_cli/runners/logs.rb +14 -0
  15. data/lib/ecs_deploy_cli/runners/run_task.rb +27 -0
  16. data/lib/ecs_deploy_cli/runners/setup.rb +128 -0
  17. data/lib/ecs_deploy_cli/runners/ssh.rb +79 -0
  18. data/lib/ecs_deploy_cli/runners/status.rb +23 -0
  19. data/lib/ecs_deploy_cli/runners/update_crons.rb +41 -0
  20. data/lib/ecs_deploy_cli/runners/update_services.rb +55 -0
  21. data/lib/ecs_deploy_cli/runners/validate.rb +47 -0
  22. data/lib/ecs_deploy_cli/version.rb +3 -1
  23. data/spec/ecs_deploy_cli/cli_spec.rb +44 -4
  24. data/spec/ecs_deploy_cli/dsl/cluster_spec.rb +48 -0
  25. data/spec/ecs_deploy_cli/dsl/container_spec.rb +6 -4
  26. data/spec/ecs_deploy_cli/dsl/cron_spec.rb +2 -0
  27. data/spec/ecs_deploy_cli/dsl/parser_spec.rb +2 -0
  28. data/spec/ecs_deploy_cli/dsl/service_spec.rb +31 -0
  29. data/spec/ecs_deploy_cli/dsl/task_spec.rb +2 -0
  30. data/spec/ecs_deploy_cli/runner_spec.rb +177 -26
  31. data/spec/ecs_deploy_cli/runners/base_spec.rb +57 -0
  32. data/spec/spec_helper.rb +2 -3
  33. data/spec/support/ECSFile +13 -1
  34. data/spec/support/ECSFile.minimal +12 -0
  35. metadata +104 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5f34210100053703e0137631635b625ea37cc1cb140e4fa432c3375c6cdf87a
4
- data.tar.gz: '08d8ead32a4b87cddb19b36539d661fc954e006a8ac3986a8dc60aaac93cd560'
3
+ metadata.gz: f3c493de7ebb99888eb436db698b8215291b733983ac8b37a16e7842c8588d0d
4
+ data.tar.gz: 34f5613fef2b6746196ed91b3c67d358c02bdafcf89703e1704c2b5e93ca987d
5
5
  SHA512:
6
- metadata.gz: 90cb49d9d8de03d5b82946493d2df2466dec05cd01c190e9673ed6023adf9b5167465032bc47076ac12f7f8bfc451fd78c8568aec3aede6fd82467b7369914ad
7
- data.tar.gz: f3dedd74c575d671fc65afb974086d8683c4eb3ee38074aec7d1dacb0b31632dd52813127bb39f1b3df95167353a8871308da8fbd885fd57cbb7f3ef34ca9941
6
+ metadata.gz: aa4641ecfd920aa198310ef81cd00f9f173d0fa3c98066172792e0c4d74cd09009c1c000f20ee128be9374e037c3ada0002f44e8a51a0ac7895b1a376699eb22
7
+ data.tar.gz: 3144d96e6f64b42faf4d47ffad4c2dfcbd4c818507978491b42586842730ae36a9c3d0cf367d00845dc347d87abc90e05ae7181264adec243d02078b19deee8d
@@ -1,14 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'yaml'
2
4
  require 'logger'
3
5
  require 'thor'
4
6
  require 'aws-sdk-ecs'
5
7
  require 'active_support/core_ext/hash/indifferent_access'
8
+ require 'active_support/concern'
6
9
 
7
10
  module EcsDeployCli
8
11
  def self.logger
9
12
  @logger ||= begin
10
13
  logger = Logger.new(STDOUT)
11
- logger.formatter = proc { |severity, datetime, progname, msg|
14
+ logger.formatter = proc { |_severity, _datetime, _progname, msg|
12
15
  "#{msg}\n"
13
16
  }
14
17
  logger.level = Logger::INFO
@@ -23,6 +26,7 @@ end
23
26
 
24
27
  require 'ecs_deploy_cli/version'
25
28
  require 'ecs_deploy_cli/dsl/auto_options'
29
+ require 'ecs_deploy_cli/dsl/cluster'
26
30
  require 'ecs_deploy_cli/dsl/container'
27
31
  require 'ecs_deploy_cli/dsl/task'
28
32
  require 'ecs_deploy_cli/dsl/cron'
@@ -1,5 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EcsDeployCli
2
4
  class CLI < Thor
5
+ def self.exit_on_failure?
6
+ true
7
+ end
8
+
3
9
  desc 'validate', 'Validates your ECSFile'
4
10
  option :file, default: 'ECSFile'
5
11
  def validate
@@ -8,11 +14,25 @@ module EcsDeployCli
8
14
  puts 'Your ECSFile looks fine! 🎉'
9
15
  end
10
16
 
17
+ desc 'diff', 'Check differences between task definitions'
18
+ option :file, default: 'ECSFile'
19
+ def diff
20
+ @parser = load(options[:file])
21
+ runner.diff
22
+ end
23
+
11
24
  desc 'version', 'Updates all services defined in your ECSFile'
12
25
  def version
13
26
  puts "ECS Deploy CLI Version #{EcsDeployCli::VERSION}."
14
27
  end
15
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
+
16
36
  desc 'deploy-scheduled-tasks', 'Updates all scheduled tasks defined in your ECSFile'
17
37
  option :file, default: 'ECSFile'
18
38
  def deploy_scheduled_tasks
@@ -29,7 +49,7 @@ module EcsDeployCli
29
49
  runner.update_services! timeout: options[:timeout], service: options[:only]
30
50
  end
31
51
 
32
- desc 'deploy', 'Updates a single service defined in your ECSFile'
52
+ desc 'deploy', 'Updates all services and scheduled tasks at once'
33
53
  option :file, default: 'ECSFile'
34
54
  option :timeout, type: :numeric, default: 500
35
55
  def deploy
@@ -38,11 +58,29 @@ module EcsDeployCli
38
58
  runner.update_crons!
39
59
  end
40
60
 
61
+ desc 'run-task NAME', 'Manually runs a task defined in your ECSFile'
62
+ option :launch_type, default: 'FARGATE'
63
+ option :security_groups, default: '', type: :string
64
+ option :subnets, required: true, type: :string
65
+ option :file, default: 'ECSFile'
66
+ def run_task(task_name)
67
+ @parser = load(options[:file])
68
+ runner.run_task!(
69
+ task_name,
70
+ launch_type: options[:launch_type],
71
+ security_groups: options[:security_groups].split(','),
72
+ subnets: options[:subnets].split(',')
73
+ )
74
+ end
75
+
41
76
  desc 'ssh', 'Connects to ECS instance via SSH'
42
77
  option :file, default: 'ECSFile'
78
+ option :service, default: nil
79
+ option :task, default: nil
43
80
  def ssh
44
81
  @parser = load(options[:file])
45
- runner.ssh
82
+ ssh_options = { family: options[:task], service_name: options[:service] }.delete_if { |_, v| v.nil? }
83
+ runner.ssh(**ssh_options)
46
84
  end
47
85
 
48
86
  private
@@ -0,0 +1,411 @@
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
+ ## TODO: FINISH
278
+ # ALBSecurityGroup:
279
+ # Condition: CreateNewLoadBalancer
280
+ # Type: AWS::EC2::SecurityGroup
281
+ # Properties:
282
+ # GroupDescription: ECS Allowed Ports
283
+ # VpcId: !If [ CreateSubnet1, !Ref Vpc, !Ref VpcId ]
284
+ # SecurityGroupIngress:
285
+ # IpProtocol: tcp
286
+ # FromPort: !Ref SecurityIngressFromPort
287
+ # ToPort: !Ref SecurityIngressToPort
288
+ # CidrIp: !Ref SecurityIngressCidrIp
289
+
290
+ # EcsLoadBalancer:
291
+ # Condition: CreateNewLoadBalancer
292
+ # Type: AWS::ElasticLoadBalancing::LoadBalancer
293
+ # Properties:
294
+ # LoadBalancerName: !Ref LoadBalancer
295
+ # AvailabilityZones:
296
+ # - !Select [ 0, !Ref VpcAvailabilityZones ]
297
+ # - !Select [ 1, !Ref VpcAvailabilityZones ]
298
+ # - !Select [ 2, !Ref VpcAvailabilityZones ]
299
+ # SecurityGroups:
300
+ # - !Select [ 0, !Ref VpcAvailabilityZones ]
301
+ # Subnets:
302
+ # -
303
+ ## /TODO: FINISH
304
+
305
+ EcsInstanceLc:
306
+ Type: AWS::AutoScaling::LaunchConfiguration
307
+ Condition: CreateWithASG
308
+ Properties:
309
+ ImageId: !Ref EcsAmiId
310
+ InstanceType: !Select [ 0, !Ref EcsInstanceType ]
311
+ AssociatePublicIpAddress: !If [ IsInheritPublicIp, !Ref "AWS::NoValue", !Ref AutoAssignPublicIp ]
312
+ IamInstanceProfile: !Ref IamRoleInstanceProfile
313
+ KeyName: !If [ CreateEC2LCWithKeyPair, !Ref KeyName, !Ref "AWS::NoValue" ]
314
+ SecurityGroups: [ !If [ CreateNewSecurityGroup, !Ref EcsSecurityGroup, !Ref SecurityGroupId ] ]
315
+ BlockDeviceMappings:
316
+ - !If
317
+ - IsConfiguringRootVolume
318
+ - DeviceName: !Ref RootDeviceName
319
+ Ebs:
320
+ VolumeSize: !Ref RootEbsVolumeSize
321
+ VolumeType: !Ref EbsVolumeType
322
+ - !Ref AWS::NoValue
323
+ - !If
324
+ - IsConfiguringDataVolume
325
+ - DeviceName: !Ref DeviceName
326
+ Ebs:
327
+ VolumeSize: !Ref EbsVolumeSize
328
+ VolumeType: !Ref EbsVolumeType
329
+ - !Ref AWS::NoValue
330
+ UserData:
331
+ Fn::Base64: !Ref UserData
332
+ EcsInstanceAsg:
333
+ Type: AWS::AutoScaling::AutoScalingGroup
334
+ Condition: CreateWithASG
335
+ Properties:
336
+ VPCZoneIdentifier: !If
337
+ - CreateSubnet1
338
+ - !If
339
+ - CreateSubnet2
340
+ - !If
341
+ - CreateSubnet3
342
+ - [ !Sub "${PubSubnetAz1}, ${PubSubnetAz2}, ${PubSubnetAz3}" ]
343
+ - [ !Sub "${PubSubnetAz1}, ${PubSubnetAz2}" ]
344
+ - [ !Sub "${PubSubnetAz1}" ]
345
+ - !Ref SubnetIds
346
+ LaunchConfigurationName: !Ref EcsInstanceLc
347
+ MinSize: '0'
348
+ MaxSize: !Ref AsgMaxSize
349
+ DesiredCapacity: !Ref AsgMaxSize
350
+ Tags:
351
+ -
352
+ Key: Name
353
+ Value: !Sub "ECS Instance - ${AWS::StackName}"
354
+ PropagateAtLaunch: true
355
+ -
356
+ Key: Description
357
+ Value: "This instance is the part of the Auto Scaling group which was created through ECS Console"
358
+ PropagateAtLaunch: true
359
+ EcsSpotFleet:
360
+ Condition: CreateWithSpot
361
+ Type: AWS::EC2::SpotFleet
362
+ Properties:
363
+ SpotFleetRequestConfigData:
364
+ AllocationStrategy: !Ref SpotAllocationStrategy
365
+ IamFleetRole: !Ref IamSpotFleetRoleArn
366
+ TargetCapacity: !Ref AsgMaxSize
367
+ SpotPrice: !If [ CreateWithSpotPrice, !Ref SpotPrice, !Ref 'AWS::NoValue' ]
368
+ TerminateInstancesWithExpiration: true
369
+ LaunchSpecifications:
370
+ -
371
+ IamInstanceProfile:
372
+ Arn: !Ref IamRoleInstanceProfile
373
+ ImageId: !Ref EcsAmiId
374
+ InstanceType: !Select [ 0, !Ref EcsInstanceType ]
375
+ KeyName: !If [ CreateEC2LCWithKeyPair, !Ref KeyName, !Ref "AWS::NoValue" ]
376
+ Monitoring:
377
+ Enabled: true
378
+ SecurityGroups:
379
+ - GroupId: !If [ CreateNewSecurityGroup, !Ref EcsSecurityGroup, !Ref SecurityGroupId ]
380
+ SubnetId: !If
381
+ - CreateSubnet1
382
+ - !If
383
+ - CreateSubnet2
384
+ - !If
385
+ - CreateSubnet3
386
+ - !Join [ "," , [ !Ref PubSubnetAz1, !Ref PubSubnetAz2, !Ref PubSubnetAz3 ] ]
387
+ - !Join [ "," , [ !Ref PubSubnetAz1, !Ref PubSubnetAz2 ] ]
388
+ - !Ref PubSubnetAz1
389
+ - !Join [ "," , !Ref SubnetIds ]
390
+ BlockDeviceMappings:
391
+ - DeviceName: !Ref DeviceName
392
+ Ebs:
393
+ VolumeSize: !Ref EbsVolumeSize
394
+ VolumeType: !Ref EbsVolumeType
395
+ UserData:
396
+ Fn::Base64: !Ref UserData
397
+ Outputs:
398
+ EcsInstanceAsgName:
399
+ Condition: CreateWithASG
400
+ Description: Auto Scaling Group Name for ECS Instances
401
+ Value: !Ref EcsInstanceAsg
402
+ EcsSpotFleetRequestId:
403
+ Condition: CreateWithSpot
404
+ Description: Spot Fleet Request for ECS Instances
405
+ Value: !Ref EcsSpotFleet
406
+ UsedByECSCreateCluster:
407
+ Description: Flag used by ECS Create Cluster Wizard
408
+ Value: 'true'
409
+ TemplateVersion:
410
+ Description: The version of the template used by Create Cluster Wizard
411
+ Value: '2.0.0'