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,88 +1,13 @@
1
1
  require 'spec_helper'
2
- require 'puppet/forge'
2
+ require 'spec_helper'
3
3
  require 'net/http'
4
+ require 'puppet/forge'
4
5
  require 'puppet/module_tool'
5
6
 
6
7
  describe Puppet::Forge do
8
+
7
9
  let(:http_response) do
8
- <<-EOF
9
- {
10
- "pagination": {
11
- "limit": 1,
12
- "offset": 0,
13
- "first": "/v3/modules?limit=1&offset=0",
14
- "previous": null,
15
- "current": "/v3/modules?limit=1&offset=0",
16
- "next": null,
17
- "total": 1832
18
- },
19
- "results": [
20
- {
21
- "uri": "/v3/modules/puppetlabs-bacula",
22
- "name": "bacula",
23
- "downloads": 640274,
24
- "created_at": "2011-05-24 18:34:58 -0700",
25
- "updated_at": "2013-12-03 15:24:20 -0800",
26
- "owner": {
27
- "uri": "/v3/users/puppetlabs",
28
- "username": "puppetlabs",
29
- "gravatar_id": "fdd009b7c1ec96e088b389f773e87aec"
30
- },
31
- "current_release": {
32
- "uri": "/v3/releases/puppetlabs-bacula-0.0.2",
33
- "module": {
34
- "uri": "/v3/modules/puppetlabs-bacula",
35
- "name": "bacula",
36
- "owner": {
37
- "uri": "/v3/users/puppetlabs",
38
- "username": "puppetlabs",
39
- "gravatar_id": "fdd009b7c1ec96e088b389f773e87aec"
40
- }
41
- },
42
- "version": "0.0.2",
43
- "metadata": {
44
- "types": [],
45
- "license": "Apache 2.0",
46
- "checksums": { },
47
- "version": "0.0.2",
48
- "source": "git://github.com/puppetlabs/puppetlabs-bacula.git",
49
- "project_page": "https://github.com/puppetlabs/puppetlabs-bacula",
50
- "summary": "bacula",
51
- "dependencies": [ ],
52
- "author": "puppetlabs",
53
- "name": "puppetlabs-bacula"
54
- },
55
- "tags": [
56
- "backup",
57
- "bacula"
58
- ],
59
- "file_uri": "/v3/files/puppetlabs-bacula-0.0.2.tar.gz",
60
- "file_size": 67586,
61
- "file_md5": "bbf919d7ee9d278d2facf39c25578bf8",
62
- "downloads": 565041,
63
- "readme": "",
64
- "changelog": "",
65
- "license": "",
66
- "created_at": "2013-05-13 08:31:19 -0700",
67
- "updated_at": "2013-05-13 08:31:19 -0700",
68
- "deleted_at": null
69
- },
70
- "releases": [
71
- {
72
- "uri": "/v3/releases/puppetlabs-bacula-0.0.2",
73
- "version": "0.0.2"
74
- },
75
- {
76
- "uri": "/v3/releases/puppetlabs-bacula-0.0.1",
77
- "version": "0.0.1"
78
- }
79
- ],
80
- "homepage_url": "https://github.com/puppetlabs/puppetlabs-bacula",
81
- "issues_url": "https://projects.puppetlabs.com/projects/bacula/issues"
82
- }
83
- ]
84
- }
85
- EOF
10
+ File.read(my_fixture('bacula.json'))
86
11
  end
87
12
 
88
13
  let(:search_results) do
@@ -99,76 +24,84 @@ describe Puppet::Forge do
99
24
  end
100
25
  end
101
26
 
102
- let(:forge) { Puppet::Forge.new }
103
-
104
- def repository_responds_with(response, &block)
105
- if block_given?
106
- allow_any_instance_of(Puppet::Forge::Repository).to receive(:make_http_request, &block).and_return(response)
107
- else
108
- allow_any_instance_of(Puppet::Forge::Repository).to receive(:make_http_request).and_return(response)
109
- end
27
+ let(:release_response) do
28
+ releases = JSON.parse(http_response)
29
+ releases['results'] = []
30
+ JSON.dump(releases)
110
31
  end
111
32
 
33
+ let(:forge) { Puppet::Forge.new }
34
+
112
35
  it "returns a list of matches from the forge when there are matches for the search term" do
113
- repository_responds_with(double(:body => http_response, :code => '200'))
36
+ stub_request(:get, "https://forgeapi.puppet.com/v3/modules?query=bacula").to_return(status: 200, body: http_response)
37
+
114
38
  expect(forge.search('bacula')).to eq(search_results)
