Bug #8138

Puppet Host Resource purge file when encounter unknown entry (Parsefile)

Added by Nan Liu almost 2 years ago. Updated almost 2 years ago.

Status:AcceptedStart date:06/29/2011
Priority:NormalDue date:
Assignee:Luke Kanies% Done:

0%

Category:host
Target version:-
Affected Puppet version:2.6.9 Branch:
Keywords:

Description

This is related to parsedfile and it’s discovered when writing a provider against it.

When parsedfile fails to process a line, instead of leaving it alone, it raises an error and throws away every record except for the resources in the catalog.

For example host file:

127.0.0.1 localhost
192.168.2.1 kermit
badrecord

If we apply the following puppet resource it will purge the entire file and only leave kermit (remove localhost, badrecord):

host { 'kermit':
  ip => '192.168.1.1',
}

I can work around this issue by changing provider/host/parsed.rb:

 43     else
 44       #raise Puppet::Error, "Could not match '#{line}'"
 45       hash = {:ip => line, :name => ''}
 46     end

However it’s really not the right solution since it simply silently ignore the parse problem. I’ve looked at parsedfile.rb, it appears to be related to the specific section below, but I’m not sure what needs to be changed in fileparsing.rb parse which invokes parse_line.

249       begin
250         @target = path
251         return self.parse(text)
252       rescue Puppet::Error => detail
253         detail.file = @target
254         raise detail
255       ensure

Related issues

Duplicated by Puppet - Bug #9440: Puppet destroys crontab files which contain whitespace be... Closed 09/12/2011

History

#1 Updated by Nan Liu almost 2 years ago

  • Category set to host
  • Affected Puppet version set to 2.6.9

#2 Updated by James Turnbull almost 2 years ago

  • Status changed from Unreviewed to Needs More Information
  • Assignee set to Luke Kanies

Luke – any ideas? ParsedFile hurts my feelings.

#3 Updated by Luke Kanies almost 2 years ago

It looks like there are 2-3 places that throw an exception, and at most one of them should.

I also recommend, for clarity, that FileParsing just be merged into ParsedFile – no other class uses it, and I think part of the confusion of ParsedFile is just that half of its functionality is in another file.

Anyway, I think this method:


  # Split a bunch of text into lines and then parse them individually.
  def parse(text)
    count = 1
    lines(text).collect do |line|
      count += 1
      if val = parse_line(line)
        val
      else
        error = Puppet::Error.new("Could not parse line #{line.inspect}")
        error.line = count
        raise error
      end
    end
  end

Should probably be changed to something like:

  def parse(text)
    count = 1
    lines(text).collect do |line|
      count += 1
      begin
        if val = parse_line(line)
          val
        else
          Puppet.warning "Could not parse invalid line #{line.inspect}"
          next
        end
      rescue => detail
        Puppet.warning "Could not parse invalid line #{line.inspect}: #{detail}"
        next
      end
    end.compact # remove nil values resulting from 'next'
  end

Note that this has the side effect of actually discarding bad (according to Puppet) lines, and I think it will do so even in noop mode. It’s worth making sure that ParsedFile doesn’t even write if global noop mode is enabled.

#4 Updated by Matthaus Owens almost 2 years ago

  • Status changed from Needs More Information to Accepted

Also available in: Atom PDF