puppet 6.10.1 → 6.11.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/Gemfile +4 -4
- data/Gemfile.lock +20 -12
- data/ext/project_data.yaml +3 -2
- data/ext/regexp_nodes/regexp_nodes.rb +4 -4
- data/ext/windows/service/daemon.rb +33 -8
- data/install.rb +6 -6
- data/lib/puppet.rb +8 -0
- data/lib/puppet/application.rb +1 -1
- data/lib/puppet/application/agent.rb +3 -0
- data/lib/puppet/application/apply.rb +2 -2
- data/lib/puppet/application/describe.rb +3 -9
- data/lib/puppet/application/device.rb +3 -0
- data/lib/puppet/application/doc.rb +1 -1
- data/lib/puppet/application/lookup.rb +1 -1
- data/lib/puppet/application/script.rb +2 -2
- data/lib/puppet/application/ssl.rb +25 -21
- data/lib/puppet/configurer.rb +42 -0
- data/lib/puppet/configurer/downloader.rb +2 -6
- data/lib/puppet/context/trusted_information.rb +42 -4
- data/lib/puppet/defaults.rb +19 -4
- data/lib/puppet/face/module/list.rb +5 -5
- data/lib/puppet/face/module/search.rb +1 -1
- data/lib/puppet/face/module/uninstall.rb +1 -1
- data/lib/puppet/face/module/upgrade.rb +1 -1
- data/lib/puppet/file_serving/http_metadata.rb +1 -1
- data/lib/puppet/file_system.rb +0 -8
- data/lib/puppet/file_system/memory_file.rb +1 -1
- data/lib/puppet/file_system/posix.rb +3 -2
- data/lib/puppet/forge.rb +3 -3
- data/lib/puppet/functions.rb +1 -2
- data/lib/puppet/gettext/module_translations.rb +1 -1
- data/lib/puppet/graph/rb_tree_map.rb +2 -2
- data/lib/puppet/graph/simple_graph.rb +4 -3
- data/lib/puppet/http.rb +29 -0
- data/lib/puppet/http/client.rb +156 -0
- data/lib/puppet/http/errors.rb +30 -0
- data/lib/puppet/http/redirector.rb +48 -0
- data/lib/puppet/http/resolver.rb +5 -0
- data/lib/puppet/http/resolver/settings.rb +5 -0
- data/lib/puppet/http/resolver/srv.rb +13 -0
- data/lib/puppet/http/response.rb +34 -0
- data/lib/puppet/http/retry_after_handler.rb +47 -0
- data/lib/puppet/http/service.rb +18 -0
- data/lib/puppet/http/service/ca.rb +49 -0
- data/lib/puppet/http/session.rb +55 -0
- data/lib/puppet/indirector/file_bucket_file/file.rb +1 -1
- data/lib/puppet/indirector/hiera.rb +2 -0
- data/lib/puppet/indirector/request.rb +1 -1
- data/lib/puppet/indirector/resource/ral.rb +1 -3
- data/lib/puppet/indirector/resource/validator.rb +1 -1
- data/lib/puppet/interface.rb +2 -1
- data/lib/puppet/interface/documentation.rb +1 -1
- data/lib/puppet/loaders.rb +0 -1
- data/lib/puppet/metatype/manager.rb +1 -1
- data/lib/puppet/module.rb +1 -1
- data/lib/puppet/module/task.rb +20 -4
- data/lib/puppet/module_tool/applications/installer.rb +1 -1
- data/lib/puppet/module_tool/applications/uninstaller.rb +3 -3
- data/lib/puppet/module_tool/metadata.rb +1 -1
- data/lib/puppet/module_tool/shared_behaviors.rb +4 -4
- data/lib/puppet/module_tool/tar/mini.rb +1 -1
- data/lib/puppet/network/http.rb +2 -6
- data/lib/puppet/network/http/api/indirected_routes.rb +12 -11
- data/lib/puppet/network/http/connection.rb +10 -12
- data/lib/puppet/network/http/pool.rb +2 -0
- data/lib/puppet/network/http/site.rb +5 -1
- data/lib/puppet/network/resolver.rb +4 -4
- data/lib/puppet/node/environment.rb +4 -2
- data/lib/puppet/pal/pal_impl.rb +2 -2
- data/lib/puppet/parser/ast.rb +1 -1
- data/lib/puppet/parser/ast/resourceparam.rb +1 -1
- data/lib/puppet/parser/functions.rb +1 -1
- data/lib/puppet/parser/scope.rb +8 -7
- data/lib/puppet/pops/evaluator/collectors/catalog_collector.rb +1 -1
- data/lib/puppet/pops/evaluator/collectors/exported_collector.rb +1 -1
- data/lib/puppet/pops/evaluator/external_syntax_support.rb +3 -2
- data/lib/puppet/pops/evaluator/runtime3_support.rb +4 -7
- data/lib/puppet/pops/loader/module_loaders.rb +1 -1
- data/lib/puppet/pops/loader/task_instantiator.rb +4 -0
- data/lib/puppet/pops/loaders.rb +1 -1
- data/lib/puppet/pops/lookup/hiera_config.rb +1 -0
- data/lib/puppet/pops/lookup/sub_lookup.rb +1 -1
- data/lib/puppet/pops/merge_strategy.rb +22 -18
- data/lib/puppet/pops/parser/heredoc_support.rb +1 -1
- data/lib/puppet/pops/parser/interpolation_support.rb +4 -4
- data/lib/puppet/pops/parser/locator.rb +1 -1
- data/lib/puppet/pops/parser/pn_parser.rb +17 -16
- data/lib/puppet/pops/puppet_stack.rb +52 -48
- data/lib/puppet/pops/types/p_sensitive_type.rb +1 -1
- data/lib/puppet/pops/types/p_uri_type.rb +1 -1
- data/lib/puppet/pops/types/string_converter.rb +10 -10
- data/lib/puppet/pops/types/types.rb +3 -3
- data/lib/puppet/property.rb +1 -1
- data/lib/puppet/property/ensure.rb +1 -1
- data/lib/puppet/provider/exec.rb +6 -2
- data/lib/puppet/provider/nameservice/directoryservice.rb +1 -1
- data/lib/puppet/provider/nameservice/pw.rb +2 -2
- data/lib/puppet/provider/package/apt.rb +5 -1
- data/lib/puppet/provider/package/dnfmodule.rb +87 -0
- data/lib/puppet/provider/package/dpkg.rb +31 -17
- data/lib/puppet/provider/package/openbsd.rb +1 -1
- data/lib/puppet/provider/package/pip.rb +34 -9
- data/lib/puppet/provider/package/portage.rb +1 -1
- data/lib/puppet/provider/package/rpm.rb +5 -5
- data/lib/puppet/provider/package/windows/package.rb +1 -1
- data/lib/puppet/provider/package/yum.rb +1 -1
- data/lib/puppet/provider/parsedfile.rb +1 -1
- data/lib/puppet/provider/service/daemontools.rb +9 -9
- data/lib/puppet/provider/service/openbsd.rb +1 -1
- data/lib/puppet/provider/service/rcng.rb +2 -2
- data/lib/puppet/provider/service/runit.rb +2 -8
- data/lib/puppet/provider/service/systemd.rb +10 -10
- data/lib/puppet/provider/user/directoryservice.rb +1 -1
- data/lib/puppet/provider/user/user_role_add.rb +1 -1
- data/lib/puppet/provider/user/useradd.rb +22 -13
- data/lib/puppet/provider/user/windows_adsi.rb +4 -5
- data/lib/puppet/reference/indirection.rb +2 -2
- data/lib/puppet/reference/metaparameter.rb +1 -3
- data/lib/puppet/reference/providers.rb +1 -1
- data/lib/puppet/reference/type.rb +3 -9
- data/lib/puppet/reports.rb +1 -1
- data/lib/puppet/resource.rb +1 -1
- data/lib/puppet/resource/catalog.rb +1 -1
- data/lib/puppet/rest/errors.rb +1 -0
- data/lib/puppet/rest/response.rb +1 -0
- data/lib/puppet/rest/route.rb +1 -0
- data/lib/puppet/rest/routes.rb +3 -0
- data/lib/puppet/runtime.rb +25 -0
- data/lib/puppet/settings.rb +3 -3
- data/lib/puppet/settings/environment_conf.rb +1 -0
- data/lib/puppet/ssl/host.rb +1 -1
- data/lib/puppet/ssl/oids.rb +1 -1
- data/lib/puppet/ssl/state_machine.rb +23 -15
- data/lib/puppet/test/test_helper.rb +1 -1
- data/lib/puppet/transaction/report.rb +1 -1
- data/lib/puppet/trusted_external.rb +13 -0
- data/lib/puppet/type.rb +1 -3
- data/lib/puppet/type/exec.rb +7 -3
- data/lib/puppet/type/file.rb +1 -2
- data/lib/puppet/type/file/source.rb +2 -2
- data/lib/puppet/type/package.rb +10 -3
- data/lib/puppet/type/schedule.rb +1 -1
- data/lib/puppet/type/service.rb +1 -1
- data/lib/puppet/util.rb +2 -2
- data/lib/puppet/util/command_line/trollop.rb +1 -1
- data/lib/puppet/util/http_proxy.rb +2 -10
- data/lib/puppet/util/log.rb +2 -2
- data/lib/puppet/util/log/destinations.rb +2 -2
- data/lib/puppet/util/logging.rb +2 -2
- data/lib/puppet/util/metric.rb +2 -2
- data/lib/puppet/util/platform.rb +15 -4
- data/lib/puppet/util/provider_features.rb +2 -4
- data/lib/puppet/util/rdoc.rb +1 -1
- data/lib/puppet/util/reference.rb +1 -1
- data/lib/puppet/util/resource_template.rb +1 -1
- data/lib/puppet/util/selinux.rb +3 -1
- data/lib/puppet/util/windows/registry.rb +7 -5
- data/lib/puppet/vendor.rb +1 -1
- data/lib/puppet/vendor/require_vendored.rb +0 -1
- data/lib/puppet/version.rb +1 -1
- data/lib/puppet/x509/cert_provider.rb +4 -1
- data/locales/puppet.pot +279 -203
- data/man/man5/puppet.conf.5 +30 -8
- data/man/man8/puppet-agent.8 +4 -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/provider/package/dnfmodule/dnf-module-list-installed.txt +11 -0
- data/spec/integration/configurer_spec.rb +52 -0
- data/spec/lib/puppet/certificate_factory.rb +2 -2
- data/spec/spec_helper.rb +24 -0
- data/spec/unit/application/device_spec.rb +6 -0
- data/spec/unit/application/ssl_spec.rb +4 -7
- data/spec/unit/configurer_spec.rb +1 -0
- data/spec/unit/context/trusted_information_spec.rb +41 -2
- data/spec/unit/http/client_spec.rb +440 -0
- data/spec/unit/http/resolver_spec.rb +45 -0
- data/spec/unit/http/service/ca_spec.rb +106 -0
- data/spec/unit/http/service_spec.rb +32 -0
- data/spec/unit/http/session_spec.rb +102 -0
- data/spec/unit/indirector/resource/ral_spec.rb +4 -4
- data/spec/unit/network/http/connection_spec.rb +119 -145
- data/spec/unit/network/http/site_spec.rb +7 -0
- data/spec/unit/parser/scope_spec.rb +10 -0
- data/spec/unit/pops/loaders/loaders_spec.rb +13 -2
- data/spec/unit/pops/loaders/module_loaders_spec.rb +37 -0
- data/spec/unit/provider/exec_spec.rb +209 -0
- data/spec/unit/provider/package/dnfmodule_spec.rb +186 -0
- data/spec/unit/provider/package/dpkg_spec.rb +238 -78
- data/spec/unit/provider/package/pip_spec.rb +51 -6
- data/spec/unit/provider/service/daemontools_spec.rb +24 -0
- data/spec/unit/provider/service/runit_spec.rb +24 -0
- data/spec/unit/provider/service/systemd_spec.rb +25 -25
- data/spec/unit/provider/user/useradd_spec.rb +46 -0
- data/spec/unit/ssl/host_spec.rb +0 -5
- data/spec/unit/ssl/state_machine_spec.rb +16 -10
- data/spec/unit/type/exec_spec.rb +6 -12
- data/spec/unit/type/file_spec.rb +9 -4
- data/spec/unit/type/package_spec.rb +5 -0
- data/spec/unit/util/execution_spec.rb +16 -0
- data/spec/unit/util/http_proxy_spec.rb +79 -27
- data/spec/unit/util/log/destinations_spec.rb +7 -3
- metadata +45 -22
- data/lib/puppet/pops/loader/null_loader.rb +0 -60
- data/lib/puppet/vendor/deep_merge/CHANGELOG +0 -45
- data/lib/puppet/vendor/deep_merge/Gemfile +0 -3
- data/lib/puppet/vendor/deep_merge/LICENSE +0 -21
- data/lib/puppet/vendor/deep_merge/PUPPET_README.md +0 -6
- data/lib/puppet/vendor/deep_merge/README.md +0 -113
- data/lib/puppet/vendor/deep_merge/Rakefile +0 -19
- data/lib/puppet/vendor/deep_merge/deep_merge.gemspec +0 -35
- data/lib/puppet/vendor/deep_merge/lib/deep_merge.rb +0 -2
- data/lib/puppet/vendor/deep_merge/lib/deep_merge/core.rb +0 -210
- data/lib/puppet/vendor/deep_merge/lib/deep_merge/deep_merge_hash.rb +0 -28
- data/lib/puppet/vendor/deep_merge/lib/deep_merge/rails_compat.rb +0 -27
- data/lib/puppet/vendor/deep_merge/test/test_deep_merge.rb +0 -608
- data/lib/puppet/vendor/load_deep_merge.rb +0 -1
- data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_get/should_yield_to_the_block.yml +0 -24
- data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_head/should_yield_to_the_block.yml +0 -24
- data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_post/should_yield_to_the_block.yml +0 -24
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'webmock/rspec'
|
3
|
+
require 'puppet/http'
|
4
|
+
|
5
|
+
describe Puppet::HTTP::Resolver do
|
6
|
+
let(:ssl_context) { Puppet::SSL::SSLContext.new }
|
7
|
+
let(:client) { Puppet::HTTP::Client.new(ssl_context: ssl_context) }
|
8
|
+
let(:session) { client.create_session }
|
9
|
+
let(:uri) { URI.parse('https://www.example.com') }
|
10
|
+
|
11
|
+
context 'when resolving using settings' do
|
12
|
+
let(:subject) { Puppet::HTTP::Resolver::Settings.new }
|
13
|
+
|
14
|
+
it 'yields a service based on the current ca_server and ca_port settings' do
|
15
|
+
Puppet[:ca_server] = 'ca.example.com'
|
16
|
+
Puppet[:ca_port] = 8141
|
17
|
+
|
18
|
+
subject.resolve(session, :ca) do |service|
|
19
|
+
expect(service).to be_an_instance_of(Puppet::HTTP::Service::Ca)
|
20
|
+
expect(service.url.to_s).to eq("https://ca.example.com:8141/puppet-ca/v1")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when resolving using SRV' do
|
26
|
+
let(:dns) { double('dns') }
|
27
|
+
let(:subject) { Puppet::HTTP::Resolver::SRV.new(domain: 'example.com', dns: dns) }
|
28
|
+
|
29
|
+
def stub_srv(host, port)
|
30
|
+
srv = Resolv::DNS::Resource::IN::SRV.new(0, 0, port, host)
|
31
|
+
srv.instance_variable_set :@ttl, 3600
|
32
|
+
|
33
|
+
allow(dns).to receive(:getresources).with("_x-puppet-ca._tcp.example.com", Resolv::DNS::Resource::IN::SRV).and_return([srv])
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'yields a service based on an SRV record' do
|
37
|
+
stub_srv('ca1.example.com', 8142)
|
38
|
+
|
39
|
+
subject.resolve(session, :ca) do |service|
|
40
|
+
expect(service).to be_an_instance_of(Puppet::HTTP::Service::Ca)
|
41
|
+
expect(service.url.to_s).to eq("https://ca1.example.com:8142/puppet-ca/v1")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'webmock/rspec'
|
3
|
+
require 'puppet/http'
|
4
|
+
|
5
|
+
describe Puppet::HTTP::Service::Ca do
|
6
|
+
let(:ssl_context) { Puppet::SSL::SSLContext.new }
|
7
|
+
let(:client) { Puppet::HTTP::Client.new(ssl_context: ssl_context) }
|
8
|
+
let(:base_url) { URI.parse('https://www.example.com') }
|
9
|
+
let(:subject) { described_class.new(client, base_url) }
|
10
|
+
|
11
|
+
context 'when getting certificates' do
|
12
|
+
let(:cert) { cert_fixture('ca.pem') }
|
13
|
+
let(:pem) { cert.to_pem }
|
14
|
+
let(:url) { "https://www.example.com/certificate/ca" }
|
15
|
+
|
16
|
+
it 'gets a certificate from the "certificate" endpoint' do
|
17
|
+
stub_request(:get, url).to_return(body: pem)
|
18
|
+
|
19
|
+
expect(subject.get_certificate('ca')).to eq(pem)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'accepts text/plain responses' do
|
23
|
+
stub_request(:get, url).with(headers: {'Accept' => 'text/plain'})
|
24
|
+
|
25
|
+
subject.get_certificate('ca')
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'raises a response error if unsuccessful' do
|
29
|
+
stub_request(:get, url).to_return(status: [404, 'Not Found'])
|
30
|
+
|
31
|
+
expect {
|
32
|
+
subject.get_certificate('ca')
|
33
|
+
}.to raise_error do |err|
|
34
|
+
expect(err).to be_an_instance_of(Puppet::HTTP::ResponseError)
|
35
|
+
expect(err.message).to eq("Not Found")
|
36
|
+
expect(err.response.code).to eq(404)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when getting CRLs' do
|
42
|
+
let(:crl) { crl_fixture('crl.pem') }
|
43
|
+
let(:pem) { crl.to_pem }
|
44
|
+
let(:url) { "https://www.example.com/certificate_revocation_list/ca" }
|
45
|
+
|
46
|
+
it 'gets a CRL from "certificate_revocation_list" endpoint' do
|
47
|
+
stub_request(:get, url).to_return(body: pem)
|
48
|
+
|
49
|
+
expect(subject.get_certificate_revocation_list).to eq(pem)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'accepts text/plain responses' do
|
53
|
+
stub_request(:get, url).with(headers: {'Accept' => 'text/plain'})
|
54
|
+
|
55
|
+
subject.get_certificate_revocation_list
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'raises a response error if unsuccessful' do
|
59
|
+
stub_request(:get, url).to_return(status: [404, 'Not Found'])
|
60
|
+
|
61
|
+
expect {
|
62
|
+
subject.get_certificate_revocation_list
|
63
|
+
}.to raise_error do |err|
|
64
|
+
expect(err).to be_an_instance_of(Puppet::HTTP::ResponseError)
|
65
|
+
expect(err.message).to eq("Not Found")
|
66
|
+
expect(err.response.code).to eq(404)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'raises a 304 response error if it is unmodified' do
|
71
|
+
stub_request(:get, url).to_return(status: [304, 'Not Modified'])
|
72
|
+
|
73
|
+
expect {
|
74
|
+
subject.get_certificate_revocation_list(if_modified_since: Time.now)
|
75
|
+
}.to raise_error do |err|
|
76
|
+
expect(err).to be_an_instance_of(Puppet::HTTP::ResponseError)
|
77
|
+
expect(err.message).to eq("Not Modified")
|
78
|
+
expect(err.response.code).to eq(304)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'when submitting a CSR' do
|
84
|
+
let(:request) { request_fixture('request.pem') }
|
85
|
+
let(:pem) { request.to_pem }
|
86
|
+
let(:url) { "https://www.example.com/certificate_request/infinity" }
|
87
|
+
|
88
|
+
it 'submits a CSR to the "certificate_request" endpoint' do
|
89
|
+
stub_request(:put, url).with(body: pem, headers: { 'Content-Type' => 'text/plain' })
|
90
|
+
|
91
|
+
subject.put_certificate_request('infinity', request)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'raises response error if unsuccessful' do
|
95
|
+
stub_request(:put, url).to_return(status: [400, 'Bad Request'])
|
96
|
+
|
97
|
+
expect {
|
98
|
+
subject.put_certificate_request('infinity', request)
|
99
|
+
}.to raise_error do |err|
|
100
|
+
expect(err).to be_an_instance_of(Puppet::HTTP::ResponseError)
|
101
|
+
expect(err.message).to eq('Bad Request')
|
102
|
+
expect(err.response.code).to eq(400)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'webmock/rspec'
|
3
|
+
require 'puppet/http'
|
4
|
+
|
5
|
+
describe Puppet::HTTP::Service do
|
6
|
+
let(:ssl_context) { Puppet::SSL::SSLContext.new }
|
7
|
+
let(:client) { Puppet::HTTP::Client.new(ssl_context: ssl_context) }
|
8
|
+
let(:url) { URI.parse('https://www.example.com') }
|
9
|
+
let(:service) { described_class.new(client, url) }
|
10
|
+
|
11
|
+
it "returns a URI containing the base URL and path" do
|
12
|
+
expect(service.with_base_url('/puppet/v3')).to eq(URI.parse("https://www.example.com/puppet/v3"))
|
13
|
+
end
|
14
|
+
|
15
|
+
it "doesn't modify frozen the base URL" do
|
16
|
+
service = described_class.new(client, url.freeze)
|
17
|
+
service.with_base_url('/puppet/v3')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "connects to the base URL with a nil ssl context" do
|
21
|
+
expect(client).to receive(:connect).with(url, ssl_context: nil)
|
22
|
+
|
23
|
+
service.connect
|
24
|
+
end
|
25
|
+
|
26
|
+
it "accepts an optional ssl_context" do
|
27
|
+
other_ctx = Puppet::SSL::SSLContext.new
|
28
|
+
expect(client).to receive(:connect).with(url, ssl_context: other_ctx)
|
29
|
+
|
30
|
+
service.connect(ssl_context: other_ctx)
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'webmock/rspec'
|
3
|
+
require 'puppet/http'
|
4
|
+
|
5
|
+
describe Puppet::HTTP::Session do
|
6
|
+
let(:ssl_context) { Puppet::SSL::SSLContext.new }
|
7
|
+
let(:client) { Puppet::HTTP::Client.new(ssl_context: ssl_context) }
|
8
|
+
let(:uri) { URI.parse('https://www.example.com') }
|
9
|
+
let(:good_service) {
|
10
|
+
double('good', url: uri, connect: nil)
|
11
|
+
}
|
12
|
+
let(:bad_service) {
|
13
|
+
service = double('good', url: uri)
|
14
|
+
allow(service).to receive(:connect).and_raise(Puppet::HTTP::ConnectionError, 'whoops')
|
15
|
+
service
|
16
|
+
}
|
17
|
+
|
18
|
+
class DummyResolver
|
19
|
+
attr_reader :count
|
20
|
+
|
21
|
+
def initialize(service)
|
22
|
+
@service = service
|
23
|
+
@count = 0
|
24
|
+
end
|
25
|
+
|
26
|
+
def resolve(session, name, &block)
|
27
|
+
@count += 1
|
28
|
+
yield @service
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when routing' do
|
33
|
+
it 'returns the first resolved service' do
|
34
|
+
Puppet[:log_level] = :debug
|
35
|
+
resolvers = [DummyResolver.new(bad_service), DummyResolver.new(good_service)]
|
36
|
+
session = described_class.new(client, resolvers)
|
37
|
+
resolved = session.route_to(:ca)
|
38
|
+
|
39
|
+
expect(resolved).to eq(good_service)
|
40
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Connection to #{uri} failed, trying next route: whoops"))
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'only resolves once per session' do
|
44
|
+
resolver = DummyResolver.new(good_service)
|
45
|
+
session = described_class.new(client, [resolver])
|
46
|
+
session.route_to(:ca)
|
47
|
+
session.route_to(:ca)
|
48
|
+
|
49
|
+
expect(resolver.count).to eq(1)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'raises if there are no more routes' do
|
53
|
+
resolvers = [DummyResolver.new(bad_service)]
|
54
|
+
session = described_class.new(client, resolvers)
|
55
|
+
|
56
|
+
expect {
|
57
|
+
session.route_to(:ca)
|
58
|
+
}.to raise_error(Puppet::HTTP::RouteError, 'No more routes to ca')
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'accepts an ssl context to use when connecting' do
|
62
|
+
alt_context = Puppet::SSL::SSLContext.new
|
63
|
+
expect(good_service).to receive(:connect).with(ssl_context: alt_context)
|
64
|
+
|
65
|
+
resolvers = [DummyResolver.new(good_service)]
|
66
|
+
session = described_class.new(client, resolvers)
|
67
|
+
session.route_to(:ca, ssl_context: alt_context)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'raises for unknown service names' do
|
71
|
+
expect {
|
72
|
+
session = described_class.new(client, [])
|
73
|
+
session.route_to(:westbound)
|
74
|
+
}.to raise_error(ArgumentError, "Unknown service westbound")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'when creating services' do
|
79
|
+
let(:session) { described_class.new(client, []) }
|
80
|
+
|
81
|
+
it 'defaults the server and port based on settings' do
|
82
|
+
Puppet[:ca_server] = 'ca.example.com'
|
83
|
+
Puppet[:ca_port] = 8141
|
84
|
+
service = session.create_service(:ca)
|
85
|
+
|
86
|
+
expect(service.url.to_s).to eq("https://ca.example.com:8141/puppet-ca/v1")
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'accepts server and port arguments' do
|
90
|
+
service = session.create_service(:ca, 'ca2.example.com', 8142)
|
91
|
+
|
92
|
+
expect(service.url.to_s).to eq("https://ca2.example.com:8142/puppet-ca/v1")
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'raises for unknown service names' do
|
96
|
+
expect {
|
97
|
+
session = described_class.new(client, [])
|
98
|
+
session.create_service(:westbound)
|
99
|
+
}.to raise_error(ArgumentError, "Unknown service westbound")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -48,7 +48,7 @@ describe "Puppet::Resource::Ral" do
|
|
48
48
|
end
|
49
49
|
|
50
50
|
it "should convert ral resources into regular resources" do
|
51
|
-
my_resource = double("my user resource")
|
51
|
+
my_resource = double("my user resource", :title => "my user resource")
|
52
52
|
my_instance = double("my user", :name => "root", :to_resource => my_resource)
|
53
53
|
|
54
54
|
expect(Puppet::Type::User).to receive(:instances).and_return([ my_instance ])
|
@@ -56,7 +56,7 @@ describe "Puppet::Resource::Ral" do
|
|
56
56
|
end
|
57
57
|
|
58
58
|
it "should filter results by name if there's a name in the key" do
|
59
|
-
my_resource = double("my user resource")
|
59
|
+
my_resource = double("my user resource", title: "my user resource")
|
60
60
|
allow(my_resource).to receive(:to_resource).and_return(my_resource)
|
61
61
|
allow(my_resource).to receive(:[]).with(:name).and_return("root")
|
62
62
|
|
@@ -74,11 +74,11 @@ describe "Puppet::Resource::Ral" do
|
|
74
74
|
end
|
75
75
|
|
76
76
|
it "should filter results by query parameters" do
|
77
|
-
wrong_resource = double("my user resource")
|
77
|
+
wrong_resource = double("my user resource", title: "my user resource")
|
78
78
|
allow(wrong_resource).to receive(:to_resource).and_return(wrong_resource)
|
79
79
|
allow(wrong_resource).to receive(:[]).with(:name).and_return("root")
|
80
80
|
|
81
|
-
my_resource = double("wrong resource")
|
81
|
+
my_resource = double("wrong resource", title: "wrong resource")
|
82
82
|
allow(my_resource).to receive(:to_resource).and_return(my_resource)
|
83
83
|
allow(my_resource).to receive(:[]).with(:name).and_return("bob")
|
84
84
|
|
@@ -4,10 +4,11 @@ require 'puppet_spec/validators'
|
|
4
4
|
require 'puppet/test_ca'
|
5
5
|
|
6
6
|
describe Puppet::Network::HTTP::Connection do
|
7
|
-
let (:host) { "me" }
|
8
|
-
let (:port) {
|
7
|
+
let (:host) { "me.example.com" }
|
8
|
+
let (:port) { 8140 }
|
9
|
+
let (:url) { "https://#{host}:#{port}/foo" }
|
10
|
+
|
9
11
|
subject { Puppet::Network::HTTP::Connection.new(host, port, :verify => Puppet::SSL::Validator.no_validator) }
|
10
|
-
let (:httpok) { Net::HTTPOK.new('1.1', 200, '') }
|
11
12
|
|
12
13
|
context "when providing HTTP connections" do
|
13
14
|
context "when initializing http instances" do
|
@@ -68,68 +69,48 @@ describe Puppet::Network::HTTP::Connection do
|
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
71
|
-
context "when handling requests"
|
72
|
-
|
73
|
-
|
74
|
-
let (:subject) { Puppet::Network::HTTP::Connection.new(host, port, :use_ssl => false, :verify => Puppet::SSL::Validator.no_validator) }
|
75
|
-
|
76
|
-
{ :request_get => {},
|
77
|
-
:request_head => {},
|
78
|
-
:request_post => "param: value" }.each do |method,body|
|
79
|
-
context "##{method}" do
|
80
|
-
it "should yield to the block" do
|
81
|
-
allow_any_instance_of(Net::HTTP).to receive(method) do |_, *_, &block|
|
82
|
-
block.call()
|
83
|
-
httpok
|
84
|
-
end
|
85
|
-
|
86
|
-
block_executed = false
|
87
|
-
subject.send(method, "/foo", body) do |response|
|
88
|
-
block_executed = true
|
89
|
-
end
|
90
|
-
expect(block_executed).to eq(true)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
72
|
+
context "when handling requests" do
|
73
|
+
it 'yields the response when request_get is called' do
|
74
|
+
stub_request(:get, url)
|
95
75
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
let (:other_path) { "other-path" }
|
100
|
-
let (:verify) { Puppet::SSL::Validator.no_validator }
|
101
|
-
let (:subject) { Puppet::Network::HTTP::Connection.new(site.host, site.port, :use_ssl => false, :verify => verify) }
|
102
|
-
let (:httpredirection) do
|
103
|
-
response = Net::HTTPFound.new('1.1', 302, 'Moved Temporarily')
|
104
|
-
response['location'] = "#{other_site.addr}/#{other_path}"
|
105
|
-
allow(response).to receive(:read_body).and_return("This resource has moved")
|
106
|
-
response
|
76
|
+
expect { |b|
|
77
|
+
subject.request_get('/foo', {}, &b)
|
78
|
+
}.to yield_with_args(Net::HTTPResponse)
|
107
79
|
end
|
108
80
|
|
109
|
-
|
110
|
-
|
111
|
-
|
81
|
+
it 'yields the response when request_head is called' do
|
82
|
+
stub_request(:head, url)
|
83
|
+
|
84
|
+
expect { |b|
|
85
|
+
subject.request_head('/foo', {}, &b)
|
86
|
+
}.to yield_with_args(Net::HTTPResponse)
|
112
87
|
end
|
113
88
|
|
114
|
-
it
|
115
|
-
|
116
|
-
allow(http).to receive(:request).and_return(httpredirection, httpok)
|
89
|
+
it 'yields the response when request_post is called' do
|
90
|
+
stub_request(:post, url)
|
117
91
|
|
118
|
-
|
119
|
-
|
120
|
-
|
92
|
+
expect { |b|
|
93
|
+
subject.request_post('/foo', "param: value", &b)
|
94
|
+
}.to yield_with_args(Net::HTTPResponse)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "when response is a redirect" do
|
99
|
+
def create_connection(options = {})
|
100
|
+
options[:use_ssl] = false
|
101
|
+
options[:verify] = Puppet::SSL::Validator.no_validator
|
102
|
+
Puppet::Network::HTTP::Connection.new(host, port, options)
|
103
|
+
end
|
121
104
|
|
122
|
-
|
123
|
-
|
105
|
+
def redirect_to(url)
|
106
|
+
{ status: 302, headers: { 'Location' => url } }
|
124
107
|
end
|
125
108
|
|
126
|
-
|
127
|
-
http
|
128
|
-
|
109
|
+
it "should follow the redirect to the final resource location" do
|
110
|
+
stub_request(:get, "http://me.example.com:8140/foo").to_return(redirect_to("http://me.example.com:8140/bar"))
|
111
|
+
stub_request(:get, "http://me.example.com:8140/bar").to_return(status: 200)
|
129
112
|
|
130
|
-
|
131
|
-
expect(pool).to receive(:with_connection).with(site, anything).and_yield(http)
|
132
|
-
pool
|
113
|
+
create_connection.get('/foo')
|
133
114
|
end
|
134
115
|
|
135
116
|
def expects_limit_exceeded(conn)
|
@@ -138,164 +119,157 @@ describe Puppet::Network::HTTP::Connection do
|
|
138
119
|
}.to raise_error(Puppet::Network::HTTP::RedirectionLimitExceededException)
|
139
120
|
end
|
140
121
|
|
141
|
-
it "should not
|
142
|
-
|
143
|
-
|
144
|
-
pool = expects_redirection(conn)
|
145
|
-
expect(pool).not_to receive(:with_connection).with(other_site, anything)
|
122
|
+
it "should not follow any redirects when the limit is 0" do
|
123
|
+
stub_request(:get, "http://me.example.com:8140/").to_return(redirect_to("http://me.example.com:8140/foo"))
|
146
124
|
|
125
|
+
conn = create_connection(:redirect_limit => 0)
|
147
126
|
expects_limit_exceeded(conn)
|
148
127
|
end
|
149
128
|
|
150
|
-
it "should redirect
|
151
|
-
|
152
|
-
|
153
|
-
pool = expects_redirection(conn)
|
154
|
-
expect(pool).to receive(:with_connection).with(other_site, anything).once
|
129
|
+
it "should follow the redirect once" do
|
130
|
+
stub_request(:get, "http://me.example.com:8140/").to_return(redirect_to("http://me.example.com:8140/foo"))
|
131
|
+
stub_request(:get, "http://me.example.com:8140/foo").to_return(redirect_to("http://me.example.com:8140/bar"))
|
155
132
|
|
133
|
+
conn = create_connection(:redirect_limit => 1)
|
156
134
|
expects_limit_exceeded(conn)
|
157
135
|
end
|
158
136
|
|
159
137
|
it "should raise an exception when the redirect limit is exceeded" do
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
138
|
+
stub_request(:get, "http://me.example.com:8140/").to_return(redirect_to("http://me.example.com:8140/foo"))
|
139
|
+
stub_request(:get, "http://me.example.com:8140/foo").to_return(redirect_to("http://me.example.com:8140/bar"))
|
140
|
+
stub_request(:get, "http://me.example.com:8140/bar").to_return(redirect_to("http://me.example.com:8140/baz"))
|
141
|
+
stub_request(:get, "http://me.example.com:8140/baz").to_return(redirect_to("http://me.example.com:8140/qux"))
|
164
142
|
|
143
|
+
conn = create_connection(:redirect_limit => 3)
|
165
144
|
expects_limit_exceeded(conn)
|
166
145
|
end
|
167
146
|
end
|
168
147
|
|
169
148
|
context "when response indicates an overloaded server" do
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
subject { Puppet::Network::HTTP::Connection.new(site.host, site.port, :use_ssl => false, :verify => verify) }
|
176
|
-
|
177
|
-
context "when parsing Retry-After headers" do
|
178
|
-
# Private method. Create a reference that can be called by tests.
|
179
|
-
let(:header_parser) { subject.method(:parse_retry_after_header) }
|
180
|
-
|
181
|
-
it "returns 0 when parsing a RFC 2822 date that has passed" do
|
182
|
-
test_date = 'Wed, 13 Apr 2005 15:18:05 GMT'
|
183
|
-
|
184
|
-
expect(header_parser.call(test_date)).to eq(0)
|
185
|
-
end
|
149
|
+
def retry_after(datetime)
|
150
|
+
stub_request(:get, url)
|
151
|
+
.to_return(status: [503, 'Service Unavailable'], headers: {'Retry-After' => datetime}).then
|
152
|
+
.to_return(status: 200)
|
186
153
|
end
|
187
154
|
|
188
155
|
it "should return a 503 response if Retry-After is not set" do
|
189
|
-
|
190
|
-
|
191
|
-
pool = Puppet.lookup(:http_pool)
|
192
|
-
expect(pool).to receive(:with_connection).with(site, anything).and_yield(http)
|
156
|
+
stub_request(:get, url).to_return(status: [503, 'Service Unavailable'])
|
193
157
|
|
194
158
|
result = subject.get('/foo')
|
195
|
-
|
196
|
-
expect(result.code).to eq(503)
|
159
|
+
expect(result.code).to eq("503")
|
197
160
|
end
|
198
161
|
|
199
162
|
it "should return a 503 response if Retry-After is not convertible to an Integer or RFC 2822 Date" do
|
200
|
-
|
201
|
-
allow(http).to receive(:request).and_return(httpunavailable)
|
202
|
-
|
203
|
-
pool = Puppet.lookup(:http_pool)
|
204
|
-
expect(pool).to receive(:with_connection).with(site, anything).and_yield(http)
|
163
|
+
stub_request(:get, url).to_return(status: [503, 'Service Unavailable'], headers: {'Retry-After' => 'foo'})
|
205
164
|
|
206
165
|
result = subject.get('/foo')
|
207
|
-
|
208
|
-
expect(result.code).to eq(503)
|
166
|
+
expect(result.code).to eq("503")
|
209
167
|
end
|
210
168
|
|
211
169
|
it "should sleep and retry if Retry-After is an Integer" do
|
212
|
-
|
213
|
-
allow(http).to receive(:request).and_return(httpunavailable, httpok)
|
214
|
-
|
215
|
-
pool = Puppet.lookup(:http_pool)
|
216
|
-
expect(pool).to receive(:with_connection).with(site, anything).twice.and_yield(http)
|
170
|
+
retry_after('42')
|
217
171
|
|
218
172
|
expect(::Kernel).to receive(:sleep).with(42)
|
219
173
|
|
220
174
|
result = subject.get('/foo')
|
221
|
-
|
222
|
-
expect(result.code).to eq(200)
|
175
|
+
expect(result.code).to eq("200")
|
223
176
|
end
|
224
177
|
|
225
178
|
it "should sleep and retry if Retry-After is an RFC 2822 Date" do
|
226
|
-
|
227
|
-
allow(http).to receive(:request).and_return(httpunavailable, httpok)
|
179
|
+
retry_after('Wed, 13 Apr 2005 15:18:05 GMT')
|
228
180
|
|
229
181
|
now = DateTime.new(2005, 4, 13, 8, 17, 5, '-07:00')
|
230
182
|
allow(DateTime).to receive(:now).and_return(now)
|
231
183
|
|
232
|
-
pool = Puppet.lookup(:http_pool)
|
233
|
-
expect(pool).to receive(:with_connection).with(site, anything).twice.and_yield(http)
|
234
|
-
|
235
184
|
expect(::Kernel).to receive(:sleep).with(60)
|
236
185
|
|
237
186
|
result = subject.get('/foo')
|
238
|
-
|
239
|
-
expect(result.code).to eq(200)
|
187
|
+
expect(result.code).to eq("200")
|
240
188
|
end
|
241
189
|
|
242
190
|
it "should sleep for no more than the Puppet runinterval" do
|
243
|
-
|
244
|
-
allow(http).to receive(:request).and_return(httpunavailable, httpok)
|
191
|
+
retry_after('60')
|
245
192
|
Puppet[:runinterval] = 30
|
246
193
|
|
247
|
-
pool = Puppet.lookup(:http_pool)
|
248
|
-
expect(pool).to receive(:with_connection).with(site, anything).twice.and_yield(http)
|
249
|
-
|
250
194
|
expect(::Kernel).to receive(:sleep).with(30)
|
251
195
|
|
252
196
|
subject.get('/foo')
|
253
197
|
end
|
254
|
-
end
|
255
198
|
|
256
|
-
|
257
|
-
|
199
|
+
it "should sleep for 0 seconds if the RFC 2822 date has past" do
|
200
|
+
retry_after('Wed, 13 Apr 2005 15:18:05 GMT')
|
201
|
+
|
202
|
+
expect(::Kernel).to receive(:sleep).with(0)
|
258
203
|
|
259
|
-
|
204
|
+
subject.get('/foo')
|
205
|
+
end
|
260
206
|
end
|
261
207
|
|
262
|
-
|
263
|
-
|
208
|
+
context "basic auth" do
|
209
|
+
let(:auth) { { :user => 'user', :password => 'password' } }
|
210
|
+
let(:creds) { [ 'user', 'password'] }
|
264
211
|
|
265
|
-
|
266
|
-
|
212
|
+
it "is allowed in get requests" do
|
213
|
+
stub_request(:get, url).with(basic_auth: creds)
|
267
214
|
|
268
|
-
|
269
|
-
|
215
|
+
subject.get('/foo', nil, :basic_auth => auth)
|
216
|
+
end
|
270
217
|
|
271
|
-
|
272
|
-
|
218
|
+
it "is allowed in post requests" do
|
219
|
+
stub_request(:post, url).with(basic_auth: creds)
|
273
220
|
|
274
|
-
|
275
|
-
|
221
|
+
subject.post('/foo', 'data', nil, :basic_auth => auth)
|
222
|
+
end
|
276
223
|
|
277
|
-
|
278
|
-
|
224
|
+
it "is allowed in head requests" do
|
225
|
+
stub_request(:head, url).with(basic_auth: creds)
|
279
226
|
|
280
|
-
|
281
|
-
|
227
|
+
subject.head('/foo', nil, :basic_auth => auth)
|
228
|
+
end
|
282
229
|
|
283
|
-
|
284
|
-
|
230
|
+
it "is allowed in delete requests" do
|
231
|
+
stub_request(:delete, url).with(basic_auth: creds)
|
285
232
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
233
|
+
subject.delete('/foo', nil, :basic_auth => auth)
|
234
|
+
end
|
235
|
+
|
236
|
+
it "is allowed in put requests" do
|
237
|
+
stub_request(:put, url).with(basic_auth: creds)
|
238
|
+
|
239
|
+
subject.put('/foo', 'data', nil, :basic_auth => auth)
|
240
|
+
end
|
290
241
|
end
|
291
242
|
|
292
243
|
it "sets HTTP User-Agent header" do
|
293
244
|
puppet_ua = "Puppet/#{Puppet.version} Ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_PLATFORM})"
|
245
|
+
stub_request(:get, url).with(headers: { 'User-Agent' => puppet_ua })
|
294
246
|
|
295
|
-
|
296
|
-
|
297
|
-
|
247
|
+
subject.get('/foo')
|
248
|
+
end
|
249
|
+
|
250
|
+
describe 'connection request errors' do
|
251
|
+
it "logs and raises generic http errors" do
|
252
|
+
generic_error = Net::HTTPError.new('generic error', double("response"))
|
253
|
+
stub_request(:get, url).to_raise(generic_error)
|
298
254
|
|
299
|
-
|
255
|
+
expect(Puppet).to receive(:log_exception).with(anything, /^.*failed: generic error$/)
|
256
|
+
expect { subject.get('/foo') }.to raise_error(generic_error)
|
257
|
+
end
|
258
|
+
|
259
|
+
it "logs and raises timeout errors" do
|
260
|
+
timeout_error = Timeout::Error.new
|
261
|
+
stub_request(:get, url).to_raise(timeout_error)
|
262
|
+
|
263
|
+
expect(Puppet).to receive(:log_exception).with(anything, /^.*timed out after .* seconds$/)
|
264
|
+
expect { subject.get('/foo') }.to raise_error(timeout_error)
|
265
|
+
end
|
266
|
+
|
267
|
+
it "logs and raises eof errors" do
|
268
|
+
eof_error = EOFError
|
269
|
+
stub_request(:get, url).to_raise(eof_error)
|
270
|
+
|
271
|
+
expect(Puppet).to receive(:log_exception).with(anything, /^.*interrupted after .* seconds$/)
|
272
|
+
expect { subject.get('/foo') }.to raise_error(eof_error)
|
273
|
+
end
|
300
274
|
end
|
301
275
|
end
|