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,131 @@
1
+ require 'aws/templates/render'
2
+ require 'aws/templates/render/view'
3
+ require 'aws/templates/utils'
4
+ require 'aws/templates/utils/dependency'
5
+ require 'aws/templates/utils/options'
6
+
7
+ module Aws
8
+ module Templates
9
+ module Render
10
+ module Utils
11
+ ##
12
+ # Utility views
13
+ #
14
+ # A collection of handful utility views which know how to flexibly render values into
15
+ # specific types.
16
+ module BaseTypeViews
17
+ include Render
18
+
19
+ ##
20
+ # Pass-through render
21
+ class AsIs < BasicView
22
+ def to_rendered
23
+ instance.object
24
+ end
25
+ end
26
+
27
+ ##
28
+ # Convert to string
29
+ class ToString < BasicView
30
+ def to_rendered
31
+ instance.to_s
32
+ end
33
+ end
34
+
35
+ ##
36
+ # Convert to array
37
+ #
38
+ # Converts value to array and iteratively renders every element in it.
39
+ class ToArray < BasicView
40
+ def to_rendered
41
+ instance
42
+ .to_a
43
+ .map { |element| render.view_for(element, parameters).to_rendered }
44
+ end
45
+ end
46
+
47
+ ##
48
+ # Convert to hash
49
+ #
50
+ # Converts value to hash and iteratively renders each key and value in it.
51
+ class ToHash < BasicView
52
+ def to_rendered
53
+ _from(instance).map { |k, v| [_to_rendered(k), _to_rendered(v)] }.to_h
54
+ end
55
+
56
+ private
57
+
58
+ def _from(obj)
59
+ if obj.respond_to?(:to_h)
60
+ instance.to_h
61
+ else
62
+ instance.to_hash
63
+ end
64
+ end
65
+
66
+ def _to_rendered(obj)
67
+ render.view_for(obj, parameters).to_rendered
68
+ end
69
+ end
70
+
71
+ ##
72
+ # Convert to float
73
+ class ToFloat < BasicView
74
+ def to_rendered
75
+ instance.to_f
76
+ end
77
+ end
78
+
79
+ ##
80
+ # Convert to integer
81
+ class ToInteger < BasicView
82
+ def to_rendered
83
+ instance.to_i
84
+ end
85
+ end
86
+
87
+ ##
88
+ # Convert to boolean
89
+ class ToBoolean < BasicView
90
+ def to_rendered
91
+ !instance.to_s.casecmp('false').zero?
92
+ end
93
+ end
94
+
95
+ DEFAULT_RENDERING_MAP = {
96
+ ::String => AsIs,
97
+ ::Float => AsIs,
98
+ ::Integer => AsIs,
99
+ ::TrueClass => AsIs,
100
+ ::FalseClass => AsIs,
101
+ ::NilClass => AsIs,
102
+ ::Symbol => AsIs,
103
+ Templates::Utils::Dependency => AsIs,
104
+ ::Array => ToArray,
105
+ ::Hash => ToHash,
106
+ Templates::Utils::Options => ToHash
107
+ }.freeze
108
+
109
+ ##
110
+ # Set all default views
111
+ #
112
+ # Set all default views for defined types. Views module class definitions are used
113
+ def initialize_base_type_views
114
+ DEFAULT_RENDERING_MAP.each_pair { |klass, view| define_view(klass, view) }
115
+ end
116
+
117
+ ##
118
+ # Set default views for specific classes
119
+ #
120
+ # Set default views only for passed types.
121
+ def initialize_base_type_views_for(*classes)
122
+ classes.each do |k|
123
+ raise "Can't find default view for class #{k}" unless DEFAULT_RENDERING_MAP.key?(k)
124
+ define_view(k, DEFAULT_RENDERING_MAP[k])
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,127 @@
1
+ module Aws
2
+ module Templates
3
+ module Render
4
+ ##
5
+ # Basic render view
6
+ #
7
+ # Views are classes encapsulating functionality of transforming
8
+ # artifacts into domain-specific output. For instance, the same
9
+ # LDAP record can be transformed into JSON description or LDIF definition.
10
+ # Views can be attached to ancestors of an artifact and it expected
11
+ # that the library will look-up the closest ancestor having view attached
12
+ # if the render is invoked on a child.
13
+ #
14
+ # Each view is attached to a registry object which stores correspondence
15
+ # between artifact classes and their views, and optionally to an artifact.
16
+ # A view is registered in a registry only when it is attached to an artifact.
17
+ # Views depend on artifacts but artifacts are not aware of views.
18
+ # As the extreme case, a sole view can be attached to Artifact
19
+ # if you have universal way to render your domain objects.
20
+ #
21
+ # Views are regular Ruby classes and all assumptions made about
22
+ # polymorphism, inheritance and incapsulation are true for them.
23
+ #
24
+ # View class itself is an abstract class which can't be instantiated
25
+ # directly.
26
+ class BasicView
27
+ ##
28
+ # Render accessor
29
+ #
30
+ # Returns either render of this view class or render of any ancestor.
31
+ def self.render
32
+ @render || superclass.render
33
+ end
34
+
35
+ ##
36
+ # Register the view class in a render
37
+ #
38
+ # Registers the view class in the render
39
+ # * +r+ - render registrar
40
+ def self.register_in(r)
41
+ @render = r
42
+ self
43
+ end
44
+
45
+ ##
46
+ # Link the view class to the artifact class
47
+ #
48
+ # Registers the link in the render object of the view class.
49
+ def self.artifact(artifact_class)
50
+ render.register(artifact_class, self)
51
+ self
52
+ end
53
+
54
+ ##
55
+ # Artifact instance view object is attached to
56
+ attr_reader :instance
57
+
58
+ ##
59
+ # Assigned view parameters
60
+ attr_reader :parameters
61
+
62
+ ##
63
+ # Execute in the instance context
64
+ #
65
+ # Executed passed block in the context of the instance being rendered. It helps against
66
+ # putting too much instance method accesses in long blocks. Returns the value returned by
67
+ # the block.
68
+ def in_instance(*args, &blk)
69
+ instance.instance_exec(*args, &blk)
70
+ end
71
+
72
+ ##
73
+ # Create view instance and link it to the artifact instance
74
+ def initialize(obj, params = nil)
75
+ @instance = obj
76
+ @parameters = params
77
+ end
78
+
79
+ ##
80
+ # Alias for class method render
81
+ def render
82
+ self.class.render
83
+ end
84
+
85
+ ##
86
+ # Render the object
87
+ #
88
+ # Renders passed object with the view default render
89
+ def rendered_for(obj)
90
+ render.view_for(obj, parameters).to_rendered
91
+ end
92
+
93
+ ##
94
+ # Render the instance of the artifact
95
+ #
96
+ # The method should be overriden and return rendered form of the attached instance
97
+ def to_rendered
98
+ raise NotImplementedError.new('The method should be overriden')
99
+ end
100
+ end
101
+
102
+ ##
103
+ # Render view
104
+ #
105
+ # The class introduces additional stage called "prepare" where you can put prepared view
106
+ # which will be additionally recursively rendered. Useful for complex views containing values
107
+ # needed additional rendering so you don't need to invoke rendered_for.
108
+ class View < BasicView
109
+ ##
110
+ # Render the instance of the artifact
111
+ #
112
+ # The method renders value returned by prepare
113
+ def to_rendered
114
+ rendered_for(prepare)
115
+ end
116
+
117
+ ##
118
+ # Prepare value for rendering
119
+ #
120
+ # Should be overriden. Should return a value which is to be passed for final rendering.
121
+ def prepare
122
+ raise NotImplementedError.new('The method should be overriden')
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,72 @@
1
+ require 'aws/templates/exceptions'
2
+ require 'aws/templates/render/registry'
3
+ require 'aws/templates/render/view'
4
+
5
+ module Aws
6
+ module Templates
7
+ ##
8
+ # View layer of the MVC pattern
9
+ #
10
+ # View layer provides means of defining "views" of your artifacts
11
+ # to define different ways of rendering the object hierarchies you
12
+ # create to end representation.
13
+ #
14
+ # The module also contains a few mixin methods to simplify creation
15
+ # of "renders" - collections of views defining the same domain
16
+ # representation. For instance JSON, LDIF, Wiki could be such
17
+ # final destinations.
18
+ #
19
+ # Renders could be classes or modules. Modules work best if no
20
+ # customization is needed and you want a singleton.
21
+ #
22
+ # === Example
23
+ #
24
+ # class Wiki
25
+ # include Aws::Templates::Render
26
+ # end
27
+ #
28
+ # module JSON
29
+ # extend Aws::Templates::Render
30
+ # end
31
+ module Render
32
+ ##
33
+ # Registry accessor
34
+ #
35
+ # All views and corresponding artifacts in a render are stored
36
+ # in a registry.
37
+ def registry
38
+ @registry ||= Registry.new
39
+ end
40
+
41
+ ##
42
+ # Proxy for Registry register method
43
+ def register(*args)
44
+ registry.register(*args)
45
+ end
46
+
47
+ ##
48
+ # Proxy for Registry can_render? method
49
+ def can_render?(*args)
50
+ registry.can_render?(*args)
51
+ end
52
+
53
+ ##
54
+ # Proxy for Registry view_for method
55
+ def view_for(*args)
56
+ registry.view_for(*args)
57
+ end
58
+
59
+ ##
60
+ # Define view for artifact
61
+ #
62
+ # Another way to define views for artifacts. Creates anonymous class and attaches as the view
63
+ # to the specified artifact
64
+ def define_view(artifact_class, view = nil, &blk)
65
+ Class
66
+ .new(view || Aws::Templates::Render::BasicView, &blk)
67
+ .register_in(self)
68
+ .artifact(artifact_class)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,141 @@
1
+ require 'aws/templates/artifact'
2
+ require 'set'
3
+
4
+ module Aws
5
+ module Templates
6
+ module Utils
7
+ ##
8
+ # Arifact storage
9
+ #
10
+ # It mimics behavior of Hash providing additional ability to search
11
+ # through elements checking for different types of matches:
12
+ # * labels
13
+ # * classes
14
+ # * parameters
15
+ # It is also able to perform recursive deep search and de-duplication of artifact objects
16
+ class ArtifactStorage < Hash
17
+ include Enumerable
18
+
19
+ ##
20
+ # Find artifacts by criteria
21
+ #
22
+ # The method allows flexible introspection of the artifacts
23
+ # enclosed into the storage.
24
+ #
25
+ # * +search_params+ - map of search parameters:
26
+ # ** +recursive+ - if true, search will be performed recusrsively
27
+ # in nested composites
28
+ # ** +label+ - search for artifacts which have the label
29
+ # ** +parameters+ - search for artifacts which have specified
30
+ # parameters values; it's a multi-level map so
31
+ # you can check for nested values also
32
+ def search(search_params = {})
33
+ found = filter_artifacts(search_params)
34
+
35
+ if search_params[:recursive]
36
+ values
37
+ .select { |object| object.respond_to?(:search) }
38
+ .each { |object| found.concat(object.search(search_params)) }
39
+ end
40
+
41
+ found
42
+ end
43
+
44
+ ##
45
+ # Artifacts list
46
+ def artifacts
47
+ @set.to_a
48
+ end
49
+
50
+ ##
51
+ # Artifacts' labels list
52
+ def labels
53
+ @map.keys
54
+ end
55
+
56
+ ##
57
+ # If the label is present
58
+ def label?(l)
59
+ @map.key?(l)
60
+ end
61
+
62
+ ##
63
+ # Extract object by label
64
+ def [](k)
65
+ @map[k]
66
+ end
67
+
68
+ ##
69
+ # Associate label to the object
70
+ def []=(k, v)
71
+ raise 'nil artifacts are not supported' if v.nil?
72
+ @set << v unless @set.include?(v)
73
+ @map[k] = v
74
+ end
75
+
76
+ alias values artifacts
77
+ alias keys labels
78
+ alias key? label?
79
+ alias include? label?
80
+
81
+ def each(&blk)
82
+ @map.each(&blk)
83
+ end
84
+
85
+ def each_pair(&blk)
86
+ @map.each_pair(&blk)
87
+ end
88
+
89
+ def map(&blk)
90
+ @map.map(&blk)
91
+ end
92
+
93
+ def select(&blk)
94
+ @map.select(&blk)
95
+ end
96
+
97
+ def reject(&blk)
98
+ @map.reject(&blk)
99
+ end
100
+
101
+ def initialize
102
+ @map = {}
103
+ @set = Set.new
104
+ end
105
+
106
+ private
107
+
108
+ def filter_artifacts(search_params)
109
+ found = filter_by_label(search_params[:label])
110
+
111
+ klass = search_params[:klass]
112
+ params_match = search_params[:parameters]
113
+
114
+ found = found.select { |object| object.is_a?(klass) } if klass
115
+ found = found.select { |object| check_parameters(object, params_match) } if params_match
116
+
117
+ found
118
+ end
119
+
120
+ def filter_by_label(label)
121
+ return values if label.nil?
122
+ return [] unless key?(label)
123
+
124
+ [self[label]]
125
+ end
126
+
127
+ def check_parameters(object, params)
128
+ params.all? do |name, value|
129
+ if object.respond_to?(name)
130
+ if value.respond_to?(:to_hash)
131
+ check_parameters(object.send(name), value.to_hash)
132
+ else
133
+ object.send(name) == value
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end