ufo 4.6.0 → 5.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -0
  3. data/docs/_docs/conventions.md +1 -1
  4. data/docs/_docs/extras/codebuild-iam-role.md +1 -1
  5. data/docs/_docs/extras/dockerfile-erb.md +1 -1
  6. data/docs/_docs/extras/ecs-network-mode.md +1 -1
  7. data/docs/_docs/extras/load-balancer.md +1 -1
  8. data/docs/_docs/extras/minimal-deploy-iam.md +1 -1
  9. data/docs/_docs/extras/notification-arns.md +21 -0
  10. data/docs/_docs/extras/redirection-support.md +9 -9
  11. data/docs/_docs/extras/route53-support.md +4 -4
  12. data/docs/_docs/extras/security-groups.md +1 -1
  13. data/docs/_docs/extras/ssl-support.md +5 -5
  14. data/docs/_docs/faq.md +1 -1
  15. data/docs/_docs/helpers.md +7 -5
  16. data/docs/_docs/iam-roles.md +112 -0
  17. data/docs/_docs/install.md +0 -10
  18. data/docs/_docs/more/auto-completion.md +1 -1
  19. data/docs/_docs/more/automated-cleanup.md +1 -1
  20. data/docs/_docs/more/customize-cloudformation.md +1 -1
  21. data/docs/_docs/more/migrations.md +1 -1
  22. data/docs/_docs/more/run-in-pieces.md +1 -1
  23. data/docs/_docs/more/single-task.md +1 -1
  24. data/docs/_docs/more/stuck-cloudformation.md +1 -1
  25. data/docs/_docs/more/why-cloudformation.md +1 -1
  26. data/docs/_docs/next-steps.md +1 -1
  27. data/docs/_docs/quick-start-ec2.md +1 -0
  28. data/docs/_docs/secrets.md +135 -0
  29. data/docs/_docs/settings.md +10 -9
  30. data/docs/_docs/settings/cluster.md +7 -13
  31. data/docs/_docs/settings/manage-security-groups.md +24 -0
  32. data/docs/_docs/settings/network.md +11 -1
  33. data/docs/_docs/structure.md +10 -9
  34. data/docs/_docs/tutorial-ufo-init.md +1 -7
  35. data/docs/_docs/ufo-current.md +1 -1
  36. data/docs/_docs/ufo-env-extra.md +1 -1
  37. data/docs/_docs/ufo-env.md +3 -5
  38. data/docs/_docs/ufo-logs.md +1 -2
  39. data/docs/_docs/ufo-task-params.md +1 -1
  40. data/docs/_docs/upgrading.md +1 -1
  41. data/docs/_docs/upgrading/upgrade4.5.md +2 -2
  42. data/docs/_docs/upgrading/upgrade4.md +2 -2
  43. data/docs/_docs/upgrading/upgrade5.md +19 -0
  44. data/docs/_docs/variables.md +1 -1
  45. data/docs/_includes/cfn-customize.md +4 -4
  46. data/docs/_includes/subnav.html +3 -0
  47. data/docs/_reference/ufo-deploy.md +1 -2
  48. data/docs/_reference/ufo-init.md +15 -16
  49. data/docs/_reference/ufo-logs.md +10 -9
  50. data/docs/_reference/ufo-rollback.md +2 -0
  51. data/docs/_reference/ufo-ship.md +1 -2
  52. data/docs/_reference/ufo-ships.md +1 -2
  53. data/docs/_reference/ufo-tasks-build.md +1 -2
  54. data/docs/articles.md +1 -1
  55. data/docs/quick-start.md +1 -0
  56. data/lib/template/.secrets +5 -0
  57. data/lib/template/.ufo/iam_roles/execution_role.rb +7 -0
  58. data/lib/template/.ufo/iam_roles/task_role.rb +21 -0
  59. data/lib/template/.ufo/settings.yml.tt +1 -0
  60. data/lib/template/.ufo/settings/cfn/default.yml.tt +27 -27
  61. data/lib/template/.ufo/settings/network/default.yml.tt +9 -0
  62. data/lib/template/.ufo/templates/fargate.json.erb +3 -1
  63. data/lib/template/.ufo/templates/main.json.erb +3 -0
  64. data/lib/template/.ufo/variables/base.rb.tt +1 -0
  65. data/lib/ufo.rb +2 -1
  66. data/lib/ufo/autoloader.rb +9 -0
  67. data/lib/ufo/cli.rb +4 -2
  68. data/lib/ufo/command.rb +7 -0
  69. data/lib/ufo/core.rb +1 -9
  70. data/lib/ufo/docker/cleaner.rb +1 -1
  71. data/lib/ufo/dsl.rb +6 -1
  72. data/lib/ufo/dsl/helper.rb +21 -27
  73. data/lib/ufo/dsl/helper/vars.rb +97 -0
  74. data/lib/ufo/dsl/outputter.rb +12 -9
  75. data/lib/ufo/help/init.md +1 -1
  76. data/lib/ufo/init.rb +0 -2
  77. data/lib/ufo/log_group.rb +1 -0
  78. data/lib/ufo/logs.rb +5 -4
  79. data/lib/ufo/role/builder.rb +66 -0
  80. data/lib/ufo/role/dsl.rb +21 -0
  81. data/lib/ufo/role/registry.rb +24 -0
  82. data/lib/ufo/rollback.rb +2 -1
  83. data/lib/ufo/sequence.rb +0 -16
  84. data/lib/ufo/setting/profile.rb +11 -7
  85. data/lib/ufo/setting/security_groups.rb +22 -0
  86. data/lib/ufo/settings.rb +20 -0
  87. data/lib/ufo/stack.rb +24 -24
  88. data/lib/ufo/stack/builder.rb +26 -0
  89. data/lib/ufo/stack/builder/base.rb +54 -0
  90. data/lib/ufo/stack/builder/conditions.rb +23 -0
  91. data/lib/ufo/stack/builder/outputs.rb +24 -0
  92. data/lib/ufo/stack/builder/parameters.rb +45 -0
  93. data/lib/ufo/stack/builder/resources.rb +20 -0
  94. data/lib/ufo/stack/builder/resources/base.rb +4 -0
  95. data/lib/ufo/stack/builder/resources/dns.rb +17 -0
  96. data/lib/ufo/stack/builder/resources/ecs.rb +67 -0
  97. data/lib/ufo/stack/builder/resources/elb.rb +45 -0
  98. data/lib/ufo/stack/builder/resources/listener.rb +42 -0
  99. data/lib/ufo/stack/builder/resources/listener_ssl.rb +16 -0
  100. data/lib/ufo/stack/builder/resources/roles/base.rb +22 -0
  101. data/lib/ufo/stack/builder/resources/roles/execution_role.rb +4 -0
  102. data/lib/ufo/stack/builder/resources/roles/task_role.rb +4 -0
  103. data/lib/ufo/stack/builder/resources/security_group/base.rb +4 -0
  104. data/lib/ufo/stack/builder/resources/security_group/ecs.rb +44 -0
  105. data/lib/ufo/stack/builder/resources/security_group/ecs_rule.rb +25 -0
  106. data/lib/ufo/stack/builder/resources/security_group/elb.rb +57 -0
  107. data/lib/ufo/stack/builder/resources/target_group.rb +39 -0
  108. data/lib/ufo/stack/builder/resources/task_definition.rb +24 -0
  109. data/lib/ufo/stack/builder/resources/task_definition/reconstructor.rb +49 -0
  110. data/lib/ufo/stack/context.rb +41 -48
  111. data/lib/ufo/stack/custom_properties.rb +59 -0
  112. data/lib/ufo/stack/helper.rb +2 -5
  113. data/lib/ufo/stack/template_body.rb +13 -0
  114. data/lib/ufo/task.rb +2 -7
  115. data/lib/ufo/tasks.rb +1 -1
  116. data/lib/ufo/tasks/builder.rb +0 -1
  117. data/lib/ufo/tasks/register.rb +11 -8
  118. data/lib/ufo/template_scope.rb +1 -66
  119. data/lib/ufo/utils/squeezer.rb +24 -0
  120. data/lib/ufo/version.rb +1 -1
  121. data/spec/fixtures/iam_roles/task_role.rb +17 -0
  122. data/spec/lib/role/builder_spec.rb +67 -0
  123. data/spec/lib/role/dsl_spec.rb +12 -0
  124. data/ufo.gemspec +1 -0
  125. metadata +61 -3
  126. data/lib/cfn/stack.yml +0 -283
