puppet 5.0.1-universal-darwin → 5.1.0-universal-darwin

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/lib/puppet/agent.rb +1 -0
  3. data/lib/puppet/defaults.rb +1 -1
  4. data/lib/puppet/functions.rb +6 -7
  5. data/lib/puppet/functions/all.rb +100 -0
  6. data/lib/puppet/functions/any.rb +105 -0
  7. data/lib/puppet/functions/defined.rb +3 -3
  8. data/lib/puppet/functions/new.rb +2 -1
  9. data/lib/puppet/functions/reduce.rb +31 -0
  10. data/lib/puppet/functions/tree_each.rb +200 -0
  11. data/lib/puppet/module.rb +30 -0
  12. data/lib/puppet/parser/functions/new.rb +67 -0
  13. data/lib/puppet/parser/functions/reduce.rb +31 -0
  14. data/lib/puppet/parser/relationship.rb +2 -2
  15. data/lib/puppet/parser/resource.rb +39 -10
  16. data/lib/puppet/parser/scope.rb +1 -1
  17. data/lib/puppet/pops/evaluator/access_operator.rb +11 -4
  18. data/lib/puppet/pops/evaluator/collector_transformer.rb +1 -1
  19. data/lib/puppet/pops/evaluator/evaluator_impl.rb +4 -4
  20. data/lib/puppet/pops/evaluator/relationship_operator.rb +1 -1
  21. data/lib/puppet/pops/evaluator/runtime3_converter.rb +3 -3
  22. data/lib/puppet/pops/evaluator/runtime3_resource_support.rb +1 -1
  23. data/lib/puppet/pops/loader/module_loaders.rb +1 -1
  24. data/lib/puppet/pops/loader/static_loader.rb +1 -2
  25. data/lib/puppet/pops/loaders.rb +1 -2
  26. data/lib/puppet/pops/lookup/context.rb +1 -1
  27. data/lib/puppet/pops/lookup/lookup_adapter.rb +2 -1
  28. data/lib/puppet/pops/model/ast.rb +440 -436
  29. data/lib/puppet/pops/model/factory.rb +140 -140
  30. data/lib/puppet/pops/pcore.rb +1 -2
  31. data/lib/puppet/pops/resource/param.rb +1 -1
  32. data/lib/puppet/pops/resource/resource_type_impl.rb +1 -1
  33. data/lib/puppet/pops/serialization/from_data_converter.rb +0 -12
  34. data/lib/puppet/pops/time/timestamp.rb +29 -17
  35. data/lib/puppet/pops/types/annotatable.rb +2 -2
  36. data/lib/puppet/pops/types/annotation.rb +8 -8
  37. data/lib/puppet/pops/types/class_loader.rb +3 -3
  38. data/lib/puppet/pops/types/implementation_registry.rb +1 -1
  39. data/lib/puppet/pops/types/iterable.rb +2 -2
  40. data/lib/puppet/pops/types/p_binary_type.rb +2 -2
  41. data/lib/puppet/pops/types/p_init_type.rb +238 -0
  42. data/lib/puppet/pops/types/p_meta_type.rb +14 -11
  43. data/lib/puppet/pops/types/p_object_type.rb +15 -15
  44. data/lib/puppet/pops/types/p_sem_ver_range_type.rb +2 -2
  45. data/lib/puppet/pops/types/p_sem_ver_type.rb +2 -2
  46. data/lib/puppet/pops/types/p_sensitive_type.rb +2 -2
  47. data/lib/puppet/pops/types/p_timespan_type.rb +6 -6
  48. data/lib/puppet/pops/types/p_timestamp_type.rb +6 -2
  49. data/lib/puppet/pops/types/p_type_set_type.rb +10 -9
  50. data/lib/puppet/pops/types/ruby_generator.rb +6 -5
  51. data/lib/puppet/pops/types/ruby_method.rb +2 -2
  52. data/lib/puppet/pops/types/string_converter.rb +1 -1
  53. data/lib/puppet/pops/types/tree_iterators.rb +250 -0
  54. data/lib/puppet/pops/types/type_calculator.rb +13 -13
  55. data/lib/puppet/pops/types/type_factory.rb +26 -7
  56. data/lib/puppet/pops/types/type_formatter.rb +9 -4
  57. data/lib/puppet/pops/types/type_parser.rb +8 -3
  58. data/lib/puppet/pops/types/type_set_reference.rb +2 -2
  59. data/lib/puppet/pops/types/types.rb +168 -109
  60. data/lib/puppet/provider/package/gem.rb +10 -9
  61. data/lib/puppet/provider/package/pip.rb +12 -3
  62. data/lib/puppet/provider/package/yum.rb +9 -1
  63. data/lib/puppet/resource/capability_finder.rb +30 -11
  64. data/lib/puppet/type/file.rb +21 -13
  65. data/lib/puppet/util/execution.rb +67 -14
  66. data/lib/puppet/util/suidmanager.rb +1 -0
  67. data/lib/puppet/version.rb +1 -1
  68. data/locales/puppet.pot +130 -66
  69. data/man/man5/puppet.conf.5 +1 -1
  70. data/spec/fixtures/unit/provider/package/yum/yum-check-update-simple.txt +1 -0
  71. data/spec/integration/parser/collection_spec.rb +40 -1
  72. data/spec/shared_contexts/types_setup.rb +41 -2
  73. data/spec/unit/agent_spec.rb +11 -0
  74. data/spec/unit/file_bucket/dipper_spec.rb +13 -4
  75. data/spec/unit/functions/all_spec.rb +97 -0
  76. data/spec/unit/functions/any_spec.rb +109 -0
  77. data/spec/unit/functions/hiera_spec.rb +5 -0
  78. data/spec/unit/functions/new_spec.rb +66 -0
  79. data/spec/unit/functions/tree_each_spec.rb +444 -0
  80. data/spec/unit/module_spec.rb +29 -0
  81. data/spec/unit/pops/serialization/serialization_spec.rb +2 -2
  82. data/spec/unit/pops/serialization/to_from_hr_spec.rb +2 -2
  83. data/spec/unit/pops/types/iterable_spec.rb +9 -9
  84. data/spec/unit/pops/types/p_init_type_spec.rb +285 -0
  85. data/spec/unit/pops/types/p_object_type_spec.rb +8 -8
  86. data/spec/unit/pops/types/p_sensitive_type_spec.rb +4 -0
  87. data/spec/unit/pops/types/p_timespan_type_spec.rb +14 -0
  88. data/spec/unit/pops/types/p_timestamp_type_spec.rb +19 -1
  89. data/spec/unit/pops/types/p_type_set_type_spec.rb +2 -2
  90. data/spec/unit/pops/types/ruby_generator_spec.rb +9 -22
  91. data/spec/unit/pops/types/string_converter_spec.rb +2 -2
  92. data/spec/unit/pops/types/type_acceptor_spec.rb +2 -2
  93. data/spec/unit/pops/types/type_calculator_spec.rb +43 -38
  94. data/spec/unit/pops/types/type_factory_spec.rb +6 -6
  95. data/spec/unit/pops/types/type_formatter_spec.rb +6 -6
  96. data/spec/unit/pops/types/types_spec.rb +16 -4
  97. data/spec/unit/provider/package/gem_spec.rb +6 -6
  98. data/spec/unit/provider/package/pip_spec.rb +44 -23
  99. data/spec/unit/provider/package/puppet_gem_spec.rb +1 -1
  100. data/spec/unit/provider/package/yum_spec.rb +8 -0
  101. data/spec/unit/resource/capability_finder_spec.rb +4 -5
  102. data/spec/unit/type/file_spec.rb +19 -14
  103. data/spec/unit/util/execution_spec.rb +216 -82
  104. data/tasks/generate_ast_model.rake +10 -2
  105. 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(loader)
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(loader)
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(loader)
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(loader)
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[5] == '--force' && args[6] == '--bindir=/usr/bin' }.returns ''
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 = { ['All', nil] => ['pip', 'pip-python'] }
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
- it "should return pip-python on legacy systems" do
35
- Facter.stubs(:value).with(:osfamily).returns("legacy")
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
- Facter.stubs(:value).with(:osfamily).returns("All")
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
- it "should return an array on #{osfamily} when #{pip_cmds.join(' or ')} is present" do
50
- Facter.stubs(:value).with(:osfamily).returns(osfamily.first)
51
- Facter.stubs(:value).with(:operatingsystemmajrelease).returns(osfamily.last)
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
- it "should return an empty array on #{osfamily} when #{pip_cmds.join(' and ')} are missing" do
68
- Facter.stubs(:value).with(:osfamily).returns(osfamily.first)
69
- Facter.stubs(:value).with(:operatingsystemmajrelease).returns(osfamily.last)
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
- Facter.stubs(:value).with(:osfamily).returns(osfamily.first)
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
- Facter.stubs(:value).with(:osfamily).returns(osfamily.first)
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
- Facter.stubs(:value).with(:osfamily).returns(osfamily.first)
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[5] == '--force' && args[6] == '--bindir=/usr/bin' }.returns ''
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 return nil if no resource matches code_id' do
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
- result = Puppet::Resource::CapabilityFinder.find('production', code_id, capability)
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
@@ -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 replace/)
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
- file.expects(:perform_backup).once.returns(true)
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 set" do
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 set" do
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 file, link, or directory" do
970
- file.stubs(:stat).returns stub('stat', :ftype => 'socket')
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
- expect { file.remove_existing(:file) }.to raise_error(Puppet::Error, /Could not back up files of type socket/)
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 "when squelch is not set" do
219
- it "should set stdout to a temporary output file" do
220
- outfile = Puppet::FileSystem::Uniquefile.new('stdout')
221
- Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
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
- Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,_|
224
- stdout.path == outfile.path
225
- end.returns(rval)
229
+ Puppet::Util::Execution.execute('test command', :squelch => false)
230
+ end
226
231
 
