Re: [Puppet Users] property file provider

David Kavanagh
Tue, 23 Aug 2011 20:17:38 -0000

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