@@ -2,21 +2,25 @@ class Ufo::Setting
2
2
  class Profile
3
3
  extend Memoist
4
4
 
5
- def initialize(type, profile='default')
5
+ def initialize(type, profile=nil)
6
6
  @type = type.to_s # cfn or network
7
7
  @profile = profile
8
8
  end
9
9
 
10
10
  def data
11
- path = "#{Ufo.root}/.ufo/settings/#{@type}/#{@profile}.yml"
12
- unless File.exist?(path)
13
- puts "#{@type.camelize} profile #{path} not found. Please double check that it exists."
11
+ names = [
12
+ @profile, # user specified
13
+ Ufo.env, # conventional based on env
14
+ "default", # fallback to default
15
+ ].compact.uniq
16
+ paths = names.map { |name| "#{Ufo.root}/.ufo/settings/#{@type}/#{name}.yml" }
17
+ found = paths.find { |p| File.exist?(p) }
18
+ unless found
19
+ puts "#{@type.camelize} profile not found. Please double check that it exists. Checked paths: #{paths}"
14
20
  exit 1
15
21
  end
16
22
 
17
- text = RenderMePretty.result(path)
18
- # puts "text:".color(:cyan)
19
- # puts text
23
+ text = RenderMePretty.result(found)
20
24
  YAML.load(text).deep_symbolize_keys
