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
@@ -9,22 +9,60 @@ describe Puppet::HTTP::Resolver do
9
9
  let(:uri) { URI.parse('https://www.example.com') }
10
10
 
11
11
  context 'when resolving using settings' do
12
- let(:subject) { Puppet::HTTP::Resolver::Settings.new }
12
+ let(:subject) { Puppet::HTTP::Resolver::Settings.new(client) }
13
13
 
14
- it 'yields a service based on the current ca_server and ca_port settings' do
14
+ it 'returns a service based on the current ca_server and ca_port settings' do
15
15
  Puppet[:ca_server] = 'ca.example.com'
16
16
  Puppet[:ca_port] = 8141
17
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
18
+ service = subject.resolve(session, :ca)
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
+
24
+ context 'when resolving using server_list' do
25
+ before :each do
26
+ Puppet[:server_list] = 'ca.example.com:8141,apple.example.com'
27
+ end
28
+ let(:subject) { Puppet::HTTP::Resolver::ServerList.new(client, server_list_setting: Puppet.settings.setting(:server_list), default_port: 8142, services: [:puppet, :ca]) }
29
+
30
+ it 'returns a service based on the current server_list setting' do
31
+ stub_request(:get, "https://ca.example.com:8141/status/v1/simple/master").to_return(status: 200)
32
+
33
+ service = subject.resolve(session, :ca)
34
+ expect(service).to be_an_instance_of(Puppet::HTTP::Service::Ca)
35
+ expect(service.url.to_s).to eq("https://ca.example.com:8141/puppet-ca/v1")
36
+ end
37
+
38
+ it 'returns a service based on the current server_list setting if the server returns any success codes' do
39
+ stub_request(:get, "https://ca.example.com:8141/status/v1/simple/master").to_return(status: 202)
40
+
41
+ service = subject.resolve(session, :ca)
42
+ expect(service).to be_an_instance_of(Puppet::HTTP::Service::Ca)
43
+ expect(service.url.to_s).to eq("https://ca.example.com:8141/puppet-ca/v1")
44
+ end
45
+
46
+ it 'falls fails if no servers in server_list are accessible' do
47
+ stub_request(:get, "https://ca.example.com:8141/status/v1/simple/master").to_return(status: 503)
48
+ stub_request(:get, "https://apple.example.com:8142/status/v1/simple/master").to_return(status: 503)
49
+
50
+ expect { subject.resolve(session, :ca) }.to raise_error(Puppet::Error, /^Could not select a functional puppet master from server_list:/)
51
+ end
52
+
53
+ it 'cycles through server_list until a valid server is found' do
54
+ stub_request(:get, "https://ca.example.com:8141/status/v1/simple/master").to_return(status: 503)
55
+ stub_request(:get, "https://apple.example.com:8142/status/v1/simple/master").to_return(status: 200)
56
+
57
+ service = subject.resolve(session, :ca)
58
+ expect(service).to be_an_instance_of(Puppet::HTTP::Service::Ca)
59
+ expect(service.url.to_s).to eq("https://apple.example.com:8142/puppet-ca/v1")
22
60
  end
23
61
  end
24
62
 
25
63
  context 'when resolving using SRV' do
26
64
  let(:dns) { double('dns') }
27
- let(:subject) { Puppet::HTTP::Resolver::SRV.new(domain: 'example.com', dns: dns) }
65
+ let(:subject) { Puppet::HTTP::Resolver::SRV.new(client, domain: 'example.com', dns: dns) }
28
66
 
29
67
  def stub_srv(host, port)
30
68
  srv = Resolv::DNS::Resource::IN::SRV.new(0, 0, port, host)
@@ -33,13 +71,12 @@ describe Puppet::HTTP::Resolver do
33
71
  allow(dns).to receive(:getresources).with("_x-puppet-ca._tcp.example.com", Resolv::DNS::Resource::IN::SRV).and_return([srv])
34
72
  end
35
73
 
36
- it 'yields a service based on an SRV record' do
74
+ it 'returns a service based on an SRV record' do
37
75
  stub_srv('ca1.example.com', 8142)
