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