ufo 4.6.3 → 5.0.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 +4 -4
- data/CHANGELOG.md +14 -0
- data/docs/_docs/extras/notification-arns.md +21 -0
- data/docs/_docs/helpers.md +6 -4
- data/docs/_docs/iam-roles.md +111 -0
- data/docs/_docs/secrets.md +112 -0
- data/docs/_docs/settings/cluster.md +7 -13
- data/docs/_includes/subnav.html +3 -0
- data/docs/_reference/ufo-deploy.md +1 -2
- data/docs/_reference/ufo-logs.md +1 -1
- data/docs/_reference/ufo-rollback.md +2 -0
- data/docs/_reference/ufo-ship.md +1 -2
- data/docs/_reference/ufo-ships.md +1 -2
- data/docs/_reference/ufo-tasks-build.md +1 -2
- data/lib/template/.secrets +3 -0
- data/lib/template/.ufo/settings.yml.tt +1 -0
- data/lib/template/.ufo/settings/cfn/default.yml.tt +27 -27
- data/lib/template/.ufo/settings/network/default.yml.tt +9 -0
- data/lib/template/.ufo/templates/fargate.json.erb +3 -0
- data/lib/template/.ufo/templates/main.json.erb +3 -0
- data/lib/template/.ufo/variables/base.rb.tt +1 -0
- data/lib/ufo.rb +2 -1
- data/lib/ufo/autoloader.rb +9 -0
- data/lib/ufo/cli.rb +3 -2
- data/lib/ufo/core.rb +1 -9
- data/lib/ufo/docker/cleaner.rb +1 -1
- data/lib/ufo/dsl.rb +6 -1
- data/lib/ufo/dsl/helper.rb +19 -37
- data/lib/ufo/dsl/helper/vars.rb +98 -0
- data/lib/ufo/dsl/outputter.rb +12 -9
- data/lib/ufo/log_group.rb +1 -0
- data/lib/ufo/role/builder.rb +66 -0
- data/lib/ufo/role/dsl.rb +21 -0
- data/lib/ufo/role/registry.rb +24 -0
- data/lib/ufo/rollback.rb +2 -1
- data/lib/ufo/setting/profile.rb +11 -7
- data/lib/ufo/setting/security_groups.rb +22 -0
- data/lib/ufo/settings.rb +20 -0
- data/lib/ufo/stack.rb +24 -24
- data/lib/ufo/stack/builder.rb +26 -0
- data/lib/ufo/stack/builder/base.rb +54 -0
- data/lib/ufo/stack/builder/conditions.rb +23 -0
- data/lib/ufo/stack/builder/outputs.rb +24 -0
- data/lib/ufo/stack/builder/parameters.rb +45 -0
- data/lib/ufo/stack/builder/resources.rb +20 -0
- data/lib/ufo/stack/builder/resources/base.rb +4 -0
- data/lib/ufo/stack/builder/resources/dns.rb +17 -0
- data/lib/ufo/stack/builder/resources/ecs.rb +63 -0
- data/lib/ufo/stack/builder/resources/elb.rb +45 -0
- data/lib/ufo/stack/builder/resources/listener.rb +42 -0
- data/lib/ufo/stack/builder/resources/listener_ssl.rb +16 -0
- data/lib/ufo/stack/builder/resources/roles/base.rb +22 -0
- data/lib/ufo/stack/builder/resources/roles/execution_role.rb +4 -0
- data/lib/ufo/stack/builder/resources/roles/task_role.rb +4 -0
- data/lib/ufo/stack/builder/resources/security_group/base.rb +4 -0
- data/lib/ufo/stack/builder/resources/security_group/ecs.rb +44 -0
- data/lib/ufo/stack/builder/resources/security_group/ecs_rule.rb +25 -0
- data/lib/ufo/stack/builder/resources/security_group/elb.rb +57 -0
- data/lib/ufo/stack/builder/resources/target_group.rb +39 -0
- data/lib/ufo/stack/builder/resources/task_definition.rb +24 -0
- data/lib/ufo/stack/builder/resources/task_definition/reconstructor.rb +49 -0
- data/lib/ufo/stack/context.rb +41 -48
- data/lib/ufo/stack/custom_properties.rb +59 -0
- data/lib/ufo/stack/helper.rb +2 -5
- data/lib/ufo/stack/template_body.rb +13 -0
- data/lib/ufo/task.rb +2 -7
- data/lib/ufo/tasks.rb +1 -1
- data/lib/ufo/tasks/builder.rb +0 -1
- data/lib/ufo/template_scope.rb +1 -66
- data/lib/ufo/utils/squeezer.rb +24 -0
- data/lib/ufo/version.rb +1 -1
- data/spec/fixtures/iam_roles/task_role.rb +17 -0
- data/spec/lib/role/builder_spec.rb +67 -0
- data/spec/lib/role/dsl_spec.rb +12 -0
- data/ufo.gemspec +1 -0
- metadata +57 -3
- data/lib/cfn/stack.yml +0 -283
data/lib/ufo/stack/context.rb
CHANGED
@@ -2,13 +2,15 @@ class Ufo::Stack
|
|
2
2
|
class Context
|
3
3
|
extend Memoist
|
4
4
|
include Helper
|
5
|
+
include Ufo::Settings
|
5
6
|
|
7
|
+
attr_reader :stack_name
|
6
8
|
def initialize(options)
|
7
9
|
@options = options
|
8
10
|
@task_definition = options[:task_definition]
|
9
11
|
@service = options[:service]
|
10
12
|
# no need to adjust @cluster or @stack_name because it was adjusted in Stack#initialize
|
11
|
-
@cluster = options[:cluster]
|
13
|
+
@cluster = options[:cluster].dup # Thor options are frozen, we thaw it because CustomProperties#substitute_variables does a sub!
|
12
14
|
@stack_name = options[:stack_name]
|
13
15
|
|
14
16
|
@stack = options[:stack]
|
@@ -20,36 +22,44 @@ class Ufo::Stack
|
|
20
22
|
# Add additional variable to scope for CloudFormation template.
|
21
23
|
# Dirties the scope but needed.
|
22
24
|
vars = {
|
25
|
+
service: @service,
|
23
26
|
cluster: @cluster,
|
24
27
|
stack_name: @stack_name, # used in custom_properties
|
25
28
|
container: container,
|
29
|
+
# to reconstruct TaskDefinition in the CloudFormation template
|
30
|
+
task_definition: @task_definition,
|
31
|
+
rollback_definition_arn: @options[:rollback_definition_arn],
|
26
32
|
# elb options remember that their 'state'
|
27
33
|
create_elb: create_elb?, # helps set Ecs DependsOn
|
28
34
|
elb_type: elb_type,
|
29
35
|
subnet_mappings: subnet_mappings,
|
30
|
-
create_route53: create_elb? &&
|
36
|
+
create_route53: create_elb? && has_dns_name?,
|
31
37
|
default_target_group_protocol: default_target_group_protocol,
|
32
38
|
default_listener_protocol: default_listener_protocol,
|
33
39
|
default_listener_ssl_protocol: default_listener_ssl_protocol,
|
34
40
|
create_listener_ssl: create_listener_ssl?,
|
35
41
|
}
|
36
|
-
|
37
|
-
# pp vars
|
42
|
+
|
38
43
|
scope.assign_instance_variables(vars)
|
39
44
|
scope
|
40
45
|
end
|
41
46
|
memoize :scope
|
42
47
|
|
48
|
+
def has_dns_name?
|
49
|
+
cfn.dig(:Dns, :Name) || cfn.dig(:dns, :name) # backwards compatiblity
|
50
|
+
end
|
51
|
+
|
43
52
|
def default_target_group_protocol
|
44
53
|
return 'TCP' if elb_type == 'network'
|
45
54
|
'HTTP'
|
46
55
|
end
|
47
56
|
|
48
57
|
def default_listener_protocol
|
58
|
+
port = cfn.dig(:Listener, :Port) || cfn.dig(:listener, :port) # backwards compatiblity
|
49
59
|
if elb_type == 'network'
|
50
|
-
|
60
|
+
port == 443 ? 'TLS' : 'TCP'
|
51
61
|
else
|
52
|
-
|
62
|
+
port == 443 ? 'HTTPS' : 'HTTP'
|
53
63
|
end
|
54
64
|
end
|
55
65
|
|
@@ -59,32 +69,8 @@ class Ufo::Stack
|
|
59
69
|
|
60
70
|
# if the configuration is set to anything then enable it
|
61
71
|
def create_listener_ssl?
|
62
|
-
cfn
|
63
|
-
end
|
64
|
-
|
65
|
-
def container
|
66
|
-
resp = ecs.describe_task_definition(task_definition: @task_definition)
|
67
|
-
task_definition = resp.task_definition
|
68
|
-
|
69
|
-
container_def = task_definition["container_definitions"].first
|
70
|
-
requires_compatibilities = task_definition["requires_compatibilities"]
|
71
|
-
fargate = requires_compatibilities && requires_compatibilities == ["FARGATE"]
|
72
|
-
network_mode = task_definition["network_mode"]
|
73
|
-
|
74
|
-
mappings = container_def["port_mappings"] || []
|
75
|
-
unless mappings.empty?
|
76
|
-
port = mappings.first["container_port"]
|
77
|
-
end
|
78
|
-
|
79
|
-
result = {
|
80
|
-
name: container_def["name"],
|
81
|
-
fargate: fargate,
|
82
|
-
network_mode: network_mode, # awsvpc, bridge, etc
|
83
|
-
}
|
84
|
-
result[:port] = port if port
|
85
|
-
result
|
72
|
+
cfn.dig(:ListenerSsl, :Port) || cfn.dig(:listener_ssl, :port) # backwards compatiblity
|
86
73
|
end
|
87
|
-
memoize :container
|
88
74
|
|
89
75
|
def create_elb?
|
90
76
|
create_elb, _ = elb_options
|
@@ -135,6 +121,29 @@ class Ufo::Stack
|
|
135
121
|
[create_elb, elb_target_group]
|
136
122
|
end
|
137
123
|
|
124
|
+
def container
|
125
|
+
task_definition = Builder::Resources::TaskDefinition::Reconstructor.new(@task_definition, @options[:rollback]).reconstruct
|
126
|
+
|
127
|
+
container_def = task_definition["ContainerDefinitions"].first
|
128
|
+
requires_compatibilities = task_definition["RequiresCompatibilities"]
|
129
|
+
fargate = requires_compatibilities && requires_compatibilities == ["FARGATE"]
|
130
|
+
network_mode = task_definition["NetworkMode"]
|
131
|
+
|
132
|
+
mappings = container_def["PortMappings"] || []
|
133
|
+
unless mappings.empty?
|
134
|
+
port = mappings.first["ContainerPort"]
|
135
|
+
end
|
136
|
+
|
137
|
+
result = {
|
138
|
+
name: container_def["Name"],
|
139
|
+
fargate: fargate,
|
140
|
+
network_mode: network_mode, # awsvpc, bridge, etc
|
141
|
+
}
|
142
|
+
result[:port] = port if port
|
143
|
+
result
|
144
|
+
end
|
145
|
+
memoize :container
|
146
|
+
|
138
147
|
def get_parameter_value(stack, key)
|
139
148
|
param = stack.parameters.find do |p|
|
140
149
|
p.parameter_key == key
|
@@ -188,10 +197,8 @@ class Ufo::Stack
|
|
188
197
|
|
189
198
|
def build_subnet_mappings!(allocations)
|
190
199
|
unless allocations.size == network[:elb_subnets].size
|
191
|
-
# puts "caller:".color(:cyan)
|
192
|
-
# puts caller
|
193
200
|
puts "ERROR: The allocation_ids must match in length to the subnets.".color(:red)
|
194
|
-
puts "Please double check that .ufo/settings/network/#{settings
|
201
|
+
puts "Please double check that .ufo/settings/network/#{settings.network_profile} has the same number of subnets as the eip allocation ids are you specifying."
|
195
202
|
subnets = network[:elb_subnets]
|
196
203
|
puts "Conigured subnets: #{subnets.inspect}"
|
197
204
|
puts "Specified allocation ids: #{allocations.inspect}"
|
@@ -242,19 +249,5 @@ class Ufo::Stack
|
|
242
249
|
end
|
243
250
|
memoize :elb_type
|
244
251
|
|
245
|
-
def network
|
246
|
-
Ufo::Setting::Profile.new(:network, settings[:network_profile]).data
|
247
|
-
end
|
248
|
-
memoize :network
|
249
|
-
|
250
|
-
def cfn
|
251
|
-
Ufo::Setting::Profile.new(:cfn, settings[:cfn_profile]).data
|
252
|
-
end
|
253
|
-
memoize :cfn
|
254
|
-
|
255
|
-
def settings
|
256
|
-
Ufo.settings
|
257
|
-
end
|
258
|
-
|
259
252
|
end
|
260
253
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class Ufo::Stack
|
2
|
+
class CustomProperties
|
3
|
+
include Ufo::Settings
|
4
|
+
|
5
|
+
def initialize(template, stack_name)
|
6
|
+
@template, @stack_name = template, stack_name
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply
|
10
|
+
customizations = camelize(cfn)
|
11
|
+
@template["Resources"].each do |logical_id, attrs|
|
12
|
+
custom_props = customizations[logical_id]
|
13
|
+
next unless custom_props
|
14
|
+
attrs["Properties"].deeper_merge!(custom_props, {overwrite_arrays: true})
|
15
|
+
end
|
16
|
+
|
17
|
+
substitute_variables!(@template["Resources"])
|
18
|
+
@template
|
19
|
+
end
|
20
|
+
|
21
|
+
# Keep backward compatiablity but encouraging CamelCase now because in the ufo init generator
|
22
|
+
# the .ufo/settings/cfn/default.yml is now CamelCase
|
23
|
+
def camelize(properties)
|
24
|
+
if ENV['UFO_CAMELIZE'] == '0' || settings[:auto_camelize] == false # provide a way to quickly test full camelize disable
|
25
|
+
return properties.deep_stringify_keys
|
26
|
+
end
|
27
|
+
|
28
|
+
# transform keys: camelize
|
29
|
+
properties.deep_stringify_keys.deep_transform_keys do |key|
|
30
|
+
if key == key.upcase # trying to generalize special rule for dns.TTL
|
31
|
+
key # leave key alone if key is already in all upcase
|
32
|
+
else
|
33
|
+
key.camelize
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Substitute special variables that cannot be baked into the template
|
39
|
+
# because they are dynamically assigned. Only one special variable:
|
40
|
+
#
|
41
|
+
# {stack_name}
|
42
|
+
def substitute_variables!(properties)
|
43
|
+
# transform values and substitute for special values
|
44
|
+
# https://stackoverflow.com/questions/34595142/process-nested-hash-to-convert-all-values-to-strings
|
45
|
+
#
|
46
|
+
# Examples:
|
47
|
+
# "{stack_name}.stag.boltops.com." => development-demo-web.stag.boltops.com.
|
48
|
+
# "{stack_name}.stag.boltops.com." => dev-demo-web-2.stag.boltops.com.
|
49
|
+
properties.deep_merge(properties) do |_,_,v|
|
50
|
+
if v.is_a?(String)
|
51
|
+
v.sub!('{stack_name}', @stack_name) # need shebang, updating in-place
|
52
|
+
else
|
53
|
+
v
|
54
|
+
end
|
55
|
+
end
|
56
|
+
properties
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/ufo/stack/helper.rb
CHANGED
@@ -2,6 +2,7 @@ class Ufo::Stack
|
|
2
2
|
module Helper
|
3
3
|
include Ufo::AwsService
|
4
4
|
include Ufo::Util
|
5
|
+
include Ufo::Settings
|
5
6
|
extend Memoist
|
6
7
|
|
7
8
|
def find_stack(stack_name)
|
@@ -34,15 +35,11 @@ class Ufo::Stack
|
|
34
35
|
when "append_nothing", "prepend_nothing"
|
35
36
|
[service, Ufo.env_extra]
|
36
37
|
else # new default. ufo v4.5 and above
|
37
|
-
[service, Ufo.env, Ufo.env_extra]
|
38
|
+
[service, Ufo.env.to_s, Ufo.env_extra]
|
38
39
|
end
|
39
40
|
parts.reject {|x| x==''}.compact.join('-') # stack_name
|
40
41
|
end
|
41
42
|
|
42
|
-
def cfn
|
43
|
-
Ufo::Setting::Profile.new(:cfn, settings[:cfn_profile]).data
|
44
|
-
end
|
45
|
-
|
46
43
|
def status
|
47
44
|
Status.new(@stack_name)
|
48
45
|
end
|
data/lib/ufo/task.rb
CHANGED
@@ -2,8 +2,9 @@ module Ufo
|
|
2
2
|
class Task < Base
|
3
3
|
extend Memoist
|
4
4
|
|
5
|
-
include Util
|
6
5
|
include AwsService
|
6
|
+
include Ufo::Settings
|
7
|
+
include Util
|
7
8
|
|
8
9
|
def initialize(task_definition, options)
|
9
10
|
@task_definition = task_definition
|
@@ -139,12 +140,6 @@ module Ufo
|
|
139
140
|
options
|
140
141
|
end
|
141
142
|
|
142
|
-
def network
|
143
|
-
settings = Ufo.settings
|
144
|
-
Setting::Profile.new(:network, settings[:network_profile]).data
|
145
|
-
end
|
146
|
-
memoize :network
|
147
|
-
|
148
143
|
def cloudwatch_info(task_arn)
|
149
144
|
config = container_definition[:log_configuration]
|
150
145
|
container_name = container_definition[:name]
|
data/lib/ufo/tasks.rb
CHANGED
@@ -2,7 +2,7 @@ module Ufo
|
|
2
2
|
class Tasks < Command
|
3
3
|
desc "build", "Build task definitions."
|
4
4
|
long_desc Help.text("tasks:build")
|
5
|
-
option :
|
5
|
+
option :image_override, desc: "Override image in task definition for quick testing"
|
6
6
|
def build
|
7
7
|
Tasks::Builder.new(options).build
|
8
8
|
end
|
data/lib/ufo/tasks/builder.rb
CHANGED
@@ -6,7 +6,6 @@ module Ufo
|
|
6
6
|
# build and register task definitions. There is little point of running them independently
|
7
7
|
# This method helps us do that.
|
8
8
|
build(options)
|
9
|
-
Tasks::Register.register(task_definition, options)
|
10
9
|
end
|
11
10
|
|
12
11
|
# ship: build and registers task definitions together
|
data/lib/ufo/template_scope.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Ufo
|
2
2
|
class TemplateScope
|
3
3
|
extend Memoist
|
4
|
+
include Ufo::Settings
|
4
5
|
|
5
6
|
attr_reader :helper
|
6
7
|
attr_reader :task_definition_name
|
@@ -44,72 +45,6 @@ module Ufo
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
47
|
-
def network
|
48
|
-
Ufo::Setting::Profile.new(:network, settings[:network_profile]).data
|
49
|
-
end
|
50
|
-
memoize :network
|
51
|
-
|
52
|
-
def cfn
|
53
|
-
Ufo::Setting::Profile.new(:cfn, settings[:cfn_profile]).data
|
54
|
-
end
|
55
|
-
memoize :cfn
|
56
|
-
|
57
|
-
def settings
|
58
|
-
Ufo.settings
|
59
|
-
end
|
60
|
-
|
61
|
-
def custom_properties(resource)
|
62
|
-
resource = resource.to_s.underscore
|
63
|
-
properties = cfn[resource.to_sym]
|
64
|
-
return unless properties
|
65
|
-
|
66
|
-
# transform keys: camelize
|
67
|
-
properties = properties.deep_stringify_keys.deep_transform_keys do |key|
|
68
|
-
if key == key.upcase # trying to generalize special rule for dns.TTL
|
69
|
-
key # leave key alone if key is already in all upcase
|
70
|
-
else
|
71
|
-
key.camelize
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
substitute_variables!(properties)
|
76
|
-
|
77
|
-
yaml = YAML.dump(properties)
|
78
|
-
# add spaces in front on each line
|
79
|
-
yaml.split("\n")[1..-1].map do |line|
|
80
|
-
" #{line}"
|
81
|
-
end.join("\n") + "\n"
|
82
|
-
end
|
83
|
-
|
84
|
-
# Substitute special variables that cannot be baked into the template
|
85
|
-
# because they are dynamically assigned. Only one special variable:
|
86
|
-
#
|
87
|
-
# {stack_name}
|
88
|
-
def substitute_variables!(properties)
|
89
|
-
# transform values and substitute for special values
|
90
|
-
# https://stackoverflow.com/questions/34595142/process-nested-hash-to-convert-all-values-to-strings
|
91
|
-
#
|
92
|
-
# Examples:
|
93
|
-
# "{stack_name}.stag.boltops.com." => development-demo-web.stag.boltops.com.
|
94
|
-
# "{stack_name}.stag.boltops.com." => dev-demo-web-2.stag.boltops.com.
|
95
|
-
properties.deep_merge(properties) do |_,_,v|
|
96
|
-
if v.is_a?(String)
|
97
|
-
v.sub!('{stack_name}', @stack_name) # unsure why need shebang, but it works
|
98
|
-
else
|
99
|
-
v
|
100
|
-
end
|
101
|
-
end
|
102
|
-
properties
|
103
|
-
end
|
104
|
-
|
105
|
-
def default_target_group_protocol
|
106
|
-
default_elb_protocol
|
107
|
-
end
|
108
|
-
|
109
|
-
def default_elb_protocol
|
110
|
-
@elb_type == "application" ? "HTTP" : "TCP"
|
111
|
-
end
|
112
|
-
|
113
48
|
def pretty_name?
|
114
49
|
# env variable takes highest precedence
|
115
50
|
if ENV["STATIC_NAME"]
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Ufo::Utils
|
2
|
+
class Squeezer
|
3
|
+
def initialize(data)
|
4
|
+
@data = data
|
5
|
+
end
|
6
|
+
|
7
|
+
def squeeze(new_data=nil)
|
8
|
+
data = new_data.nil? ? @data : new_data
|
9
|
+
|
10
|
+
case data
|
11
|
+
when Array
|
12
|
+
data.map! { |v| squeeze(v) }
|
13
|
+
when Hash
|
14
|
+
data.each_with_object({}) do |(k,v), squeezed|
|
15
|
+
# only remove nil and empty Array values within Hash structures
|
16
|
+
squeezed[k] = squeeze(v) unless v.nil? || v.is_a?(Array) && v.empty?
|
17
|
+
squeezed
|
18
|
+
end
|
19
|
+
else
|
20
|
+
data # do not transform
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/ufo/version.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
iam_policy("AmazonS3ReadOnlyAccess",
|
2
|
+
Action: [
|
3
|
+
"s3:Get*",
|
4
|
+
"s3:List*"
|
5
|
+
],
|
6
|
+
Effect: "Allow",
|
7
|
+
Resource: "*"
|
8
|
+
)
|
9
|
+
iam_policy("CloudwatchWrite",
|
10
|
+
Action: [
|
11
|
+
"cloudwatch:PutMetricData",
|
12
|
+
],
|
13
|
+
Effect: "Allow",
|
14
|
+
Resource: "*"
|
15
|
+
)
|
16
|
+
|
17
|
+
managed_iam_policy("AmazonS3ReadOnlyAccess", "AmazonEC2ReadOnlyAccess")
|
@@ -0,0 +1,67 @@
|
|
1
|
+
describe Ufo::Role::Builder do
|
2
|
+
let(:builder) { described_class.new(role_type) }
|
3
|
+
let(:role_type) { "task_role" }
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
Ufo::Role::Registry.register_policy("task_role",
|
7
|
+
"AmazonS3ReadOnlyAccess",
|
8
|
+
{:Action=>["s3:Get*", "s3:List*"], :Effect=>"Allow", :Resource=>"*"}
|
9
|
+
)
|
10
|
+
Ufo::Role::Registry.register_policy("task_role",
|
11
|
+
"CloudwatchWrite",
|
12
|
+
{:Action=>["cloudwatch:PutMetricData"], :Effect=>"Allow", :Resource=>"*"}
|
13
|
+
)
|
14
|
+
# Called twice on purpose to show that duplicated items in the set wont create doubles.
|
15
|
+
# This allows the DSL evaluate to be ran multiple times.
|
16
|
+
Ufo::Role::Registry.register_policy("task_role",
|
17
|
+
"CloudwatchWrite",
|
18
|
+
{:Action=>["cloudwatch:PutMetricData"], :Effect=>"Allow", :Resource=>"*"}
|
19
|
+
)
|
20
|
+
|
21
|
+
|
22
|
+
Ufo::Role::Registry.register_managed_policy("task_role",
|
23
|
+
"AmazonS3ReadOnlyAccess", "AmazonEC2ReadOnlyAccess"
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
context "build" do
|
28
|
+
it "builds role" do
|
29
|
+
resource = builder.build
|
30
|
+
expected = <<YAML
|
31
|
+
---
|
32
|
+
Type: AWS::IAM::Role
|
33
|
+
Properties:
|
34
|
+
AssumeRolePolicyDocument:
|
35
|
+
Version: '2012-10-17'
|
36
|
+
Statement:
|
37
|
+
- Effect: Allow
|
38
|
+
Principal:
|
39
|
+
Service: ecs-tasks.amazonaws.com
|
40
|
+
Action: sts:AssumeRole
|
41
|
+
Policies:
|
42
|
+
- PolicyName: AmazonS3ReadOnlyAccess
|
43
|
+
PolicyDocument:
|
44
|
+
Version: '2012-10-17'
|
45
|
+
Statement:
|
46
|
+
- Action:
|
47
|
+
- s3:Get*
|
48
|
+
- s3:List*
|
49
|
+
Effect: Allow
|
50
|
+
Resource: "*"
|
51
|
+
- PolicyName: CloudwatchWrite
|
52
|
+
PolicyDocument:
|
53
|
+
Version: '2012-10-17'
|
54
|
+
Statement:
|
55
|
+
- Action:
|
56
|
+
- cloudwatch:PutMetricData
|
57
|
+
Effect: Allow
|
58
|
+
Resource: "*"
|
59
|
+
ManagedPolicyArns:
|
60
|
+
- arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
|
61
|
+
- arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess
|
62
|
+
YAML
|
63
|
+
yaml = YAML.dump(resource)
|
64
|
+
expect(yaml).to eq(expected)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|