115
39
  end
116
40
 
117
41
  context "when module_groups are defined" do
118
- let(:release_response) do
119
- releases = JSON.parse(http_response)
120
- releases['results'] = []
121
- JSON.dump(releases)
122
- end
123
-
124
42
  before :each do
125
- repository_responds_with(double(:body => release_response, :code => '200')) {|uri| uri =~ /module_groups=foo/}
126
43
  Puppet[:module_groups] = "foo"
127
44
  end
128
45
 
129
46
  it "passes module_groups with search" do
47
+ stub_request(:get, "https://forgeapi.puppet.com/v3/modules")
48
+ .with(query: hash_including("module_groups" => "foo"))
49
+ .to_return(status: 200, body: release_response)
50
+
130
51
  forge.search('bacula')
131
52
  end
132
53
 
133
54
  it "passes module_groups with fetch" do
55
+ stub_request(:get, "https://forgeapi.puppet.com/v3/releases")
56
+ .with(query: hash_including("module_groups" => "foo"))
57
+ .to_return(status: 200, body: release_response)
58
+
134
59
  forge.fetch('puppetlabs-bacula')
135
60
  end
136
61
  end
137
62
 
138
63
  # See PUP-8008
139
64
  context "when multiple module_groups are defined" do
140
- let(:release_response) do
141
- releases = JSON.parse(http_response)
142
- releases['results'] = []
143
- JSON.dump(releases)
144
- end
145
-
146
65
  context "with space seperator" do
147
66
  before :each do
148
- repository_responds_with(double(:body => release_response, :code => '200')) {|uri| uri =~ /module_groups=foo bar/}
149
67
  Puppet[:module_groups] = "foo bar"
150
68
  end
151
69
 
152
70
  it "passes module_groups with search" do
71
+ stub_request(:get, %r{forgeapi.puppet.com/v3/modules}).with do |req|
72
+ expect(req.uri.query).to match(/module_groups=foo%20bar/)
73
+ end.to_return(status: 200, body: release_response)
74
+
153
75
  forge.search('bacula')
154
76
  end
155
77
 
156
78
  it "passes module_groups with fetch" do
79
+ stub_request(:get, %r{forgeapi.puppet.com/v3/releases}).with do |req|
80
+ expect(req.uri.query).to match(/module_groups=foo%20bar/)
81
+ end.to_return(status: 200, body: release_response)
82
+
157
83
  forge.fetch('puppetlabs-bacula')
158
84
  end
159
85
  end
160
86
 
161
87
  context "with plus seperator" do
162
88
  before :each do
163
- repository_responds_with(double(:body => release_response, :code => '200')) {|uri| uri =~ /module_groups=foo bar/}
164
89
  Puppet[:module_groups] = "foo+bar"
165
90
  end
166
91
 
167
92
  it "passes module_groups with search" do
93
+ stub_request(:get, %r{forgeapi.puppet.com/v3/modules}).with do |req|
94
+ expect(req.uri.query).to match(/module_groups=foo%20bar/)
95
+ end.to_return(status: 200, body: release_response)
96
+
168
97
  forge.search('bacula')
169
98
  end
170
99
 
171
100
  it "passes module_groups with fetch" do
101
+ stub_request(:get, %r{forgeapi.puppet.com/v3/releases}).with do |req|
102
+ expect(req.uri.query).to match(/module_groups=foo%20bar/)
103
+ end.to_return(status: 200, body: release_response)
104
+
172
105
  forge.fetch('puppetlabs-bacula')
173
106
  end
174
107
  end
@@ -176,10 +109,10 @@ describe Puppet::Forge do
176
109
  # See PUP-8008
177
110
  context "when there are multiple pages of results" do
178
111
  before(:each) do
179
- expect_any_instance_of(Puppet::Forge::Repository).to receive(:make_http_request) {|_, uri| uri =~ /module_groups=foo bar/ && uri !=~ /offset/ }.and_return(double(:body => first_page, :code => '200'))
180
-
181
- # Request for second page should not have module_groups already encoded
182
- expect_any_instance_of(Puppet::Forge::Repository).to receive(:make_http_request) {|_, uri| uri =~ /module_groups=foo bar/ && uri =~ /offset=1/ }.and_return(double(:body => last_page, :code => '200'))
112
+ stub_request(:get, %r{forgeapi.puppet.com}).with do |req|
113
+ expect(req.uri.query).to match(/module_groups=foo%20bar/)
114
+ end.to_return(status: 200, body: first_page)
115
+ .to_return(status: 200, body: last_page)
183
116
  end
