puppet 6.11.1 → 6.12.0

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +1 -1
  3. data/Gemfile +1 -0
  4. data/Gemfile.lock +16 -16
  5. data/README.md +1 -1
  6. data/ext/build_defaults.yaml +1 -0
  7. data/ext/windows/service/daemon.rb +22 -17
  8. data/lib/puppet/concurrent.rb +2 -0
  9. data/lib/puppet/concurrent/lock.rb +16 -0
  10. data/lib/puppet/concurrent/synchronized.rb +15 -0
  11. data/lib/puppet/concurrent/thread_local_singleton.rb +14 -0
  12. data/lib/puppet/configurer.rb +45 -31
  13. data/lib/puppet/defaults.rb +42 -3
  14. data/lib/puppet/environments.rb +3 -0
  15. data/lib/puppet/error.rb +9 -1
  16. data/lib/puppet/forge.rb +3 -3
  17. data/lib/puppet/forge/errors.rb +2 -2
  18. data/lib/puppet/forge/repository.rb +30 -86
  19. data/lib/puppet/functions/camelcase.rb +2 -2
  20. data/lib/puppet/functions/epp.rb +4 -4
  21. data/lib/puppet/functions/find_file.rb +9 -9
  22. data/lib/puppet/functions/find_template.rb +63 -0
  23. data/lib/puppet/functions/inline_epp.rb +5 -5
  24. data/lib/puppet/http.rb +2 -0
  25. data/lib/puppet/http/client.rb +89 -17
  26. data/lib/puppet/http/resolver.rb +14 -1
  27. data/lib/puppet/http/resolver/server_list.rb +38 -0
  28. data/lib/puppet/http/resolver/settings.rb +3 -2
  29. data/lib/puppet/http/resolver/srv.rb +10 -4
  30. data/lib/puppet/http/service.rb +32 -0
  31. data/lib/puppet/http/service/ca.rb +11 -10
  32. data/lib/puppet/http/service/report.rb +40 -0
  33. data/lib/puppet/http/session.rb +11 -32
  34. data/lib/puppet/network/http/base_pool.rb +13 -0
  35. data/lib/puppet/node/environment.rb +13 -7
  36. data/lib/puppet/pal/pal_impl.rb +5 -0
  37. data/lib/puppet/parser/functions/epp.rb +3 -3
  38. data/lib/puppet/parser/functions/inline_epp.rb +5 -5
  39. data/lib/puppet/pops/evaluator/runtime3_support.rb +1 -1
  40. data/lib/puppet/pops/lookup/invocation.rb +10 -3
  41. data/lib/puppet/pops/model/pn_transformer.rb +5 -9
  42. data/lib/puppet/pops/parser/evaluating_parser.rb +3 -4
  43. data/lib/puppet/pops/serialization/json_path.rb +3 -3
  44. data/lib/puppet/pops/time/timespan.rb +3 -5
  45. data/lib/puppet/pops/types/string_converter.rb +6 -9
  46. data/lib/puppet/pops/types/type_calculator.rb +6 -10
  47. data/lib/puppet/pops/types/type_formatter.rb +9 -11
  48. data/lib/puppet/pops/types/type_parser.rb +3 -3
  49. data/lib/puppet/provider/package/portage.rb +3 -3
  50. data/lib/puppet/provider/package_targetable.rb +5 -4
  51. data/lib/puppet/provider/service/systemd.rb +1 -1
  52. data/lib/puppet/provider/user/hpux.rb +1 -1
  53. data/lib/puppet/runtime.rb +1 -0
  54. data/lib/puppet/ssl/ssl_provider.rb +20 -0
  55. data/lib/puppet/transaction.rb +33 -11
  56. data/lib/puppet/type.rb +1 -1
  57. data/lib/puppet/type/file/data_sync.rb +5 -1
  58. data/lib/puppet/type/group.rb +3 -2
  59. data/lib/puppet/type/user.rb +3 -2
  60. data/lib/puppet/util.rb +34 -11
  61. data/lib/puppet/util/logging.rb +30 -18
  62. data/lib/puppet/util/windows/adsi.rb +48 -18
  63. data/lib/puppet/version.rb +1 -1
  64. data/lib/puppet/x509/cert_provider.rb +9 -5
  65. data/locales/puppet.pot +155 -141
  66. data/man/man5/puppet.conf.5 +33 -3
  67. data/man/man8/puppet-agent.8 +1 -1
  68. data/man/man8/puppet-apply.8 +1 -1
  69. data/man/man8/puppet-catalog.8 +1 -1
  70. data/man/man8/puppet-config.8 +1 -1
  71. data/man/man8/puppet-describe.8 +1 -1
  72. data/man/man8/puppet-device.8 +1 -1
  73. data/man/man8/puppet-doc.8 +1 -1
  74. data/man/man8/puppet-epp.8 +1 -1
  75. data/man/man8/puppet-facts.8 +1 -1
  76. data/man/man8/puppet-filebucket.8 +1 -1
  77. data/man/man8/puppet-generate.8 +1 -1
  78. data/man/man8/puppet-help.8 +1 -1
  79. data/man/man8/puppet-key.8 +1 -1
  80. data/man/man8/puppet-lookup.8 +1 -1
  81. data/man/man8/puppet-man.8 +1 -1
  82. data/man/man8/puppet-module.8 +1 -1
  83. data/man/man8/puppet-node.8 +1 -1
  84. data/man/man8/puppet-parser.8 +1 -1
  85. data/man/man8/puppet-plugin.8 +1 -1
  86. data/man/man8/puppet-report.8 +1 -1
  87. data/man/man8/puppet-resource.8 +1 -1
  88. data/man/man8/puppet-script.8 +1 -1
  89. data/man/man8/puppet-ssl.8 +1 -1
  90. data/man/man8/puppet-status.8 +1 -1
  91. data/man/man8/puppet.8 +2 -2
  92. data/spec/fixtures/unit/forge/bacula.json +76 -0
  93. data/spec/integration/http/client_spec.rb +144 -0
  94. data/spec/integration/module_tool/forge_spec.rb +64 -0
  95. data/spec/lib/puppet_spec/https.rb +5 -3
  96. data/spec/spec_helper.rb +6 -2
  97. data/spec/unit/concurrent/lock_spec.rb +29 -0
  98. data/spec/unit/configurer_spec.rb +394 -399
  99. data/spec/unit/defaults_spec.rb +15 -4
  100. data/spec/unit/forge/errors_spec.rb +1 -1
  101. data/spec/unit/forge/forge_spec.rb +12 -54
  102. data/spec/unit/forge/module_release_spec.rb +19 -6
  103. data/spec/unit/forge/repository_spec.rb +63 -157
  104. data/spec/unit/forge_spec.rb +46 -116
  105. data/spec/unit/functions/find_template_spec.rb +69 -0
  106. data/spec/unit/http/client_spec.rb +138 -6
  107. data/spec/unit/http/resolver_spec.rb +49 -12
  108. data/spec/unit/http/service/ca_spec.rb +56 -5
  109. data/spec/unit/http/service/report_spec.rb +100 -0
  110. data/spec/unit/http/service_spec.rb +20 -0
  111. data/spec/unit/http/session_spec.rb +53 -18
  112. data/spec/unit/network/http/connection_spec.rb +0 -1
  113. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +8 -3
  114. data/spec/unit/provider/package/portage_spec.rb +4 -4
  115. data/spec/unit/provider/package_targetable_spec.rb +60 -0
  116. data/spec/unit/provider/user/hpux_spec.rb +2 -2
  117. data/spec/unit/ssl/ssl_provider_spec.rb +71 -0
  118. data/spec/unit/transaction_spec.rb +46 -0
  119. data/spec/unit/type/file/content_spec.rb +9 -3
  120. data/spec/unit/util/log_spec.rb +0 -138
  121. data/spec/unit/util/logging_spec.rb +200 -0
  122. data/spec/unit/util/windows/adsi_spec.rb +51 -0
  123. data/spec/unit/x509/cert_provider_spec.rb +24 -4
  124. data/tasks/manpages.rake +1 -0
  125. metadata +24 -5
  126. data/spec/lib/puppet_spec/validators.rb +0 -37
