puppet 5.0.1 → 5.1.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/lib/puppet/agent.rb +1 -0
- data/lib/puppet/defaults.rb +1 -1
- data/lib/puppet/functions.rb +6 -7
- data/lib/puppet/functions/all.rb +100 -0
- data/lib/puppet/functions/any.rb +105 -0
- data/lib/puppet/functions/defined.rb +3 -3
- data/lib/puppet/functions/new.rb +2 -1
- data/lib/puppet/functions/reduce.rb +31 -0
- data/lib/puppet/functions/tree_each.rb +200 -0
- data/lib/puppet/module.rb +30 -0
- data/lib/puppet/parser/functions/new.rb +67 -0
- data/lib/puppet/parser/functions/reduce.rb +31 -0
- data/lib/puppet/parser/relationship.rb +2 -2
- data/lib/puppet/parser/resource.rb +39 -10
- data/lib/puppet/parser/scope.rb +1 -1
- data/lib/puppet/pops/evaluator/access_operator.rb +11 -4
- data/lib/puppet/pops/evaluator/collector_transformer.rb +1 -1
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +4 -4
- data/lib/puppet/pops/evaluator/relationship_operator.rb +1 -1
- data/lib/puppet/pops/evaluator/runtime3_converter.rb +3 -3
- data/lib/puppet/pops/evaluator/runtime3_resource_support.rb +1 -1
- data/lib/puppet/pops/loader/module_loaders.rb +1 -1
- data/lib/puppet/pops/loader/static_loader.rb +1 -2
- data/lib/puppet/pops/loaders.rb +1 -2
- data/lib/puppet/pops/lookup/context.rb +1 -1
- data/lib/puppet/pops/lookup/lookup_adapter.rb +2 -1
- data/lib/puppet/pops/model/ast.rb +440 -436
- data/lib/puppet/pops/model/factory.rb +140 -140
- data/lib/puppet/pops/pcore.rb +1 -2
- data/lib/puppet/pops/resource/param.rb +1 -1
- data/lib/puppet/pops/resource/resource_type_impl.rb +1 -1
- data/lib/puppet/pops/serialization/from_data_converter.rb +0 -12
- data/lib/puppet/pops/time/timestamp.rb +29 -17
- data/lib/puppet/pops/types/annotatable.rb +2 -2
- data/lib/puppet/pops/types/annotation.rb +8 -8
- data/lib/puppet/pops/types/class_loader.rb +3 -3
- data/lib/puppet/pops/types/implementation_registry.rb +1 -1
- data/lib/puppet/pops/types/iterable.rb +2 -2
- data/lib/puppet/pops/types/p_binary_type.rb +2 -2
- data/lib/puppet/pops/types/p_init_type.rb +238 -0
- data/lib/puppet/pops/types/p_meta_type.rb +14 -11
- data/lib/puppet/pops/types/p_object_type.rb +15 -15
- data/lib/puppet/pops/types/p_sem_ver_range_type.rb +2 -2
- data/lib/puppet/pops/types/p_sem_ver_type.rb +2 -2
- data/lib/puppet/pops/types/p_sensitive_type.rb +2 -2
- data/lib/puppet/pops/types/p_timespan_type.rb +6 -6
- data/lib/puppet/pops/types/p_timestamp_type.rb +6 -2
- data/lib/puppet/pops/types/p_type_set_type.rb +10 -9
- data/lib/puppet/pops/types/ruby_generator.rb +6 -5
- data/lib/puppet/pops/types/ruby_method.rb +2 -2
- data/lib/puppet/pops/types/string_converter.rb +1 -1
- data/lib/puppet/pops/types/tree_iterators.rb +250 -0
- data/lib/puppet/pops/types/type_calculator.rb +13 -13
- data/lib/puppet/pops/types/type_factory.rb +26 -7
- data/lib/puppet/pops/types/type_formatter.rb +9 -4
- data/lib/puppet/pops/types/type_parser.rb +8 -3
- data/lib/puppet/pops/types/type_set_reference.rb +2 -2
- data/lib/puppet/pops/types/types.rb +168 -109
- data/lib/puppet/provider/package/gem.rb +10 -9
- data/lib/puppet/provider/package/pip.rb +12 -3
- data/lib/puppet/provider/package/yum.rb +9 -1
- data/lib/puppet/resource/capability_finder.rb +30 -11
- data/lib/puppet/type/file.rb +21 -13
- data/lib/puppet/util/execution.rb +67 -14
- data/lib/puppet/util/suidmanager.rb +1 -0
- data/lib/puppet/version.rb +1 -1
- data/locales/puppet.pot +130 -66
- data/man/man5/puppet.conf.5 +1 -1
- data/spec/fixtures/unit/provider/package/yum/yum-check-update-simple.txt +1 -0
- data/spec/integration/parser/collection_spec.rb +40 -1
- data/spec/shared_contexts/types_setup.rb +41 -2
- data/spec/unit/agent_spec.rb +11 -0
- data/spec/unit/file_bucket/dipper_spec.rb +13 -4
- data/spec/unit/functions/all_spec.rb +97 -0
- data/spec/unit/functions/any_spec.rb +109 -0
- data/spec/unit/functions/hiera_spec.rb +5 -0
- data/spec/unit/functions/new_spec.rb +66 -0
- data/spec/unit/functions/tree_each_spec.rb +444 -0
- data/spec/unit/module_spec.rb +29 -0
- data/spec/unit/pops/serialization/serialization_spec.rb +2 -2
- data/spec/unit/pops/serialization/to_from_hr_spec.rb +2 -2
- data/spec/unit/pops/types/iterable_spec.rb +9 -9
- data/spec/unit/pops/types/p_init_type_spec.rb +285 -0
- data/spec/unit/pops/types/p_object_type_spec.rb +8 -8
- data/spec/unit/pops/types/p_sensitive_type_spec.rb +4 -0
- data/spec/unit/pops/types/p_timespan_type_spec.rb +14 -0
- data/spec/unit/pops/types/p_timestamp_type_spec.rb +19 -1
- data/spec/unit/pops/types/p_type_set_type_spec.rb +2 -2
- data/spec/unit/pops/types/ruby_generator_spec.rb +9 -22
- data/spec/unit/pops/types/string_converter_spec.rb +2 -2
- data/spec/unit/pops/types/type_acceptor_spec.rb +2 -2
- data/spec/unit/pops/types/type_calculator_spec.rb +43 -38
- data/spec/unit/pops/types/type_factory_spec.rb +6 -6
- data/spec/unit/pops/types/type_formatter_spec.rb +6 -6
- data/spec/unit/pops/types/types_spec.rb +16 -4
- data/spec/unit/provider/package/gem_spec.rb +6 -6
- data/spec/unit/provider/package/pip_spec.rb +44 -23
- data/spec/unit/provider/package/puppet_gem_spec.rb +1 -1
- data/spec/unit/provider/package/yum_spec.rb +8 -0
- data/spec/unit/resource/capability_finder_spec.rb +4 -5
- data/spec/unit/type/file_spec.rb +19 -14
- data/spec/unit/util/execution_spec.rb +216 -82
- data/tasks/generate_ast_model.rake +10 -2
- metadata +15 -2
@@ -570,19 +570,19 @@ describe 'Puppet Type System' do
|
|
570
570
|
context 'instantiation via new_function is supported by' do
|
571
571
|
let(:loader) { Loader::BaseLoader.new(nil, "types_unit_test_loader") }
|
572
572
|
it 'Integer' do
|
573
|
-
func_class = tf.integer.new_function
|
573
|
+
func_class = tf.integer.new_function
|
574
574
|
expect(func_class).to be_a(Class)
|
575
575
|
expect(func_class.superclass).to be(Puppet::Functions::Function)
|
576
576
|
end
|
577
577
|
|
578
578
|
it 'Optional[Integer]' do
|
579
|
-
func_class = tf.optional(tf.integer).new_function
|
579
|
+
func_class = tf.optional(tf.integer).new_function
|
580
580
|
expect(func_class).to be_a(Class)
|
581
581
|
expect(func_class.superclass).to be(Puppet::Functions::Function)
|
582
582
|
end
|
583
583
|
|
584
584
|
it 'Regexp' do
|
585
|
-
func_class = tf.regexp.new_function
|
585
|
+
func_class = tf.regexp.new_function
|
586
586
|
expect(func_class).to be_a(Class)
|
587
587
|
expect(func_class.superclass).to be(Puppet::Functions::Function)
|
588
588
|
end
|
@@ -593,7 +593,7 @@ describe 'Puppet Type System' do
|
|
593
593
|
|
594
594
|
it 'Any, Scalar, Collection' do
|
595
595
|
[tf.any, tf.scalar, tf.collection ].each do |t|
|
596
|
-
expect { t.new_function
|
596
|
+
expect { t.new_function
|
597
597
|
}.to raise_error(ArgumentError, /Creation of new instance of type '#{t.to_s}' is not supported/)
|
598
598
|
end
|
599
599
|
end
|
@@ -645,6 +645,18 @@ describe 'Puppet Type System' do
|
|
645
645
|
expect(rx_type).to eq(tf.regexp(/[a-z]+/))
|
646
646
|
end
|
647
647
|
end
|
648
|
+
|
649
|
+
context 'backward compatibility' do
|
650
|
+
it 'PTypeType can be accessed from PType' do
|
651
|
+
# should appoint the exact same instance
|
652
|
+
expect(PType).to equal(PTypeType)
|
653
|
+
end
|
654
|
+
|
655
|
+
it 'PClassType can be accessed from PHostClassType' do
|
656
|
+
# should appoint the exact same instance
|
657
|
+
expect(PHostClassType).to equal(PClassType)
|
658
|
+
end
|
659
|
+
end
|
648
660
|
end
|
649
661
|
end
|
650
662
|
end
|
@@ -56,7 +56,7 @@ context 'installing myresource' do
|
|
56
56
|
|
57
57
|
it "should allow setting an install_options parameter" do
|
58
58
|
resource[:install_options] = [ '--force', {'--bindir' => '/usr/bin' } ]
|
59
|
-
provider.expects(:execute).with { |args| args[
|
59
|
+
provider.expects(:execute).with { |args| args[2] == '--force' && args[3] == '--bindir=/usr/bin' }.returns ''
|
60
60
|
provider.install
|
61
61
|
end
|
62
62
|
|
@@ -137,12 +137,12 @@ context 'installing myresource' do
|
|
137
137
|
end
|
138
138
|
|
139
139
|
it "should return an empty array when no gems installed" do
|
140
|
-
provider_class.expects(:execute).with(%w{/my/gem list --local}).returns("\n")
|
140
|
+
provider_class.expects(:execute).with(%w{/my/gem list --local}, {:failonfail => true, :combine => true, :custom_environment => {"HOME"=>ENV["HOME"]}}).returns("\n")
|
141
141
|
expect(provider_class.instances).to eq([])
|
142
142
|
end
|
143
143
|
|
144
144
|
it "should return ensure values as an array of installed versions" do
|
145
|
-
provider_class.expects(:execute).with(%w{/my/gem list --local}).returns <<-HEREDOC.gsub(/ /, '')
|
145
|
+
provider_class.expects(:execute).with(%w{/my/gem list --local}, {:failonfail => true, :combine => true, :custom_environment => {"HOME"=>ENV["HOME"]}}).returns <<-HEREDOC.gsub(/ /, '')
|
146
146
|
systemu (1.2.0)
|
147
147
|
vagrant (0.8.7, 0.6.9)
|
148
148
|
HEREDOC
|
@@ -154,7 +154,7 @@ context 'installing myresource' do
|
|
154
154
|
end
|
155
155
|
|
156
156
|
it "should ignore platform specifications" do
|
157
|
-
provider_class.expects(:execute).with(%w{/my/gem list --local}).returns <<-HEREDOC.gsub(/ /, '')
|
157
|
+
provider_class.expects(:execute).with(%w{/my/gem list --local}, {:failonfail => true, :combine => true, :custom_environment => {"HOME"=>ENV["HOME"]}}).returns <<-HEREDOC.gsub(/ /, '')
|
158
158
|
systemu (1.2.0)
|
159
159
|
nokogiri (1.6.1 ruby java x86-mingw32 x86-mswin32-60, 1.4.4.1 x86-mswin32)
|
160
160
|
HEREDOC
|
@@ -166,7 +166,7 @@ context 'installing myresource' do
|
|
166
166
|
end
|
167
167
|
|
168
168
|
it "should not fail when an unmatched line is returned" do
|
169
|
-
provider_class.expects(:execute).with(%w{/my/gem list --local}).
|
169
|
+
provider_class.expects(:execute).with(%w{/my/gem list --local}, {:failonfail => true, :combine => true, :custom_environment => {"HOME"=>ENV["HOME"]}}).
|
170
170
|
returns(File.read(my_fixture('line-with-1.8.5-warning')))
|
171
171
|
|
172
172
|
expect(provider_class.instances.map {|p| p.properties}).
|
@@ -186,7 +186,7 @@ context 'installing myresource' do
|
|
186
186
|
describe "listing gems" do
|
187
187
|
describe "searching for a single package" do
|
188
188
|
it "searches for an exact match" do
|
189
|
-
provider_class.expects(:execute).with(includes('^bundler$')).returns(File.read(my_fixture('gem-list-single-package')))
|
189
|
+
provider_class.expects(:execute).with(includes('^bundler$'), {:failonfail => true, :combine => true, :custom_environment => {"HOME"=>ENV["HOME"]}}).returns(File.read(my_fixture('gem-list-single-package')))
|
190
190
|
expected = {:name => 'bundler', :ensure => %w[1.6.2], :provider => :gem}
|
191
191
|
expect(provider_class.gemlist({:justme => 'bundler'})).to eq(expected)
|
192
192
|
end
|
@@ -2,11 +2,11 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
provider_class = Puppet::Type.type(:package).provider(:pip)
|
5
|
-
osfamilies = { ['
|
5
|
+
osfamilies = { 'windows' => ['pip.exe'], 'other' => ['pip', 'pip-python'] }
|
6
6
|
|
7
7
|
describe provider_class do
|
8
8
|
|
9
|
-
before do
|
9
|
+
before do
|
10
10
|
@resource = Puppet::Resource.new(:package, "fake_package")
|
11
11
|
@provider = provider_class.new(@resource)
|
12
12
|
@client = stub_everything('client')
|
@@ -31,13 +31,19 @@ describe provider_class do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
describe "cmd" do
|
34
|
-
|
35
|
-
|
34
|
+
|
35
|
+
it "should return 'pip.exe' by default on Windows systems" do
|
36
|
+
Puppet.features.stubs(:microsoft_windows?).returns true
|
37
|
+
expect(provider_class.cmd[0]).to eq('pip.exe')
|
38
|
+
end
|
39
|
+
|
40
|
+
it "could return pip-python on legacy redhat systems which rename pip" do
|
41
|
+
Puppet.features.stubs(:microsoft_windows?).returns false
|
36
42
|
expect(provider_class.cmd[1]).to eq('pip-python')
|
37
43
|
end
|
38
44
|
|
39
|
-
it "should return pip by default" do
|
40
|
-
|
45
|
+
it "should return pip by default on other systems" do
|
46
|
+
Puppet.features.stubs(:microsoft_windows?).returns false
|
41
47
|
expect(provider_class.cmd[0]).to eq('pip')
|
42
48
|
end
|
43
49
|
|
@@ -46,10 +52,10 @@ describe provider_class do
|
|
46
52
|
describe "instances" do
|
47
53
|
|
48
54
|
osfamilies.each do |osfamily, pip_cmds|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
pip_cmds.each do |pip_cmd|
|
55
|
+
|
56
|
+
it "should return an array on #{osfamily} systems when #{pip_cmds.join(' or ')} is present" do
|
57
|
+
Puppet.features.stubs(:microsoft_windows?).returns (osfamily == 'windows')
|
58
|
+
pip_cmds.each do |pip_cmd|
|
53
59
|
pip_cmds.each do |cmd|
|
54
60
|
unless cmd == pip_cmd
|
55
61
|
provider_class.expects(:which).with(cmd).returns(nil)
|
@@ -59,19 +65,34 @@ describe provider_class do
|
|
59
65
|
provider_class.expects(:which).with(pip_cmd).returns("/fake/bin/#{pip_cmd}")
|
60
66
|
p = stub("process")
|
61
67
|
p.expects(:collect).yields("real_package==1.2.5")
|
62
|
-
provider_class.expects(:execpipe).with("/fake/bin/#{pip_cmd} freeze").yields(p)
|
68
|
+
provider_class.expects(:execpipe).with(["/fake/bin/#{pip_cmd}", "freeze"]).yields(p)
|
63
69
|
provider_class.instances
|
64
70
|
end
|
65
71
|
end
|
66
72
|
|
67
|
-
|
68
|
-
|
69
|
-
|
73
|
+
context "with pip version >= 8.1.0" do
|
74
|
+
versions = ['8.1.0', '9.0.1']
|
75
|
+
versions.each do |version|
|
76
|
+
it "should use the --all option when version is '#{version}'" do
|
77
|
+
Puppet.features.stubs(:microsoft_windows?).returns (osfamily == 'windows')
|
78
|
+
provider_class.stubs(:pip_cmd).returns('/fake/bin/pip')
|
79
|
+
provider_class.stubs(:pip_version).returns(version)
|
80
|
+
p = stub("process")
|
81
|
+
p.expects(:collect).yields("real_package==1.2.5")
|
82
|
+
provider_class.expects(:execpipe).with(["/fake/bin/pip", "freeze", "--all"]).yields(p)
|
83
|
+
provider_class.instances
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should return an empty array on #{osfamily} systems when #{pip_cmds.join(' and ')} are missing" do
|
89
|
+
Puppet.features.stubs(:microsoft_windows?).returns (osfamily == 'windows')
|
70
90
|
pip_cmds.each do |cmd|
|
71
91
|
provider_class.expects(:which).with(cmd).returns nil
|
72
92
|
end
|
73
93
|
expect(provider_class.instances).to eq([])
|
74
94
|
end
|
95
|
+
|
75
96
|
end
|
76
97
|
|
77
98
|
end
|
@@ -125,6 +146,7 @@ describe provider_class do
|
|
125
146
|
provider_class.stubs(:pip_version).returns('1.0.1')
|
126
147
|
provider_class.stubs(:which).with('pip').returns("/fake/bin/pip")
|
127
148
|
provider_class.stubs(:which).with('pip-python').returns("/fake/bin/pip")
|
149
|
+
provider_class.stubs(:which).with('pip.exe').returns("/fake/bin/pip")
|
128
150
|
end
|
129
151
|
|
130
152
|
it "should find a version number for new_pip_package" do
|
@@ -181,6 +203,7 @@ describe provider_class do
|
|
181
203
|
provider_class.stubs(:pip_version).returns('1.5.4')
|
182
204
|
provider_class.stubs(:which).with('pip').returns("/fake/bin/pip")
|
183
205
|
provider_class.stubs(:which).with('pip-python').returns("/fake/bin/pip")
|
206
|
+
provider_class.stubs(:which).with('pip.exe').returns("/fake/bin/pip")
|
184
207
|
end
|
185
208
|
|
186
209
|
it "should find a version number for real_package" do
|
@@ -343,10 +366,10 @@ describe provider_class do
|
|
343
366
|
end
|
344
367
|
|
345
368
|
osfamilies.each do |osfamily, pip_cmds|
|
369
|
+
|
346
370
|
pip_cmds.each do |pip_cmd|
|
347
|
-
it "should retry on #{osfamily} if #{pip_cmd} has not yet been found" do
|
348
|
-
|
349
|
-
Facter.stubs(:value).with(:operatingsystemmajrelease).returns(osfamily.last)
|
371
|
+
it "should retry on #{osfamily} systems if #{pip_cmd} has not yet been found" do
|
372
|
+
Puppet.features.stubs(:microsoft_windows?).returns (osfamily == 'windows')
|
350
373
|
@provider.expects(:pip).twice.with('freeze').raises(NoMethodError).then.returns(nil)
|
351
374
|
pip_cmds.each do |cmd|
|
352
375
|
unless cmd == pip_cmd
|
@@ -358,9 +381,8 @@ describe provider_class do
|
|
358
381
|
end
|
359
382
|
end
|
360
383
|
|
361
|
-
it "should fail on #{osfamily} if #{pip_cmds.join(' and ')} are missing" do
|
362
|
-
|
363
|
-
Facter.stubs(:value).with(:operatingsystemmajrelease).returns(osfamily.last)
|
384
|
+
it "should fail on #{osfamily} systems if #{pip_cmds.join(' and ')} are missing" do
|
385
|
+
Puppet.features.stubs(:microsoft_windows?).returns (osfamily == 'windows')
|
364
386
|
@provider.expects(:pip).with('freeze').raises(NoMethodError)
|
365
387
|
pip_cmds.each do |pip_cmd|
|
366
388
|
@provider.expects(:which).with(pip_cmd).returns(nil)
|
@@ -368,9 +390,8 @@ describe provider_class do
|
|
368
390
|
expect { @provider.method(:lazy_pip).call("freeze") }.to raise_error(NoMethodError)
|
369
391
|
end
|
370
392
|
|
371
|
-
it "should output a useful error message on #{osfamily} if #{pip_cmds.join(' and ')} are missing" do
|
372
|
-
|
373
|
-
Facter.stubs(:value).with(:operatingsystemmajrelease).returns(osfamily.last)
|
393
|
+
it "should output a useful error message on #{osfamily} systems if #{pip_cmds.join(' and ')} are missing" do
|
394
|
+
Puppet.features.stubs(:microsoft_windows?).returns (osfamily == 'windows')
|
374
395
|
@provider.expects(:pip).with('freeze').raises(NoMethodError)
|
375
396
|
pip_cmds.each do |pip_cmd|
|
376
397
|
@provider.expects(:which).with(pip_cmd).returns(nil)
|
@@ -41,7 +41,7 @@ describe provider_class do
|
|
41
41
|
|
42
42
|
it "should allow setting an install_options parameter" do
|
43
43
|
resource[:install_options] = [ '--force', {'--bindir' => '/usr/bin' } ]
|
44
|
-
provider.expects(:execute).with { |args| args[
|
44
|
+
provider.expects(:execute).with { |args| args[2] == '--force' && args[3] == '--bindir=/usr/bin' }.returns ''
|
45
45
|
provider.install
|
46
46
|
end
|
47
47
|
end
|
@@ -23,6 +23,7 @@ describe provider_class do
|
|
23
23
|
expect(output['gawk.i686']).to eq([{:name => 'gawk', :epoch => '0', :version => '4.1.0', :release => '3.fc20', :arch => 'i686'}])
|
24
24
|
expect(output['dhclient.i686']).to eq([{:name => 'dhclient', :epoch => '12', :version => '4.1.1', :release => '38.P1.fc20', :arch => 'i686'}])
|
25
25
|
expect(output['selinux-policy.noarch']).to eq([{:name => 'selinux-policy', :epoch => '0', :version => '3.12.1', :release => '163.fc20', :arch => 'noarch'}])
|
26
|
+
expect(output['java-1.8.0-openjdk.x86_64']).to eq([{:name => 'java-1.8.0-openjdk', :epoch => '1', :version => '1.8.0.131', :release => '2.b11.el7_3', :arch => 'x86_64'}])
|
26
27
|
end
|
27
28
|
end
|
28
29
|
describe "with multiline entries" do
|
@@ -61,5 +62,12 @@ describe provider_class do
|
|
61
62
|
expect(output).to include("yum-plugin-fastestmirror.noarch")
|
62
63
|
end
|
63
64
|
end
|
65
|
+
describe "with improper package names in output" do
|
66
|
+
it "raises an exception parsing package name" do
|
67
|
+
expect {
|
68
|
+
described_class.update_to_hash('badpackagename', '1')
|
69
|
+
}.to raise_exception(Exception, /Failed to parse/)
|
70
|
+
end
|
71
|
+
end
|
64
72
|
end
|
65
73
|
end
|
@@ -124,22 +124,21 @@ describe Puppet::Resource::CapabilityFinder do
|
|
124
124
|
expect(result['host']).to eq('chost')
|
125
125
|
end
|
126
126
|
|
127
|
-
it 'should
|
127
|
+
it 'should fail if no resource matches code_id' do
|
128
128
|
Puppet::Resource::CapabilityFinder.stubs(:search).with('production', code_id, capability).returns []
|
129
129
|
|
130
|
-
|
131
|
-
expect(result).to be_nil
|
130
|
+
expect { Puppet::Resource::CapabilityFinder.find('production', code_id, capability) }.to raise_error(Puppet::Error, /expected exactly one resource but got 2/)
|
132
131
|
end
|
133
132
|
|
134
133
|
it 'should fail if multiple resources match code_id' do
|
135
134
|
Puppet::Resource::CapabilityFinder.stubs(:search).with('production', code_id, capability).returns resources
|
136
135
|
|
137
|
-
expect { Puppet::Resource::CapabilityFinder.find('production', code_id, capability) }.to raise_error(Puppet::DevError, /expected exactly one resource/)
|
136
|
+
expect { Puppet::Resource::CapabilityFinder.find('production', code_id, capability) }.to raise_error(Puppet::DevError, /expected exactly one resource but got 2/)
|
138
137
|
end
|
139
138
|
|
140
139
|
it 'should fail if no code_id was specified' do
|
141
140
|
Puppet::Resource::CapabilityFinder.stubs(:search).with('production', nil, capability).returns resources
|
142
|
-
expect { Puppet::Resource::CapabilityFinder.find('production', nil, capability) }.to raise_error(Puppet::DevError, /expected exactly one resource/)
|
141
|
+
expect { Puppet::Resource::CapabilityFinder.find('production', nil, capability) }.to raise_error(Puppet::DevError, /expected exactly one resource but got 2/)
|
143
142
|
end
|
144
143
|
end
|
145
144
|
end
|
data/spec/unit/type/file_spec.rb
CHANGED
@@ -893,26 +893,31 @@ describe Puppet::Type.type(:file) do
|
|
893
893
|
end
|
894
894
|
|
895
895
|
it "should fail if it can't backup the file" do
|
896
|
+
# Default: file[:backup] = true
|
896
897
|
file.stubs(:stat).returns stub('stat', :ftype => 'file')
|
897
898
|
file.stubs(:perform_backup).returns false
|
898
899
|
|
899
|
-
expect { file.remove_existing(:file) }.to raise_error(Puppet::Error, /Could not back up; will not
|
900
|
+
expect { file.remove_existing(:file) }.to raise_error(Puppet::Error, /Could not back up; will not remove/)
|
900
901
|
end
|
901
902
|
|
902
903
|
describe "backing up directories" do
|
903
|
-
it "should not backup directories if force is false" do
|
904
|
+
it "should not backup directories if backup is true and force is false" do
|
905
|
+
# Default: file[:backup] = true
|
904
906
|
file[:force] = false
|
905
907
|
file.stubs(:stat).returns stub('stat', :ftype => 'directory')
|
908
|
+
|
906
909
|
file.expects(:perform_backup).never
|
910
|
+
file.expects(:warning).with("Could not back up file of type directory")
|
907
911
|
expect(file.remove_existing(:file)).to eq(false)
|
908
912
|
end
|
909
913
|
|
910
|
-
it "should backup directories if force is true" do
|
914
|
+
it "should backup directories if backup is true and force is true" do
|
915
|
+
# Default: file[:backup] = true
|
911
916
|
file[:force] = true
|
912
|
-
FileUtils.expects(:rmtree).with(file[:path])
|
913
|
-
|
914
917
|
file.stubs(:stat).returns stub('stat', :ftype => 'directory')
|
915
|
-
|
918
|
+
|
919
|
+
FileUtils.expects(:rmtree).with(file[:path])
|
920
|
+
file.expects(:perform_backup).returns(true)
|
916
921
|
|
917
922
|
expect(file.remove_existing(:file)).to eq(true)
|
918
923
|
end
|
@@ -924,18 +929,17 @@ describe Puppet::Type.type(:file) do
|
|
924
929
|
expect(file.remove_existing(:file)).to eq(false)
|
925
930
|
end
|
926
931
|
|
927
|
-
it "should not remove directories and should not invalidate the stat unless force is
|
932
|
+
it "should not remove directories and should not invalidate the stat unless force is true" do
|
933
|
+
file[:force] = false
|
928
934
|
# Actually call stat to set @needs_stat to nil
|
929
935
|
file.stat
|
930
936
|
file.stubs(:stat).returns stub('stat', :ftype => 'directory')
|
931
937
|
|
932
|
-
file.remove_existing(:file)
|
933
|
-
|
934
938
|
expect(file.instance_variable_get(:@stat)).to eq(nil)
|
935
|
-
expect(@logs).to be_any {|log| log.level == :notice and log.message =~ /Not removing directory; use 'force' to override/}
|
936
939
|
end
|
937
940
|
|
938
|
-
it "should remove a directory if force is
|
941
|
+
it "should remove a directory if backup is true and force is true" do
|
942
|
+
# Default: file[:backup] = true
|
939
943
|
file[:force] = true
|
940
944
|
file.stubs(:stat).returns stub('stat', :ftype => 'directory')
|
941
945
|
|
@@ -966,10 +970,11 @@ describe Puppet::Type.type(:file) do
|
|
966
970
|
expect(Puppet::FileSystem.exist?(file[:path])).to eq(false)
|
967
971
|
end
|
968
972
|
|
969
|
-
it "should fail if the file is not a
|
970
|
-
file.stubs(:stat).returns stub('stat', :ftype => '
|
973
|
+
it "should fail if the file is not a directory, link, file, fifo, socket, or is unknown" do
|
974
|
+
file.stubs(:stat).returns stub('stat', :ftype => 'blockSpecial')
|
971
975
|
|
972
|
-
|
976
|
+
file.expects(:warning).with("Could not back up file of type blockSpecial")
|
977
|
+
expect { file.remove_existing(:file) }.to raise_error(Puppet::Error, /Could not remove files of type blockSpecial/)
|
973
978
|
end
|
974
979
|
|
975
980
|
it "should invalidate the existing stat of the file" do
|
@@ -1,6 +1,8 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
2
3
|
require 'spec_helper'
|
3
4
|
require 'puppet/file_system/uniquefile'
|
5
|
+
require 'puppet_spec/character_encoding'
|
4
6
|
|
5
7
|
describe Puppet::Util::Execution do
|
6
8
|
include Puppet::Util::Execution
|
@@ -25,10 +27,12 @@ describe Puppet::Util::Execution do
|
|
25
27
|
FFI::WIN32.stubs(:CloseHandle).with(process_handle)
|
26
28
|
FFI::WIN32.stubs(:CloseHandle).with(thread_handle)
|
27
29
|
else
|
30
|
+
Process.stubs(:waitpid2).with(pid, Process::WNOHANG).returns(nil, [pid, stub('child_status', :exitstatus => exitstatus)])
|
28
31
|
Process.stubs(:waitpid2).with(pid).returns([pid, stub('child_status', :exitstatus => exitstatus)])
|
29
32
|
end
|
30
33
|
end
|
31
34
|
|
35
|
+
|
32
36
|
describe "#execute_posix (stubs)", :unless => Puppet.features.microsoft_windows? do
|
33
37
|
before :each do
|
34
38
|
# Most of the things this method does are bad to do during specs. :/
|
@@ -215,82 +219,136 @@ describe Puppet::Util::Execution do
|
|
215
219
|
end
|
216
220
|
end
|
217
221
|
|
218
|
-
describe "
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
+
describe "on POSIX", :if => Puppet.features.posix? do
|
223
|
+
describe "when squelch is not set" do
|
224
|
+
it "should set stdout to a pipe" do
|
225
|
+
Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,_|
|
226
|
+
stdout.class == IO
|
227
|
+
end.returns(rval)
|
222
228
|
|
223
|
-
|
224
|
-
|
225
|
-
end.returns(rval)
|
229
|
+
Puppet::Util::Execution.execute('test command', :squelch => false)
|
230
|
+
end
|
226
231
|
|
227
|
-
|
228
|
-
|
232
|
+
it "should set stderr to the same file as stdout if combine is true" do
|
233
|
+
Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
|
234
|
+
stdout == stderr
|
235
|
+
end.returns(rval)
|
229
236
|
|
230
|
-
|
231
|
-
|
232
|
-
Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
|
237
|
+
Puppet::Util::Execution.execute('test command', :squelch => false, :combine => true)
|
238
|
+
end
|
233
239
|
|
234
|
-
|
235
|
-
|
236
|
-
|
240
|
+
it "should set stderr to the null device if combine is false" do
|
241
|
+
Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
|
242
|
+
stdout.class == IO and stderr.path == null_file
|
243
|
+
end.returns(rval)
|
237
244
|
|
238
|
-
|
239
|
-
|
245
|
+
Puppet::Util::Execution.execute('test command', :squelch => false, :combine => false)
|
246
|
+
end
|
240
247
|
|
241
|
-
|
242
|
-
|
243
|
-
|
248
|
+
it "should default combine to true when no options are specified" do
|
249
|
+
Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
|
250
|
+
stdout == stderr
|
251
|
+
end.returns(rval)
|
244
252
|
|
245
|
-
|
246
|
-
|
247
|
-
end.returns(rval)
|
253
|
+
Puppet::Util::Execution.execute('test command')
|
254
|
+
end
|
248
255
|
|
249
|
-
|
250
|
-
|
256
|
+
it "should default combine to false when options are specified, but combine is not" do
|
257
|
+
Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
|
258
|
+
stdout.class == IO and stderr.path == null_file
|
259
|
+
end.returns(rval)
|
251
260
|
|
252
|
-
|
253
|
-
|
254
|
-
Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
|
261
|
+
Puppet::Util::Execution.execute('test command', :failonfail => false)
|
262
|
+
end
|
255
263
|
|
256
|
-
|
257
|
-
|
258
|
-
|
264
|
+
it "should default combine to false when an empty hash of options is specified" do
|
265
|
+
Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
|
266
|
+
stdout.class == IO and stderr.path == null_file
|
267
|
+
end.returns(rval)
|
259
268
|
|
260
|
-
|
269
|
+
Puppet::Util::Execution.execute('test command', {})
|
270
|
+
end
|
261
271
|
end
|
272
|
+
end
|
262
273
|
|
263
|
-
|
264
|
-
|
265
|
-
|
274
|
+
describe "on Windows", :if => Puppet.features.microsoft_windows? do
|
275
|
+
describe "when squelch is not set" do
|
276
|
+
it "should set stdout to a temporary output file" do
|
277
|
+
outfile = Puppet::FileSystem::Uniquefile.new('stdout')
|
278
|
+
Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
|
266
279
|
|
267
|
-
|
268
|
-
|
269
|
-
|
280
|
+
Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,_|
|
281
|
+
stdout.path == outfile.path
|
282
|
+
end.returns(rval)
|
270
283
|
|
271
|
-
|
272
|
-
|
284
|
+
Puppet::Util::Execution.execute('test command', :squelch => false)
|
285
|
+
end
|
273
286
|
|
274
|
-
|
275
|
-
|
276
|
-
|
287
|
+
it "should set stderr to the same file as stdout if combine is true" do
|
288
|
+
outfile = Puppet::FileSystem::Uniquefile.new('stdout')
|
289
|
+
Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
|
277
290
|
|
278
|
-
|
279
|
-
|
280
|
-
|
291
|
+
Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
|
292
|
+
stdout.path == outfile.path and stderr.path == outfile.path
|
293
|
+
end.returns(rval)
|
281
294
|
|
282
|
-
|
283
|
-
|
295
|
+
Puppet::Util::Execution.execute('test command', :squelch => false, :combine => true)
|
296
|
+
end
|
284
297
|
|
285
|
-
|
286
|
-
|
287
|
-
|
298
|
+
it "should set stderr to the null device if combine is false" do
|
299
|
+
outfile = Puppet::FileSystem::Uniquefile.new('stdout')
|
300
|
+
Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
|
288
301
|
|
289
|
-
|
290
|
-
|
291
|
-
|
302
|
+
Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
|
303
|
+
stdout.path == outfile.path and stderr.path == null_file
|
304
|
+
end.returns(rval)
|
305
|
+
|
306
|
+
Puppet::Util::Execution.execute('test command', :squelch => false, :combine => false)
|
307
|
+
end
|
308
|
+
|
309
|
+
it "should combine stdout and stderr if combine is true" do
|
310
|
+
outfile = Puppet::FileSystem::Uniquefile.new('stdout')
|
311
|
+
Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
|
312
|
+
|
313
|
+
Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
|
314
|
+
stdout.path == outfile.path and stderr.path == outfile.path
|
315
|
+
end.returns(rval)
|
316
|
+
|
317
|
+
Puppet::Util::Execution.execute('test command', :combine => true)
|
318
|
+
end
|
319
|
+
|
320
|
+
it "should default combine to true when no options are specified" do
|
321
|
+
outfile = Puppet::FileSystem::Uniquefile.new('stdout')
|
322
|
+
Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
|
323
|
+
|
324
|
+
Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
|
325
|
+
stdout.path == outfile.path and stderr.path == outfile.path
|
326
|
+
end.returns(rval)
|
327
|
+
|
328
|
+
Puppet::Util::Execution.execute('test command')
|
329
|
+
end
|
330
|
+
|
331
|
+
it "should default combine to false when options are specified, but combine is not" do
|
332
|
+
outfile = Puppet::FileSystem::Uniquefile.new('stdout')
|
333
|
+
Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
|
334
|
+
|
335
|
+
Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
|
336
|
+
stdout.path == outfile.path and stderr.path == null_file
|
337
|
+
end.returns(rval)
|
338
|
+
|
339
|
+
Puppet::Util::Execution.execute('test command', :failonfail => false)
|
340
|
+
end
|
341
|
+
|
342
|
+
it "should default combine to false when an empty hash of options is specified" do
|
343
|
+
outfile = Puppet::FileSystem::Uniquefile.new('stdout')
|
344
|
+
Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
|
345
|
+
|
346
|
+
Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
|
347
|
+
stdout.path == outfile.path and stderr.path == null_file
|
348
|
+
end.returns(rval)
|
292
349
|
|
293
|
-
|
350
|
+
Puppet::Util::Execution.execute('test command', {})
|
351
|
+
end
|
294
352
|
end
|
295
353
|
end
|
296
354
|
end
|
@@ -536,9 +594,10 @@ describe Puppet::Util::Execution do
|
|
536
594
|
end
|
537
595
|
|
538
596
|
it "should close the stdin/stdout/stderr files used by the child" do
|
539
|
-
stdin = mock 'file'
|
540
|
-
stdout = mock 'file'
|
541
|
-
stderr = mock 'file'
|
597
|
+
stdin = mock 'file'
|
598
|
+
stdout = mock 'file'
|
599
|
+
stderr = mock 'file'
|
600
|
+
[stdin, stdout, stderr].each {|io| io.expects(:close).at_least_once}
|
542
601
|
|
543
602
|
File.expects(:open).
|
544
603
|
times(3).
|
@@ -549,38 +608,113 @@ describe Puppet::Util::Execution do
|
|
549
608
|
Puppet::Util::Execution.execute('test command', {:squelch => true, :combine => false})
|
550
609
|
end
|
551
610
|
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
611
|
+
describe "on POSIX", :if => Puppet.features.posix? do
|
612
|
+
context "reading the output" do
|
613
|
+
before :each do
|
614
|
+
r, w = IO.pipe
|
615
|
+
IO.expects(:pipe).returns([r, w])
|
616
|
+
w.write("My expected \u2744 command output")
|
617
|
+
end
|
556
618
|
|
557
|
-
|
558
|
-
|
619
|
+
it "should return output with external encoding ISO_8859_1" do
|
620
|
+
result = PuppetSpec::CharacterEncoding.with_external_encoding(Encoding::ISO_8859_1) do
|
621
|
+
Puppet::Util::Execution.execute('test command')
|
622
|
+
end
|
623
|
+
expect(result.encoding).to eq(Encoding::ISO_8859_1)
|
624
|
+
expect(result).to eq("My expected \u2744 command output".force_encoding(Encoding::ISO_8859_1))
|
625
|
+
end
|
559
626
|
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
627
|
+
it "should return output with external encoding UTF_8" do
|
628
|
+
result = PuppetSpec::CharacterEncoding.with_external_encoding(Encoding::UTF_8) do
|
629
|
+
Puppet::Util::Execution.execute('test command')
|
630
|
+
end
|
631
|
+
expect(result.encoding).to eq(Encoding::UTF_8)
|
632
|
+
expect(result).to eq("My expected \u2744 command output")
|
633
|
+
end
|
634
|
+
end
|
564
635
|
|
565
|
-
|
566
|
-
|
636
|
+
it "should not read the output if squelch is true" do
|
637
|
+
IO.expects(:pipe).never
|
567
638
|
|
568
|
-
|
569
|
-
|
570
|
-
path = stdout.path
|
571
|
-
Puppet::FileSystem::Uniquefile.stubs(:new).returns(stdout)
|
639
|
+
expect(Puppet::Util::Execution.execute('test command', :squelch => true)).to eq('')
|
640
|
+
end
|
572
641
|
|
573
|
-
|
642
|
+
it "should close the pipe used for output if squelch is false" do
|
643
|
+
r, w = IO.pipe
|
644
|
+
IO.expects(:pipe).returns([r, w])
|
574
645
|
|
575
|
-
|
646
|
+
expect(Puppet::Util::Execution.execute('test command')).to eq("")
|
647
|
+
expect(r.closed?)
|
648
|
+
expect(w.closed?)
|
649
|
+
end
|
650
|
+
|
651
|
+
it "should close the pipe used for output if squelch is false and an error is raised" do
|
652
|
+
r, w = IO.pipe
|
653
|
+
IO.expects(:pipe).returns([r, w])
|
654
|
+
|
655
|
+
if Puppet.features.microsoft_windows?
|
656
|
+
Puppet::Util::Execution.expects(:execute_windows).raises(Exception, 'execution failed')
|
657
|
+
else
|
658
|
+
Puppet::Util::Execution.expects(:execute_posix).raises(Exception, 'execution failed')
|
659
|
+
end
|
660
|
+
|
661
|
+
expect {
|
662
|
+
subject.execute('fail command')
|
663
|
+
}.to raise_error(Exception, 'execution failed')
|
664
|
+
expect(r.closed?)
|
665
|
+
expect(w.closed?)
|
666
|
+
end
|
576
667
|
end
|
668
|
+
describe "on Windows", :if => Puppet.features.microsoft_windows? do
|
669
|
+
context "reading the output" do
|
670
|
+
before :each do
|
671
|
+
stdout = Puppet::FileSystem::Uniquefile.new('test')
|
672
|
+
Puppet::FileSystem::Uniquefile.stubs(:new).returns(stdout)
|
673
|
+
stdout.write("My expected \u2744 command output")
|
674
|
+
end
|
577
675
|
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
676
|
+
it "should return output with external encoding ISO_8859_1" do
|
677
|
+
result = PuppetSpec::CharacterEncoding.with_external_encoding(Encoding::ISO_8859_1) do
|
678
|
+
Puppet::Util::Execution.execute('test command')
|
679
|
+
end
|
680
|
+
expect(result.encoding).to eq(Encoding::ISO_8859_1)
|
681
|
+
expect(result).to eq("My expected \u2744 command output".force_encoding(Encoding::ISO_8859_1))
|
682
|
+
end
|
582
683
|
|
583
|
-
|
684
|
+
it "should return output with external encoding UTF_8" do
|
685
|
+
result = PuppetSpec::CharacterEncoding.with_external_encoding(Encoding::UTF_8) do
|
686
|
+
Puppet::Util::Execution.execute('test command')
|
687
|
+
end
|
688
|
+
expect(result.encoding).to eq(Encoding::UTF_8)
|
689
|
+
expect(result).to eq("My expected \u2744 command output")
|
690
|
+
end
|
691
|
+
end
|
692
|
+
|
693
|
+
it "should not read the output if squelch is true" do
|
694
|
+
stdout = Puppet::FileSystem::Uniquefile.new('test')
|
695
|
+
Puppet::FileSystem::Uniquefile.stubs(:new).returns(stdout)
|
696
|
+
stdout.write("My expected command output")
|
697
|
+
|
698
|
+
expect(Puppet::Util::Execution.execute('test command', :squelch => true)).to eq('')
|
699
|
+
end
|
700
|
+
|
701
|
+
it "should delete the file used for output if squelch is false" do
|
702
|
+
stdout = Puppet::FileSystem::Uniquefile.new('test')
|
703
|
+
path = stdout.path
|
704
|
+
Puppet::FileSystem::Uniquefile.stubs(:new).returns(stdout)
|
705
|
+
|
706
|
+
Puppet::Util::Execution.execute('test command')
|
707
|
+
|
708
|
+
expect(Puppet::FileSystem.exist?(path)).to be_falsey
|
709
|
+
end
|
710
|
+
|
711
|
+
it "should not raise an error if the file is open" do
|
712
|
+
stdout = Puppet::FileSystem::Uniquefile.new('test')
|
713
|
+
Puppet::FileSystem::Uniquefile.stubs(:new).returns(stdout)
|
714
|
+
file = File.new(stdout.path, 'r')
|
715
|
+
|
716
|
+
Puppet::Util::Execution.execute('test command')
|
717
|
+
end
|
584
718
|
end
|
585
719
|
|
586
720
|
it "should raise an error if failonfail is true and the child failed" do
|
@@ -710,7 +844,7 @@ describe Puppet::Util::Execution do
|
|
710
844
|
Puppet::Util::Execution.stubs(:execute).raises(Puppet::ExecutionFailure, "failed to execute")
|
711
845
|
expect {
|
712
846
|
Puppet::Util::Execution.execfail('echo hello', nil)
|
713
|
-
}.to raise_error(TypeError
|
847
|
+
}.to raise_error(TypeError, /exception class\/object expected/)
|
714
848
|
end
|
715
849
|
end
|
716
850
|
end
|