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 } def self.to_line(hash) "#{hash[:name]}=#{hash[:value]}" end end -- 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.
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]}" > endIf 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
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.
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 >> >-- 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.
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]}" > endAs 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. >
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. >> >-- 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.
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. >>> >> >-- 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.
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. >>>> >>> >> >-- 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.
On Tue, Aug 23, 2011 at 04:19:40PM -0400, David Kavanagh wrote:> for reference, here''s how the regex matches the trailing comment; > http://rubular.com/r/vJUtBWpB6J >Yes, rubular shows all fields but the last field is in fact nil and not an empty string. Try to replace str += " # #{hash[:comment]}" if hash[:comment] != :absent with str += " # #{hash[:comment]}" unless hash[:comment].nil? Does this work? -Stefan
Like a charm! What designates the fields in the regex? I''m having trouble finding documentation on that part. David On Tue, Aug 23, 2011 at 4:59 PM, Stefan Schulte <stefan.schulte@taunusstein.net> wrote:> On Tue, Aug 23, 2011 at 04:19:40PM -0400, David Kavanagh wrote: >> for reference, here''s how the regex matches the trailing comment; >> http://rubular.com/r/vJUtBWpB6J >> > > Yes, rubular shows all fields but the last field is in fact nil and not an > empty string. Try to replace > > str += " # #{hash[:comment]}" if hash[:comment] != :absent > > with > > str += " # #{hash[:comment]}" unless hash[:comment].nil? > > Does this work? > > -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.
On Tue, Aug 23, 2011 at 04:27:30PM -0400, David Kavanagh wrote:> I understand regular expressions. been doing them a long time in > various languages. But, how are the fields determined from this regex? > > David >You have to put everything you want to capture in parentheses, so /^Hello (.*)$/.match(''Hello World'').captures == [''World''] However if you want to just define a block and you don''t want to capture it you can use (?: and ) instead of ( and ). I used that in the regex like in (?:\s*=\s*(.*?))? This means there is an optional equal sign with stuff after it as indicated by the quotation mark after the block marked with the outer parentheses (?: and ). But I dont want to capture the whole block so I just capture what is after the equal sign (the inner parentheses). Does this answers your question? -Stefan
yes, That''s actually does. I wasn''t finding much to read about this. David On Tue, Aug 23, 2011 at 5:12 PM, Stefan Schulte <stefan.schulte@taunusstein.net> wrote:> On Tue, Aug 23, 2011 at 04:27:30PM -0400, David Kavanagh wrote: >> I understand regular expressions. been doing them a long time in >> various languages. But, how are the fields determined from this regex? >> >> David >> > > You have to put everything you want to capture in parentheses, so > > /^Hello (.*)$/.match(''Hello World'').captures == [''World''] > > However if you want to just define a block and you don''t > want to capture it you can use (?: and ) instead of ( and ). > > I used that in the regex like in > > (?:\s*=\s*(.*?))? > > This means there is an optional equal sign with stuff after it as > indicated by the quotation mark after the block marked with the > outer parentheses (?: and ). But I dont want to capture the whole > block so I just capture what is after the equal sign > (the inner parentheses). > > Does this answers your question? > > -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.
On Tue, Aug 23, 2011 at 05:47:07PM -0400, David Kavanagh wrote:> yes, That''s actually does. I wasn''t finding much to read about this. > > DavidMaybe http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html#UN -Stefan