@@ -1,3 +1,5 @@
1
+ require 'puppet/concurrent/synchronized'
2
+
1
3
  # @api private
2
4
  module Puppet::Environments
3
5
 
@@ -293,6 +295,7 @@ module Puppet::Environments
293
295
 
294
296
  class Cached
295
297
  include EnvironmentLoader
298
+ include Puppet::Concurrent::Synchronized
296
299
 
297
300
  class DefaultCacheExpirationService
298
301
  def created(env)
@@ -12,7 +12,7 @@ module Puppet
12
12
  # This module implements logging with a filename and line number. Use this
13
13
  # for errors that need to report a location in a non-ruby file that we
14
14
  # parse.
15
- attr_accessor :line, :file, :pos
15
+ attr_accessor :line, :file, :pos, :puppetstack
16
16
 
17
17
  # May be called with 3 arguments for message, file, line, and exception, or
18
18
  # 4 args including the position on the line.
@@ -22,10 +22,18 @@ module Puppet
22
22
  original = pos
23
23
  pos = nil
24
24
  end
25
+
25
26
  super(message, original)
27
+
26
28
  @file = file unless (file.is_a?(String) && file.empty?)
27
29
  @line = line
28
30
  @pos = pos
31
+
32
+ if original && original.respond_to?(:puppetstack)
33
+ @puppetstack = original.puppetstack
34
+ else
35
+ @puppetstack = Puppet::Pops::PuppetStack.stacktrace()
36
+ end
29
37
  end
