cloud-templates 0.1.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 +7 -0
- data/.rubocop.yml +29 -0
- data/.simplecov +6 -0
- data/Gemfile +2 -0
- data/LICENSE +201 -0
- data/NOTICE +13 -0
- data/README.md +124 -0
- data/Rakefile +27 -0
- data/cloud-templates.gemspec +27 -0
- data/examples/lib/user_directory/artifacts/catalogized.rb +11 -0
- data/examples/lib/user_directory/artifacts/group.rb +37 -0
- data/examples/lib/user_directory/artifacts/ided.rb +11 -0
- data/examples/lib/user_directory/artifacts/organization.rb +17 -0
- data/examples/lib/user_directory/artifacts/pathed.rb +22 -0
- data/examples/lib/user_directory/artifacts/person.rb +20 -0
- data/examples/lib/user_directory/artifacts/team.rb +31 -0
- data/examples/lib/user_directory/artifacts/unit.rb +24 -0
- data/examples/lib/user_directory/artifacts/user.rb +29 -0
- data/examples/lib/user_directory/render/etc/artifact_view.rb +15 -0
- data/examples/lib/user_directory/render/etc/composite_view.rb +26 -0
- data/examples/lib/user_directory/render/etc/group_view.rb +23 -0
- data/examples/lib/user_directory/render/etc/person_view.rb +19 -0
- data/examples/lib/user_directory/render/etc/registry.rb +33 -0
- data/examples/lib/user_directory/render/etc/user_view.rb +35 -0
- data/examples/lib/user_directory/render/etc.rb +3 -0
- data/examples/lib/user_directory/render/ldap/artifact_view.rb +27 -0
- data/examples/lib/user_directory/render/ldap/composite_view.rb +32 -0
- data/examples/lib/user_directory/render/ldap/group_view.rb +28 -0
- data/examples/lib/user_directory/render/ldap/organization_view.rb +26 -0
- data/examples/lib/user_directory/render/ldap/person_view.rb +39 -0
- data/examples/lib/user_directory/render/ldap/registry.rb +16 -0
- data/examples/lib/user_directory/render/ldap/unit_view.rb +26 -0
- data/examples/lib/user_directory/render/ldap/user_view.rb +39 -0
- data/examples/lib/user_directory/render/ldap.rb +3 -0
- data/examples/lib/user_directory/utils.rb +18 -0
- data/examples/lib/user_directory.rb +23 -0
- data/examples/lib_path.rb +2 -0
- data/examples/spec/spec_helper.rb +1 -0
- data/examples/spec/user_directory_spec.rb +568 -0
- data/lib/aws/templates/artifact.rb +140 -0
- data/lib/aws/templates/composite.rb +178 -0
- data/lib/aws/templates/exceptions.rb +221 -0
- data/lib/aws/templates/render/registry.rb +60 -0
- data/lib/aws/templates/render/utils/base_type_views.rb +131 -0
- data/lib/aws/templates/render/view.rb +127 -0
- data/lib/aws/templates/render.rb +72 -0
- data/lib/aws/templates/utils/artifact_storage.rb +141 -0
- data/lib/aws/templates/utils/contextualized/filters.rb +437 -0
- data/lib/aws/templates/utils/contextualized/hash.rb +13 -0
- data/lib/aws/templates/utils/contextualized/nil.rb +13 -0
- data/lib/aws/templates/utils/contextualized/proc.rb +13 -0
- data/lib/aws/templates/utils/contextualized.rb +113 -0
- data/lib/aws/templates/utils/default.rb +185 -0
- data/lib/aws/templates/utils/dependency/enumerable.rb +13 -0
- data/lib/aws/templates/utils/dependency/object.rb +46 -0
- data/lib/aws/templates/utils/dependency.rb +121 -0
- data/lib/aws/templates/utils/dependent.rb +28 -0
- data/lib/aws/templates/utils/inheritable.rb +52 -0
- data/lib/aws/templates/utils/late_bound.rb +89 -0
- data/lib/aws/templates/utils/memoized.rb +27 -0
- data/lib/aws/templates/utils/named.rb +19 -0
- data/lib/aws/templates/utils/options.rb +279 -0
- data/lib/aws/templates/utils/parametrized/constraints.rb +423 -0
- data/lib/aws/templates/utils/parametrized/getters.rb +293 -0
- data/lib/aws/templates/utils/parametrized/guarded.rb +32 -0
- data/lib/aws/templates/utils/parametrized/mapper.rb +73 -0
- data/lib/aws/templates/utils/parametrized/nested.rb +72 -0
- data/lib/aws/templates/utils/parametrized/transformations.rb +660 -0
- data/lib/aws/templates/utils/parametrized.rb +240 -0
- data/lib/aws/templates/utils.rb +219 -0
- data/lib/aws/templates.rb +16 -0
- data/spec/aws/templates/artifact_spec.rb +161 -0
- data/spec/aws/templates/composite_spec.rb +361 -0
- data/spec/aws/templates/render/utils/base_type_views_spec.rb +104 -0
- data/spec/aws/templates/render_spec.rb +62 -0
- data/spec/aws/templates/utils/as_named_spec.rb +31 -0
- data/spec/aws/templates/utils/contextualized/filters_spec.rb +108 -0
- data/spec/aws/templates/utils/contextualized_spec.rb +115 -0
- data/spec/aws/templates/utils/late_bound_spec.rb +52 -0
- data/spec/aws/templates/utils/options_spec.rb +67 -0
- data/spec/aws/templates/utils/parametrized/constraint_spec.rb +175 -0
- data/spec/aws/templates/utils/parametrized/getters_spec.rb +139 -0
- data/spec/aws/templates/utils/parametrized/transformation_spec.rb +314 -0
- data/spec/aws/templates/utils/parametrized_spec.rb +241 -0
- data/spec/spec_helper.rb +6 -0
- metadata +244 -0
@@ -0,0 +1,293 @@
|
|
1
|
+
require 'aws/templates/exceptions'
|
2
|
+
require 'aws/templates/utils/parametrized'
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
module Aws
|
6
|
+
module Templates
|
7
|
+
module Utils
|
8
|
+
module Parametrized #:nodoc:
|
9
|
+
##
|
10
|
+
# Getter functor class
|
11
|
+
#
|
12
|
+
# A getter is a Proc without parameters and it is expected to return
|
13
|
+
# a value. Since the proc is to be executed in instance context
|
14
|
+
# the value can be calculated based on other methods or extracted from
|
15
|
+
# options attrribute
|
16
|
+
#
|
17
|
+
# The class implements functor pattern through to_proc method and
|
18
|
+
# closure. Essentially, all getters can be used everywhere where
|
19
|
+
# a block is expected.
|
20
|
+
#
|
21
|
+
# It provides protected method get which should be overriden in
|
22
|
+
# all concrete getter classes.
|
23
|
+
class Getter
|
24
|
+
##
|
25
|
+
# Get parameter from instance variables as is
|
26
|
+
#
|
27
|
+
# Gets value from instance variable by parameter's name without
|
28
|
+
# any other operations performed.
|
29
|
+
#
|
30
|
+
# === Example
|
31
|
+
#
|
32
|
+
# class Piece
|
33
|
+
# include Aws::Templates::Utils::Parametrized
|
34
|
+
#
|
35
|
+
# parameter :param1, getter: as_instance_variable
|
36
|
+
#
|
37
|
+
# def initialize(x)
|
38
|
+
# @param1 = x
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# i = Piece.new(3)
|
43
|
+
# i.param1 # => 3
|
44
|
+
class AsInstanceVariable < Getter
|
45
|
+
include Singleton
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def get(parameter, instance)
|
50
|
+
instance.instance_variable_get("@#{parameter.name}")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Get options value "as is"
|
56
|
+
#
|
57
|
+
# Gets value from options attribute by parameter's name without
|
58
|
+
# any other operations performed.
|
59
|
+
#
|
60
|
+
# === Example
|
61
|
+
#
|
62
|
+
# class Piece
|
63
|
+
# include Aws::Templates::Utils::Parametrized
|
64
|
+
#
|
65
|
+
# parameter :param1, :getter => as_is
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# i = Piece.new(:param1 => 3)
|
69
|
+
# i.param1 # => 3
|
70
|
+
class AsIs < Getter
|
71
|
+
include Singleton
|
72
|
+
|
73
|
+
protected
|
74
|
+
|
75
|
+
def get(parameter, instance)
|
76
|
+
instance.options[parameter.name]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Lookup value in options by path
|
82
|
+
#
|
83
|
+
# Looks up value from options attribute by specified path. The path
|
84
|
+
# can be either statically specified or a block can be provided.
|
85
|
+
# The block shouldn't have parameters and should return an array
|
86
|
+
# containing path. The block will be executed in the instance context.
|
87
|
+
#
|
88
|
+
# === Example
|
89
|
+
#
|
90
|
+
# class Piece
|
91
|
+
# include Aws::Templates::Utils::Parametrized
|
92
|
+
#
|
93
|
+
# parameter :param1, :getter => path(:a, :b)
|
94
|
+
# end
|
95
|
+
#
|
96
|
+
# i = Piece.new(:a => { :b => 3 })
|
97
|
+
# i.param1 # => 3
|
98
|
+
class Path < Getter
|
99
|
+
attr_reader :path
|
100
|
+
|
101
|
+
def initialize(path)
|
102
|
+
unless path.respond_to?(:to_proc) || path.respond_to?(:to_a)
|
103
|
+
raise ArgumentError.new(
|
104
|
+
"Path can be either array or Proc: #{path.inspect}"
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
@path = path
|
109
|
+
end
|
110
|
+
|
111
|
+
protected
|
112
|
+
|
113
|
+
def get(_, instance)
|
114
|
+
if path.respond_to?(:to_proc)
|
115
|
+
instance.options[*instance.instance_eval(&path)]
|
116
|
+
elsif path.respond_to?(:to_a)
|
117
|
+
instance.options[*path]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# Calculate value
|
124
|
+
#
|
125
|
+
# If a block is specified, it will be executed in the instance
|
126
|
+
# context and return will be used as parameter value. If a value
|
127
|
+
# specified then it will be used as parameter value instead.
|
128
|
+
#
|
129
|
+
# === Example
|
130
|
+
#
|
131
|
+
# class Piece
|
132
|
+
# include Aws::Templates::Utils::Parametrized
|
133
|
+
#
|
134
|
+
# parameter :param1, :getter => value(1)
|
135
|
+
# parameter :param2, :getter => value { options[:z] + 1 }
|
136
|
+
# end
|
137
|
+
#
|
138
|
+
# i = Piece.new(:z => 3)
|
139
|
+
# i.param2 # => 4
|
140
|
+
# i.param1 # => 1
|
141
|
+
class Value < Getter
|
142
|
+
attr_reader :calculation
|
143
|
+
|
144
|
+
def initialize(calculation)
|
145
|
+
@calculation = calculation
|
146
|
+
end
|
147
|
+
|
148
|
+
protected
|
149
|
+
|
150
|
+
def get(_, instance)
|
151
|
+
if calculation.respond_to?(:to_hash)
|
152
|
+
calculation
|
153
|
+
elsif calculation.respond_to?(:to_proc)
|
154
|
+
instance.instance_eval(&calculation)
|
155
|
+
else
|
156
|
+
calculation
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
##
|
162
|
+
# Pick one of non-nil values returned by nested getters
|
163
|
+
#
|
164
|
+
# In general it plays the same role as || operator in Ruby. It
|
165
|
+
# just picks first non-nil value returned by a list of getters
|
166
|
+
#
|
167
|
+
# === Example
|
168
|
+
#
|
169
|
+
# class Piece
|
170
|
+
# include Aws::Templates::Utils::Parametrized
|
171
|
+
#
|
172
|
+
# parameter :param1, :getter => one_of(
|
173
|
+
# path(:a, :b),
|
174
|
+
# path(:b, :c)
|
175
|
+
# )
|
176
|
+
# end
|
177
|
+
#
|
178
|
+
# i = Piece.new( :a => { :b => 3 } )
|
179
|
+
# i.param1 # => 3
|
180
|
+
# i = Piece.new( :b => { :c => 4 } )
|
181
|
+
# i.param1 # => 4
|
182
|
+
class OneOf < Getter
|
183
|
+
attr_reader :getters
|
184
|
+
|
185
|
+
def initialize(getters)
|
186
|
+
@getters = getters
|
187
|
+
end
|
188
|
+
|
189
|
+
protected
|
190
|
+
|
191
|
+
def get(parameter, instance)
|
192
|
+
getters.inject(nil) do |value, g|
|
193
|
+
value = instance.instance_exec(parameter, &g)
|
194
|
+
break value unless value.nil?
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
##
|
200
|
+
# Creates closure with getter invocation
|
201
|
+
#
|
202
|
+
# It's an interface method required for Getter to expose
|
203
|
+
# functor properties. It encloses invocation of Getter get_wrapper
|
204
|
+
# method into a closure. The closure itself is executed in the context
|
205
|
+
# of Parametrized instance which provides proper set "self" variable.
|
206
|
+
#
|
207
|
+
# The closure itself accepts 1 parameters
|
208
|
+
# * +parameter+ - the Parameter object which the getter is executed for
|
209
|
+
# ...where instance is assumed from self
|
210
|
+
def to_proc
|
211
|
+
getter = self
|
212
|
+
|
213
|
+
lambda do |parameter|
|
214
|
+
getter.get_wrapper(parameter, self)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
##
|
219
|
+
# Wraps getter-dependent method
|
220
|
+
#
|
221
|
+
# It wraps constraint-dependent "get" method into a rescue block
|
222
|
+
# to standardize exception type and information provided by failed
|
223
|
+
# value calculation
|
224
|
+
# * +parameter+ - the Parameter object which the getter is executed for
|
225
|
+
# * +instance+ - the instance value is taken from
|
226
|
+
def get_wrapper(parameter, instance)
|
227
|
+
get(parameter, instance)
|
228
|
+
rescue StandardError
|
229
|
+
raise NestedParameterException.new(parameter)
|
230
|
+
end
|
231
|
+
|
232
|
+
protected
|
233
|
+
|
234
|
+
##
|
235
|
+
# Getter method
|
236
|
+
#
|
237
|
+
# * +parameter+ - the Parameter object which the getter is executed for
|
238
|
+
# * +instance+ - the instance value is taken from
|
239
|
+
def get(parameter, instance); end
|
240
|
+
end
|
241
|
+
|
242
|
+
##
|
243
|
+
# Syntax sugar for getters definition
|
244
|
+
#
|
245
|
+
# It injects the methods as class-scope methods into mixing classes.
|
246
|
+
# The methods are factories to create particular type of getter
|
247
|
+
class_scope do
|
248
|
+
##
|
249
|
+
# Get parameter from instance variables as is
|
250
|
+
#
|
251
|
+
# alias for AsInstanceVariable class
|
252
|
+
def as_instance_variable
|
253
|
+
Getter::AsInstanceVariable.instance
|
254
|
+
end
|
255
|
+
|
256
|
+
##
|
257
|
+
# Get parameter from Options as is
|
258
|
+
#
|
259
|
+
# alias for AsIs class
|
260
|
+
def as_is
|
261
|
+
Getter::AsIs.instance
|
262
|
+
end
|
263
|
+
|
264
|
+
##
|
265
|
+
# Calculate value of parameter
|
266
|
+
#
|
267
|
+
# alias for Value class
|
268
|
+
def value(v = nil, &blk)
|
269
|
+
Getter::Value.new(v.nil? ? blk : v)
|
270
|
+
end
|
271
|
+
|
272
|
+
##
|
273
|
+
# Look up value of the parameter with path
|
274
|
+
#
|
275
|
+
# alias for Path class
|
276
|
+
def path(*v, &blk)
|
277
|
+
Getter::Path.new(
|
278
|
+
v.empty? ? blk : v
|
279
|
+
)
|
280
|
+
end
|
281
|
+
|
282
|
+
##
|
283
|
+
# Choose one non-nil value from nested getters
|
284
|
+
#
|
285
|
+
# alias for OneOf class
|
286
|
+
def one_of(*getters)
|
287
|
+
Getter::OneOf.new(getters)
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Aws
|
4
|
+
module Templates
|
5
|
+
module Utils
|
6
|
+
module Parametrized
|
7
|
+
##
|
8
|
+
# Remember Alan Turing's halting problem and don't believe in miracles. The method will
|
9
|
+
# only work with parameters because they are supposed to be pure unmodifying functions.
|
10
|
+
# Hence we can terminate if a parameter method was invoked twice in the stack with the same
|
11
|
+
# context.
|
12
|
+
module Guarded
|
13
|
+
Call = Struct.new(:instance, :parameter)
|
14
|
+
|
15
|
+
def guarded_get(instance, parameter_object)
|
16
|
+
current_call = Call.new(instance, parameter_object)
|
17
|
+
return unless trace.add?(current_call)
|
18
|
+
ret = parameter_object.get(self)
|
19
|
+
trace.delete(current_call)
|
20
|
+
ret
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def trace
|
26
|
+
Thread.current[Guarded.name] ||= Set.new
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Aws
|
4
|
+
module Templates
|
5
|
+
module Utils
|
6
|
+
module Parametrized
|
7
|
+
##
|
8
|
+
# Map from "parametrized" to "recursive"
|
9
|
+
#
|
10
|
+
# The class is adapter used to wrap any "parametrized" object (implementing "parametrized"
|
11
|
+
# concept) into an object implementing "hashable" and "recursive" concepts.
|
12
|
+
class Mapper
|
13
|
+
attr_reader :delegate
|
14
|
+
|
15
|
+
SPECIAL_CASE = [:root].freeze
|
16
|
+
|
17
|
+
def [](key)
|
18
|
+
@delegate.public_send(key) if @parameter_names.include?(key)
|
19
|
+
end
|
20
|
+
|
21
|
+
def include?(key)
|
22
|
+
@parameter_names.include?(key)
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_hash
|
26
|
+
@parameter_names.each_with_object({}) do |method_name, hsh|
|
27
|
+
hsh[method_name] = @delegate.public_send(method_name)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def keys
|
32
|
+
@parameter_names.to_a
|
33
|
+
end
|
34
|
+
|
35
|
+
def dependency?
|
36
|
+
delegate.dependency?
|
37
|
+
end
|
38
|
+
|
39
|
+
def dependencies
|
40
|
+
delegate.dependencies
|
41
|
+
end
|
42
|
+
|
43
|
+
def object
|
44
|
+
delegate.object
|
45
|
+
end
|
46
|
+
|
47
|
+
def initialize(obj)
|
48
|
+
obj.parameter_names.each { |pname| _check_parameter(obj, pname) }
|
49
|
+
@delegate = obj
|
50
|
+
@parameter_names = Set.new(@delegate.parameter_names).merge(SPECIAL_CASE)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
PROPERTY_LIKE = /^[^_!?][^!?]*$/
|
56
|
+
|
57
|
+
def _check_parameter(obj, name)
|
58
|
+
_raise_misnamed(obj, name) unless name.to_s =~ PROPERTY_LIKE
|
59
|
+
_raise_arity(obj, name) unless obj.public_method(name).arity.zero?
|
60
|
+
end
|
61
|
+
|
62
|
+
def _raise_misnamed(obj, name)
|
63
|
+
raise "Parameter #{name} of #{obj} is mis-named"
|
64
|
+
end
|
65
|
+
|
66
|
+
def _raise_arity(obj, name)
|
67
|
+
raise "Parameter #{name} of #{obj} has arity"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'aws/templates/utils/default'
|
3
|
+
require 'aws/templates/utils/parametrized'
|
4
|
+
require 'aws/templates/utils/parametrized/getters'
|
5
|
+
require 'aws/templates/utils/dependent'
|
6
|
+
require 'aws/templates/utils/options'
|
7
|
+
|
8
|
+
module Aws
|
9
|
+
module Templates
|
10
|
+
module Utils
|
11
|
+
module Parametrized
|
12
|
+
##
|
13
|
+
# Parametrized wrapper
|
14
|
+
#
|
15
|
+
# Wraps hash or object into "parametrized" instance. Used for nested parameter definitions.
|
16
|
+
class Nested
|
17
|
+
include Parametrized
|
18
|
+
include Default
|
19
|
+
include Dependent
|
20
|
+
|
21
|
+
attr_reader :options
|
22
|
+
|
23
|
+
def self.getter
|
24
|
+
as_is
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.create_class(scope)
|
28
|
+
klass = ::Class.new(self)
|
29
|
+
klass.singleton_class.send(:define_method, :scope) { scope }
|
30
|
+
klass
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.with(mod)
|
34
|
+
include mod
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.inspect
|
39
|
+
to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.scope
|
43
|
+
::Object
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.to_s
|
47
|
+
"<Nested object definition in #{scope}>"
|
48
|
+
end
|
49
|
+
|
50
|
+
def dependency?
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
attr_reader :root
|
55
|
+
|
56
|
+
def dependencies
|
57
|
+
@dependencies ||= Set.new
|
58
|
+
end
|
59
|
+
|
60
|
+
protected
|
61
|
+
|
62
|
+
def initialize(root_link, obj)
|
63
|
+
@root = root_link
|
64
|
+
depends_on(obj) if obj.dependency?
|
65
|
+
@options = Options.new(obj)
|
66
|
+
process_options(obj)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|