puppet 6.12.0-x86-mingw32 → 6.13.0-x86-mingw32
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.lock +12 -12
- data/README.md +1 -1
- data/ext/project_data.yaml +1 -1
- data/lib/puppet.rb +22 -7
- data/lib/puppet/application/resource.rb +1 -1
- data/lib/puppet/configurer.rb +8 -13
- data/lib/puppet/defaults.rb +83 -49
- data/lib/puppet/environments.rb +26 -18
- data/lib/puppet/face/facts.rb +8 -5
- data/lib/puppet/file_system/memory_file.rb +6 -0
- data/lib/puppet/file_system/memory_impl.rb +13 -0
- data/lib/puppet/file_system/windows.rb +7 -10
- data/lib/puppet/http.rb +2 -0
- data/lib/puppet/http/client.rb +30 -0
- data/lib/puppet/http/errors.rb +2 -0
- data/lib/puppet/http/service.rb +61 -2
- data/lib/puppet/http/service/compiler.rb +86 -0
- data/lib/puppet/http/service/file_server.rb +85 -0
- data/lib/puppet/http/service/report.rb +4 -8
- data/lib/puppet/http/session.rb +8 -1
- data/lib/puppet/indirector/catalog/compiler.rb +10 -0
- data/lib/puppet/indirector/file_bucket_file/file.rb +1 -1
- data/lib/puppet/indirector/json.rb +1 -1
- data/lib/puppet/indirector/msgpack.rb +1 -1
- data/lib/puppet/network/http/connection.rb +4 -0
- data/lib/puppet/network/http/nocache_pool.rb +1 -0
- data/lib/puppet/network/http/pool.rb +5 -1
- data/lib/puppet/parser/ast/pops_bridge.rb +6 -11
- data/lib/puppet/pops/evaluator/access_operator.rb +2 -2
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +1 -1
- data/lib/puppet/pops/loader/puppet_plan_instantiator.rb +12 -3
- data/lib/puppet/pops/parser/evaluating_parser.rb +5 -7
- data/lib/puppet/pops/types/p_object_type_extension.rb +10 -0
- data/lib/puppet/pops/types/type_calculator.rb +24 -0
- data/lib/puppet/pops/validation/checker4_0.rb +1 -1
- data/lib/puppet/pops/validation/tasks_checker.rb +5 -1
- data/lib/puppet/provider/aix_object.rb +4 -2
- data/lib/puppet/provider/group/aix.rb +1 -0
- data/lib/puppet/provider/group/groupadd.rb +52 -24
- data/lib/puppet/provider/package/apt.rb +14 -3
- data/lib/puppet/provider/package/dnfmodule.rb +9 -2
- data/lib/puppet/provider/package/dpkg.rb +14 -7
- data/lib/puppet/provider/package/fink.rb +20 -3
- data/lib/puppet/provider/package/openbsd.rb +13 -1
- data/lib/puppet/provider/package/pkg.rb +18 -5
- data/lib/puppet/provider/package/yum.rb +9 -5
- data/lib/puppet/provider/user/aix.rb +1 -0
- data/lib/puppet/provider/user/directoryservice.rb +30 -5
- data/lib/puppet/provider/user/useradd.rb +6 -7
- data/lib/puppet/reports/store.rb +1 -1
- data/lib/puppet/settings.rb +2 -0
- data/lib/puppet/ssl/certificate.rb +2 -1
- data/lib/puppet/test/test_helper.rb +4 -0
- data/lib/puppet/transaction/resource_harness.rb +1 -1
- data/lib/puppet/type/group.rb +2 -2
- data/lib/puppet/type/package.rb +63 -9
- data/lib/puppet/type/user.rb +2 -2
- data/lib/puppet/util/log/destinations.rb +1 -1
- data/lib/puppet/util/pidlock.rb +26 -6
- data/lib/puppet/util/plist.rb +6 -0
- data/lib/puppet/util/storage.rb +0 -1
- data/lib/puppet/util/yaml.rb +1 -1
- data/lib/puppet/version.rb +1 -1
- data/locales/puppet.pot +127 -115
- data/man/man5/puppet.conf.5 +21 -7
- 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/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_fetch_if_not_on_the_local_disk.yml +0 -35
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_not_update_if_content_on_disk_is_up-to-date.yml +0 -37
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_update_if_content_differs_on_disk.yml +0 -37
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_mtime_is_older_on_disk.yml +0 -35
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_no_header_specified.yml +0 -33
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_not_on_the_local_disk.yml +0 -35
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_not_update_if_mtime_is_newer_on_disk.yml +0 -35
- data/spec/integration/configurer_spec.rb +26 -7
- data/spec/integration/indirector/facts/facter_spec.rb +4 -0
- data/spec/unit/application/apply_spec.rb +2 -12
- data/spec/unit/application/resource_spec.rb +2 -2
- data/spec/unit/configurer/fact_handler_spec.rb +0 -4
- data/spec/unit/configurer_spec.rb +0 -3
- data/spec/unit/defaults_spec.rb +1 -1
- data/spec/unit/environments_spec.rb +57 -28
- data/spec/unit/face/facts_spec.rb +24 -20
- data/spec/unit/file_system_spec.rb +16 -2
- data/spec/unit/http/client_spec.rb +6 -0
- data/spec/unit/http/service/compiler_spec.rb +322 -0
- data/spec/unit/http/service/file_server_spec.rb +219 -0
- data/spec/unit/http/service/report_spec.rb +8 -1
- data/spec/unit/http/service_spec.rb +4 -0
- data/spec/unit/http/session_spec.rb +31 -0
- data/spec/unit/indirector/catalog/compiler_spec.rb +46 -29
- data/spec/unit/network/http/connection_spec.rb +23 -1
- data/spec/unit/network/http/nocache_pool_spec.rb +3 -3
- data/spec/unit/network/http/pool_spec.rb +32 -0
- data/spec/unit/node/facts_spec.rb +2 -1
- data/spec/unit/node_spec.rb +7 -4
- data/spec/unit/pops/serialization/to_from_hr_spec.rb +6 -1
- data/spec/unit/pops/validator/validator_spec.rb +7 -2
- data/spec/unit/provider/aix_object_spec.rb +16 -2
- data/spec/unit/provider/group/groupadd_spec.rb +167 -56
- data/spec/unit/provider/package/apt_spec.rb +13 -2
- data/spec/unit/provider/package/aptitude_spec.rb +1 -0
- data/spec/unit/provider/package/dnfmodule_spec.rb +22 -0
- data/spec/unit/provider/package/dpkg_spec.rb +28 -6
- data/spec/unit/provider/package/openbsd_spec.rb +17 -0
- data/spec/unit/provider/package/pkg_spec.rb +15 -1
- data/spec/unit/provider/package/yum_spec.rb +50 -0
- data/spec/unit/provider/user/directoryservice_spec.rb +41 -0
- data/spec/unit/provider/user/useradd_spec.rb +13 -8
- data/spec/unit/puppet_pal_2pec.rb +3 -0
- data/spec/unit/puppet_pal_catalog_spec.rb +3 -0
- data/spec/unit/puppet_spec.rb +14 -0
- data/spec/unit/ssl/certificate_spec.rb +7 -0
- data/spec/unit/transaction/persistence_spec.rb +1 -10
- data/spec/unit/type/package_spec.rb +8 -0
- data/spec/unit/type/user_spec.rb +0 -1
- data/spec/unit/util/pidlock_spec.rb +38 -16
- data/spec/unit/util/plist_spec.rb +20 -0
- data/spec/unit/util/storage_spec.rb +1 -8
- metadata +10 -4
@@ -12,9 +12,12 @@ describe Puppet::Face[:facts, '0.0.1'] do
|
|
12
12
|
let(:model) { Puppet::Node::Facts }
|
13
13
|
let(:test_data) { model.new('puppet.node.test', {test_fact: 'test value'}) }
|
14
14
|
let(:facter_terminus) { model.indirection.terminus(:facter) }
|
15
|
-
let(:rest_terminus) { model.indirection.terminus(:rest) }
|
16
15
|
|
17
16
|
before(:each) do
|
17
|
+
Puppet[:facts_terminus] = :memory
|
18
|
+
Puppet::Node::Facts.indirection.save(test_data)
|
19
|
+
allow(Puppet::Node::Facts.indirection).to receive(:terminus_class=).with(:facter)
|
20
|
+
|
18
21
|
Puppet.settings.parse_config(<<-CONF)
|
19
22
|
[main]
|
20
23
|
server=puppet.server.invalid
|
@@ -26,45 +29,46 @@ CONF
|
|
26
29
|
|
27
30
|
# Faces start in :user run mode
|
28
31
|
Puppet.settings.preferred_run_mode = :user
|
29
|
-
|
30
|
-
allow(facter_terminus).to receive(:find).with(instance_of(Puppet::Indirector::Request)).and_return(test_data)
|
31
|
-
allow(rest_terminus).to receive(:save).with(instance_of(Puppet::Indirector::Request)).and_return(nil)
|
32
|
-
end
|
33
|
-
|
34
|
-
it { is_expected.to be_action :upload }
|
35
|
-
|
36
|
-
it "finds facts from terminus_class :facter" do
|
37
|
-
expect(facter_terminus).to receive(:find).with(instance_of(Puppet::Indirector::Request)).and_return(test_data)
|
38
|
-
|
39
|
-
subject.upload
|
40
32
|
end
|
41
33
|
|
42
|
-
it "
|
43
|
-
|
34
|
+
it "uploads facts as application/json" do
|
35
|
+
stub_request(:put, 'https://puppet.server.test:8140/puppet/v3/facts/puppet.node.test?environment=*root*')
|
36
|
+
.with(
|
37
|
+
headers: { 'Content-Type' => 'application/json' },
|
38
|
+
body: hash_including(
|
39
|
+
{
|
40
|
+
"name" => "puppet.node.test",
|
41
|
+
"values" => {
|
42
|
+
"test_fact" => "test value"
|
43
|
+
}
|
44
|
+
}
|
45
|
+
)
|
46
|
+
)
|
44
47
|
|
45
48
|
subject.upload
|
46
49
|
end
|
47
50
|
|
48
51
|
it "passes the current environment" do
|
49
|
-
|
50
|
-
expect(model.indirection).to receive(:save).with(anything, nil, :environment => env)
|
52
|
+
stub_request(:put, 'https://puppet.server.test:8140/puppet/v3/facts/puppet.node.test?environment=qa')
|
51
53
|
|
52
|
-
Puppet.override(:current_environment =>
|
54
|
+
Puppet.override(:current_environment => Puppet::Node::Environment.remote('qa')) do
|
53
55
|
subject.upload
|
54
56
|
end
|
55
57
|
end
|
56
58
|
|
57
|
-
it "uses settings from the agent section of puppet.conf" do
|
58
|
-
|
59
|
+
it "uses settings from the agent section of puppet.conf to resolve the node name" do
|
60
|
+
stub_request(:put, /puppet.node.test/)
|
59
61
|
|
60
62
|
subject.upload
|
61
63
|
end
|
62
64
|
|
63
65
|
it "logs the name of the server that received the upload" do
|
66
|
+
stub_request(:put, 'https://puppet.server.test:8140/puppet/v3/facts/puppet.node.test?environment=*root*')
|
67
|
+
|
64
68
|
subject.upload
|
65
69
|
|
66
70
|
expect(@logs).to be_any {|log| log.level == :notice &&
|
67
|
-
log.message =~ /Uploading facts for '.*' to
|
71
|
+
log.message =~ /Uploading facts for '.*' to 'puppet\.server\.test'/}
|
68
72
|
end
|
69
73
|
end
|
70
74
|
end
|
@@ -988,7 +988,7 @@ describe "Puppet::FileSystem" do
|
|
988
988
|
it 'rejects unsupported modes' do
|
989
989
|
expect {
|
990
990
|
Puppet::FileSystem.replace_file(dest, 0755) { |_| }
|
991
|
-
}.to raise_error(ArgumentError, /Only modes 0644, 0640 and
|
991
|
+
}.to raise_error(ArgumentError, /Only modes 0644, 0640, 0660, and 0440 are allowed/)
|
992
992
|
end
|
993
993
|
end
|
994
994
|
end
|
@@ -1065,12 +1065,26 @@ describe "Puppet::FileSystem" do
|
|
1065
1065
|
end
|
1066
1066
|
end
|
1067
1067
|
|
1068
|
-
it 'applies
|
1068
|
+
it 'applies 0644 mode' do
|
1069
1069
|
Puppet::FileSystem.replace_file(dest, 0644) { |f| f.write(content) }
|
1070
1070
|
|
1071
1071
|
expects_public_file(dest)
|
1072
1072
|
end
|
1073
1073
|
|
1074
|
+
[0660, 0640, 0600, 0440].each do |mode|
|
1075
|
+
it "applies #{mode} mode" do
|
1076
|
+
Puppet::FileSystem.replace_file(dest, mode) { |f| f.write(content) }
|
1077
|
+
current_sid = Puppet::Util::Windows::SID.name_to_sid(Puppet::Util::Windows::ADSI::User.current_user_name)
|
1078
|
+
sd = Puppet::Util::Windows::Security.get_security_descriptor(dest)
|
1079
|
+
|
1080
|
+
expect(sd.dacl).to contain_exactly(
|
1081
|
+
an_object_having_attributes(sid: Puppet::Util::Windows::SID::LocalSystem, mask: 0x1f01ff),
|
1082
|
+
an_object_having_attributes(sid: Puppet::Util::Windows::SID::BuiltinAdministrators, mask: 0x1f01ff),
|
1083
|
+
an_object_having_attributes(sid: current_sid, mask: 0x1f01ff),
|
1084
|
+
)
|
1085
|
+
end
|
1086
|
+
end
|
1087
|
+
|
1074
1088
|
it 'raises Errno::EACCES if access is denied' do
|
1075
1089
|
allow(Puppet::Util::Windows::Security).to receive(:get_security_descriptor).and_raise(Puppet::Util::Windows::Error.new('access denied', 5))
|
1076
1090
|
|
@@ -99,6 +99,12 @@ describe Puppet::HTTP::Client do
|
|
99
99
|
client.get(uri, params: {:foo => "bar=baz"})
|
100
100
|
end
|
101
101
|
|
102
|
+
it "fails if a user passes in an invalid param type" do
|
103
|
+
environment = Puppet::Node::Environment.create(:testing, [])
|
104
|
+
|
105
|
+
expect{client.get(uri, params: {environment: environment})}.to raise_error(Puppet::HTTP::SerializationError, /HTTP REST queries cannot handle values of type/)
|
106
|
+
end
|
107
|
+
|
102
108
|
it "merges custom headers with default ones" do
|
103
109
|
stub_request(:get, uri).with(headers: { 'X-Foo' => 'Bar', 'X-Puppet-Version' => /./, 'User-Agent' => /./ })
|
104
110
|
|
@@ -0,0 +1,322 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'webmock/rspec'
|
4
|
+
require 'puppet/http'
|
5
|
+
|
6
|
+
describe Puppet::HTTP::Service::Compiler do
|
7
|
+
let(:ssl_context) { Puppet::SSL::SSLContext.new }
|
8
|
+
let(:client) { Puppet::HTTP::Client.new(ssl_context: ssl_context) }
|
9
|
+
let(:subject) { client.create_session.route_to(:puppet) }
|
10
|
+
let(:environment) { 'testing' }
|
11
|
+
let(:certname) { 'ziggy' }
|
12
|
+
let(:node) { Puppet::Node.new(certname) }
|
13
|
+
let(:facts) { Puppet::Node::Facts.new(certname) }
|
14
|
+
let(:catalog) { Puppet::Resource::Catalog.new(certname) }
|
15
|
+
let(:formatter) { Puppet::Network::FormatHandler.format(:json) }
|
16
|
+
|
17
|
+
before :each do
|
18
|
+
Puppet[:server] = 'compiler.example.com'
|
19
|
+
Puppet[:masterport] = 8140
|
20
|
+
|
21
|
+
Puppet::Node::Facts.indirection.terminus_class = :memory
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when making requests' do
|
25
|
+
let(:uri) {"https://compiler.example.com:8140/puppet/v3/catalog/ziggy?environment=testing"}
|
26
|
+
|
27
|
+
it 'includes default HTTP headers' do
|
28
|
+
stub_request(:post, uri).with do |request|
|
29
|
+
expect(request.headers).to include({'X-Puppet-Version' => /./, 'User-Agent' => /./})
|
30
|
+
expect(request.headers).to_not include('X-Puppet-Profiling')
|
31
|
+
end.to_return(body: formatter.render(catalog), headers: {'Content-Type' => formatter.mime })
|
32
|
+
|
33
|
+
subject.get_catalog(certname, environment: environment, facts: facts)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'includes the X-Puppet-Profiling header in requests when Puppet[:profile] is true' do
|
37
|
+
stub_request(:post, uri).with(headers: {'X-Puppet-Version' => /./, 'User-Agent' => /./, 'X-Puppet-Profiling' => 'true'})
|
38
|
+
.to_return(body: formatter.render(catalog), headers: {'Content-Type' => formatter.mime })
|
39
|
+
|
40
|
+
Puppet[:profile] = true
|
41
|
+
|
42
|
+
subject.get_catalog(certname, environment: environment, facts: facts)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when routing to the compiler service' do
|
47
|
+
it 'defaults the server and port based on settings' do
|
48
|
+
Puppet[:server] = 'compiler2.example.com'
|
49
|
+
Puppet[:masterport] = 8141
|
50
|
+
|
51
|
+
stub_request(:post, "https://compiler2.example.com:8141/puppet/v3/catalog/ziggy?environment=testing")
|
52
|
+
.to_return(body: formatter.render(catalog), headers: {'Content-Type' => formatter.mime })
|
53
|
+
|
54
|
+
subject.get_catalog(certname, environment: environment, facts: facts)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when posting for a catalog' do
|
59
|
+
let(:uri) { %r{/puppet/v3/catalog/ziggy} }
|
60
|
+
let(:catalog_response) { { body: formatter.render(catalog), headers: {'Content-Type' => formatter.mime } } }
|
61
|
+
|
62
|
+
it 'submits facts as application/json by default' do
|
63
|
+
stub_request(:post, uri)
|
64
|
+
.with(body: hash_including("facts_format" => /application\/json/))
|
65
|
+
.to_return(**catalog_response)
|
66
|
+
|
67
|
+
subject.get_catalog(certname, environment: environment, facts: facts)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'submits facts as pson if set as the preferred format' do
|
71
|
+
Puppet[:preferred_serialization_format] = "pson"
|
72
|
+
|
73
|
+
stub_request(:post, uri)
|
74
|
+
.with(body: hash_including("facts_format" => /pson/))
|
75
|
+
.to_return(**catalog_response)
|
76
|
+
|
77
|
+
subject.get_catalog(certname, environment: environment, facts: facts)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'includes environment as a query parameter AND in the POST body' do
|
81
|
+
stub_request(:post, uri)
|
82
|
+
.with(query: {"environment" => "outerspace"},
|
83
|
+
body: hash_including("environment" => 'outerspace'))
|
84
|
+
.to_return(**catalog_response)
|
85
|
+
|
86
|
+
subject.get_catalog(certname, environment: 'outerspace', facts: facts)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'includes configured_environment' do
|
90
|
+
stub_request(:post, uri)
|
91
|
+
.with(body: hash_including("configured_environment" => 'agent_specified'))
|
92
|
+
.to_return(**catalog_response)
|
93
|
+
|
94
|
+
subject.get_catalog(certname, environment: 'production', facts: facts, configured_environment: 'agent_specified')
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'includes transaction_uuid' do
|
98
|
+
uuid = "ec3d2844-b236-4287-b0ad-632fbb4d1ff0"
|
99
|
+
|
100
|
+
stub_request(:post, uri)
|
101
|
+
.with(body: hash_including("transaction_uuid" => uuid))
|
102
|
+
.to_return(**catalog_response)
|
103
|
+
|
104
|
+
subject.get_catalog(certname, environment: 'production', facts: facts, transaction_uuid: uuid)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'includes job_uuid' do
|
108
|
+
uuid = "3dd13eec-1b6b-4b5d-867b-148193e0593e"
|
109
|
+
|
110
|
+
stub_request(:post, uri)
|
111
|
+
.with(body: hash_including("job_uuid" => uuid))
|
112
|
+
.to_return(**catalog_response)
|
113
|
+
|
114
|
+
subject.get_catalog(certname, environment: 'production', facts: facts, job_uuid: uuid)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'includes static_catalog' do
|
118
|
+
stub_request(:post, uri)
|
119
|
+
.with(body: hash_including("static_catalog" => "false"))
|
120
|
+
.to_return(**catalog_response)
|
121
|
+
|
122
|
+
subject.get_catalog(certname, environment: 'production', facts: facts, static_catalog: false)
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'includes dot-separated list of checksum_types' do
|
126
|
+
stub_request(:post, uri)
|
127
|
+
.with(body: hash_including("checksum_type" => "sha256.sha384"))
|
128
|
+
.to_return(**catalog_response)
|
129
|
+
|
130
|
+
subject.get_catalog(certname, environment: 'production', facts: facts, checksum_type: %w[sha256 sha384])
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'returns a deserialized catalog' do
|
134
|
+
stub_request(:post, uri)
|
135
|
+
.to_return(**catalog_response)
|
136
|
+
|
137
|
+
cat = subject.get_catalog(certname, environment: 'production', facts: facts)
|
138
|
+
expect(cat).to be_a(Puppet::Resource::Catalog)
|
139
|
+
expect(cat.name).to eq(certname)
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'raises a response error if unsuccessful' do
|
143
|
+
stub_request(:post, uri)
|
144
|
+
.to_return(status: [500, "Server Error"])
|
145
|
+
|
146
|
+
expect {
|
147
|
+
subject.get_catalog(certname, environment: 'production', facts: facts)
|
148
|
+
}.to raise_error do |err|
|
149
|
+
expect(err).to be_an_instance_of(Puppet::HTTP::ResponseError)
|
150
|
+
expect(err.message).to eq('Server Error')
|
151
|
+
expect(err.response.code).to eq(500)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'raises a protocol error if the content-type header is missing' do
|
156
|
+
stub_request(:post, uri)
|
157
|
+
.to_return(body: "content-type is missing")
|
158
|
+
|
159
|
+
expect {
|
160
|
+
subject.get_catalog(certname, environment: 'production', facts: facts)
|
161
|
+
}.to raise_error(Puppet::HTTP::ProtocolError, /No content type in http response; cannot parse/)
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'raises a serialization error if the content is invalid' do
|
165
|
+
stub_request(:post, uri)
|
166
|
+
.to_return(body: "this isn't valid JSON", headers: {'Content-Type' => 'application/json'})
|
167
|
+
|
168
|
+
expect {
|
169
|
+
subject.get_catalog(certname, environment: 'production', facts: facts)
|
170
|
+
}.to raise_error(Puppet::HTTP::SerializationError, /Failed to deserialize Puppet::Resource::Catalog from json/)
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'serializing facts' do
|
174
|
+
facts_with_special_characters = [
|
175
|
+
{ :hash => { 'afact' => 'a+b' }, :encoded => 'a%2Bb' },
|
176
|
+
{ :hash => { 'afact' => 'a b' }, :encoded => 'a%20b' },
|
177
|
+
{ :hash => { 'afact' => 'a&b' }, :encoded => 'a%26b' },
|
178
|
+
{ :hash => { 'afact' => 'a*b' }, :encoded => 'a%2Ab' },
|
179
|
+
{ :hash => { 'afact' => 'a=b' }, :encoded => 'a%3Db' },
|
180
|
+
# different UTF-8 widths
|
181
|
+
# 1-byte A
|
182
|
+
# 2-byte ۿ - http://www.fileformat.info/info/unicode/char/06ff/index.htm - 0xDB 0xBF / 219 191
|
183
|
+
# 3-byte ᚠ - http://www.fileformat.info/info/unicode/char/16A0/index.htm - 0xE1 0x9A 0xA0 / 225 154 160
|
184
|
+
# 4-byte 𠜎 - http://www.fileformat.info/info/unicode/char/2070E/index.htm - 0xF0 0xA0 0x9C 0x8E / 240 160 156 142
|
185
|
+
{ :hash => { 'afact' => "A\u06FF\u16A0\u{2070E}" }, :encoded => 'A%DB%BF%E1%9A%A0%F0%A0%9C%8E' },
|
186
|
+
]
|
187
|
+
|
188
|
+
facts_with_special_characters.each do |test_fact|
|
189
|
+
it "escapes special characters #{test_fact[:hash]}" do
|
190
|
+
facts = Puppet::Node::Facts.new(certname, test_fact[:hash])
|
191
|
+
Puppet::Node::Facts.indirection.save(facts)
|
192
|
+
|
193
|
+
stub_request(:post, uri)
|
194
|
+
.with(body: hash_including("facts" => /#{test_fact[:encoded]}/))
|
195
|
+
.to_return(**catalog_response)
|
196
|
+
|
197
|
+
subject.get_catalog(certname, environment: environment, facts: facts)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
context 'when getting a node' do
|
204
|
+
let(:uri) { %r{/puppet/v3/node/ziggy} }
|
205
|
+
let(:node_response) { { body: formatter.render(node), headers: {'Content-Type' => formatter.mime } } }
|
206
|
+
|
207
|
+
it 'includes environment' do
|
208
|
+
stub_request(:get, uri)
|
209
|
+
.with(query: hash_including("environment" => "outerspace"))
|
210
|
+
.to_return(**node_response)
|
211
|
+
|
212
|
+
subject.get_node(certname, environment: 'outerspace')
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'includes configured_environment' do
|
216
|
+
stub_request(:get, uri)
|
217
|
+
.with(query: hash_including("configured_environment" => 'agent_specified'))
|
218
|
+
.to_return(**node_response)
|
219
|
+
|
220
|
+
subject.get_node(certname, environment: 'production', configured_environment: 'agent_specified')
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'includes transaction_uuid' do
|
224
|
+
uuid = "ec3d2844-b236-4287-b0ad-632fbb4d1ff0"
|
225
|
+
|
226
|
+
stub_request(:get, uri)
|
227
|
+
.with(query: hash_including("transaction_uuid" => uuid))
|
228
|
+
.to_return(**node_response)
|
229
|
+
|
230
|
+
subject.get_node(certname, environment: 'production', transaction_uuid: uuid)
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'returns a deserialized node' do
|
234
|
+
stub_request(:get, uri)
|
235
|
+
.to_return(**node_response)
|
236
|
+
|
237
|
+
n = subject.get_node(certname, environment: 'production')
|
238
|
+
expect(n).to be_a(Puppet::Node)
|
239
|
+
expect(n.name).to eq(certname)
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'raises a response error if unsuccessful' do
|
243
|
+
stub_request(:get, uri)
|
244
|
+
.to_return(status: [500, "Server Error"])
|
245
|
+
|
246
|
+
expect {
|
247
|
+
subject.get_node(certname, environment: 'production')
|
248
|
+
}.to raise_error do |err|
|
249
|
+
expect(err).to be_an_instance_of(Puppet::HTTP::ResponseError)
|
250
|
+
expect(err.message).to eq('Server Error')
|
251
|
+
expect(err.response.code).to eq(500)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'raises a protocol error if the content-type header is missing' do
|
256
|
+
stub_request(:get, uri)
|
257
|
+
.to_return(body: "content-type is missing")
|
258
|
+
|
259
|
+
expect {
|
260
|
+
subject.get_node(certname, environment: 'production')
|
261
|
+
}.to raise_error(Puppet::HTTP::ProtocolError, /No content type in http response; cannot parse/)
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'raises a serialization error if the content is invalid' do
|
265
|
+
stub_request(:get, uri)
|
266
|
+
.to_return(body: "this isn't valid JSON", headers: {'Content-Type' => 'application/json'})
|
267
|
+
|
268
|
+
expect {
|
269
|
+
subject.get_node(certname, environment: 'production')
|
270
|
+
}.to raise_error(Puppet::HTTP::SerializationError, /Failed to deserialize Puppet::Node from json/)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
context 'when putting facts' do
|
275
|
+
let(:uri) { %r{/puppet/v3/facts/ziggy} }
|
276
|
+
|
277
|
+
it 'serializes facts in the body' do
|
278
|
+
facts = Puppet::Node::Facts.new(certname, { 'domain' => 'zork'})
|
279
|
+
Puppet::Node::Facts.indirection.save(facts)
|
280
|
+
|
281
|
+
stub_request(:put, uri)
|
282
|
+
.with(body: hash_including("name" => "ziggy", "values" => {"domain" => "zork"}))
|
283
|
+
|
284
|
+
subject.put_facts(certname, environment: environment, facts: facts)
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'includes environment' do
|
288
|
+
stub_request(:put, uri)
|
289
|
+
.with(query: {"environment" => "outerspace"})
|
290
|
+
|
291
|
+
subject.put_facts(certname, environment: 'outerspace', facts: facts)
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'returns true' do
|
295
|
+
# the REST API returns the filename, good grief
|
296
|
+
stub_request(:put, uri)
|
297
|
+
.to_return(status: 200, body: "/opt/puppetlabs/server/data/puppetserver/yaml/facts/#{certname}.yaml")
|
298
|
+
|
299
|
+
expect(subject.put_facts(certname, environment: environment, facts: facts)).to eq(true)
|
300
|
+
end
|
301
|
+
|
302
|
+
it 'raises a response error if unsuccessful' do
|
303
|
+
stub_request(:put, uri)
|
304
|
+
.to_return(status: [500, "Server Error"])
|
305
|
+
|
306
|
+
expect {
|
307
|
+
subject.put_facts(certname, environment: environment, facts: facts)
|
308
|
+
}.to raise_error do |err|
|
309
|
+
expect(err).to be_an_instance_of(Puppet::HTTP::ResponseError)
|
310
|
+
expect(err.message).to eq('Server Error')
|
311
|
+
expect(err.response.code).to eq(500)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
it 'raises a serialization error if the report cannot be serialized' do
|
316
|
+
invalid_facts = Puppet::Node::Facts.new(certname, {'invalid_utf8_sequence' => "\xE2\x82".force_encoding('binary')})
|
317
|
+
expect {
|
318
|
+
subject.put_facts(certname, environment: 'production', facts: invalid_facts)
|
319
|
+
}.to raise_error(Puppet::HTTP::SerializationError, /Failed to serialize Puppet::Node::Facts to json: "\\xE2" from ASCII-8BIT to UTF-8/)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|