30
38
 
31
39
  def to_s
@@ -65,7 +65,7 @@ class Puppet::Forge < SemanticPuppet::Dependency::Source
65
65
  # make_http_request URI encodes parameters
66
66
  response = make_http_request(uri)
67
67
 
68
- if response.code == '200'
68
+ if response.code == 200
69
69
  result = Puppet::Util::Json.load(response.body)
70
70
  uri = decode_uri(result['pagination']['next'])
71
71
  matches.concat result['results']
@@ -102,7 +102,7 @@ class Puppet::Forge < SemanticPuppet::Dependency::Source
102
102
  # make_http_request URI encodes parameters
103
103
  response = make_http_request(uri)
104
104
 
105
- if response.code == '200'
105
+ if response.code == 200
106
106
  response = Puppet::Util::Json.load(response.body)
107
107
  else
108
108
  raise ResponseError.new(:uri => URI.parse(@host).merge(uri), :response => response)
@@ -207,7 +207,7 @@ class Puppet::Forge < SemanticPuppet::Dependency::Source
207
207
  def download(uri, destination)
208
208
  response = @source.make_http_request(uri, destination)
209
209
  destination.flush and destination.close
210
- unless response.code == '200'
210
+ unless response.code == 200
211
211
  raise Puppet::Forge::Errors::ResponseError.new(:uri => uri, :response => response)
212
212
  end
213
213
  end
@@ -74,12 +74,12 @@ module Puppet::Forge::Errors
74
74
  # @option options [String] :uri The URI that failed
75
75
  # @option options [String] :input The user's input (e.g. module name)
76
76
  # @option options [String] :message Error from the API response (optional)
77
- # @option options [Net::HTTPResponse] :response The original HTTP response
77
+ # @option options [Puppet::HTTP::Response] :response The original HTTP response
78
78
  def initialize(options)
79
79
  @uri = options[:uri]
80
80
  @message = options[:message]
81
81
  response = options[:response]
82
- @response = "#{response.code} #{response.message.strip}"
82
+ @response = "#{response.code} #{response.reason.strip}"
83
83
 
84
84
  begin
85
85
  body = Puppet::Util::Json.load(response.body)
@@ -15,24 +15,6 @@ class Puppet::Forge
15
15
 
16
16
  attr_reader :uri, :cache
17
17
 
