This excellent nugget of information led me to create a nifty little recipe
showing the agony we put Chef through in our daily lives.
Here's my recipe, bar::default (gist at
Chef recipe showing order of lazy evaluation · GitHub )
node.default.bar.tags = ['tag1-bar']
file "/tmp/bar.txt" do
content lazy { node.bar.tags.join(',') }
end
ruby_block 'update second tag' do
block { node.default.bar.tags << 'tag2-bar' }
only_if { node.default.bar.tags << 'tag3-bar' }
notifies :create, 'file[/tmp/bar.txt]', :delayed
end
r = resources(file: '/tmp/bar.txt')
r.content(Chef::DelayedEvaluator.new {
node.default.bar.tags << 'tag4-bar'
node.bar.tags.join(',')
})
Quickly: what will be written to my file /tmp/bar.txt?
kitchen converge output at
I wasn't sure what I was going to get-- that was the point of the
experiment-- but I was certainly surprised to get what I did!
On Thu, Oct 16, 2014 at 11:11 AM, Noah Kantrowitz noah@coderanger.net
wrote:
On Oct 16, 2014, at 10:49 AM, Justin Dossey justin.dossey@newcontext.com
wrote:
I ran into an interesting one today.
If you're wrapping a (community) cookbook and your wrapper needs lazy {}
to move evaluation of something to the execute phase, the #resources method
doesn't work.
Example
Cookbook foo, recipes/default.rb
file '/tmp/foo.txt' do
owner node['foo']['user']
end
Cookbook bar, recipes/default.rb
include_recipe 'foo::default'
user 'new_user'
node.override['foo']['user'] = 'new_user'
this doesn't work:
resources(file: '/tmp/foo.txt').owner( lazy { node['foo']['user'] })
Use this:
resources(file: '/tmp/foo.txt').owner(Chef::DelayedEvaluator.new {
node['foo']['user'] })
#lazy is just a helper method for that, but only available in the resource
class scope.
--Noah
--
Justin Dossey
Practice Owner
New Context Services, Inc