1
votes

I created a cookbook using:

chef generate cookbook demo
chef generate attribute default
chef generate resource package

recipes\default.rb:

demo_package 'Demo'

resources\package.rb:

property :resource_prop1, String
property :resource_prop2, String

default_action :install

load_current_value do
  puts
  puts "the current value before change for 'test_prop1': #{resource_prop1}"
  puts "the current value before change for 'test_prop2': #{resource_prop2}"
  resource_prop1 = node['demo_resource']['test_prop1']
  resource_prop2 = node['demo_resource']['test_prop2']
  puts "the current value after change for 'test_prop1': #{resource_prop1}"
  puts "the current value after change for 'test_prop2': #{resource_prop2}"
end

action :install do
    puts "the current value after load properties for 'test_prop1': #{new_resource.resource_prop1}"
    puts "the current value after load properties for 'test_prop2': #{new_resource.resource_prop2}"
end

attributes\default.rb:

default['demo_resource'] = {}
default['demo_resource']['test_prop1'] = 'test value 1'
default['demo_resource']['test_prop2'] = 'test value 2'

I expected the output to look like this:

the current value before change for 'test_prop1':
the current value before change for 'test_prop2':
the current value after change for 'test_prop1': test value 1
the current value after change for 'test_prop2': test value 2
the current value after load properties for 'test_prop1': test value 1
the current value after load properties for 'test_prop2': test value 2

but I actually got:

the current value before change for 'test_prop1':
the current value before change for 'test_prop2':
the current value after change for 'test_prop1': test value 1
the current value after change for 'test_prop2': test value 2
the current value after load properties for 'test_prop1': 
the current value after load properties for 'test_prop2':

I am trying to figure out the proper way of referencing the properties of a resource from the action block. What am I doing wrong?


UPDATE

I tried changing this line:

puts "the current value after load properties for 'test_prop1': #{new_resource.resource_prop1}"

into this:

puts "the current value after load properties for 'test_prop1': #{resource_prop1}"

but I got this error:

NameError undefined local variable or method `resource_prop1' for #<#Class:0x0000000007b51178>:0x00000000084b3680> Did you mean?  resources

UPDATE 2

I was able to workaround this issue by modifying the local_current_value block as follows:

load_current_value do |package|
  puts
  puts "the current value before change for 'test_prop1': #{package.resource_prop1}"
  puts "the current value before change for 'test_prop2': #{package.resource_prop2}"
  package.resource_prop1 = node['demo_resource']['test_prop1']
  package.resource_prop2 = node['demo_resource']['test_prop2']
  puts "the current value after change for 'test_prop1': #{package.resource_prop1}"
  puts "the current value after change for 'test_prop2': #{package.resource_prop2}"
end
2
Welcome to SO! I'd recommend reading "Writing The Perfect Question" and "How To Ask Questions The Smart Way". We don't care about your expertise; The most important thing to us is writing a well researched and asked question. - the Tin Man

2 Answers

1
votes

There are 2 objects in custom resources: current_resource and new_resource. You create the new_resource, when you use your custom resource in a recipe:

demo_package 'Demo' do
  resource_prop1 'foo'
  resource_prop2 'bar'
end

Inside the load_current_value you should be loading the current state of the resource. For example, if you are to create a file with some path and owner, then in load_current_resource you should get the file and its current owner, for the later check, if the resource has changed. In your current method you actually assign current_resource.resource_prop1 and current_resource.prop2.

And as new_resource and current_resource are different objects, the values you set in load_current_resource are not passed from current_resource to new_resource.

If you need the loaded values inside action block, use current_resource:

action :install do
    puts "the current value after load properties for 'test_prop1': #{current_resource.resource_prop1}"
    puts "the current value after load properties for 'test_prop2': #{current_resource.resource_prop2}"
end

Answer to Update 2

When you are passing a parameter to load_corrent_resource, this parameter actually references new_resource. This is sometimes helpful, if

  1. You need some values from new_resource to calculate values of the current_resource.
  2. You need to calculate and assign some value of the new_resource.

There is a convention to call this parameter desired, like this:

load_current_value do |desired|
  # will assign current_resource.resource_prop1 = calculate_value(new_resource.resource_prop1)
  resource_prop1 calculate_value(desired.resource_prop1)
  [...]
  # will assign new_resource.resource_prop2
  desired.resource_prop2 some_calculation
end
0
votes

see custom resources, in your case it should be something like

new_resource.resource_prop1