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.
- checksums.yaml +4 -4
- data/CODEOWNERS +1 -1
- data/Gemfile +1 -0
- data/Gemfile.lock +16 -16
- data/README.md +1 -1
- data/ext/build_defaults.yaml +1 -0
- data/ext/windows/service/daemon.rb +22 -17
- data/lib/puppet/concurrent.rb +2 -0
- data/lib/puppet/concurrent/lock.rb +16 -0
- data/lib/puppet/concurrent/synchronized.rb +15 -0
- data/lib/puppet/concurrent/thread_local_singleton.rb +14 -0
- data/lib/puppet/configurer.rb +45 -31
- data/lib/puppet/defaults.rb +42 -3
- data/lib/puppet/environments.rb +3 -0
- data/lib/puppet/error.rb +9 -1
- data/lib/puppet/forge.rb +3 -3
- data/lib/puppet/forge/errors.rb +2 -2
- data/lib/puppet/forge/repository.rb +30 -86
- data/lib/puppet/functions/camelcase.rb +2 -2
- data/lib/puppet/functions/epp.rb +4 -4
- data/lib/puppet/functions/find_file.rb +9 -9
- data/lib/puppet/functions/find_template.rb +63 -0
- data/lib/puppet/functions/inline_epp.rb +5 -5
- data/lib/puppet/http.rb +2 -0
- data/lib/puppet/http/client.rb +89 -17
- data/lib/puppet/http/resolver.rb +14 -1
- data/lib/puppet/http/resolver/server_list.rb +38 -0
- data/lib/puppet/http/resolver/settings.rb +3 -2
- data/lib/puppet/http/resolver/srv.rb +10 -4
- data/lib/puppet/http/service.rb +32 -0
- data/lib/puppet/http/service/ca.rb +11 -10
- data/lib/puppet/http/service/report.rb +40 -0
- data/lib/puppet/http/session.rb +11 -32
- data/lib/puppet/network/http/base_pool.rb +13 -0
- data/lib/puppet/node/environment.rb +13 -7
- data/lib/puppet/pal/pal_impl.rb +5 -0
- data/lib/puppet/parser/functions/epp.rb +3 -3
- data/lib/puppet/parser/functions/inline_epp.rb +5 -5
- data/lib/puppet/pops/evaluator/runtime3_support.rb +1 -1
- data/lib/puppet/pops/lookup/invocation.rb +10 -3
- data/lib/puppet/pops/model/pn_transformer.rb +5 -9
- data/lib/puppet/pops/parser/evaluating_parser.rb +3 -4
- data/lib/puppet/pops/serialization/json_path.rb +3 -3
- data/lib/puppet/pops/time/timespan.rb +3 -5
- data/lib/puppet/pops/types/string_converter.rb +6 -9
- data/lib/puppet/pops/types/type_calculator.rb +6 -10
- data/lib/puppet/pops/types/type_formatter.rb +9 -11
- data/lib/puppet/pops/types/type_parser.rb +3 -3
- data/lib/puppet/provider/package/portage.rb +3 -3
- data/lib/puppet/provider/package_targetable.rb +5 -4
- data/lib/puppet/provider/service/systemd.rb +1 -1
- data/lib/puppet/provider/user/hpux.rb +1 -1
- data/lib/puppet/runtime.rb +1 -0
- data/lib/puppet/ssl/ssl_provider.rb +20 -0
- data/lib/puppet/transaction.rb +33 -11
- data/lib/puppet/type.rb +1 -1
- data/lib/puppet/type/file/data_sync.rb +5 -1
- data/lib/puppet/type/group.rb +3 -2
- data/lib/puppet/type/user.rb +3 -2
- data/lib/puppet/util.rb +34 -11
- data/lib/puppet/util/logging.rb +30 -18
- data/lib/puppet/util/windows/adsi.rb +48 -18
- data/lib/puppet/version.rb +1 -1
- data/lib/puppet/x509/cert_provider.rb +9 -5
- data/locales/puppet.pot +155 -141
- data/man/man5/puppet.conf.5 +33 -3
- data/man/man8/puppet-agent.8 +1 -1
- data/man/man8/puppet-apply.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-config.8 +1 -1
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +1 -1
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +1 -1
- data/man/man8/puppet-facts.8 +1 -1
- data/man/man8/puppet-filebucket.8 +1 -1
- data/man/man8/puppet-generate.8 +1 -1
- data/man/man8/puppet-help.8 +1 -1
- data/man/man8/puppet-key.8 +1 -1
- data/man/man8/puppet-lookup.8 +1 -1
- data/man/man8/puppet-man.8 +1 -1
- data/man/man8/puppet-module.8 +1 -1
- data/man/man8/puppet-node.8 +1 -1
- data/man/man8/puppet-parser.8 +1 -1
- data/man/man8/puppet-plugin.8 +1 -1
- data/man/man8/puppet-report.8 +1 -1
- data/man/man8/puppet-resource.8 +1 -1
- data/man/man8/puppet-script.8 +1 -1
- data/man/man8/puppet-ssl.8 +1 -1
- data/man/man8/puppet-status.8 +1 -1
- data/man/man8/puppet.8 +2 -2
- data/spec/fixtures/unit/forge/bacula.json +76 -0
- data/spec/integration/http/client_spec.rb +144 -0
- data/spec/integration/module_tool/forge_spec.rb +64 -0
- data/spec/lib/puppet_spec/https.rb +5 -3
- data/spec/spec_helper.rb +6 -2
- data/spec/unit/concurrent/lock_spec.rb +29 -0
- data/spec/unit/configurer_spec.rb +394 -399
- data/spec/unit/defaults_spec.rb +15 -4
- data/spec/unit/forge/errors_spec.rb +1 -1
- data/spec/unit/forge/forge_spec.rb +12 -54
- data/spec/unit/forge/module_release_spec.rb +19 -6
- data/spec/unit/forge/repository_spec.rb +63 -157
- data/spec/unit/forge_spec.rb +46 -116
- data/spec/unit/functions/find_template_spec.rb +69 -0
- data/spec/unit/http/client_spec.rb +138 -6
- data/spec/unit/http/resolver_spec.rb +49 -12
- data/spec/unit/http/service/ca_spec.rb +56 -5
- data/spec/unit/http/service/report_spec.rb +100 -0
- data/spec/unit/http/service_spec.rb +20 -0
- data/spec/unit/http/session_spec.rb +53 -18
- data/spec/unit/network/http/connection_spec.rb +0 -1
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +8 -3
- data/spec/unit/provider/package/portage_spec.rb +4 -4
- data/spec/unit/provider/package_targetable_spec.rb +60 -0
- data/spec/unit/provider/user/hpux_spec.rb +2 -2
- data/spec/unit/ssl/ssl_provider_spec.rb +71 -0
- data/spec/unit/transaction_spec.rb +46 -0
- data/spec/unit/type/file/content_spec.rb +9 -3
- data/spec/unit/util/log_spec.rb +0 -138
- data/spec/unit/util/logging_spec.rb +200 -0
- data/spec/unit/util/windows/adsi_spec.rb +51 -0
- data/spec/unit/x509/cert_provider_spec.rb +24 -4
- data/tasks/manpages.rake +1 -0
- metadata +24 -5
- data/spec/lib/puppet_spec/validators.rb +0 -37
data/spec/unit/forge_spec.rb
CHANGED
@@ -1,88 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require '
|
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
|
-
|
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(:
|
103
|
-
|
104
|
-
|
105
|
-
|
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
|
-
|
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
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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{
|
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
|
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
|
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)
|