21
25
  end
22
26
  memoize :data
@@ -0,0 +1,22 @@
1
+ class Ufo::Setting
2
+ class SecurityGroups
3
+ include Ufo::Settings
4
+ extend Memoist
5
+
6
+ def initialize(service, type)
7
+ @service, @type = service, type
8
+ end
9
+
10
+ def load
11
+ groups = network[@type] # IE: network[:ecs_security_groups] or network[:elb_security_groups]
12
+ return [] unless groups
13
+
14
+ case groups
15
+ when Array # same security groups used for all services
16
+ groups
17
+ when Hash # service specific security groups
18
+ groups[@service.to_sym] || []
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ module Ufo
2
+ module Settings
3
+ extend Memoist
4
+
5
+ def network
6
+ Ufo::Setting::Profile.new(:network, settings[:network_profile]).data
7
+ end
8
+ memoize :network
9
+
10
+ def cfn
11
+ Ufo::Setting::Profile.new(:cfn, settings[:cfn_profile]).data
12
+ end
13
+ memoize :cfn
14
+
15
+ def settings
16
+ Setting.new.data
17
+ end
18
+ memoize :settings
19
+ end
20
+ end
@@ -25,10 +25,12 @@ module Ufo
25
25
  class Stack
26
26
  extend Memoist
27
27
  include Helper
28
+ include Ufo::Settings
28
29
 
29
30
  def initialize(options)
30
31
  @options = options
31
32
  @task_definition = options[:task_definition]
33
+ @rollback = options[:rollback]
32
34
  @service = options[:service]
33
35
  @cluster = @options[:cluster] || default_cluster(@service)
34
36
  @stack_name = adjust_stack_name(@cluster, options[:service])
@@ -66,18 +68,6 @@ module Ufo
66
68
  handle_stack_error(e)
67
69
  end
68
70
 
69
- # do not memoize template_body it can change for a rename retry
70
- def template_body
71
- custom_template = "#{Ufo.root}/.ufo/settings/cfn/stack.yml"
72
- path = if File.exist?(custom_template)
73
- custom_template
74
- else
75
- # built-in default
76
- File.expand_path("../cfn/stack.yml", File.dirname(__FILE__))
77
- end
78
- RenderMePretty.result(path, context: context.scope)
79
- end
80
-
81
71
  def stack_options
82
72
  save_template
83
73
  if ENV['SAVE_TEMPLATE_EXIT']
@@ -85,22 +75,26 @@ module Ufo
85
75
  exit 1
86
76
  end
87
77
  {
78
+ capabilities: ["CAPABILITY_IAM"],
79
+ notification_arns: notification_arns,
88
80
  parameters: parameters,
89
81
  stack_name: @stack_name,
90
82
  template_body: template_body,
91
83
  }