184
117
 
185
118
  context "with space seperator" do
@@ -242,7 +175,7 @@ describe Puppet::Forge do
242
175
 
243
176
  context "when the connection to the forge fails" do
244
177
  before :each do
245
- repository_responds_with(double(:body => '{}', :code => '404', :message => "not found"))
178
+ stub_request(:get, /forgeapi.puppet.com/).to_return(status: [404, 'not found'])
246
179
  end
247
180
 
248
181
  it "raises an error for search" do
@@ -255,25 +188,22 @@ describe Puppet::Forge do
255
188
  end
256
189
 
257
190
  context "when the API responds with an error" do
258
- before :each do
259
- repository_responds_with(double(:body => '{"error":"invalid module"}', :code => '410', :message => "Gone"))
260
- end
261
-
262
191
  it "raises an error for fetch" do
192
+ stub_request(:get, /forgeapi.puppet.com/).to_return(status: [410, 'Gone'], body: '{"error":"invalid module"}')
193
+
263
194
  expect { forge.fetch('puppetlabs/bacula') }.to raise_error Puppet::Forge::Errors::ResponseError, "Request to Puppet Forge failed. Detail: 410 Gone."
264
195
  end
265
196
  end
266
197
 
267
198
  context "when the forge returns a module with unparseable dependencies" do
268
- before :each do
199
+ it "ignores modules with unparseable dependencies" do
269
200
  response = JSON.parse(http_response)
270
201
  release = response['results'][0]['current_release']
271
202
  release['metadata']['dependencies'] = [{'name' => 'broken-garbage >= 1.0.0', 'version_requirement' => 'banana'}]
272
203
  response['results'] = [release]
273
- repository_responds_with(double(:body => JSON.dump(response), :code => '200'))
274
- end
275
204
 
276
- it "ignores modules with unparseable dependencies" do
205
+ stub_request(:get, /forgeapi.puppet.com/).to_return(status: 200, body: JSON.dump(response))
206
+
277
207
  expect(forge.fetch('puppetlabs/bacula')).to be_empty
278
208
  end
279
209
  end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+ require 'puppet_spec/compiler'
3
+ require 'matchers/resource'
4
+ require 'puppet_spec/files'
5
+
6
+ describe 'the find_template function' do
7
+ include PuppetSpec::Compiler
8
+ include Matchers::Resource
9
+ include PuppetSpec::Files
10
+
11
+ def with_file_content(content)
12
+ path = tmpfile('find-file-function')
13
+ file = File.new(path, 'wb')
14
+ file.sync = true
15
+ file.print content
16
+ yield path
17
+ end
18
+
19
+ it 'finds an existing absolute file when given arguments individually' do
20
+ with_file_content('one') do |one|
21
+ with_file_content('two') do |two|
22
+ expect(compile_to_catalog("notify { find_template('#{one}', '#{two}'):}")).to have_resource("Notify[#{one}]")
23
+ end
24
+ end
25
+ end
26
+
27
+ it 'skips non existing files' do
28
+ with_file_content('one') do |one|
29
+ with_file_content('two') do |two|
30
+ expect(compile_to_catalog("notify { find_template('#{one}/nope', '#{two}'):}")).to have_resource("Notify[#{two}]")
31
+ end
32
+ end
33
+ end
34
+
35
+ it 'accepts arguments given as an array' do
36
+ with_file_content('one') do |one|
37
+ with_file_content('two') do |two|
38
+ expect(compile_to_catalog("notify { find_template(['#{one}', '#{two}']):}")).to have_resource("Notify[#{one}]")
39
+ end
40
+ end
41
+ end
42
+
43
+ it 'finds an existing file in a module' do
44
+ with_file_content('file content') do |name|
45
+ mod = double('module')
46
+ allow(mod).to receive(:template).with('myfile').and_return(name)
47
+ Puppet[:code] = "notify { find_template('mymod/myfile'):}"
48
+ node = Puppet::Node.new('localhost')
49
+ compiler = Puppet::Parser::Compiler.new(node)
50
+ allow(compiler.environment).to receive(:module).with('mymod').and_return(mod)
51
+
52
+ expect(compiler.compile().filter { |r| r.virtual? }).to have_resource("Notify[#{name}]")
53
+ end
54
+ end
55
+
56
+ it 'returns undef when none of the paths were found' do
57
+ mod = double('module')
58
+ allow(mod).to receive(:template).with('myfile').and_return(nil)
59
+ Puppet[:code] = "notify { String(type(find_template('mymod/myfile', 'nomod/nofile'))):}"
60
+ node = Puppet::Node.new('localhost')
61
+ compiler = Puppet::Parser::Compiler.new(node)
62
+ # For a module that does not have the file
63
+ allow(compiler.environment).to receive(:module).with('mymod').and_return(mod)
64
+ # For a module that does not exist
65
+ allow(compiler.environment).to receive(:module).with('nomod').and_return(nil)
66
+
67
+ expect(compiler.compile().filter { |r| r.virtual? }).to have_resource("Notify[Undef]")
68
+ end
69
+ end
@@ -35,7 +35,15 @@ describe Puppet::HTTP::Client do
35
35
 