18
- # List of Net::HTTP exceptions to catch
19
- NET_HTTP_EXCEPTIONS = [
20
- EOFError,
21
- Errno::ECONNABORTED,
22
- Errno::ECONNREFUSED,
23
- Errno::ECONNRESET,
24
- Errno::EINVAL,
25
- Errno::ETIMEDOUT,
26
- Net::HTTPBadResponse,
27
- Net::HTTPHeaderSyntaxError,
28
- Net::ProtocolError,
29
- SocketError,
30
- ]
31
-
32
- if Puppet.features.zlib?
33
- NET_HTTP_EXCEPTIONS << Zlib::GzipFile::Error
34
- end
35
-
36
18
  # Instantiate a new repository instance rooted at the +url+.
37
19
  # The library will report +for_agent+ in the User-Agent to the repository.
38
20
  def initialize(host, for_agent)
@@ -40,13 +22,40 @@ class Puppet::Forge
40
22
  @agent = for_agent
41
23
  @cache = Cache.new(self)
42
24
  @uri = URI.parse(host)
25
+
26
+ ssl_provider = Puppet::SSL::SSLProvider.new
27
+ @ssl_context = ssl_provider.create_system_context(cacerts: [])
43
28
  end
44
29
 
45
30
  # Return a Net::HTTPResponse read for this +path+.
46
31
  def make_http_request(path, io = nil)
47
- request = get_request_object(@uri.path.chomp('/')+path)
48
- Puppet.debug "HTTP GET #{@host}#{request.path}"
49
- return read_response(request, io)
32
+ raise ArgumentError, "Path must start with forward slash" unless path.start_with?('/')
33
+ begin
34
+ str = @uri.to_s
35
+ str.chomp!('/')
36
+ str += Puppet::Util.uri_encode(path)
37
+ uri = URI(str)
38
+
39
+ headers = { "User-Agent" => user_agent }
40
+ user = nil
41
+ password = nil
42
+
43
+ if forge_authorization
44
+ headers["Authorization"] = forge_authorization
45
+ elsif @uri.user && @uri.password
46
+ user = @uri.user
47
+ password = @uri.password
48
+ end
49
+
50
+ http = Puppet.runtime['http']
51
+ response = http.get(uri, headers: headers, user: user, password: password, ssl_context: @ssl_context)
52
+ io.write(response.body) if io.respond_to?(:write)
53
+ response
54
+ rescue Puppet::SSL::CertVerifyError => e
55
+ raise SSLVerifyError.new(:uri => @uri.to_s, :original => e.cause)
56
+ rescue => e
57
+ raise CommunicationError.new(:uri => @uri.to_s, :original => e)
58
+ end
50
59
  end
51
60
 
52
61
  def forge_authorization
@@ -57,71 +66,6 @@ class Puppet::Forge
57
66
  end
58
67
  end
59
68
 
60
- # responsible for properly encoding a URI
61
- def get_request_object(path)
62
- headers = {
63
- "User-Agent" => user_agent,
64
- }
65
-
66
- if Puppet.features.zlib?
67
- headers = headers.merge({
68
- "Accept-Encoding" => Puppet::Network::HTTP::Compression::ACCEPT_ENCODING
69
- })
70
- end
71
-
72
- if forge_authorization
73
- headers = headers.merge({"Authorization" => forge_authorization})
74
- end
75
-
76
- request = Net::HTTP::Get.new(Puppet::Util.uri_encode(path), headers)
77
-
78
- unless @uri.user.nil? || @uri.password.nil? || forge_authorization
79
- request.basic_auth(@uri.user, @uri.password)
80
- end
81
-
82
- return request
83
- end
84
-
85
- # Return a Net::HTTPResponse read from this HTTPRequest +request+.
86
- #
87
- # @param request [Net::HTTPRequest] request to make
88
- # @return [Net::HTTPResponse] response from request
89
- # @raise [Puppet::Forge::Errors::CommunicationError] if there is a network
90
- # related error
91
- # @raise [Puppet::Forge::Errors::SSLVerifyError] if there is a problem
92
- # verifying the remote SSL certificate
93
- def read_response(request, io = nil)
94
- http_object = Puppet::Util::HttpProxy.get_http_object(uri)
95
-
96
- http_object.start do |http|
97
- response = http.request(request)
98
-
99
- if Puppet.features.zlib?
100
- if response && response.key?("content-encoding")
101
- case response["content-encoding"]
102
- when "gzip"
103
- response.body = Zlib::GzipReader.new(StringIO.new(response.read_body), :encoding => "ASCII-8BIT").read
104
- response.delete("content-encoding")
105
- when "deflate"
106
- response.body = Zlib::Inflate.inflate(response.read_body)
107
- response.delete("content-encoding")
108
- end
109
- end
110
- end
111
-
112
- io.write(response.body) if io.respond_to? :write
113
- response
114
- end
115
- rescue *NET_HTTP_EXCEPTIONS => e
116
- raise CommunicationError.new(:uri => @uri.to_s, :original => e)
117
- rescue OpenSSL::SSL::SSLError => e
118
- if e.message =~ /certificate verify failed/
119
- raise SSLVerifyError.new(:uri => @uri.to_s, :original => e)
120
- else
121
- raise e
122
- end
123
- end
124
-
125
69
  # Return the local file name containing the data downloaded from the
