bosh_common 0.5.0 → 0.5.1
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.
- data/lib/common/properties/errors.rb +16 -0
- data/lib/common/properties/property_helper.rb +43 -0
- data/lib/common/properties/template_evaluation_context.rb +86 -0
- data/lib/common/properties.rb +6 -0
- data/lib/common/version.rb +1 -1
- data/spec/unit/properties/property_helper_spec.rb +39 -0
- data/spec/unit/properties/template_evaluation_context_spec.rb +74 -0
- metadata +12 -4
@@ -0,0 +1,16 @@
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
2
|
+
|
3
|
+
module Bosh::Common
|
4
|
+
|
5
|
+
class TemplateEvaluationFailed < StandardError; end
|
6
|
+
|
7
|
+
class UnknownProperty < StandardError
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
def initialize(name)
|
11
|
+
@name = name
|
12
|
+
super("Can't find property `#{name}'")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
2
|
+
|
3
|
+
module Bosh::Common
|
4
|
+
module PropertyHelper
|
5
|
+
# Copies property with a given name from src to dst.
|
6
|
+
# @param [Hash] dst Property destination
|
7
|
+
# @param [Hash] src Property source
|
8
|
+
# @param [String] name Property name (dot-separated)
|
9
|
+
# @param [Object] default Default value (if property is not in src)
|
10
|
+
def copy_property(dst, src, name, default = nil)
|
11
|
+
keys = name.split(".")
|
12
|
+
src_ref = src
|
13
|
+
dst_ref = dst
|
14
|
+
|
15
|
+
keys.each do |key|
|
16
|
+
src_ref = src_ref[key]
|
17
|
+
break if src_ref.nil? # no property with this name is src
|
18
|
+
end
|
19
|
+
|
20
|
+
keys[0..-2].each do |key|
|
21
|
+
dst_ref[key] ||= {}
|
22
|
+
dst_ref = dst_ref[key]
|
23
|
+
end
|
24
|
+
|
25
|
+
dst_ref[keys[-1]] ||= {}
|
26
|
+
dst_ref[keys[-1]] = src_ref || default
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param [Hash] collection Property collection
|
30
|
+
# @param [String] name Dot-separated property name
|
31
|
+
def lookup_property(collection, name)
|
32
|
+
keys = name.split(".")
|
33
|
+
ref = collection
|
34
|
+
|
35
|
+
keys.each do |key|
|
36
|
+
ref = ref[key]
|
37
|
+
return nil if ref.nil?
|
38
|
+
end
|
39
|
+
|
40
|
+
ref
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
2
|
+
|
3
|
+
module Bosh::Common
|
4
|
+
# Helper class to evaluate templates. Used by Director, CLI and Agent.
|
5
|
+
class TemplateEvaluationContext
|
6
|
+
include PropertyHelper
|
7
|
+
|
8
|
+
# @return [String] Template name
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
# @return [Integer] Template instance index
|
12
|
+
attr_reader :index
|
13
|
+
|
14
|
+
# @return [Hash] Template properties
|
15
|
+
attr_reader :properties
|
16
|
+
|
17
|
+
# @return [Hash] Template spec
|
18
|
+
attr_reader :spec
|
19
|
+
|
20
|
+
# @param [Hash] spec Template spec
|
21
|
+
def initialize(spec)
|
22
|
+
unless spec.is_a?(Hash)
|
23
|
+
raise TemplateEvaluationFailed,
|
24
|
+
"Invalid spec provided for template evaluation context, " +
|
25
|
+
"Hash expected, #{spec.class} given"
|
26
|
+
end
|
27
|
+
|
28
|
+
if spec["job"].is_a?(Hash)
|
29
|
+
@name = spec["job"]["name"]
|
30
|
+
else
|
31
|
+
@name = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
@index = spec["index"]
|
35
|
+
@spec = openstruct(spec)
|
36
|
+
@raw_properties = spec["properties"] || {}
|
37
|
+
@properties = openstruct(@raw_properties)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Binding] Template binding
|
41
|
+
def get_binding
|
42
|
+
binding.taint
|
43
|
+
end
|
44
|
+
|
45
|
+
# Property lookup helper
|
46
|
+
# @param [String] name Property name
|
47
|
+
# @param [optional, Object] default Default value
|
48
|
+
# @return [Object] Property value
|
49
|
+
def p(name, default = nil)
|
50
|
+
result = lookup_property(@raw_properties, name)
|
51
|
+
if result.nil?
|
52
|
+
return default if default
|
53
|
+
raise UnknownProperty.new(name)
|
54
|
+
end
|
55
|
+
result
|
56
|
+
end
|
57
|
+
|
58
|
+
# Run a block of code if all given properties are defined
|
59
|
+
# @param [Array<String>] names Property names
|
60
|
+
# @yield [Object] property values
|
61
|
+
def if_p(*names)
|
62
|
+
values = names.map do |name|
|
63
|
+
value = lookup_property(@raw_properties, name)
|
64
|
+
return if value.nil?
|
65
|
+
value
|
66
|
+
end
|
67
|
+
|
68
|
+
yield *values
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [Object] Object representation where all hashes are unrolled
|
72
|
+
# into OpenStruct objects. This exists mostly for backward
|
73
|
+
# compatibility, as it doesn't provide good error reporting.
|
74
|
+
def openstruct(object)
|
75
|
+
case object
|
76
|
+
when Hash
|
77
|
+
mapped = object.inject({}) { |h, (k,v)| h[k] = openstruct(v); h }
|
78
|
+
OpenStruct.new(mapped)
|
79
|
+
when Array
|
80
|
+
object.map { |item| openstruct(item) }
|
81
|
+
else
|
82
|
+
object
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/common/version.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Copyright (c) 2012 VMware, Inc.
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
require "common/properties"
|
5
|
+
|
6
|
+
describe Bosh::Common::PropertyHelper do
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@helper = Object.new
|
10
|
+
@helper.extend(Bosh::Common::PropertyHelper)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "can copy named property from one collection to another" do
|
14
|
+
dst = {}
|
15
|
+
src = {"foo" => {"bar" => "baz", "secret" => "zazzle"}}
|
16
|
+
|
17
|
+
@helper.copy_property(dst, src, "foo.bar")
|
18
|
+
dst.should == {"foo" => {"bar" => "baz"}}
|
19
|
+
|
20
|
+
@helper.copy_property(dst, src, "no.such.prop", "default")
|
21
|
+
dst.should == {
|
22
|
+
"foo" => {"bar" => "baz"},
|
23
|
+
"no" => {
|
24
|
+
"such" => {"prop" => "default"}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
it "can lookup the property in a Hash using dot-syntax" do
|
30
|
+
properties = {
|
31
|
+
"foo" => {"bar" => "baz"},
|
32
|
+
"router" => {"token" => "foo"}
|
33
|
+
}
|
34
|
+
|
35
|
+
@helper.lookup_property(properties, "foo.bar").should == "baz"
|
36
|
+
@helper.lookup_property(properties, "router").should == {"token" => "foo"}
|
37
|
+
@helper.lookup_property(properties, "no.prop").should be_nil
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# Copyright (c) 2012 VMware, Inc.
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
require "common/properties"
|
5
|
+
|
6
|
+
describe Bosh::Common::TemplateEvaluationContext do
|
7
|
+
|
8
|
+
def eval_template(erb, context)
|
9
|
+
ERB.new(erb).result(context.get_binding)
|
10
|
+
end
|
11
|
+
|
12
|
+
def make(spec)
|
13
|
+
Bosh::Common::TemplateEvaluationContext.new(spec)
|
14
|
+
end
|
15
|
+
|
16
|
+
before(:each) do
|
17
|
+
@spec = {
|
18
|
+
"job" => {
|
19
|
+
"name" => "foobar"
|
20
|
+
},
|
21
|
+
"properties" => {
|
22
|
+
"foo" => "bar",
|
23
|
+
"router" => {"token" => "zbb"}
|
24
|
+
},
|
25
|
+
"index" => 0,
|
26
|
+
}
|
27
|
+
|
28
|
+
@context = make(@spec)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "unrolls properties into OpenStruct" do
|
32
|
+
eval_template("<%= properties.foo %>", @context).should == "bar"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "supports looking up template index" do
|
36
|
+
eval_template("<%= spec.index %>", @context).should == "0"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "supports 'p' helper" do
|
40
|
+
eval_template("<%= p('router.token') %>", @context).should == "zbb"
|
41
|
+
expect {
|
42
|
+
eval_template("<%= p('bar.baz') %>", @context)
|
43
|
+
}.to raise_error(Bosh::Common::UnknownProperty)
|
44
|
+
|
45
|
+
eval_template("<%= p('bar.baz', 22) %>", @context).should == "22"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "supports 'if_p' helper" do
|
49
|
+
template = <<-TMPL
|
50
|
+
<% if_p("router.token") do |token| %>
|
51
|
+
<%= token %>
|
52
|
+
<% end %>
|
53
|
+
TMPL
|
54
|
+
|
55
|
+
eval_template(template, @context).strip.should == "zbb"
|
56
|
+
|
57
|
+
template = <<-TMPL
|
58
|
+
<% if_p("router.token", "foo") do |token, foo| %>
|
59
|
+
<%= token %>, <%= foo %>
|
60
|
+
<% end %>
|
61
|
+
TMPL
|
62
|
+
|
63
|
+
eval_template(template, @context).strip.should == "zbb, bar"
|
64
|
+
|
65
|
+
template = <<-TMPL
|
66
|
+
<% if_p("router.token", "no.such.prop") do |token, none| %>
|
67
|
+
test output
|
68
|
+
<% end %>
|
69
|
+
TMPL
|
70
|
+
|
71
|
+
eval_template(template, @context).strip.should == ""
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bosh_common
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-10-05 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: BOSH common
|
15
15
|
email: support@vmware.com
|
@@ -21,6 +21,10 @@ files:
|
|
21
21
|
- lib/common/exec.rb
|
22
22
|
- lib/common/exec/error.rb
|
23
23
|
- lib/common/exec/result.rb
|
24
|
+
- lib/common/properties.rb
|
25
|
+
- lib/common/properties/errors.rb
|
26
|
+
- lib/common/properties/property_helper.rb
|
27
|
+
- lib/common/properties/template_evaluation_context.rb
|
24
28
|
- lib/common/thread_formatter.rb
|
25
29
|
- lib/common/thread_pool.rb
|
26
30
|
- lib/common/version.rb
|
@@ -31,6 +35,8 @@ files:
|
|
31
35
|
- spec/spec_helper.rb
|
32
36
|
- spec/unit/common_spec.rb
|
33
37
|
- spec/unit/exec_spec.rb
|
38
|
+
- spec/unit/properties/property_helper_spec.rb
|
39
|
+
- spec/unit/properties/template_evaluation_context_spec.rb
|
34
40
|
- spec/unit/thread_pool_spec.rb
|
35
41
|
homepage: http://www.vmware.com
|
36
42
|
licenses: []
|
@@ -46,7 +52,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
46
52
|
version: '0'
|
47
53
|
segments:
|
48
54
|
- 0
|
49
|
-
hash:
|
55
|
+
hash: -411355085407901587
|
50
56
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
57
|
none: false
|
52
58
|
requirements:
|
@@ -55,7 +61,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
55
61
|
version: '0'
|
56
62
|
segments:
|
57
63
|
- 0
|
58
|
-
hash:
|
64
|
+
hash: -411355085407901587
|
59
65
|
requirements: []
|
60
66
|
rubyforge_project:
|
61
67
|
rubygems_version: 1.8.24
|
@@ -68,5 +74,7 @@ test_files:
|
|
68
74
|
- spec/spec_helper.rb
|
69
75
|
- spec/unit/common_spec.rb
|
70
76
|
- spec/unit/exec_spec.rb
|
77
|
+
- spec/unit/properties/property_helper_spec.rb
|
78
|
+
- spec/unit/properties/template_evaluation_context_spec.rb
|
71
79
|
- spec/unit/thread_pool_spec.rb
|
72
80
|
has_rdoc:
|