diff options
Diffstat (limited to 'spec')
33 files changed, 1181 insertions, 320 deletions
diff --git a/spec/data/templates/chef-seattle20160930-4388-1crv7ef.txt b/spec/data/templates/chef-seattle20160930-4388-1crv7ef.txt new file mode 100644 index 0000000000..f476ccd704 --- /dev/null +++ b/spec/data/templates/chef-seattle20160930-4388-1crv7ef.txt @@ -0,0 +1 @@ +Do do do do, do do do do, do do do do, do do do do
\ No newline at end of file diff --git a/spec/data/templates/chef-seattle20160930-4388-jjfoae.txt b/spec/data/templates/chef-seattle20160930-4388-jjfoae.txt new file mode 100644 index 0000000000..f476ccd704 --- /dev/null +++ b/spec/data/templates/chef-seattle20160930-4388-jjfoae.txt @@ -0,0 +1 @@ +Do do do do, do do do do, do do do do, do do do do
\ No newline at end of file diff --git a/spec/data/templates/chef-seattle20160930-4388-umeq2c.txt b/spec/data/templates/chef-seattle20160930-4388-umeq2c.txt new file mode 100644 index 0000000000..f476ccd704 --- /dev/null +++ b/spec/data/templates/chef-seattle20160930-4388-umeq2c.txt @@ -0,0 +1 @@ +Do do do do, do do do do, do do do do, do do do do
\ No newline at end of file diff --git a/spec/functional/knife/cookbook_delete_spec.rb b/spec/functional/knife/cookbook_delete_spec.rb index 99f3309752..7438ef9841 100644 --- a/spec/functional/knife/cookbook_delete_spec.rb +++ b/spec/functional/knife/cookbook_delete_spec.rb @@ -20,86 +20,75 @@ require "spec_helper" require "tiny_server" describe Chef::Knife::CookbookDelete do - before(:each) do - @server = TinyServer::Manager.new - @server.start - end - - after(:each) do - @server.stop + let(:server) { TinyServer::Manager.new } + let(:api) { TinyServer::API.instance } + let(:knife_stdout) { StringIO.new } + let(:knife_stderr) { StringIO.new } + let(:knife) do + knife = Chef::Knife::CookbookDelete.new + allow(knife.ui).to receive(:stdout).and_return(knife_stdout) + allow(knife.ui).to receive(:stderr).and_return(knife_stderr) + knife end before(:each) do - @knife = Chef::Knife::CookbookDelete.new - @api = TinyServer::API.instance - @api.clear + server.start + api.clear Chef::Config[:node_name] = nil Chef::Config[:client_key] = nil Chef::Config[:chef_server_url] = "http://localhost:9000" end - context "when the cookbook doesn't exist" do - let(:log_output) { StringIO.new } + after(:each) do + server.stop + end + context "when the cookbook doesn't exist" do before do - @knife.name_args = %w{no-such-cookbook} - @api.get("/cookbooks/no-such-cookbook", 404, Chef::JSONCompat.to_json({ "error" => "dear Tim, no. -Sent from my iPad" })) - end - - around do |ex| - old_logger = Chef::Log.logger - old_level = Chef::Log.level - begin - Chef::Log.logger = Logger.new(log_output) - Chef::Log.level = :debug - ex.run - ensure - Chef::Log.logger = old_logger - Chef::Log.level = old_level - end + knife.name_args = %w{no-such-cookbook} + api.get("/cookbooks/no-such-cookbook", 404, Chef::JSONCompat.to_json({ "error" => "dear Tim, no. -Sent from my iPad" })) end it "logs an error and exits" do - allow(@knife.ui).to receive(:stderr).and_return(log_output) - expect { @knife.run }.to raise_error(SystemExit) - expect(log_output.string).to match(/Cannot find a cookbook named no-such-cookbook to delete/) + expect { knife.run }.to raise_error(SystemExit) + expect(knife_stderr.string).to match(/Cannot find a cookbook named no-such-cookbook to delete/) end end context "when there is only one version of a cookbook" do before do - @knife.name_args = %w{obsolete-cookbook} + knife.name_args = %w{obsolete-cookbook} @cookbook_list = { "obsolete-cookbook" => { "versions" => ["version" => "1.0.0"] } } - @api.get("/cookbooks/obsolete-cookbook", 200, Chef::JSONCompat.to_json(@cookbook_list)) + api.get("/cookbooks/obsolete-cookbook", 200, Chef::JSONCompat.to_json(@cookbook_list)) end it "asks for confirmation, then deletes the cookbook" do stdin, stdout = StringIO.new("y\n"), StringIO.new - allow(@knife.ui).to receive(:stdin).and_return(stdin) - allow(@knife.ui).to receive(:stdout).and_return(stdout) + allow(knife.ui).to receive(:stdin).and_return(stdin) + allow(knife.ui).to receive(:stdout).and_return(stdout) cb100_deleted = false - @api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } - @knife.run + knife.run expect(stdout.string).to match(/#{Regexp.escape('Do you really want to delete obsolete-cookbook version 1.0.0? (Y/N)')}/) expect(cb100_deleted).to be_truthy end it "asks for confirmation before purging" do - @knife.config[:purge] = true + knife.config[:purge] = true stdin, stdout = StringIO.new("y\ny\n"), StringIO.new - allow(@knife.ui).to receive(:stdin).and_return(stdin) - allow(@knife.ui).to receive(:stdout).and_return(stdout) + allow(knife.ui).to receive(:stdin).and_return(stdin) + allow(knife.ui).to receive(:stdout).and_return(stdout) cb100_deleted = false - @api.delete("/cookbooks/obsolete-cookbook/1.0.0?purge=true", 200) { cb100_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.0.0?purge=true", 200) { cb100_deleted = true; "[\"true\"]" } - @knife.run + knife.run expect(stdout.string).to match(/#{Regexp.escape('Are you sure you want to purge files')}/) expect(stdout.string).to match(/#{Regexp.escape('Do you really want to delete obsolete-cookbook version 1.0.0? (Y/N)')}/) @@ -111,21 +100,21 @@ describe Chef::Knife::CookbookDelete do context "when there are several versions of a cookbook" do before do - @knife.name_args = %w{obsolete-cookbook} + knife.name_args = %w{obsolete-cookbook} versions = ["1.0.0", "1.1.0", "1.2.0"] with_version = lambda { |version| { "version" => version } } @cookbook_list = { "obsolete-cookbook" => { "versions" => versions.map(&with_version) } } - @api.get("/cookbooks/obsolete-cookbook", 200, Chef::JSONCompat.to_json(@cookbook_list)) + api.get("/cookbooks/obsolete-cookbook", 200, Chef::JSONCompat.to_json(@cookbook_list)) end it "deletes all versions of a cookbook when given the '-a' flag" do - @knife.config[:all] = true - @knife.config[:yes] = true + knife.config[:all] = true + knife.config[:yes] = true cb100_deleted = cb110_deleted = cb120_deleted = nil - @api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } - @api.delete("/cookbooks/obsolete-cookbook/1.1.0", 200) { cb110_deleted = true; "[\"true\"]" } - @api.delete("/cookbooks/obsolete-cookbook/1.2.0", 200) { cb120_deleted = true; "[\"true\"]" } - @knife.run + api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.1.0", 200) { cb110_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.2.0", 200) { cb120_deleted = true; "[\"true\"]" } + knife.run expect(cb100_deleted).to be_truthy expect(cb110_deleted).to be_truthy @@ -134,28 +123,28 @@ describe Chef::Knife::CookbookDelete do it "asks which version to delete and deletes that when not given the -a flag" do cb100_deleted = cb110_deleted = cb120_deleted = nil - @api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } stdin, stdout = StringIO.new, StringIO.new - allow(@knife.ui).to receive(:stdin).and_return(stdin) - allow(@knife.ui).to receive(:stdout).and_return(stdout) + allow(knife.ui).to receive(:stdin).and_return(stdin) + allow(knife.ui).to receive(:stdout).and_return(stdout) stdin << "1\n" stdin.rewind - @knife.run + knife.run expect(cb100_deleted).to be_truthy expect(stdout.string).to match(/Which version\(s\) do you want to delete\?/) end it "deletes all versions of the cookbook when not given the -a flag and the user chooses to delete all" do cb100_deleted = cb110_deleted = cb120_deleted = nil - @api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } - @api.delete("/cookbooks/obsolete-cookbook/1.1.0", 200) { cb110_deleted = true; "[\"true\"]" } - @api.delete("/cookbooks/obsolete-cookbook/1.2.0", 200) { cb120_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.0.0", 200) { cb100_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.1.0", 200) { cb110_deleted = true; "[\"true\"]" } + api.delete("/cookbooks/obsolete-cookbook/1.2.0", 200) { cb120_deleted = true; "[\"true\"]" } stdin, stdout = StringIO.new("4\n"), StringIO.new - allow(@knife.ui).to receive(:stdin).and_return(stdin) - allow(@knife.ui).to receive(:stdout).and_return(stdout) + allow(knife.ui).to receive(:stdin).and_return(stdin) + allow(knife.ui).to receive(:stdout).and_return(stdout) - @knife.run + knife.run expect(cb100_deleted).to be_truthy expect(cb110_deleted).to be_truthy diff --git a/spec/functional/resource/group_spec.rb b/spec/functional/resource/group_spec.rb index aa5a29f92c..31f9933546 100644 --- a/spec/functional/resource/group_spec.rb +++ b/spec/functional/resource/group_spec.rb @@ -99,8 +99,12 @@ describe Chef::Resource::Group, :requires_root_or_running_windows, :not_supporte usr end - def create_user(username) - user(username).run_action(:create) if ! windows_domain_user?(username) + def create_user(username, uid = nil) + if ! windows_domain_user?(username) + user_to_create = user(username) + user_to_create.uid(uid) if uid + user_to_create.run_action(:create) + end # TODO: User should exist end @@ -169,8 +173,11 @@ describe Chef::Resource::Group, :requires_root_or_running_windows, :not_supporte describe "when the users exist" do before do + high_uid = 30000 (spec_members).each do |member| - create_user(member) + remove_user(member) + create_user(member, high_uid) + high_uid += 1 end end @@ -296,6 +303,7 @@ describe Chef::Resource::Group, :requires_root_or_running_windows, :not_supporte group = Chef::Resource::Group.new(group_name, run_context) group.members(included_members) group.excluded_members(excluded_members) + group.gid(30000) unless ohai[:platform_family] == "mac_os_x" group end diff --git a/spec/functional/resource/ifconfig_spec.rb b/spec/functional/resource/ifconfig_spec.rb index a30dcff641..0298dbcf45 100644 --- a/spec/functional/resource/ifconfig_spec.rb +++ b/spec/functional/resource/ifconfig_spec.rb @@ -51,11 +51,17 @@ describe Chef::Resource::Ifconfig, :requires_root, :skip_travis, :external => in end end + def fetch_first_interface_name + shell_out("ifconfig | grep Ethernet | head -1 | cut -d' ' -f1").stdout.strip + end + # **Caution: any updates to core interfaces can be risky. def en0_interface_for_test case ohai[:platform] when "aix" "en0" + when "ubuntu" + fetch_first_interface_name else "eth0" end diff --git a/spec/functional/resource/registry_spec.rb b/spec/functional/resource/registry_spec.rb index e64b6697c5..a7748fa4e7 100644 --- a/spec/functional/resource/registry_spec.rb +++ b/spec/functional/resource/registry_spec.rb @@ -153,6 +153,16 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do expect(@registry.data_exists?(reg_child, { :name => "Color", :type => :string, :data => "Orange" })).to eq(true) end + it "does not create the key if it already exists with same value and type but datatype of data differs" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "number", :type => :dword, :data => "12345" }]) + @new_resource.run_action(:create) + + expect(@new_resource).not_to be_updated_by_last_action + expect(@registry.key_exists?(reg_child)).to eq(true) + expect(@registry.data_exists?(reg_child, { :name => "number", :type => :dword, :data => 12344 })).to eq(true) + end + it "creates a value if it does not exist" do @new_resource.key(reg_child) @new_resource.values([{ :name => "Mango", :type => :string, :data => "Yellow" }]) @@ -187,13 +197,37 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do expect(@registry.value_exists?(reg_child + '\OpscodeTest', { :name => "Chef", :type => :multi_string, :data => %w{OpscodeOrange Rules} })).to eq(true) end - it "gives error if action create and parent does not exist and recursive is set to false" do + it "raises an error if action create and parent does not exist and recursive is set to false" do @new_resource.key(reg_child + '\Missing1\Missing2') @new_resource.values([{ :name => "OC", :type => :string, :data => "MissingData" }]) @new_resource.recursive(false) expect { @new_resource.run_action(:create) }.to raise_error(Chef::Exceptions::Win32RegNoRecursive) end + it "raises an error if action create and type key missing in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC", :data => "my_data" }]) + expect { @new_resource.run_action(:create) }.to raise_error(Chef::Exceptions::RegKeyValuesTypeMissing) + end + + it "raises an error if action create and data key missing in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC", :type => :string }]) + expect { @new_resource.run_action(:create) }.to raise_error(Chef::Exceptions::RegKeyValuesDataMissing) + end + + it "raises an error if action create and only name key present in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC" }]) + expect { @new_resource.run_action(:create) }.to raise_error(Chef::Exceptions::RegKeyValuesTypeMissing) + end + + it "does not raise an error if action create and all keys are present in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC", :type => :string, :data => "my_data" }]) + expect { @new_resource.run_action(:create) }.to_not raise_error + end + it "creates missing keys if action create and parent does not exist and recursive is set to true" do @new_resource.key(reg_child + '\Missing1\Missing2') @new_resource.values([{ :name => "OC", :type => :string, :data => "MissingData" }]) @@ -260,7 +294,7 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do Chef::Config[:why_run] = true end - it "does not throw an exception if the keys do not exist but recursive is set to false" do + it "does not raise an exception if the keys do not exist but recursive is set to false" do @new_resource.key(reg_child + '\Slitheen\Raxicoricofallapatorius') @new_resource.values([{ :name => "BriskWalk", :type => :string, :data => "is good for health" }]) @new_resource.recursive(false) @@ -268,6 +302,7 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do expect(@registry.key_exists?(reg_child + '\Slitheen')).to eq(false) expect(@registry.key_exists?(reg_child + '\Slitheen\Raxicoricofallapatorius')).to eq(false) end + it "does not create key if the action is create" do @new_resource.key(reg_child + '\Slitheen') @new_resource.values([{ :name => "BriskWalk", :type => :string, :data => "is good for health" }]) @@ -275,6 +310,34 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do @new_resource.run_action(:create) expect(@registry.key_exists?(reg_child + '\Slitheen')).to eq(false) end + + it "does not raise an exception if the action create and type key missing in values hash" do + @new_resource.key(reg_child + '\Slitheen') + @new_resource.values([{ :name => "BriskWalk", :data => "my_data" }]) + @new_resource.run_action(:create) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Slitheen')).to eq(false) + end + + it "does not raise an exception if the action create and data key missing in values hash" do + @new_resource.key(reg_child + '\Slitheen') + @new_resource.values([{ :name => "BriskWalk", :type => :string }]) + @new_resource.run_action(:create) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Slitheen')).to eq(false) + end + + it "does not raise an exception if the action create and only name key present in values hash" do + @new_resource.key(reg_child + '\Slitheen') + @new_resource.values([{ :name => "BriskWalk" }]) + @new_resource.run_action(:create) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Slitheen')).to eq(false) + end + + it "does not raise an exception if the action create and all keys are present in values hash" do + @new_resource.key(reg_child + '\Slitheen') + @new_resource.values([{ :name => "BriskWalk", :type => :string, :data => "my_data" }]) + @new_resource.run_action(:create) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Slitheen')).to eq(false) + end end end @@ -320,13 +383,37 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do expect(@registry.value_exists?(reg_child + '\Pyrovile', { :name => "Chef", :type => :multi_string, :data => %w{OpscodeOrange Rules} })).to eq(true) end - it "gives error if action create and parent does not exist and recursive is set to false" do + it "raises an error if action create and parent does not exist and recursive is set to false" do @new_resource.key(reg_child + '\Sontaran\Sontar') @new_resource.values([{ :name => "OC", :type => :string, :data => "MissingData" }]) @new_resource.recursive(false) expect { @new_resource.run_action(:create_if_missing) }.to raise_error(Chef::Exceptions::Win32RegNoRecursive) end + it "raises an error if action create_if_missing and type key missing in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC", :data => "my_data" }]) + expect { @new_resource.run_action(:create_if_missing) }.to raise_error(Chef::Exceptions::RegKeyValuesTypeMissing) + end + + it "raises an error if action create_if_missing and data key missing in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC", :type => :string }]) + expect { @new_resource.run_action(:create_if_missing) }.to raise_error(Chef::Exceptions::RegKeyValuesDataMissing) + end + + it "raises an error if action create_if_missing and only name key present in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC" }]) + expect { @new_resource.run_action(:create_if_missing) }.to raise_error(Chef::Exceptions::RegKeyValuesTypeMissing) + end + + it "does not raise an error if action create_if_missing and all keys are present in values hash" do + @new_resource.key(reg_child) + @new_resource.values([{ :name => "OC", :type => :string, :data => "my_data" }]) + expect { @new_resource.run_action(:create_if_missing) }.to_not raise_error + end + it "creates missing keys if action create and parent does not exist and recursive is set to true" do @new_resource.key(reg_child + '\Sontaran\Sontar') @new_resource.values([{ :name => "OC", :type => :string, :data => "MissingData" }]) @@ -371,7 +458,7 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do Chef::Config[:why_run] = true end - it "does not throw an exception if the keys do not exist but recursive is set to false" do + it "does not raise an exception if the keys do not exist but recursive is set to false" do @new_resource.key(reg_child + '\Zygons\Zygor') @new_resource.values([{ :name => "BriskWalk", :type => :string, :data => "is good for health" }]) @new_resource.recursive(false) @@ -379,6 +466,7 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do expect(@registry.key_exists?(reg_child + '\Zygons')).to eq(false) expect(@registry.key_exists?(reg_child + '\Zygons\Zygor')).to eq(false) end + it "does nothing if the action is create_if_missing" do @new_resource.key(reg_child + '\Zygons') @new_resource.values([{ :name => "BriskWalk", :type => :string, :data => "is good for health" }]) @@ -386,6 +474,34 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do @new_resource.run_action(:create_if_missing) expect(@registry.key_exists?(reg_child + '\Zygons')).to eq(false) end + + it "does not raise an exception if the action create_if_missing and type key missing in values hash" do + @new_resource.key(reg_child + '\Zygons') + @new_resource.values([{ :name => "BriskWalk", :data => "my_data" }]) + @new_resource.run_action(:create_if_missing) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Zygons')).to eq(false) + end + + it "does not raise an exception if the action create_if_missing and data key missing in values hash" do + @new_resource.key(reg_child + '\Zygons') + @new_resource.values([{ :name => "BriskWalk", :type => :string }]) + @new_resource.run_action(:create_if_missing) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Zygons')).to eq(false) + end + + it "does not raise an exception if the action create_if_missing and only name key present in values hash" do + @new_resource.key(reg_child + '\Zygons') + @new_resource.values([{ :name => "BriskWalk" }]) + @new_resource.run_action(:create_if_missing) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Zygons')).to eq(false) + end + + it "does not raise an exception if the action create_if_missing and all keys are present in values hash" do + @new_resource.key(reg_child + '\Zygons') + @new_resource.values([{ :name => "BriskWalk", :type => :string, :data => "my_data" }]) + @new_resource.run_action(:create_if_missing) # should not raise_error + expect(@registry.key_exists?(reg_child + '\Zygons')).to eq(false) + end end end diff --git a/spec/integration/recipes/resource_action_spec.rb b/spec/integration/recipes/resource_action_spec.rb index 0f90ed62f8..60d5831a50 100644 --- a/spec/integration/recipes/resource_action_spec.rb +++ b/spec/integration/recipes/resource_action_spec.rb @@ -9,54 +9,70 @@ module ResourceActionSpec shared_context "ActionJackson" do it "the default action is the first declared action" do converge <<-EOM, __FILE__, __LINE__ + 1 - #{resource_dsl} "hi" do - foo "foo!" - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + end + EOM expect(ActionJackson.ran_action).to eq :access_recipe_dsl expect(ActionJackson.succeeded).to eq true end + context "when running in whyrun mode" do + before do + Chef::Config[:why_run] = true + end + + it "the default action runs" do + converge <<-EOM, __FILE__, __LINE__ + 1 + #{resource_dsl} "hi" do + foo "foo!" + end + EOM + expect(ActionJackson.ran_action).to eq :access_recipe_dsl + expect(ActionJackson.succeeded).to eq true + end + end + it "the action can access recipe DSL" do converge <<-EOM, __FILE__, __LINE__ + 1 - #{resource_dsl} "hi" do - foo "foo!" - action :access_recipe_dsl - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + action :access_recipe_dsl + end + EOM expect(ActionJackson.ran_action).to eq :access_recipe_dsl expect(ActionJackson.succeeded).to eq true end it "the action can access attributes" do converge <<-EOM, __FILE__, __LINE__ + 1 - #{resource_dsl} "hi" do - foo "foo!" - action :access_attribute - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + action :access_attribute + end + EOM expect(ActionJackson.ran_action).to eq :access_attribute expect(ActionJackson.succeeded).to eq "foo!" end it "the action can access public methods" do converge <<-EOM, __FILE__, __LINE__ + 1 - #{resource_dsl} "hi" do - foo "foo!" - action :access_method - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + action :access_method + end + EOM expect(ActionJackson.ran_action).to eq :access_method expect(ActionJackson.succeeded).to eq "foo_public!" end it "the action can access protected methods" do converge <<-EOM, __FILE__, __LINE__ + 1 - #{resource_dsl} "hi" do - foo "foo!" - action :access_protected_method - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + action :access_protected_method + end + EOM expect(ActionJackson.ran_action).to eq :access_protected_method expect(ActionJackson.succeeded).to eq "foo_protected!" end @@ -64,39 +80,39 @@ module ResourceActionSpec it "the action cannot access private methods" do expect do converge(<<-EOM, __FILE__, __LINE__ + 1) - #{resource_dsl} "hi" do - foo "foo!" - action :access_private_method - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + action :access_private_method + end + EOM end.to raise_error(NameError) expect(ActionJackson.ran_action).to eq :access_private_method end it "the action cannot access resource instance variables" do converge <<-EOM, __FILE__, __LINE__ + 1 - #{resource_dsl} "hi" do - foo "foo!" - action :access_instance_variable - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + action :access_instance_variable + end + EOM expect(ActionJackson.ran_action).to eq :access_instance_variable expect(ActionJackson.succeeded).to be_nil end it "the action does not compile until the prior resource has converged" do converge <<-EOM, __FILE__, __LINE__ + 1 - ruby_block "wow" do - block do - ResourceActionSpec::ActionJackson.ruby_block_converged = "ruby_block_converged!" + ruby_block "wow" do + block do + ResourceActionSpec::ActionJackson.ruby_block_converged = "ruby_block_converged!" + end end - end - #{resource_dsl} "hi" do - foo "foo!" - action :access_class_method - end - EOM + #{resource_dsl} "hi" do + foo "foo!" + action :access_class_method + end + EOM expect(ActionJackson.ran_action).to eq :access_class_method expect(ActionJackson.succeeded).to eq "ruby_block_converged!" end @@ -141,7 +157,7 @@ module ResourceActionSpec action :access_recipe_dsl do ActionJackson.ran_action = :access_recipe_dsl - ruby_block "hi there" do + whyrun_safe_ruby_block "hi there" do block do ActionJackson.succeeded = true end diff --git a/spec/integration/solo/solo_spec.rb b/spec/integration/solo/solo_spec.rb index bfcb74b45c..e4228a7559 100644 --- a/spec/integration/solo/solo_spec.rb +++ b/spec/integration/solo/solo_spec.rb @@ -113,7 +113,7 @@ EOM ruby_block "sleeping" do block do retries = 200 - while IO.read(Chef::Config[:log_location]) !~ /Chef client [0-9]+ is running, will wait for it to finish and then run./ + while IO.read(Chef::Config[:log_location]) !~ /Chef client .* is running, will wait for it to finish and then run./ sleep 0.1 raise "we ran out of retries" if ( retries -= 1 ) <= 0 end @@ -157,7 +157,7 @@ EOM run_log = File.read(path_to("logs/runs.log")) # second run should have a message which indicates it's waiting for the first run - expect(run_log).to match(/Chef client [0-9]+ is running, will wait for it to finish and then run./) + expect(run_log).to match(/Chef client .* is running, will wait for it to finish and then run./) # both of the runs should succeed expect(run_log.lines.reject { |l| !l.include? "INFO: Chef Run complete in" }.length).to eq(2) diff --git a/spec/unit/cookbook/file_vendor_spec.rb b/spec/unit/cookbook/file_vendor_spec.rb index 139a5932f9..164fbd8177 100644 --- a/spec/unit/cookbook/file_vendor_spec.rb +++ b/spec/unit/cookbook/file_vendor_spec.rb @@ -94,4 +94,19 @@ describe Chef::Cookbook::FileVendor do end + context "when vendoring a cookbook with a name mismatch" do + let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "cookbooks") } + + # A manifest is a Hash of the format defined by Chef::CookbookVersion#manifest + let(:manifest) { { :cookbook_name => "name-mismatch" } } + + before do + file_vendor_class.fetch_from_disk(cookbook_path) + end + + it "retrieves the file from the correct location based on path to the cookbook that conatins the correct name metadata" do + file_vendor = file_vendor_class.create_from_manifest(manifest) + file_vendor.get_filename("metadata.rb") + end + end end diff --git a/spec/unit/cookbook/metadata_spec.rb b/spec/unit/cookbook/metadata_spec.rb index 27666eb338..389f02501a 100644 --- a/spec/unit/cookbook/metadata_spec.rb +++ b/spec/unit/cookbook/metadata_spec.rb @@ -948,5 +948,24 @@ describe Chef::Cookbook::Metadata do end end + describe "from_file" do + it "ignores unknown metadata fields in metadata.rb files" do + expect(Chef::Log).to receive(:debug).with(/ignoring method some_spiffy_new_metadata_field/) + Tempfile.open("metadata.rb") do |f| + f.write <<-EOF + some_spiffy_new_metadata_field "stuff its set to" + EOF + f.close + metadata.from_file(f.path) + end + end + end + + describe "from_json" do + it "ignores unknown metadata fields in metdata.json files" do + json = %q{{ "some_spiffy_new_metadata_field": "stuff its set to" }} + metadata.from_json(json) + end + end end end diff --git a/spec/unit/exceptions_spec.rb b/spec/unit/exceptions_spec.rb index 940edfec2e..e952a5448a 100644 --- a/spec/unit/exceptions_spec.rb +++ b/spec/unit/exceptions_spec.rb @@ -68,6 +68,8 @@ describe Chef::Exceptions do Chef::Exceptions::EnvironmentNotFound => RuntimeError, Chef::Exceptions::InvalidVersionConstraint => ArgumentError, Chef::Exceptions::IllegalVersionConstraint => NotImplementedError, + Chef::Exceptions::RegKeyValuesTypeMissing => ArgumentError, + Chef::Exceptions::RegKeyValuesDataMissing => ArgumentError, } exception_to_super_class.each do |exception, expected_super_class| diff --git a/spec/unit/file_content_management/tempfile_spec.rb b/spec/unit/file_content_management/tempfile_spec.rb index 4b27fc8cc9..a04ace5f16 100644 --- a/spec/unit/file_content_management/tempfile_spec.rb +++ b/spec/unit/file_content_management/tempfile_spec.rb @@ -19,38 +19,59 @@ require "spec_helper" describe Chef::FileContentManagement::Tempfile do - let(:resource) do - r = Chef::Resource::File.new("new_file") - r.path "/foo/bar/new_file" - r - end - subject { described_class.new(resource) } + def tempfile_object_for_path(path) + r = Chef::Resource::File.new("decorative name that should not matter") + r.path path + Chef::FileContentManagement::Tempfile.new(r) + end describe "#tempfile_basename" do it "should return a dotfile", :unix_only do + subject = tempfile_object_for_path("/foo/bar/new_file") expect(subject.send(:tempfile_basename)).to eql(".chef-new_file") end it "should return a file", :windows_only do + subject = tempfile_object_for_path("/foo/bar/new_file") expect(subject.send(:tempfile_basename)).to eql("chef-new_file") end + + it "should strip the extension", :unix_only do + subject = tempfile_object_for_path("/foo/bar/new_file.html.erb") + expect(subject.send(:tempfile_basename)).to eql(".chef-new_file") + end + + it "should strip the extension", :windows_only do + subject = tempfile_object_for_path("/foo/bar/new_file.html.erb") + expect(subject.send(:tempfile_basename)).to eql("chef-new_file") + end + end + + describe "#tempfile_extension" do + it "should preserve the file extension" do + subject = tempfile_object_for_path("/foo/bar/new_file.html.erb") + expect(subject.send(:tempfile_extension)).to eql(".html.erb") + end end describe "#tempfile_dirnames" do it "should select a temp dir" do + subject = tempfile_object_for_path("/foo/bar/new_file") Chef::Config[:file_staging_uses_destdir] = false expect(Dir).to receive(:tmpdir).and_return("/tmp/dir") expect(subject.send(:tempfile_dirnames)).to eql(%w{ /tmp/dir }) end it "should select the destdir" do + subject = tempfile_object_for_path("/foo/bar/new_file") Chef::Config[:file_staging_uses_destdir] = true expect(subject.send(:tempfile_dirnames)).to eql(%w{ /foo/bar }) end it "should select the destdir and a temp dir" do + subject = tempfile_object_for_path("/foo/bar/new_file") Chef::Config[:file_staging_uses_destdir] = :auto expect(Dir).to receive(:tmpdir).and_return("/tmp/dir") expect(subject.send(:tempfile_dirnames)).to eql(%w{ /foo/bar /tmp/dir }) @@ -67,18 +88,27 @@ describe Chef::FileContentManagement::Tempfile do end it "should create a temporary file" do + subject = tempfile_object_for_path("/foo/bar/new_file") expect(subject.send(:tempfile_open)).to be_a(Tempfile) end + it "should preserve the extension in the tempfile path" do + subject = tempfile_object_for_path("/foo/bar/new_file.html.erb") + tempfile = subject.send(:tempfile_open) + expect(tempfile.path).to match(/chef-new_file.*\.html\.erb$/) + end + it "should pick the destdir preferrentially" do - expect(Tempfile).to receive(:open).with(tempname, "/foo/bar").and_return(tempfile) + subject = tempfile_object_for_path("/foo/bar/new_file") + expect(Tempfile).to receive(:open).with([tempname, ""], "/foo/bar").and_return(tempfile) subject.send(:tempfile_open) end it "should use ENV['TMP'] otherwise" do + subject = tempfile_object_for_path("/foo/bar/new_file") expect(Dir).to receive(:tmpdir).and_return("/tmp/dir") - expect(Tempfile).to receive(:open).with(tempname, "/foo/bar").and_raise(SystemCallError, "foo") - expect(Tempfile).to receive(:open).with(tempname, "/tmp/dir").and_return(tempfile) + expect(Tempfile).to receive(:open).with([tempname, ""], "/foo/bar").and_raise(SystemCallError, "foo") + expect(Tempfile).to receive(:open).with([tempname, ""], "/tmp/dir").and_return(tempfile) subject.send(:tempfile_open) end end diff --git a/spec/unit/knife/core/ui_spec.rb b/spec/unit/knife/core/ui_spec.rb index 9f525f22f0..be77fd8501 100644 --- a/spec/unit/knife/core/ui_spec.rb +++ b/spec/unit/knife/core/ui_spec.rb @@ -377,12 +377,33 @@ EOM end it "should return the name attribute" do - allow_any_instance_of(Chef::Node).to receive(:name).and_return("chef.localdomain") input = Chef::Node.new + input.name("chef.localdomain") @ui.config[:attribute] = "name" expect(@ui.format_for_display(input)).to eq( { "chef.localdomain" => { "name" => "chef.localdomain" } }) end + it "should return a 'class' attribute and not the node.class" do + input = Chef::Node.new + input.default["class"] = "classy!" + @ui.config[:attribute] = "class" + expect(@ui.format_for_display(input)).to eq( { nil => { "class" => "classy!" } } ) + end + + it "should return the chef_environment attribute" do + input = Chef::Node.new + input.chef_environment = "production-partner-load-integration-preview-testing" + @ui.config[:attribute] = "chef_environment" + expect(@ui.format_for_display(input)).to eq( { nil => { "chef_environment" => "production-partner-load-integration-preview-testing" } } ) + end + + it "works with arrays" do + input = Chef::Node.new + input.default["array"] = %w{zero one two} + @ui.config[:attribute] = "array.1" + expect(@ui.format_for_display(input)).to eq( { nil => { "array.1" => "one" } } ) + end + it "returns nil when given an attribute path that isn't a name or attribute" do input = { "keys" => { "keys" => "values" }, "hi" => "ho", "id" => "sample-data-bag-item" } non_existing_path = "nope.nada.nothingtoseehere" diff --git a/spec/unit/mixin/checksum_spec.rb b/spec/unit/mixin/checksum_spec.rb index 997dcd523e..801c8820d2 100644 --- a/spec/unit/mixin/checksum_spec.rb +++ b/spec/unit/mixin/checksum_spec.rb @@ -37,4 +37,18 @@ describe Chef::Mixin::Checksum do expect(@checksum_user.checksum(@file)).to eq("09ee9c8cc70501763563bcf9c218d71b2fbf4186bf8e1e0da07f0f42c80a3394") end + describe "short_cksum" do + context "nil provided for checksum" do + it "returns none" do + expect(@checksum_user.short_cksum(nil)).to eq("none") + end + end + + context "non-nil provided for checksum" do + it "returns the short checksum" do + expect(@checksum_user.short_cksum("u7ghbxikk3i9blsimmy2y2ionmxx")).to eq("u7ghbx") + end + end + end + end diff --git a/spec/unit/node/attribute_spec.rb b/spec/unit/node/attribute_spec.rb index e40f454c0b..00081a9fd9 100644 --- a/spec/unit/node/attribute_spec.rb +++ b/spec/unit/node/attribute_spec.rb @@ -1171,7 +1171,29 @@ describe Chef::Node::Attribute do Chef::Config[:treat_deprecation_warnings_as_errors] = false expect { @attributes.new_key = "new value" }.to raise_error(Chef::Exceptions::ImmutableAttributeModification) end - end + describe "deeply converting values" do + it "converts values through an array" do + @attributes.default[:foo] = [ { bar: true } ] + expect(@attributes["foo"].class).to eql(Chef::Node::ImmutableArray) + expect(@attributes["foo"][0].class).to eql(Chef::Node::ImmutableMash) + expect(@attributes["foo"][0]["bar"]).to be true + end + + it "converts values through nested arrays" do + @attributes.default[:foo] = [ [ { bar: true } ] ] + expect(@attributes["foo"].class).to eql(Chef::Node::ImmutableArray) + expect(@attributes["foo"][0].class).to eql(Chef::Node::ImmutableArray) + expect(@attributes["foo"][0][0].class).to eql(Chef::Node::ImmutableMash) + expect(@attributes["foo"][0][0]["bar"]).to be true + end + + it "converts values through nested hashes" do + @attributes.default[:foo] = { baz: { bar: true } } + expect(@attributes["foo"].class).to eql(Chef::Node::ImmutableMash) + expect(@attributes["foo"]["baz"].class).to eql(Chef::Node::ImmutableMash) + expect(@attributes["foo"]["baz"]["bar"]).to be true + end + end end diff --git a/spec/unit/node/vivid_mash_spec.rb b/spec/unit/node/vivid_mash_spec.rb index 5319ba4a35..206b15ef6c 100644 --- a/spec/unit/node/vivid_mash_spec.rb +++ b/spec/unit/node/vivid_mash_spec.rb @@ -37,6 +37,33 @@ describe Chef::Node::VividMash do expect(root).to receive(:top_level_breadcrumb=).with(key).at_least(:once).and_call_original end + context "#[]=" do + it "deep converts values through arrays" do + allow(root).to receive(:reset_cache) + vivid[:foo] = [ { :bar => true } ] + expect(vivid["foo"].class).to eql(Chef::Node::AttrArray) + expect(vivid["foo"][0].class).to eql(Chef::Node::VividMash) + expect(vivid["foo"][0]["bar"]).to be true + end + + it "deep converts values through nested arrays" do + allow(root).to receive(:reset_cache) + vivid[:foo] = [ [ { :bar => true } ] ] + expect(vivid["foo"].class).to eql(Chef::Node::AttrArray) + expect(vivid["foo"][0].class).to eql(Chef::Node::AttrArray) + expect(vivid["foo"][0][0].class).to eql(Chef::Node::VividMash) + expect(vivid["foo"][0][0]["bar"]).to be true + end + + it "deep converts values through hashes" do + allow(root).to receive(:reset_cache) + vivid[:foo] = { baz: { :bar => true } } + expect(vivid["foo"]).to be_an_instance_of(Chef::Node::VividMash) + expect(vivid["foo"]["baz"]).to be_an_instance_of(Chef::Node::VividMash) + expect(vivid["foo"]["baz"]["bar"]).to be true + end + end + context "#read" do before do # vivify the vividmash, then we're read-only so the cache should never be cleared afterwards diff --git a/spec/unit/provider/group/groupadd_spec.rb b/spec/unit/provider/group/groupadd_spec.rb index 93159dd16e..054d953414 100644 --- a/spec/unit/provider/group/groupadd_spec.rb +++ b/spec/unit/provider/group/groupadd_spec.rb @@ -18,156 +18,175 @@ require "spec_helper" -describe Chef::Provider::Group::Groupadd, "set_options" do - before do - @node = Chef::Node.new - @events = Chef::EventDispatch::Dispatcher.new - @run_context = Chef::RunContext.new(@node, {}, @events) - @new_resource = Chef::Resource::Group.new("aj") - @new_resource.gid(50) - @new_resource.members(%w{root aj}) - @new_resource.system false - @new_resource.non_unique false - @current_resource = Chef::Resource::Group.new("aj") - @current_resource.gid(50) - @current_resource.members(%w{root aj}) - @current_resource.system false - @current_resource.non_unique false - @provider = Chef::Provider::Group::Groupadd.new(@new_resource, @run_context) - @provider.current_resource = @current_resource - end - - field_list = { - :gid => "-g", - } - - field_list.each do |attribute, option| - it "should check for differences in #{attribute} between the current and new resources" do - expect(@new_resource).to receive(attribute) - expect(@current_resource).to receive(attribute) - @provider.set_options +describe Chef::Provider::Group::Groupadd do + let(:node) { Chef::Node.new } + let(:events) { Chef::EventDispatch::Dispatcher.new } + let(:run_context) { Chef::RunContext.new(node, {}, events) } + let(:new_resource) do + Chef::Resource::Group.new("aj").tap do |r| + r.gid 50 + r.members %w{root aj} + r.system false + r.non_unique false end - it "should set the option for #{attribute} if the new resources #{attribute} is not null" do - allow(@new_resource).to receive(attribute).and_return("wowaweea") - expect(@provider.set_options).to eql(" #{option} '#{@new_resource.send(attribute)}' #{@new_resource.group_name}") + end + let(:current_resource) do + Chef::Resource::Group.new("aj").tap do |r| + r.gid 50 + r.members %w{root aj} + r.system false + r.non_unique false end end - - it "should combine all the possible options" do - match_string = "" - field_list.sort { |a, b| a[0] <=> b[0] }.each do |attribute, option| - allow(@new_resource).to receive(attribute).and_return("hola") - match_string << " #{option} 'hola'" + let(:provider) do + described_class.new(new_resource, run_context).tap do |p| + p.current_resource = current_resource end - match_string << " aj" - expect(@provider.set_options).to eql(match_string) end - describe "when we want to create a system group" do - it "should not set groupadd_options '-r' when system is false" do - @new_resource.system(false) - expect(@provider.groupadd_options).not_to match(/-r/) + describe "#set_options" do + field_list = { + :gid => "-g", + } + + field_list.each do |attribute, option| + it "should check for differences in #{attribute} between the current and new resources" do + expect(new_resource).to receive(attribute) + expect(current_resource).to receive(attribute) + provider.set_options + end + + it "should set the option for #{attribute} if the new resources #{attribute} is not null" do + allow(new_resource).to receive(attribute).and_return("wowaweea") + expect(provider.set_options).to eql(" #{option} '#{new_resource.send(attribute)}' #{new_resource.group_name}") + end end - it "should set groupadd -r if system is true" do - @new_resource.system(true) - expect(@provider.groupadd_options).to eq(" -r") + it "should combine all the possible options" do + match_string = "" + field_list.sort { |a, b| a[0] <=> b[0] }.each do |attribute, option| + allow(new_resource).to receive(attribute).and_return("hola") + match_string << " #{option} 'hola'" + end + match_string << " aj" + expect(provider.set_options).to eql(match_string) end - end - describe "when we want to create a non_unique gid group" do - it "should not set groupadd_options '-o' when non_unique is false" do - @new_resource.non_unique(false) - expect(@provider.groupadd_options).not_to match(/-o/) + describe "when we want to create a system group" do + it "should not set groupadd_options '-r' when system is false" do + new_resource.system(false) + expect(provider.groupadd_options).not_to match(/-r/) + end + + it "should set groupadd -r if system is true" do + new_resource.system(true) + expect(provider.groupadd_options).to eq(" -r") + end + + context "on Solaris" do + before { node.automatic["platform"] = "solaris2" } + it "should not set groupadd -r if system is true" do + new_resource.system(true) + expect(provider.groupadd_options).not_to match(/-r/) + end + end end - it "should set groupadd -o if non_unique is true" do - @new_resource.non_unique(true) - expect(@provider.groupadd_options).to eq(" -o") - end - end -end + describe "when we want to create a non_unique gid group" do + it "should not set groupadd_options '-o' when non_unique is false" do + new_resource.non_unique(false) + expect(provider.groupadd_options).not_to match(/-o/) + end -describe Chef::Provider::Group::Groupadd, "create_group" do - before do - @node = Chef::Node.new - @new_resource = Chef::Resource::Group.new("aj") - @provider = Chef::Provider::Group::Groupadd.new(@node, @new_resource) - allow(@provider).to receive(:run_command).and_return(true) - allow(@provider).to receive(:set_options).and_return(" monkey") - allow(@provider).to receive(:groupadd_options).and_return("") - allow(@provider).to receive(:modify_group_members).and_return(true) + it "should set groupadd -o if non_unique is true" do + new_resource.non_unique(true) + expect(provider.groupadd_options).to eq(" -o") + end + end end - it "should run groupadd with the return of set_options" do - expect(@provider).to receive(:run_command).with({ :command => "groupadd monkey" }).and_return(true) - @provider.create_group - end + describe "#create_group" do + before do + allow(provider).to receive(:run_command).and_return(true) + allow(provider).to receive(:set_options).and_return(" monkey") + allow(provider).to receive(:groupadd_options).and_return("") + allow(provider).to receive(:modify_group_members).and_return(true) + end - it "should modify the group members" do - expect(@provider).to receive(:modify_group_members).and_return(true) - @provider.create_group - end -end + it "should run groupadd with the return of set_options" do + expect(provider).to receive(:run_command).with({ :command => "groupadd monkey" }).and_return(true) + provider.create_group + end -describe Chef::Provider::Group::Groupadd do - before do - @node = Chef::Node.new - @events = Chef::EventDispatch::Dispatcher.new - @run_context = Chef::RunContext.new(@node, {}, @events) - @new_resource = Chef::Resource::Group.new("aj") - @provider = Chef::Provider::Group::Groupadd.new(@new_resource, @run_context) - allow(@provider).to receive(:run_command).and_return(true) - allow(@provider).to receive(:set_options).and_return(" monkey") + it "should modify the group members" do + expect(provider).to receive(:modify_group_members).and_return(true) + provider.create_group + end end - describe "manage group" do + describe "#manage_group" do + before do + allow(provider).to receive(:run_command).and_return(true) + allow(provider).to receive(:set_options).and_return(" monkey") + end it "should run groupmod with the return of set_options" do - allow(@provider).to receive(:modify_group_members).and_return(true) - expect(@provider).to receive(:run_command).with({ :command => "groupmod monkey" }).and_return(true) - @provider.manage_group + allow(provider).to receive(:modify_group_members).and_return(true) + expect(provider).to receive(:run_command).with({ :command => "groupmod monkey" }).and_return(true) + provider.manage_group end it "should modify the group members" do - expect(@provider).to receive(:modify_group_members).and_return(true) - @provider.manage_group + expect(provider).to receive(:modify_group_members).and_return(true) + provider.manage_group end end - describe "remove_group" do + describe "#remove_group" do + before do + allow(provider).to receive(:run_command).and_return(true) + allow(provider).to receive(:set_options).and_return(" monkey") + end it "should run groupdel with the new resources group name" do - expect(@provider).to receive(:run_command).with({ :command => "groupdel aj" }).and_return(true) - @provider.remove_group + expect(provider).to receive(:run_command).with({ :command => "groupdel aj" }).and_return(true) + provider.remove_group end end [:add_member, :remove_member, :set_members].each do |m| it "should raise an error when calling #{m}" do - expect { @provider.send(m, [ ]) }.to raise_error(Chef::Exceptions::Group, "you must override #{m} in #{@provider}") + expect { provider.send(m, [ ]) }.to raise_error(Chef::Exceptions::Group, "you must override #{m} in #{provider}") end end - describe "load_current_resource" do + describe "#load_current_resource" do + before do + allow(provider).to receive(:run_command).and_return(true) + allow(provider).to receive(:set_options).and_return(" monkey") + end + before do allow(File).to receive(:exists?).and_return(false) - @provider.define_resource_requirements + provider.define_resource_requirements end + it "should raise an error if the required binary /usr/sbin/groupadd doesn't exist" do expect(File).to receive(:exists?).with("/usr/sbin/groupadd").and_return(false) - expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group) + expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group) end + it "should raise an error if the required binary /usr/sbin/groupmod doesn't exist" do expect(File).to receive(:exists?).with("/usr/sbin/groupadd").and_return(true) expect(File).to receive(:exists?).with("/usr/sbin/groupmod").and_return(false) - expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group) + expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group) end + it "should raise an error if the required binary /usr/sbin/groupdel doesn't exist" do expect(File).to receive(:exists?).with("/usr/sbin/groupadd").and_return(true) expect(File).to receive(:exists?).with("/usr/sbin/groupmod").and_return(true) expect(File).to receive(:exists?).with("/usr/sbin/groupdel").and_return(false) - expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group) + expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Group) end end diff --git a/spec/unit/provider/log_spec.rb b/spec/unit/provider/log_spec.rb index 2e4f9c4e52..ce7b1af55a 100644 --- a/spec/unit/provider/log_spec.rb +++ b/spec/unit/provider/log_spec.rb @@ -72,4 +72,18 @@ describe Chef::Provider::Log::ChefLog do expect(Chef::Log).to receive(:info).with(log_str).and_return(true) provider.run_action(:write) end + + context "when count_log_resource_updates is passed in knife.rb" do + it "updates the resource count if count_log_resource_updates=true" do + Chef::Config[:count_log_resource_updates] = true + expect(new_resource).to receive(:updated_by_last_action) + provider.run_action(:write) + end + + it "doesn't update the resource count if count_log_resource_updates=false" do + Chef::Config[:count_log_resource_updates] = false + expect(new_resource).not_to receive(:updated_by_last_action) + provider.run_action(:write) + end + end end diff --git a/spec/unit/provider/package/cab_spec.rb b/spec/unit/provider/package/cab_spec.rb new file mode 100644 index 0000000000..5e16795aa8 --- /dev/null +++ b/spec/unit/provider/package/cab_spec.rb @@ -0,0 +1,218 @@ +# +# Author:: Vasundhara Jagdale (<vasundhara.jagdale@msystechnologies.com>) +# Copyright:: Copyright 2008-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" + +describe Chef::Provider::Package::Cab do + let(:timeout) {} + + let(:new_resource) { Chef::Resource::CabPackage.new("windows_test_pkg") } + + let(:provider) do + node = Chef::Node.new + events = Chef::EventDispatch::Dispatcher.new + run_context = Chef::RunContext.new(node, {}, events) + Chef::Provider::Package::Cab.new(new_resource, run_context) + end + + let(:installed_package_list_stdout) do + <<-EOF +Packages listing: +Package Identity : Package_for_KB2999486~31bf3856ad364e35~amd64~~6.1.9768.0 +Package Identity : Package_for_KB2994825~31bf3856ad364e35~amd64~~6.1.7601.0 + EOF + end + + let(:package_version_stdout) do + <<-EOF +Package information: +Package Identity : Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0 +State : Installed +Dependency : Language Pack +The operation completed successfully + EOF + end + + before do + new_resource.source = "C:\\Temp\\Test6.1-KB2664825-v3-x64.cab" + installed_package_list_obj = double(stdout: installed_package_list_stdout) + allow(provider).to receive(:dism_command).with("/Get-Packages").and_return(installed_package_list_obj) + package_version_obj = double(stdout: package_version_stdout) + allow(provider).to receive(:dism_command).with("/Get-PackageInfo /PackagePath:\"#{new_resource.source}\"").and_return(package_version_obj) + end + + def allow_package_info(package_path = nil, package_name = nil) + get_package_info_stdout = <<-EOF +Deployment Image Servicing and Management tool +Version: 6.1.7600.16385 + +Image Version: 6.1.7600.16385 + +Package information: +Package Identity : Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0 +Applicable : Yes +Copyright : Microsoft Corporation +Company : Microsoft Corporation +State : Installed +Dependency : Language Pack +The operation completed successfully + EOF + get_package_info_obj = double(stdout: get_package_info_stdout) + if package_path + allow(provider).to receive(:dism_command).with("/Get-PackageInfo /PackagePath:\"#{package_path}\"").and_return(get_package_info_obj) + else + allow(provider).to receive(:dism_command).with("/Get-PackageInfo /PackageName:\"#{package_name}\"").and_return(get_package_info_obj) + end + end + + def allow_get_packages + get_packages_stdout = <<-EOF +Deployment Image Servicing and Management tool +Version: 6.1.7600.16385 + +Image Version: 6.1.7600.16385 + +Packages listing: + +Package Identity : Package_for_KB2999486~31bf3856ad364e35~amd64~~6.1.9768.0 +State : Installed +Release Type : Language Pack +Install Time : 2/11/2015 11:33 PM + +Package Identity : Package_for_KB2994825~31bf3856ad364e35~amd64~~6.1.7601.0 +State : Installed +Release Type : Language Pack +Install Time : 2/11/2015 11:33 PM + +Package Identity : Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0 +State : Installed +Release Type : Feature Pack +Install Time : 11/21/2010 3:40 AM + +The operation completed successfully. + EOF + get_packages_obj = double(stdout: get_packages_stdout) + allow(provider).to receive(:dism_command).with("/Get-Packages").and_return(get_packages_obj) + end + + describe "#load_current_resource" do + it "returns a current_resource" do + expect(provider.load_current_resource).to be_kind_of(Chef::Resource::CabPackage) + end + + it "sets the current_resource.version to nil when the package is not installed" do + provider.load_current_resource + expect(provider.current_resource.version).to eql(nil) + end + + it "sets the new resource package version" do + provider.load_current_resource + expect(provider.new_resource.version).to eql("6.1.3.0") + end + end + + describe "#initialize" do + it "returns the correct class" do + expect(provider).to be_kind_of(Chef::Provider::Package::Cab) + end + end + + describe "#package_version" do + it "returns the new package version" do + allow_package_info(new_resource.source, nil) + expect(provider.package_version).to eql("6.1.3.0") + end + end + + describe "#installed_version" do + it "returns the current installed version of package" do + allow_package_info(new_resource.source, nil) + allow_get_packages + allow_package_info(nil, "Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0") + expect(provider.installed_version).to eql("6.1.3.0") + end + end + + describe "#action_remove" do + it "does nothing when the package is already removed" do + provider.load_current_resource + expect(provider).not_to receive(:remove_package) + provider.run_action(:remove) + expect(new_resource).not_to be_updated_by_last_action + end + + it "removes packages if package is installed" do + allow_package_info(new_resource.source, nil) + allow_get_packages + allow_package_info(nil, "Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0") + provider.load_current_resource + expect(provider.installed_version).not_to eql(nil) + expect(provider).to receive(:remove_package) + provider.run_action(:remove) + expect(new_resource).to be_updated_by_last_action + end + end + + describe "#action_install" do + it "installs package if already not installed" do + provider.load_current_resource + expect(provider.installed_version).to eql(nil) + expect(provider).to receive(:install_package) + provider.run_action(:install) + expect(new_resource).to be_updated_by_last_action + end + + it "does not install package if already installed" do + allow_package_info(new_resource.source, nil) + allow_get_packages + allow_package_info(nil, "Package_for_KB2664825~31bf3856ad364e35~amd64~~6.1.3.0") + provider.load_current_resource + expect(provider.installed_version).not_to eql(nil) + expect(provider).not_to receive(:install_package) + provider.run_action(:install) + expect(new_resource).not_to be_updated_by_last_action + end + end + + context "Invalid package source" do + def package_version_stdout + package_version_stdout = <<-EOF + +Deployment Image Servicing and Management tool +Version: 6.1.7600.16385 + +Image Version: 6.1.7600.16385 + +An error occurred trying to open - c:\\temp\\test6.1-KB2664825-v3-x64.cab Error: 0x80070003 +Error: 3 +The system cannot find the path specified. +The DISM log file can be found at C:\\Windows\\Logs\\DISM\\dism.log. + EOF + end + + before do + new_resource.source = "C:\\Temp\\Test6.1-KB2664825-v3-x64.cab" + installed_package_list_obj = double(stdout: installed_package_list_stdout) + allow(provider).to receive(:dism_command).with("/Get-Packages").and_return(installed_package_list_obj) + end + + it "raises error for invalid source path or file" do + expect { provider.load_current_resource }.to raise_error(Chef::Exceptions::Package, "DISM: The system cannot find the path or file specified.") + end + end +end diff --git a/spec/unit/provider/package/rubygems_spec.rb b/spec/unit/provider/package/rubygems_spec.rb index 4934505583..548204df75 100644 --- a/spec/unit/provider/package/rubygems_spec.rb +++ b/spec/unit/provider/package/rubygems_spec.rb @@ -735,10 +735,9 @@ describe Chef::Provider::Package::Rubygems do context "when source is a path" do let(:source) { CHEF_SPEC_DATA + "/gems/chef-integration-test-0.1.0.gem" } let(:target_version) { ">= 0" } - let(:domain) { " --local" } it "installs the gem by shelling out to gem install" do - expect(provider).to receive(:shell_out!).with("#{gem_binary} install #{source} -q --no-rdoc --no-ri -v \"#{target_version}\"#{domain}", env: nil, timeout: 900) + expect(provider).to receive(:shell_out!).with("#{gem_binary} install #{source} -q --no-rdoc --no-ri -v \"#{target_version}\"", env: nil, timeout: 900) provider.run_action(:install) expect(new_resource).to be_updated_by_last_action end @@ -747,11 +746,10 @@ describe Chef::Provider::Package::Rubygems do context "when the package is a path and source is nil" do let(:gem_name) { CHEF_SPEC_DATA + "/gems/chef-integration-test-0.1.0.gem" } let(:target_version) { ">= 0" } - let(:domain) { " --local" } it "installs the gem from file by shelling out to gem install when the package is a path and the source is nil" do expect(new_resource.source).to eq(gem_name) - expect(provider).to receive(:shell_out!).with("#{gem_binary} install #{gem_name} -q --no-rdoc --no-ri -v \"#{target_version}\"#{domain}", env: nil, timeout: 900) + expect(provider).to receive(:shell_out!).with("#{gem_binary} install #{gem_name} -q --no-rdoc --no-ri -v \"#{target_version}\"", env: nil, timeout: 900) provider.run_action(:install) expect(new_resource).to be_updated_by_last_action end diff --git a/spec/unit/provider/package/windows_spec.rb b/spec/unit/provider/package/windows_spec.rb index e26662ac75..d1d717bdbe 100644 --- a/spec/unit/provider/package/windows_spec.rb +++ b/spec/unit/provider/package/windows_spec.rb @@ -394,4 +394,49 @@ describe Chef::Provider::Package::Windows, :windows_only do end end end + + shared_context "valid checksum" do + context "checksum is valid" do + before do + allow(provider).to receive(:checksum).and_return("jiie00u3bbs92vsbhvgvklb2lasgh20ah") + end + + it "does not raise the checksum mismatch exception" do + expect { provider.send(:validate_content!) }.to_not raise_error + end + end + end + + shared_context "invalid checksum" do + context "checksum is invalid" do + before do + allow(provider).to receive(:checksum).and_return("kiie30u3bbs92vsbhvgvklb2lasgh20ah") + end + + it "raises the checksum mismatch exception" do + expect { provider.send(:validate_content!) }.to raise_error( + Chef::Exceptions::ChecksumMismatch) + end + end + end + + describe "validate_content!" do + before(:each) do + new_resource.checksum("jiie00u3bbs92vsbhvgvklb2lasgh20ah") + end + + context "checksum is in lowercase" do + include_context "valid checksum" + include_context "invalid checksum" + end + + context "checksum is in uppercase" do + before do + new_resource.checksum = new_resource.checksum.upcase + end + + include_context "valid checksum" + include_context "invalid checksum" + end + end end diff --git a/spec/unit/provider/registry_key_spec.rb b/spec/unit/provider/registry_key_spec.rb index 41bc5b33d3..3fb9468f5d 100644 --- a/spec/unit/provider/registry_key_spec.rb +++ b/spec/unit/provider/registry_key_spec.rb @@ -19,23 +19,6 @@ require "spec_helper" shared_examples_for "a registry key" do - before(:each) do - @node = Chef::Node.new - @events = Chef::EventDispatch::Dispatcher.new - @run_context = Chef::RunContext.new(@node, {}, @events) - - @new_resource = Chef::Resource::RegistryKey.new("windows is fun", @run_context) - @new_resource.key keyname - @new_resource.values( testval1 ) - @new_resource.recursive false - - @provider = Chef::Provider::RegistryKey.new(@new_resource, @run_context) - - allow(@provider).to receive(:running_on_windows!).and_return(true) - @double_registry = double(Chef::Win32::Registry) - allow(@provider).to receive(:registry).and_return(@double_registry) - end - describe "when first created" do end @@ -273,6 +256,23 @@ shared_examples_for "a registry key" do end describe Chef::Provider::RegistryKey do + before(:each) do + @node = Chef::Node.new + @events = Chef::EventDispatch::Dispatcher.new + @run_context = Chef::RunContext.new(@node, {}, @events) + + @new_resource = Chef::Resource::RegistryKey.new("windows is fun", @run_context) + @new_resource.key keyname + @new_resource.values( testval1 ) + @new_resource.recursive false + + @provider = Chef::Provider::RegistryKey.new(@new_resource, @run_context) + + allow(@provider).to receive(:running_on_windows!).and_return(true) + @double_registry = double(Chef::Win32::Registry) + allow(@provider).to receive(:registry).and_return(@double_registry) + end + context "when the key data is safe" do let(:keyname) { 'HKLM\Software\Opscode\Testing\Safe' } let(:testval1) { { :name => "one", :type => :string, :data => "1" } } @@ -292,4 +292,116 @@ describe Chef::Provider::RegistryKey do it_should_behave_like "a registry key" end + + describe "action_create" do + context "when key exists and type matches" do + let(:keyname) { 'hklm\\software\\opscode\\testing\\dword' } + let(:dword_passed_as_integer) { { :name => "one", :type => :dword, :data => 12345 } } + let(:testval1) { { :name => "one", :type => :dword, :data => "12345" } } + before do + expect(@double_registry).to receive(:key_exists?).twice.with(keyname).and_return(true) + end + + it "does not make a change for datatype of data value differing" do + expect(@double_registry).to receive(:get_values).with(keyname).and_return( dword_passed_as_integer ) + expect(@double_registry).not_to receive(:set_value) + @provider.load_current_resource + @provider.action_create + end + end + end +end + +describe Chef::Provider::RegistryKey, "key_missing?" do + let(:provider) { Chef::Provider::RegistryKey.new(nil, nil) } + let(:all_keys_present_in_all_hash) do + [ { :name => "input1_value1", :type => :string, :data => "my_value1" }, + { :name => "input1_value2", :type => :string, :data => "my_value2" }, + ] + end + let(:type_key_not_present_in_any_hash) do + [ { :name => "input2_value1", :data => "my_value1" }, + { :name => "input2_value2", :data => "my_value2" }, + ] + end + let(:type_key_not_present_in_some_hash) do + [ { :name => "input3_value1", :data => "my_value1" }, + { :name => "input3_value2", :type => :string, :data => "my_value2" }, + ] + end + let(:data_key_not_present_in_any_hash) do + [ { :name => "input4_value1", :type => :string }, + { :name => "input4_value2", :type => :string }, + ] + end + let(:data_key_not_present_in_some_hash) do + [ { :name => "input5_value1", :type => :string, :data => "my_value1" }, + { :name => "input5_value2", :type => :string }, + ] + end + let(:only_name_key_present_in_all_hash) do + [ { :name => "input6_value1" }, + { :name => "input6_value2" }, + ] + end + + context "type key" do + context "when type key is present in all the values hash of registry_key resource" do + it "returns false" do + response = provider.key_missing?(all_keys_present_in_all_hash, :type) + expect(response).to be == false + end + end + + context "when type key is not present in any of the values hash of registry_key resource" do + it "returns true" do + response = provider.key_missing?(type_key_not_present_in_any_hash, :type) + expect(response).to be == true + end + end + + context "when type key is not present only in some of the values hash of registry_key resource" do + it "returns true" do + response = provider.key_missing?(type_key_not_present_in_some_hash, :type) + expect(response).to be == true + end + end + + context "when only name key is present in all the values hash of registry_key resource" do + it "returns true" do + response = provider.key_missing?(only_name_key_present_in_all_hash, :type) + expect(response).to be == true + end + end + end + + context "data key" do + context "when data key is present in all the values hash of registry_key resource" do + it "returns false" do + response = provider.key_missing?(all_keys_present_in_all_hash, :data) + expect(response).to be == false + end + end + + context "when data key is not present in any of the values hash of registry_key resource" do + it "returns true" do + response = provider.key_missing?(data_key_not_present_in_any_hash, :data) + expect(response).to be == true + end + end + + context "when data key is not present only in some of the values hash of registry_key resource" do + it "returns true" do + response = provider.key_missing?(data_key_not_present_in_some_hash, :data) + expect(response).to be == true + end + end + + context "when only name key is present in all the values hash of registry_key resource" do + it "returns true" do + response = provider.key_missing?(only_name_key_present_in_all_hash, :data) + expect(response).to be == true + end + end + end end diff --git a/spec/unit/provider/remote_file/content_spec.rb b/spec/unit/provider/remote_file/content_spec.rb index c6a560b123..db9a75458d 100644 --- a/spec/unit/provider/remote_file/content_spec.rb +++ b/spec/unit/provider/remote_file/content_spec.rb @@ -180,6 +180,7 @@ describe Chef::Provider::RemoteFile::Content do Net::HTTPServerException, Net::HTTPFatalError, Net::FTPError, + Errno::ETIMEDOUT, ].each do |exception| describe "with an exception of #{exception}" do before do diff --git a/spec/unit/provider/user/dscl_spec.rb b/spec/unit/provider/user/dscl_spec.rb index dfaaa377d3..7b8be02f3a 100644 --- a/spec/unit/provider/user/dscl_spec.rb +++ b/spec/unit/provider/user/dscl_spec.rb @@ -219,6 +219,8 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30" end before do + Chef::Config[:treat_deprecation_warnings_as_errors] = false + Chef::Config[:treat_deprecation_warnings_as_errors] = false new_resource.supports({ :manage_home => true }) new_resource.home("/Users/toor") @@ -237,6 +239,7 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30" end it "moves the users home to the new location if it exists and the target location is different" do + Chef::Config[:treat_deprecation_warnings_as_errors] = false new_resource.supports(:manage_home => true) current_home = CHEF_SPEC_DATA + "/old_home_dir" @@ -856,6 +859,7 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30") describe "when Chef is removing the user" do it "removes the user from the groups and deletes home directory when the resource is configured to manage home" do + Chef::Config[:treat_deprecation_warnings_as_errors] = false new_resource.supports({ :manage_home => true }) expect(provider).to receive(:run_dscl).with("list /Groups").and_return("my_group\nyour_group\nreal_group\n") expect(provider).to receive(:run_dscl).with("read /Groups/my_group").and_raise(Chef::Exceptions::DsclCommandFailed) # Empty group diff --git a/spec/unit/provider/user/linux_spec.rb b/spec/unit/provider/user/linux_spec.rb index ac94592859..1c487c0de9 100644 --- a/spec/unit/provider/user/linux_spec.rb +++ b/spec/unit/provider/user/linux_spec.rb @@ -45,20 +45,50 @@ describe Chef::Provider::User::Linux do @current_resource = Chef::Resource::User::LinuxUser.new("adam", @run_context) end - it "sets supports manage_home to true" do - Chef::Config[:treat_deprecation_warnings_as_errors] = false - expect( @new_resource.supports[:manage_home] ).to be true + it "supports manage_home does not exist", chef: ">= 13" do + expect( @new_resource.supports.key?(:manage_home) ).to be false + end + + it "supports non_unique does not exist", chef: ">= 13" do + expect( @new_resource.supports.key?(:non_unique) ).to be false + end + + # supports is a method on the superclass so can't totally be removed, but we should aggressively NOP it to decisively break it + it "disables the supports API", chef: ">= 13" do + @new_resource.supports( { manage_home: true } ) + expect( @new_resource.supports.key?(:manage_home) ).to be false + end + + it "sets supports manage_home to false" do + expect( @new_resource.supports[:manage_home] ).to be false + end + + it "sets supports non-unique to false" do + expect( @new_resource.supports[:non_unique] ).to be false end - it "sets supports non-unique to true" do + it "throws a deprecation warning on setting supports[:manage_home]" do Chef::Config[:treat_deprecation_warnings_as_errors] = false - expect( @new_resource.supports[:non_unique] ).to be true + expect(Chef).to receive(:log_deprecation).with("supports { manage_home: true } on the user resource is deprecated and will be removed in Chef 13, set manage_home: true instead") + @new_resource.supports( { :manage_home => true } ) end - it "defaults manage_home to true" do + it "defaults manage_home to false" do expect( @new_resource.manage_home ).to be false end + it "supports[:manage_home] (incorectly) acts like manage_home" do + Chef::Config[:treat_deprecation_warnings_as_errors] = false + @new_resource.supports({ manage_home: true }) + expect( provider.useradd_options ).to eql(["-m"]) + end + + it "supports[:manage_home] does not change behavior of manage_home: false", chef: ">= 13" do + Chef::Config[:treat_deprecation_warnings_as_errors] = false + @new_resource.supports({ manage_home: true }) + expect( provider.useradd_options ).to eql(["-M"]) + end + it "by default manage_home is false and we use -M" do expect( provider.useradd_options ).to eql(["-M"]) end diff --git a/spec/unit/provider/user/pw_spec.rb b/spec/unit/provider/user/pw_spec.rb index 624bcfc67d..fb7c9211a1 100644 --- a/spec/unit/provider/user/pw_spec.rb +++ b/spec/unit/provider/user/pw_spec.rb @@ -32,6 +32,8 @@ describe Chef::Provider::User::Pw do @new_resource.shell "/usr/bin/zsh" @new_resource.password "abracadabra" + # XXX: rip out in Chef-13 + Chef::Config[:treat_deprecation_warnings_as_errors] = false @new_resource.supports :manage_home => true @current_resource = Chef::Resource::User::PwUser.new("adam") diff --git a/spec/unit/provider/user/solaris_spec.rb b/spec/unit/provider/user/solaris_spec.rb index 860c9e41dd..8a5e654a0d 100644 --- a/spec/unit/provider/user/solaris_spec.rb +++ b/spec/unit/provider/user/solaris_spec.rb @@ -29,26 +29,31 @@ describe Chef::Provider::User::Solaris do Struct.new(:stdout, :stderr, :exitstatus) end - subject(:provider) do - p = described_class.new(@new_resource, @run_context) - p.current_resource = @current_resource + let(:node) do + Chef::Node.new.tap do |node| + node.automatic["platform"] = "solaris2" + end + end + let(:events) { Chef::EventDispatch::Dispatcher.new } + let(:run_context) { Chef::RunContext.new(node, {}, events) } + let(:new_resource) do + Chef::Resource::User::SolarisUser.new("adam", @run_context) + end + let(:current_resource) do + Chef::Resource::User::SolarisUser.new("adam", @run_context) + end - # Prevent the useradd-based provider tests from trying to write /etc/shadow - allow(p).to receive(:write_shadow_file) - p + subject(:provider) do + described_class.new(new_resource, run_context).tap do |p| + p.current_resource = current_resource + # Prevent the useradd-based provider tests from trying to write /etc/shadow + allow(p).to receive(:write_shadow_file) + end end describe "when we want to set a password" do before(:each) do - @node = Chef::Node.new - @events = Chef::EventDispatch::Dispatcher.new - @run_context = Chef::RunContext.new(@node, {}, @events) - - @new_resource = Chef::Resource::User::SolarisUser.new("adam", @run_context) - @current_resource = Chef::Resource::User::SolarisUser.new("adam", @run_context) - - @new_resource.password "hocus-pocus" - + new_resource.password "hocus-pocus" end it "should use its own shadow file writer to set the password" do @@ -68,53 +73,60 @@ describe Chef::Provider::User::Solaris do # may not be able to write to /etc for tests... temp_file = Tempfile.new("shadow") allow(Tempfile).to receive(:new).with("shadow", "/etc").and_return(temp_file) - @new_resource.password "verysecurepassword" + new_resource.password "verysecurepassword" provider.manage_user expect(::File.open(password_file.path, "r").read).to match(/adam:verysecurepassword:/) password_file.unlink end end - describe "when managing user locked status" do - before(:each) do - @node = Chef::Node.new - @events = Chef::EventDispatch::Dispatcher.new - @run_context = Chef::RunContext.new(@node, {}, @events) - - @new_resource = Chef::Resource::User::SolarisUser.new("dave") - @current_resource = @new_resource.dup + describe "#create_user" do + context "with a system user" do + before { new_resource.system(true) } + it "should not pass -r" do + expect(provider).to receive(:shell_out!).with("useradd", "adam") + provider.create_user + end + end - @provider = Chef::Provider::User::Solaris.new(@new_resource, @run_context) - @provider.current_resource = @current_resource + context "with manage_home" do + before { new_resource.manage_home(true) } + it "should not pass -r" do + expect(provider).to receive(:shell_out!).with("useradd", "-m", "adam") + provider.create_user + end end + end + + describe "when managing user locked status" do describe "when determining if the user is locked" do # locked shadow lines [ - "dave:LK:::::::", - "dave:*LK*:::::::", - "dave:*LK*foobar:::::::", - "dave:*LK*bahamas10:::::::", - "dave:*LK*L....:::::::", + "adam:LK:::::::", + "adam:*LK*:::::::", + "adam:*LK*foobar:::::::", + "adam:*LK*bahamas10:::::::", + "adam:*LK*L....:::::::", ].each do |shadow| it "should return true if user is locked with #{shadow}" do shell_return = shellcmdresult.new(shadow + "\n", "", 0) - expect(provider).to receive(:shell_out!).with("getent", "shadow", @new_resource.username).and_return(shell_return) + expect(provider).to receive(:shell_out!).with("getent", "shadow", "adam").and_return(shell_return) expect(provider.check_lock).to eql(true) end end # unlocked shadow lines [ - "dave:NP:::::::", - "dave:*NP*:::::::", - "dave:foobar:::::::", - "dave:bahamas10:::::::", - "dave:L...:::::::", + "adam:NP:::::::", + "adam:*NP*:::::::", + "adam:foobar:::::::", + "adam:bahamas10:::::::", + "adam:L...:::::::", ].each do |shadow| it "should return false if user is unlocked with #{shadow}" do shell_return = shellcmdresult.new(shadow + "\n", "", 0) - expect(provider).to receive(:shell_out!).with("getent", "shadow", @new_resource.username).and_return(shell_return) + expect(provider).to receive(:shell_out!).with("getent", "shadow", "adam").and_return(shell_return) expect(provider.check_lock).to eql(false) end end @@ -123,7 +135,7 @@ describe Chef::Provider::User::Solaris do describe "when locking the user" do it "should run passwd -l with the new resources username" do shell_return = shellcmdresult.new("", "", 0) - expect(provider).to receive(:shell_out!).with("passwd", "-l", @new_resource.username).and_return(shell_return) + expect(provider).to receive(:shell_out!).with("passwd", "-l", "adam").and_return(shell_return) provider.lock_user end end @@ -131,7 +143,7 @@ describe Chef::Provider::User::Solaris do describe "when unlocking the user" do it "should run passwd -u with the new resources username" do shell_return = shellcmdresult.new("", "", 0) - expect(provider).to receive(:shell_out!).with("passwd", "-u", @new_resource.username).and_return(shell_return) + expect(provider).to receive(:shell_out!).with("passwd", "-u", "adam").and_return(shell_return) provider.unlock_user end end diff --git a/spec/unit/resource/apt_update_spec.rb b/spec/unit/resource/apt_update_spec.rb index dd72b18063..a7d2c64fee 100644 --- a/spec/unit/resource/apt_update_spec.rb +++ b/spec/unit/resource/apt_update_spec.rb @@ -24,27 +24,35 @@ describe Chef::Resource::AptUpdate do let(:run_context) { Chef::RunContext.new(node, {}, events) } let(:resource) { Chef::Resource::AptUpdate.new("update", run_context) } - it "should create a new Chef::Resource::AptUpdate" do - expect(resource).to be_a_kind_of(Chef::Resource) - expect(resource).to be_a_kind_of(Chef::Resource::AptUpdate) - end + context "on linux", :linux_only do + it "should create a new Chef::Resource::AptUpdate" do + expect(resource).to be_a_kind_of(Chef::Resource) + expect(resource).to be_a_kind_of(Chef::Resource::AptUpdate) + end - it "the default frequency should be 1 day" do - expect(resource.frequency).to eql(86_400) - end + it "the default frequency should be 1 day" do + expect(resource.frequency).to eql(86_400) + end - it "the frequency should accept integers" do - resource.frequency(400) - expect(resource.frequency).to eql(400) - end + it "the frequency should accept integers" do + resource.frequency(400) + expect(resource.frequency).to eql(400) + end + + it "should resolve to a Noop class when apt-get is not found" do + expect(Chef::Provider::AptUpdate).to receive(:which).with("apt-get").and_return(false) + expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop) + end - it "should resolve to a Noop class when apt-get is not found" do - expect(Chef::Provider::AptUpdate).to receive(:which).with("apt-get").and_return(false) - expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop) + it "should resolve to a AptUpdate class when apt-get is found" do + expect(Chef::Provider::AptUpdate).to receive(:which).with("apt-get").and_return(true) + expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::AptUpdate) + end end - it "should resolve to a AptUpdate class when apt-get is found" do - expect(Chef::Provider::AptUpdate).to receive(:which).with("apt-get").and_return(true) - expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::AptUpdate) + 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) + end end end diff --git a/spec/unit/resource/cab_package_spec.rb b/spec/unit/resource/cab_package_spec.rb new file mode 100644 index 0000000000..aa4890f171 --- /dev/null +++ b/spec/unit/resource/cab_package_spec.rb @@ -0,0 +1,38 @@ +# +# Author:: Vasundhara Jagdale (<vasundhara.jagdale@msystechnologies.com>) +# Copyright:: Copyright 2008-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" + +describe Chef::Resource::CabPackage do + + let(:resource) { Chef::Resource::CabPackage.new("test_pkg") } + + it "creates a new Chef::Resource::CabPackage" do + expect(resource).to be_a_kind_of(Chef::Resource) + expect(resource).to be_a_kind_of(Chef::Resource::Package) + expect(resource).to be_a_instance_of(Chef::Resource::CabPackage) + end + + it "sets resource name as :cab_package" do + expect(resource.resource_name).to eql(:cab_package) + end + + it "coerce its name to a package_name" do + expect(resource.package_name).to eql("test_pkg") + end +end diff --git a/spec/unit/resource/registry_key_spec.rb b/spec/unit/resource/registry_key_spec.rb index 472c511857..d378da3ed0 100644 --- a/spec/unit/resource/registry_key_spec.rb +++ b/spec/unit/resource/registry_key_spec.rb @@ -94,19 +94,11 @@ describe Chef::Resource::RegistryKey, "values" do expect(@resource.values).to eql([ { :name => "poosh", :type => :binary, :data => "a8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb89" } ]) end - it "should throw an exception if the name field is missing" do + it "should raise an exception if the name field is missing" do expect { @resource.values [ { :type => :string, :data => "carmen" } ] }.to raise_error(ArgumentError) end - it "should throw an exception if the type field is missing" do - expect { @resource.values [ { :name => "poosh", :data => "carmen" } ] }.to raise_error(ArgumentError) - end - - it "should throw an exception if the data field is missing" do - expect { @resource.values [ { :name => "poosh", :type => :string } ] }.to raise_error(ArgumentError) - end - - it "should throw an exception if extra fields are present" do + it "should raise an exception if extra fields are present" do expect { @resource.values [ { :name => "poosh", :type => :string, :data => "carmen", :screwdriver => "sonic" } ] }.to raise_error(ArgumentError) end @@ -117,6 +109,30 @@ describe Chef::Resource::RegistryKey, "values" do it "should not allow an integer" do expect { @resource.send(:values, 100) }.to raise_error(ArgumentError) end + + it "should raise an exception if type of name is not string" do + expect { @resource.values([ { :name => 123, :type => :string, :data => "carmen" } ]) }.to raise_error(ArgumentError) + end + + it "should not raise an exception if type of name is string" do + expect { @resource.values([ { :name => "123", :type => :string, :data => "carmen" } ]) }.to_not raise_error + end + + context "type key not given" do + it "should not raise an exception" do + expect { @resource.values([ { :name => "123", :data => "carmen" } ]) }.to_not raise_error + end + end + + context "type key given" do + it "should raise an exception if type of type is not symbol" do + expect { @resource.values([ { :name => "123", :type => "string", :data => "carmen" } ]) }.to raise_error(ArgumentError) + end + + it "should not raise an exception if type of type is symbol" do + expect { @resource.values([ { :name => "123", :type => :string, :data => "carmen" } ]) }.to_not raise_error + end + end end describe Chef::Resource::RegistryKey, "recursive" do diff --git a/spec/unit/server_api_spec.rb b/spec/unit/server_api_spec.rb new file mode 100644 index 0000000000..05d2a28ed4 --- /dev/null +++ b/spec/unit/server_api_spec.rb @@ -0,0 +1,50 @@ +require "spec_helper" + +SIGNING_KEY_DOT_PEM = "-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA49TA0y81ps0zxkOpmf5V4/c4IeR5yVyQFpX3JpxO4TquwnRh +8VSUhrw8kkTLmB3cS39Db+3HadvhoqCEbqPE6915kXSuk/cWIcNozujLK7tkuPEy +YVsyTioQAddSdfe+8EhQVf3oHxaKmUd6waXrWqYCnhxgOjxocenREYNhZ/OETIei +PbOku47vB4nJK/0GhKBytL2XnsRgfKgDxf42BqAi1jglIdeq8lAWZNF9TbNBU21A +O1iuT7Pm6LyQujhggPznR5FJhXKRUARXBJZawxpGV4dGtdcahwXNE4601aXPra+x +PcRd2puCNoEDBzgVuTSsLYeKBDMSfs173W1QYwIDAQABAoIBAGF05q7vqOGbMaSD +2Q7YbuE/JTHKTBZIlBI1QC2x+0P5GDxyEFttNMOVzcs7xmNhkpRw8eX1LrInrpMk +WsIBKAFFEfWYlf0RWtRChJjNl+szE9jQxB5FJnWtJH/FHa78tR6PsF24aQyzVcJP +g0FGujBihwgfV0JSCNOBkz8MliQihjQA2i8PGGmo4R4RVzGfxYKTIq9vvRq/+QEa +Q4lpVLoBqnENpnY/9PTl6JMMjW2b0spbLjOPVwDaIzXJ0dChjNXo15K5SHI5mALJ +I5gN7ODGb8PKUf4619ez194FXq+eob5YJdilTFKensIUvt3YhP1ilGMM+Chi5Vi/ +/RCTw3ECgYEA9jTw4wv9pCswZ9wbzTaBj9yZS3YXspGg26y6Ohq3ZmvHz4jlT6uR +xK+DDcUiK4072gci8S4Np0fIVS7q6ivqcOdzXPrTF5/j+MufS32UrBbUTPiM1yoO +ECcy+1szl/KoLEV09bghPbvC58PFSXV71evkaTETYnA/F6RK12lEepcCgYEA7OSy +bsMrGDVU/MKJtwqyGP9ubA53BorM4Pp9VVVSCrGGVhb9G/XNsjO5wJC8J30QAo4A +s59ZzCpyNRy046AB8jwRQuSwEQbejSdeNgQGXhZ7aIVUtuDeFFdaIz/zjVgxsfj4 +DPOuzieMmJ2MLR4F71ocboxNoDI7xruPSE8dDhUCgYA3vx732cQxgtHwAkeNPJUz +dLiE/JU7CnxIoSB9fYUfPLI+THnXgzp7NV5QJN2qzMzLfigsQcg3oyo6F2h7Yzwv +GkjlualIRRzCPaCw4Btkp7qkPvbs1QngIHALt8fD1N69P3DPHkTwjG4COjKWgnJq +qoHKS6Fe/ZlbigikI6KsuwKBgQCTlSLoyGRHr6oj0hqz01EDK9ciMJzMkZp0Kvn8 +OKxlBxYW+jlzut4MQBdgNYtS2qInxUoAnaz2+hauqhSzntK3k955GznpUatCqx0R +b857vWviwPX2/P6+E3GPdl8IVsKXCvGWOBZWTuNTjQtwbDzsUepWoMgXnlQJSn5I +YSlLxQKBgQD16Gw9kajpKlzsPa6XoQeGmZALT6aKWJQlrKtUQIrsIWM0Z6eFtX12 +2jjHZ0awuCQ4ldqwl8IfRogWMBkHOXjTPVK0YKWWlxMpD/5+bGPARa5fir8O1Zpo +Y6S6MeZ69Rp89ma4ttMZ+kwi1+XyHqC/dlcVRW42Zl5Dc7BALRlJjQ== +-----END RSA PRIVATE KEY-----" + +describe Chef::ServerAPI do + let(:url) { "http://chef.example.com:4000" } + let(:key_path) { "/tmp/foo" } + + describe "#initialize" do + it "uses the configured key file" do + allow(IO).to receive(:read).with(key_path).and_return(SIGNING_KEY_DOT_PEM) + Chef::Config[:client_key] = key_path + + api = described_class.new(url) + expect(api.options[:signing_key_filename]).to eql(key_path) + end + + it "allows a user to set a raw_key" do + api = described_class.new(url, raw_key: SIGNING_KEY_DOT_PEM) + expect(api.options[:signing_key_filename]).to be_nil + expect(api.options[:raw_key]).to eql(SIGNING_KEY_DOT_PEM) + 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 45fe8df40d..3f1210dbf1 100644 --- a/spec/unit/util/dsc/local_configuration_manager_spec.rb +++ b/spec/unit/util/dsc/local_configuration_manager_spec.rb @@ -59,10 +59,6 @@ EOH allow(lcm).to receive(:run_configuration_cmdlet).and_return(lcm_status) end context "that returns successfully" do - before(:each) do - allow(lcm).to receive(:run_configuration_cmdlet).and_return(lcm_status) - end - let(:lcm_standard_output) { normal_lcm_output } let(:lcm_standard_error) { nil } let(:lcm_cmdlet_success) { true } @@ -138,4 +134,14 @@ EOH expect(lcm.send(:dsc_module_import_failure?, dsc_resource_import_failure_output.gsub("CimException", "ArgumentException"))).to be(false) end end + + describe "#run_configuration_cmdlet" do + context "when invalid dsc script is given" do + it "raises exception" do + configuration_document = "invalid-config" + shellout_flags = { :cwd => nil, :environment => nil, :timeout => nil } + expect { lcm.send(:run_configuration_cmdlet, configuration_document, true, shellout_flags) }.to raise_error(Chef::Exceptions::PowershellCmdletException) + end + end + end end |