126
70
  # repository at +release+ (e.g. "myuser-mymodule").
127
71
  def retrieve(release)
@@ -23,8 +23,8 @@
23
23
  #
24
24
  # @example Camelcase of strings in an Array
25
25
  # ```puppet
26
- # ['abc_def', 'bcd_xyz'].capitalize()
27
- # capitalize(['abc_def', 'bcd_xyz'])
26
+ # ['abc_def', 'bcd_xyz'].camelcase()
27
+ # camelcase(['abc_def', 'bcd_xyz'])
28
28
  # ```
29
29
  # Would both result in `['AbcDef', 'BcdXyz']`
30
30
  #
@@ -6,12 +6,12 @@
6
6
  # The first argument to this function should be a `<MODULE NAME>/<TEMPLATE FILE>`
7
7
  # reference, which loads `<TEMPLATE FILE>` from `<MODULE NAME>`'s `templates`
8
8
  # directory. In most cases, the last argument is optional; if used, it should be a
9
- # [hash](/puppet/latest/reference/lang_data_hash.html) that contains parameters to
9
+ # [hash](https://puppet.com/docs/puppet/latest/lang_data_hash.html) that contains parameters to
10
10
  # pass to the template.
11
11
  #
12
- # - See the [template](/puppet/latest/reference/lang_template.html) documentation
13
- # for general template usage information.
14
- # - See the [EPP syntax](/puppet/latest/reference/lang_template_epp.html)
12
+ # - See the [template](https://puppet.com/docs/puppet/latest/lang_template.html)
13
+ # documentation for general template usage information.
14
+ # - See the [EPP syntax](https://puppet.com/docs/puppet/latest/lang_template_epp.html)
15
15
  # documentation for examples of EPP.
16
16
  #
17
17
  # For example, to call the apache module's `templates/vhost/_docroot.epp`
@@ -1,19 +1,19 @@
1
1
  # Finds an existing file from a module and returns its path.
2
2
  #
3
- # The argument to this function should be a String as a `<MODULE NAME>/<FILE>`
4
- # reference, which will search for `<FILE>` relative to a module's `files`
3
+ # This function accepts an argument that is a String as a `<MODULE NAME>/<FILE>`
4
+ # reference, which searches for `<FILE>` relative to a module's `files`
5
5
  # directory. (For example, the reference `mysql/mysqltuner.pl` will search for the
6
6
  # file `<MODULES DIRECTORY>/mysql/files/mysqltuner.pl`.)
7
7
  #
8
8
  # This function can also accept:
9
- #
10
- # * An absolute String path, which will check for the existence of a file from anywhere on disk.
11
- # * Multiple String arguments, which will return the path of the **first** file
12
- # found, skipping non existing files.
13
- # * An array of string paths, which will return the path of the **first** file
14
- # found from the given paths in the array, skipping non existing files.
15
9
  #
