chef 12.15.19-universal-mingw32 → 12.16.42-universal-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -1
  3. data/VERSION +1 -1
  4. data/acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml +3 -1
  5. data/acceptance/Gemfile.lock +14 -14
  6. data/acceptance/data-collector/test/integration/default/serverspec/default_spec.rb +3 -11
  7. data/distro/common/html/knife_bootstrap.html +1 -1
  8. data/distro/common/man/man1/README.md +2 -2
  9. data/distro/common/man/man1/knife-client.1 +1 -1
  10. data/lib/chef/application.rb +7 -15
  11. data/lib/chef/application/client.rb +2 -2
  12. data/lib/chef/application/solo.rb +1 -1
  13. data/lib/chef/chef_class.rb +1 -0
  14. data/lib/chef/chef_fs/file_system/chef_server/cookbook_file.rb +3 -7
  15. data/lib/chef/chef_fs/file_system/chef_server/versioned_cookbook_dir.rb +1 -1
  16. data/lib/chef/data_collector.rb +83 -9
  17. data/lib/chef/data_collector/messages.rb +2 -1
  18. data/lib/chef/dsl/core.rb +1 -1
  19. data/lib/chef/dsl/declare_resource.rb +10 -4
  20. data/lib/chef/dsl/method_missing.rb +1 -1
  21. data/lib/chef/dsl/recipe.rb +1 -1
  22. data/lib/chef/dsl/universal.rb +1 -1
  23. data/lib/chef/event_dispatch/base.rb +3 -0
  24. data/lib/chef/http.rb +3 -4
  25. data/lib/chef/knife.rb +20 -2
  26. data/lib/chef/knife/core/generic_presenter.rb +18 -4
  27. data/lib/chef/knife/node_show.rb +0 -5
  28. data/lib/chef/knife/osc_user_show.rb +0 -1
  29. data/lib/chef/knife/ssl_fetch.rb +9 -5
  30. data/lib/chef/mixin/powershell_out.rb +1 -1
  31. data/lib/chef/mixin/shell_out.rb +1 -1
  32. data/lib/chef/node.rb +1 -5
  33. data/lib/chef/node/attribute.rb +70 -98
  34. data/lib/chef/node/attribute_collections.rb +28 -19
  35. data/lib/chef/node/common_api.rb +0 -6
  36. data/lib/chef/node/immutable_collections.rb +16 -79
  37. data/lib/chef/node/mixin/deep_merge_cache.rb +61 -0
  38. data/lib/chef/node/mixin/immutablize_array.rb +67 -0
  39. data/lib/chef/node/mixin/immutablize_hash.rb +54 -0
  40. data/lib/chef/node/mixin/state_tracking.rb +93 -0
  41. data/lib/chef/property.rb +4 -4
  42. data/lib/chef/provider/cron.rb +1 -1
  43. data/lib/chef/provider/group/suse.rb +23 -4
  44. data/lib/chef/provider/package.rb +43 -5
  45. data/lib/chef/provider/package/apt.rb +20 -0
  46. data/lib/chef/provider/package/windows/exe.rb +4 -3
  47. data/lib/chef/provider/package/windows/msi.rb +4 -3
  48. data/lib/chef/provider/package/yum.rb +20 -0
  49. data/lib/chef/provider/package/zypper.rb +20 -0
  50. data/lib/chef/provider/ruby_block.rb +1 -1
  51. data/lib/chef/provider/service/upstart.rb +25 -9
  52. data/lib/chef/provider/user.rb +4 -6
  53. data/lib/chef/provider/user/dscl.rb +8 -3
  54. data/lib/chef/provider/user/solaris.rb +5 -12
  55. data/lib/chef/resource.rb +19 -0
  56. data/lib/chef/resource/file.rb +1 -1
  57. data/lib/chef/resource/package.rb +1 -1
  58. data/lib/chef/resource/scm.rb +1 -7
  59. data/lib/chef/resource/yum_repository.rb +1 -1
  60. data/lib/chef/rest.rb +1 -0
  61. data/lib/chef/run_context.rb +12 -0
  62. data/lib/chef/version.rb +1 -1
  63. data/spec/data/trusted_certs/example_no_cn.crt +36 -0
  64. data/spec/functional/resource/group_spec.rb +1 -0
  65. data/spec/functional/resource/user/useradd_spec.rb +4 -2
  66. data/spec/integration/knife/data_bag_create_spec.rb +0 -3
  67. data/spec/integration/knife/environment_show_spec.rb +24 -4
  68. data/spec/integration/knife/node_environment_set_spec.rb +4 -1
  69. data/spec/integration/recipes/accumulator_spec.rb +232 -0
  70. data/spec/integration/recipes/resource_action_spec.rb +1 -1
  71. data/spec/spec_helper.rb +2 -2
  72. data/spec/support/shared/context/client.rb +12 -3
  73. data/spec/support/shared/integration/app_server_support.rb +1 -1
  74. data/spec/support/shared/integration/knife_support.rb +4 -1
  75. data/spec/unit/data_collector/messages_spec.rb +2 -0
  76. data/spec/unit/data_collector_spec.rb +158 -21
  77. data/spec/unit/http_spec.rb +1 -1
  78. data/spec/unit/knife/core/gem_glob_loader_spec.rb +1 -1
  79. data/spec/unit/knife/core/ui_spec.rb +10 -0
  80. data/spec/unit/knife/ssl_fetch_spec.rb +38 -0
  81. data/spec/unit/knife_spec.rb +31 -0
  82. data/spec/unit/mixin/powershell_out_spec.rb +25 -1
  83. data/spec/unit/node/attribute_spec.rb +46 -1
  84. data/spec/unit/node/vivid_mash_spec.rb +27 -89
  85. data/spec/unit/node_spec.rb +134 -3
  86. data/spec/unit/provider/deploy_spec.rb +1 -1
  87. data/spec/unit/provider/group/suse_spec.rb +90 -0
  88. data/spec/unit/provider/package/apt_spec.rb +22 -0
  89. data/spec/unit/provider/package/windows/msi_spec.rb +13 -4
  90. data/spec/unit/provider/package/windows_spec.rb +3 -3
  91. data/spec/unit/provider/package/yum_spec.rb +18 -0
  92. data/spec/unit/provider/package/zypper_spec.rb +64 -0
  93. data/spec/unit/provider/package_spec.rb +58 -0
  94. data/spec/unit/provider/remote_file/content_spec.rb +1 -1
  95. data/spec/unit/provider/service/upstart_service_spec.rb +13 -6
  96. data/spec/unit/provider/user/solaris_spec.rb +36 -9
  97. data/spec/unit/provider/user_spec.rb +6 -0
  98. data/spec/unit/resource/apt_repository_spec.rb +1 -1
  99. metadata +12 -5
