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,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