16
- # The function returns `undef` if none of the given paths were found
10
+ # * An absolute String path, which checks for the existence of a file from anywhere on disk.
11
+ # * Multiple String arguments, which returns the path of the **first** file
12
+ # found, skipping nonexistent files.
13
+ # * An array of string paths, which returns the path of the **first** file
14
+ # found from the given paths in the array, skipping nonexistent files.
15
+ #
16
+ # The function returns `undef` if none of the given paths were found.
17
17
  #
18
18
  # @since 4.8.0
19
19
  #
@@ -0,0 +1,63 @@
1
+ # Finds an existing template from a module and returns its path.
2
+ #
3
+ # This function accepts an argument that is a String as a `<MODULE NAME>/<TEMPLATE>`
4
+ # reference, which searches for `<TEMPLATE>` relative to a module's `templates`
5
+ # directory on the master. (For example, the reference `mymod/secret.conf.epp`
6
+ # will search for the file `<MODULES DIRECTORY>/mymod/templates/secret.conf.epp`.)
7
+ #
8
+ # The primary use case is for agent-side template rendering with late-bound variables
9
+ # resolved, such as from secret stores inaccessible to the master, such as
10
+ #
11
+ # ```
12
+ # $variables = {
13
+ # 'password' => Deferred('vault_lookup::lookup',
14
+ # ['secret/mymod', 'https://vault.example.com:8200']),
15
+ # }
16
+ #
17
+ # # compile the template source into the catalog
18
+ # file { '/etc/secrets.conf':
19
+ # ensure => file,
20
+ # content => Deferred('inline_epp',
21
+ # [find_template('mymod/secret.conf.epp').file, $variables]),
22
+ # }
23
+ # ```
24
+ #
25
+ #
26
+ #
27
+ # This function can also accept:
28
+ #
29
+ # * An absolute String path, which checks for the existence of a template from anywhere on disk.
30
+ # * Multiple String arguments, which returns the path of the **first** template
31
+ # found, skipping nonexistent files.
32
+ # * An array of string paths, which returns the path of the **first** template
33
+ # found from the given paths in the array, skipping nonexistent files.
34
+ #
35
+ # The function returns `undef` if none of the given paths were found.
36
+ #
37
+ # @since 6.x
38
+ #
39
+ Puppet::Functions.create_function(:find_template, Puppet::Functions::InternalFunction) do
40
+ dispatch :find_template do
41
+ scope_param
42
+ repeated_param 'String', :paths
43
+ end
44
+
45
+ dispatch :find_template_array do
46
+ scope_param
47
+ repeated_param 'Array[String]', :paths_array
48
+ end
49
+
50
+ def find_template_array(scope, array)
51
+ find_template(scope, *array)
52
+ end
53
+
54
+ def find_template(scope, *args)
55
+ args.each do |file|
56
+ found = Puppet::Parser::Files.find_template(file, scope.compiler.environment)
57
+ if found && Puppet::FileSystem.exist?(found)
58
+ return found
59
+ end
60
+ end
61
+ nil
62
+ end
63
+ end
@@ -5,12 +5,12 @@
5
5
  #
6
6
  # The first argument to this function should be a string containing an EPP
7
7
  # template. In most cases, the last argument is optional; if used, it should be a
8
- # [hash](/puppet/latest/reference/lang_data_hash.html) that contains parameters to
8
+ # [hash](https://puppet.com/docs/puppet/latest/lang_data_hash.html) that contains parameters to
9
9
  # pass to the template.
10
10
  #
11
- # - See the [template](/puppet/latest/reference/lang_template.html) documentation
12
- # for general template usage information.
13
- # - See the [EPP syntax](/puppet/latest/reference/lang_template_epp.html)
11
+ # - See the [template](https://puppet.com/docs/puppet/latest/lang_template.html)
12
+ # documentation for general template usage information.
13
+ # - See the [EPP syntax](https://puppet.com/docs/puppet/latest/lang_template_epp.html)
14
14
  # documentation for examples of EPP.
15
15
  #
16
16
  # For example, to evaluate an inline EPP template and pass it the `docroot` and
@@ -28,7 +28,7 @@
28
28
  # `inline_epp` function fails to pass any required parameter.