@@ -243,6 +243,34 @@ describe Chef::Node do
243
243
  expect { node.sunshine = "is bright" }.to raise_error(Chef::Exceptions::ImmutableAttributeModification)
244
244
  end
245
245
 
246
+ it "does not allow modification of node attributes via hash methods" do
247
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
248
+ node.default["h4sh"] = { foo: "bar" }
249
+ expect { node["h4sh"].delete("foo") }.to raise_error(Chef::Exceptions::ImmutableAttributeModification)
250
+ expect { node.h4sh.delete("foo") }.to raise_error(Chef::Exceptions::ImmutableAttributeModification)
251
+ end
252
+
253
+ it "does not allow modification of node attributes via array methods" do
254
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
255
+ node.default["array"] = []
256
+ expect { node["array"] << "boom" }.to raise_error(Chef::Exceptions::ImmutableAttributeModification)
257
+ expect { node.array << "boom" }.to raise_error(Chef::Exceptions::ImmutableAttributeModification)
258
+ end
259
+
260
+ it "returns merged immutable attributes for arrays" do
261
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
262
+ node.default["array"] = []
263
+ expect( node["array"].class ).to eql(Chef::Node::ImmutableArray)
264
+ expect( node.array.class ).to eql(Chef::Node::ImmutableArray)
265
+ end
266
+
267
+ it "returns merged immutable attributes for hashes" do
268
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
269
+ node.default["h4sh"] = {}
270
+ expect( node["h4sh"].class ).to eql(Chef::Node::ImmutableMash)
271
+ expect( node.h4sh.class ).to eql(Chef::Node::ImmutableMash)
272
+ end
273
+
246
274
  it "should allow you get get an attribute via method_missing" do
