puppet 5.5.17-x86-mingw32 → 5.5.18-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/CODEOWNERS +1 -1
- data/Gemfile +2 -3
- data/Gemfile.lock +35 -31
- data/ext/build_defaults.yaml +1 -0
- data/ext/cert_inspector +3 -3
- data/ext/puppet-test +2 -2
- data/ext/regexp_nodes/regexp_nodes.rb +4 -4
- data/ext/windows/service/daemon.rb +54 -8
- data/install.rb +6 -6
- data/lib/puppet/application.rb +1 -1
- data/lib/puppet/application/apply.rb +2 -2
- data/lib/puppet/application/describe.rb +3 -9
- 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/configurer.rb +86 -28
- data/lib/puppet/configurer/downloader.rb +2 -6
- data/lib/puppet/defaults.rb +17 -4
- data/lib/puppet/error.rb +9 -1
- data/lib/puppet/external/nagios/base.rb +1 -1
- data/lib/puppet/face/ca.rb +1 -1
- 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/epp.rb +4 -4
- data/lib/puppet/functions/inline_epp.rb +5 -5
- 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 +6 -5
- data/lib/puppet/indirector/file_bucket_file/file.rb +1 -1
- data/lib/puppet/indirector/hiera.rb +2 -0
- 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/loaders.rb +0 -1
- data/lib/puppet/metatype/manager.rb +1 -1
- data/lib/puppet/module.rb +1 -1
- data/lib/puppet/module_tool/applications/builder.rb +1 -1
- 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/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/rack/rest.rb +2 -2
- data/lib/puppet/network/http/site.rb +1 -1
- data/lib/puppet/network/resolver.rb +2 -2
- data/lib/puppet/node/environment.rb +4 -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/functions/epp.rb +3 -3
- data/lib/puppet/parser/functions/inline_epp.rb +5 -5
- 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 -4
- 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 +51 -48
- data/lib/puppet/pops/types/p_sensitive_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/augeas/augeas.rb +1 -1
- data/lib/puppet/provider/cron/crontab.rb +1 -1
- data/lib/puppet/provider/exec.rb +6 -2
- data/lib/puppet/provider/mount.rb +1 -1
- data/lib/puppet/provider/mount/parsed.rb +8 -8
- data/lib/puppet/provider/nameservice/directoryservice.rb +1 -1
- data/lib/puppet/provider/nameservice/pw.rb +2 -2
- data/lib/puppet/provider/package/dnfmodule.rb +87 -0
- data/lib/puppet/provider/package/dpkg.rb +3 -12
- 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 +4 -4
- data/lib/puppet/provider/package/rpm.rb +6 -6
- data/lib/puppet/provider/package/windows/package.rb +1 -1
- data/lib/puppet/provider/package/yum.rb +1 -1
- data/lib/puppet/provider/package_targetable.rb +5 -4
- data/lib/puppet/provider/parsedfile.rb +1 -1
- data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +3 -3
- 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 +8 -8
- data/lib/puppet/provider/user/directoryservice.rb +1 -1
- data/lib/puppet/provider/user/hpux.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/provider/yumrepo/inifile.rb +2 -2
- 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/settings.rb +3 -3
- data/lib/puppet/settings/environment_conf.rb +1 -0
- data/lib/puppet/ssl/certificate_authority/interface.rb +1 -1
- data/lib/puppet/ssl/certificate_factory.rb +2 -2
- data/lib/puppet/ssl/host.rb +3 -3
- data/lib/puppet/ssl/oids.rb +1 -1
- data/lib/puppet/transaction/report.rb +1 -1
- data/lib/puppet/type.rb +2 -4
- data/lib/puppet/type/cron.rb +1 -1
- data/lib/puppet/type/exec.rb +7 -3
- data/lib/puppet/type/file.rb +1 -2
- data/lib/puppet/type/file/data_sync.rb +5 -1
- data/lib/puppet/type/group.rb +4 -2
- data/lib/puppet/type/interface.rb +1 -1
- data/lib/puppet/type/notify.rb +3 -2
- data/lib/puppet/type/package.rb +2 -2
- data/lib/puppet/type/schedule.rb +1 -1
- data/lib/puppet/type/selboolean.rb +17 -3
- data/lib/puppet/type/service.rb +1 -1
- data/lib/puppet/type/user.rb +4 -2
- data/lib/puppet/util.rb +35 -12
- data/lib/puppet/util/command_line/trollop.rb +1 -1
- data/lib/puppet/util/http_proxy.rb +8 -14
- data/lib/puppet/util/instance_loader.rb +1 -1
- data/lib/puppet/util/log.rb +1 -1
- data/lib/puppet/util/log/destinations.rb +2 -2
- data/lib/puppet/util/logging.rb +30 -18
- data/lib/puppet/util/metric.rb +2 -2
- data/lib/puppet/util/monkey_patches.rb +1 -1
- data/lib/puppet/util/nagios_maker.rb +2 -2
- data/lib/puppet/util/network_device/cisco/device.rb +1 -1
- data/lib/puppet/util/network_device/cisco/interface.rb +2 -2
- data/lib/puppet/util/network_device/transport/ssh.rb +1 -1
- 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/adsi.rb +58 -28
- data/lib/puppet/util/windows/registry.rb +7 -5
- data/lib/puppet/vendor.rb +1 -1
- data/lib/puppet/version.rb +1 -1
- data/lib/puppet_pal.rb +2 -2
- data/locales/puppet.pot +115 -95
- data/man/man5/puppet.conf.5 +21 -5
- data/man/man8/puppet-agent.8 +1 -1
- data/man/man8/puppet-apply.8 +1 -1
- data/man/man8/puppet-ca.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-cert.8 +1 -1
- data/man/man8/puppet-certificate.8 +1 -1
- data/man/man8/puppet-certificate_request.8 +1 -1
- data/man/man8/puppet-certificate_revocation_list.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-master.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-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/integration/type/notify_spec.rb +46 -0
- data/spec/unit/configurer_spec.rb +380 -397
- data/spec/unit/forge/forge_spec.rb +1 -3
- data/spec/unit/forge/repository_spec.rb +1 -3
- data/spec/unit/indirector/resource/ral_spec.rb +4 -4
- data/spec/unit/network/http/connection_spec.rb +26 -0
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +8 -3
- 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 +15 -3
- data/spec/unit/provider/package/pip_spec.rb +51 -6
- data/spec/unit/provider/package/portage_spec.rb +4 -4
- data/spec/unit/provider/package_targetable_spec.rb +60 -0
- 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 +22 -22
- data/spec/unit/provider/user/hpux_spec.rb +2 -2
- data/spec/unit/provider/user/useradd_spec.rb +46 -0
- data/spec/unit/type/exec_spec.rb +6 -12
- data/spec/unit/type/file/content_spec.rb +9 -3
- data/spec/unit/type/file_spec.rb +9 -4
- data/spec/unit/type/selboolean_spec.rb +4 -6
- data/spec/unit/util/execution_spec.rb +16 -0
- data/spec/unit/util/http_proxy_spec.rb +97 -0
- data/spec/unit/util/log/destinations_spec.rb +7 -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/tasks/manpages.rake +1 -0
- metadata +12 -5
- data/lib/puppet/pops/loader/null_loader.rb +0 -60
- data/locales/ja/puppet.po +0 -12114
@@ -97,10 +97,8 @@ describe Puppet::Forge do
|
|
97
97
|
def mock_proxy(port, proxy_args, result, &block)
|
98
98
|
http = double("http client")
|
99
99
|
proxy = double("http proxy")
|
100
|
-
proxy_class = double("http proxy class")
|
101
100
|
|
102
|
-
expect(Net::HTTP).to receive(:
|
103
|
-
expect(proxy_class).to receive(:new).with(host, port).and_return(proxy)
|
101
|
+
expect(Net::HTTP).to receive(:new).with(host, port, *proxy_args).and_return(proxy)
|
104
102
|
|
105
103
|
expect(proxy).to receive(:open_timeout=)
|
106
104
|
expect(proxy).to receive(:read_timeout=)
|
@@ -234,10 +234,8 @@ describe Puppet::Forge::Repository do
|
|
234
234
|
def mock_proxy(port, proxy_args, result, &block)
|
235
235
|
http = double("http client")
|
236
236
|
proxy = double("http proxy")
|
237
|
-
proxy_class = double("http proxy class")
|
238
237
|
|
239
|
-
expect(Net::HTTP).to receive(:
|
240
|
-
expect(proxy_class).to receive(:new).with("fake.com", port).and_return(proxy)
|
238
|
+
expect(Net::HTTP).to receive(:new).with("fake.com", port, *proxy_args).and_return(proxy)
|
241
239
|
|
242
240
|
expect(proxy).to receive(:open_timeout=)
|
243
241
|
expect(proxy).to receive(:read_timeout=)
|
@@ -47,7 +47,7 @@ describe "Puppet::Resource::Ral" do
|
|
47
47
|
end
|
48
48
|
|
49
49
|
it "should convert ral resources into regular resources" do
|
50
|
-
my_resource = double("my user resource")
|
50
|
+
my_resource = double("my user resource", :title => "my user resource")
|
51
51
|
my_instance = double("my user", :name => "root", :to_resource => my_resource)
|
52
52
|
|
53
53
|
expect(Puppet::Type::User).to receive(:instances).and_return([ my_instance ])
|
@@ -55,7 +55,7 @@ describe "Puppet::Resource::Ral" do
|
|
55
55
|
end
|
56
56
|
|
57
57
|
it "should filter results by name if there's a name in the key" do
|
58
|
-
my_resource = double("my user resource")
|
58
|
+
my_resource = double("my user resource", title: "my user resource")
|
59
59
|
allow(my_resource).to receive(:to_resource).and_return(my_resource)
|
60
60
|
allow(my_resource).to receive(:[]).with(:name).and_return("root")
|
61
61
|
|
@@ -73,11 +73,11 @@ describe "Puppet::Resource::Ral" do
|
|
73
73
|
end
|
74
74
|
|
75
75
|
it "should filter results by query parameters" do
|
76
|
-
wrong_resource = double("my user resource")
|
76
|
+
wrong_resource = double("my user resource", title: "my user resource")
|
77
77
|
allow(wrong_resource).to receive(:to_resource).and_return(wrong_resource)
|
78
78
|
allow(wrong_resource).to receive(:[]).with(:name).and_return("root")
|
79
79
|
|
80
|
-
my_resource = double("wrong resource")
|
80
|
+
my_resource = double("wrong resource", title: "wrong resource")
|
81
81
|
allow(my_resource).to receive(:to_resource).and_return(my_resource)
|
82
82
|
allow(my_resource).to receive(:[]).with(:name).and_return("bob")
|
83
83
|
|
@@ -266,4 +266,30 @@ describe Puppet::Network::HTTP::Connection do
|
|
266
266
|
|
267
267
|
subject.get('/path')
|
268
268
|
end
|
269
|
+
|
270
|
+
describe 'connection request errors' do
|
271
|
+
it "logs and raises generic http errors" do
|
272
|
+
generic_error = Net::HTTPError.new('generic error', double("response"))
|
273
|
+
expect_any_instance_of(Net::HTTP).to receive(:request).and_raise(generic_error)
|
274
|
+
|
275
|
+
expect(Puppet).to receive(:log_exception).with(anything, /^.*failed: generic error$/)
|
276
|
+
expect { subject.get('/foo') }.to raise_error(generic_error)
|
277
|
+
end
|
278
|
+
|
279
|
+
it "logs and raises timeout errors" do
|
280
|
+
timeout_error = Timeout::Error.new
|
281
|
+
expect_any_instance_of(Net::HTTP).to receive(:request).and_raise(timeout_error)
|
282
|
+
|
283
|
+
expect(Puppet).to receive(:log_exception).with(anything, /^.*timed out after .* seconds$/)
|
284
|
+
expect { subject.get('/foo') }.to raise_error(timeout_error)
|
285
|
+
end
|
286
|
+
|
287
|
+
it "logs and raises eof errors" do
|
288
|
+
eof_error = EOFError
|
289
|
+
expect_any_instance_of(Net::HTTP).to receive(:request).and_raise(eof_error)
|
290
|
+
|
291
|
+
expect(Puppet).to receive(:log_exception).with(anything, /^.*interrupted after .* seconds$/)
|
292
|
+
expect { subject.get('/foo') }.to raise_error(eof_error)
|
293
|
+
end
|
294
|
+
end
|
269
295
|
end
|
@@ -442,21 +442,26 @@ describe 'Puppet::Pops::Evaluator::EvaluatorImpl' do
|
|
442
442
|
}.each do |source, coerced_val|
|
443
443
|
it "should warn about numeric coercion in '#{source}' when strict = warning" do
|
444
444
|
Puppet[:strict] = :warning
|
445
|
+
expect(Puppet::Pops::Evaluator::Runtime3Support::EvaluationError).not_to receive(:new)
|
445
446
|
collect_notices(source)
|
446
447
|
expect(warnings).to include(/The string '#{coerced_val}' was automatically coerced to the numerical value #{coerced_val}/)
|
447
448
|
end
|
448
449
|
|
449
450
|
it "should not warn about numeric coercion in '#{source}' if strict = off" do
|
450
451
|
Puppet[:strict] = :off
|
452
|
+
expect(Puppet::Pops::Evaluator::Runtime3Support::EvaluationError).not_to receive(:new)
|
451
453
|
collect_notices(source)
|
452
454
|
expect(warnings).to_not include(/The string '#{coerced_val}' was automatically coerced to the numerical value #{coerced_val}/)
|
453
455
|
end
|
454
456
|
|
455
457
|
it "should error when finding numeric coercion in '#{source}' if strict = error" do
|
456
458
|
Puppet[:strict] = :error
|
457
|
-
expect {
|
458
|
-
|
459
|
-
|
459
|
+
expect {
|
460
|
+
parser.evaluate_string(scope, source, __FILE__)
|
461
|
+
}.to raise_error {|error|
|
462
|
+
expect(error.message).to match(/The string '#{coerced_val}' was automatically coerced to the numerical value #{coerced_val}/)
|
463
|
+
expect(error.backtrace.first).to match(/runtime3_support\.rb.+optionally_fail/)
|
464
|
+
}
|
460
465
|
end
|
461
466
|
end
|
462
467
|
|
@@ -1,7 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'puppet/provider/exec'
|
3
|
+
require 'puppet_spec/compiler'
|
4
|
+
require 'puppet_spec/files'
|
3
5
|
|
4
6
|
describe Puppet::Provider::Exec do
|
7
|
+
include PuppetSpec::Compiler
|
8
|
+
include PuppetSpec::Files
|
9
|
+
|
5
10
|
describe "#extractexe" do
|
6
11
|
it "should return the first element of an array" do
|
7
12
|
expect(subject.extractexe(['one', 'two'])).to eq('one')
|
@@ -31,4 +36,208 @@ describe Puppet::Provider::Exec do
|
|
31
36
|
end
|
32
37
|
end
|
33
38
|
end
|
39
|
+
|
40
|
+
context "when handling sensitive data" do
|
41
|
+
before :each do
|
42
|
+
Puppet[:log_level] = 'debug'
|
43
|
+
end
|
44
|
+
|
45
|
+
let(:supersecret) { 'supersecret' }
|
46
|
+
let(:path) do
|
47
|
+
if Puppet::Util::Platform.windows?
|
48
|
+
# The `apply_compiled_manifest` helper doesn't add the `path` fact, so
|
49
|
+
# we can't reference that in our manifest. Windows PATHs can contain
|
50
|
+
# double quotes and trailing backslashes, which confuse HEREDOC
|
51
|
+
# interpolation below. So sanitize it:
|
52
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).map do |dir|
|
53
|
+
dir.gsub(/"/, '\"').gsub(/\\$/, '')
|
54
|
+
end.join(File::PATH_SEPARATOR)
|
55
|
+
else
|
56
|
+
ENV['PATH']
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def ruby_exit_0
|
61
|
+
"ruby -e 'exit 0'"
|
62
|
+
end
|
63
|
+
|
64
|
+
def echo_from_ruby_exit_0(message)
|
65
|
+
# Escape double quotes due to HEREDOC interpolation below
|
66
|
+
"ruby -e 'puts \"#{message}\"; exit 0'".gsub(/"/, '\"')
|
67
|
+
end
|
68
|
+
|
69
|
+
def echo_from_ruby_exit_1(message)
|
70
|
+
# Escape double quotes due to HEREDOC interpolation below
|
71
|
+
"ruby -e 'puts \"#{message}\"; exit 1'".gsub(/"/, '\"')
|
72
|
+
end
|
73
|
+
|
74
|
+
context "when validating the command" do
|
75
|
+
it "redacts the arguments if the command is relative" do
|
76
|
+
expect {
|
77
|
+
apply_compiled_manifest(<<-MANIFEST)
|
78
|
+
exec { 'echo':
|
79
|
+
command => Sensitive.new('echo #{supersecret}')
|
80
|
+
}
|
81
|
+
MANIFEST
|
82
|
+
}.to raise_error do |err|
|
83
|
+
expect(err).to be_a(Puppet::Error)
|
84
|
+
expect(err.message).to match(/'echo' is not qualified and no path was specified. Please qualify the command or specify a path./)
|
85
|
+
expect(err.message).to_not match(/#{supersecret}/)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it "redacts the arguments if the command is a directory" do
|
90
|
+
dir = tmpdir('exec')
|
91
|
+
apply_compiled_manifest(<<-MANIFEST)
|
92
|
+
exec { 'echo':
|
93
|
+
command => Sensitive.new('#{dir} #{supersecret}'),
|
94
|
+
}
|
95
|
+
MANIFEST
|
96
|
+
expect(@logs).to include(an_object_having_attributes(level: :err, message: /'#{dir}' is a directory, not a file/))
|
97
|
+
expect(@logs).to_not include(an_object_having_attributes(message: /#{supersecret}/))
|
98
|
+
end
|
99
|
+
|
100
|
+
it "redacts the arguments if the command isn't executable" do
|
101
|
+
file = tmpfile('exec')
|
102
|
+
Puppet::FileSystem.touch(file)
|
103
|
+
Puppet::FileSystem.chmod(0644, file)
|
104
|
+
|
105
|
+
apply_compiled_manifest(<<-MANIFEST)
|
106
|
+
exec { 'echo':
|
107
|
+
command => Sensitive.new('#{file} #{supersecret}'),
|
108
|
+
}
|
109
|
+
MANIFEST
|
110
|
+
# Execute permission works differently on Windows, but execute will fail since the
|
111
|
+
# file doesn't have a valid extension and isn't a valid executable. The raised error
|
112
|
+
# will be Errno::EIO, which is not useful. The Windows execute code needs to raise
|
113
|
+
# Puppet::Util::Windows::Error so the Win32 error message is preserved.
|
114
|
+
pending("PUP-3561 Needs to raise a meaningful Puppet::Error") if Puppet::Util::Platform.windows?
|
115
|
+
expect(@logs).to include(an_object_having_attributes(level: :err, message: /'#{file}' is not executable/))
|
116
|
+
expect(@logs).to_not include(an_object_having_attributes(message: /#{supersecret}/))
|
117
|
+
end
|
118
|
+
|
119
|
+
it "redacts the arguments if the relative command cannot be resolved using the path parameter" do
|
120
|
+
file = File.basename(tmpfile('exec'))
|
121
|
+
dir = tmpdir('exec')
|
122
|
+
|
123
|
+
apply_compiled_manifest(<<-MANIFEST)
|
124
|
+
exec { 'echo':
|
125
|
+
command => Sensitive.new('#{file} #{supersecret}'),
|
126
|
+
path => "#{dir}",
|
127
|
+
}
|
128
|
+
MANIFEST
|
129
|
+
expect(@logs).to include(an_object_having_attributes(level: :err, message: /Could not find command '#{file}'/))
|
130
|
+
expect(@logs).to_not include(an_object_having_attributes(message: /#{supersecret}/))
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
it "redacts the command on success" do
|
135
|
+
command = echo_from_ruby_exit_0(supersecret)
|
136
|
+
|
137
|
+
apply_compiled_manifest(<<-MANIFEST)
|
138
|
+
exec { 'true':
|
139
|
+
command => Sensitive.new("#{command}"),
|
140
|
+
path => "#{path}",
|
141
|
+
}
|
142
|
+
MANIFEST
|
143
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Executing '[redacted]'", source: /Exec\[true\]/))
|
144
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Executing: '[redacted]'", source: "Puppet"))
|
145
|
+
expect(@logs).to include(an_object_having_attributes(level: :notice, message: "executed successfully"))
|
146
|
+
expect(@logs).to_not include(an_object_having_attributes(message: /#{supersecret}/))
|
147
|
+
end
|
148
|
+
|
149
|
+
it "redacts the command on failure" do
|
150
|
+
command = echo_from_ruby_exit_1(supersecret)
|
151
|
+
|
152
|
+
apply_compiled_manifest(<<-MANIFEST)
|
153
|
+
exec { 'false':
|
154
|
+
command => Sensitive.new("#{command}"),
|
155
|
+
path => "#{path}",
|
156
|
+
}
|
157
|
+
MANIFEST
|
158
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Executing '[redacted]'", source: /Exec\[false\]/))
|
159
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Executing: '[redacted]'", source: "Puppet"))
|
160
|
+
expect(@logs).to include(an_object_having_attributes(level: :err, message: "[command redacted] returned 1 instead of one of [0]"))
|
161
|
+
expect(@logs).to_not include(an_object_having_attributes(message: /#{supersecret}/))
|
162
|
+
end
|
163
|
+
|
164
|
+
context "when handling checks" do
|
165
|
+
let(:onlyifsecret) { "onlyifsecret" }
|
166
|
+
let(:unlesssecret) { "unlesssecret" }
|
167
|
+
|
168
|
+
it "redacts command and onlyif outputs" do
|
169
|
+
onlyif = echo_from_ruby_exit_0(onlyifsecret)
|
170
|
+
|
171
|
+
apply_compiled_manifest(<<-MANIFEST)
|
172
|
+
exec { 'true':
|
173
|
+
command => Sensitive.new("#{ruby_exit_0}"),
|
174
|
+
onlyif => Sensitive.new("#{onlyif}"),
|
175
|
+
path => "#{path}",
|
176
|
+
}
|
177
|
+
MANIFEST
|
178
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Executing check '[redacted]'"))
|
179
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Executing '[redacted]'", source: /Exec\[true\]/))
|
180
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Executing: '[redacted]'", source: "Puppet"))
|
181
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "[output redacted]"))
|
182
|
+
expect(@logs).to include(an_object_having_attributes(level: :notice, message: "executed successfully"))
|
183
|
+
expect(@logs).to_not include(an_object_having_attributes(message: /#{onlyifsecret}/))
|
184
|
+
end
|
185
|
+
|
186
|
+
it "redacts the command that would have been executed but didn't due to onlyif" do
|
187
|
+
command = echo_from_ruby_exit_0(supersecret)
|
188
|
+
onlyif = echo_from_ruby_exit_1(onlyifsecret)
|
189
|
+
|
190
|
+
apply_compiled_manifest(<<-MANIFEST)
|
191
|
+
exec { 'true':
|
192
|
+
command => Sensitive.new("#{command}"),
|
193
|
+
onlyif => Sensitive.new("#{onlyif}"),
|
194
|
+
path => "#{path}",
|
195
|
+
}
|
196
|
+
MANIFEST
|
197
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Executing check '[redacted]'"))
|
198
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Executing: '[redacted]'", source: "Puppet"))
|
199
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "[output redacted]"))
|
200
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "'[command redacted]' won't be executed because of failed check 'onlyif'"))
|
201
|
+
expect(@logs).to_not include(an_object_having_attributes(message: /#{supersecret}/))
|
202
|
+
expect(@logs).to_not include(an_object_having_attributes(message: /#{onlyifsecret}/))
|
203
|
+
end
|
204
|
+
|
205
|
+
it "redacts command and unless outputs" do
|
206
|
+
unlesscmd = echo_from_ruby_exit_1(unlesssecret)
|
207
|
+
|
208
|
+
apply_compiled_manifest(<<-MANIFEST)
|
209
|
+
exec { 'true':
|
210
|
+
command => Sensitive.new("#{ruby_exit_0}"),
|
211
|
+
unless => Sensitive.new("#{unlesscmd}"),
|
212
|
+
path => "#{path}",
|
213
|
+
}
|
214
|
+
MANIFEST
|
215
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Executing check '[redacted]'"))
|
216
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Executing '[redacted]'", source: /Exec\[true\]/))
|
217
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Executing: '[redacted]'", source: "Puppet"))
|
218
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "[output redacted]"))
|
219
|
+
expect(@logs).to include(an_object_having_attributes(level: :notice, message: "executed successfully"))
|
220
|
+
expect(@logs).to_not include(an_object_having_attributes(message: /#{unlesssecret}/))
|
221
|
+
end
|
222
|
+
|
223
|
+
it "redacts the command that would have been executed but didn't due to unless" do
|
224
|
+
command = echo_from_ruby_exit_0(supersecret)
|
225
|
+
unlesscmd = echo_from_ruby_exit_0(unlesssecret)
|
226
|
+
|
227
|
+
apply_compiled_manifest(<<-MANIFEST)
|
228
|
+
exec { 'true':
|
229
|
+
command => Sensitive.new("#{command}"),
|
230
|
+
unless => Sensitive.new("#{unlesscmd}"),
|
231
|
+
path => "#{path}",
|
232
|
+
}
|
233
|
+
MANIFEST
|
234
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Executing check '[redacted]'"))
|
235
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "Executing: '[redacted]'", source: "Puppet"))
|
236
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "[output redacted]"))
|
237
|
+
expect(@logs).to include(an_object_having_attributes(level: :debug, message: "'[command redacted]' won't be executed because of failed check 'unless'"))
|
238
|
+
expect(@logs).to_not include(an_object_having_attributes(message: /#{supersecret}/))
|
239
|
+
expect(@logs).to_not include(an_object_having_attributes(message: /#{unlesssecret}/))
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
34
243
|
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Puppet::Type.type(:package).provider(:dnfmodule) do
|
4
|
+
include PuppetSpec::Fixtures
|
5
|
+
|
6
|
+
let(:dnf_version) do
|
7
|
+
<<-DNF_OUTPUT
|
8
|
+
4.0.9
|
9
|
+
Installed: dnf-0:4.0.9.2-5.el8.noarch at Wed 29 May 2019 07:05:05 AM GMT
|
10
|
+
Built : Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla> at Thu 14 Feb 2019 12:04:07 PM GMT
|
11
|
+
|
12
|
+
Installed: rpm-0:4.14.2-9.el8.x86_64 at Wed 29 May 2019 07:04:33 AM GMT
|
13
|
+
Built : Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla> at Thu 20 Dec 2018 01:30:03 PM GMT
|
14
|
+
DNF_OUTPUT
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:execute_options) do
|
18
|
+
{:failonfail => true, :combine => true, :custom_environment => {}}
|
19
|
+
end
|
20
|
+
|
21
|
+
let(:packages) { File.read(my_fixture("dnf-module-list-installed.txt")) }
|
22
|
+
let(:dnf_path) { '/usr/bin/dnf' }
|
23
|
+
|
24
|
+
before(:each) { allow(Puppet::Util).to receive(:which).with('/usr/bin/dnf').and_return(dnf_path) }
|
25
|
+
|
26
|
+
it "should have lower specificity" do
|
27
|
+
allow(Facter).to receive(:value).with(:osfamily).and_return(:redhat)
|
28
|
+
allow(Facter).to receive(:value).with(:operatingsystem).and_return(:redhat)
|
29
|
+
allow(Facter).to receive(:value).with(:operatingsystemmajrelease).and_return('8')
|
30
|
+
expect(described_class.specificity).to be < 200
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "should be an opt-in provider" do
|
34
|
+
Array(4..8).each do |ver|
|
35
|
+
it "should not be default for redhat #{ver}" do
|
36
|
+
allow(Facter).to receive(:value).with(:operatingsystem).and_return('redhat')
|
37
|
+
allow(Facter).to receive(:value).with(:osfamily).and_return('redhat')
|
38
|
+
allow(Facter).to receive(:value).with(:operatingsystemmajrelease).and_return(ver.to_s)
|
39
|
+
expect(described_class).not_to be_default
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "handling dnf versions" do
|
45
|
+
before(:each) do
|
46
|
+
expect(Puppet::Type::Package::ProviderDnfmodule).to receive(:execute)
|
47
|
+
.with(["/usr/bin/dnf", "--version"])
|
48
|
+
.and_return(dnf_version).at_most(:once)
|
49
|
+
expect(Puppet::Util::Execution).to receive(:execute)
|
50
|
+
.with(["/usr/bin/dnf", "--version"], execute_options)
|
51
|
+
.and_return(Puppet::Util::Execution::ProcessOutput.new(dnf_version, 0))
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "with a supported dnf version" do
|
55
|
+
it "correctly parses the version" do
|
56
|
+
expect(described_class.current_version).to eq('4.0.9')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "with an unsupported dnf version" do
|
61
|
+
let(:dnf_version) do
|
62
|
+
<<-DNF_OUTPUT
|
63
|
+
2.7.5
|
64
|
+
Installed: dnf-0:2.7.5-12.fc28.noarch at Mon 13 Aug 2018 11:05:27 PM GMT
|
65
|
+
Built : Fedora Project at Wed 18 Apr 2018 02:29:51 PM GMT
|
66
|
+
|
67
|
+
Installed: rpm-0:4.14.1-7.fc28.x86_64 at Mon 13 Aug 2018 11:05:25 PM GMT
|
68
|
+
Built : Fedora Project at Mon 19 Feb 2018 09:29:01 AM GMT
|
69
|
+
DNF_OUTPUT
|
70
|
+
end
|
71
|
+
|
72
|
+
before(:each) { described_class.instance_variable_set("@current_version", nil) }
|
73
|
+
|
74
|
+
it "correctly parses the version" do
|
75
|
+
expect(described_class.current_version).to eq('2.7.5')
|
76
|
+
end
|
77
|
+
|
78
|
+
it "raises an error when attempting prefetch" do
|
79
|
+
expect { described_class.prefetch('anything') }.to raise_error(Puppet::Error, "Modules are not supported on DNF versions lower than 3.0.1")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "when installing a module" do
|
85
|
+
let(:name) { 'baz' }
|
86
|
+
|
87
|
+
let(:resource) do
|
88
|
+
Puppet::Type.type(:package).new(
|
89
|
+
:name => name,
|
90
|
+
:provider => 'dnfmodule',
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
let(:provider) do
|
95
|
+
provider = described_class.new
|
96
|
+
provider.resource = resource
|
97
|
+
provider
|
98
|
+
end
|
99
|
+
|
100
|
+
describe 'provider features' do
|
101
|
+
it { is_expected.to be_versionable }
|
102
|
+
it { is_expected.to be_installable }
|
103
|
+
it { is_expected.to be_uninstallable }
|
104
|
+
end
|
105
|
+
|
106
|
+
context "when installing a new module" do
|
107
|
+
before do
|
108
|
+
provider.instance_variable_get('@property_hash')[:ensure] = :absent
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should not reset the module stream when package is absent" do
|
112
|
+
resource[:ensure] = :present
|
113
|
+
expect(provider).not_to receive(:uninstall)
|
114
|
+
expect(provider).to receive(:execute)
|
115
|
+
provider.install
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should not reset the module stream when package is purged" do
|
119
|
+
provider.instance_variable_get('@property_hash')[:ensure] = :purged
|
120
|
+
resource[:ensure] = :present
|
121
|
+
expect(provider).not_to receive(:uninstall)
|
122
|
+
expect(provider).to receive(:execute)
|
123
|
+
provider.install
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should install the default stream and flavor" do
|
127
|
+
resource[:ensure] = :present
|
128
|
+
expect(provider).to receive(:execute).with(array_including('baz'))
|
129
|
+
provider.install
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should install a specific stream" do
|
133
|
+
resource[:ensure] = '9.6'
|
134
|
+
expect(provider).to receive(:execute).with(array_including('baz:9.6'))
|
135
|
+
provider.install
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should install a specific flavor" do
|
139
|
+
resource[:ensure] = :present
|
140
|
+
resource[:flavor] = 'minimal'
|
141
|
+
expect(provider).to receive(:execute).with(array_including('baz/minimal'))
|
142
|
+
provider.install
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should install a specific flavor and stream" do
|
146
|
+
resource[:ensure] = '9.6'
|
147
|
+
resource[:flavor] = 'minimal'
|
148
|
+
expect(provider).to receive(:execute).with(array_including('baz:9.6/minimal'))
|
149
|
+
provider.install
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context "when ensuring a specific version on top of another stream" do
|
154
|
+
before do
|
155
|
+
provider.instance_variable_get('@property_hash')[:ensure] = '9.6'
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should remove existing packages and reset the module stream before installing" do
|
159
|
+
resource[:ensure] = '10'
|
160
|
+
expect(provider).to receive(:execute).thrice.with(array_including(/remove|reset|install/))
|
161
|
+
provider.install
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context "parsing the output of module list --installed" do
|
167
|
+
before { allow(described_class).to receive(:command).with(:dnf).and_return(dnf_path) }
|
168
|
+
|
169
|
+
it "returns an array of installed modules" do
|
170
|
+
allow(Puppet::Util::Execution).to receive(:execute)
|
171
|
+
.with("/usr/bin/dnf module list --installed -d 0 -e 1")
|
172
|
+
.and_return(packages)
|
173
|
+
|
174
|
+
installed_packages = described_class.instances.map { |package| package.properties }
|
175
|
+
expected_packages = [{name: "gimp", ensure: "2.8", flavor: "devel", :provider => :dnfmodule},
|
176
|
+
{name: "mariadb", ensure: "10.3", flavor: "client", :provider => :dnfmodule},
|
177
|
+
{name: "nodejs", ensure: "10", flavor: "minimal", :provider => :dnfmodule},
|
178
|
+
{name: "perl", ensure: "5.26", flavor: "minimal", :provider => :dnfmodule},
|
179
|
+
{name: "postgresql", ensure: "10", flavor: "server", :provider => :dnfmodule},
|
180
|
+
{name: "rust-toolset", ensure: "rhel8", flavor: "common", :provider => :dnfmodule},
|
181
|
+
{name: "subversion", ensure: "1.10", flavor: "server", :provider => :dnfmodule}]
|
182
|
+
|
183
|
+
expect(installed_packages).to eql(expected_packages)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|