cloud-templates 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +29 -0
  3. data/.simplecov +6 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE +201 -0
  6. data/NOTICE +13 -0
  7. data/README.md +124 -0
  8. data/Rakefile +27 -0
  9. data/cloud-templates.gemspec +27 -0
  10. data/examples/lib/user_directory/artifacts/catalogized.rb +11 -0
  11. data/examples/lib/user_directory/artifacts/group.rb +37 -0
  12. data/examples/lib/user_directory/artifacts/ided.rb +11 -0
  13. data/examples/lib/user_directory/artifacts/organization.rb +17 -0
  14. data/examples/lib/user_directory/artifacts/pathed.rb +22 -0
  15. data/examples/lib/user_directory/artifacts/person.rb +20 -0
  16. data/examples/lib/user_directory/artifacts/team.rb +31 -0
  17. data/examples/lib/user_directory/artifacts/unit.rb +24 -0
  18. data/examples/lib/user_directory/artifacts/user.rb +29 -0
  19. data/examples/lib/user_directory/render/etc/artifact_view.rb +15 -0
  20. data/examples/lib/user_directory/render/etc/composite_view.rb +26 -0
  21. data/examples/lib/user_directory/render/etc/group_view.rb +23 -0
  22. data/examples/lib/user_directory/render/etc/person_view.rb +19 -0
  23. data/examples/lib/user_directory/render/etc/registry.rb +33 -0
  24. data/examples/lib/user_directory/render/etc/user_view.rb +35 -0
  25. data/examples/lib/user_directory/render/etc.rb +3 -0
  26. data/examples/lib/user_directory/render/ldap/artifact_view.rb +27 -0
  27. data/examples/lib/user_directory/render/ldap/composite_view.rb +32 -0
  28. data/examples/lib/user_directory/render/ldap/group_view.rb +28 -0
  29. data/examples/lib/user_directory/render/ldap/organization_view.rb +26 -0
  30. data/examples/lib/user_directory/render/ldap/person_view.rb +39 -0
  31. data/examples/lib/user_directory/render/ldap/registry.rb +16 -0
  32. data/examples/lib/user_directory/render/ldap/unit_view.rb +26 -0
  33. data/examples/lib/user_directory/render/ldap/user_view.rb +39 -0
  34. data/examples/lib/user_directory/render/ldap.rb +3 -0
  35. data/examples/lib/user_directory/utils.rb +18 -0
  36. data/examples/lib/user_directory.rb +23 -0
  37. data/examples/lib_path.rb +2 -0
  38. data/examples/spec/spec_helper.rb +1 -0
  39. data/examples/spec/user_directory_spec.rb +568 -0
  40. data/lib/aws/templates/artifact.rb +140 -0
  41. data/lib/aws/templates/composite.rb +178 -0
  42. data/lib/aws/templates/exceptions.rb +221 -0
  43. data/lib/aws/templates/render/registry.rb +60 -0
  44. data/lib/aws/templates/render/utils/base_type_views.rb +131 -0
  45. data/lib/aws/templates/render/view.rb +127 -0
  46. data/lib/aws/templates/render.rb +72 -0
  47. data/lib/aws/templates/utils/artifact_storage.rb +141 -0
  48. data/lib/aws/templates/utils/contextualized/filters.rb +437 -0
  49. data/lib/aws/templates/utils/contextualized/hash.rb +13 -0
  50. data/lib/aws/templates/utils/contextualized/nil.rb +13 -0
  51. data/lib/aws/templates/utils/contextualized/proc.rb +13 -0
  52. data/lib/aws/templates/utils/contextualized.rb +113 -0
  53. data/lib/aws/templates/utils/default.rb +185 -0
  54. data/lib/aws/templates/utils/dependency/enumerable.rb +13 -0
  55. data/lib/aws/templates/utils/dependency/object.rb +46 -0
  56. data/lib/aws/templates/utils/dependency.rb +121 -0
  57. data/lib/aws/templates/utils/dependent.rb +28 -0
  58. data/lib/aws/templates/utils/inheritable.rb +52 -0
  59. data/lib/aws/templates/utils/late_bound.rb +89 -0
  60. data/lib/aws/templates/utils/memoized.rb +27 -0
  61. data/lib/aws/templates/utils/named.rb +19 -0
  62. data/lib/aws/templates/utils/options.rb +279 -0
  63. data/lib/aws/templates/utils/parametrized/constraints.rb +423 -0
  64. data/lib/aws/templates/utils/parametrized/getters.rb +293 -0
  65. data/lib/aws/templates/utils/parametrized/guarded.rb +32 -0
  66. data/lib/aws/templates/utils/parametrized/mapper.rb +73 -0
  67. data/lib/aws/templates/utils/parametrized/nested.rb +72 -0
  68. data/lib/aws/templates/utils/parametrized/transformations.rb +660 -0
  69. data/lib/aws/templates/utils/parametrized.rb +240 -0
  70. data/lib/aws/templates/utils.rb +219 -0
  71. data/lib/aws/templates.rb +16 -0
  72. data/spec/aws/templates/artifact_spec.rb +161 -0
  73. data/spec/aws/templates/composite_spec.rb +361 -0
  74. data/spec/aws/templates/render/utils/base_type_views_spec.rb +104 -0
  75. data/spec/aws/templates/render_spec.rb +62 -0
  76. data/spec/aws/templates/utils/as_named_spec.rb +31 -0
  77. data/spec/aws/templates/utils/contextualized/filters_spec.rb +108 -0
  78. data/spec/aws/templates/utils/contextualized_spec.rb +115 -0
  79. data/spec/aws/templates/utils/late_bound_spec.rb +52 -0
  80. data/spec/aws/templates/utils/options_spec.rb +67 -0
  81. data/spec/aws/templates/utils/parametrized/constraint_spec.rb +175 -0
  82. data/spec/aws/templates/utils/parametrized/getters_spec.rb +139 -0
  83. data/spec/aws/templates/utils/parametrized/transformation_spec.rb +314 -0
  84. data/spec/aws/templates/utils/parametrized_spec.rb +241 -0
  85. data/spec/spec_helper.rb +6 -0
  86. metadata +244 -0