247
275
  Chef::Config[:treat_deprecation_warnings_as_errors] = false
248
276
  node.default.sunshine = "is bright"
@@ -756,9 +784,9 @@ describe Chef::Node do
756
784
  # In Chef-12.0 there is a deep_merge cache on the top level attribute which had a bug
757
785
  # where it cached node[:foo] separate from node['foo']. These tests exercise those edge conditions.
758
786
  #
759
- # https://github.com/opscode/chef/issues/2700
760
- # https://github.com/opscode/chef/issues/2712
761
- # https://github.com/opscode/chef/issues/2745
787
+ # https://github.com/chef/chef/issues/2700
788
+ # https://github.com/chef/chef/issues/2712
789
+ # https://github.com/chef/chef/issues/2745
762
790
  #
763
791
  describe "deep merge attribute cache edge conditions" do
764
792
  it "does not error with complicated attribute substitution" do
@@ -1681,4 +1709,107 @@ describe Chef::Node do
1681
1709
  end
1682
1710
  end
1683
1711
 
1712
+ describe "path tracking via __path__" do
1713
+ it "works through hash keys" do
1714
+ node.default["foo"] = { "bar" => { "baz" => "qux" } }
1715
+ expect(node["foo"]["bar"].__path__).to eql(%w{foo bar})
1716
+ end
1717
+
1718
+ it "works through the default level" do
1719
+ node.default["foo"] = { "bar" => { "baz" => "qux" } }
1720
+ expect(node.default["foo"]["bar"].__path__).to eql(%w{foo bar})
1721
+ end
1722
+
1723
+ it "works through arrays" do
1724
+ node.default["foo"] = [ { "bar" => { "baz" => "qux" } } ]
1725
+ expect(node["foo"][0].__path__).to eql(["foo", 0])
1726
+ expect(node["foo"][0]["bar"].__path__).to eql(["foo", 0, "bar"])
1727
+ end
1728
+
1729
+ it "works through arrays at the default level" do
1730
+ node.default["foo"] = [ { "bar" => { "baz" => "qux" } } ]
1731
+ expect(node.default["foo"][0].__path__).to eql(["foo", 0])
1732
+ expect(node.default["foo"][0]["bar"].__path__).to eql(["foo", 0, "bar"])
1733
+ end
1734
+
1735
+ # if we set __path__ in the initializer we'd get this wrong, this is why we
1736
+ # update the path on every #[] or #[]= operator
1737
+ it "works on access when the node has been rearranged" do
1738
+ node.default["foo"] = { "bar" => { "baz" => "qux" } }
1739
+ a = node.default["foo"]
1740
+ node.default["fizz"] = a
1741
+ expect(node["fizz"]["bar"].__path__).to eql(%w{fizz bar})
1742
+ expect(node["foo"]["bar"].__path__).to eql(%w{foo bar})
1743
+ end
1744
+
1745
+ # We have a problem because the __path__ is stored on in each node, but the
1746
+ # node can be wired up at multiple locations in the tree via pointers. One
1747
+ # solution would be to deep-dup the value in `#[]=(key, value)` and fix the
1748
+ # __path__ on all the dup'd nodes. The problem is that this would create an
1749
+ # unusual situation where after assignment, you couldn't mutate the thing you
1750
+ # hand a handle on. I'm not entirely positive this behavior is the correct
1751
+ # thing to support, but it is more hash-like (although if we start with a hash
1752
+ # then convert_value does its thing and we *do* get dup'd on assignment). This
1753
+ # behavior likely makes any implementation of a deep merge cache built over the
1754
+ # top of __path__ tracking have edge conditions where it will fail.
1755
+ #
1756
+ # Removing this support would be a breaking change. The test is included here
1757
+ # because it seems most likely that someone would break this behavior while trying
1758
+ # to fix __path__ behavior.
1759
+ it "does not dup in the background when a node is assigned" do
1760
+ # get a handle on a vividmash (can't be a hash or else we convert_value it)
1761
+ node.default["foo"] = { "bar" => { "baz" => "qux" } }
1762
+ a = node.default["foo"]
1763
+ # assign that somewhere else in the tree
1764
+ node.default["fizz"] = a
1765
+ # now upate the source
1766
+ a["duptest"] = true
1767
+ # the tree should have been updated
1768
+ expect(node.default["fizz"]["duptest"]).to be true
1769
+ expect(node["fizz"]["duptest"]).to be true
1770
+ end
1771
+ end
1772
+
1773
+ describe "root tracking via __root__" do
1774
+ it "works through hash keys" do
1775
+ node.default["foo"] = { "bar" => { "baz" => "qux" } }
1776
+ expect(node["foo"]["bar"].__root__).to eql(node.attributes)
1777
+ end
1778
+
1779
+ it "works through the default level" do
1780
+ node.default["foo"] = { "bar" => { "baz" => "qux" } }
1781
+ expect(node.default["foo"]["bar"].__root__).to eql(node.attributes)
1782
+ end
1783
+
1784
+ it "works through arrays" do
1785
+ node.default["foo"] = [ { "bar" => { "baz" => "qux" } } ]
1786
+ expect(node["foo"][0].__root__).to eql(node.attributes)
1787
+ expect(node["foo"][0]["bar"].__root__).to eql(node.attributes)
1788
+ end
1789
+
1790
+ it "works through arrays at the default level" do
1791
+ node.default["foo"] = [ { "bar" => { "baz" => "qux" } } ]
1792
+ expect(node.default["foo"][0].__root__).to eql(node.attributes)
1793
+ expect(node.default["foo"][0]["bar"].__root__).to eql(node.attributes)
1794
+ end
1795
+ end
1796
+
1797
+ describe "ways of abusing Chef 12 node state" do
1798
+ # these tests abuse the top_level_breadcrumb state in Chef 12
1799
+ it "derived attributes work correctly" do
1800
+ node.default["v1"] = 1
1801
+ expect(node["a"]).to eql(nil)
1802
+ node.default["a"] = node["v1"]
1803
+ expect(node["a"]).to eql(1)
1804
+ end
1805
+
1806
+ it "works when saving nodes to variables" do
1807
+ a = node.default["a"]
1808
+ expect(node["a"]).to eql({})
1809
+ node.default["b"] = 0
1810
+ a["key"] = 1
1811
+
1812
+ expect(node["a"]["key"]).to eql(1)
1813
+ end
1814
+ end
1684
1815
  end
