File: parser.rb

package info (click to toggle)
puppet-agent 8.10.0-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 27,404 kB
  • sloc: ruby: 286,820; sh: 492; xml: 116; makefile: 88; cs: 68
file content (116 lines) | stat: -rw-r--r-- 3,867 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# frozen_string_literal: true

require_relative '../../../puppet/file_serving/configuration'
require_relative '../../../puppet/util/watched_file'

class Puppet::FileServing::Configuration::Parser
  Mount = Puppet::FileServing::Mount
  MODULES = 'modules'

  # Parse our configuration file.
  def parse
    raise(_("File server configuration %{config_file} does not exist") % { config_file: @file }) unless Puppet::FileSystem.exist?(@file)
    raise(_("Cannot read file server configuration %{config_file}") % { config_file: @file }) unless FileTest.readable?(@file)

    @mounts = {}
    @count = 0

    File.open(@file) do |f|
      mount = nil
      f.each_line do |line|
        # Have the count increment at the top, in case we throw exceptions.
        @count += 1

        case line
        when /^\s*#/; next # skip comments
        when /^\s*$/; next # skip blank lines
        when /\[([-\w]+)\]/
          mount = newmount(::Regexp.last_match(1))
        when /^\s*(\w+)\s+(.+?)(\s*#.*)?$/
          var = ::Regexp.last_match(1)
          value = ::Regexp.last_match(2)
          value.strip!
          raise(ArgumentError, _("Fileserver configuration file does not use '=' as a separator")) if value =~ /^=/

          case var
          when "path"
            path(mount, value)
          when "allow", "deny"
            # ignore `allow *`, otherwise report error
            if var != 'allow' || value != '*'
              error_location_str = Puppet::Util::Errors.error_location(@file.filename, @count)
              Puppet.err("Entry '#{line.chomp}' is unsupported and will be ignored at #{error_location_str}")
            end
          else
            error_location_str = Puppet::Util::Errors.error_location(@file.filename, @count)
            raise ArgumentError, _("Invalid argument '%{var}' at %{error_location}") %
                                 { var: var, error_location: error_location_str }
          end
        else
          error_location_str = Puppet::Util::Errors.error_location(@file.filename, @count)
          raise ArgumentError, _("Invalid entry at %{error_location}: '%{file_text}'") %
                               { file_text: line.chomp, error_location: error_location_str }
        end
      end
    end

    validate

    @mounts
  end

  def initialize(filename)
    @file = Puppet::Util::WatchedFile.new(filename)
  end

  def changed?
    @file.changed?
  end

  private

  # Create a new mount.
  def newmount(name)
    if @mounts.include?(name)
      error_location_str = Puppet::Util::Errors.error_location(@file, @count)
      raise ArgumentError, _("%{mount} is already mounted at %{name} at %{error_location}") %
                           { mount: @mounts[name], name: name, error_location: error_location_str }
    end
    case name
    when "modules"
      mount = Mount::Modules.new(name)
    when "plugins"
      mount = Mount::Plugins.new(name)
    when "scripts"
      mount = Mount::Scripts.new(name)
    when "tasks"
      mount = Mount::Tasks.new(name)
    when "locales"
      mount = Mount::Locales.new(name)
    else
      mount = Mount::File.new(name)
    end
    @mounts[name] = mount
    mount
  end

  # Set the path for a mount.
  def path(mount, value)
    if mount.respond_to?(:path=)
      begin
        mount.path = value
      rescue ArgumentError => detail
        Puppet.log_exception(detail, _("Removing mount \"%{mount}\": %{detail}") % { mount: mount.name, detail: detail })
        @mounts.delete(mount.name)
      end
    else
      Puppet.warning _("The '%{mount}' module can not have a path. Ignoring attempt to set it") % { mount: mount.name }
    end
  end

  # Make sure all of our mounts are valid.  We have to do this after the fact
  # because details are added over time as the file is parsed.
  def validate
    @mounts.each { |_name, mount| mount.validate }
  end
end