How to override node attribute value within ruby block / using a value of variable in ruby block?

Hi,

i have a custom attribute JSON like below;

{
    "custom_attributes": {
        "custom_attribute_1": "default_value"
    }
}

and, I can use #{node[:custom_attributes][:custom_attribute_1]}" to print / use that value anywhere in my recipes. Then, I want to change that value and I can achieve it by mentioning it in default.rb file inside attributes directory of my cookbook, like below;

override['custom_attributes']['custom_attribute_1'] = "overridden_value"

Now, if I print / use this attribute, new value will get reflected. This works well.

Lets consider I haven't overridden the value and trying to use a ruby block for this like below;

ruby_block 'test_block' do
    block do
        node.override['custom_attributes']['custom_attribute_1'] = "overridden_value"
    end
    action :run
end

log 'message' do
    message "attribute value = #{node[:custom_attributes][:custom_attribute_1]}"
    level :info
end

Now, if we take a look at log, it will show default_value instead of overridden_value. Why this is happening and how to fix this?

below are couple of links I have came across, but I don't know how to make use of it because I am a beginner.

Thanks.

message lazy { "attribute value = #{node[:custom_attributes][:custom_attribute_1]}" }

When the log resource is compiled, your ruby block resource hasn't been run, just compiled, it's the usual compile vs converge problem people stumble on.

Wrapping the property value with lazy { } will tell chef to delay until converge phase to resolve the value instead of evaluating it at compile time.

More details: Chef's Two Pass Model – Noah Kantrowitz

2 Likes

Thanks @Tensibai , it helped :+1:

Following this post , I am using lazy block to evaluate node attribute lazily in registry_key chef resource to set registry key , However lazy evaluation is not working as expected & I am getting
undefined method `to_a' for #<Chef::DelayedEvaluator:0x000000000a585c28> error . I would appreciate if some one can take a look on it & suggest a hint.

Recipe

# Simple Recipe:: rectify-java-param-heapdump

node.default['options_value1'] = []
options_value = []

#Creating common heapdump directory path for given tomcat services on node (if it doesn't exist)
directory "#{node['birst_post_installation']['heapdump_path']}" do
	recursive true
	not_if { ::Dir.exist?("#{node['birst_post_installation']['heapdump_path']}") }
end

  
#Fetching existing registry value of birst service
ruby_block "heapdump - Proceeding for modifying registry" do
      block do
        existing_value = registry_get_values("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Apache Software Foundation\\Procrun 2.0\\ABC\\Parameters\\Java", :x86_64)
        Chef::Log.info("heapdump existing value is - service is  ")
        Chef::Log.info(existing_value)
        #Checking existing registry value & storing conditionally modified registry object in variable
        existing_value.each{|e| 
           if e[:name] == "Options" 
            		node.override['options_value1'] = e[:data]
            		node.override['options_value1'].insert(-1, "-XX:+HeapDumpOnOutOfMemoryError")
           end
        }
		Chef::Log.info("here heapdump options node value is ")
		Chef::Log.info(node['options_value1'])
      end
	  action :run
end

#Setting updated 'Options' param's value for given birst tomcat service in registry
registry_key "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Apache Software Foundation\\Procrun 2.0\\ABC\\Parameters\\Java" do
	  values [{
        name: 'Options',
        type: :multi_string,
        data: lazy { node['options_value1'] }
      }]
      action :create
end

Output

Installing Cookbook Gems:
Compiling Cookbooks...
Converging 3 resources
Recipe: mycookbook::rectify-java-param-heapdump
  * directory[D:/Heapdumps] action create (skipped due to not_if)
  * ruby_block[heapdump - Proceeding for modifying registry] action run
    - execute the ruby block heapdump - Proceeding for modifying registry
  * registry_key[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Apache Software Foundation\Procrun 2.0\ABC\Parameters\Java] action create

    ================================================================================
    Error executing action `create` on resource 'registry_key[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Apache Software Foundation\Procrun 2.0\ABC\Parameters\Java]'
    ================================================================================

    NoMethodError
    -------------
    undefined method `to_a' for #<Chef::DelayedEvaluator:0x000000000a585c28>
    Did you mean?  to_s

    Resource Declaration:
    ---------------------
    # In D:/chefRepo/cache/cookbooks/mycookbook/recipes/rectify-java-param-heapdump.rb

     77: registry_key "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Apache Software Foundation\\Procrun 2.0\\ABC\\Parameters\\Java" do
     78:          values [{
     79:         name: 'Options',
     80:         type: :multi_string,
     81:         data: lazy { node['options_value1'] }
     82:       }]
     83:       action :create
     84: end

    Compiled Resource:
    ------------------
    # Declared in D:/chefRepo/cache/cookbooks/mycookbook/recipes/rectify-java-param-heapdump.rb:77:in `from_file'

    registry_key("HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Apache Software Foundation\Procrun 2.0\ABC\Parameters\Java") do
      action [:create]
      default_guard_interpreter :default
      values [{:name=>"Options", :type=>:multi_string, :data=>#<Chef::DelayedEvaluator:0x000000000a585c28@D:/chefRepo/cache/cookbooks/mycookbook/recipes/rectify-java-param-heapdump.rb:81>}]
      unscrubbed_values [{:name=>"Options", :type=>:multi_string, :data=>#<Chef::DelayedEvaluator:0x000000000a585c28@D:/chefRepo/cache/cookbooks/mycookbook/recipes/rectify-java-param-heapdump.rb:81>}]
      declared_type :registry_key
      cookbook_name "mycookbook"
      recipe_name "rectify-java-param-heapdump"
      key "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Apache Software Foundation\\Procrun 2.0\\ABC\\Parameters\\Java"
    end

    System Info:
    ------------
    chef_version=15.7.32
    platform=windows
    platform_version=6.3.9600
    ruby=ruby 2.6.5p114 (2019-10-01 revision 67812) [x64-mingw32]
    program_name=C:/opscode/chefdk/bin/chef-solo
    executable=C:/opscode/chefdk/bin/chef-solo

Created 'registry_key' resource's values can't be set lazily. · Issue #11877 · chef/chef · GitHub for this