29
29
  #
30
30
  # An inline EPP template should be written as a single-quoted string or
31
- # [heredoc](/puppet/latest/reference/lang_data_string.html#heredocs).
31
+ # [heredoc](https://puppet.com/docs/puppet/latest/lang_data_string.html#heredocs).
32
32
  # A double-quoted string is subject to expression interpolation before the string
33
33
  # is parsed as an EPP template.
34
34
  #
@@ -18,8 +18,10 @@ module Puppet
18
18
  require 'puppet/http/response'
19
19
  require 'puppet/http/service'
20
20
  require 'puppet/http/service/ca'
21
+ require 'puppet/http/service/report'
21
22
  require 'puppet/http/session'
22
23
  require 'puppet/http/resolver'
24
+ require 'puppet/http/resolver/server_list'
23
25
  require 'puppet/http/resolver/settings'
24
26
  require 'puppet/http/resolver/srv'
25
27
  require 'puppet/http/client'
@@ -16,19 +16,31 @@ class Puppet::HTTP::Client
16
16
  end
17
17
 
18
18
  def connect(uri, ssl_context: nil, &block)
19
+ start = Time.now
19
20
  ctx = ssl_context ? ssl_context : default_ssl_context
20
21
  site = Puppet::Network::HTTP::Site.from_uri(uri)
21
22
  verifier = Puppet::SSL::Verifier.new(site.host, ctx)
23
+ connected = false
22
24
 
23
25
  @pool.with_connection(site, verifier) do |http|
26
+ connected = true
24
27
  if block_given?
25
- handle_post_connect(uri, http, &block)
28
+ yield http
26
29
  end
27
30
  end
31
+ rescue Net::OpenTimeout => e
32
+ raise_error(_("Request to %{uri} timed out connect operation after %{elapsed} seconds") % {uri: uri, elapsed: elapsed(start)}, e, connected)
33
+ rescue Net::ReadTimeout => e
34
+ raise_error(_("Request to %{uri} timed out read operation after %{elapsed} seconds") % {uri: uri, elapsed: elapsed(start)}, e, connected)
35
+ rescue EOFError => e
36
+ raise_error(_("Request to %{uri} interrupted after %{elapsed} seconds") % {uri: uri, elapsed: elapsed(start)}, e, connected)
37
+ rescue Puppet::SSL::SSLError
38
+ raise
28
39
  rescue Puppet::HTTP::HTTPError
29
40
  raise
30
41
  rescue => e
31
- raise Puppet::HTTP::ConnectionError.new(_("Failed to connect to %{uri}: %{message}") % {uri: uri, message: e.message}, e)
42
+ raise_error(_("Request to %{uri} failed after %{elapsed} seconds: %{message}") %
43
+ {uri: uri, elapsed: elapsed(start), message: e.message}, e, connected)
32
44
  end
33
45
 
34
46
  def get(url, headers: {}, params: {}, ssl_context: nil, user: nil, password: nil, &block)
@@ -49,6 +61,20 @@ class Puppet::HTTP::Client
49
61
  end
50
62
  end
51
63
 
64
+ def head(url, headers: {}, params: {}, ssl_context: nil, user: nil, password: nil)
65
+ query = encode_params(params)
66
+ unless query.empty?
67
+ url = url.dup
68
+ url.query = query
69
+ end
70
+
71
+ request = Net::HTTP::Head.new(url, @default_headers.merge(headers))
72
+
73
+ execute_streaming(request, ssl_context: ssl_context, user: user, password: password) do |response|
74
+ response.read_body
75
+ end
76
+ end
77
+
52
78
  def put(url, headers: {}, params: {}, content_type:, body:, ssl_context: nil, user: nil, password: nil)
53
79
  query = encode_params(params)
54
80
  unless query.empty?
@@ -66,6 +92,41 @@ class Puppet::HTTP::Client
66
92
  end
67
93
  end
68
94
 