@@ -0,0 +1,314 @@
1
+ require 'spec_helper'
2
+ require 'aws/templates/utils/parametrized'
3
+ require 'aws/templates/utils/parametrized/transformations'
4
+ require 'aws/templates/utils/parametrized/constraints'
5
+ require 'aws/templates/utils/parametrized/getters'
6
+ require 'aws/templates/render'
7
+
8
+ module TestRender
9
+ extend Aws::Templates::Render
10
+ StringView = Class.new(Aws::Templates::Render::BasicView) do
11
+ def to_rendered
12
+ _stringify(instance)
13
+ end
14
+
15
+ def _stringify(obj)
16
+ return obj.to_s unless obj.respond_to?(:to_hash)
17
+ obj.to_hash.map { |k, v| [_stringify(k), _stringify(v)] }.to_h
18
+ end
19
+ end
20
+ StringView.register_in self
21
+ StringView.artifact ::Object
22
+ end
23
+
24
+ describe Aws::Templates::Utils::Parametrized::Transformation do
25
+ let(:parametrized_class) do
26
+ Class.new do
27
+ include Aws::Templates::Utils::Parametrized
28
+
29
+ def self.getter
30
+ as_is
31
+ end
32
+
33
+ attr_reader :options
34
+
35
+ def initialize(options)
36
+ @options = options
37
+ end
38
+ end
39
+ end
40
+
41
+ describe 'as_object' do
42
+ let(:test_class) do
43
+ Class.new(parametrized_class) do
44
+ parameter :something,
45
+ transform: as_object {
46
+ parameter :a, description: 'Parameter A'
47
+ parameter :b, description: 'Parameter B'
48
+ parameter :c, description: 'Parameter C', constraint: not_nil
49
+ }
50
+ end
51
+ end
52
+
53
+ it 'transforms hash into object correctly' do
54
+ i = test_class.new(something: { a: 1, b: 2, c: 3 })
55
+ expect([i.something.a, i.something.b, i.something.c])
56
+ .to be == [1, 2, 3]
57
+ end
58
+
59
+ it 'allows nil values in sub-fields if no constraint is specified' do
60
+ i = test_class.new(something: { a: 1, b: nil, c: 3 })
61
+ expect([i.something.a, i.something.b, i.something.c])
62
+ .to be == [1, nil, 3]
63
+ end
64
+
65
+ it 'throws an error if sub-parameter constraint is not satisfied' do
66
+ i = test_class.new(something: { a: 1, b: 2, c: nil })
67
+ expect { [i.something.a, i.something.b, i.something.c] }
68
+ .to raise_error Aws::Templates::ParameterValueInvalid
69
+ end
70
+ end
71
+
72
+ describe 'as_list' do
73
+ let(:test_class) do
74
+ Class.new(parametrized_class) do
75
+ parameter :something,
76
+ description: 'Something misterious',
77
+ transform: as_list(
78
+ name: :element,
79
+ description: 'Force of nature'
80
+ )
81
+ parameter :something_else,
82
+ description: 'Absolutely incomprehensible',
83
+ transform: as_list(
84
+ name: :element,
85
+ description: 'Celestial image',
86
+ constraint: not_nil
87
+ )
88
+ end
89
+ end
90
+
91
+ it 'handles nil values' do
92
+ expect(test_class.new({}).something).to be_nil
93
+ end
94
+
95
+ it 'handles list value' do
96
+ expect(test_class.new(something: [1, 2, 3]).something).to be == [1, 2, 3]
97
+ end
98
+
99
+ it 'allows nil values if no constraints are specified' do
100
+ expect(test_class.new(something: [1, nil, 3]).something).to be == [1, nil, 3]
101
+ end
102
+
103
+ it 'works with any kind of object' do
104
+ expect(test_class.new(something: 'abc'.each_char).something).to be == %w[a b c]
105
+ end
106
+
107
+ it 'fails if the value can be transformed to an array' do
108
+ expect { test_class.new(something: 'abc').something }
109
+ .to raise_error Aws::Templates::NestedParameterException
110
+ end
111
+
112
+ it 'returns correct value if sub-constraints are satisfied' do
113
+ expect(test_class.new(something_else: [1, 2, 3]).something_else).to be == [1, 2, 3]
114
+ end
115
+
116
+ it 'throws an exception if one or more elements don\'t satisfy sub-constraint' do
117
+ expect { test_class.new(something_else: [1, nil, 3]).something_else }
118
+ .to raise_error(/Celestial image/)
119
+ end
120
+ end
121
+
122
+ describe 'as_rendered' do
123
+ let(:render) { TestRender }
124
+
125
+ let(:test_class) do
126
+ klass = Class.new(parametrized_class)
127
+ klass.parameter :something, transform: klass.as_rendered(render)
128
+ klass
129
+ end
130
+
131
+ it 'transforms hash into stringified hash correctly' do
132
+ i = test_class.new(something: { a: 1, b: 2, c: 3 })
133
+ expect(i.something).to be == { 'a' => '1', 'b' => '2', 'c' => '3' }
134
+ end
135
+
136
+ it 'allows nil value' do
137
+ i = test_class.new({})
138
+ expect(i.something).to be_nil
139
+ end
140
+ end
141
+
142
+ describe 'as_integer' do
143
+ let(:test_class) do
144
+ Class.new(parametrized_class) do
145
+ parameter :something, transform: as_integer
146
+ end
147
+ end
148
+
149
+ it 'transforms string into integer correctly' do
150
+ i = test_class.new(something: '23')
151
+ expect(i.something).to be == 23
152
+ end
153
+
154
+ it 'allows nil value' do
155
+ i = test_class.new({})
156
+ expect(i.something).to be_nil
157
+ end
158
+
159
+ it 'fails on wrong value' do
160
+ i = test_class.new(something: [])
161
+ expect { i.something }.to raise_error Aws::Templates::NestedParameterException
162
+ end
163
+ end
164
+
165
+ describe 'as_string' do
166
+ let(:test_class) do
167
+ Class.new(parametrized_class) do
168
+ parameter :something, transform: as_string
169
+ end
170
+ end
171
+
172
+ it 'transforms integer into string correctly' do
173
+ i = test_class.new(something: 23)
174
+ expect(i.something).to be == '23'
175
+ end
176
+
177
+ it 'allows nil value' do
178
+ i = test_class.new({})
179
+ expect(i.something).to be_nil
180
+ end
181
+ end
182
+
183
+ describe 'as_boolean' do
184
+ let(:test_class) do
185
+ Class.new(parametrized_class) do
186
+ parameter :something, transform: as_boolean
187
+ end
188
+ end
189
+
190
+ it 'transforms string into boolean correctly' do
191
+ i = test_class.new(something: 23)
192
+ expect(i.something).to be == true
193
+ end
194
+
195
+ it 'transforms false correctly' do
196
+ i = test_class.new(something: false)
197
+ expect(i.something).to be == false
198
+ end
199
+
200
+ it 'transforms true correctly' do
201
+ i = test_class.new(something: true)
202
+ expect(i.something).to be == true
203
+ end
204
+
205
+ it 'transforms false string correctly' do
206
+ i = test_class.new(something: 'false')
207
+ expect(i.something).to be == false
208
+ end
209
+
210
+ it 'allows nil value' do
211
+ i = test_class.new({})
212
+ expect(i.something).to be_nil
213
+ end
214
+ end
215
+
216
+ describe 'as_hash' do
217
+ let(:test_class) do
218
+ Class.new(parametrized_class) do
219
+ parameter :something, transform: as_hash
220
+ parameter :something2,
221
+ transform: as_hash {
222
+ key name: :key,
223
+ description: 'String key',
224
+ constraint: not_nil,
225
+ transform: as_string
226
+ value name: :number,
227
+ description: 'Just a number',
228
+ constraint: not_nil,
229
+ transform: as_integer
230
+ }
231
+ end
232
+ end
233
+
234
+ let(:hashable) do
235
+ Class.new do
236
+ def to_hash
237
+ { w: 'qwe' }
238
+ end
239
+ end
240
+ end
241
+
242
+ it 'transforms hash correctly' do
243
+ i = test_class.new(something: { q: 3 })
244
+ expect(i.something).to be == { q: 3 }
245
+ end
246
+
247
+ it 'transforms array into hash correctly' do
248
+ i = test_class.new(something: [[:q, 3]])
249
+ expect(i.something).to be == { q: 3 }
250
+ end
251
+
252
+ it 'transforms an object into hash correctly' do
253
+ i = test_class.new(something: hashable.new)
254
+ expect(i.something).to be == { w: 'qwe' }
255
+ end
256
+
257
+ it 'allows nil value' do
258
+ i = test_class.new({})
259
+ expect(i.something).to be_nil
260
+ end
261
+
262
+ it 'understands internal structure' do
263
+ i = test_class.new(something2: { q: '3' })
264
+ expect(i.something2).to be == { 'q' => 3 }
265
+ end
266
+
267
+ it 'performs internal constraint check' do
268
+ i = test_class.new(something2: { q: nil })
269
+ expect { i.something2 }.to raise_error(/Just a number/)
270
+ end
271
+ end
272
+
273
+ describe 'as_module' do
274
+ let(:test_class) do
275
+ Class.new(parametrized_class) do
276
+ parameter :something, transform: as_module
277
+ end
278
+ end
279
+
280
+ it 'passes a class as is' do
281
+ i = test_class.new(something: Object)
282
+ expect(i.something).to be == Object
283
+ end
284
+
285
+ it 'looks up class name' do
286
+ i = test_class.new(something: 'Object')
287
+ expect(i.something).to be == Object
288
+ end
289
+
290
+ it 'is able to work with paths' do
291
+ i = test_class.new(something: 'Object::Object::Object::Array')
292
+ expect(i.something).to be == Array
293
+ end
294
+
295
+ it 'accepts different path specifications' do
296
+ i = test_class.new(something: 'Object/Object/Object/Array')
297
+ expect(i.something).to be == Array
298
+ end
299
+ end
300
+
301
+ describe 'as_chain' do
302
+ let(:test_class) do
303
+ Class.new(parametrized_class) do
304
+ parameter :something,
305
+ transform: as_chain(as_hash, as_object { parameter :rule })
306
+ end
307
+ end
308
+
309
+ it 'applies all transformations' do
310
+ i = test_class.new(something: [[:rule, 1]])
311
+ expect(i.something.rule).to be == 1
312
+ end
313
+ end
314
+ end
@@ -0,0 +1,241 @@
1
+ require 'spec_helper'
2
+ require 'aws/templates/utils/parametrized'
3
+ require 'aws/templates/utils/parametrized/getters'
4
+
5
+ describe Aws::Templates::Utils::Parametrized do
6
+ let(:including_class) do
7
+ Class.new do
8
+ include Aws::Templates::Utils::Parametrized
9
+
10
+ attr_reader :options
11
+
12
+ def self.getter
13
+ as_is
14
+ end
15
+
16
+ def initialize(options)
17
+ @options = options
18
+ end
19
+ end
20
+ end
21
+
22
+ let(:including_module) do
23
+ Module.new do
24
+ include Aws::Templates::Utils::Parametrized
25
+
26
+ parameter :mixed_parameter,
27
+ description: 'Just a parameter which will be added ' \
28
+ 'into including modules/classes',
29
+ transform: ->(_, v) { v.to_s }
30
+ end
31
+ end
32
+
33
+ describe 'module include' do
34
+ it 'has parameter DSL method' do
35
+ expect(including_module).to respond_to(:parameter)
36
+ end
37
+
38
+ it 'has accessor defined with the DSL' do
39
+ expect(including_module.method_defined?(:mixed_parameter))
40
+ .to be == true
41
+ end
42
+
43
+ it 'has parameter object defined with appropriate name' do
44
+ expect(including_module.get_parameter(:mixed_parameter).name)
45
+ .to be == :mixed_parameter
46
+ end
47
+ end
48
+
49
+ describe 'class include' do
50
+ it 'has parameter DSL method' do
51
+ expect(including_class).to respond_to(:parameter)
52
+ end
53
+ end
54
+
55
+ context 'Class is inherited and the module is included' do
56
+ let(:parametrized_class) do
57
+ INCLUDING_MODULE = including_module
58
+
59
+ Class.new(including_class) do
60
+ include INCLUDING_MODULE
61
+ end
62
+ end
63
+
64
+ let(:create_parameters) { { mixed_parameter: 5 } }
65
+
66
+ let(:instance) do
67
+ parametrized_class.new(create_parameters)
68
+ end
69
+
70
+ it 'returns value of module parameter' do
71
+ expect(instance.mixed_parameter).to be == '5'
72
+ end
73
+ end
74
+
75
+ context 'Class is inherited and extended with parameters' do
76
+ let(:parametrized_class) do
77
+ Class.new(including_class) do
78
+ parameter :all_properties_parameter,
79
+ description: 'Made to test the situation when all ' \
80
+ 'properties are specified',
81
+ getter: lambda { |p|
82
+ options[p.name.to_s.sub('parameter', 'option').to_sym]
83
+ },
84
+ transform: ->(_, v) { v + 1 },
85
+ constraint: ->(_, v) { raise "it's > 3!" if v > 3 }
86
+
87
+ parameter :bare_minimum,
88
+ description: '"Do defaults" type of parameter'
89
+ end
90
+ end
91
+
92
+ it 'parameter objects have correct attributes' do
93
+ expect(parametrized_class.get_parameter(:all_properties_parameter).name)
94
+ .to be == :all_properties_parameter
95
+ end
96
+
97
+ describe 'DSL' do
98
+ it 'has parameter DSL method' do
99
+ expect(parametrized_class).to respond_to(:parameter)
100
+ end
101
+ end
102
+
103
+ context 'Instance of the class created' do
104
+ let(:create_parameters) {}
105
+
106
+ let(:instance) do
107
+ parametrized_class.new(create_parameters)
108
+ end
109
+
110
+ it 'contains all_properties_parameter as accessor' do
111
+ expect(instance).to respond_to(:all_properties_parameter)
112
+ end
113
+
114
+ it 'contains bare_minimum as accessor' do
115
+ expect(instance).to respond_to(:bare_minimum)
116
+ end
117
+
118
+ context 'with compliant parameters' do
119
+ let(:create_parameters) do
120
+ {
121
+ all_properties_option: 2,
122
+ bare_minimum: 5
123
+ }
124
+ end
125
+
126
+ it 'returns all_properties_parameter correctly' do
127
+ expect(instance.all_properties_parameter).to be == 3
128
+ end
129
+
130
+ it 'returns bare_minimum correctly' do
131
+ expect(instance.bare_minimum).to be == 5
132
+ end
133
+ end
134
+
135
+ context 'with parameters violating the constraint' do
136
+ let(:create_parameters) do
137
+ {
138
+ all_properties_option: 3,
139
+ bare_minimum: 5
140
+ }
141
+ end
142
+
143
+ it 'raises an exception' do
144
+ expect { instance.all_properties_parameter }.to raise_error RuntimeError
145
+ end
146
+ end
147
+ end
148
+
149
+ context 'Class is inherited and a parameter added' do
150
+ let(:extending_class) do
151
+ Class.new(parametrized_class) do
152
+ parameter :just_addition,
153
+ description: 'Trying to add parameter to the ' \
154
+ 'parent\'s parameter list'
155
+ end
156
+ end
157
+
158
+ %i[just_addition all_properties_parameter bare_minimum].each do |name|
159
+ it "has accessor #{name} inherited from parent" do
160
+ expect(extending_class.method_defined?(name)).to be == true
161
+ end
162
+
163
+ it "has parameter #{name} inherited from parent" do
164
+ expect(extending_class.get_parameter(name).name).to be == name
165
+ end
166
+ end
167
+
168
+ context 'Instance of the class created' do
169
+ let(:create_parameters) do
170
+ {
171
+ all_properties_option: 2,
172
+ bare_minimum: 5,
173
+ just_addition: 'bonus'
174
+ }
175
+ end
176
+
177
+ let(:instance) do
178
+ extending_class.new(create_parameters)
179
+ end
180
+
181
+ {
182
+ all_properties_parameter: 3,
183
+ bare_minimum: 5,
184
+ just_addition: 'bonus'
185
+ }.each_pair do |name, value|
186
+ it "returns #{name} attributes correctly" do
187
+ expect(instance.send(name)).to be == value
188
+ end
189
+ end
190
+ end
191
+
192
+ context 'Class inherited and parameter mixin added' do
193
+ let(:mixing_class) do
194
+ k = Class.new(extending_class)
195
+ k.send(:include, including_module)
196
+ k
197
+ end
198
+
199
+ %i[just_addition all_properties_parameter bare_minimum].each do |name|
200
+ it "has accessor #{name} inherited from parent" do
201
+ expect(mixing_class.method_defined?(name)).to be == true
202
+ end
203
+
204
+ it "has parameter #{name} inherited from parent" do
205
+ expect(mixing_class.get_parameter(name).name).to be == name
206
+ end
207
+ end
208
+
209
+ it 'has accessor mixed_parameter derived from mixin' do
210
+ expect(mixing_class.method_defined?(:mixed_parameter)).to be == true
211
+ end
212
+
213
+ it 'has parameter mixed_parameter derived from mixin' do
214
+ expect(mixing_class.get_parameter(:mixed_parameter).name)
215
+ .to be == :mixed_parameter
216
+ end
217
+ end
218
+ end
219
+
220
+ it 'fails when trying to add existing parameter' do
221
+ expect do
222
+ Class.new(parametrized_class) do
223
+ parameter :bare_minimum, description: 'Something existing'
224
+ end
225
+ end.to raise_error Aws::Templates::ParameterAlreadyExist
226
+ end
227
+
228
+ context 'method is defined' do
229
+ let(:failing_class) do
230
+ Class.new(parametrized_class) do
231
+ def a; end
232
+ end
233
+ end
234
+
235
+ it 'fails when adding a parameter with the same name as a method' do
236
+ expect { failing_class.parameter(:a, description: 'Unexpected') }
237
+ .to raise_error Aws::Templates::ParameterMethodNameConflict
238
+ end
239
+ end
240
+ end
241
+ end
@@ -0,0 +1,6 @@
1
+ require 'simplecov'
2
+
3
+ RSpec.configure do |config|
4
+ config.run_all_when_everything_filtered = true
5
+ config.filter_run :focus
6
+ end