Class: Puppet::Util::Puppetdb::Command

Inherits:
Object
  • Object
show all
Includes:
Puppet::Util::Puppetdb, CommandNames
Defined in:
lib/puppet/util/puppetdb/command.rb

Constant Summary collapse

CommandsUrl =
"/pdb/cmd/v1"

Constants included from CommandNames

Puppet::Util::Puppetdb::CommandNames::CommandDeactivateNode, Puppet::Util::Puppetdb::CommandNames::CommandReplaceCatalog, Puppet::Util::Puppetdb::CommandNames::CommandReplaceFacts, Puppet::Util::Puppetdb::CommandNames::CommandStoreReport

Instance Attribute Summary collapse

Private instance methods collapse

Instance Method Summary collapse

Methods included from Puppet::Util::Puppetdb

config, log_x_deprecation_header, #profile, query_puppetdb, #submit_command, to_bool, to_wire_time

Constructor Details

#initialize(command, version, certname, payload) ⇒ Command

Initialize a Command object, for later submission.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/puppet/util/puppetdb/command.rb', line 26

def initialize(command, version, certname, payload)
  profile("Format payload", [:puppetdb, :payload, :format]) do
    @checksum_payload = Puppet::Util::Puppetdb::CharEncoding.utf8_string({
      :command => command,
      :version => version,
      :certname => certname,
      :payload => payload,
    # We use to_pson still here, to work around the support for shifting
    # binary data from a catalog to PuppetDB. Attempting to use to_json
    # we get to_json conversion errors:
    #
    #   Puppet source sequence is illegal/malformed utf-8
    #   json/ext/GeneratorMethods.java:71:in `to_json'
    #   puppet/util/puppetdb/command.rb:31:in `initialize'
    #
    # This is roughly inline with how Puppet serializes for catalogs as of
    # Puppet 4.1.0. We need a better answer to non-utf8 data end-to-end.
    }.to_pson, "Error encoding a '#{command}' command for host '#{certname}'")
  end
  @command = Puppet::Util::Puppetdb::CharEncoding.coerce_to_utf8(command).gsub(" ", "_")
  @version = version
  @certname = Puppet::Util::Puppetdb::CharEncoding.coerce_to_utf8(certname)
  @payload = Puppet::Util::Puppetdb::CharEncoding.coerce_to_utf8(payload.to_pson)
end

Instance Attribute Details

#certnameObject (readonly)

Returns the value of attribute certname.



51
52
53
# File 'lib/puppet/util/puppetdb/command.rb', line 51

def certname
  @certname
end

#checksum_payloadObject (readonly)

Returns the value of attribute checksum_payload.



51
52
53
# File 'lib/puppet/util/puppetdb/command.rb', line 51

def checksum_payload
  @checksum_payload
end

#commandObject (readonly)

Returns the value of attribute command.



51
52
53
# File 'lib/puppet/util/puppetdb/command.rb', line 51

def command
  @command
end

#payloadObject (readonly)

Returns the value of attribute payload.



51
52
53
# File 'lib/puppet/util/puppetdb/command.rb', line 51

def payload
  @payload
end

#versionObject (readonly)

Returns the value of attribute version.



51
52
53
# File 'lib/puppet/util/puppetdb/command.rb', line 51

def version
  @version
end

Instance Method Details

#configObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



112
113
114
115
116
# File 'lib/puppet/util/puppetdb/command.rb', line 112

def config
  # Would prefer to pass this to the constructor or acquire it some other
  # way besides this pseudo-global reference.
  Puppet::Util::Puppetdb.config
end

#headersObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



104
105
106
107
108
109
# File 'lib/puppet/util/puppetdb/command.rb', line 104

def headers
  {
    "Accept" => "application/json",
    "Content-Type" => "application/json; charset=utf-8",
  }
end

#submitHash <String, String>

Submit the command, returning the result hash.



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
# File 'lib/puppet/util/puppetdb/command.rb', line 56

def submit
  checksum = Digest::SHA1.hexdigest(checksum_payload)

  for_whom = " for #{certname}" if certname
  params = "checksum=#{checksum}&version=#{version}&certname=#{certname}&command=#{command}"
  begin
    response = profile("Submit command HTTP post", [:puppetdb, :command, :submit]) do
      Http.action("#{CommandsUrl}?#{params}", :command) do |http_instance, path|
        http_instance.post(path, payload, headers)
      end
    end

    Puppet::Util::Puppetdb.log_x_deprecation_header(response)

    if response.is_a? Net::HTTPSuccess
      result = JSON.parse(response.body)
      Puppet.info "'#{command}' command#{for_whom} submitted to PuppetDB with UUID #{result['uuid']}"
      result
    else
      # Newline characters cause an HTTP error, so strip them
      error = "[#{response.code} #{response.message}] #{response.body.gsub(/[\r\n]/, '')}"
      if config.soft_write_failure
        Puppet.err "'#{command}'command#{for_whom} failed during submission to PuppetDB: #{error}"
      else
        raise Puppet::Error, error
      end
    end
  rescue => e
    if config.soft_write_failure
      Puppet.err e.message
    else
      # TODO: Use new exception handling methods from Puppet 3.0 here as soon as
      #  we are able to do so (can't call them yet w/o breaking backwards
      #  compatibility.)  We should either be using a nested exception or calling
      #  Puppet::Util::Logging#log_exception or #log_and_raise here; w/o them
      #  we lose context as to where the original exception occurred.
      if Puppet[:trace]
        Puppet.err(e)
        Puppet.err(e.backtrace)
      end
      raise Puppet::Util::Puppetdb::CommandSubmissionError.new(e.message, {:command => command, :for_whom => for_whom})
    end
  end
end