poise-derived 0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +11 -0
- data/.kitchen.yml +3 -0
- data/.travis.yml +40 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +32 -0
- data/LICENSE +201 -0
- data/README.md +110 -0
- data/Rakefile +17 -0
- data/chef/recipes/default.rb +17 -0
- data/lib/poise_derived.rb +22 -0
- data/lib/poise_derived/cheftie.rb +18 -0
- data/lib/poise_derived/core_ext.rb +28 -0
- data/lib/poise_derived/core_ext/deep_merge.rb +55 -0
- data/lib/poise_derived/core_ext/string.rb +35 -0
- data/lib/poise_derived/dsl.rb +45 -0
- data/lib/poise_derived/handler.rb +43 -0
- data/lib/poise_derived/lazy_attribute.rb +125 -0
- data/lib/poise_derived/version.rb +20 -0
- data/poise-derived.gemspec +41 -0
- data/test/cookbook/attributes/default.rb +46 -0
- data/test/cookbook/metadata.rb +18 -0
- data/test/cookbook/recipes/default.rb +28 -0
- data/test/gemfiles/chef-12.10.gemfile +20 -0
- data/test/gemfiles/chef-12.11.gemfile +20 -0
- data/test/gemfiles/chef-12.12.gemfile +19 -0
- data/test/gemfiles/chef-12.13.gemfile +19 -0
- data/test/gemfiles/chef-12.14.gemfile +19 -0
- data/test/gemfiles/chef-12.3.gemfile +20 -0
- data/test/gemfiles/chef-12.4.gemfile +21 -0
- data/test/gemfiles/chef-12.5.gemfile +20 -0
- data/test/gemfiles/chef-12.6.gemfile +20 -0
- data/test/gemfiles/chef-12.7.gemfile +20 -0
- data/test/gemfiles/chef-12.8.gemfile +20 -0
- data/test/gemfiles/chef-12.9.gemfile +20 -0
- data/test/gemfiles/chef-12.gemfile +19 -0
- data/test/gemfiles/master.gemfile +21 -0
- data/test/integration/default/serverspec/default_spec.rb +35 -0
- data/test/spec/lazy_attribute_spec.rb +158 -0
- data/test/spec/spec_helper.rb +21 -0
- metadata +123 -8
@@ -0,0 +1,22 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
|
18
|
+
module PoiseDerived
|
19
|
+
autoload :DSL, 'poise_derived/dsl'
|
20
|
+
autoload :LazyAttribute, 'poise_derived/lazy_attribute'
|
21
|
+
autoload :VERSION, 'poise_derived/version'
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'poise_derived/core_ext'
|
18
|
+
require 'poise_derived/handler'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'poise_derived/core_ext/deep_merge'
|
18
|
+
require 'poise_derived/core_ext/string'
|
19
|
+
|
20
|
+
|
21
|
+
module PoiseDerived
|
22
|
+
# Here be dragons.
|
23
|
+
#
|
24
|
+
# @since 1.0.0
|
25
|
+
# @api private
|
26
|
+
module CoreExt
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'chef/mixin/deep_merge'
|
18
|
+
|
19
|
+
require 'poise_derived/lazy_attribute'
|
20
|
+
|
21
|
+
|
22
|
+
module PoiseDerived
|
23
|
+
module CoreExt
|
24
|
+
# Monkey-patch deep merge to carry over LazyAttribute on override. This means
|
25
|
+
# that if a lazy is set in a cookbook and then that attribute is overridden
|
26
|
+
# in a role or another cookbook, the override value gets wrapped in a
|
27
|
+
# LazyAttribute too so it will act as a template string. There is no way to
|
28
|
+
# put a block in JSON data so that would have to be explicit.
|
29
|
+
#
|
30
|
+
# @since 1.0.0
|
31
|
+
# @api private
|
32
|
+
module DeepMerge
|
33
|
+
def deep_merge!(source, dest)
|
34
|
+
if source.is_a?(PoiseDerived::LazyAttribute) && dest.is_a?(String)
|
35
|
+
source._override(dest)
|
36
|
+
else
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def hash_only_merge!(merge_onto, merge_with)
|
42
|
+
if merge_onto.is_a?(PoiseDerived::LazyAttribute) && merge_with.is_a?(String)
|
43
|
+
merge_onto._override(merge_with)
|
44
|
+
else
|
45
|
+
super
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Kinder, gentler monkey patching. The singleton_class is the important
|
50
|
+
# one since everything in Chef calls these are module methods.
|
51
|
+
Chef::Mixin::DeepMerge.prepend(self)
|
52
|
+
Chef::Mixin::DeepMerge.singleton_class.prepend(self)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'poise_derived/lazy_attribute'
|
18
|
+
|
19
|
+
|
20
|
+
# Monkeypatch String so that our magic works in case statements. If you're
|
21
|
+
# reading this, something has probably gone wrong. I'm so sorry.
|
22
|
+
#
|
23
|
+
# @since 1.0.0
|
24
|
+
# @api private
|
25
|
+
class String
|
26
|
+
old_method = method(:===)
|
27
|
+
define_singleton_method(:===) do |obj|
|
28
|
+
if obj.class <= ::PoiseDerived::LazyAttribute
|
29
|
+
true
|
30
|
+
else
|
31
|
+
old_method.call(obj)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'chef/node'
|
18
|
+
|
19
|
+
require 'poise_derived/lazy_attribute'
|
20
|
+
|
21
|
+
|
22
|
+
module PoiseDerived
|
23
|
+
module DSL
|
24
|
+
def _lazy_attribute(str=nil, &block)
|
25
|
+
PoiseDerived::LazyAttribute.new(self, str, &block)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Install the DSL addition globally.
|
29
|
+
#
|
30
|
+
# @return [void]
|
31
|
+
def self.install
|
32
|
+
Chef::Log.debug('[poise-derived] Installing node DSL')
|
33
|
+
Chef::Node.prepend(self)
|
34
|
+
alias_method(:lazy, :_lazy_attribute)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Disable the DSL extension so `node.lazy` will no longer work.
|
38
|
+
#
|
39
|
+
# @return [void]
|
40
|
+
def self.uninstall
|
41
|
+
Chef::Log.debug('[poise-derived] Uninstalling node DSL')
|
42
|
+
remove_method(:lazy)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'chef/chef_class'
|
18
|
+
require 'chef/event_dispatch/base'
|
19
|
+
|
20
|
+
require 'poise_derived/dsl'
|
21
|
+
|
22
|
+
|
23
|
+
module PoiseDerived
|
24
|
+
# A small event handler to install and uninstall our DSL addition so it only
|
25
|
+
# appears during attribute compilation. Is this a good idea?
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
class Handler < Chef::EventDispatch::Base
|
29
|
+
include Singleton
|
30
|
+
|
31
|
+
def attribute_load_start(count)
|
32
|
+
PoiseDerived::DSL.install
|
33
|
+
end
|
34
|
+
|
35
|
+
def attribute_load_complete
|
36
|
+
PoiseDerived::DSL.uninstall
|
37
|
+
end
|
38
|
+
|
39
|
+
# Install event handler.
|
40
|
+
Chef::Log.debug('[poise-derived] Installing event handler')
|
41
|
+
Chef.run_context.events.register(self.instance)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
|
18
|
+
module PoiseDerived
|
19
|
+
# A class to lazily evaluate node attributes either from format strings or
|
20
|
+
# code blocks.
|
21
|
+
#
|
22
|
+
# @example Cookbook attributes file
|
23
|
+
# default['mycookbook']['version'] = '1.0'
|
24
|
+
# default['mycookbook']['url'] = lazy 'https://example.com/myapp-%{mycookbook.version}.zip'
|
25
|
+
class LazyAttribute
|
26
|
+
# Parser regexp for format strings.
|
27
|
+
# @api private
|
28
|
+
FORMAT_STRING_REGEXP = /%\{([^}]+)\}/
|
29
|
+
|
30
|
+
def initialize(node, str=nil, &block)
|
31
|
+
unless (!!str) ^ (!!block)
|
32
|
+
raise ArgumentError.new('Either a string or block must be passed when creating a lazy attribute')
|
33
|
+
end
|
34
|
+
@node = node
|
35
|
+
@value = str || block
|
36
|
+
end
|
37
|
+
|
38
|
+
# Shorter inspect output for debugging so we don't vomit the node into the
|
39
|
+
# log or spec output.
|
40
|
+
#
|
41
|
+
# @return [String]
|
42
|
+
def inspect
|
43
|
+
if @value.is_a?(Proc)
|
44
|
+
"#<#{self.class.name} @value=proc>"
|
45
|
+
else
|
46
|
+
"#<#{self.class.name} @value=#{@value.inspect}>"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Return a copy of this attribute with the same node context but an
|
51
|
+
# override value as the format string. This can't support blocks because of
|
52
|
+
# how it is called generally.
|
53
|
+
#
|
54
|
+
# @api private
|
55
|
+
# @see PoiseDerived::CoreExt
|
56
|
+
# @return [PoiseDerived::LazyAttribute]
|
57
|
+
def _override(str)
|
58
|
+
self.class.new(@node, str)
|
59
|
+
end
|
60
|
+
|
61
|
+
# @!group delegators
|
62
|
+
# Delegate to the lazy value.
|
63
|
+
# @api private
|
64
|
+
def method_missing(method, *args, &block)
|
65
|
+
_evaluate.send(method, *args, &block)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Delegate to the lazy value.
|
69
|
+
# @api private
|
70
|
+
def respond_to_missing?(method, include_all)
|
71
|
+
_evaluate.respond_to?(method, include_all)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Delegate to the lazy value.
|
75
|
+
# @api private
|
76
|
+
def to_s
|
77
|
+
_evaluate.to_s
|
78
|
+
end
|
79
|
+
|
80
|
+
# Make sure we implement to_str because that activates the == hack.
|
81
|
+
# @api private
|
82
|
+
def to_str
|
83
|
+
to_s
|
84
|
+
end
|
85
|
+
|
86
|
+
# Fake is_a? and kind_of? for params_validate and `_pv_kind_of`.
|
87
|
+
# @api private
|
88
|
+
def is_a?(klass)
|
89
|
+
return true if Object.instance_method(:is_a?).bind(self).call(klass)
|
90
|
+
klass <= String
|
91
|
+
end
|
92
|
+
|
93
|
+
# @api private
|
94
|
+
# @see is_a?
|
95
|
+
alias_method :kind_of?, :is_a?
|
96
|
+
|
97
|
+
# Specifically delegate == because not caught by method_missing.
|
98
|
+
# @api private
|
99
|
+
def ==(other)
|
100
|
+
_evaluate == other
|
101
|
+
end
|
102
|
+
# !@endgroup
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
# Evaluate the lazy attribute.
|
107
|
+
#
|
108
|
+
# @return [Object]
|
109
|
+
def _evaluate
|
110
|
+
return @evaluate_cache if defined?(@evaluate_cache)
|
111
|
+
@evaluate_cache = if @value.is_a?(Proc)
|
112
|
+
# Block mode, just run the block.
|
113
|
+
@node.instance_eval(&@value).to_s
|
114
|
+
else
|
115
|
+
# String mode, parse the template string and fill it in.
|
116
|
+
format_keys = @value.scan(FORMAT_STRING_REGEXP).inject({}) do |memo, (key)|
|
117
|
+
# Keys must be symbols because Ruby.
|
118
|
+
memo[key.to_sym] = key.split(/\./).inject(@node) {|n, k| n.nil? ? n : n[k] }
|
119
|
+
memo
|
120
|
+
end
|
121
|
+
@value % format_keys
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
|
18
|
+
module PoiseDerived
|
19
|
+
VERSION = '1.0.0'
|
20
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
lib = File.expand_path('../lib', __FILE__)
|
18
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
19
|
+
require 'poise_derived/version'
|
20
|
+
|
21
|
+
Gem::Specification.new do |spec|
|
22
|
+
spec.name = 'poise-derived'
|
23
|
+
spec.version = PoiseDerived::VERSION
|
24
|
+
spec.authors = ['Noah Kantrowitz']
|
25
|
+
spec.email = %w{noah@coderanger.net}
|
26
|
+
spec.description = 'A Chef cookbook for defining lazily evaluated node attributes.'
|
27
|
+
spec.summary = spec.description
|
28
|
+
spec.homepage = 'https://github.com/poise/poise-derived'
|
29
|
+
spec.license = 'Apache 2.0'
|
30
|
+
|
31
|
+
spec.files = `git ls-files`.split($/)
|
32
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
33
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
34
|
+
spec.require_paths = %w{lib}
|
35
|
+
|
36
|
+
spec.add_dependency 'chef', '~> 12.3'
|
37
|
+
spec.add_dependency 'halite', '~> 1.0'
|
38
|
+
|
39
|
+
spec.add_development_dependency 'poise', '~> 2.0'
|
40
|
+
spec.add_development_dependency 'poise-boiler', '~> 1.0'
|
41
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2016, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
# Baseline for sanity.
|
18
|
+
default['a']['value'] = 'a'
|
19
|
+
|
20
|
+
default['b']['value'] = lazy 'b'
|
21
|
+
|
22
|
+
default['c']['one'] = '1'
|
23
|
+
default['c']['value'] = lazy '%{c.one}'
|
24
|
+
|
25
|
+
default['d']['value'] = lazy { 'd' }
|
26
|
+
|
27
|
+
default['e']['one'] = 1
|
28
|
+
default['e']['two'] = '2'
|
29
|
+
default['e']['value'] = lazy '%{e.one} %{e.two}'
|
30
|
+
|
31
|
+
# This value is changed later.
|
32
|
+
default['f']['one'] = '1'
|
33
|
+
default['f']['value'] = lazy '%{f.one}'
|
34
|
+
|
35
|
+
# This value is changed later.
|
36
|
+
default['g']['one'] = '1'
|
37
|
+
default['g']['value'] = lazy { node['g']['one'] }
|
38
|
+
|
39
|
+
# This template is changed later.
|
40
|
+
default['h']['one'] = '1'
|
41
|
+
default['h']['two'] = '2'
|
42
|
+
default['h']['value'] = lazy 'one %{h.one}'
|
43
|
+
|
44
|
+
default['i']['one'] = '1'
|
45
|
+
default['i']['two'] = lazy 'one %{i.one}'
|
46
|
+
default['i']['value'] = lazy 'two %{i.two} 2'
|