36
36
  expect {
37
37
  client.connect(uri)
38
- }.to raise_error(Puppet::HTTP::ConnectionError, %r{Failed to connect to https://www.example.com:})
38
+ }.to raise_error(Puppet::HTTP::ConnectionError, %r{^Request to https://www.example.com failed after .* seconds: (Connection refused|No connection could be made because the target machine actively refused it)})
39
+ end
40
+
41
+ it 'raises ConnectionError if the connect times out' do
42
+ allow_any_instance_of(Net::HTTP).to receive(:start).and_raise(Net::OpenTimeout)
43
+
44
+ expect {
45
+ client.connect(uri)
46
+ }.to raise_error(Puppet::HTTP::ConnectionError, %r{^Request to https://www.example.com timed out connect operation after .* seconds})
39
47
  end
40
48
  end
41
49
 
@@ -53,15 +61,15 @@ describe Puppet::HTTP::Client do
53
61
  end
54
62
 
55
63
  it 'raises HTTPError if connection is interrupted while reading' do
56
- expect_http_error(EOFError, %r{Request to https://www.example.com interrupted after .* seconds})
64
+ expect_http_error(EOFError, %r{^Request to https://www.example.com interrupted after .* seconds})
57
65
  end
58
66
 
59
67
  it 'raises HTTPError if connection times out' do
60
- expect_http_error(Net::ReadTimeout, %r{Request to https://www.example.com timed out after .* seconds})
68
+ expect_http_error(Net::ReadTimeout, %r{^Request to https://www.example.com timed out read operation after .* seconds})
61
69
  end
62
70
 
63
71
  it 'raises HTTPError if connection fails' do
64
- expect_http_error(ArgumentError, %r{Request to https://www.example.com failed after .* seconds})
72
+ expect_http_error(ArgumentError, %r{^Request to https://www.example.com failed after .* seconds})
65
73
  end
66
74
  end
67
75
 
@@ -77,7 +85,10 @@ describe Puppet::HTTP::Client do
77
85
 
78
86
  context "for GET requests" do
79
87
  it "includes default HTTP headers" do
80
- stub_request(:get, uri).with(headers: {'X-Puppet-Version' => /./, 'User-Agent' => /./})
88
+ stub_request(:get, uri).with do |request|
89
+ expect(request.headers).to include({'X-Puppet-Version' => /./, 'User-Agent' => /./})
90
+ expect(request.headers).to_not include('X-Puppet-Profiling')
91
+ end
81
92
 
82
93
  client.get(uri)
83
94
  end
@@ -123,9 +134,47 @@ describe Puppet::HTTP::Client do
123
134
  end
124
135
  end
125
136
 
137
+ context "for HEAD requests" do
138
+ it "includes default HTTP headers" do
139
+ stub_request(:head, uri).with(headers: {'X-Puppet-Version' => /./, 'User-Agent' => /./})
140
+
141
+ client.head(uri)
142
+ end
143
+
144
+ it "stringifies keys and encodes values in the query" do
145
+ stub_request(:head, uri).with(query: "foo=bar%3Dbaz")
146
+
147
+ client.head(uri, params: {:foo => "bar=baz"})
148
+ end
149
+
150
+ it "merges custom headers with default ones" do
151
+ stub_request(:head, uri).with(headers: { 'X-Foo' => 'Bar', 'X-Puppet-Version' => /./, 'User-Agent' => /./ })
152
+
153
+ client.head(uri, headers: {'X-Foo' => 'Bar'})
154
+ end
155
+
156
+ it "returns the response" do
157
+ stub_request(:head, uri)
158
+
159
+ response = client.head(uri)
160
+ expect(response).to be_an_instance_of(Puppet::HTTP::Response)
161
+ expect(response).to be_success
162
+ expect(response.code).to eq(200)
163
+ end
164
+
165
+ it "returns the entire response body" do
166
+ stub_request(:head, uri).to_return(body: "abc")
167
+
168
+ expect(client.head(uri).body).to eq("abc")
169
+ end
170
+ end
171
+
126
172
  context "for PUT requests" do
127
173
  it "includes default HTTP headers" do
128
- stub_request(:put, uri).with(headers: {'X-Puppet-Version' => /./, 'User-Agent' => /./})
174
+ stub_request(:put, uri).with do |request|
175
+ expect(request.headers).to include({'X-Puppet-Version' => /./, 'User-Agent' => /./})
176
+ expect(request.headers).to_not include('X-Puppet-Profiling')
177
+ end
129
178
 
130
179
  client.put(uri, content_type: 'text/plain', body: "")
131
180
  end
@@ -158,6 +207,89 @@ describe Puppet::HTTP::Client do
158
207
  end
159
208
  end
160
209
 
210
+ context "for POST requests" do
211
+ it "includes default HTTP headers" do
212
+ stub_request(:post, uri).with(headers: {'X-Puppet-Version' => /./, 'User-Agent' => /./})
213
+
214
+ client.post(uri, content_type: 'text/plain', body: "")
215
+ end
216
+
217
+ it "stringifies keys and encodes values in the query" do
218
+ stub_request(:post, "https://www.example.com").with(query: "foo=bar%3Dbaz")
219
+
220
+ client.post(uri, params: {:foo => "bar=baz"}, content_type: 'text/plain', body: "")
221
+ end
222
+
223
+ it "includes custom headers" do
224
+ stub_request(:post, "https://www.example.com").with(headers: { 'X-Foo' => 'Bar' })
225
+
226
+ client.post(uri, headers: {'X-Foo' => 'Bar'}, content_type: 'text/plain', body: "")
227
+ end
228
+
229
+ it "returns the response" do
230
+ stub_request(:post, uri)
231
+
232
+ response = client.post(uri, content_type: 'text/plain', body: "")
233
+ expect(response).to be_an_instance_of(Puppet::HTTP::Response)
234
+ expect(response).to be_success
235
+ expect(response.code).to eq(200)
236
+ end
237
+
238
+ it "sets content-length and content-type for the body" do
239
+ stub_request(:post, uri).with(headers: {"Content-Length" => "5", "Content-Type" => "text/plain"})
240
+
241
+ client.post(uri, content_type: 'text/plain', body: "hello")
242
+ end
243
+
244
+ it "streams the response body when a block is given" do
245
+ stub_request(:post, uri).to_return(body: "abc")
246
+
247
+ io = StringIO.new
248
+ client.post(uri, content_type: 'text/plain', body: "") do |response|
249
+ response.read_body do |data|
250
+ io.write(data)
251
+ end
252
+ end
253
+
254
+ expect(io.string).to eq("abc")
255
+ end
256
+ end
257
+
258
+ context "for DELETE requests" do
259
+ it "includes default HTTP headers" do
260
+ stub_request(:delete, uri).with(headers: {'X-Puppet-Version' => /./, 'User-Agent' => /./})
261
+
262
+ client.delete(uri)
263
+ end
264
+
265
+ it "merges custom headers with default ones" do
266
+ stub_request(:delete, uri).with(headers: { 'X-Foo' => 'Bar', 'X-Puppet-Version' => /./, 'User-Agent' => /./ })
267
+
268
+ client.delete(uri, headers: {'X-Foo' => 'Bar'})
269
+ end
270
+
271
+ it "stringifies keys and encodes values in the query" do
272
+ stub_request(:delete, "https://www.example.com").with(query: "foo=bar%3Dbaz")
273
+
274
+ client.delete(uri, params: {:foo => "bar=baz"})
275
+ end
276
+
277
+ it "returns the response" do
278
+ stub_request(:delete, uri)
279
+
280
+ response = client.delete(uri)
281
+ expect(response).to be_an_instance_of(Puppet::HTTP::Response)
282
+ expect(response).to be_success
283
+ expect(response.code).to eq(200)
284
+ end
285
+
286
+ it "returns the entire response body" do
287
+ stub_request(:delete, uri).to_return(body: "abc")
288
+
289
+ expect(client.delete(uri).body).to eq("abc")
290
+ end
291
+ end
292
+
161
293
  context "Basic Auth" do
162
294
  it "submits credentials for GET requests" do
163
295
  stub_request(:get, uri).with(basic_auth: credentials)