Re: [Puppet Users] property file provider

David Kavanagh
Tue, 23 Aug 2011 20:19:40 -0000

for reference, here''s how the regex matches the trailing comment;
http://rubular.com/r/vJUtBWpB6J


On Tue, Aug 23, 2011 at 4:17 PM, David Kavanagh <dkavanagh@gmail.com>
wrote:
> Hi Stefan,
> I have it working using your suggestions (I took out my hacks). I
> adjusted the match regex to match the quotes in the value portion.
> Otherwise, I kept getting more quotes added in each time the file was
> processed.
> The only glitch now is that it always thinks there''s a comment, so
> even if there isn''t a comment after the value, it adds a
"#" at the
> end of line.
>
> David
>
> On Tue, Aug 23, 2011 at 11:45 AM, Stefan Schulte
> <stefan.schulte@taunusstein.net> wrote:
>> On Tue, Aug 23, 2011 at 10:32:54AM -0400, David Kavanagh wrote:
>>> 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
>>
>> As I said, I wouldn''t to that. Just pass a :to_line => proc
{...} to your
>> record_line call because you will then just overwrite the to_line
method
>> of that particular record_type.
>>
>>>
>>> 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.
>>
>> Hm, in my opinion using a regex that gets the value as an unqoted
string
>> and put the quotes back to the string in the to_line method looks saner
>> than munging the value.
>>
>>>
>>> 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.
>>
>> You have to store the inlinecomment in the record hash and then put it
>> back in the to_line hook. So this should work
>> (to test the regex I recommend rubular.com)
>>
>> record_line :parsed,
>>  :fields   => %w{name value comment},
>>  :optional => %w{value comment},
>>  :regex    => /^\s*(.*?)(?:\s*=\s*(.*?))?(?:\s*#\s*(.*))?\s*$/,
>>  :to_line  => proc { |hash|
>>    str = hash[:name]
>>    str += "=\"#{hash[:value]}\"" if hash[:value] !=
:absent
>>    str += " # #{hash[:comment]}" if hash[:comment] != :absent
>>    str
>>  }
>>
>>
>>>
>>> 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
>>> >>
>>> >
>>>
>>> --
>>> You received this message because you are subscribed to the Google
Groups "Puppet Users" group.
>>> To post to this group, send email to puppet-users@googlegroups.com.
>>> To unsubscribe from this group, send email to
puppet-users+unsubscribe@googlegroups.com.
>>> For more options, visit this group at
http://groups.google.com/group/puppet-users?hl=en.
>>>