38
76
 
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
77
+ service = subject.resolve(session, :ca)
78
+ expect(service).to be_an_instance_of(Puppet::HTTP::Service::Ca)
79
+ expect(service.url.to_s).to eq("https://ca1.example.com:8142/puppet-ca/v1")
43
80
  end
44
81
  end
45
82
  end
@@ -5,13 +5,64 @@ require 'puppet/http'
5
5
  describe Puppet::HTTP::Service::Ca do
6
6
  let(:ssl_context) { Puppet::SSL::SSLContext.new }
7
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) }
8
+ let(:subject) { client.create_session.route_to(:ca) }
9
+
10
+ before :each do
11
+ Puppet[:ca_server] = 'www.example.com'
12
+ Puppet[:ca_port] = 443
13
+ end
14
+
15
+ context 'when making requests' do
16
+ let(:uri) {"https://www.example.com:443/puppet-ca/v1/certificate/ca"}
17
+
18
+ it 'includes default HTTP headers' do
19
+ stub_request(:get, uri).with do |request|
20
+ expect(request.headers).to include({'X-Puppet-Version' => /./, 'User-Agent' => /./})
21
+ expect(request.headers).to_not include('X-Puppet-Profiling')
22
+ end
23
+
24
+ subject.get_certificate('ca')
25
+ end
26
+
27
+
28
+ it 'includes the X-Puppet-Profiling header when Puppet[:profile] is true' do
29
+ stub_request(:get, uri).with(headers: {'X-Puppet-Version' => /./, 'User-Agent' => /./, 'X-Puppet-Profiling' => 'true'})
30
+
31
+ Puppet[:profile] = true
32
+
33
+ subject.get_certificate('ca')
34
+ end
35
+ end
36
+
37
+ context 'when routing to the CA service' do
38
+ let(:cert) { cert_fixture('ca.pem') }
39
+ let(:pem) { cert.to_pem }
40
+
41
+ it 'defaults the server and port based on settings' do
42
+ Puppet[:ca_server] = 'ca.example.com'
43
+ Puppet[:ca_port] = 8141
44
+
45
+ stub_request(:get, "https://ca.example.com:8141/puppet-ca/v1/certificate/ca").to_return(body: pem)
46
+
47
+ subject.get_certificate('ca')
48
+ end
49
+
50
+ it 'fallbacks to server and masterport' do
51
+ Puppet[:ca_server] = nil
52
+ Puppet[:ca_port] = nil
53
+ Puppet[:server] = 'ca2.example.com'
54
+ Puppet[:masterport] = 8142
55
+
56
+ stub_request(:get, "https://ca2.example.com:8142/puppet-ca/v1/certificate/ca").to_return(body: pem)
57
+
58
+ subject.get_certificate('ca')
59
+ end
60
+ end
10
61
 
11
62
  context 'when getting certificates' do
12
63
  let(:cert) { cert_fixture('ca.pem') }
13
64
  let(:pem) { cert.to_pem }
14
- let(:url) { "https://www.example.com/certificate/ca" }
65
+ let(:url) { "https://www.example.com/puppet-ca/v1/certificate/ca" }
15
66
 
16
67
  it 'gets a certificate from the "certificate" endpoint' do
17
68
  stub_request(:get, url).to_return(body: pem)
@@ -41,7 +92,7 @@ describe Puppet::HTTP::Service::Ca do
41
92
  context 'when getting CRLs' do
42
93
  let(:crl) { crl_fixture('crl.pem') }
43
94
  let(:pem) { crl.to_pem }
44
- let(:url) { "https://www.example.com/certificate_revocation_list/ca" }
95
+ let(:url) { "https://www.example.com/puppet-ca/v1/certificate_revocation_list/ca" }
45
96
 
46
97
  it 'gets a CRL from "certificate_revocation_list" endpoint' do
47
98
  stub_request(:get, url).to_return(body: pem)
@@ -83,7 +134,7 @@ describe Puppet::HTTP::Service::Ca do
83
134
  context 'when submitting a CSR' do
84
135
  let(:request) { request_fixture('request.pem') }