@@ -556,7 +556,7 @@ describe Chef::Provider::Deploy do
556
556
  @resource.deploy_to("/my/app")
557
557
  expect(mock_execution).to receive(:user).with("notCoolMan")
558
558
  expect(mock_execution).to receive(:group).with("Ggroup")
559
- expect(mock_execution).to receive(:cwd) {|*args|
559
+ expect(mock_execution).to receive(:cwd) { |*args|
560
560
  if args.empty?
561
561
  nil
562
562
  else
@@ -0,0 +1,90 @@
1
+ #
2
+ # Author:: Tom Duffield (<tom@chef.io>)
3
+ # Copyright:: Copyright 2016 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ #     http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require "spec_helper"
20
+
21
+ describe Chef::Provider::Group::Suse do
22
+ let(:node) { Chef::Node.new }
23
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
24
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
25
+ let(:new_members) { %w{root new_user} }
26
+ let(:new_resource) do
27
+ Chef::Resource::Group.new("new_group").tap do |r|
28
+ r.gid 50
29
+ r.members new_members
30
+ r.system false
31
+ r.non_unique false
32
+ end
33
+ end
34
+ let(:current_resource) do
35
+ Chef::Resource::Group.new("new_group").tap do |r|
36
+ r.gid 50
37
+ r.members %w{root}
38
+ r.system false
39
+ r.non_unique false
40
+ end
41
+ end
42
+ let(:provider) do
43
+ described_class.new(new_resource, run_context).tap do |p|
44
+ p.current_resource = current_resource
45
+ end
46
+ end
47
+
48
+ describe "when determining the current group state" do
49
+ before(:each) do
50
+ allow(File).to receive(:exists?).and_return(true)
51
+ provider.action = :create
52
+ provider.define_resource_requirements
53
+ end
54
+
55
+ # Checking for required binaries is already done in the spec
56
+ # for Chef::Provider::Group - no need to repeat it here. We'll
57
+ # include only what's specific to this provider.
58
+ it "should raise an error if the required binary /usr/sbin/groupmod doesn't exist" do
59
+ expect(File).to receive(:exists?).with("/usr/sbin/groupmod").and_return(false)
60
+ expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group)
61
+ end
62
+
63
+ it "should raise error if one of the member users does not exist" do
64
+ expect(Etc).to receive(:getpwnam).with("new_user").and_raise ArgumentError
65
+ expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group)
66
+ end
67
+ end
68
+
69
+ describe "#set_members" do
70
+ it "should add missing members and remove deleted members" do
71
+ expect(provider).not_to receive(:remove_member)
72
+ expect(provider).to receive(:add_member).with("new_user")
73
+ provider.set_members(new_members)
74
+ end
75
+ end
76
+
77
+ describe "#add_member" do
78
+ it "should call out to groupmod to add user" do
79
+ expect(provider).to receive(:shell_out!).with("groupmod -A new_user new_group")
80
+ provider.add_member("new_user")
81
+ end
82
+ end
83
+
84
+ describe "#remove_member" do
85
+ it "should call out to groupmod to remove user" do
86
+ expect(provider).to receive(:shell_out!).with("groupmod -R new_user new_group")
87
+ provider.remove_member("new_user")
88
+ end
89
+ end
90
+ end
@@ -395,6 +395,28 @@ mpg123 1.12.1-0ubuntu1
395
395
  end