95
+ def post(url, headers: {}, params: {}, content_type:, body:, ssl_context: nil, user: nil, password: nil, &block)
96
+ query = encode_params(params)
97
+ unless query.empty?
98
+ url = url.dup
99
+ url.query = query
100
+ end
101
+
102
+ request = Net::HTTP::Post.new(url, @default_headers.merge(headers))
103
+ request.body = body
104
+ request['Content-Length'] = body.bytesize
105
+ request['Content-Type'] = content_type
106
+
107
+ execute_streaming(request, ssl_context: ssl_context, user: user, password: password) do |response|
108
+ if block_given?
109
+ yield response
110
+ else
111
+ response.read_body
112
+ end
113
+ end
114
+ end
115
+
116
+ def delete(url, headers: {}, params: {}, ssl_context: nil, user: nil, password: nil)
117
+ query = encode_params(params)
118
+ unless query.empty?
119
+ url = url.dup
120
+ url.query = query
121
+ end
122
+
123
+ request = Net::HTTP::Delete.new(url, @default_headers.merge(headers))
124
+
125
+ execute_streaming(request, ssl_context: ssl_context, user: user, password: password) do |response|
126
+ response.read_body
127
+ end
128
+ end
129
+
69
130
  def close
70
131
  @pool.close
71
132
  end
@@ -116,23 +177,18 @@ class Puppet::HTTP::Client
116
177
  end.join('&')
117
178
  end
118
179
 
119
- def handle_post_connect(uri, http, &block)
120
- start = Time.now
121
- yield http
122
- rescue Puppet::HTTP::HTTPError
123
- raise
124
- rescue EOFError => e
125
- raise Puppet::HTTP::HTTPError.new(_("Request to %{uri} interrupted after %{elapsed} seconds") % {uri: uri, elapsed: elapsed(start)}, e)
126
- rescue Timeout::Error => e
127
- raise Puppet::HTTP::HTTPError.new(_("Request to %{uri} timed out after %{elapsed} seconds") % {uri: uri, elapsed: elapsed(start)}, e)
128
- rescue => e
129
- raise Puppet::HTTP::HTTPError.new(_("Request to %{uri} failed after %{elapsed} seconds: %{message}") % {uri: uri, elapsed: elapsed(start), message: e.message}, e)
130
- end
131
-
132
180
  def elapsed(start)
133
181
  (Time.now - start).to_f.round(3)
134
182
  end
135
183
 
184
+ def raise_error(message, cause, connected)
185
+ if connected
186
+ raise Puppet::HTTP::HTTPError.new(message, cause)
187
+ else
188
+ raise Puppet::HTTP::ConnectionError.new(message, cause)
189
+ end
190
+ end
191
+
136
192
  def default_ssl_context
137
193
  @default_ssl_context || Puppet.lookup(:ssl_context)
138
194
  end
@@ -147,10 +203,26 @@ class Puppet::HTTP::Client
147
203
  resolvers = []
148
204
 
149
205
  if Puppet[:use_srv_records]
150
- resolvers << Puppet::HTTP::Resolver::SRV.new(domain: Puppet[:srv_domain])
206
+ resolvers << Puppet::HTTP::Resolver::SRV.new(self, domain: Puppet[:srv_domain])
151
207
  end
152
208
 
153
- resolvers << Puppet::HTTP::Resolver::Settings.new
209
+ server_list_setting = Puppet.settings.setting(:server_list)
210
+ if server_list_setting.value && !server_list_setting.value.empty?
211
+ services = [:puppet]
212
+
213
+ # If we have not explicitly set :ca_server either on the command line or
214
+ # in puppet.conf, we want to be able to try the servers defined by
215
+ # :server_list when resolving the :ca service. Otherwise, :server_list
216
+ # should only be used with the :puppet service.
217
+ if !Puppet.settings.set_by_config?(:ca_server)
218
+ services << :ca
219
+ end
220
+
221
+ resolvers << Puppet::HTTP::Resolver::ServerList.new(self, server_list_setting: server_list_setting, default_port: Puppet[:masterport], services: services)
222
+ end
223
+
224
+ resolvers << Puppet::HTTP::Resolver::Settings.new(self)
225
+
154
226
  resolvers.freeze
155
227
  end
156
228
  end