85
136
  let(:pem) { request.to_pem }
86
- let(:url) { "https://www.example.com/certificate_request/infinity" }
137
+ let(:url) { "https://www.example.com/puppet-ca/v1/certificate_request/infinity" }
87
138
 
88
139
  it 'submits a CSR to the "certificate_request" endpoint' do
89
140
  stub_request(:put, url).with(body: pem, headers: { 'Content-Type' => 'text/plain' })
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+ require 'webmock/rspec'
3
+ require 'puppet/http'
4
+
5
+ describe Puppet::HTTP::Service::Report do
6
+ let(:ssl_context) { Puppet::SSL::SSLContext.new }
7
+ let(:client) { Puppet::HTTP::Client.new(ssl_context: ssl_context) }
8
+ let(:subject) { client.create_session.route_to(:report) }
9
+ let(:environment) { Puppet::Node::Environment.create(:testing, []) }
10
+ let(:report) { Puppet::Transaction::Report.new }
11
+
12
+ before :each do
13
+ Puppet[:report_server] = 'www.example.com'
14
+ Puppet[:report_port] = 443
15
+ end
16
+
17
+ context 'when making requests' do
18
+ let(:uri) {"https://www.example.com:443/puppet/v3/report/report?environment=testing"}
19
+
20
+ it 'includes default HTTP headers' do
21
+ stub_request(:put, uri).with do |request|
22
+ expect(request.headers).to include({'X-Puppet-Version' => /./, 'User-Agent' => /./})
23
+ expect(request.headers).to_not include('X-Puppet-Profiling')
24
+ end
25
+
26
+ subject.put_report('report', report, environment: environment)
27
+ end
28
+
29
+ it 'includes the X-Puppet-Profiling header when Puppet[:profile] is true' do
30
+ stub_request(:put, uri).with(headers: {'X-Puppet-Version' => /./, 'User-Agent' => /./, 'X-Puppet-Profiling' => 'true'})
31
+
32
+ Puppet[:profile] = true
33
+
34
+ subject.put_report('report', report, environment: environment)
35
+ end
36
+ end
37
+
38
+ context 'when routing to the report service' do
39
+ it 'defaults the server and port based on settings' do
40
+ Puppet[:report_server] = 'report.example.com'
41
+ Puppet[:report_port] = 8141
42
+
43
+ stub_request(:put, "https://report.example.com:8141/puppet/v3/report/report?environment=testing")
44
+
45
+ subject.put_report('report', report, environment: environment)
46
+ end
47
+
48
+ it 'fallbacks to server and masterport' do
49
+ Puppet[:report_server] = nil
50
+ Puppet[:report_port] = nil
51
+ Puppet[:server] = 'report2.example.com'
52
+ Puppet[:masterport] = 8142
53
+
54
+ stub_request(:put, "https://report2.example.com:8142/puppet/v3/report/report?environment=testing")
55
+
56
+ subject.put_report('report', report, environment: environment)
57
+ end
58
+ end
59
+
60
+ context 'when submitting a report' do
61
+ let(:url) { "https://www.example.com/puppet/v3/report/infinity?environment=testing" }
62
+
63
+ it 'submits a report to the "report" endpoint' do
64
+ stub_request(:put, url)
65
+ .with(
66
+ headers: {
67
+ 'Accept'=>'application/json, application/x-msgpack, text/pson',
68
+ 'Content-Type'=>'application/json',
69
+ }).
70
+ to_return(status: 200, body: "", headers: {})
71
+
72
+ subject.put_report('infinity', report, environment: environment)
73
+ end
74
+
75
+ it 'raises response error if unsuccessful' do
76
+ stub_request(:put, url).to_return(status: [400, 'Bad Request'], headers: {'X-Puppet-Version' => '6.1.8' })
77
+
78
+ expect {
79
+ subject.put_report('infinity', report, environment: environment)
80
+ }.to raise_error do |err|
81
+ expect(err).to be_an_instance_of(Puppet::HTTP::ResponseError)
82
+ expect(err.message).to eq('Bad Request')
83
+ expect(err.response.code).to eq(400)
84
+ end
85
+ end
86
+
87
+ it 'raises an error if unsuccessful, the server version is < 5, and the current serialization format is not pson' do
88
+ Puppet[:preferred_serialization_format] = 'json'
89
+
90
+ stub_request(:put, url).to_return(status: [400, 'Bad Request'], headers: {'X-Puppet-Version' => '4.2.3' })
91
+
92
+ expect {
93
+ subject.put_report('infinity', report, environment: environment)
94
+ }.to raise_error do |err|
95
+ expect(err).to be_an_instance_of(Puppet::HTTP::ProtocolError)
96
+ expect(err.message).to eq('To submit reports to a server running puppetserver 4.2.3, set preferred_serialization_format to pson')
97
+ end
98
+ end
99
+ end
100
+ end
@@ -29,4 +29,24 @@ describe Puppet::HTTP::Service do
29
29
 
