How to Pass Value from One Resource to Another Resource in Chef Recipe

How to pass value from one resource to another resource in chef recipe?

Your problem is that the code variable is set during the compile phase of chef, before the ruby block has changed the value of your attribute. You need to add a lazy initializer around your code block.

Chef::Log.info("I am in #{cookbook_name}::#{recipe_name} and current disk count #{node[:oracle][:asm][:test]}") 

bash "beforeTest" do
code lazy{ "echo #{node[:oracle][:asm][:test]}" }
end

ruby_block "test current disk count" do
block do
node.set[:oracle][:asm][:test] = "#{node[:oracle][:asm][:test]}".to_i+1
end
end

bash "test" do
code lazy{ "echo #{node[:oracle][:asm][:test]}" }
end

The first block doesn't really need the lazy, but I threw it in there just in case the value is changing elsewhere too.

pass variables from a chef resouce to other resources in the same chef recipe

Since you are running some Ruby code to get the file contents, you can even do it outside Chef resources. Something like:

if File.exists?("/work/customer/Var.js")
var = File.read("/work/customer/Var.js")
end

http_request 'cusromer update' do
action :put
# rest of code
end

Note that I've used var with lower case v.

Explanation:

The chef-client goes through several phases during the run. The two relevant for this answer are:

  • Compile
  • Converge

All variable and resources are compiled and assignments happen in the compile phase. So var remains unassigned as there is no definition in for it in compile phase. Whereas ruby_block and http_request run in the converge phase.

How to pass variable between Chef resource blocks of same recipe

UUID is part of filesystem2 Ohai data:

filesystem2:
by_device:
/dev/md1:
...
uuid: f49a3dc8-a0b6-4e1c-8cd3-926fa7d8ee29

There is no need to run blkid for this.

However, if you really need to do compute something in a block and use it later, you could declare uuid variable before the block and use ruby_block instead. You can also use node variable inside a ruby block. Anyway, you will be affected by Chef's two pass model and it would require further workarounds (like lazy attributes).

There is also a option to use helper method, but since UUID is part of Ohai data, I do not see any reason to even try (in this case).

Passing variables between chef resources

You have already solved problem A with the Ruby block.

Now you have to solve problem B with a similar approach:

ruby_block "create user" do
block do
user = Chef::Resource::User.new(node[:var], run_context)
user.shell '/bin/bash' # Set parameters using this syntax
user.run_action :create
user.run_action :manage # Run multiple actions (if needed) by declaring them sequentially
end
end

You could also solve problem A by creating the file during the compile phase:

execute "echo 'echo stuff' > /usr/local/bin/stuff.sh" do
action :nothing
end.run_action(:run)

If following this course of action, make sure that:

  • /usr/local/bin exist during Chef's compile phase;
  • Either:
    • stuff.sh is executable; OR
    • Execute it through a shell (e.g.: var=`sh /usr/local/bin/stuff.sh`

How to pass variables in Chef recipe

It seems you are looking for string/variable interpolation. Chef attributes are same as variables in programming languages like Ruby.

String interpolation in Ruby is performed by using "#{}" syntax. Any variable/attribute within the curly braces will be interpolated.

So your remote_file resource should look like this:

remote_file "/tmp/docker-#{node['common']['docker']}.tgz" do
source "https://download.docker.com/linux/static/stable/x86_64/docker-#{node['common']['docker']}.tgz"
owner 'root'
group 'root'
mode '0755'
action :create
end

Note that I have used outer double quotes " as it is required for interpolation. Also I have included the destination path as /tmp to save the file.

Passing the value from a ruby block to a resource in chef

You can use lazy attribute like below:-

Chef::Log.info("Updating WLSADMIN Password")
passwd_backup 'Updating wlsadmin password' do
action :update_wlsadmin
osuser node[:password][:wls_config_user]
usergroup node[:password][:wls_install_group]
new_wls_password lazy { JSON.parse(File.read("/tmp/password.json"))['rase_wlsadmin_pwd'] }
end

Template resource can be written as:-

template "#{Chef::Config[:file_cache_path]}/domain.properties" do 
source 'domain_properties.erb'
variables (lazy{{ :domain_name => "#{domain_name}",
:admin_url => "#{admin_url}",
:new_wls_password => JSON.parse(File.read("/tmp/password.json"))['rase_wlsadmin_pwd'] }})
end

Output:-

     * template[/tmp/kitchen/cache/domain.properties] action create
- create new file /tmp/kitchen/cache/domain.properties
- update content in file /tmp/kitchen/cache/domain.properties from none to fa22e0
--- /tmp/kitchen/cache/domain.properties 2017-01-12 03:30:13.002968715 +0000
+++ /tmp/kitchen/cache/.chef-domain20170112-11387-1ytkyk2.properties 2017-01-12 03:30:13.002968715 +0000
@@ -1 +1,4 @@
+domain_name= mmm
+admin_url= nnn
+new_wls_password= xH#3zIS9Q4Hc#B

how to pass parameter to execute in chef?

The main issue is the use of single quotes ('') in the command. Single quotes in Ruby don't allow for interpolation of the variable #{execf}. You should rewrite it as:

execute 'e.sh' do
command "/tmp/e.sh #{execf}"
action :nothing
end

However variable assignment (such as execf="e1") in the file resources will not have any effect. You will get something like haha 2022-05-13 22:04:48 in the logs.

Edit

However variable assignment (such as execf="e1") in the file resources will not have any effect.

Turns out that the variable assignment from within resource is also compiled, and last assigned value is used.



Related Topics



Leave a reply



Submit