396
396
  end
397
397
 
398
+ describe "when locking a package" do
399
+ it "should run apt-mark hold package" do
400
+ expect(@provider).to receive(:shell_out!).with(
401
+ "apt-mark hold irssi",
402
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
403
+ :timeout => @timeout
404
+ )
405
+ @provider.lock_package("irssi", "0.8.12-7")
406
+ end
407
+ end
408
+
409
+ describe "when unlocking a package" do
410
+ it "should run apt-mark unhold package" do
411
+ expect(@provider).to receive(:shell_out!).with(
412
+ "apt-mark unhold irssi",
413
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
414
+ :timeout => @timeout
415
+ )
416
+ @provider.unlock_package("irssi", "0.8.12-7")
417
+ end
418
+ end
419
+
398
420
  describe "when installing a virtual package" do
399
421
  it "should install the package without specifying a version" do
400
422
  @provider.package_data["libmysqlclient15-dev"][:virtual] = true
@@ -121,7 +121,7 @@ describe Chef::Provider::Package::Windows::MSI do
121
121
  end
122
122
 
123
123
  it "removes installed package" do
124
- expect(provider).to receive(:shell_out!).with(/MsiExec.exe \/X{guid} \/Q/, kind_of(Hash))
124
+ expect(provider).to receive(:shell_out!).with(/msiexec \/x {guid} \/q/, kind_of(Hash))
125
125
  provider.remove_package
126
126
  end
127
127
 
@@ -140,8 +140,8 @@ describe Chef::Provider::Package::Windows::MSI do
140
140
  end
141
141
 
142
142
  it "removes both installed package" do
143
- expect(provider).to receive(:shell_out!).with(/MsiExec.exe \/X{guid} \/Q/, kind_of(Hash))
144
- expect(provider).to receive(:shell_out!).with(/MsiExec.exe \/X{guid2} \/Q/, kind_of(Hash))
143
+ expect(provider).to receive(:shell_out!).with(/msiexec \/x {guid} \/q/, kind_of(Hash))
144
+ expect(provider).to receive(:shell_out!).with(/msiexec \/x {guid2} \/q/, kind_of(Hash))
145
145
  provider.remove_package
146
146
  end
147
147
  end
@@ -150,7 +150,16 @@ describe Chef::Provider::Package::Windows::MSI do
150
150
  before { new_resource.options("/Q") }
151
151
 
152
152
  it "does not duplicate quiet switch" do