30
30
  service.connect(ssl_context: other_ctx)
31
31
  end
32
+
33
+ it 'raises for unknown service names' do
34
+ expect {
35
+ described_class.create_service(client, :westbound)
36
+ }.to raise_error(ArgumentError, "Unknown service westbound")
37
+ end
38
+
39
+ [:ca].each do |name|
40
+ it "returns true for #{name}" do
41
+ expect(described_class.valid_name?(name)).to eq(true)
42
+ end
43
+ end
44
+
45
+ it "returns false when the service name is a string" do
46
+ expect(described_class.valid_name?("ca")).to eq(false)
47
+ end
48
+
49
+ it "returns false for unknown service names" do
50
+ expect(described_class.valid_name?(:westbound)).to eq(false)
51
+ end
32
52
  end
@@ -10,12 +10,12 @@ describe Puppet::HTTP::Session do
10
10
  double('good', url: uri, connect: nil)
11
11
  }
12
12
  let(:bad_service) {
13
- service = double('good', url: uri)
13
+ service = double('bad', url: uri)
14
14
  allow(service).to receive(:connect).and_raise(Puppet::HTTP::ConnectionError, 'whoops')
15
15
  service
16
16
  }
17
17
 
18
- class DummyResolver
18
+ class DummyResolver < Puppet::HTTP::Resolver
19
19
  attr_reader :count
20
20
 
21
21
  def initialize(service)
@@ -23,9 +23,9 @@ describe Puppet::HTTP::Session do
23
23
  @count = 0
24
24
  end
25
25
 
26
- def resolve(session, name, &block)
26
+ def resolve(session, name, ssl_context: nil)
27
27
  @count += 1
28
- yield @service
28
+ return @service if check_connection?(session, @service, ssl_context: ssl_context)
29
29
  end
30
30
  end
31
31
 
@@ -75,28 +75,63 @@ describe Puppet::HTTP::Session do
75
75
  end
76
76
  end
77
77
 
78
- context 'when creating services' do
79
- let(:session) { described_class.new(client, []) }
78
+ context 'when resolving using multiple resolvers' do
79
+ let(:session) { client.create_session }
80
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)
81
+ it "prefers SRV records" do
82
+ Puppet[:use_srv_records] = true
83
+ Puppet[:server_list] = 'foo.example.com,bar.example.com,baz.example.com'
84
+ Puppet[:ca_server] = 'caserver.example.com'
85
85
 
86
- expect(service.url.to_s).to eq("https://ca.example.com:8141/puppet-ca/v1")
86
+ allow_any_instance_of(Puppet::Network::Resolver).to receive(:each_srv_record).and_yield('mars.example.srv', 8140)
87
+ service = session.route_to(:ca)
88
+
89
+ expect(service.url).to eq(URI("https://mars.example.srv:8140/puppet-ca/v1"))
87
90
  end
88
91
 
89
- it 'accepts server and port arguments' do
90
- service = session.create_service(:ca, 'ca2.example.com', 8142)
92
+ it "next prefers :ca_server when explicitly set" do
93
+ Puppet[:use_srv_records] = true
94
+ Puppet[:server_list] = 'foo.example.com,bar.example.com,baz.example.com'
95
+ Puppet[:ca_server] = 'caserver.example.com'
96
+
97
+ service = session.route_to(:ca)
91
98
 
