puppet 2.7.5 → 2.7.6

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (140) hide show
  1. data/CHANGELOG +121 -0
  2. data/conf/redhat/puppet.spec +16 -7
  3. data/lib/puppet.rb +1 -1
  4. data/lib/puppet/application/cert.rb +17 -3
  5. data/lib/puppet/application/device.rb +1 -0
  6. data/lib/puppet/application/kick.rb +0 -2
  7. data/lib/puppet/application/resource.rb +73 -66
  8. data/lib/puppet/configurer/plugin_handler.rb +6 -2
  9. data/lib/puppet/defaults.rb +60 -5
  10. data/lib/puppet/face/ca.rb +11 -2
  11. data/lib/puppet/face/certificate.rb +33 -4
  12. data/lib/puppet/file_serving/fileset.rb +1 -1
  13. data/lib/puppet/file_serving/indirection_hooks.rb +2 -2
  14. data/lib/puppet/file_serving/metadata.rb +43 -4
  15. data/lib/puppet/indirector.rb +0 -1
  16. data/lib/puppet/indirector/request.rb +3 -4
  17. data/lib/puppet/indirector/resource/active_record.rb +3 -10
  18. data/lib/puppet/indirector/resource/ral.rb +2 -2
  19. data/lib/puppet/indirector/rest.rb +1 -1
  20. data/lib/puppet/network/handler/ca.rb +16 -106
  21. data/lib/puppet/network/handler/master.rb +0 -3
  22. data/lib/puppet/network/handler/runner.rb +1 -0
  23. data/lib/puppet/parser/scope.rb +10 -0
  24. data/lib/puppet/provider/file/posix.rb +72 -34
  25. data/lib/puppet/provider/file/windows.rb +100 -0
  26. data/lib/puppet/provider/group/windows_adsi.rb +2 -2
  27. data/lib/puppet/provider/user/windows_adsi.rb +19 -4
  28. data/lib/puppet/resource.rb +16 -0
  29. data/lib/puppet/resource/catalog.rb +1 -1
  30. data/lib/puppet/ssl/certificate.rb +2 -2
  31. data/lib/puppet/ssl/certificate_authority.rb +86 -10
  32. data/lib/puppet/ssl/certificate_authority/interface.rb +64 -19
  33. data/lib/puppet/ssl/certificate_factory.rb +112 -91
  34. data/lib/puppet/ssl/certificate_request.rb +88 -1
  35. data/lib/puppet/ssl/host.rb +20 -3
  36. data/lib/puppet/type/file.rb +15 -34
  37. data/lib/puppet/type/file/group.rb +11 -91
  38. data/lib/puppet/type/file/mode.rb +11 -41
  39. data/lib/puppet/type/file/owner.rb +18 -34
  40. data/lib/puppet/type/file/source.rb +22 -7
  41. data/lib/puppet/type/group.rb +4 -3
  42. data/lib/puppet/type/user.rb +4 -1
  43. data/lib/puppet/util.rb +59 -6
  44. data/lib/puppet/util/adsi.rb +11 -0
  45. data/lib/puppet/util/log.rb +4 -0
  46. data/lib/puppet/util/log/destinations.rb +7 -1
  47. data/lib/puppet/util/monkey_patches.rb +19 -0
  48. data/lib/puppet/util/network_device/config.rb +4 -5
  49. data/lib/puppet/util/settings.rb +5 -0
  50. data/lib/puppet/util/suidmanager.rb +0 -1
  51. data/lib/puppet/util/windows.rb +4 -0
  52. data/lib/puppet/util/windows/error.rb +16 -0
  53. data/lib/puppet/util/windows/security.rb +593 -0
  54. data/spec/integration/defaults_spec.rb +27 -0
  55. data/spec/integration/network/handler_spec.rb +1 -1
  56. data/spec/integration/type/file_spec.rb +382 -145
  57. data/spec/integration/util/windows/security_spec.rb +468 -0
  58. data/spec/shared_behaviours/file_serving.rb +4 -3
  59. data/spec/unit/application/agent_spec.rb +1 -0
  60. data/spec/unit/application/device_spec.rb +5 -0
  61. data/spec/unit/application/resource_spec.rb +62 -101
  62. data/spec/unit/configurer/downloader_spec.rb +2 -2
  63. data/spec/unit/configurer/plugin_handler_spec.rb +15 -8
  64. data/spec/unit/configurer_spec.rb +2 -2
  65. data/spec/unit/face/ca_spec.rb +34 -0
  66. data/spec/unit/face/certificate_spec.rb +168 -1
  67. data/spec/unit/file_serving/fileset_spec.rb +1 -1
  68. data/spec/unit/file_serving/indirection_hooks_spec.rb +1 -1
  69. data/spec/unit/file_serving/metadata_spec.rb +151 -107
  70. data/spec/unit/indirector/certificate_request/ca_spec.rb +0 -3
  71. data/spec/unit/indirector/direct_file_server_spec.rb +10 -9
  72. data/spec/unit/indirector/file_metadata/file_spec.rb +6 -4
  73. data/spec/unit/indirector/request_spec.rb +13 -3
  74. data/spec/unit/indirector/resource/active_record_spec.rb +4 -10
  75. data/spec/unit/indirector/resource/ral_spec.rb +6 -4
  76. data/spec/unit/indirector/rest_spec.rb +5 -6
  77. data/spec/unit/network/handler/ca_spec.rb +86 -0
  78. data/spec/unit/parser/collector_spec.rb +7 -7
  79. data/spec/unit/parser/scope_spec.rb +20 -0
  80. data/spec/unit/provider/file/posix_spec.rb +226 -0
  81. data/spec/unit/provider/file/windows_spec.rb +136 -0
  82. data/spec/unit/provider/group/windows_adsi_spec.rb +7 -2
  83. data/spec/unit/provider/user/windows_adsi_spec.rb +36 -3
  84. data/spec/unit/resource/catalog_spec.rb +20 -10
  85. data/spec/unit/resource_spec.rb +55 -8
  86. data/spec/unit/ssl/certificate_authority/interface_spec.rb +97 -54
  87. data/spec/unit/ssl/certificate_authority_spec.rb +133 -23
  88. data/spec/unit/ssl/certificate_factory_spec.rb +90 -70
  89. data/spec/unit/ssl/certificate_request_spec.rb +62 -1
  90. data/spec/unit/ssl/certificate_spec.rb +20 -14
  91. data/spec/unit/ssl/host_spec.rb +52 -6
  92. data/spec/unit/type/file/content_spec.rb +4 -4
  93. data/spec/unit/type/file/group_spec.rb +34 -96
  94. data/spec/unit/type/file/mode_spec.rb +88 -0
  95. data/spec/unit/type/file/owner_spec.rb +32 -123
  96. data/spec/unit/type/file/source_spec.rb +120 -41
  97. data/spec/unit/type/file_spec.rb +1033 -753
  98. data/spec/unit/type_spec.rb +19 -1
  99. data/spec/unit/util/adsi_spec.rb +19 -0
  100. data/spec/unit/util/log/destinations_spec.rb +75 -0
  101. data/spec/unit/util/log_spec.rb +15 -0
  102. data/spec/unit/util/network_device/config_spec.rb +7 -0
  103. data/spec/unit/util/settings_spec.rb +10 -0
  104. data/spec/unit/util_spec.rb +126 -13
  105. data/test/language/functions.rb +0 -1
  106. data/test/language/snippets.rb +0 -9
  107. data/test/lib/puppettest/exetest.rb +1 -1
  108. data/test/lib/puppettest/servertest.rb +0 -1
  109. data/test/rails/rails.rb +0 -1
  110. data/test/ral/type/filesources.rb +0 -60
  111. metadata +13 -33
  112. data/lib/puppet/network/client.rb +0 -174
  113. data/lib/puppet/network/client/ca.rb +0 -56
  114. data/lib/puppet/network/client/file.rb +0 -6
  115. data/lib/puppet/network/client/proxy.rb +0 -27
  116. data/lib/puppet/network/client/report.rb +0 -26
  117. data/lib/puppet/network/client/runner.rb +0 -10
  118. data/lib/puppet/network/client/status.rb +0 -4
  119. data/lib/puppet/network/http_server.rb +0 -3
  120. data/lib/puppet/network/http_server/mongrel.rb +0 -130
  121. data/lib/puppet/network/http_server/webrick.rb +0 -155
  122. data/lib/puppet/network/xmlrpc/client.rb +0 -211
  123. data/lib/puppet/provider/file/win32.rb +0 -72
  124. data/lib/puppet/sslcertificates.rb +0 -146
  125. data/lib/puppet/sslcertificates/ca.rb +0 -375
  126. data/lib/puppet/sslcertificates/certificate.rb +0 -255
  127. data/lib/puppet/sslcertificates/inventory.rb +0 -38
  128. data/lib/puppet/sslcertificates/support.rb +0 -146
  129. data/spec/integration/network/client_spec.rb +0 -18
  130. data/spec/unit/network/xmlrpc/client_spec.rb +0 -172
  131. data/spec/unit/sslcertificates/ca_spec.rb +0 -106
  132. data/test/certmgr/certmgr.rb +0 -308
  133. data/test/certmgr/inventory.rb +0 -69
  134. data/test/certmgr/support.rb +0 -105
  135. data/test/network/client/ca.rb +0 -69
  136. data/test/network/client/dipper.rb +0 -34
  137. data/test/network/handler/ca.rb +0 -273
  138. data/test/network/server/mongrel_test.rb +0 -99
  139. data/test/network/server/webrick.rb +0 -111
  140. data/test/network/xmlrpc/client.rb +0 -45