92
84
  end
93
85
 
86
+ def notification_arns
87
+ settings[:notification_arns] || []
88
+ end
89
+
94
90
  def parameters
95
91
  create_elb, elb_target_group = context.elb_options
96
92
 
97
- network = Setting::Profile.new(:network, settings[:network_profile]).data
98
- # pp network
99
93
  elb_subnets = network[:elb_subnets] && !network[:elb_subnets].empty? ?
100
94
  network[:elb_subnets] :
101
95
  network[:ecs_subnets]
102
96
 
103
- hash = {
97
+ params = {
104
98
  Vpc: network[:vpc],
105
99
  ElbSubnets: elb_subnets.join(','),
106
100
  EcsSubnets: network[:ecs_subnets].join(','),
@@ -110,14 +104,11 @@ module Ufo
110
104
  ElbEipIds: context.elb_eip_ids,
111
105
 
112
106
  EcsDesiredCount: current_desired_count,
113
- EcsTaskDefinition: task_definition_arn,
114
107
  EcsSchedulingStrategy: scheduling_strategy,
115
108
  }
116
109
 
117
- hash[:EcsSecurityGroups] = network[:ecs_security_groups].join(',') if network[:ecs_security_groups]
118
- hash[:ElbSecurityGroups] = network[:elb_security_groups].join(',') if network[:elb_security_groups]
119
-
120
- hash.map do |k,v|
110
+ params = Ufo::Utils::Squeezer.new(params).squeeze
111
+ params.map do |k,v|
121
112
  if v == :use_previous_value
122
113
  { parameter_key: k, use_previous_value: true }
123
114
  else
@@ -127,12 +118,20 @@ module Ufo
127
118
  end
128
119
  memoize :parameters
129
120
 
121
+ # do not memoize template_body it can change for a rename retry
122
+ def template_body
123
+ TemplateBody.new(context).build
124
+ end
125
+ memoize :template_body
126
+
130
127
  def context
131
- Context.new(@options.merge(
128
+ o = @options.merge(
132
129
  cluster: @cluster,
133
130
  stack_name: @stack_name,
134
131
  stack: @stack,
135
- ))
132
+ )
133
+ o[:rollback_definition_arn] = rollback_definition_arn if rollback_definition_arn
134
+ Context.new(o)
136
135
  end
137
136
  memoize :context
138
137
 
@@ -154,11 +153,12 @@ module Ufo
154
153
  end
155
154
  end
156
155
 
157
- def task_definition_arn
156
+ def rollback_definition_arn
157
+ return unless @rollback
158
158
  resp = ecs.describe_task_definition(task_definition: @task_definition)
159
159
  resp.task_definition.task_definition_arn
160
160
  end
161
- memoize :task_definition_arn
161
+ memoize :rollback_definition_arn
162
162
 
163
163
  # Store template in tmp in case for debugging
164
164
  def save_template
@@ -0,0 +1,26 @@
1
+ class Ufo::Stack
2
+ class Builder
3
+ class_attribute :context
4
+
5
+ def initialize(context)
6
+ @context = context
7
+ # This builder class is really used as a singleton.
8
+ # To avoid having to pass context to all the builder classes.
9
+ self.class.context = @context
10
+ @template = {
11
+ Description: "Ufo ECS stack #{context.stack_name}",
12
+ }
13
+ end
14
+
15
+ def build
16
+ @template[:Parameters] = Parameters.new.build
17
+ @template[:Conditions] = Conditions.new.build
18
+ @template[:Resources] = Resources.new.build
19
+ @template[:Outputs] = Outputs.new.build
20
+ @template.deep_stringify_keys!
21
+ @template = Ufo::Utils::Squeezer.new(@template).squeeze
22
+ @template = CustomProperties.new(@template, @context.stack_name).apply
23
+ YAML.dump(@template)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,54 @@
1
+ class Ufo::Stack::Builder
2
+ class Base
3
+ include Ufo::Settings
4
+
5
+ def initialize
6
+ copy_instance_variables
7
+ end
8
+
9
+ # Copy the instance variables from TemplateScope Stack Builder classes
10
+ def copy_instance_variables
11
+ context = Ufo::Stack::Builder.context
12
+ scope = context.scope
13
+ scope.instance_variables.each do |var|
14
+ val = scope.instance_variable_get(var)
15
+ instance_variable_set(var, val)
16
+ end
17
+ end
18
+
19
+ def self.build
20
+ new.build
21
+ end
22
+
23
+ # type: elb or ecs
24
+ # NOTE: Application ELBs always seem to need a security group even though the docs say its not required
25
+ # However, there's a case where no ELB is created for a worker tier and if the settings are all blank
26
+ # CloudFormation fails to resolve and splits out this error:
27
+ #
28
+ # Template error: every Fn::Split object requires two parameters
29
+ #
30
+ # So we will not assign security groups at all for case of workers with no security groups at all.
31
+ #
32
+ def security_groups(type)
33
+ settings_key = "#{type}_security_groups".to_sym
34
+ group_ids = Ufo::Setting::SecurityGroups.new(@service, settings_key).load
35
+ # no security groups at all
36
+ return if !managed_security_groups? && group_ids.blank?
37
+
38
+ groups = []
39
+ groups += group_ids
40
+ groups += [managed_security_group(type.to_s.camelize)] if managed_security_groups?
41
+ groups
42
+ end
43
+
44
+ def managed_security_group(type)
45
+ logical_id = managed_security_groups? ? "#{type.camelize}SecurityGroup" : "AWS::NoValue"
46
+ {Ref: logical_id}
47
+ end
48
+
49
+ def managed_security_groups?
50
+ managed = settings[:managed_security_groups]
51
+ managed.nil? ? true : managed
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,23 @@
1
+ class Ufo::Stack::Builder
2
+ class Conditions < Base
3
+ def build
4
+ {
5
+ CreateElbIsTrue: {
6
+ "Fn::Equals": [{Ref: "CreateElb"}, true]
7
+ },
8
+ ElbTargetGroupIsBlank: {
9
+ "Fn::Equals": [{Ref: "ElbTargetGroup"}, ""]
10
+ },
11
+ CreateTargetGroupIsTrue: {
12
+ "Fn::And": [
13
+ {Condition: "CreateElbIsTrue"},
14
+ {Condition: "ElbTargetGroupIsBlank"},
15
+ ]
16
+ },
17
+ EcsDesiredCountIsBlank: {
18
+ "Fn::Equals": [{Ref: "EcsDesiredCount"}, ""]
19
+ }
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ class Ufo::Stack::Builder
2
+ class Outputs < Base
3
+ def build
4
+ outputs = {
5
+ ElbDns: {
6
+ Description: "Elb Dns",
7
+ Condition: "CreateElbIsTrue",
8
+ Value: {
9
+ "Fn::GetAtt": "Elb.DNSName"
10
+ }
11
+ }
12
+ }
13
+
14
+ if @create_route53
15
+ outputs[:Route53Dns] = {
16
+ Description: "Route53 Dns",
17
+ Value: {Ref: "Dns"},
18
+ }
19
+ end
20
+
21
+ outputs
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,45 @@
1
+ class Ufo::Stack::Builder
2
+ class Parameters < Base
3
+ def build
4
+ {
5
+ "Vpc": {
6
+ "Description": "Existing vpc id",
7
+ "Type": "AWS::EC2::VPC::Id"
8
+ },
9
+ "ElbSubnets": {
10
+ "Description": "Existing subnet ids for ELB",
11
+ "Type": "List<AWS::EC2::Subnet::Id>"
12
+ },
13
+ "EcsSubnets": {
14
+ "Description": "Existing subnet ids for ECS",
15
+ "Type": "List<AWS::EC2::Subnet::Id>"
16
+ },
17
+ "ElbTargetGroup": {
18
+ "Description": "Existing target group",
19
+ "Type": "String",
20
+ "Default": ""
21
+ },
22
+ "CreateElb": {
23
+ "Description": "Create elb",
24
+ "Type": "String",
25
+ "Default": true
26
+ },
27
+ "EcsDesiredCount": {
28
+ "Description": "Ecs desired count",
29
+ "Type": "String",
30
+ "Default": 1
31
+ },
32
+ "ElbEipIds": {
33
+ "Description": "ELB EIP Allocation ids to use for network load balancer",
34
+ "Type": "String",
35
+ "Default": ""
36
+ },
37
+ "EcsSchedulingStrategy": {
38
+ "Description": "The scheduling strategy to use for the service",
39
+ "Type": "String",
40
+ "Default": "REPLICA"
41
+ }
42
+ }
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,20 @@
1
+ class Ufo::Stack::Builder
2
+ class Resources < Base
3
+ def build
4
+ {
5
+ Dns: Dns.build,
6
+ Ecs: Ecs.build,
7
+ EcsSecurityGroup: SecurityGroup::Ecs.build,
8
+ EcsSecurityGroupRule: SecurityGroup::EcsRule.build,
9
+ Elb: Elb.build,
10
+ ElbSecurityGroup: SecurityGroup::Elb.build,
11
+ ExecutionRole: Roles::ExecutionRole.build,
12
+ Listener: Listener.build,
13
+ ListenerSsl: ListenerSsl.build,
14
+ TargetGroup: TargetGroup.build,
15
+ TaskDefinition: TaskDefinition.build,
16
+ TaskRole: Roles::TaskRole.build,
17
+ }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ class Ufo::Stack::Builder::Resources
2
+ class Base < Ufo::Stack::Builder::Base
3
+ end
4
+ end
@@ -0,0 +1,17 @@
1
+ class Ufo::Stack::Builder::Resources
2
+ class Dns < Base
3
+ def build
4
+ return unless @create_route53
5
+
6
+ {
7
+ Type: "AWS::Route53::RecordSet",
8
+ Properties: {
9
+ Comment: "cname to load balancer",
10
+ Type: "CNAME",
11
+ TTL: 60, # ttl has special casing
12
+ ResourceRecords: [{"Fn::GetAtt": "Elb.DNSName"}]
13
+ }
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,67 @@
1
+ class Ufo::Stack::Builder::Resources
2
+ class Ecs < Base
3
+ def build
4
+ attrs = {
5
+ Type: "AWS::ECS::Service",
6
+ Properties: properties
7
+ }
8
+
9
+ attrs[:DependsOn] = "Listener" if @create_elb
10
+
11
+ attrs
12
+ end
13
+
14
+ def properties
15
+ props = {
16
+ Cluster: @cluster,
17
+ DesiredCount: {
18
+ "Fn::If": [
19
+ "EcsDesiredCountIsBlank",
20
+ {Ref: "AWS::NoValue"},
21
+ {Ref: "EcsDesiredCount"}
22
+ ]
23
+ },
24
+ NetworkConfiguration: {
25
+ AwsvpcConfiguration: {
26
+ Subnets: {Ref: "EcsSubnets"},
27
+ SecurityGroups: security_groups(:ecs)
28
+ }
29
+ },
30
+ LoadBalancers: {
31
+ "Fn::If": [
32
+ "CreateTargetGroupIsTrue",
33
+ [
34
+ {
35
+ ContainerName: "web",
36
+ ContainerPort: @container[:port],
37
+ TargetGroupArn: {Ref: "TargetGroup"}
38
+ }
39
+ ],
40
+ {
41
+ "Fn::If": [
42
+ "ElbTargetGroupIsBlank",
43
+ [],
44
+ [
45
+ {
46
+ ContainerName: "web",
47
+ ContainerPort: @container[:port],
48
+ TargetGroupArn: {Ref: "ElbTargetGroup"}
49
+ }
50
+ ]
51
+ ]
52
+ }
53
+ ]
54
+ },
55
+ SchedulingStrategy: {Ref: "EcsSchedulingStrategy"}
56
+ }
57
+
58
+ props[:TaskDefinition] = @rollback_definition_arn ? @rollback_definition_arn : {Ref: "TaskDefinition"}
59
+ if @container[:fargate]
60
+ props[:LaunchType] = "FARGATE"
61
+ props[:NetworkConfiguration][:AwsvpcConfiguration][:AssignPublicIp] = "ENABLED" # Works with fargate but doesnt seem to work with non-fargate
62
+ end
63
+
64
+ props
65
+ end
66
+ end
67
+ end