92
- expect(service.url.to_s).to eq("https://ca2.example.com:8142/puppet-ca/v1")
99
+ expect(service.url).to eq(URI("https://caserver.example.com:8140/puppet-ca/v1"))
93
100
  end
94
101
 
95
- it 'raises for unknown service names' do
102
+ it "next prefers the first successful connection from server_list" do
103
+ Puppet[:use_srv_records] = true
104
+ Puppet[:server_list] = 'foo.example.com,bar.example.com,baz.example.com'
105
+
106
+ allow_any_instance_of(Puppet::Network::Resolver).to receive(:each_srv_record)
107
+ stub_request(:get, "https://foo.example.com:8140/status/v1/simple/master").to_return(status: 500)
108
+ stub_request(:get, "https://bar.example.com:8140/status/v1/simple/master").to_return(status: 200)
109
+
110
+ service = session.route_to(:ca)
111
+
112
+ expect(service.url).to eq(URI("https://bar.example.com:8140/puppet-ca/v1"))
113
+ end
114
+
115
+ it "fails if server_list doesn't return anything valid" do
116
+ Puppet[:server_list] = 'foo.example.com,bar.example.com'
117
+
118
+ allow_any_instance_of(Puppet::Network::Resolver).to receive(:each_srv_record)
119
+ stub_request(:get, "https://foo.example.com:8140/status/v1/simple/master").to_return(status: 500)
120
+ stub_request(:get, "https://bar.example.com:8140/status/v1/simple/master").to_return(status: 500)
121
+
96
122
  expect {
97
- session = described_class.new(client, [])
98
- session.create_service(:westbound)
99
- }.to raise_error(ArgumentError, "Unknown service westbound")
123
+ session.route_to(:ca)
124
+ }.to raise_error(Puppet::Error, "Could not select a functional puppet master from server_list: 'foo.example.com,bar.example.com'")
125
+ end
126
+
127
+
128
+ it "raises when there are no more routes" do
129
+ allow_any_instance_of(Net::HTTP).to receive(:start).and_raise(Errno::EHOSTUNREACH)
130
+ session = client.create_session
131
+
132
+ expect {
133
+ session.route_to(:ca)
134
+ }.to raise_error(Puppet::HTTP::RouteError, 'No more routes to ca')
100
135
  end
101
136
  end
102
137
  end
@@ -1,6 +1,5 @@
1
1
  require 'spec_helper'
2
2
  require 'puppet/network/http/connection'
3
- require 'puppet_spec/validators'
4
3
  require 'puppet/test_ca'
5
4
 
6
5
  describe Puppet::Network::HTTP::Connection do
@@ -478,21 +478,26 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
478
478
  }.each do |source, coerced_val|
479
479
  it "should warn about numeric coercion in '#{source}' when strict = warning" do
480
480
  Puppet[:strict] = :warning
481
+ expect(Puppet::Pops::Evaluator::Runtime3Support::EvaluationError).not_to receive(:new)
481
482
  collect_notices(source)
