Re: [Puppet Users] property file provider

Stefan Schulte
Tue, 23 Aug 2011 15:45:53 -0000

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