3

I am trying to change an attribute in one resource and want to use updated value in another resource but updated value is not getting reflected in another resources. please help me

Code

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

    bash "beforeTest" do
        code <<-EOH
            echo #{node[:oracle][:asm][:test]}
        EOH
    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 <<-EOH
            echo #{node[:oracle][:asm][:test]}
        EOH
    end
end

The value I'm trying to update is the one stored at node[:oracle][:asm][:test]

Ethaan
  • 11,291
  • 5
  • 35
  • 45
SASI
  • 475
  • 2
  • 7
  • 16

2 Answers2

5

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.

Tejay Cardon
  • 4,193
  • 2
  • 16
  • 31
  • Still i am getting error as below: NoMethodError ------------- undefined method `echo' for Chef::Resource::Bash Cookbook Trace: --------------- /var/chef/cache/cookbooks/Oracle11G/recipes/testSplit.rb:3:in `block (2 levels) in from_file' Resource Declaration: --------------------- # In /var/chef/cache/cookbooks/Oracle11G/recipes/testSplit.rb 1: bash "beforeTest" do 2: code lazy{ 3: echo "#{node[:oracle][:asm][:test]}" 4: } 5: end – SASI Apr 20 '15 at 09:08
  • 1
    sorry, that's just because the command isn't in quotes. I'll fix it. – Tejay Cardon Apr 20 '15 at 16:54
  • Why would you want to use lazy in a ruby_block? – Tejay Cardon Apr 23 '15 at 15:29
  • @TejayCardon i am blown away. Been using Chef for 3 - 4 years and have tried some pretty elaborate ways to get output from 1 resource into another (especially around encrypted data bags). This solves so many problems. Thanks!! – Brett Sep 21 '16 at 15:42
  • @Brett no problem. The Lazy concept was a HUGE addition to Chef that really did make many more things possible. Now if only I could use Lazy outside the scope of a recipe.... – Tejay Cardon Sep 21 '16 at 16:35
2

Lazy is good, but here is another approach. You may use node.run_state for your purposes.

Here is usage example from https://docs.chef.io/recipes.html

package 'httpd' do
  action :install
end

ruby_block 'randomly_choose_language' do
  block do
    if Random.rand > 0.5
      node.run_state['scripting_language'] = 'php'
    else
      node.run_state['scripting_language'] = 'perl'
    end
  end
end

package 'scripting_language' do
  package_name lazy { node.run_state['scripting_language'] }
  action :install
end
Baurito
  • 121
  • 1
  • 9