227
- Puppet::Util::Execution.execute('test command', :squelch => false)
228
- end
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
- it "should set stderr to the same file as stdout if combine is true" do
231
- outfile = Puppet::FileSystem::Uniquefile.new('stdout')
232
- Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
237
+ Puppet::Util::Execution.execute('test command', :squelch => false, :combine => true)
238
+ end
233
239
 
234
- Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
235
- stdout.path == outfile.path and stderr.path == outfile.path
236
- end.returns(rval)
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
- Puppet::Util::Execution.execute('test command', :squelch => false, :combine => true)
239
- end
245
+ Puppet::Util::Execution.execute('test command', :squelch => false, :combine => false)
246
+ end
240
247
 
241
- it "should set stderr to the null device if combine is false" do
242
- outfile = Puppet::FileSystem::Uniquefile.new('stdout')
243
- Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
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
- Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
246
- stdout.path == outfile.path and stderr.path == null_file
247
- end.returns(rval)
253
+ Puppet::Util::Execution.execute('test command')
254
+ end
248
255
 
249
- Puppet::Util::Execution.execute('test command', :squelch => false, :combine => false)
250
- end
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
- it "should combine stdout and stderr if combine is true" do
253
- outfile = Puppet::FileSystem::Uniquefile.new('stdout')
254
- Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
261
+ Puppet::Util::Execution.execute('test command', :failonfail => false)
262
+ end
255
263
 