153
- expect(provider).to receive(:shell_out!).with(/MsiExec.exe \/X{guid} \/Q/, kind_of(Hash))
153
+ expect(provider).to receive(:shell_out!).with(/msiexec \/x {guid} \/Q/, kind_of(Hash))
154
+ provider.remove_package
155
+ end
156
+ end
157
+
158
+ context "custom options includes /qn" do
159
+ before { new_resource.options("/qn") }
160
+
161
+ it "does not duplicate quiet switch" do
162
+ expect(provider).to receive(:shell_out!).with(/msiexec \/x {guid} \/qn/, kind_of(Hash))
154
163
  provider.remove_package
155
164
  end
156
165
  end
@@ -26,9 +26,9 @@ describe Chef::Provider::Package::Windows, :windows_only do
26
26
  allow(Chef::FileCache).to receive(:create_cache_path).with("package/").and_return(cache_path)
27
27
  end
28
28
 
29
- let(:node) { double("Chef::Node") }
30
- let(:events) { double("Chef::Events").as_null_object } # mock all the methods
31
- let(:run_context) { double("Chef::RunContext", :node => node, :events => events) }
29
+ let(:node) { Chef::Node.new }
30
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
31
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
32
32
  let(:resource_source) { "calculator.msi" }
33
33
  let(:resource_name) { "calculator" }
34
34
  let(:installer_type) { nil }
@@ -785,6 +785,24 @@ describe Chef::Provider::Package::Yum do
785
785
  end
786
786
  end
787
787
 
788
+ describe "when locking a package" do
789
+ it "should run yum versionlock add with the package name" do
790
+ expect(@provider).to receive(:yum_command).with(
791
+ "-d0 -e0 -y versionlock add emacs"
792
+ )
793
+ @provider.lock_package("emacs", nil)
794
+ end
795
+ end
796
+
797
+ describe "when unlocking a package" do
798
+ it "should run yum versionlock delete with the package name" do
799
+ expect(@provider).to receive(:yum_command).with(
800
+ "-d0 -e0 -y versionlock delete emacs"
801
+ )
802
+ @provider.unlock_package("emacs", nil)
803
+ end
804
+ end
805
+
788
806
  describe "when running yum" do
789
807
  it "should run yum once if it exits with a return code of 0" do
790
808
  @status = double("Status", :exitstatus => 0, :stdout => "", :stderr => "")
@@ -231,6 +231,70 @@ describe Chef::Provider::Package::Zypper do
231
231
  end
232
232
  end
233
233
 
234
+ describe "lock_package" do
235
+ it "should run zypper addlock with the package name" do
236
+ allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(true)
237
+ shell_out_expectation!(
238
+ "zypper --non-interactive addlock emacs"
239
+ )
240
+ provider.lock_package(["emacs"], [nil])
241
+ end
242
+ it "should run zypper addlock without gpg checks" do
243
+ allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(false)
244
+ shell_out_expectation!(
245
+ "zypper --non-interactive --no-gpg-checks addlock emacs"
246
+ )
247
+ provider.lock_package(["emacs"], [nil])
248
+ end
249
+ it "should warn about gpg checks on zypper addlock" do
250
+ expect(Chef::Log).to receive(:warn).with(
251
+ /All packages will be installed without gpg signature checks/
252
+ )
253
+ shell_out_expectation!(
254
+ "zypper --non-interactive --no-gpg-checks addlock emacs"
255
+ )
256
+ provider.lock_package(["emacs"], [nil])
257
+ end
258
+ it "should run zypper addlock without gpg checks" do
259
+ shell_out_expectation!(
260
+ "zypper --non-interactive --no-gpg-checks addlock emacs"
261
+ )
262
+ provider.lock_package(["emacs"], [nil])
263
+ end
264
+ end
265
+
266
+ describe "unlock_package" do
267
+ it "should run zypper removelock with the package name" do
268
+ allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(true)
269
+ shell_out_expectation!(
270
+ "zypper --non-interactive removelock emacs"
271
+ )
272
+ provider.unlock_package(["emacs"], [nil])
273
+ end
274
+ it "should run zypper removelock without gpg checks" do
275
+ allow(Chef::Config).to receive(:[]).with(:zypper_check_gpg).and_return(false)
276
+ shell_out_expectation!(
277
+ "zypper --non-interactive --no-gpg-checks removelock emacs"
278
+ )
279
+ provider.unlock_package(["emacs"], [nil])
280
+ end
281
+ it "should warn about gpg checks on zypper removelock" do
282
+ expect(Chef::Log).to receive(:warn).with(
283
+ /All packages will be installed without gpg signature checks/
284
+ )
285
+ shell_out_expectation!(
286
+ "zypper --non-interactive --no-gpg-checks removelock emacs"
287
+ )
288
+ provider.unlock_package(["emacs"], [nil])
289
+ end
290
+ it "should run zypper removelock without gpg checks" do
291
+ shell_out_expectation!(
292
+ "zypper --non-interactive --no-gpg-checks removelock emacs"
293
+ )
294
+ provider.unlock_package(["emacs"], [nil])
295
+ end
296
+ end
297
+
234
298
  describe "on an older zypper" do
