I'm trying to set the default value of one resource attribute to the value of another attribute.
I'm defining a resource with the following definitions in it for a tomcat cookbook I'm building. I want to have "name" and "service_name" attributes that can be set independently. When service name is not set, I want it to default to whatever is provided for "name."
The following does not work as I would expect:
attribute :name, :kind_of => String, :required => true, :name_attribute => true
attribute :service_name, :kind_of => String, :default => :name
Notice the ":default => :name" at the end of the second line. When I refer to my resource in a new block in a recipe as such
my_tomcat "install tomcat" do
name "foo_bar"
end
The attribute values get assigned as
name = "foo_bar"
service_name = "name"
which is not what I expected. I wanted service_name to be "foo_bar" unless it was explicitly set.
I've tried
attribute :service_name, :kind_of => String, :default => new_resource.name
attribute :service_name, :kind_of => String, :default => @new_resource.name
but those don't compile.
Is there a way to do what I'm trying to do?
Since those are class-level methods, you need to use the lazy
attribute:
attribute :service_name, kind_of: String, default: lazy { |r| r.name }
It's also worth noting that:
attribute :name, kind_of: String, required: true, name_attribute: true
is entirely redundant. That's the default...
I was unable to use Seth's "lazy" evaluation, but was able to simulate by creating a dynamic accessor method.
This other post was useful: How to implement a dynamic attribute default in chef LWRP definition
First, the definition in my resource definition file:
attribute :service_name, :kind_of => String, default: nil
Next, the accessor block at the bottom of the same resource definition file:
def service_name( arg=nil )
if arg.nil? and @service_name.nil?
set_or_return( :service_name, @name, :kind_of => String)
else
set_or_return( :service_name, arg, :kind_of => String )
end
end
Which effectively sets the value of "service_name" the first time it is used in my provider code.
This works for all combinations of
resource "title" do
# name defaults to "title"
# service_name defaults to "title"
end
resource "title" do
name "my_name"
# service_name defaults to "my_name"
end
resource "title" do
name "my_name"
service_name "my_service_name"
end
Thanks, again, for your help. I hope someone else finds this useful in the future.
Rich
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With