Re: [Puppet Users] property file provider

David Kavanagh
Tue, 23 Aug 2011 20:27:30 -0000

I understand regular expressions. been doing them a long time in
various languages. But, how are the fields determined from this regex?

David

On Tue, Aug 23, 2011 at 4:19 PM, David Kavanagh <dkavanagh@gmail.com>
wrote:
> 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.
>>>>
>>>