256
- Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
257
- stdout.path == outfile.path and stderr.path == outfile.path
258
- end.returns(rval)
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
- Puppet::Util::Execution.execute('test command', :combine => true)
269
+ Puppet::Util::Execution.execute('test command', {})
270
+ end
261
271
  end
272
+ end
262
273
 
263
- it "should default combine to true when no options are specified" do
264
- outfile = Puppet::FileSystem::Uniquefile.new('stdout')
265
- Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
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
- Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
268
- stdout.path == outfile.path and stderr.path == outfile.path
269
- end.returns(rval)
280
+ Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,_|
281
+ stdout.path == outfile.path
282
+ end.returns(rval)
270
283
 
271
- Puppet::Util::Execution.execute('test command')
272
- end
284
+ Puppet::Util::Execution.execute('test command', :squelch => false)
285
+ end
273
286
 
274
- it "should default combine to false when options are specified, but combine is not" do
275
- outfile = Puppet::FileSystem::Uniquefile.new('stdout')
276
- Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
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
- Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
279
- stdout.path == outfile.path and stderr.path == null_file
280
- end.returns(rval)
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
- Puppet::Util::Execution.execute('test command', :failonfail => false)
283
- end
295
+ Puppet::Util::Execution.execute('test command', :squelch => false, :combine => true)
296
+ end
284
297
 
285
- it "should default combine to false when an empty hash of options is specified" do
286
- outfile = Puppet::FileSystem::Uniquefile.new('stdout')
287
- Puppet::FileSystem::Uniquefile.stubs(:new).returns(outfile)
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
- Puppet::Util::Execution.expects(executor).with do |_,_,_,stdout,stderr|
290
- stdout.path == outfile.path and stderr.path == null_file
291
- end.returns(rval)
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
- Puppet::Util::Execution.execute('test command', {})
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', :close
540
- stdout = mock 'file', :close
541
- stderr = mock 'file', :close
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
- it "should read and return the output if squelch is false" do
553
- stdout = Puppet::FileSystem::Uniquefile.new('test')
554
- Puppet::FileSystem::Uniquefile.stubs(:new).returns(stdout)
555
- stdout.write("My expected command output")
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
- expect(Puppet::Util::Execution.execute('test command')).to eq("My expected command output")
558
- end
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
- it "should not read the output if squelch is true" do
561
- stdout = Puppet::FileSystem::Uniquefile.new('test')
562
- Puppet::FileSystem::Uniquefile.stubs(:new).returns(stdout)
563
- stdout.write("My expected command output")
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
- expect(Puppet::Util::Execution.execute('test command', :squelch => true)).to eq('')
566
- end
636
+ it "should not read the output if squelch is true" do
637
+ IO.expects(:pipe).never
567
638
 
568
- it "should delete the file used for output if squelch is false" do
569
- stdout = Puppet::FileSystem::Uniquefile.new('test')
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
- Puppet::Util::Execution.execute('test command')
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
- expect(Puppet::FileSystem.exist?(path)).to be_falsey
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
- it "should not raise an error if the file is open" do
579
- stdout = Puppet::FileSystem::Uniquefile.new('test')
580
- Puppet::FileSystem::Uniquefile.stubs(:new).returns(stdout)
581
- file = File.new(stdout.path, 'r')
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
- Puppet::Util::Execution.execute('test command')
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), /exception class\/object expected/
847
+ }.to raise_error(TypeError, /exception class\/object expected/)
714
848
  end
715
849
  end
716
850
  end