File: msgpack.rb

package info (click to toggle)
puppet-agent 7.23.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 19,092 kB
  • sloc: ruby: 245,074; sh: 456; makefile: 38; xml: 33
file content (83 lines) | stat: -rw-r--r-- 2,818 bytes parent folder | download
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
require_relative '../../puppet/indirector/terminus'
require_relative '../../puppet/util'

# The base class for MessagePack indirection terminus implementations.
#
# This should generally be preferred to the PSON base for any future
# implementations, since it is ~ 30 times faster
class Puppet::Indirector::Msgpack < Puppet::Indirector::Terminus
  def initialize(*args)
    if ! Puppet.features.msgpack?
      raise _("MessagePack terminus not supported without msgpack library")
    end
    super
  end

  def find(request)
    load_msgpack_from_file(path(request.key), request.key)
  end

  def save(request)
    filename = path(request.key)
    FileUtils.mkdir_p(File.dirname(filename))

    Puppet::FileSystem.replace_file(filename, 0660) {|f| f.print to_msgpack(request.instance) }
  rescue TypeError => detail
    Puppet.log_exception(detail, _("Could not save %{name} %{request}: %{detail}") % { name: self.name, request: request.key, detail: detail })
  end

  def destroy(request)
    Puppet::FileSystem.unlink(path(request.key))
  rescue => detail
    unless detail.is_a? Errno::ENOENT
      raise Puppet::Error, _("Could not destroy %{name} %{request}: %{detail}") % { name: self.name, request: request.key, detail: detail }, detail.backtrace
    end
    1                           # emulate success...
  end

  def search(request)
    Dir.glob(path(request.key)).collect do |file|
      load_msgpack_from_file(file, request.key)
    end
  end

  # Return the path to a given node's file.
  def path(name, ext = '.msgpack')
    if name =~ Puppet::Indirector::BadNameRegexp then
      Puppet.crit(_("directory traversal detected in %{indirection}: %{name}") % { indirection: self.class, name: name.inspect })
      raise ArgumentError, _("invalid key")
    end

    base = Puppet.run_mode.server? ? Puppet[:server_datadir] : Puppet[:client_datadir]
    File.join(base, self.class.indirection_name.to_s, name.to_s + ext)
  end

  private

  def load_msgpack_from_file(file, key)
    msgpack = nil

    begin
      msgpack = Puppet::FileSystem.read(file, :encoding => 'utf-8')
    rescue Errno::ENOENT
      return nil
    rescue => detail
      #TRANSLATORS "MessagePack" is a program name and should not be translated
      raise Puppet::Error, _("Could not read MessagePack data for %{indirection} %{key}: %{detail}") % { indirection: indirection.name, key: key, detail: detail }, detail.backtrace
    end

    begin
      return from_msgpack(msgpack)
    rescue => detail
      raise Puppet::Error, _("Could not parse MessagePack data for %{indirection} %{key}: %{detail}") % { indirection: indirection.name, key: key, detail: detail }, detail.backtrace
    end
  end

  def from_msgpack(text)
    model.convert_from('msgpack', text)
  end

  def to_msgpack(object)
    object.render('msgpack')
  end
end