Re: [Puppet Users] property file provider

David Kavanagh
Tue, 23 Aug 2011 14:32:54 -0000

I did get this working. In a nutshell, I modified to_line like this;
  def self.to_line(hash)
    return super unless hash[:record_type] == :parsed
    "#{hash[:name]}=#{hash[:value]}"
  end

which handles the other line types. To handle wrapping values in
quotes, I changed the type like this;
  newproperty(:value) do
    munge do |value|
      ''"''+value.to_s+''"''
    end
    newvalues(/^\S+$/)
  end

so, that line where value.to_s is wrapped with quotes seems to work nicely.

My other problem now is that aside from handling these variations

# comment lines
key="value"

I also need to handle this;

key="value" #optional comment

I could add to the regex for the line matching (in record_line
:parsed). Then, I''m not sure how to get that into to_line for output.

David

On Mon, Aug 22, 2011 at 8:48 PM, David Kavanagh <dkavanagh@gmail.com>
wrote:
> Thanks, I''ll try to work through your suggestions. I took this
from
> the nova_config stuff on github, so that was my example.
>
> David
>
> On Mon, Aug 22, 2011 at 7:36 PM, Stefan Schulte
> <stefan.schulte@taunusstein.net> wrote:
>> On Mon, Aug 22, 2011 at 06:33:27PM -0400, David Kavanagh wrote:
>>> I''m working on a type/provider for the eucalyptus.conf
file. What I
>>> have generally works for modifying properties. I have a couple of
>>> issues and not being very experienced with Ruby and custom
providers,
>>> I wonder if anyone can help?
>>> The code is included below. The key/value constructs in the file
look like:
>>>
>>> key="value"
>>>
>>> 1. I''m not getting the quotes surrounding the value, which
I think I
>>> can figure out myself.
>>> 2. I get all blanks and comments replaced by "=", which
is more of a problem.
>>>
>>> David
>>>
>>>
>>> require ''puppet/provider/parsedfile''
>>>
>>> eucaconf = "/etc/eucalyptus/eucalyptus.conf"
>>>
>>> Puppet::Type.type(:eucalyptus_config).provide(
>>>   :parsed,
>>>   :parent => Puppet::Provider::ParsedFile,
>>>   :default_target => eucaconf,
>>>   :filetype => :flat
>>> ) do
>>>
>>>   confine :exists => eucaconf
>>>   text_line :comment, :match => /^#/;
>>>   text_line :blank, :match => /^\s*$/;
>>>
>>>   record_line :parsed,
>>>     :fields => %w{line},
>>>     :match => /(.*)/ ,
>>>     :post_parse => proc { |hash|
>>>       Puppet.debug("eucalyptus config line:#{hash[:line]} has
been parsed")
>>>       if hash[:line] =~ /^\s*(\S+)\s*=\s*(\S+)\s*$/
>>>         hash[:name]=$1
>>>         hash[:value]=$2
>>>       elsif hash[:line] =~ /^\s*(\S+)\s*$/
>>>         hash[:name]=$1
>>>         hash[:value]=false
>>>       else
>>>         raise Puppet::Error, "Invalid line:
#{hash[:line]}"
>>>       end
>>>     }
>>
>> instead of the post_parse hook you can probably just change your regex
>>  :fields   => %w{name value},
>>  :optional => %w{value},
>>  :match    => /^\s*(.*?)(?:\s*=\s*"(\S+)")?\s*$/
>>
>> This matches line like
>>
>>  foo
>>
>> and
>>
>>  foo = "bar"
>>
>>>
>>>   def self.to_line(hash)
>>>     "#{hash[:name]}=#{hash[:value]}"
>>>   end
>>
>> If you just overwrite the to_line method you have to take care of the
>> different record_types (you defined :comment, :text and :parsed).
>> So you have to do
>>
>>    def self.to_line(hash)
>>      return super unless hash[:record_type] == :parsed
>>      if hash[:value] == :absent
>>        hash[:name]
>>      else
>>        "#{hash[:name]}=\"#{hash[:value]}\""
>>      end
>>    end
>>
>> Nevertheless the "right" thing to do is to pass a block to
the
>> record_line method:
>>
>>  record_line :parsed,
>>    :fields  => ...,
>>    :match   => ...,
>>    :to_line => proc { |hash|
>>      if hash[:value] == :absent
>>        hash[:name]
>>      else
>>        "#{hash[:name]}=\"#{hash[:value]}\""
>>      end
>>    }
>>
>> Hope that helps.
>>
>> -Stefan