diff options
Diffstat (limited to 'spec/unit')
-rw-r--r-- | spec/unit/application/client_spec.rb | 50 | ||||
-rw-r--r-- | spec/unit/policy_builder/policyfile_spec.rb | 76 | ||||
-rw-r--r-- | spec/unit/provider/apt_repository_spec.rb | 139 | ||||
-rw-r--r-- | spec/unit/resource/portage_package_spec.rb | 6 | ||||
-rw-r--r-- | spec/unit/resource/registry_key_spec.rb | 6 | ||||
-rw-r--r-- | spec/unit/resource/windows_feature.rb | 41 | ||||
-rw-r--r-- | spec/unit/resource/windows_feature_dism.rb | 41 | ||||
-rw-r--r-- | spec/unit/resource/windows_feature_powershell.rb | 41 | ||||
-rw-r--r-- | spec/unit/resource_inspector_spec.rb | 60 |
9 files changed, 409 insertions, 51 deletions
diff --git a/spec/unit/application/client_spec.rb b/spec/unit/application/client_spec.rb index 3f803f2033..0cd3cb3995 100644 --- a/spec/unit/application/client_spec.rb +++ b/spec/unit/application/client_spec.rb @@ -107,6 +107,7 @@ describe Chef::Application::Client, "reconfigure" do shared_examples "sets the configuration" do |cli_arguments, expected_config| describe cli_arguments do before do + cli_arguments ||= "" ARGV.replace(cli_arguments.split) app.reconfigure end @@ -144,6 +145,36 @@ describe Chef::Application::Client, "reconfigure" do end end + describe "--[no]-fork" do + before do + Chef::Config[:interval] = nil # FIXME: we're overriding the before block setting this + end + + context "by default" do + it_behaves_like "sets the configuration", "", client_fork: false + end + + context "with --fork" do + it_behaves_like "sets the configuration", "--fork", client_fork: true + end + + context "with --no-fork" do + it_behaves_like "sets the configuration", "--no-fork", client_fork: false + end + + context "with an interval" do + it_behaves_like "sets the configuration", "--interval 1800", client_fork: true + end + + context "with once" do + it_behaves_like "sets the configuration", "--once", client_fork: false + end + + context "with daemonize", :unix_only do + it_behaves_like "sets the configuration", "--daemonize", client_fork: true + end + end + describe "--config-option" do context "with a single value" do it_behaves_like "sets the configuration", "--config-option chef_server_url=http://example", @@ -186,21 +217,16 @@ describe Chef::Application::Client, "reconfigure" do Chef::Config[:splay] = nil end - context "when interval is given" do - before do - Chef::Config[:interval] = 600 - allow(ChefConfig).to receive(:windows?).and_return(false) - end - - it "should terminate with message" do - expect(Chef::Application).to receive(:fatal!).with( -"Unforked chef-client interval runs are disabled in Chef 12. + it "should terminal with message when interval is given" do + Chef::Config[:interval] = 600 + allow(ChefConfig).to receive(:windows?).and_return(false) + expect(Chef::Application).to receive(:fatal!).with( + "Unforked chef-client interval runs are disabled in Chef 12. Configuration settings: interval = 600 seconds Enable chef-client interval runs by setting `:client_fork = true` in your config file or adding `--fork` to your command line options." - ) - app.reconfigure - end + ) + app.reconfigure end context "when interval is given on windows" do diff --git a/spec/unit/policy_builder/policyfile_spec.rb b/spec/unit/policy_builder/policyfile_spec.rb index 466d0f970b..b8cf56750d 100644 --- a/spec/unit/policy_builder/policyfile_spec.rb +++ b/spec/unit/policy_builder/policyfile_spec.rb @@ -70,8 +70,44 @@ describe Chef::PolicyBuilder::Policyfile do } end - let(:policyfile_default_attributes) { { "policyfile_default_attr" => "policyfile_default_value" } } - let(:policyfile_override_attributes) { { "policyfile_override_attr" => "policyfile_override_value" } } + let(:policyfile_default_attributes) do + { + "policyfile_default_attr" => "policyfile_default_value", + "top_level_attr" => "hat", + "baseline_attr" => { + "one" => 1, + "two" => 2, + "deep" => { + "three" => 3, + "four" => [4], + "five" => [5], + }, + }, + "policy_group_value" => { + "baseline_attr" => { + "one" => 111, + }, + }, + } + end + + let(:policyfile_override_attributes) do + { + "policyfile_override_attr" => "policyfile_override_value", + "baseline_attr" => { + "deep" => { + "three" => 333 }, + }, + "policy_group_value" => { + "top_level_attr" => "cat", + "baseline_attr" => { + "deep" => { + "four" => [444], + }, + }, + }, + } + end let(:policyfile_run_list) { ["recipe[example1::default]", "recipe[example2::server]"] } @@ -636,6 +672,42 @@ describe Chef::PolicyBuilder::Policyfile do end end + + describe "hoisting attribute values" do + context "with no policy group set" do + it "does not hoist policy_group specific attributes" do + expect( node["top_level_attr"] ).to eql("hat") + expect( node["baseline_attr"]["one"] ).to eql(1) + expect( node["baseline_attr"]["two"] ).to eql(2) + expect( node["baseline_attr"]["deep"]["three"] ).to eql(333) + expect( node["baseline_attr"]["deep"]["four"] ).to eql([4]) + expect( node["baseline_attr"]["deep"]["five"] ).to eql([5]) + end + end + + context "with a policy group set" do + before do + Chef::Config[:policy_group] = "policy_group_value" + policy_builder.finish_load_node(node) + policy_builder.build_node + end + + it "hoists default attributes" do + expect( node["top_level_attr"] ).to eql("cat") + expect( node["baseline_attr"]["one"]).to eql(111) + expect( node["baseline_attr"]["two"] ).to eql(2) + expect( node["baseline_attr"]["deep"]["five"] ).to eql([5]) + end + + it "hoists override attributes" do + expect( node["top_level_attr"] ).to eql("cat") + expect( node["baseline_attr"]["two"] ).to eql(2) + expect( node["baseline_attr"]["deep"]["three"] ).to eql(333) + expect( node["baseline_attr"]["deep"]["four"] ).to eql([444]) + expect( node["baseline_attr"]["deep"]["five"] ).to eql([5]) + end + end + end end describe "fetching the desired cookbook set" do diff --git a/spec/unit/provider/apt_repository_spec.rb b/spec/unit/provider/apt_repository_spec.rb index cabf6551c9..ca85831a06 100644 --- a/spec/unit/provider/apt_repository_spec.rb +++ b/spec/unit/provider/apt_repository_spec.rb @@ -47,7 +47,6 @@ EOF describe Chef::Provider::AptRepository do let(:new_resource) { Chef::Resource::AptRepository.new("multiverse") } - let(:shellout_env) { { env: { "LANG" => "en_US", "LANGUAGE" => "en_US" } } } let(:provider) do node = Chef::Node.new events = Chef::EventDispatch::Dispatcher.new @@ -60,15 +59,22 @@ describe Chef::Provider::AptRepository do end let(:apt_key_finger) do - r = double("Mixlib::ShellOut", stdout: APT_KEY_FINGER, exitstatus: 0, live_stream: true) - allow(r).to receive(:run_command) - r + double("shell_out", stdout: APT_KEY_FINGER, exitstatus: 0, error?: false) end let(:gpg_finger) do - r = double("Mixlib::ShellOut", stdout: GPG_FINGER, exitstatus: 0, live_stream: true) - allow(r).to receive(:run_command) - r + double("shell_out", stdout: GPG_FINGER, exitstatus: 0, error?: false) + end + + let(:gpg_shell_out_success) do + double("shell_out", :stdout => "pub 2048R/7BD9BF62 2011-08-19 nginx signing key <signing-key@nginx.com>", + :exitstatus => 0, :error? => false) + end + + let(:gpg_shell_out_failure) do + double("shell_out", :stderr => "gpg: no valid OpenPGP data found.\n + gpg: processing message failed: eof", + :exitstatus => 1, :error? => true) end let(:apt_fingerprints) do @@ -83,35 +89,39 @@ C5986B4F1257FFA86632CBA746181433FBB75451 end describe "#is_key_id?" do - it "should detect a key" do + it "detects a key" do expect(provider.is_key_id?("A4FF2279")).to be_truthy end - it "should detect a key with a hex signifier" do + it "detects a key with a hex signifier" do expect(provider.is_key_id?("0xA4FF2279")).to be_truthy end - it "should reject a key with the wrong length" do + it "rejects a key with the wrong length" do expect(provider.is_key_id?("4FF2279")).to be_falsey end - it "should reject a key with non-hex characters" do + it "rejects a key with non-hex characters" do expect(provider.is_key_id?("A4KF2279")).to be_falsey end end describe "#extract_fingerprints_from_cmd" do - before do - expect(Mixlib::ShellOut).to receive(:new).and_return(apt_key_finger) - end - - it "should run the desired command" do - expect(apt_key_finger).to receive(:run_command) + it "runs the desired command" do + expect(provider).to receive(:shell_out).and_return(apt_key_finger) provider.extract_fingerprints_from_cmd(apt_key_finger_cmd) end - it "should return a list of key fingerprints" do + it "returns a list of key fingerprints" do + expect(provider).to receive(:shell_out).and_return(apt_key_finger) expect(provider.extract_fingerprints_from_cmd(apt_key_finger_cmd)).to eql(apt_fingerprints) 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 "#no_new_keys?" do before do allow(provider).to receive(:extract_fingerprints_from_cmd).with(apt_key_finger_cmd).and_return(apt_fingerprints) @@ -119,14 +129,14 @@ C5986B4F1257FFA86632CBA746181433FBB75451 let(:file) { "/tmp/remote-gpg-keyfile" } - it "should match a set of keys" do + it "matches a set of keys" do allow(provider).to receive(:extract_fingerprints_from_cmd) .with("gpg --with-fingerprint --with-colons #{file}") .and_return(Array(apt_fingerprints.first)) expect(provider.no_new_keys?(file)).to be_truthy end - it "should notice missing keys" do + it "notices missing keys" do allow(provider).to receive(:extract_fingerprints_from_cmd) .with("gpg --with-fingerprint --with-colons #{file}") .and_return(%w{ F36A89E33CC1BD0F71079007327574EE02A818DD }) @@ -134,11 +144,71 @@ C5986B4F1257FFA86632CBA746181433FBB75451 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/bar.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/bar.key") }.to raise_error(Chef::Exceptions::FileNotFound) + end + end + + describe "#keyserver_install_cmd" do + it "returns keyserver install command" do + expect(provider.keyserver_install_cmd("ABC", "gpg.mit.edu")).to eq("apt-key adv --recv --keyserver hkp://gpg.mit.edu:80 ABC") + end + + it "uses proxy if key_proxy property is set" do + new_resource.key_proxy("proxy.mycorp.dmz:3128") + expect(provider.keyserver_install_cmd("ABC", "gpg.mit.edu")).to eq("apt-key adv --recv --keyserver-options http-proxy=proxy.mycorp.dmz:3128 --keyserver hkp://gpg.mit.edu:80 ABC") + end + + it "properly handles keyservers passed with hkp:// URIs" do + expect(provider.keyserver_install_cmd("ABC", "hkp://gpg.mit.edu")).to eq("apt-key adv --recv --keyserver hkp://gpg.mit.edu ABC") + end + end + + describe "#is_ppa_url" do + it "returns true if the URL starts with ppa:" do + expect(provider.is_ppa_url?("ppa://example.com")).to be_truthy + end + + it "returns false if the URL does not start with ppa:" do + expect(provider.is_ppa_url?("example.com")).to be_falsey + end + end + + describe "#repo_components" do + it "returns 'main' if a PPA and components property not set" do + expect(provider).to receive(:is_ppa_url?).and_return(true) + expect(provider.repo_components).to eq("main") + end + + it "returns components property if a PPA and components is set" do + new_resource.components(["foo"]) + expect(provider).to receive(:is_ppa_url?).and_return(true) + expect(provider.repo_components).to eq(["foo"]) + end + + it "returns components property if not a PPA" do + new_resource.components(["foo"]) + expect(provider).to receive(:is_ppa_url?).and_return(false) + expect(provider.repo_components).to eq(["foo"]) + end + end + describe "#install_ppa_key" do let(:url) { "https://launchpad.net/api/1.0/~chef/+archive/main" } let(:key) { "C5986B4F1257FFA86632CBA746181433FBB75451" } - it "should get a key" do + it "gets a key" do simples = double("HTTP") allow(simples).to receive(:get).and_return("\"#{key}\"") expect(Chef::HTTP::Simple).to receive(:new).with(url).and_return(simples) @@ -148,42 +218,49 @@ C5986B4F1257FFA86632CBA746181433FBB75451 end describe "#make_ppa_url" do - it "should ignore non-ppa repositories" do - expect(provider.make_ppa_url("some_string")).to be_nil - end - - it "should create a URL" do + it "creates a URL" do expect(provider).to receive(:install_ppa_key).with("chef", "main").and_return(true) expect(provider.make_ppa_url("ppa:chef/main")).to eql("http://ppa.launchpad.net/chef/main/ubuntu") end end describe "#build_repo" do - it "should create a repository string" do + it "creates a repository string" do target = %Q{deb "http://test/uri" unstable main\n} expect(provider.build_repo("http://test/uri", "unstable", "main", false, nil)).to eql(target) end - it "should create a repository string with no distribution" do + it "creates a repository string with no distribution" do target = %Q{deb "http://test/uri" main\n} expect(provider.build_repo("http://test/uri", nil, "main", false, nil)).to eql(target) end - it "should create a repository string with source" do + it "creates a repository string with source" do target = %Q{deb "http://test/uri" unstable main\ndeb-src "http://test/uri" unstable main\n} expect(provider.build_repo("http://test/uri", "unstable", "main", false, nil, true)).to eql(target) end - it "should create a repository string with options" do + it "creates a repository string with options" do target = %Q{deb [trusted=yes] "http://test/uri" unstable main\n} expect(provider.build_repo("http://test/uri", "unstable", "main", true, nil)).to eql(target) end - it "should handle a ppa repo" do + it "handles a ppa repo" do target = %Q{deb "http://ppa.launchpad.net/chef/main/ubuntu" unstable main\n} expect(provider).to receive(:make_ppa_url).with("ppa:chef/main").and_return("http://ppa.launchpad.net/chef/main/ubuntu") expect(provider.build_repo("ppa:chef/main", "unstable", "main", false, nil)).to eql(target) end end + describe "#keyfile_is_invalid?" do + it "returns true if the file is invalid" do + expect(provider).to receive(:shell_out).and_return(gpg_shell_out_failure) + expect(provider.keyfile_is_invalid?("/foo/bar.key")).to be_truthy + end + + it "returns false if the file is valid" do + expect(provider).to receive(:shell_out).and_return(gpg_shell_out_success) + expect(provider.keyfile_is_invalid?("/foo/bar.key")).to be_falsey + end + end end diff --git a/spec/unit/resource/portage_package_spec.rb b/spec/unit/resource/portage_package_spec.rb index 02a7aef39a..a37cfd6e41 100644 --- a/spec/unit/resource/portage_package_spec.rb +++ b/spec/unit/resource/portage_package_spec.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,8 +29,4 @@ describe Chef::Resource::PortagePackage, "initialize" do it "sets the resource_name to :portage_package" do expect(resource.resource_name).to eql(:portage_package) end - - it "sets the provider to Chef::Provider::Package::Portage" do - expect(resource.provider).to eql(Chef::Provider::Package::Portage) - end end diff --git a/spec/unit/resource/registry_key_spec.rb b/spec/unit/resource/registry_key_spec.rb index 07ad4f820b..d8eea74ed4 100644 --- a/spec/unit/resource/registry_key_spec.rb +++ b/spec/unit/resource/registry_key_spec.rb @@ -25,7 +25,7 @@ describe Chef::Resource::RegistryKey, "initialize" do expect(resource.resource_name).to eql(:registry_key) end - it "sets the key equal to the argument to initialize" do + it "sets the key property to the resource name" do expect(resource.key).to eql('HKCU\Software\Raxicoricofallapatorius') end @@ -159,6 +159,10 @@ describe Chef::Resource::RegistryKey, "architecture" do end end + it "does not allow other symbols" do + expect { resource.architecture(:nope) }.to raise_error(ArgumentError) + end + it "does not allow a hash" do expect { resource.architecture({ :sonic => :screwdriver }) }.to raise_error(ArgumentError) end diff --git a/spec/unit/resource/windows_feature.rb b/spec/unit/resource/windows_feature.rb new file mode 100644 index 0000000000..c8b8587ed8 --- /dev/null +++ b/spec/unit/resource/windows_feature.rb @@ -0,0 +1,41 @@ +# +# Copyright:: Copyright 2018, 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::WindowsFeature do + let(:resource) { Chef::Resource::WindowsFeature.new("SNMP") } + + it "sets resource name as :windows_feature" do + expect(resource.resource_name).to eql(:windows_feature) + end + + it "sets the default action as :install" do + expect(resource.action).to eql([:install]) + end + + it "sets the feature_name property as its name" do + expect(resource.feature_name).to eql("SNMP") + end + + it "supports :install, :remove, and :delete actions" do + expect { resource.action :install }.not_to raise_error + expect { resource.action :remove }.not_to raise_error + expect { resource.action :delete }.not_to raise_error + expect { resource.action :update }.to raise_error(ArgumentError) + end +end diff --git a/spec/unit/resource/windows_feature_dism.rb b/spec/unit/resource/windows_feature_dism.rb new file mode 100644 index 0000000000..3885f4813e --- /dev/null +++ b/spec/unit/resource/windows_feature_dism.rb @@ -0,0 +1,41 @@ +# +# Copyright:: Copyright 2018, 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::WindowsFeatureDism do + let(:resource) { Chef::Resource::WindowsFeatureDism.new("SNMP") } + + it "sets resource name as :windows_feature_dism" do + expect(resource.resource_name).to eql(:windows_feature_dism) + end + + it "sets the default action as :install" do + expect(resource.action).to eql([:install]) + end + + it "sets the feature_name property as its name and coerces it to an array" do + expect(resource.feature_name).to eql(["SNMP"]) + end + + it "supports :install, :remove, and :delete actions" do + expect { resource.action :install }.not_to raise_error + expect { resource.action :remove }.not_to raise_error + expect { resource.action :delete }.not_to raise_error + expect { resource.action :update }.to raise_error(ArgumentError) + end +end diff --git a/spec/unit/resource/windows_feature_powershell.rb b/spec/unit/resource/windows_feature_powershell.rb new file mode 100644 index 0000000000..02f308ca73 --- /dev/null +++ b/spec/unit/resource/windows_feature_powershell.rb @@ -0,0 +1,41 @@ +# +# Copyright:: Copyright 2018, 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::WindowsFeaturePowershell do + let(:resource) { Chef::Resource::WindowsFeaturePowershell.new("SNMP") } + + it "sets resource name as :windows_feature_powershell" do + expect(resource.resource_name).to eql(:windows_feature_powershell) + end + + it "sets the default action as :install" do + expect(resource.action).to eql([:install]) + end + + it "sets the feature_name property as its name and coerces it to an array" do + expect(resource.feature_name).to eql(["SNMP"]) + end + + it "supports :install, :remove, and :delete actions" do + expect { resource.action :install }.not_to raise_error + expect { resource.action :remove }.not_to raise_error + expect { resource.action :delete }.not_to raise_error + expect { resource.action :update }.to raise_error(ArgumentError) + end +end diff --git a/spec/unit/resource_inspector_spec.rb b/spec/unit/resource_inspector_spec.rb new file mode 100644 index 0000000000..2cb9c0bb65 --- /dev/null +++ b/spec/unit/resource_inspector_spec.rb @@ -0,0 +1,60 @@ +# Copyright:: Copyright 2018, 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 "chef/resource_inspector" + +class DummyResource < Chef::Resource + resource_name :dummy + description "A dummy resource" + examples <<~EOH + dummy "foo" do + first "yes" + end + EOH + introduced "14.0" + property :first, String, description: "My First Property", introduced: "14.0" + + action :dummy do + return true + end +end + +describe ResourceInspector do + describe "inspecting a resource" do + subject { ResourceInspector.extract_resource(DummyResource, false) } + + it "returns a hash with required data" do + expect(subject[:description]).to eq "A dummy resource" + expect(subject[:actions]).to match_array [:nothing, :dummy] + end + + context "excluding built in properties" do + it "returns a single property" do + expect(subject[:properties].count).to eq 1 + expect(subject[:properties].first[:name]).to eq :first + end + end + + context "including built in properties" do + subject { ResourceInspector.extract_resource(DummyResource, true) } + it "returns many properties" do + expect(subject[:properties].count).to be > 1 + expect(subject[:properties].map { |n| n[:name] }).to include(:name, :first, :sensitive) + end + end + end +end |