summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/functional/rebooter_spec.rb33
-rw-r--r--spec/functional/resource/user/useradd_spec.rb8
-rw-r--r--spec/functional/resource/windows_task_spec.rb25
-rw-r--r--spec/functional/win32/security_spec.rb40
-rw-r--r--spec/support/shared/functional/execute_resource.rb2
-rw-r--r--spec/unit/chef_fs/data_handler/data_bag_item_data_handler.rb79
-rw-r--r--spec/unit/client_spec.rb13
-rw-r--r--spec/unit/knife/data_bag_create_spec.rb8
-rw-r--r--spec/unit/mixin/user_context_spec.rb3
-rw-r--r--spec/unit/provider/package/apt_spec.rb34
-rw-r--r--spec/unit/provider/package/chocolatey_spec.rb4
-rw-r--r--spec/unit/provider/package/rubygems_spec.rb5
-rw-r--r--spec/unit/provider/package/zypper_spec.rb8
-rw-r--r--spec/unit/provider/remote_file/network_file_spec.rb2
-rw-r--r--spec/unit/provider/route_spec.rb2
-rw-r--r--spec/unit/provider/windows_task_spec.rb28
-rw-r--r--spec/unit/provider/zypper_repository_spec.rb124
-rw-r--r--spec/unit/provider_resolver_spec.rb5
-rw-r--r--spec/unit/resource/windows_task_spec.rb10
-rw-r--r--spec/unit/resource/zypper_repository_spec.rb20
-rw-r--r--spec/unit/util/dsc/lcm_output_parser_spec.rb120
-rw-r--r--spec/unit/util/dsc/local_configuration_manager_spec.rb3
22 files changed, 517 insertions, 59 deletions
diff --git a/spec/functional/rebooter_spec.rb b/spec/functional/rebooter_spec.rb
index a28491cc0b..36961593b0 100644
--- a/spec/functional/rebooter_spec.rb
+++ b/spec/functional/rebooter_spec.rb
@@ -35,8 +35,9 @@ describe Chef::Platform::Rebooter do
resource
end
+ let(:node) { Chef::Node.new }
+
let(:run_context) do
- node = Chef::Node.new
events = Chef::EventDispatch::Dispatcher.new
Chef::RunContext.new(node, {}, events)
end
@@ -44,7 +45,8 @@ describe Chef::Platform::Rebooter do
let(:expected) do
{
:windows => "#{ENV['SYSTEMROOT']}/System32/shutdown.exe /r /t 300 /c \"rebooter spec test\"",
- :linux => 'shutdown -r +5 "rebooter spec test"',
+ :linux => 'shutdown -r +5 "rebooter spec test" &',
+ :solaris => 'shutdown -i6 -g5 -y "rebooter spec test" &',
}
end
@@ -69,8 +71,9 @@ describe Chef::Platform::Rebooter do
end
shared_context "test a reboot method" do
- def test_rebooter_method(method_sym, is_windows, expected_reboot_str)
+ def test_rebooter_method(method_sym, is_windows, is_solaris, expected_reboot_str)
allow(ChefConfig).to receive(:windows?).and_return(is_windows)
+ node.automatic["os"] = node.automatic["platform"] = node.automatic["platform_family"] = "solaris2" if is_solaris
expect(rebooter).to receive(:shell_out!).once.with(expected_reboot_str)
expect(rebooter).to receive(:raise).with(Chef::Exceptions::Reboot)
expect(rebooter).to receive(method_sym).once.and_call_original
@@ -81,24 +84,32 @@ describe Chef::Platform::Rebooter do
describe "when using #reboot_if_needed!" do
include_context "test a reboot method"
- it "should produce the correct string on Windows", :windows_only do
- test_rebooter_method(:reboot_if_needed!, true, expected[:windows])
+ it "should produce the correct string on Windows" do
+ test_rebooter_method(:reboot_if_needed!, true, false, expected[:windows])
+ end
+
+ it "should produce a SysV-like shutdown on solaris" do
+ test_rebooter_method(:reboot_if_needed!, false, true, expected[:solaris])
end
- it "should produce the correct (Linux-specific) string on non-Windows" do
- test_rebooter_method(:reboot_if_needed!, false, expected[:linux])
+ it "should produce a BSD-like shutdown by default" do
+ test_rebooter_method(:reboot_if_needed!, false, false, expected[:linux])
end
end
describe "when using #reboot!" do
include_context "test a reboot method"
- it "should produce the correct string on Windows", :windows_only do
- test_rebooter_method(:reboot!, true, expected[:windows])
+ it "should produce the correct string on Windows" do
+ test_rebooter_method(:reboot!, true, false, expected[:windows])
+ end
+
+ it "should produce a SysV-like shutdown on solaris" do
+ test_rebooter_method(:reboot!, false, true, expected[:solaris])
end
- it "should produce the correct (Linux-specific) string on non-Windows" do
- test_rebooter_method(:reboot!, false, expected[:linux])
+ it "should produce a BSD-like shutdown by default" do
+ test_rebooter_method(:reboot!, false, false, expected[:linux])
end
end
end
diff --git a/spec/functional/resource/user/useradd_spec.rb b/spec/functional/resource/user/useradd_spec.rb
index e783356c9f..175809b5c0 100644
--- a/spec/functional/resource/user/useradd_spec.rb
+++ b/spec/functional/resource/user/useradd_spec.rb
@@ -646,10 +646,10 @@ describe Chef::Provider::User::Useradd, metadata do
expect(@error.message).to include("Cannot unlock the password")
end
elsif %w{rhel}.include?(OHAI_SYSTEM["platform_family"]) &&
- OHAI_SYSTEM["platform_version"].to_f == 6.8
- # usermod -U returns following message for rhel68 on s390x platforms
- # usermod: unlocking the user's password would result in a passwordless account.
- #You should set a password with usermod -p to unlock this user's password.
+ (Chef::VersionConstraint.new("~> 6.8").include?(OHAI_SYSTEM["platform_version"].to_f) || Chef::VersionConstraint.new("~> 7.3").include?(OHAI_SYSTEM["platform_version"].to_f))
+ # RHEL 6.8 and 7.3 ship with a fixed `usermod` command
+ # Reference: https://access.redhat.com/errata/RHBA-2016:0864
+ # Reference: https://access.redhat.com/errata/RHBA-2016:2322
it "errors out trying to unlock the user" do
expect(@error).to be_a(Mixlib::ShellOut::ShellCommandFailed)
expect(@error.message).to include("You should set a password")
diff --git a/spec/functional/resource/windows_task_spec.rb b/spec/functional/resource/windows_task_spec.rb
index c2496c702f..6c4b4c4fdc 100644
--- a/spec/functional/resource/windows_task_spec.rb
+++ b/spec/functional/resource/windows_task_spec.rb
@@ -163,6 +163,31 @@ describe Chef::Resource::WindowsTask, :windows_only do
end
end
+ context "frequency :none" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :none
+ new_resource.random_delay ""
+ new_resource
+ end
+
+ it "creates the scheduled task to run on demand only" do
+ subject.run_action(:create)
+ task_details = windows_task_provider.send(:load_task_hash, task_name)
+
+ expect(task_details[:TaskName]).to eq("\\chef-client")
+ expect(task_details[:TaskToRun]).to eq("chef-client")
+ expect(task_details[:ScheduleType]).to eq("On demand only")
+ expect(task_details[:StartTime]).to eq("N/A")
+ expect(task_details[:StartDate]).to eq("N/A")
+ expect(task_details[:NextRunTime]).to eq("N/A")
+ expect(task_details[:none]).to eq(true)
+ expect(task_details[:run_level]).to eq("HighestAvailable")
+ end
+ end
+
context "frequency :weekly" do
subject do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
diff --git a/spec/functional/win32/security_spec.rb b/spec/functional/win32/security_spec.rb
index 40ae99bfa4..f3faf24c52 100644
--- a/spec/functional/win32/security_spec.rb
+++ b/spec/functional/win32/security_spec.rb
@@ -17,6 +17,8 @@
#
require "spec_helper"
+require "mixlib/shellout"
+require "chef/mixin/user_context"
if Chef::Platform.windows?
require "chef/win32/security"
end
@@ -26,13 +28,37 @@ describe "Chef::Win32::Security", :windows_only do
expect(Chef::ReservedNames::Win32::Security.has_admin_privileges?).to eq(true)
end
- # We've done some investigation adding a negative test and it turned
- # out to be a lot of work since mixlib-shellout doesn't have user
- # support for windows.
- #
- # TODO - Add negative tests once mixlib-shellout has user support
- it "has_admin_privileges? returns false when running as non-admin" do
- skip "requires user support in mixlib-shellout"
+ describe "running as non admin user" do
+ include Chef::Mixin::UserContext
+ let(:user) { "security_user" }
+ let(:password) { "Security@123" }
+
+ let(:domain) do
+ whoami = Mixlib::ShellOut.new("whoami")
+ whoami.run_command
+ whoami.error!
+ whoami.stdout.split("\\")[0]
+ end
+ before do
+ allow_any_instance_of(Chef::Mixin::UserContext).to receive(:node).and_return({ "platform_family" => "windows" })
+ allow(Chef::Platform).to receive(:windows_server_2003?).and_return(false)
+ allow(Chef::ReservedNames::Win32::Security).to receive(:OpenProcessToken).and_return(true)
+ add_user = Mixlib::ShellOut.new("net user #{user} #{password} /ADD")
+ add_user.run_command
+ add_user.error!
+ end
+
+ after do
+ delete_user = Mixlib::ShellOut.new("net user #{user} /delete")
+ delete_user.run_command
+ delete_user.error!
+ end
+ it "has_admin_privileges? returns false" do
+ has_admin_privileges = with_user_context(user, password, domain) do
+ Chef::ReservedNames::Win32::Security.has_admin_privileges?
+ end
+ expect(has_admin_privileges).to eq(false)
+ end
end
describe "get_file_security" do
diff --git a/spec/support/shared/functional/execute_resource.rb b/spec/support/shared/functional/execute_resource.rb
index 4f7cea1cd1..1a14bb38c3 100644
--- a/spec/support/shared/functional/execute_resource.rb
+++ b/spec/support/shared/functional/execute_resource.rb
@@ -63,7 +63,7 @@ shared_context "a command that can be executed as an alternate user" do
after do
File.delete(script_output_path) if File.exists?(script_output_path)
- Dir.rmdir(script_output_dir) if Dir.exists?(script_output_dir)
+ Dir.rmdir(script_output_dir) if Dir.exist?(script_output_dir)
end
end
diff --git a/spec/unit/chef_fs/data_handler/data_bag_item_data_handler.rb b/spec/unit/chef_fs/data_handler/data_bag_item_data_handler.rb
new file mode 100644
index 0000000000..fea7a2d54d
--- /dev/null
+++ b/spec/unit/chef_fs/data_handler/data_bag_item_data_handler.rb
@@ -0,0 +1,79 @@
+#
+# Author:: Sandra Tiffin (<sandi.tiffin@gmail.com>)
+# Copyright:: Copyright 2014-2016, Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+require "lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb"
+
+class TestDataBag < Mash
+ attr_accessor :name
+
+ def initialize(bag_name)
+ @name = bag_name
+ end
+end
+
+class TestDataBagItem < Mash
+ attr_accessor :name, :parent
+
+ def path_for_printing
+ "/some/path"
+ end
+
+ def initialize(bag_name, item_name)
+ @name = "#{item_name}.json"
+ @parent = TestDataBag.new(bag_name)
+ end
+end
+
+describe Chef::ChefFS::DataHandler::DataBagItemDataHandler do
+ let(:handler) { described_class.new }
+
+ describe "#verify_integrity" do
+ context "json id does not match data bag item name" do
+ let(:entry) { TestDataBagItem.new("luggage", "bag") }
+ let(:object) do
+ { "raw_data" => { "id" => "duffel" } }
+ end
+ it "rejects the data bag item name" do
+ expect { |b| handler.verify_integrity(object, entry, &b) }.to yield_with_args
+ end
+ end
+
+ context "using a reserved word for the data bag name" do
+ %w{node role environment client}.each do |reserved_word|
+ let(:entry) { TestDataBagItem.new(reserved_word, "bag") }
+ let(:object) do
+ { "raw_data" => { "id" => "bag" } }
+ end
+ it "rejects the data bag name '#{reserved_word}'" do
+ expect { |b| handler.verify_integrity(object, entry, &b) }.to yield_with_args
+ end
+ end
+ end
+
+ context "valid data" do
+ let(:entry) { TestDataBagItem.new("luggage", "bag") }
+ let(:object) do
+ { "raw_data" => { "id" => "bag" } }
+ end
+ it "validates the data bag item" do
+ expect(handler.verify_integrity(object, entry)).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/unit/client_spec.rb b/spec/unit/client_spec.rb
index d348c24385..2aff7b2a71 100644
--- a/spec/unit/client_spec.rb
+++ b/spec/unit/client_spec.rb
@@ -38,12 +38,23 @@ describe Chef::Client do
end
it "runs ohai with only the minimum required plugins" do
- expected_filter = %w{fqdn machinename hostname platform platform_version os os_version}
+ expected_filter = %w{fqdn machinename hostname platform platform_version ohai_time os os_version}
expect(ohai_system).to receive(:all_plugins).with(expected_filter)
client.run_ohai
end
end
+ context "when Ohai tells us to fail" do
+ it "fails" do
+ ohai_system = Ohai::System.new
+ module Ohai::Exceptions
+ class CriticalPluginFailure < Error; end
+ end
+ expect(ohai_system).to receive(:all_plugins) { raise Ohai::Exceptions::CriticalPluginFailure }
+ expect { client.run_ohai }.to raise_error(SystemExit)
+ end
+ end
+
describe "authentication protocol selection" do
context "when FIPS is disabled" do
before do
diff --git a/spec/unit/knife/data_bag_create_spec.rb b/spec/unit/knife/data_bag_create_spec.rb
index b7d185a58c..1f99fe74fe 100644
--- a/spec/unit/knife/data_bag_create_spec.rb
+++ b/spec/unit/knife/data_bag_create_spec.rb
@@ -72,6 +72,14 @@ describe Chef::Knife::DataBagCreate do
expect { knife.run }.to exit_with_code(1)
end
+ it "won't create a data bag with a reserved name for search" do
+ %w{node role client environment}.each do |name|
+ knife.name_args = [name]
+ expect(Chef::DataBag).to receive(:validate_name!).with(knife.name_args[0]).and_raise(Chef::Exceptions::InvalidDataBagName)
+ expect { knife.run }.to exit_with_code(1)
+ end
+ end
+
context "when given one argument" do
before do
knife.name_args = [bag_name]
diff --git a/spec/unit/mixin/user_context_spec.rb b/spec/unit/mixin/user_context_spec.rb
index f2119b6dbc..3dadf6a2c3 100644
--- a/spec/unit/mixin/user_context_spec.rb
+++ b/spec/unit/mixin/user_context_spec.rb
@@ -41,7 +41,6 @@ describe "a class that mixes in user_context" do
before do
allow(::Chef::Platform).to receive(:windows?).and_return(true)
allow(::Chef::Util::Windows::LogonSession).to receive(:new).and_return(logon_session)
- allow(instance_with_user_context).to receive(:node).and_return({ "platform_family" => "windows" })
end
let(:logon_session) { instance_double("::Chef::Util::Windows::LogonSession", :set_user_context => nil, :open => nil, :close => nil) }
@@ -99,7 +98,7 @@ describe "a class that mixes in user_context" do
context "when not running on Windows" do
before do
- allow(instance_with_user_context).to receive(:node).and_return({ "platform_family" => "ubuntu" })
+ allow(::Chef::Platform).to receive(:windows?).and_return(false)
end
it "raises a ::Chef::Exceptions::UnsupportedPlatform exception" do
diff --git a/spec/unit/provider/package/apt_spec.rb b/spec/unit/provider/package/apt_spec.rb
index 46ae7fcadc..ff14edcffd 100644
--- a/spec/unit/provider/package/apt_spec.rb
+++ b/spec/unit/provider/package/apt_spec.rb
@@ -475,6 +475,40 @@ mpg123 1.12.1-0ubuntu1
end
end
+ describe "#action_install" do
+ it "should run dpkg to compare versions if an existing version is installed" do
+ allow(@provider).to receive(:get_current_versions).and_return("1.4.0")
+ allow(@new_resource).to receive(:allow_downgrade).and_return(false)
+ expect(@provider).to receive(:shell_out_compact_timeout).with(
+ "dpkg", "--compare-versions", "1.4.0", "gt", "0.8.12-7"
+ ).and_return(double(error?: false))
+ @provider.run_action(:upgrade)
+ end
+
+ it "should install the package if the installed version is older" do
+ allow(@provider).to receive(:get_current_versions).and_return("0.4.0")
+ allow(@new_resource).to receive(:allow_downgrade).and_return(false)
+ expect(@provider).to receive(:version_compare).and_return(-1)
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-get", "-q", "-y", "install", "irssi=0.8.12-7",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @provider.run_action(:upgrade)
+ end
+
+ it "should not compare versions if an existing version is not installed" do
+ allow(@provider).to receive(:get_current_versions).and_return(nil)
+ allow(@new_resource).to receive(:allow_downgrade).and_return(false)
+ expect(@provider).not_to receive(:version_compare)
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-get", "-q", "-y", "install", "irssi=0.8.12-7",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @provider.run_action(:upgrade)
+ end
+ end
end
end
end
diff --git a/spec/unit/provider/package/chocolatey_spec.rb b/spec/unit/provider/package/chocolatey_spec.rb
index 68b121960c..afc068041d 100644
--- a/spec/unit/provider/package/chocolatey_spec.rb
+++ b/spec/unit/provider/package/chocolatey_spec.rb
@@ -59,7 +59,9 @@ Git|2.6.2
munin-node|1.6.1.20130823
EOF
remote_list_obj = double(stdout: remote_list_stdout)
- allow(provider).to receive(:shell_out!).with("#{choco_exe} list -r #{package_names.join ' '}#{args}", { :returns => [0], timeout: timeout }).and_return(remote_list_obj)
+ package_names.each do |pkg|
+ allow(provider).to receive(:shell_out!).with("#{choco_exe} list -r #{pkg}#{args}", { :returns => [0], timeout: timeout }).and_return(remote_list_obj)
+ end
end
describe "#initialize" do
diff --git a/spec/unit/provider/package/rubygems_spec.rb b/spec/unit/provider/package/rubygems_spec.rb
index 856f8d460c..ac2b511ca9 100644
--- a/spec/unit/provider/package/rubygems_spec.rb
+++ b/spec/unit/provider/package/rubygems_spec.rb
@@ -383,6 +383,11 @@ describe Chef::Provider::Package::Rubygems do
provider.load_current_resource
expect(provider.target_version_already_installed?(provider.current_resource.version, new_resource.version)).to be_falsey
end
+
+ it "version_equals? should return false so that we can search for candidates" do
+ provider.load_current_resource
+ expect(provider.version_equals?(provider.current_resource.version, new_resource.version)).to be_falsey
+ end
end
describe "when new_resource version is an rspec version" do
diff --git a/spec/unit/provider/package/zypper_spec.rb b/spec/unit/provider/package/zypper_spec.rb
index b20a548c73..598fedc9fa 100644
--- a/spec/unit/provider/package/zypper_spec.rb
+++ b/spec/unit/provider/package/zypper_spec.rb
@@ -140,6 +140,14 @@ describe Chef::Provider::Package::Zypper do
provider.install_package(["emacs"], ["1.0"])
end
+ it "setting the property should allow downgrade" do
+ new_resource.allow_downgrade true
+ shell_out_expectation!(
+ "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
+ )
+ provider.install_package(["emacs"], ["1.0"])
+ end
+
it "should add user provided options to the command" do
new_resource.options "--user-provided"
shell_out_expectation!(
diff --git a/spec/unit/provider/remote_file/network_file_spec.rb b/spec/unit/provider/remote_file/network_file_spec.rb
index 621d2769a4..ecb326fc64 100644
--- a/spec/unit/provider/remote_file/network_file_spec.rb
+++ b/spec/unit/provider/remote_file/network_file_spec.rb
@@ -33,7 +33,7 @@ describe Chef::Provider::RemoteFile::NetworkFile do
let(:source_file) { double("::File", :read => nil) }
before do
- allow(fetcher).to receive(:node).and_return({ "platform_family" => "windows" })
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
end
it "stages the local file to a temporary file" do
diff --git a/spec/unit/provider/route_spec.rb b/spec/unit/provider/route_spec.rb
index 5e655bda0c..ea6ddffb81 100644
--- a/spec/unit/provider/route_spec.rb
+++ b/spec/unit/provider/route_spec.rb
@@ -236,9 +236,11 @@ describe Chef::Provider::Route do
@node.automatic_attrs[:platform] = platform
route_file = StringIO.new
+ allow(File).to receive(:exist?).with("/etc/sysconfig/network").and_return(false)
expect(File).to receive(:new).with("/etc/sysconfig/network", "w").and_return(route_file)
@run_context.resource_collection << @default_resource
@default_provider.generate_config
+ expect(route_file.string).to match(/GATEWAY=10\.0\.0\.9/)
end
end
diff --git a/spec/unit/provider/windows_task_spec.rb b/spec/unit/provider/windows_task_spec.rb
index b18d842bfa..55a1e77e4e 100644
--- a/spec/unit/provider/windows_task_spec.rb
+++ b/spec/unit/provider/windows_task_spec.rb
@@ -143,6 +143,17 @@ describe Chef::Provider::WindowsTask do
provider.run_action(:create)
expect(new_resource).to be_updated_by_last_action
end
+
+ it "updates the task XML if frequency is set as `:none`" do
+ new_resource.frequency :none
+ new_resource.random_delay ""
+ allow(provider).to receive(:task_need_update?).and_return(true)
+ allow(provider).to receive(:basic_validation).and_return(true)
+ allow(provider).to receive(:run_schtasks).and_return("CREATE", { "F" => "", "SC" => :once, "ST" => "00:00", "SD" => "12/12/2012", "TR" => nil, "RU" => "SYSTEM" })
+ expect(provider).to receive(:update_task_xml)
+ provider.run_action(:create)
+ expect(new_resource).to be_updated_by_last_action
+ end
end
end
@@ -507,6 +518,18 @@ describe Chef::Provider::WindowsTask do
expect(provider).to receive(:run_schtasks).twice
output = provider.send(:update_task_xml, ["random_delay"])
end
+
+ it "updates the task XML if frequency is set as `:none`" do
+ new_resource.frequency :none
+ new_resource.random_delay ""
+ shell_out_obj = double("xml", :exitstatus => 0, :stdout => task_xml)
+ allow(provider).to receive(:powershell_out).and_return(shell_out_obj)
+ expect(::File).to receive(:delete)
+ expect(::File).to receive(:join)
+ expect(::File).to receive(:open)
+ expect(provider).to receive(:run_schtasks).twice
+ output = provider.send(:update_task_xml, ["random_delay"])
+ end
end
describe "#load_task_hash" do
@@ -541,5 +564,10 @@ describe Chef::Provider::WindowsTask do
new_resource.frequency :once
expect(provider.send(:frequency_modifier_allowed)).to be(false)
end
+
+ it "returns false for frequency :none" do
+ new_resource.frequency :none
+ expect(provider.send(:frequency_modifier_allowed)).to be(false)
+ end
end
end
diff --git a/spec/unit/provider/zypper_repository_spec.rb b/spec/unit/provider/zypper_repository_spec.rb
new file mode 100644
index 0000000000..a366a33e86
--- /dev/null
+++ b/spec/unit/provider/zypper_repository_spec.rb
@@ -0,0 +1,124 @@
+#
+# Author:: Tim Smith (<tsmith@chef.io>)
+# Copyright:: 2017, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+# Output of the command:
+# => rpm -qa gpg-pubkey*
+RPM_KEYS = <<-EOF
+gpg-pubkey-307e3d54-4be01a65
+gpg-pubkey-3dbdc284-53674dd4
+EOF
+
+# Output of the command:
+# => gpg --with-fingerprint [FILE]
+GPG_FINGER = <<-EOF
+pub 2048R/3DBDC284 2011-08-19 [expires: 2024-06-14]
+ Key fingerprint = 573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62
+uid nginx signing key <signing-key@nginx.com>
+EOF
+
+describe Chef::Provider::ZypperRepository do
+ let(:new_resource) { Chef::Resource::ZypperRepository.new("Nginx Repository") }
+ let(:provider) do
+ node = Chef::Node.new
+ events = Chef::EventDispatch::Dispatcher.new
+ run_context = Chef::RunContext.new(node, {}, events)
+ Chef::Provider::ZypperRepository.new(new_resource, run_context)
+ end
+
+ let(:rpm_key_finger) do
+ double("shell_out_with_systems_locale", stdout: RPM_KEYS, exitstatus: 0, error?: false)
+ end
+
+ let(:gpg_finger) do
+ double("shell_out_with_systems_locale", stdout: GPG_FINGER, exitstatus: 0, error?: false)
+ end
+
+ it "responds to load_current_resource" do
+ expect(provider).to respond_to(:load_current_resource)
+ end
+
+ describe "#action_create" do
+ it "skips key import if gpgautoimportkeys is false" do
+ new_resource.gpgautoimportkeys(false)
+ expect(provider).to receive(:declare_resource)
+ expect(Chef::Log).to receive(:debug)
+ provider.run_action(:create)
+ end
+ end
+
+ describe "#escaped_repo_name" do
+ it "returns an escaped repo name" do
+ expect(provider.escaped_repo_name).to eq('Nginx\\ Repository')
+ end
+ end
+
+ describe "#cookbook_name" do
+ it "returns 'test' when the cookbook property is set" do
+ new_resource.cookbook("test")
+ expect(provider.cookbook_name).to eq("test")
+ end
+ end
+
+ describe "#key_type" do
+ it "returns :remote_file with an http URL" do
+ expect(provider.key_type("https://www.chef.io/key")).to eq(:remote_file)
+ end
+
+ it "returns :cookbook_file with a chef managed file" do
+ expect(provider).to receive(:has_cookbook_file?).and_return(true)
+ expect(provider.key_type("/foo/nginx.key")).to eq(:cookbook_file)
+ end
+
+ it "throws exception if an unknown file specified" do
+ expect(provider).to receive(:has_cookbook_file?).and_return(false)
+ expect { provider.key_type("/foo/nginx.key") }.to raise_error(Chef::Exceptions::FileNotFound)
+ end
+ end
+
+ describe "#key_installed?" do
+ before do
+ expect(provider).to receive(:shell_out).with("rpm -qa gpg-pubkey*").and_return(rpm_key_finger)
+ end
+
+ it "returns true if the key is installed" do
+ expect(provider).to receive(:key_fingerprint).and_return("3dbdc284")
+ expect(provider.key_installed?("/foo/nginx.key")).to be_truthy
+ end
+
+ it "returns false if the key is not installed" do
+ expect(provider).to receive(:key_fingerprint).and_return("BOGUS")
+ expect(provider.key_installed?("/foo/nginx.key")).to be_falsey
+ end
+ end
+
+ describe "#key_fingerprint" do
+ it "returns the key's fingerprint" do
+ expect(provider).to receive(:shell_out!).with("gpg --with-fingerprint /foo/nginx.key").and_return(gpg_finger)
+ expect(provider.key_fingerprint("/foo/nginx.key")).to eq("3dbdc284")
+ end
+ end
+
+ describe "#install_gpg_key" do
+ it "skips installing the key if a nil value for key is passed" do
+ expect(Chef::Log).to receive(:debug)
+ provider.install_gpg_key(nil)
+ end
+ end
+end
diff --git a/spec/unit/provider_resolver_spec.rb b/spec/unit/provider_resolver_spec.rb
index 1902fb5375..d1aaa6a8ea 100644
--- a/spec/unit/provider_resolver_spec.rb
+++ b/spec/unit/provider_resolver_spec.rb
@@ -708,18 +708,21 @@ describe Chef::ProviderResolver do
"rhel" => {
# service: [ Chef::Resource::SystemdService, Chef::Provider::Service::Systemd ],
- package: [ Chef::Resource::YumPackage, Chef::Provider::Package::Yum ],
+ package: [ Chef::Resource::DnfPackage, Chef::Provider::Package::Dnf ],
ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig::Redhat ],
%w{amazon xcp xenserver ibm_powerkvm cloudlinux parallels} => {
"3.1.4" => {
+ package: [ Chef::Resource::YumPackage, Chef::Provider::Package::Yum ],
# service: [ Chef::Resource::RedhatService, Chef::Provider::Service::Redhat ],
},
},
%w{redhat centos scientific oracle} => {
"7.0" => {
+ package: [ Chef::Resource::YumPackage, Chef::Provider::Package::Yum ],
},
"6.0" => {
+ package: [ Chef::Resource::YumPackage, Chef::Provider::Package::Yum ],
# service: [ Chef::Resource::RedhatService, Chef::Provider::Service::Redhat ],
},
},
diff --git a/spec/unit/resource/windows_task_spec.rb b/spec/unit/resource/windows_task_spec.rb
index 2b3ee16024..cf4651cf52 100644
--- a/spec/unit/resource/windows_task_spec.rb
+++ b/spec/unit/resource/windows_task_spec.rb
@@ -102,8 +102,14 @@ describe Chef::Resource::WindowsTask do
end
context "#validate_start_time" do
- it "raises error if start_time is nil" do
- expect { resource.send(:validate_start_time, nil) }.to raise_error(Chef::Exceptions::ArgumentError, "`start_time` needs to be provided with `frequency :once`")
+ it "raises error if start_time is nil when frequency `:once`" do
+ resource.frequency :once
+ expect { resource.send(:validate_start_time, nil, :once) }.to raise_error(Chef::Exceptions::ArgumentError, "`start_time` needs to be provided with `frequency :once`")
+ end
+
+ it "raises error if start_time is given when frequency `:none`" do
+ resource.frequency :none
+ expect { resource.send(:validate_start_time, "12.00", :none) }.to raise_error(Chef::Exceptions::ArgumentError, "`start_time` property is not supported with `frequency :none`")
end
end
diff --git a/spec/unit/resource/zypper_repository_spec.rb b/spec/unit/resource/zypper_repository_spec.rb
index 16951d071c..de08b183a5 100644
--- a/spec/unit/resource/zypper_repository_spec.rb
+++ b/spec/unit/resource/zypper_repository_spec.rb
@@ -46,20 +46,22 @@ describe Chef::Resource::ZypperRepository do
expect { resource.action :delete }.to raise_error(ArgumentError)
end
- it "should resolve to a Noop class when zypper is not found" do
- expect(Chef::Provider::ZypperRepository).to receive(:which).with("zypper").and_return(false)
+ it "resolves to a Noop class when on non-linux OS" do
+ node.automatic[:os] = "windows"
+ node.automatic[:platform_family] = "windows"
expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop)
end
- it "should resolve to a ZypperRepository class when zypper is found" do
- expect(Chef::Provider::ZypperRepository).to receive(:which).with("zypper").and_return(true)
- expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::ZypperRepository)
+ it "resolves to a Noop class when on non-suse linux" do
+ node.automatic[:os] = "linux"
+ node.automatic[:platform_family] = "debian"
+ expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop)
end
- end
- context "on windows", :windows_only do
- it "should resolve to a NoOp provider" do
- expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop)
+ it "resolves to a ZypperRepository class when on a suse platform_family" do
+ node.automatic[:os] = "linux"
+ node.automatic[:platform_family] = "suse"
+ expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::ZypperRepository)
end
end
end
diff --git a/spec/unit/util/dsc/lcm_output_parser_spec.rb b/spec/unit/util/dsc/lcm_output_parser_spec.rb
index d59497de6f..65eaafe19c 100644
--- a/spec/unit/util/dsc/lcm_output_parser_spec.rb
+++ b/spec/unit/util/dsc/lcm_output_parser_spec.rb
@@ -19,20 +19,33 @@
require "chef/util/dsc/lcm_output_parser"
describe Chef::Util::DSC::LocalConfigurationManager::Parser do
- context "empty input parameter" do
+ context "empty input parameter for WhatIfParser" do
it "raises an exception when there are no valid lines" do
str = <<-EOF
EOF
- expect { Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str) }.to raise_error(Chef::Exceptions::LCMParser)
+ expect { Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false) }.to raise_error(Chef::Exceptions::LCMParser)
end
it "raises an exception for a nil input" do
- expect { Chef::Util::DSC::LocalConfigurationManager::Parser.parse(nil) }.to raise_error(Chef::Exceptions::LCMParser)
+ expect { Chef::Util::DSC::LocalConfigurationManager::Parser.parse(nil, false) }.to raise_error(Chef::Exceptions::LCMParser)
end
end
- context "correctly formatted output from lcm" do
+ context "empty input parameter for TestDSCParser" do
+ it "raises an exception when there are no valid lines" do
+ str = <<-EOF
+
+ EOF
+ expect { Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, true) }.to raise_error(Chef::Exceptions::LCMParser)
+ end
+
+ it "raises an exception for a nil input" do
+ expect { Chef::Util::DSC::LocalConfigurationManager::Parser.parse(nil, true) }.to raise_error(Chef::Exceptions::LCMParser)
+ end
+ end
+
+ context "correctly formatted output from lcm for WhatIfParser" do
it "returns a single resource when only 1 logged with the correct name" do
str = <<EOF
logtype: [machinename]: LCM: [ Start Set ]
@@ -40,7 +53,7 @@ logtype: [machinename]: LCM: [ Start Resource ] [name]
logtype: [machinename]: LCM: [ End Resource ] [name]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources.length).to eq(1)
expect(resources[0].name).to eq("[name]")
end
@@ -54,7 +67,7 @@ logtype: [machinename]: LCM: [ End Set ] [name]
logtype: [machinename]: LCM: [ End Resource ] [name]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources[0].changes_state?).to be_truthy
end
@@ -68,11 +81,11 @@ logtype: [machinename]: LCM: [ End Set ] [name]
logtype: [machinename]: LCM: [ End Resource ] [name]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources[0].change_log).to match_array(["[name]", "[message]", "[name]"])
end
- it "should return false for changes_state?" do
+ it "returns false for changes_state?" do
str = <<EOF
logtype: [machinename]: LCM: [ Start Set ]
logtype: [machinename]: LCM: [ Start Resource ] [name]
@@ -80,11 +93,11 @@ logtype: [machinename]: LCM: [ Skip Set ] [name]
logtype: [machinename]: LCM: [ End Resource ] [name]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources[0].changes_state?).to be_falsey
end
- it "should return an empty array for change_log if changes_state? is false" do
+ it "returns an empty array for change_log if changes_state? is false" do
str = <<EOF
logtype: [machinename]: LCM: [ Start Set ]
logtype: [machinename]: LCM: [ Start Resource ] [name]
@@ -92,13 +105,64 @@ logtype: [machinename]: LCM: [ Skip Set ] [name]
logtype: [machinename]: LCM: [ End Resource ] [name]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources[0].change_log).to be_empty
end
end
- context "Incorrectly formatted output from LCM" do
- it "should allow missing a [End Resource] when its the last one and still find all the resource" do
+ context "correctly formatted output from lcm for TestDSCParser" do
+ it "returns a single resource when only 1 logged with the correct name" do
+ str = <<EOF
+InDesiredState : False
+ResourcesInDesiredState :
+ResourcesNotInDesiredState: [name]
+ReturnValue : 0
+PSComputerName : .
+EOF
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, true)
+ expect(resources.length).to eq(1)
+ expect(resources[0].name).to eq("[name]")
+ end
+
+ it "identifies when a resource changes the state of the system" do
+ str = <<EOF
+InDesiredState : False
+ResourcesInDesiredState :
+ResourcesNotInDesiredState: [name]
+ReturnValue : 0
+PSComputerName : .
+EOF
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, true)
+ expect(resources[0].changes_state?).to be_truthy
+ end
+
+ it "returns false for changes_state?" do
+ str = <<EOF
+InDesiredState : True
+ResourcesInDesiredState : [name]
+ResourcesNotInDesiredState:
+ReturnValue : 0
+PSComputerName : .
+EOF
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, true)
+ expect(resources[0].changes_state?).to be_falsey
+ end
+
+ it "returns an empty array for change_log if changes_state? is false" do
+ str = <<EOF
+InDesiredState : True
+ResourcesInDesiredState : [name]
+ResourcesNotInDesiredState:
+ReturnValue : 0
+PSComputerName : .
+EOF
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, true)
+ expect(resources[0].change_log).to be_empty
+ end
+ end
+
+ context "Incorrectly formatted output from LCM for WhatIfParser" do
+ it "allows missing [End Resource] when its the last one and still find all the resource" do
str = <<-EOF
logtype: [machinename]: LCM: [ Start Set ]
logtype: [machinename]: LCM: [ Start Resource ] [name]
@@ -114,12 +178,12 @@ logtype: [machinename]: LCM: [ End Set ]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources[0].changes_state?).to be_falsey
expect(resources[1].changes_state?).to be_truthy
end
- it "should allow missing a [End Resource] when its the first one and still find all the resource" do
+ it "allow missing [End Resource] when its the first one and still find all the resource" do
str = <<-EOF
logtype: [machinename]: LCM: [ Start Set ]
logtype: [machinename]: LCM: [ Start Resource ] [name]
@@ -135,12 +199,12 @@ logtype: [machinename]: LCM: [ End Resource ]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources[0].changes_state?).to be_falsey
expect(resources[1].changes_state?).to be_truthy
end
- it "should allow missing set and end resource and assume an unconverged resource in this case" do
+ it "allows missing set and end resource and assume an unconverged resource in this case" do
str = <<-EOF
logtype: [machinename]: LCM: [ Start Set ]
logtype: [machinename]: LCM: [ Start Resource ] [name]
@@ -154,11 +218,31 @@ logtype: [machinename]: LCM: [ End Set ]
logtype: [machinename]: LCM: [ End Resource ]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources[0].changes_state?).to be_truthy
expect(resources[0].name).to eql("[name]")
expect(resources[1].changes_state?).to be_truthy
expect(resources[1].name).to eql("[name2]")
end
end
+
+ context "Incorrectly formatted output from LCM for TestDSCParser" do
+ it "allows missing [End Resource] when its the last one and still find all the resource" do
+ str = <<EOF
+InDesiredState : True
+ResourcesInDesiredState :
+ResourcesNotInDesiredState: [name]
+ReturnValue : 0
+PSComputerName : .
+InDesiredState : True
+ResourcesInDesiredState :
+ResourcesNotInDesiredState: [name2]
+ReturnValue : 0
+PSComputerName : .
+EOF
+
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, true)
+ expect(resources[0].changes_state?).to be_falsey
+ end
+ end
end
diff --git a/spec/unit/util/dsc/local_configuration_manager_spec.rb b/spec/unit/util/dsc/local_configuration_manager_spec.rb
index c87b446286..4c33fc8616 100644
--- a/spec/unit/util/dsc/local_configuration_manager_spec.rb
+++ b/spec/unit/util/dsc/local_configuration_manager_spec.rb
@@ -57,6 +57,7 @@ EOH
context "when interacting with the LCM using a PowerShell cmdlet" do
before(:each) do
allow(lcm).to receive(:run_configuration_cmdlet).and_return(lcm_status)
+ allow(lcm).to receive(:ps_version_gte_5?).and_return(false)
end
context "that returns successfully" do
let(:lcm_standard_output) { normal_lcm_output }
@@ -103,7 +104,7 @@ EOH
let(:common_command_prefix) { "$ProgressPreference = 'SilentlyContinue';" }
let(:ps4_base_command) { "#{common_command_prefix} Start-DscConfiguration -path tmp -wait -erroraction 'stop' -force" }
let(:lcm_command_ps4) { ps4_base_command + " -whatif; if (! $?) { exit 1 }" }
- let(:lcm_command_ps5) { "#{common_command_prefix} Test-DscConfiguration -path tmp" }
+ let(:lcm_command_ps5) { "#{common_command_prefix} Test-DscConfiguration -path tmp | format-list" }
let(:lcm_standard_output) { normal_lcm_output }
let(:lcm_standard_error) { nil }
let(:lcm_cmdlet_success) { true }