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.
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,115 @@
1
+ require 'spec_helper'
2
+ require 'aws/templates/utils/contextualized'
3
+ require 'aws/templates/utils/options'
4
+
5
+ describe Aws::Templates::Utils::Contextualized do
6
+ let(:including_class) do
7
+ Class.new do
8
+ include Aws::Templates::Utils::Contextualized
9
+
10
+ contextualize ->(opts, _) { opts.dup }
11
+ end
12
+ end
13
+
14
+ let(:including_module) do
15
+ Module.new do
16
+ include Aws::Templates::Utils::Contextualized
17
+
18
+ contextualize lambda { |_, memo|
19
+ memo.delete(:z)
20
+ memo
21
+ }
22
+ end
23
+ end
24
+
25
+ describe 'module include' do
26
+ it 'has filter DSL method' do
27
+ expect(including_module).to respond_to(:contextualize)
28
+ end
29
+ end
30
+
31
+ describe 'class include' do
32
+ it 'has parameter DSL method' do
33
+ expect(including_class).to respond_to(:contextualize)
34
+ end
35
+ end
36
+
37
+ context 'Class is inherited and the module is included' do
38
+ let(:parametrized_class) do
39
+ klass = Class.new(including_class)
40
+ klass.send(:include, including_module)
41
+ klass
42
+ end
43
+
44
+ let(:instance) { parametrized_class.new }
45
+
46
+ let(:options) { Aws::Templates::Utils::Options.new(a: 5, z: 10) }
47
+
48
+ it 'returns properly filtered options' do
49
+ expect(options.filter(&instance.context).to_hash).to be == { a: 5 }
50
+ end
51
+ end
52
+
53
+ context 'Class is inherited and extended with filters' do
54
+ let(:parametrized_class) do
55
+ Class.new(including_class) do
56
+ contextualize lambda { |_, memo|
57
+ memo.delete(:r)
58
+ memo
59
+ }
60
+
61
+ contextualize lambda { |_, memo|
62
+ memo[:x] = memo[:a] + 1
63
+ memo
64
+ }
65
+ end
66
+ end
67
+
68
+ let(:options) { Aws::Templates::Utils::Options.new(a: 3, r: 5, z: 7) }
69
+
70
+ describe 'DSL' do
71
+ it 'has filter DSL method' do
72
+ expect(parametrized_class).to respond_to(:contextualize)
73
+ end
74
+ end
75
+
76
+ context 'Instance of the class created' do
77
+ let(:instance) { parametrized_class.new }
78
+
79
+ it 'filters it according to specified parameters' do
80
+ expect(options.filter(&instance.context).to_hash).to be == { a: 3, z: 7, x: 4 }
81
+ end
82
+ end
83
+
84
+ context 'Class is inherited and a filter added' do
85
+ let(:extending_class) do
86
+ Class.new(parametrized_class) do
87
+ contextualize lambda { |_, memo|
88
+ memo[:w] = memo[:z] + memo[:x]
89
+ memo
90
+ }
91
+ end
92
+ end
93
+
94
+ let(:instance) { extending_class.new }
95
+
96
+ it 'filters it according to specified parameters' do
97
+ expect(options.filter(&instance.context).to_hash).to be == { a: 3, z: 7, x: 4, w: 11 }
98
+ end
99
+
100
+ context 'Class inherited and a filtered mixin added' do
101
+ let(:mixing_class) do
102
+ k = Class.new(extending_class)
103
+ k.send(:include, including_module)
104
+ k
105
+ end
106
+
107
+ let(:instance) { mixing_class.new }
108
+
109
+ it 'filters it according to specified parameters' do
110
+ expect(options.filter(&instance.context).to_hash).to be == { a: 3, x: 4, w: 11 }
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+ require 'aws/templates/utils/late_bound'
3
+
4
+ describe Aws::Templates::Utils::LateBound do
5
+ let(:including_class) do
6
+ Class.new do
7
+ include Aws::Templates::Utils::LateBound
8
+ end
9
+ end
10
+
11
+ let(:instance) { including_class.new }
12
+
13
+ describe 'DSL' do
14
+ it 'has parameter DSL class-level method' do
15
+ expect(including_class).to respond_to(:reference)
16
+ end
17
+
18
+ it 'has parameter DSL instance-level method' do
19
+ expect(including_class.new).to respond_to(:reference)
20
+ end
21
+ end
22
+
23
+ describe 'behavior' do
24
+ context 'class' do
25
+ let(:reference) { including_class.reference(%i[a b c], explosive: true) }
26
+
27
+ let(:evaluated) { instance.instance_exec(&reference) }
28
+
29
+ it 'creates proc for reference' do
30
+ expect(reference).to be_a Proc
31
+ end
32
+
33
+ it 'is evaluated into normal reference' do
34
+ expect(evaluated).to be_a Aws::Templates::Utils::LateBound::Reference
35
+ end
36
+
37
+ it 'contains assigned attributes' do
38
+ expect([evaluated.path, evaluated.arguments, evaluated.instance])
39
+ .to be == [%i[a b c], [{ explosive: true }], instance]
40
+ end
41
+ end
42
+
43
+ context 'instance' do
44
+ let(:reference) { instance.reference(%i[a b c], explosive: true) }
45
+
46
+ it 'is evaluated into normal reference' do
47
+ expect([reference.path, reference.arguments, reference.instance])
48
+ .to be == [%i[a b c], [{ explosive: true }], instance]
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+ require 'aws/templates/utils/options'
3
+
4
+ describe Aws::Templates::Utils::Options do
5
+ let(:options) do
6
+ described_class.new(
7
+ a: 1,
8
+ b: { c: 2 },
9
+ d: { c: { z: 3 } },
10
+ :* => { c: { :* => 5 } }
11
+ )
12
+ end
13
+
14
+ describe 'merge' do
15
+ let(:merged_options) do
16
+ options.merge(a: 12, b: { w: 30 }, d: { c: { z: 34 } })
17
+ end
18
+
19
+ let(:result) do
20
+ {
21
+ a: 12,
22
+ b: { c: 2, w: 30 },
23
+ d: { c: { z: 34 } },
24
+ :* => { c: { :* => 5 } }
25
+ }
26
+ end
27
+
28
+ it 'has correct class' do
29
+ expect(merged_options).to be_a_kind_of(described_class)
30
+ end
31
+
32
+ it 'merges according to the algorithm' do
33
+ expect(merged_options.to_hash).to be == result
34
+ end
35
+ end
36
+
37
+ describe 'lookup' do
38
+ it 'returns value when simple path is specified' do
39
+ expect(options[:b, :c]).to be == 2
40
+ end
41
+
42
+ it 'return nil when value is not found' do
43
+ expect(options[:b, :d, :z]).to be_nil
44
+ end
45
+
46
+ it 'wildcard lookup works' do
47
+ expect(options[:q, :c, :e]).to be == 5
48
+ end
49
+ end
50
+
51
+ describe 'assignment' do
52
+ it 'existing path assignment works' do
53
+ options[:b, :c] = 3
54
+ expect(options[:b, :c]).to be == 3
55
+ end
56
+
57
+ it 'new path assignment works' do
58
+ options[:b, :z, :y, :d] = 10
59
+ expect(options[:b, :z, :y, :d]).to be == 10
60
+ end
61
+
62
+ it 'throws an exception when value is not hash' do
63
+ options[:b, :c, :y, :d] = 13
64
+ expect(options[:b, :c, :y, :d]).to be == 13
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,175 @@
1
+ require 'spec_helper'
2
+ require 'aws/templates/utils/parametrized'
3
+ require 'aws/templates/utils/parametrized/constraints'
4
+ require 'aws/templates/utils/parametrized/getters'
5
+
6
+ module Constraints
7
+ include Aws::Templates::Utils::Parametrized
8
+ end
9
+
10
+ describe Aws::Templates::Utils::Parametrized::Constraint do
11
+ let(:constraint) {}
12
+
13
+ let(:parametrized_class) do
14
+ Class.new do
15
+ include Aws::Templates::Utils::Parametrized
16
+
17
+ attr_reader :options
18
+
19
+ def self.getter
20
+ as_is
21
+ end
22
+
23
+ def initialize(options)
24
+ @options = options
25
+ end
26
+ end
27
+ end
28
+
29
+ let(:test_class) do
30
+ k = Class.new(parametrized_class)
31
+ k.parameter(:something, constraint: constraint)
32
+ k
33
+ end
34
+
35
+ describe 'not_nil' do
36
+ let(:constraint) { Constraints.not_nil }
37
+
38
+ it 'passes when non-nil value is specified' do
39
+ expect(test_class.new(something: 1).something).to be == 1
40
+ end
41
+
42
+ it 'throws error when parameter is not specified' do
43
+ expect { test_class.new(something_else: 1).something }
44
+ .to raise_error Aws::Templates::ParameterValueInvalid
45
+ end
46
+ end
47
+
48
+ describe 'enum works as expected' do
49
+ let(:constraint) { Constraints.enum(1, 2, 3) }
50
+
51
+ it 'passes when a value from the list is specifed' do
52
+ expect(test_class.new(something: 2).something).to be == 2
53
+ end
54
+
55
+ it 'passes when value is not specified' do
56
+ expect(test_class.new(something_else: 2).something).to be_nil
57
+ end
58
+
59
+ it 'throws an error when a value is specified which is not a member of the enumeration' do
60
+ expect { test_class.new(something: 5).something }
61
+ .to raise_error Aws::Templates::ParameterValueInvalid
62
+ end
63
+ end
64
+
65
+ describe 'all_of' do
66
+ let(:constraint) { Constraints.all_of(Constraints.not_nil, Constraints.enum(1, 2, 3)) }
67
+
68
+ it 'passes if all constraints are met' do
69
+ expect(test_class.new(something: 2).something).to be == 2
70
+ end
71
+
72
+ it 'throws an error if one of the constraints are failed (not_nil)' do
73
+ expect { test_class.new(something_else: 2).something }
74
+ .to raise_error Aws::Templates::ParameterValueInvalid
75
+ end
76
+
77
+ it 'throws an error if one of the constraints are failed (enum)' do
78
+ expect { test_class.new(something: 5).something }
79
+ .to raise_error Aws::Templates::ParameterValueInvalid
80
+ end
81
+ end
82
+
83
+ describe 'requires' do
84
+ let(:test_class) do
85
+ Class.new(parametrized_class) do
86
+ parameter :something, constraint: requires(:requirement)
87
+ parameter :requirement, description: 'Nothing'
88
+ end
89
+ end
90
+
91
+ it 'passes when requirement is satisfied' do
92
+ expect(test_class.new(something: 2, requirement: 1).something).to be == 2
93
+ end
94
+
95
+ it 'passes if value is nil so no requirements are enforced' do
96
+ expect(test_class.new({}).something).to be_nil
97
+ end
98
+
99
+ it 'throws an error when requirement is not satisfied' do
100
+ expect { test_class.new(something: 5).something }
101
+ .to raise_error Aws::Templates::ParameterValueInvalid
102
+ end
103
+ end
104
+
105
+ describe 'depends_on_value' do
106
+ let(:test_class) do
107
+ Class.new(parametrized_class) do
108
+ parameter :something,
109
+ constraint: depends_on_value(
110
+ requirement: requires(:requirement),
111
+ condition: requires(:condition)
112
+ )
113
+ parameter :requirement, description: 'Nothing'
114
+ parameter :condition, description: 'Nothing'
115
+ end
116
+ end
117
+
118
+ it 'passes when nil' do
119
+ expect(test_class.new({}).something).to be_nil
120
+ end
121
+
122
+ it 'passes when value is not one of the conditions' do
123
+ expect(test_class.new(something: 2).something).to be == 2
124
+ end
125
+
126
+ it 'passes when conditional constraint is met' do
127
+ expect(test_class.new(something: :condition, condition: 2).something)
128
+ .to be == :condition
129
+ end
130
+
131
+ it 'throws an error when conditional constraint is not met' do
132
+ expect { test_class.new(something: :condition, requirement: 2).something }
133
+ .to raise_error Aws::Templates::ParameterValueInvalid
134
+ end
135
+
136
+ it 'passes when other conditional constraint is met' do
137
+ expect(test_class.new(something: :requirement, requirement: 2).something)
138
+ .to be == :requirement
139
+ end
140
+ end
141
+
142
+ describe 'satisfies' do
143
+ let(:constraint) { Constraints.satisfies('some interesting case') { |v| v > 3 } }
144
+
145
+ it 'passes when nil' do
146
+ expect(test_class.new({}).something).to be_nil
147
+ end
148
+
149
+ it 'passes when condition is satisfied' do
150
+ expect(test_class.new(something: 4).something).to be == 4
151
+ end
152
+
153
+ it 'throws an error when condition is not satisfied' do
154
+ expect { test_class.new(something: 1).something }
155
+ .to raise_error Aws::Templates::ParameterValueInvalid
156
+ end
157
+ end
158
+
159
+ describe 'matches' do
160
+ let(:constraint) { Constraints.matches('[Tt]$') }
161
+
162
+ it 'passes when nil' do
163
+ expect(test_class.new({}).something).to be_nil
164
+ end
165
+
166
+ it 'passes when condition is satisfied' do
167
+ expect(test_class.new(something: 'rest').something).to be == 'rest'
168
+ end
169
+
170
+ it 'throws an error when condition is not satisfied' do
171
+ expect { test_class.new(something: 'rooster').something }
172
+ .to raise_error Aws::Templates::ParameterValueInvalid
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,139 @@
1
+ require 'spec_helper'
2
+ require 'aws/templates/utils/parametrized'
3
+ require 'aws/templates/utils/parametrized/getters'
4
+
5
+ module Getters
6
+ include Aws::Templates::Utils::Parametrized
7
+ end
8
+
9
+ describe Aws::Templates::Utils::Parametrized::Getter do
10
+ let(:parametrized_class) do
11
+ Class.new do
12
+ include Aws::Templates::Utils::Parametrized
13
+
14
+ attr_reader :options
15
+
16
+ def initialize(options)
17
+ @options = options
18
+ end
19
+ end
20
+ end
21
+
22
+ let(:options_hash) {}
23
+
24
+ let(:getter) {}
25
+
26
+ let(:test_class) do
27
+ k = Class.new(parametrized_class)
28
+ k.parameter(:something, getter: getter)
29
+ k
30
+ end
31
+
32
+ let(:instance) { test_class.new(options_hash) }
33
+
34
+ describe 'as_instance_variable' do
35
+ let(:parametrized_class) do
36
+ Class.new do
37
+ include Aws::Templates::Utils::Parametrized
38
+
39
+ def initialize(something)
40
+ @something = something
41
+ end
42
+ end
43
+ end
44
+
45
+ let(:options_hash) { 'a' }
46
+
47
+ let(:getter) { Getters.as_instance_variable }
48
+
49
+ it 'returns the value from hash by parameter name' do
50
+ expect(instance.something).to be == 'a'
51
+ end
52
+ end
53
+
54
+ describe 'as_is' do
55
+ let(:options_hash) { { something: 'a' } }
56
+
57
+ let(:getter) { Getters.as_is }
58
+
59
+ it 'returns the value from hash by parameter name' do
60
+ expect(instance.something).to be == 'a'
61
+ end
62
+ end
63
+
64
+ describe 'path' do
65
+ let(:options_hash) do
66
+ hash = { object: { something: 'a' } }
67
+
68
+ class << hash
69
+ def [](*path)
70
+ if path.size == 1
71
+ super(path[0])
72
+ else
73
+ path.inject(self) { |acc, elem| acc[elem] }
74
+ end
75
+ end
76
+ end
77
+
78
+ hash
79
+ end
80
+
81
+ context 'static path is specified' do
82
+ let(:getter) { Getters.path(:object, :something) }
83
+
84
+ it 'returns value correctly' do
85
+ expect(instance.something).to be == 'a'
86
+ end
87
+ end
88
+
89
+ context 'dynamic path is specified' do
90
+ let(:getter) { Getters.path { %i[object something] } }
91
+
92
+ it 'returns value correctly' do
93
+ expect(instance.something).to be == 'a'
94
+ end
95
+ end
96
+ end
97
+
98
+ describe 'value' do
99
+ let(:options_hash) { { something: 3 } }
100
+
101
+ context 'static value is specified' do
102
+ let(:getter) { Getters.value(1) }
103
+
104
+ it 'returns value correctly' do
105
+ expect(instance.something).to be == 1
106
+ end
107
+ end
108
+
109
+ context 'dynamic calculation is specified' do
110
+ let(:getter) { Getters.value { options[:something] + 2 } }
111
+
112
+ it 'returns value correctly' do
113
+ expect(instance.something).to be == 5
114
+ end
115
+ end
116
+ end
117
+
118
+ describe 'one_of' do
119
+ let(:getter) do
120
+ Getters.one_of(->(p) { options[p.name] }, ->(_) { options[:default] })
121
+ end
122
+
123
+ context 'first option value is specified' do
124
+ let(:options_hash) { { something: 'a' } }
125
+
126
+ it 'returns the value' do
127
+ expect(instance.something).to be == 'a'
128
+ end
129
+ end
130
+
131
+ context 'another options value is specified' do
132
+ let(:options_hash) { { default: 'a' } }
133
+
134
+ it 'returns the value' do
135
+ expect(instance.something).to be == 'a'
136
+ end
137
+ end
138
+ end
139
+ end