235
299
  before(:each) do
236
300
  allow(provider).to receive(:`).and_return("0.11.6")
@@ -321,6 +321,56 @@ describe Chef::Provider::Package do
321
321
  end
322
322
  end
323
323
 
324
+ describe "When locking the package" do
325
+ before(:each) do
326
+ allow(provider).to receive(:lock_package).and_return(true)
327
+ end
328
+
329
+ it "should lock the package if it is unlocked" do
330
+ allow(provider).to receive(:package_locked).and_return(false)
331
+ expect(provider).to receive(:lock_package)
332
+ provider.run_action(:lock)
333
+ end
334
+
335
+ it "should not lock the package if it is already locked" do
336
+ allow(provider).to receive(:package_locked).and_return(true)
337
+ expect(provider).not_to receive(:lock_package)
338
+ provider.run_action(:lock)
339
+ expect(new_resource).not_to be_updated_by_last_action
340
+ end
341
+
342
+ it "should set the resource to updated if it locks the package" do
343
+ allow(provider).to receive(:package_locked).and_return(false)
344
+ provider.run_action(:lock)
345
+ expect(new_resource).to be_updated
346
+ end
347
+ end
348
+
349
+ describe "When unlocking the package" do
350
+ before(:each) do
351
+ allow(provider).to receive(:unlock_package).and_return(true)
352
+ end
353
+
354
+ it "should unlock the package if it is locked" do
355
+ allow(provider).to receive(:package_locked).and_return(true)
356
+ expect(provider).to receive(:unlock_package)
357
+ provider.run_action(:unlock)
358
+ end
359
+
360
+ it "should not unlock the package if it is already unlocked" do
361
+ allow(provider).to receive(:package_locked).and_return(false)
362
+ expect(provider).not_to receive(:unlock_package)
363
+ provider.run_action(:unlock)
364
+ expect(new_resource).not_to be_updated_by_last_action
365
+ end
366
+
367
+ it "should set the resource to updated if it unlocks the package" do
368
+ allow(provider).to receive(:package_locked).and_return(true)
369
+ provider.run_action(:unlock)
370
+ expect(new_resource).to be_updated
371
+ end
372
+ end
373
+
324
374
  describe "when running commands to be implemented by subclasses" do
325
375
  it "should raises UnsupportedAction for install" do
326
376
  expect { provider.install_package("emacs", "1.4.2") }.to raise_error(Chef::Exceptions::UnsupportedAction)
@@ -346,6 +396,14 @@ describe Chef::Provider::Package do
346
396
  it "should raise UnsupportedAction for reconfig" do
347
397
  expect { provider.reconfig_package("emacs", "1.4.2") }.to raise_error(Chef::Exceptions::UnsupportedAction)
348
398
  end
399
+
400
+ it "should raise UnsupportedAction for lock" do
401
+ expect { provider.lock_package("emacs", nil) }.to raise_error(Chef::Exceptions::UnsupportedAction)
402
+ end
403
+
404
+ it "should raise UnsupportedAction for unlock" do
405
+ expect { provider.unlock_package("emacs", nil) }.to raise_error(Chef::Exceptions::UnsupportedAction)
406
+ end
349
407
  end
350
408
 
351
409
  describe "when given a response file" do