482
483
  expect(warnings).to include(/The string '#{coerced_val}' was automatically coerced to the numerical value #{coerced_val}/)
483
484
  end
484
485
 
485
486
  it "should not warn about numeric coercion in '#{source}' if strict = off" do
486
487
  Puppet[:strict] = :off
488
+ expect(Puppet::Pops::Evaluator::Runtime3Support::EvaluationError).not_to receive(:new)
487
489
  collect_notices(source)
488
490
  expect(warnings).to_not include(/The string '#{coerced_val}' was automatically coerced to the numerical value #{coerced_val}/)
489
491
  end
490
492
 
491
493
  it "should error when finding numeric coercion in '#{source}' if strict = error" do
492
494
  Puppet[:strict] = :error
493
- expect { parser.evaluate_string(scope, source, __FILE__) }.to raise_error(
494
- /The string '#{coerced_val}' was automatically coerced to the numerical value #{coerced_val}/
495
- )
495
+ expect {
496
+ parser.evaluate_string(scope, source, __FILE__)
497
+ }.to raise_error {|error|
498
+ expect(error.message).to match(/The string '#{coerced_val}' was automatically coerced to the numerical value #{coerced_val}/)
499
+ expect(error.backtrace.first).to match(/runtime3_support\.rb.+optionally_fail/)
500
+ }
496
501
  end
497
502
  end
498
503
 
@@ -44,13 +44,13 @@ describe Puppet::Type.type(:package).provider(:portage) do
44
44
  allow(@unslotted_provider).to receive(:qatom).and_return({:category=>"dev-lang", :pn=>"ruby", :pv=>nil, :pr=>nil, :slot=>nil, :pfx=>nil, :sfx=>nil})
45
45
  allow(@unslotted_provider.class).to receive(:emerge).with('--list-sets').and_return(package_sets)
46
46
  @slotted_provider = described_class.new(@slotted_resource)
47
- allow(@slotted_provider).to receive(:qatom).and_return({:category=>"dev-lang", :pn=>"ruby", :pv=>nil, :pr=>nil, :slot=>":2.1", :pfx=>nil, :sfx=>nil})
47
+ allow(@slotted_provider).to receive(:qatom).and_return({:category=>"dev-lang", :pn=>"ruby", :pv=>nil, :pr=>nil, :slot=>"2.1", :pfx=>nil, :sfx=>nil})
48
48
  allow(@slotted_provider.class).to receive(:emerge).with('--list-sets').and_return(package_sets)
49
49
  @versioned_provider = described_class.new(@versioned_resource)
50
50
  allow(@versioned_provider).to receive(:qatom).and_return({:category=>"dev-lang", :pn=>"ruby", :pv=>"1.9.3", :pr=>nil, :slot=>nil, :pfx=>"=", :sfx=>nil})
51
51
  allow(@versioned_provider.class).to receive(:emerge).with('--list-sets').and_return(package_sets)
52
52
  @versioned_slotted_provider = described_class.new(@versioned_slotted_resource)
53
- allow(@versioned_slotted_provider).to receive(:qatom).and_return({:category=>"dev-lang", :pn=>"ruby", :pv=>"1.9.3", :pr=>nil, :slot=>":1.9", :pfx=>"=", :sfx=>nil})
53
+ allow(@versioned_slotted_provider).to receive(:qatom).and_return({:category=>"dev-lang", :pn=>"ruby", :pv=>"1.9.3", :pr=>nil, :slot=>"1.9", :pfx=>"=", :sfx=>nil})
54
54
  allow(@versioned_slotted_provider.class).to receive(:emerge).with('--list-sets').and_return(package_sets)
55
55
  @set_provider = described_class.new(@set_resource)
56
56
  allow(@set_provider).to receive(:qatom).and_return({:category=>nil, :pn=>"@system", :pv=>nil, :pr=>nil, :slot=>nil, :pfx=>nil, :sfx=>nil})
@@ -180,7 +180,7 @@ describe Puppet::Type.type(:package).provider(:portage) do
180
180
  end
181
181
 
182
182
  it "can extract the slot from the package name" do
183
- expect(@slotted_provider.qatom[:slot]).to eq(':2.1')
183
+ expect(@slotted_provider.qatom[:slot]).to eq('2.1')
184
184
  end
185
185
 
186
186
  it "returns nil for as the slot when no slot is specified" do
@@ -196,7 +196,7 @@ describe Puppet::Type.type(:package).provider(:portage) do
196
196
  expect(@versioned_slotted_provider.qatom[:category]).to eq('dev-lang')
197
197
  expect(@versioned_slotted_provider.qatom[:pn]).to eq('ruby')
198
198
  expect(@versioned_slotted_provider.qatom[:pv]).to eq('1.9.3')
199
- expect(@versioned_slotted_provider.qatom[:slot]).to eq(':1.9')
199
+ expect(@versioned_slotted_provider.qatom[:slot]).to eq('1.9')
200
200
  end
201
201
 
202
202
  it "can handle search output with slots for unslotted packages" do