Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement a dynamic attribute default in chef LWRP definition

I would like to be able to define a lightweight resource with let's say 3 parameters, two of them being basic/elementary parameters and the third being a combination of these two. I would also like to provide a possibility of customization of the third parameter. For example:

How to modify following code to achieve above behaviour for the full_name attribute:

resource definition:

actions :install

attribute :name, :kind_of => String, :name_attribute => true
attribute :version, :kind_of => String
attribute :full_name, :kind_of => String

provider definition:

action :install do
    Chef::Log.info "#{new_resource.full_name}"
end

I would like to see different outputs for different resource directives, e.g.:

resource "abc" do
    version "1.0.1"
end

will result in abc-1.0.1, but:

resource "def" do
    version "0.1.3"
    full_name "completely_irrelevant"
end

will result in completely_irrelevant.

Is there a possibility to define this behaviour in the resource definition (probably through the default parameter) or I am able to do it in provider definition only? If the second is true, then can I store the calculated value in the new_resource object's full_name attribute (the class seems to miss the full_name= method definition) or I have to store it in a local variable?

Update

Thanks to Draco's hint, I realized that I can create an accessor method in the resource file and calculate the full_name value on the fly when requested. I would prefer a cleaner solution but it's much better than calculating it in action implementation.

Chef version Chef: 10.16.4

like image 976
Dariusz Walczak Avatar asked Oct 05 '22 11:10

Dariusz Walczak


2 Answers

Setting @full_name in constructor, similar to providing default action in chef < 0.10.10, as written in wiki, does not work, because @version is not set at that point yet.

def initialize( name, run_context=nil )
  super
  @full_name ||= "%s-%s" % [name, version]
end

So we have to overwrite full_name method in resource by adding

def full_name( arg=nil )
  if arg.nil? and @full_name.nil?
    "%s-%s" % [name, version]
  else
    set_or_return( :full_name, arg, :kind_of => String )
  end
end

into resource definition. That works. Tested.

like image 180
Draco Ater Avatar answered Oct 10 '22 11:10

Draco Ater


attribute :full_name, :kind_of => String, default => lazy {|r| "#{r.name}-#{r.version}" }
like image 26
John Stadt Avatar answered Oct 10 '22 13:10

John Stadt