There is one thing that need an attention when developing a recipe. If we create a method in recipe then that method is not available inside resource block's parameter. I will show it in the following example using Shef, the Chef interactive Ruby console.
[root@localhost gems]# shef
Ohai2u root@localhost!
chef > recipe
chef:recipe > # here we are inside of a recipe
chef:recipe > def account(path) # create a method
chef:recipe ?> return 'nobody' if File.dirname(path) == '/tmp'
chef:recipe ?> return 'root'
chef:recipe ?> end
=> nil
chef:recipe > file "/tmp/file.test" do
chef:recipe > action :create
chef:recipe ?> owner account(name) # try to use this method inside the block and we got a error
chef:recipe ?> end
NoMethodError: undefined method `account' for Chef::Resource::File
from /usr/lib/ruby/gems/1.8/gems/chef-0.9.8/lib/chef/resource.rb:84:in `method_missing'
One way to workaround is to call the method outside of resource block's parameter so the method is called in the context of recipe
chef:recipe > fname = "/tmp/file.test"
=> "/tmp/file.test"
chef:recipe > account_val = account(fname)
=> "root"
chef:recipe > file fname do
chef:recipe > action :create
chef:recipe ?> owner account_val
chef:recipe ?> end
chef:recipe >
Other way is to define it as library (put it inside the directory libraries), in shef we would do like that
chef:recipe > exit
=> :recipe
chef > # here we are in top context, in which libraries are loaded
chef > def account(dirname)
chef ?> return 'nobody' if File.dirname(path) == '/tmp'
chef ?> return 'root'
chef ?> end
=> nil
chef > recipe
chef:recipe > # here we are inside of a recipe
chef:recipe > file "/tmp/file.test" do
chef:recipe > action :create
chef:recipe ?> owner account(name) # now it is OK
chef:recipe ?> end
chef:recipe >
In that case, the method is visible in the context of resource.
1 comment:
Thanks for this. I was looking for a way to assign the output of an exec to a variable. This did it:
result = IO.popen("ls -1t").readlines[0].strip
Post a Comment