@@ -1,6 +0,0 @@
1
- class Puppet::Network::Client::File < Puppet::Network::Client::ProxyClient
2
- @handler = Puppet::Network::Handler.handler(:fileserver)
3
- @drivername = :FileServer
4
- self.mkmethods
5
- end
6
-
@@ -1,27 +0,0 @@
1
- # unlike the other client classes (again, this design sucks) this class
2
- # is basically just a proxy class -- it calls its methods on the driver
3
- # and that's about it
4
- class Puppet::Network::Client::ProxyClient < Puppet::Network::Client
5
- def self.mkmethods
6
- interface = self.handler.interface
7
- namespace = interface.prefix
8
-
9
-
10
- interface.methods.each { |ary|
11
- method = ary[0]
12
- Puppet.debug "#{self}: defining #{namespace}.#{method}"
13
- define_method(method) { |*args|
14
- begin
15
- @driver.send(method, *args)
16
- rescue XMLRPC::FaultException => detail
17
- #Puppet.err "Could not call %s.%s: %s" %
18
- # [namespace, method, detail.faultString]
19
- #raise NetworkClientError,
20
- # "XMLRPC Error: #{detail.faultString}"
21
- raise NetworkClientError, detail.faultString
22
- end
23
- }
24
- }
25
- end
26
- end
27
-
@@ -1,26 +0,0 @@
1
- class Puppet::Network::Client::Report < Puppet::Network::Client
2
- @handler = Puppet::Network::Handler.handler(:report)
3
-
4
- def initialize(hash = {})
5
- hash[:Report] = self.class.handler.new if hash.include?(:Report)
6
-
7
- super(hash)
8
- end
9
-
10
- # Send our report. We get the transaction report and convert it to YAML
11
- # as appropriate.
12
- def report(transreport)
13
- report = YAML.dump(transreport)
14
-
15
- report = CGI.escape(report) unless self.local
16
-
17
- # Now send the report
18
- file = nil
19
- benchmark(:info, "Sent transaction report") do
20
- file = @driver.report(report)
21
- end
22
-
23
- file
24
- end
25
- end
26
-
@@ -1,10 +0,0 @@
1
- class Puppet::Network::Client::Runner < Puppet::Network::Client::ProxyClient
2
- self.mkmethods
3
-
4
- def initialize(hash = {})
5
- hash[:Runner] = self.class.handler.new if hash.include?(:Runner)
6
-
7
- super(hash)
8
- end
9
- end
10
-
@@ -1,4 +0,0 @@
1
- class Puppet::Network::Client::Status < Puppet::Network::Client::ProxyClient
2
- self.mkmethods
3
- end
4
-
@@ -1,3 +0,0 @@
1
- # Just a stub, so we can correctly scope other classes.
2
- module Puppet::Network::HTTPServer # :nodoc:
3
- end
@@ -1,130 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # File: 06-11-14-mongrel_xmlrpc.rb
3
- # Author: Manuel Holtgrewe <purestorm at ggnore.net>
4
- #
5
- # Copyright (c) 2006 Manuel Holtgrewe, 2007 Luke Kanies
6
- #
7
- # This file is based heavily on a file retrieved from
8
- # http://ttt.ggnore.net/2006/11/15/xmlrpc-with-mongrel-and-ruby-off-rails/
9
-
10
- require 'rubygems'
11
- require 'mongrel'
12
- require 'xmlrpc/server'
13
- require 'puppet/network/xmlrpc/server'
14
- require 'puppet/network/http_server'
15
- require 'puppet/network/client_request'
16
- require 'puppet/network/handler'
17
-
18
- require 'resolv'
19
-
20
- # This handler can be hooked into Mongrel to accept HTTP requests. After
21
- # checking whether the request itself is sane, the handler forwards it
22
- # to an internal instance of XMLRPC::BasicServer to process it.
23
- #
24
- # You can access the server by calling the Handler's "xmlrpc_server"
25
- # attribute accessor method and add XMLRPC handlers there. For example:
26
- #
27
- # <pre>
28
- # handler = XmlRpcHandler.new
29
- # handler.xmlrpc_server.add_handler("my.add") { |a, b| a.to_i + b.to_i }
30
- # </pre>
31
- module Puppet::Network
32
- class HTTPServer::Mongrel < ::Mongrel::HttpHandler
33
- attr_reader :xmlrpc_server
34
-
35
- def initialize(handlers)
36
- if Puppet[:debug]
37
- $mongrel_debug_client = true
38
- Puppet.debug 'Mongrel client debugging enabled. [$mongrel_debug_client = true].'
39
- end
40
- # Create a new instance of BasicServer. We are supposed to subclass it
41
- # but that does not make sense since we would not introduce any new
42
- # behaviour and we have to subclass Mongrel::HttpHandler so our handler
43
- # works for Mongrel.
44
- @xmlrpc_server = Puppet::Network::XMLRPCServer.new
45
- handlers.each do |name|
46
- unless handler = Puppet::Network::Handler.handler(name)
47
- raise ArgumentError, "Invalid handler #{name}"
48
- end
49
- @xmlrpc_server.add_handler(handler.interface, handler.new({}))
50
- end
51
- end
52
-
53
- # This method produces the same results as XMLRPC::CGIServer.serve
54
- # from Ruby's stdlib XMLRPC implementation.
55
- def process(request, response)
56
- # Make sure this has been a POST as required for XMLRPC.
57
- request_method = request.params[Mongrel::Const::REQUEST_METHOD] || Mongrel::Const::GET
58
- if request_method != "POST"
59
- response.start(405) { |head, out| out.write("Method Not Allowed") }
60
- return
61
- end
62
-
63
- # Make sure the user has sent text/xml data.
64
- request_mime = request.params["CONTENT_TYPE"] || "text/plain"
65
- if parse_content_type(request_mime).first != "text/xml"
66
- response.start(400) { |head, out| out.write("Bad Request") }
67
- return
68
- end
69
-
70
- # Make sure there is data in the body at all.
71
- length = request.params[Mongrel::Const::CONTENT_LENGTH].to_i
72
- if length <= 0
73
- response.start(411) { |head, out| out.write("Length Required") }
74
- return
75
- end
76
-
77
- # Check the body to be valid.
78
- if request.body.nil? or request.body.size != length
79
- response.start(400) { |head, out| out.write("Bad Request") }
80
- return
81
- end
82
-
83
- info = client_info(request)
84
-
85
- # All checks above passed through
86
- response.start(200) do |head, out|
87
- head["Content-Type"] = "text/xml; charset=utf-8"
88
- begin
89
- out.write(@xmlrpc_server.process(request.body, info))
90
- rescue => detail
91
- puts detail.backtrace
92
- raise
93
- end
94
- end
95
- end
96
-
97
- private
98
-
99
- def client_info(request)
100
- params = request.params
101
- ip = params["HTTP_X_FORWARDED_FOR"] ? params["HTTP_X_FORWARDED_FOR"].split(',').last.strip : params["REMOTE_ADDR"]
102
- # JJM #906 The following dn.match regular expression is forgiving
103
- # enough to match the two Distinguished Name string contents
104
- # coming from Apache, Pound or other reverse SSL proxies.
105
- if dn = params[Puppet[:ssl_client_header]] and dn_matchdata = dn.match(/^.*?CN\s*=\s*(.*)/)
106
- client = dn_matchdata[1].to_str
107
- valid = (params[Puppet[:ssl_client_verify_header]] == 'SUCCESS')
108
- else
109
- begin
110
- client = Resolv.getname(ip)
111
- rescue => detail
112
- Puppet.err "Could not resolve #{ip}: #{detail}"
113
- client = "unknown"
114
- end
115
- valid = false
116
- end
117
-
118
- info = Puppet::Network::ClientRequest.new(client, ip, valid)
119
-
120
- info
121
- end
122
-
123
- # Taken from XMLRPC::ParseContentType
124
- def parse_content_type(str)
125
- a, *b = str.split(";")
126
- return a.strip, *b
127
- end
128
- end
129
- end
130
-
@@ -1,155 +0,0 @@
1
- require 'puppet'
2
- require 'webrick'
3
- require 'webrick/https'
4
- require 'fcntl'
5
-
6
- require 'puppet/sslcertificates/support'
7
- require 'puppet/network/xmlrpc/webrick_servlet'
8
- require 'puppet/network/http_server'
9
- require 'puppet/network/client'
10
- require 'puppet/network/handler'
11
-
12
- module Puppet
13
- class ServerError < RuntimeError; end
14
- module Network
15
- # The old-school, pure ruby webrick server, which is the default serving
16
- # mechanism.
17
- class HTTPServer::WEBrick < WEBrick::HTTPServer
18
- include Puppet::SSLCertificates::Support
19
-
20
- # Read the CA cert and CRL and populate an OpenSSL::X509::Store
21
- # with them, with flags appropriate for checking client
22
- # certificates for revocation
23
- def x509store
24
- unless File.exist?(Puppet[:cacrl])
25
- # No CRL, no store needed
26
- return nil
27
- end
28
- crl = OpenSSL::X509::CRL.new(File.read(Puppet[:cacrl]))
29
- store = OpenSSL::X509::Store.new
30
- store.purpose = OpenSSL::X509::PURPOSE_ANY
31
- store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL|OpenSSL::X509::V_FLAG_CRL_CHECK if Puppet.settings[:certificate_revocation]
32
- raise Puppet::Error, "Could not find CA certificate" unless self.ca_cert
33
-
34
- store.add_file(Puppet[:localcacert])
35
- store.add_crl(crl)
36
- store
37
- end
38
-
39
- # Set up the http log.
40
- def httplog
41
- args = []
42
-
43
- # yuck; separate http logs
44
- file = nil
45
- Puppet.settings.use(:main, :ssl, Puppet[:name])
46
- if Puppet.run_mode.master?
47
- file = Puppet[:masterhttplog]
48
- else
49
- file = Puppet[:httplog]
50
- end
51
-
52
- # open the log manually to prevent file descriptor leak
53
- file_io = open(file, "a+")
54
- file_io.sync
55
- file_io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
56
-
57
- args << file_io
58
- args << WEBrick::Log::DEBUG if Puppet[:debug]
59
-
60
- log = WEBrick::Log.new(*args)
61
-
62
-
63
- log
64
- end
65
-
66
- # Create our server, yo.
67
- def initialize(hash = {})
68
- Puppet.info "Starting server for Puppet version #{Puppet.version}"
69
-
70
- if handlers = hash[:Handlers]
71
- handler_instances = setup_handlers(handlers)
72
- else
73
- raise ServerError, "A server must have handlers"
74
- end
75
-
76
- unless self.read_cert
77
- if ca = handler_instances.find { |handler| handler.is_a?(Puppet::Network::Handler.ca) }
78
- request_cert(ca)
79
- else
80
- raise Puppet::Error, "No certificate and no CA; cannot get cert"
81
- end
82
- end
83
-
84
- setup_webrick(hash)
85
-
86
- begin
87
- super(hash)
88
- rescue => detail
89
- puts detail.backtrace if Puppet[:trace]
90
- raise Puppet::Error, "Could not start WEBrick: #{detail}"
91
- end
92
-
93
- # make sure children don't inherit the sockets
94
- listeners.each { |sock|
95
- sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
96
- }
97
-
98
- Puppet.info "Listening on port #{hash[:Port]}"
99
-
100
- # this creates a new servlet for every connection,
101
- # but all servlets have the same list of handlers
102
- # thus, the servlets can have their own state -- passing
103
- # around the requests and such -- but the handlers
104
- # have a global state
105
-
106
- # mount has to be called after the server is initialized
107
- servlet = Puppet::Network::XMLRPC::WEBrickServlet.new( handler_instances)
108
- self.mount("/RPC2", servlet)
109
- end
110
-
111
- # Create a ca client to set up our cert for us.
112
- def request_cert(ca)
113
- client = Puppet::Network::Client.ca.new(:CA => ca)
114
- raise Puppet::Error, "Could get certificate" unless client.request_cert
115
- end
116
-
117
- # Create all of our handler instances.
118
- def setup_handlers(handlers)
119
- raise ServerError, "Handlers must have arguments" unless handlers.is_a?(Hash)
120
-
121
- handlers.collect { |handler, args|
122
- hclass = nil
123
- unless hclass = Puppet::Network::Handler.handler(handler)
124
- raise ServerError, "Invalid handler #{handler}"
125
- end
126
- hclass.new(args)
127
- }
128
- end
129
-
130
- # Handle all of the many webrick arguments.
131
- def setup_webrick(hash)
132
- hash[:Port] ||= Puppet[:masterport]
133
- hash[:Logger] ||= self.httplog
134
- hash[:AccessLog] ||= [
135
- [ self.httplog, WEBrick::AccessLog::COMMON_LOG_FORMAT ],
136
- [ self.httplog, WEBrick::AccessLog::REFERER_LOG_FORMAT ]
137
- ]
138
-
139
- hash[:SSLCertificateStore] = x509store
140
- hash[:SSLCertificate] = self.cert
141
- hash[:SSLPrivateKey] = self.key
142
- hash[:SSLStartImmediately] = true
143
- hash[:SSLEnable] = true
144
- hash[:SSLCACertificateFile] = Puppet[:localcacert]
145
- hash[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_PEER
146
- hash[:SSLCertName] = nil
147
-
148
- if addr = Puppet[:bindaddress] and addr != ""
149
- hash[:BindAddress] = addr
150
- end
151
- end
152
- end
153
- end
154
- end
155
-
@@ -1,211 +0,0 @@
1
- require 'puppet/sslcertificates'
2
- require 'puppet/network/http_pool'
3
- require 'openssl'
4
- require 'puppet/external/base64'
5
-
6
- require 'xmlrpc/client'
7
- require 'net/https'
8
- require 'yaml'
9
-
10
- module Puppet::Network
11
- class ClientError < Puppet::Error; end
12
- class XMLRPCClientError < Puppet::Error; end
13
- class XMLRPCClient < ::XMLRPC::Client
14
-
15
- attr_accessor :puppet_server, :puppet_port
16
- @clients = {}
17
-
18
- class << self
19
- include Puppet::Util
20
- include Puppet::Util::ClassGen
21
- end
22
-
23
- # Create a netclient for each handler
24
- def self.mkclient(handler)
25
- interface = handler.interface
26
- namespace = interface.prefix
27
-
28
- # Create a subclass for every client type. This is
29
- # so that all of the methods are on their own class,
30
- # so that their namespaces can define the same methods if
31
- # they want.
32
- constant = handler.name.to_s.capitalize
33
- name = namespace.downcase
34
- newclient = genclass(name, :hash => @clients, :constant => constant)
35
-
36
- interface.methods.each { |ary|
37
- method = ary[0]
38
- newclient.send(:define_method,method) { |*args|
39
- make_rpc_call(namespace, method, *args)
40
- }
41
- }
42
-
43
- newclient
44
- end
45
-
46
- def self.handler_class(handler)
47
- @clients[handler] || self.mkclient(handler)
48
- end
49
-
50
- class ErrorHandler
51
- def initialize(&block)
52
- singleton_class.define_method(:execute, &block)
53
- end
54
- end
55
-
56
- # Use a class variable so all subclasses have access to it.
57
- @@error_handlers = {}
58
-
59
- def self.error_handler(exception)
60
- if handler = @@error_handlers[exception.class]
61
- return handler
62
- else
63
- return @@error_handlers[:default]
64
- end
65
- end
66
-
67
- def self.handle_error(*exceptions, &block)
68
- handler = ErrorHandler.new(&block)
69
-
70
- exceptions.each do |exception|
71
- @@error_handlers[exception] = handler
72
- end
73
- end
74
-
75
- handle_error(OpenSSL::SSL::SSLError) do |client, detail, namespace, method|
76
- if detail.message =~ /bad write retry/
77
- Puppet.warning "Transient SSL write error; restarting connection and retrying"
78
- client.recycle_connection
79
- return :retry
80
- end
81
- ["certificate verify failed", "hostname was not match", "hostname not match"].each do |str|
82
- Puppet.warning "Certificate validation failed; consider using the certname configuration option" if detail.message.include?(str)
83
- end
84
- raise XMLRPCClientError, "Certificates were not trusted: #{detail}"
85
- end
86
-
87
- handle_error(:default) do |client, detail, namespace, method|
88
- if detail.message.to_s =~ /^Wrong size\. Was \d+, should be \d+$/
89
- Puppet.warning "XMLRPC returned wrong size. Retrying."
90
- return :retry
91
- end
92
- Puppet.err "Could not call #{namespace}.#{method}: #{detail.inspect}"
93
- error = XMLRPCClientError.new(detail.to_s)
94
- error.set_backtrace detail.backtrace
95
- raise error
96
- end
97
-
98
- handle_error(OpenSSL::SSL::SSLError) do |client, detail, namespace, method|
99
- if detail.message =~ /bad write retry/
100
- Puppet.warning "Transient SSL write error; restarting connection and retrying"
101
- client.recycle_connection
102
- return :retry
103
- end
104
- ["certificate verify failed", "hostname was not match", "hostname not match"].each do |str|
105
- Puppet.warning "Certificate validation failed; consider using the certname configuration option" if detail.message.include?(str)
106
- end
107
- raise XMLRPCClientError, "Certificates were not trusted: #{detail}"
108
- end
109
-
110
- handle_error(::XMLRPC::FaultException) do |client, detail, namespace, method|
111
- raise XMLRPCClientError, detail.faultString
112
- end
113
-
114
- handle_error(Errno::ECONNREFUSED) do |client, detail, namespace, method|
115
- msg = "Could not connect to #{client.host} on port #{client.port}"
116
- raise XMLRPCClientError, msg
117
- end
118
-
119
- handle_error(SocketError) do |client, detail, namespace, method|
120
- Puppet.err "Could not find server #{@host}: #{detail}"
121
- error = XMLRPCClientError.new("Could not find server #{client.host}")
122
- error.set_backtrace detail.backtrace
123
- raise error
124
- end
125
-
126
- handle_error(Errno::EPIPE, EOFError) do |client, detail, namespace, method|
127
- Puppet.info "Other end went away; restarting connection and retrying"
128
- client.recycle_connection
129
- return :retry
130
- end
131
-
132
- handle_error(Timeout::Error) do |client, detail, namespace, method|
133
- Puppet.err "Connection timeout calling #{namespace}.#{method}: #{detail}"
134
- error = XMLRPCClientError.new("Connection Timeout")
135
- error.set_backtrace(detail.backtrace)
136
- raise error
137
- end
138
-
139
- def make_rpc_call(namespace, method, *args)
140
- Puppet.debug "Calling #{namespace}.#{method}"
141
- begin
142
- call("#{namespace}.#{method}",*args)
143
- rescue SystemExit,NoMemoryError
144
- raise
145
- rescue Exception => detail
146
- retry if self.class.error_handler(detail).execute(self, detail, namespace, method) == :retry
147
- end
148
- ensure
149
- http.finish if http.started?
150
- end
151
-
152
- def http
153
- @http ||= Puppet::Network::HttpPool.http_instance(host, port, true)
154
- end
155
-
156
- attr_reader :host, :port
157
-
158
- def initialize(hash = {})
159
- hash[:Path] ||= "/RPC2"
160
- hash[:Server] ||= Puppet[:server]
161
- hash[:Port] ||= Puppet[:masterport]
162
- hash[:HTTPProxyHost] ||= Puppet[:http_proxy_host]
163
- hash[:HTTPProxyPort] ||= Puppet[:http_proxy_port]
164
-
165
- if "none" == hash[:HTTPProxyHost]
166
- hash[:HTTPProxyHost] = nil
167
- hash[:HTTPProxyPort] = nil
168
- end
169
-
170
-
171
- super(
172
-
173
- hash[:Server],
174
- hash[:Path],
175
- hash[:Port],
176
- hash[:HTTPProxyHost],
177
- hash[:HTTPProxyPort],
178
-
179
- nil, # user
180
- nil, # password
181
- true, # use_ssl
182
- Puppet[:configtimeout] # use configured timeout (#1176)
183
- )
184
- @http = Puppet::Network::HttpPool.http_instance(@host, @port)
185
- end
186
-
187
- # Get rid of our existing connection, replacing it with a new one.
188
- # This should only happen if we lose our connection somehow (e.g., an EPIPE)
189
- # or we've just downloaded certs and we need to create new http instances
190
- # with the certs added.
191
- def recycle_connection
192
- http.finish if http.started?
193
- @http = nil
194
- self.http # force a new one
195
- end
196
-
197
- def start
198
- @http.start unless @http.started?
199
- rescue => detail
200
- Puppet.err "Could not connect to server: #{detail}"
201
- end
202
-
203
- def local
204
- false
205
- end
206
-
207
- def local?
208
- false
209
- end
210
- end
211
- end