summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorsawanoboly <sawanoboriyu@higanworks.com>2014-08-04 15:03:02 +0900
committersawanoboly <sawanoboriyu@higanworks.com>2014-08-04 15:03:02 +0900
commite717a8a050f1e7d0b8419b1a058b98f4f9ef294f (patch)
tree35169e6630451a0f74f2dc89d3a68df6bf5ed9b6 /spec
parente2d090be774b1c2e18c4864884588e29ec2bc3bb (diff)
parent930d12091511aa2d547366796ea49f4e26f18253 (diff)
downloadchef-e717a8a050f1e7d0b8419b1a058b98f4f9ef294f.tar.gz
Merge remote-tracking branch 'upstream/master' into use_shared_path_for_deploy_resource
Diffstat (limited to 'spec')
-rw-r--r--spec/functional/resource/base.rb10
-rw-r--r--spec/functional/resource/cookbook_file_spec.rb2
-rw-r--r--spec/functional/resource/package_spec.rb4
-rw-r--r--spec/functional/resource/remote_directory_spec.rb2
-rw-r--r--spec/functional/resource/template_spec.rb2
-rw-r--r--spec/integration/knife/chef_fs_data_store_spec.rb4
-rw-r--r--spec/support/platform_helpers.rb5
-rw-r--r--spec/unit/cookbook/file_vendor_spec.rb78
-rw-r--r--spec/unit/cookbook/synchronizer_spec.rb667
-rw-r--r--spec/unit/cookbook_uploader_spec.rb160
-rw-r--r--spec/unit/dsl/recipe_spec.rb12
-rw-r--r--spec/unit/formatters/base_spec.rb48
-rw-r--r--spec/unit/http/json_input_spec.rb128
-rw-r--r--spec/unit/knife/client_create_spec.rb6
-rw-r--r--spec/unit/knife/configure_client_spec.rb11
-rw-r--r--spec/unit/knife/cookbook_delete_spec.rb2
-rw-r--r--spec/unit/knife/cookbook_download_spec.rb10
-rw-r--r--spec/unit/knife/cookbook_metadata_spec.rb2
-rw-r--r--spec/unit/knife/cookbook_site_download_spec.rb20
-rw-r--r--spec/unit/knife/cookbook_site_share_spec.rb4
-rw-r--r--spec/unit/knife/cookbook_upload_spec.rb5
-rw-r--r--spec/unit/knife/tag_create_spec.rb6
-rw-r--r--spec/unit/knife/tag_delete_spec.rb6
-rw-r--r--spec/unit/knife/user_create_spec.rb2
-rw-r--r--spec/unit/knife_spec.rb28
-rw-r--r--spec/unit/lwrp_spec.rb13
-rw-r--r--spec/unit/mixin/template_spec.rb2
-rw-r--r--spec/unit/provider/http_request_spec.rb16
-rw-r--r--spec/unit/provider/log_spec.rb18
-rw-r--r--spec/unit/provider/package_spec.rb2
-rw-r--r--spec/unit/provider/remote_directory_spec.rb2
-rw-r--r--spec/unit/provider/template/content_spec.rb2
-rw-r--r--spec/unit/provider_spec.rb12
-rw-r--r--spec/unit/shell/shell_session_spec.rb2
34 files changed, 969 insertions, 324 deletions
diff --git a/spec/functional/resource/base.rb b/spec/functional/resource/base.rb
index 056db39877..cdb52fbc1b 100644
--- a/spec/functional/resource/base.rb
+++ b/spec/functional/resource/base.rb
@@ -16,16 +16,6 @@
# limitations under the License.
#
-require 'spec_helper'
-
-def ohai
- # provider is platform-dependent, we need platform ohai data:
- @OHAI_SYSTEM ||= begin
- ohai = Ohai::System.new
- ohai.all_plugins("platform")
- ohai
- end
-end
def run_context
@run_context ||= begin
diff --git a/spec/functional/resource/cookbook_file_spec.rb b/spec/functional/resource/cookbook_file_spec.rb
index 173dac8268..7797ed0041 100644
--- a/spec/functional/resource/cookbook_file_spec.rb
+++ b/spec/functional/resource/cookbook_file_spec.rb
@@ -40,7 +40,7 @@ describe Chef::Resource::CookbookFile do
# set up cookbook collection for this run to use, based on our
# spec data.
cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, 'cookbooks'))
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) }
+ Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_repo)
loader = Chef::CookbookLoader.new(cookbook_repo)
loader.load_cookbooks
cookbook_collection = Chef::CookbookCollection.new(loader)
diff --git a/spec/functional/resource/package_spec.rb b/spec/functional/resource/package_spec.rb
index 797f308cf9..548db40e79 100644
--- a/spec/functional/resource/package_spec.rb
+++ b/spec/functional/resource/package_spec.rb
@@ -135,9 +135,7 @@ describe Chef::Resource::Package, metadata do
cookbook_path = File.join(CHEF_SPEC_DATA, "cookbooks")
cl = Chef::CookbookLoader.new(cookbook_path)
cl.load_cookbooks
- Chef::Cookbook::FileVendor.on_create do |manifest|
- Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_path)
- end
+ Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_path)
Chef::CookbookCollection.new(cl)
end
diff --git a/spec/functional/resource/remote_directory_spec.rb b/spec/functional/resource/remote_directory_spec.rb
index 70e575abb0..f9eb20711e 100644
--- a/spec/functional/resource/remote_directory_spec.rb
+++ b/spec/functional/resource/remote_directory_spec.rb
@@ -26,7 +26,7 @@ describe Chef::Resource::RemoteDirectory do
def create_resource
cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) }
+ Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_repo)
node = Chef::Node.new
cl = Chef::CookbookLoader.new(cookbook_repo)
cl.load_cookbooks
diff --git a/spec/functional/resource/template_spec.rb b/spec/functional/resource/template_spec.rb
index 7816d6357b..fefd995743 100644
--- a/spec/functional/resource/template_spec.rb
+++ b/spec/functional/resource/template_spec.rb
@@ -37,7 +37,7 @@ describe Chef::Resource::Template do
def create_resource
cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) }
+ Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_repo)
cl = Chef::CookbookLoader.new(cookbook_repo)
cl.load_cookbooks
cookbook_collection = Chef::CookbookCollection.new(cl)
diff --git a/spec/integration/knife/chef_fs_data_store_spec.rb b/spec/integration/knife/chef_fs_data_store_spec.rb
index e8a3b3dde5..7e55aa7319 100644
--- a/spec/integration/knife/chef_fs_data_store_spec.rb
+++ b/spec/integration/knife/chef_fs_data_store_spec.rb
@@ -141,7 +141,7 @@ EOM
end
it 'knife cookbook upload works' do
- knife("cookbook upload -z --cookbook-path #{path_to('cookbooks_to_upload')} x").should_succeed <<EOM
+ knife("cookbook upload -z --cookbook-path #{path_to('cookbooks_to_upload')} x").should_succeed :stderr => <<EOM
Uploading x [1.0.0]
Uploaded 1 cookbook.
EOM
@@ -199,7 +199,7 @@ EOM
end
it 'knife cookbook upload works' do
- knife("cookbook upload -z --cookbook-path #{path_to('cookbooks_to_upload')} z").should_succeed <<EOM
+ knife("cookbook upload -z --cookbook-path #{path_to('cookbooks_to_upload')} z").should_succeed :stderr => <<EOM
Uploading z [1.0.0]
Uploaded 1 cookbook.
EOM
diff --git a/spec/support/platform_helpers.rb b/spec/support/platform_helpers.rb
index 75ab0c9cde..ad7104d170 100644
--- a/spec/support/platform_helpers.rb
+++ b/spec/support/platform_helpers.rb
@@ -27,6 +27,11 @@ def windows?
!!(RUBY_PLATFORM =~ /mswin|mingw|windows/)
end
+def ohai
+ # This is defined in spec_helper; it has the `platform` populated.
+ OHAI_SYSTEM
+end
+
require 'wmi-lite/wmi' if windows?
def windows_domain_joined?
diff --git a/spec/unit/cookbook/file_vendor_spec.rb b/spec/unit/cookbook/file_vendor_spec.rb
new file mode 100644
index 0000000000..4fad7d5808
--- /dev/null
+++ b/spec/unit/cookbook/file_vendor_spec.rb
@@ -0,0 +1,78 @@
+#--
+# Author:: Daniel DeLeo (<dan@getchef.com>)
+# Copyright:: Copyright (c) 2014 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::Cookbook::FileVendor do
+
+ let(:file_vendor_class) { Class.new(described_class) }
+
+ # A manifest is a Hash of the format defined by Chef::CookbookVersion#manifest
+ let(:manifest) { {:cookbook_name => "bob"} }
+
+ context "when configured to fetch files over http" do
+
+ let(:http) { double("Chef::REST") }
+
+ before do
+ file_vendor_class.fetch_from_remote(http)
+ end
+
+ it "sets the vendor class to RemoteFileVendor" do
+ expect(file_vendor_class.vendor_class).to eq(Chef::Cookbook::RemoteFileVendor)
+ end
+
+ it "sets the initialization options to the given http object" do
+ expect(file_vendor_class.initialization_options).to eq(http)
+ end
+
+ it "creates a RemoteFileVendor for a given manifest" do
+ file_vendor = file_vendor_class.create_from_manifest(manifest)
+ expect(file_vendor).to be_a_kind_of(Chef::Cookbook::RemoteFileVendor)
+ expect(file_vendor.rest).to eq(http)
+ expect(file_vendor.cookbook_name).to eq("bob")
+ end
+
+ end
+
+ context "when configured to load files from disk" do
+
+ let(:cookbook_path) { %w[/var/chef/cookbooks /var/chef/other_cookbooks] }
+
+ before do
+ file_vendor_class.fetch_from_disk(cookbook_path)
+ end
+
+ it "sets the vendor class to FileSystemFileVendor" do
+ expect(file_vendor_class.vendor_class).to eq(Chef::Cookbook::FileSystemFileVendor)
+ end
+
+ it "sets the initialization options to the given cookbook paths" do
+ expect(file_vendor_class.initialization_options).to eq(cookbook_path)
+ end
+
+ it "creates a FileSystemFileVendor for a given manifest" do
+ file_vendor = file_vendor_class.create_from_manifest(manifest)
+ expect(file_vendor).to be_a_kind_of(Chef::Cookbook::FileSystemFileVendor)
+ expect(file_vendor.cookbook_name).to eq("bob")
+ expect(file_vendor.repo_paths).to eq(cookbook_path)
+ end
+
+ end
+
+end
+
diff --git a/spec/unit/cookbook/synchronizer_spec.rb b/spec/unit/cookbook/synchronizer_spec.rb
index c52593287a..2b040f3c95 100644
--- a/spec/unit/cookbook/synchronizer_spec.rb
+++ b/spec/unit/cookbook/synchronizer_spec.rb
@@ -5,302 +5,517 @@ require 'chef/cookbook_version'
describe Chef::CookbookCacheCleaner do
describe "when cleaning up unused cookbook components" do
- before do
- @cleaner = Chef::CookbookCacheCleaner.instance
- @cleaner.reset!
+ let(:cleaner) do
+ cleaner = Chef::CookbookCacheCleaner.instance
+ cleaner.reset!
+ cleaner
end
- it "removes all files that belong to unused cookbooks" do
- end
+ let(:file_cache) { double("Chef::FileCache with files from unused cookbooks") }
- it "removes all files not validated during the chef run" do
- file_cache = double("Chef::FileCache with files from unused cookbooks")
- unused_template_files = %w{cookbooks/unused/templates/default/foo.conf.erb cookbooks/unused/tempaltes/default/bar.conf.erb}
- valid_cached_cb_files = %w{cookbooks/valid1/recipes/default.rb cookbooks/valid2/recipes/default.rb}
- @cleaner.mark_file_as_valid('cookbooks/valid1/recipes/default.rb')
- @cleaner.mark_file_as_valid('cookbooks/valid2/recipes/default.rb')
- file_cache.should_receive(:find).with(File.join(%w{cookbooks ** *})).and_return(valid_cached_cb_files + unused_template_files)
- file_cache.should_receive(:delete).with('cookbooks/unused/templates/default/foo.conf.erb')
- file_cache.should_receive(:delete).with('cookbooks/unused/tempaltes/default/bar.conf.erb')
- cookbook_hash = {"valid1"=> {}, "valid2" => {}}
- @cleaner.stub(:cache).and_return(file_cache)
- @cleaner.cleanup_file_cache
+ let(:unused_template_files) do
+ %w{
+ cookbooks/unused/templates/default/foo.conf.erb
+ cookbooks/unused/tempaltes/default/bar.conf.erb
+ }
end
- describe "on chef-solo" do
- before do
- Chef::Config[:solo] = true
- end
+ let(:valid_cached_cb_files) do
+ %w{
+ cookbooks/valid1/recipes/default.rb
+ cookbooks/valid2/recipes/default.rb
+ }
+ end
- after do
- Chef::Config[:solo] = false
+ before do
+ valid_cached_cb_files.each do |cbf|
+ cleaner.mark_file_as_valid(cbf)
end
+ end
- it "does not remove anything" do
- @cleaner.cache.stub(:find).and_return(%w{cookbooks/valid1/recipes/default.rb cookbooks/valid2/recipes/default.rb})
- @cleaner.cache.should_not_receive(:delete)
- @cleaner.cleanup_file_cache
+ it "removes all files not validated during the chef run" do
+ expect(file_cache).to receive(:find).with(File.join(%w{cookbooks ** {*,.*}})).and_return(valid_cached_cb_files + unused_template_files)
+ unused_template_files.each do |cbf|
+ expect(file_cache).to receive(:delete).with(cbf)
end
+ cookbook_hash = {"valid1"=> {}, "valid2" => {}}
+ allow(cleaner).to receive(:cache).and_return(file_cache)
+ cleaner.cleanup_file_cache
+ end
+ it "does not remove anything when skip_removal is true" do
+ cleaner.skip_removal = true
+ allow(cleaner.cache).to receive(:find).and_return(%w{cookbooks/valid1/recipes/default.rb cookbooks/valid2/recipes/default.rb})
+ expect(cleaner.cache).not_to receive(:delete)
+ cleaner.cleanup_file_cache
end
+ it "does not remove anything on chef-solo" do
+ Chef::Config[:solo] = true
+ allow(cleaner.cache).to receive(:find).and_return(%w{cookbooks/valid1/recipes/default.rb cookbooks/valid2/recipes/default.rb})
+ expect(cleaner.cache).not_to receive(:delete)
+ cleaner.cleanup_file_cache
+ end
end
end
describe Chef::CookbookSynchronizer do
- before do
+ let(:cookbook_a_default_recipe) do
+ {
+ "path" => "recipes/default.rb",
+ "url" => "http://chef.example.com/abc123",
+ "checksum" => "abc123",
+ }
+ end
+
+ let(:cookbook_a_default_attrs) do
+ {
+ "path" => "attributes/default.rb",
+ "url" => "http://chef.example.com/abc456",
+ "checksum" => "abc456",
+ }
+ end
+
+ let(:cookbook_a_template) do
+ {
+ "path" => "templates/default/apache2.conf.erb",
+ "url" => "http://chef.example.com/ffffff",
+ "checksum" => "abc125",
+ }
+ end
+
+ let(:cookbook_a_file) do
+ {
+ "path" => "files/default/megaman.conf",
+ "url" => "http://chef.example.com/megaman.conf",
+ "checksum" => "abc124",
+ }
+ end
+
+ let(:cookbook_a_manifest) do
segments = [ :resources, :providers, :recipes, :definitions, :libraries, :attributes, :files, :templates, :root_files ]
- @cookbook_manifest = {}
- @cookbook_a = Chef::CookbookVersion.new("cookbook_a")
- @cookbook_a_manifest = segments.inject({}) {|h, segment| h[segment.to_s] = []; h}
- @cookbook_a_default_recipe = { "path" => "recipes/default.rb",
- "url" => "http://chef.example.com/abc123",
- "checksum" => "abc123" }
- @cookbook_a_manifest["recipes"] = [ @cookbook_a_default_recipe ]
-
- @cookbook_a_default_attrs = { "path" => "attributes/default.rb",
- "url" => "http://chef.example.com/abc456",
- "checksum" => "abc456" }
- @cookbook_a_manifest["attributes"] = [ @cookbook_a_default_attrs ]
- @cookbook_a_manifest["templates"] = [{"path" => "templates/default/apache2.conf.erb", "url" => "http://chef.example.com/ffffff"}]
- @cookbook_a_manifest["files"] = [{"path" => "files/default/megaman.conf", "url" => "http://chef.example.com/megaman.conf"}]
- @cookbook_a.manifest = @cookbook_a_manifest
- @cookbook_manifest["cookbook_a"] = @cookbook_a
-
- @events = Chef::EventDispatch::Dispatcher.new
- @synchronizer = Chef::CookbookSynchronizer.new(@cookbook_manifest, @events)
+ cookbook_a_manifest = segments.inject({}) {|h, segment| h[segment.to_s] = []; h}
+ cookbook_a_manifest["recipes"] = [ cookbook_a_default_recipe ]
+ cookbook_a_manifest["attributes"] = [ cookbook_a_default_attrs ]
+ cookbook_a_manifest["templates"] = [ cookbook_a_template ]
+ cookbook_a_manifest["files"] = [ cookbook_a_file ]
+ cookbook_a_manifest
+ end
+
+ let(:cookbook_a) do
+ cookbook_a = Chef::CookbookVersion.new("cookbook_a")
+ cookbook_a.manifest = cookbook_a_manifest
+ cookbook_a
+ end
+
+ let(:cookbook_manifest) do
+ {
+ "cookbook_a" => cookbook_a
+ }
+ end
+
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
+
+ let(:no_lazy_load) { true }
+
+ let(:synchronizer) do
+ Chef::Config[:no_lazy_load] = no_lazy_load
+ Chef::CookbookSynchronizer.new(cookbook_manifest, events)
end
it "lists the cookbook names" do
- @synchronizer.cookbook_names.should == %w[cookbook_a]
+ expect(synchronizer.cookbook_names).to eq(%w[cookbook_a])
end
it "lists the cookbook manifests" do
- @synchronizer.cookbooks.should == [@cookbook_a]
+ expect(synchronizer.cookbooks).to eq([cookbook_a])
end
- context "when the cache contains unneeded cookbooks" do
- before do
- @file_cache = double("Chef::FileCache with files from unused cookbooks")
- @valid_cached_cb_files = %w{cookbooks/valid1/recipes/default.rb cookbooks/valid2/recipes/default.rb}
- @obsolete_cb_files = %w{cookbooks/old1/recipes/default.rb cookbooks/old2/recipes/default.rb}
+ context "#clear_obsoleted_cookbooks" do
+ after do
+ # Singletons == Global State == Bad
+ Chef::CookbookCacheCleaner.instance.skip_removal = nil
+ end
- @cookbook_hash = {"valid1"=> {}, "valid2" => {}}
+ it "behaves correctly when remove_obsoleted_files is false" do
+ synchronizer.remove_obsoleted_files = false
+ expect(synchronizer).not_to receive(:remove_old_cookbooks)
+ expect(synchronizer).to receive(:remove_deleted_files)
+ synchronizer.clear_obsoleted_cookbooks
+ expect(Chef::CookbookCacheCleaner.instance.skip_removal).to be true
+ end
+
+ it "behaves correctly when remove_obsoleted_files is true" do
+ synchronizer.remove_obsoleted_files = true
+ expect(synchronizer).to receive(:remove_old_cookbooks)
+ expect(synchronizer).to receive(:remove_deleted_files)
+ synchronizer.clear_obsoleted_cookbooks
+ expect(Chef::CookbookCacheCleaner.instance.skip_removal).to be nil
+ end
+ end
+
+ context "#remove_old_cookbooks" do
+ let(:file_cache) { double("Chef::FileCache with files from unused cookbooks") }
- @synchronizer = Chef::CookbookSynchronizer.new(@cookbook_hash, @events)
+ let(:cookbook_manifest) do
+ {"valid1"=> {}, "valid2" => {}}
end
it "removes unneeded cookbooks" do
- @file_cache.should_receive(:find).with(File.join(%w{cookbooks ** *})).and_return(@valid_cached_cb_files + @obsolete_cb_files)
- @file_cache.should_receive(:delete).with('cookbooks/old1/recipes/default.rb')
- @file_cache.should_receive(:delete).with('cookbooks/old2/recipes/default.rb')
- @synchronizer.stub(:cache).and_return(@file_cache)
- @synchronizer.clear_obsoleted_cookbooks
+ valid_cached_cb_files = %w{cookbooks/valid1/recipes/default.rb cookbooks/valid2/recipes/default.rb}
+ obsolete_cb_files = %w{cookbooks/old1/recipes/default.rb cookbooks/old2/recipes/default.rb}
+ expect(file_cache).to receive(:find).with(File.join(%w{cookbooks ** {*,.*}})).and_return(valid_cached_cb_files + obsolete_cb_files)
+ expect(file_cache).to receive(:delete).with('cookbooks/old1/recipes/default.rb')
+ expect(file_cache).to receive(:delete).with('cookbooks/old2/recipes/default.rb')
+ allow(synchronizer).to receive(:cache).and_return(file_cache)
+ synchronizer.remove_old_cookbooks
end
end
- describe "when syncing cookbooks with the server" do
- before do
- # Would rather not stub out methods on the test subject, but setting up
- # the state is a PITA and tests for this behavior are above.
- @synchronizer.stub(:clear_obsoleted_cookbooks)
+ context "#remove_deleted_files" do
+ let(:file_cache) { double("Chef::FileCache with files from unused cookbooks") }
+
+ let(:cookbook_manifest) do
+ {"valid1"=> {}, "valid2" => {}}
+ end
+
+ it "removes only deleted files" do
+ valid_cached_cb_files = %w{cookbooks/valid1/recipes/default.rb cookbooks/valid2/recipes/default.rb}
+ obsolete_cb_files = %w{cookbooks/valid1/recipes/deleted.rb cookbooks/valid2/recipes/deleted.rb}
+ expect(file_cache).to receive(:find).with(File.join(%w{cookbooks ** {*,.*}})).and_return(valid_cached_cb_files + obsolete_cb_files)
+ # valid1 is a cookbook in our run_list
+ expect(synchronizer).to receive(:have_cookbook?).with("valid1").at_least(:once).and_return(true)
+ # valid2 is a cookbook not in our run_list (we're simulating an override run_list where valid2 needs to be preserved)
+ expect(synchronizer).to receive(:have_cookbook?).with("valid2").at_least(:once).and_return(false)
+ expect(file_cache).to receive(:delete).with('cookbooks/valid1/recipes/deleted.rb')
+ expect(synchronizer).to receive(:cookbook_segment).with("valid1", "recipes").at_least(:once).and_return([ { "path" => "recipes/default.rb" }])
+ allow(synchronizer).to receive(:cache).and_return(file_cache)
+ synchronizer.remove_deleted_files
+ end
+ end
+
+ let(:cookbook_a_default_recipe_tempfile) do
+ double("Tempfile for cookbook_a default.rb recipe",
+ :path => "/tmp/cookbook_a_recipes_default_rb")
+ end
- @server_api = double("Chef::REST (mock)")
- @file_cache = double("Chef::FileCache (mock)")
- @synchronizer.stub(:server_api).and_return(@server_api)
- @synchronizer.stub(:cache).and_return(@file_cache)
+ let(:cookbook_a_default_attribute_tempfile) do
+ double("Tempfile for cookbook_a default.rb attr file",
+ :path => "/tmp/cookbook_a_attributes_default_rb")
+ end
+ let(:cookbook_a_file_default_tempfile) do
+ double("Tempfile for cookbook_a megaman.conf file",
+ :path => "/tmp/cookbook_a_file_default_tempfile")
+ end
- @cookbook_a_default_recipe_tempfile = double("Tempfile for cookbook_a default.rb recipe",
- :path => "/tmp/cookbook_a_recipes_default_rb")
+ let(:cookbook_a_template_default_tempfile) do
+ double("Tempfile for cookbook_a apache.conf.erb template",
+ :path => "/tmp/cookbook_a_template_default_tempfile")
+ end
- @cookbook_a_default_attribute_tempfile = double("Tempfile for cookbook_a default.rb attr file",
- :path => "/tmp/cookbook_a_attributes_default_rb")
+ def setup_common_files_missing_expectations
+ # Files are not in the cache:
+ expect(file_cache).to receive(:has_key?).
+ with("cookbooks/cookbook_a/recipes/default.rb").
+ and_return(false)
+ expect(file_cache).to receive(:has_key?).
+ with("cookbooks/cookbook_a/attributes/default.rb").
+ and_return(false)
+
+ # Fetch and copy default.rb recipe
+ expect(server_api).to receive(:get_rest).
+ with('http://chef.example.com/abc123', true).
+ and_return(cookbook_a_default_recipe_tempfile)
+ expect(file_cache).to receive(:move_to).
+ with("/tmp/cookbook_a_recipes_default_rb", "cookbooks/cookbook_a/recipes/default.rb")
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/recipes/default.rb", false).
+ and_return("/file-cache/cookbooks/cookbook_a/recipes/default.rb")
+
+ # Fetch and copy default.rb attribute file
+ expect(server_api).to receive(:get_rest).
+ with('http://chef.example.com/abc456', true).
+ and_return(cookbook_a_default_attribute_tempfile)
+ expect(file_cache).to receive(:move_to).
+ with("/tmp/cookbook_a_attributes_default_rb", "cookbooks/cookbook_a/attributes/default.rb")
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/attributes/default.rb", false).
+ and_return("/file-cache/cookbooks/cookbook_a/attributes/default.rb")
+ end
+ def setup_no_lazy_files_and_templates_missing_expectations
+ expect(file_cache).to receive(:has_key?).
+ with("cookbooks/cookbook_a/files/default/megaman.conf").
+ and_return(false)
+ expect(file_cache).to receive(:has_key?).
+ with("cookbooks/cookbook_a/templates/default/apache2.conf.erb").
+ and_return(false)
+
+ expect(server_api).to receive(:get_rest).
+ with('http://chef.example.com/megaman.conf', true).
+ and_return(cookbook_a_file_default_tempfile)
+ expect(file_cache).to receive(:move_to).
+ with("/tmp/cookbook_a_file_default_tempfile", "cookbooks/cookbook_a/files/default/megaman.conf")
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/files/default/megaman.conf", false).
+ and_return("/file-cache/cookbooks/cookbook_a/default/megaman.conf")
+
+ expect(server_api).to receive(:get_rest).
+ with('http://chef.example.com/ffffff', true).
+ and_return(cookbook_a_template_default_tempfile)
+ expect(file_cache).to receive(:move_to).
+ with("/tmp/cookbook_a_template_default_tempfile", "cookbooks/cookbook_a/templates/default/apache2.conf.erb")
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/templates/default/apache2.conf.erb", false).
+ and_return("/file-cache/cookbooks/cookbook_a/templates/default/apache2.conf.erb")
+ end
+
+ def setup_common_files_chksum_mismatch_expectations
+ # Files are in the cache:
+ expect(file_cache).to receive(:has_key?).
+ with("cookbooks/cookbook_a/recipes/default.rb").
+ and_return(true)
+ expect(file_cache).to receive(:has_key?).
+ with("cookbooks/cookbook_a/attributes/default.rb").
+ and_return(true)
+
+ # Fetch and copy default.rb recipe
+ expect(server_api).to receive(:get_rest).
+ with('http://chef.example.com/abc123', true).
+ and_return(cookbook_a_default_recipe_tempfile)
+ expect(file_cache).to receive(:move_to).
+ with("/tmp/cookbook_a_recipes_default_rb", "cookbooks/cookbook_a/recipes/default.rb")
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/recipes/default.rb", false).
+ twice.
+ and_return("/file-cache/cookbooks/cookbook_a/recipes/default.rb")
+
+ # Current file has fff000, want abc123
+ expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file).
+ with("/file-cache/cookbooks/cookbook_a/recipes/default.rb").
+ and_return("fff000")
+
+ # Fetch and copy default.rb attribute file
+ expect(server_api).to receive(:get_rest).
+ with('http://chef.example.com/abc456', true).
+ and_return(cookbook_a_default_attribute_tempfile)
+ expect(file_cache).to receive(:move_to).
+ with("/tmp/cookbook_a_attributes_default_rb", "cookbooks/cookbook_a/attributes/default.rb")
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/attributes/default.rb", false).
+ twice.
+ and_return("/file-cache/cookbooks/cookbook_a/attributes/default.rb")
+
+ # Current file has fff000, want abc456
+ expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file).
+ with("/file-cache/cookbooks/cookbook_a/attributes/default.rb").
+ and_return("fff000")
+ end
+
+ def setup_no_lazy_files_and_templates_chksum_mismatch_expectations
+ # Files are in the cache:
+ expect(file_cache).to receive(:has_key?).
+ with("cookbooks/cookbook_a/files/default/megaman.conf").
+ and_return(true)
+ expect(file_cache).to receive(:has_key?).
+ with("cookbooks/cookbook_a/templates/default/apache2.conf.erb").
+ and_return(true)
+
+ # Fetch and copy megaman.conf
+ expect(server_api).to receive(:get_rest).
+ with('http://chef.example.com/megaman.conf', true).
+ and_return(cookbook_a_file_default_tempfile)
+ expect(file_cache).to receive(:move_to).
+ with("/tmp/cookbook_a_file_default_tempfile", "cookbooks/cookbook_a/files/default/megaman.conf")
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/files/default/megaman.conf", false).
+ twice.
+ and_return("/file-cache/cookbooks/cookbook_a/default/megaman.conf")
+
+ # Fetch and copy apache2.conf template
+ expect(server_api).to receive(:get_rest).
+ with('http://chef.example.com/ffffff', true).
+ and_return(cookbook_a_template_default_tempfile)
+ expect(file_cache).to receive(:move_to).
+ with("/tmp/cookbook_a_template_default_tempfile", "cookbooks/cookbook_a/templates/default/apache2.conf.erb")
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/templates/default/apache2.conf.erb", false).
+ twice.
+ and_return("/file-cache/cookbooks/cookbook_a/templates/default/apache2.conf.erb")
+
+ # Current file has fff000
+ expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file).
+ with("/file-cache/cookbooks/cookbook_a/default/megaman.conf").
+ and_return("fff000")
+
+ # Current file has fff000
+ expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file).
+ with("/file-cache/cookbooks/cookbook_a/templates/default/apache2.conf.erb").
+ and_return("fff000")
+ end
+
+ def setup_common_files_present_expectations
+ # Files are in the cache:
+ expect(file_cache).to receive(:has_key?).
+ with("cookbooks/cookbook_a/recipes/default.rb").
+ and_return(true)
+ expect(file_cache).to receive(:has_key?).
+ with("cookbooks/cookbook_a/attributes/default.rb").
+ and_return(true)
+
+ # Current file has abc123, want abc123
+ expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file).
+ with("/file-cache/cookbooks/cookbook_a/recipes/default.rb").
+ and_return("abc123")
+
+ # Current file has abc456, want abc456
+ expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file).
+ with("/file-cache/cookbooks/cookbook_a/attributes/default.rb").
+ and_return("abc456")
+
+ # :load called twice
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/recipes/default.rb", false).
+ twice.
+ and_return("/file-cache/cookbooks/cookbook_a/recipes/default.rb")
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/attributes/default.rb", false).
+ twice.
+ and_return("/file-cache/cookbooks/cookbook_a/attributes/default.rb")
+ end
+
+ def setup_no_lazy_files_and_templates_present_expectations
+ # Files are in the cache:
+ expect(file_cache).to receive(:has_key?).
+ with("cookbooks/cookbook_a/files/default/megaman.conf").
+ and_return(true)
+ expect(file_cache).to receive(:has_key?).
+ with("cookbooks/cookbook_a/templates/default/apache2.conf.erb").
+ and_return(true)
+
+ # Current file has abc124, want abc124
+ expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file).
+ with("/file-cache/cookbooks/cookbook_a/default/megaman.conf").
+ and_return("abc124")
+
+ # Current file has abc125, want abc125
+ expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file).
+ with("/file-cache/cookbooks/cookbook_a/templates/default/apache2.conf.erb").
+ and_return("abc125")
+
+ # :load called twice
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/files/default/megaman.conf", false).
+ twice.
+ and_return("/file-cache/cookbooks/cookbook_a/default/megaman.conf")
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/templates/default/apache2.conf.erb", false).
+ twice.
+ and_return("/file-cache/cookbooks/cookbook_a/templates/default/apache2.conf.erb")
+ end
+
+ describe "when syncing cookbooks with the server" do
+ let(:server_api) { double("Chef::REST (mock)") }
+
+ let(:file_cache) { double("Chef::FileCache (mock)") }
+
+ before do
+ # Would rather not stub out methods on the test subject, but setting up
+ # the state is a PITA and tests for this behavior are above.
+ allow(synchronizer).to receive(:clear_obsoleted_cookbooks)
+ allow(synchronizer).to receive(:server_api).and_return(server_api)
+ allow(synchronizer).to receive(:cache).and_return(file_cache)
end
context "when the cache does not contain the desired files" do
before do
-
- # Files are not in the cache:
- @file_cache.should_receive(:has_key?).
- with("cookbooks/cookbook_a/recipes/default.rb").
- and_return(false)
- @file_cache.should_receive(:has_key?).
- with("cookbooks/cookbook_a/attributes/default.rb").
- and_return(false)
-
- # Fetch and copy default.rb recipe
- @server_api.should_receive(:get_rest).
- with('http://chef.example.com/abc123', true).
- and_return(@cookbook_a_default_recipe_tempfile)
- @file_cache.should_receive(:move_to).
- with("/tmp/cookbook_a_recipes_default_rb", "cookbooks/cookbook_a/recipes/default.rb")
- @file_cache.should_receive(:load).
- with("cookbooks/cookbook_a/recipes/default.rb", false).
- and_return("/file-cache/cookbooks/cookbook_a/recipes/default.rb")
-
- # Fetch and copy default.rb attribute file
- @server_api.should_receive(:get_rest).
- with('http://chef.example.com/abc456', true).
- and_return(@cookbook_a_default_attribute_tempfile)
- @file_cache.should_receive(:move_to).
- with("/tmp/cookbook_a_attributes_default_rb", "cookbooks/cookbook_a/attributes/default.rb")
- @file_cache.should_receive(:load).
- with("cookbooks/cookbook_a/attributes/default.rb", false).
- and_return("/file-cache/cookbooks/cookbook_a/attributes/default.rb")
+ setup_common_files_missing_expectations
end
- it "fetches eagerly loaded files" do
- @synchronizer.sync_cookbooks
- end
+ context "Chef::Config[:no_lazy_load] is false" do
+ let(:no_lazy_load) { false }
- it "does not fetch templates or cookbook files" do
- # Implicitly tested in previous test; this test is just for behavior specification.
- @server_api.should_not_receive(:get_rest).
- with('http://chef.example.com/ffffff', true)
+ it "fetches eagerly loaded files" do
+ synchronizer.sync_cookbooks
+ end
+
+ it "does not fetch templates or cookbook files" do
+ # Implicitly tested in previous test; this test is just for behavior specification.
+ expect(server_api).not_to receive(:get_rest).
+ with('http://chef.example.com/ffffff', true)
- @synchronizer.sync_cookbooks
+ synchronizer.sync_cookbooks
+ end
end
context "Chef::Config[:no_lazy_load] is true" do
- before do
- Chef::Config[:no_lazy_load] = true
- @synchronizer = Chef::CookbookSynchronizer.new(@cookbook_manifest, @events)
- @synchronizer.stub(:server_api).and_return(@server_api)
- @synchronizer.stub(:cache).and_return(@file_cache)
- @synchronizer.stub(:clear_obsoleted_cookbooks)
-
- @cookbook_a_file_default_tempfile = double("Tempfile for cookbook_a megaman.conf file",
- :path => "/tmp/cookbook_a_file_default_tempfile")
- @cookbook_a_template_default_tempfile = double("Tempfile for cookbook_a apache.conf.erb template",
- :path => "/tmp/cookbook_a_template_default_tempfile")
- end
+ let(:no_lazy_load) { true }
- after do
- Chef::Config[:no_lazy_load] = false
+ before do
+ setup_no_lazy_files_and_templates_missing_expectations
end
it "fetches templates and cookbook files" do
- @file_cache.should_receive(:has_key?).
- with("cookbooks/cookbook_a/files/default/megaman.conf").
- and_return(false)
- @file_cache.should_receive(:has_key?).
- with("cookbooks/cookbook_a/templates/default/apache2.conf.erb").
- and_return(false)
-
- @server_api.should_receive(:get_rest).
- with('http://chef.example.com/megaman.conf', true).
- and_return(@cookbook_a_file_default_tempfile)
- @file_cache.should_receive(:move_to).
- with("/tmp/cookbook_a_file_default_tempfile", "cookbooks/cookbook_a/files/default/megaman.conf")
- @file_cache.should_receive(:load).
- with("cookbooks/cookbook_a/files/default/megaman.conf", false).
- and_return("/file-cache/cookbooks/cookbook_a/default/megaman.conf")
-
- @server_api.should_receive(:get_rest).
- with('http://chef.example.com/ffffff', true).
- and_return(@cookbook_a_template_default_tempfile)
- @file_cache.should_receive(:move_to).
- with("/tmp/cookbook_a_template_default_tempfile", "cookbooks/cookbook_a/templates/default/apache2.conf.erb")
- @file_cache.should_receive(:load).
- with("cookbooks/cookbook_a/templates/default/apache2.conf.erb", false).
- and_return("/file-cache/cookbooks/cookbook_a/templates/default/apache2.conf.erb")
-
- @synchronizer.sync_cookbooks
+ synchronizer.sync_cookbooks
end
end
end
context "when the cache contains outdated files" do
before do
- # Files are in the cache:
- @file_cache.should_receive(:has_key?).
- with("cookbooks/cookbook_a/recipes/default.rb").
- and_return(true)
- @file_cache.should_receive(:has_key?).
- with("cookbooks/cookbook_a/attributes/default.rb").
- and_return(true)
-
-
- # Fetch and copy default.rb recipe
- @server_api.should_receive(:get_rest).
- with('http://chef.example.com/abc123', true).
- and_return(@cookbook_a_default_recipe_tempfile)
- @file_cache.should_receive(:move_to).
- with("/tmp/cookbook_a_recipes_default_rb", "cookbooks/cookbook_a/recipes/default.rb")
- @file_cache.should_receive(:load).
- with("cookbooks/cookbook_a/recipes/default.rb", false).
- twice.
- and_return("/file-cache/cookbooks/cookbook_a/recipes/default.rb")
-
- # Current file has fff000, want abc123
- Chef::CookbookVersion.should_receive(:checksum_cookbook_file).
- with("/file-cache/cookbooks/cookbook_a/recipes/default.rb").
- and_return("fff000")
-
- # Fetch and copy default.rb attribute file
- @server_api.should_receive(:get_rest).
- with('http://chef.example.com/abc456', true).
- and_return(@cookbook_a_default_attribute_tempfile)
- @file_cache.should_receive(:move_to).
- with("/tmp/cookbook_a_attributes_default_rb", "cookbooks/cookbook_a/attributes/default.rb")
- @file_cache.should_receive(:load).
- with("cookbooks/cookbook_a/attributes/default.rb", false).
- twice.
- and_return("/file-cache/cookbooks/cookbook_a/attributes/default.rb")
-
- # Current file has fff000, want abc456
- Chef::CookbookVersion.should_receive(:checksum_cookbook_file).
- with("/file-cache/cookbooks/cookbook_a/attributes/default.rb").
- and_return("fff000")
+ setup_common_files_chksum_mismatch_expectations
end
- it "updates the outdated files" do
- @synchronizer.sync_cookbooks
+ context "Chef::Config[:no_lazy_load] is true" do
+ let(:no_lazy_load) { true }
+
+ before do
+ setup_no_lazy_files_and_templates_chksum_mismatch_expectations
+ end
+
+ it "updates the outdated files" do
+ synchronizer.sync_cookbooks
+ end
+ end
+
+ context "Chef::Config[:no_lazy_load] is false" do
+ let(:no_lazy_load) { false }
+
+ it "updates the outdated files" do
+ synchronizer.sync_cookbooks
+ end
end
end
context "when the cache is up to date" do
before do
- # Files are in the cache:
- @file_cache.should_receive(:has_key?).
- with("cookbooks/cookbook_a/recipes/default.rb").
- and_return(true)
- @file_cache.should_receive(:has_key?).
- with("cookbooks/cookbook_a/attributes/default.rb").
- and_return(true)
-
- # Current file has abc123, want abc123
- Chef::CookbookVersion.should_receive(:checksum_cookbook_file).
- with("/file-cache/cookbooks/cookbook_a/recipes/default.rb").
- and_return("abc123")
-
- # Current file has abc456, want abc456
- Chef::CookbookVersion.should_receive(:checksum_cookbook_file).
- with("/file-cache/cookbooks/cookbook_a/attributes/default.rb").
- and_return("abc456")
-
- @file_cache.should_receive(:load).
- with("cookbooks/cookbook_a/recipes/default.rb", false).
- twice.
- and_return("/file-cache/cookbooks/cookbook_a/recipes/default.rb")
-
- @file_cache.should_receive(:load).
- with("cookbooks/cookbook_a/attributes/default.rb", false).
- twice.
- and_return("/file-cache/cookbooks/cookbook_a/attributes/default.rb")
+ setup_common_files_present_expectations
end
- it "does not update files" do
- @file_cache.should_not_receive(:move_to)
- @server_api.should_not_receive(:get_rest)
- @synchronizer.sync_cookbooks
+ context "Chef::Config[:no_lazy_load] is true" do
+ let(:no_lazy_load) { true }
+
+ before do
+ setup_no_lazy_files_and_templates_present_expectations
+ end
+
+ it "does not update files" do
+ expect(file_cache).not_to receive(:move_to)
+ expect(server_api).not_to receive(:get_rest)
+ synchronizer.sync_cookbooks
+ end
end
- end
+ context "Chef::Config[:no_lazy_load] is false" do
+ let(:no_lazy_load) { false }
+ it "does not update files" do
+ expect(file_cache).not_to receive(:move_to)
+ expect(server_api).not_to receive(:get_rest)
+ synchronizer.sync_cookbooks
+ end
+ end
+ end
end
-
end
-
diff --git a/spec/unit/cookbook_uploader_spec.rb b/spec/unit/cookbook_uploader_spec.rb
new file mode 100644
index 0000000000..af25baff13
--- /dev/null
+++ b/spec/unit/cookbook_uploader_spec.rb
@@ -0,0 +1,160 @@
+#
+# Author:: Daniel DeLeo (<dan@getchef.com>)
+# Copyright:: Copyright (c) 2014 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::CookbookUploader do
+
+ let(:http_client) { double("Chef::REST") }
+
+ let(:cookbook_loader) do
+ loader = Chef::CookbookLoader.new(File.join(CHEF_SPEC_DATA, "cookbooks"))
+ loader.load_cookbooks
+ loader
+ end
+
+ let(:apache2_cookbook) { cookbook_loader.cookbooks_by_name["apache2"] }
+
+ let(:java_cookbook) { cookbook_loader.cookbooks_by_name["java"] }
+
+ let(:cookbooks_to_upload) { [apache2_cookbook, java_cookbook] }
+
+ let(:checksums_of_cookbook_files) { apache2_cookbook.checksums.merge(java_cookbook.checksums) }
+
+ let(:checksums_set) do
+ checksums_of_cookbook_files.keys.inject({}) do |set, cksum|
+ set[cksum] = nil
+ set
+ end
+ end
+
+ let(:sandbox_commit_uri) { "https://chef.example.org/sandboxes/abc123" }
+
+ let(:uploader) { described_class.new(cookbooks_to_upload, :rest => http_client) }
+
+ it "has a list of cookbooks to upload" do
+ expect(uploader.cookbooks).to eq(cookbooks_to_upload)
+ end
+
+ it "creates an HTTP client with default configuration when not initialized with one" do
+ default_http_client = double("Chef::REST")
+ expect(Chef::REST).to receive(:new).with(Chef::Config[:chef_server_url]).and_return(default_http_client)
+ uploader = described_class.new(cookbooks_to_upload)
+ expect(uploader.rest).to eq(default_http_client)
+ end
+
+ describe "uploading cookbooks" do
+
+ def url_for(cksum)
+ "https://storage.example.com/#{cksum}"
+ end
+
+ let(:sandbox_response) do
+ sandbox_checksums = cksums_not_on_remote.inject({}) do |cksum_map, cksum|
+ cksum_map[cksum] = { "needs_upload" => true, "url" => url_for(cksum)}
+ cksum_map
+ end
+ { "checksums" => sandbox_checksums, "uri" => sandbox_commit_uri }
+ end
+
+ def expect_sandbox_create
+ expect(http_client).to receive(:post).
+ with("sandboxes", {:checksums => checksums_set}).
+ and_return(sandbox_response)
+ end
+
+ def expect_checksum_upload
+ checksums_of_cookbook_files.each do |md5, file_path|
+ next unless cksums_not_on_remote.include?(md5)
+
+ upload_headers = {
+ "content-type" => "application/x-binary",
+ "content-md5" => an_instance_of(String),
+ "accept" => "application/json"
+ }
+
+ expect(http_client).to receive(:put).
+ with(url_for(md5), IO.binread(file_path), upload_headers)
+
+ end
+ end
+
+ def expect_sandbox_commit
+ expect(http_client).to receive(:put).with(sandbox_commit_uri, {:is_completed => true})
+ end
+
+ def expect_cookbook_create
+ cookbooks_to_upload.each do |cookbook|
+
+ expect(http_client).to receive(:put).
+ with(cookbook.save_url, cookbook)
+
+ end
+ end
+
+ context "when no files exist on the server" do
+
+ let(:cksums_not_on_remote) do
+ checksums_of_cookbook_files.keys
+ end
+
+ it "uploads all files in a sandbox transaction, then creates cookbooks on the server" do
+ expect_sandbox_create
+ expect_checksum_upload
+ expect_sandbox_commit
+ expect_cookbook_create
+
+ uploader.upload_cookbooks
+ end
+
+ end
+
+ context "when some files exist on the server" do
+
+ let(:cksums_not_on_remote) do
+ checksums_of_cookbook_files.keys[0, 1]
+ end
+
+ it "uploads all files in a sandbox transaction, then creates cookbooks on the server" do
+ expect_sandbox_create
+ expect_checksum_upload
+ expect_sandbox_commit
+ expect_cookbook_create
+
+ uploader.upload_cookbooks
+ end
+
+ end
+
+ context "when all files already exist on the server" do
+
+ let(:cksums_not_on_remote) { [] }
+
+ it "uploads all files in a sandbox transaction, then creates cookbooks on the server" do
+ expect_sandbox_create
+ expect_checksum_upload
+ expect_sandbox_commit
+ expect_cookbook_create
+
+ uploader.upload_cookbooks
+ end
+
+ end
+ end
+
+end
diff --git a/spec/unit/dsl/recipe_spec.rb b/spec/unit/dsl/recipe_spec.rb
index 14ee30be44..dfaad0b73e 100644
--- a/spec/unit/dsl/recipe_spec.rb
+++ b/spec/unit/dsl/recipe_spec.rb
@@ -46,6 +46,18 @@ describe Chef::DSL::Recipe do
it "responds to recipe_name" do
expect(recipe.recipe_name).to eq(recipe_name)
end
+
+ it "responds to shell_out" do
+ expect(recipe.respond_to?(:shell_out)).to be true
+ end
+
+ it "responds to shell_out" do
+ expect(recipe.respond_to?(:shell_out!)).to be true
+ end
+
+ it "responds to shell_out" do
+ expect(recipe.respond_to?(:shell_out_with_systems_locale)).to be true
+ end
end
context "when included in a class that defines the required interface directly" do
diff --git a/spec/unit/formatters/base_spec.rb b/spec/unit/formatters/base_spec.rb
new file mode 100644
index 0000000000..6a843ea775
--- /dev/null
+++ b/spec/unit/formatters/base_spec.rb
@@ -0,0 +1,48 @@
+#
+# Author:: Lamont Granquist (<lamont@getchef.com>)
+#
+# Copyright:: Copyright (c) 2012 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::Formatters::Base do
+ let(:out) { double("out") }
+ let(:err) { double("err") }
+ let(:formatter) { Chef::Formatters::Base.new(out, err) }
+
+ it "starts with an indentation of zero" do
+ expect(formatter.output.indent).to eql(0)
+ end
+
+ it "increments it to two correctly" do
+ formatter.indent_by(2)
+ expect(formatter.output.indent).to eql(2)
+ end
+
+ it "increments it and then decrements it corectly" do
+ formatter.indent_by(2)
+ formatter.indent_by(-2)
+ expect(formatter.output.indent).to eql(0)
+ end
+
+ it "does not allow negative indentation" do
+ formatter.indent_by(-2)
+ expect(formatter.output.indent).to eql(0)
+ end
+end
+
+
diff --git a/spec/unit/http/json_input_spec.rb b/spec/unit/http/json_input_spec.rb
new file mode 100644
index 0000000000..fbf8f22503
--- /dev/null
+++ b/spec/unit/http/json_input_spec.rb
@@ -0,0 +1,128 @@
+#--
+# Author:: Daniel DeLeo (<dan@getchef.com>)
+# Copyright:: Copyright (c) 2014 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/http/json_input'
+
+describe Chef::HTTP::JSONInput do
+
+ let(:json_encoder) { described_class.new() }
+
+ let(:url) { URI.parse("http://example.com") }
+ let(:headers) { {} }
+
+ def handle_request
+ json_encoder.handle_request(http_method, url, headers, data)
+ end
+
+ it "passes the response unmodified" do
+ http_response = double("Net::HTTPSuccess")
+ request = double("Chef::HTTP::HTTPRequest")
+ return_value = "response body"
+
+ result = json_encoder.handle_response(http_response, request, return_value)
+ expect(result).to eq([http_response, request, return_value])
+ end
+
+ it "doesn't handle streaming responses" do
+ http_response = double("Net::HTTPSuccess")
+ expect(json_encoder.stream_response_handler(http_response)).to be nil
+ end
+
+ it "does nothing for stream completion" do
+ http_response = double("Net::HTTPSuccess")
+ request = double("Chef::HTTP::HTTPRequest")
+ return_value = "response body"
+
+ result = json_encoder.handle_response(http_response, request, return_value)
+ expect(result).to eq([http_response, request, return_value])
+ end
+
+ context "when handling a request with no body" do
+
+ let(:http_method) { :get }
+ let(:data) { nil }
+
+ it "passes the request unmodified" do
+ expect(handle_request).to eq([http_method, url, headers, data])
+ end
+ end
+
+ context "when the request should be serialized" do
+
+ let(:http_method) { :put }
+ let(:data) { {foo: "bar"} }
+ let(:expected_data) { %q[{"foo":"bar"}] }
+
+ context "and the request has a ruby object as the body and no explicit content-type" do
+
+ it "serializes the body to json" do
+ # Headers Hash get mutated, so we start by asserting it's empty:
+ expect(headers).to be_empty
+
+ expect(handle_request).to eq([http_method, url, headers, expected_data])
+
+ # Now the headers Hash should have json content type:
+ expect(headers).to have_key("Content-Type")
+ expect(headers["Content-Type"]).to eq("application/json")
+ end
+ end
+
+ context "ant the request has an explicit content type of json" do
+
+ it "serializes the body to json when content-type is all lowercase" do
+ headers["content-type"] = "application/json"
+
+ expect(handle_request).to eq([http_method, url, headers, expected_data])
+
+ # Content-Type header should be normalized:
+ expect(headers.size).to eq(1)
+ expect(headers).to have_key("Content-Type")
+ expect(headers["Content-Type"]).to eq("application/json")
+ end
+
+ end
+
+ end
+
+ context "when handling a request with an explicit content type other than json" do
+
+ let(:http_method) { :put }
+ let(:data) { "some arbitrary bytes" }
+
+ it "does not serialize the body to json when content type is given as lowercase" do
+ headers["content-type"] = "application/x-binary"
+
+ expect(handle_request).to eq([http_method, url, headers, data])
+
+ # not normalized
+ expect(headers).to eq({"content-type" => "application/x-binary"})
+ end
+
+ it "does not serialize the body to json when content type is given in capitalized form" do
+ headers["Content-Type"] = "application/x-binary"
+
+ expect(handle_request).to eq([http_method, url, headers, data])
+
+ # not normalized
+ expect(headers).to eq({"Content-Type" => "application/x-binary"})
+ end
+
+ end
+
+end
diff --git a/spec/unit/knife/client_create_spec.rb b/spec/unit/knife/client_create_spec.rb
index 897cee8974..59238d69ec 100644
--- a/spec/unit/knife/client_create_spec.rb
+++ b/spec/unit/knife/client_create_spec.rb
@@ -35,15 +35,15 @@ describe Chef::Knife::ClientCreate do
@knife.stub(:edit_data).and_return(@client)
@knife.stub(:puts)
Chef::ApiClient.stub(:new).and_return(@client)
- @stdout = StringIO.new
- @knife.ui.stub(:stdout).and_return(@stdout)
+ @stderr = StringIO.new
+ @knife.ui.stub(:stderr).and_return(@stderr)
end
describe "run" do
it "should create a new Client" do
Chef::ApiClient.should_receive(:new).and_return(@client)
@knife.run
- @stdout.string.should match /created client.+adam/i
+ @stderr.string.should match /created client.+adam/i
end
it "should set the Client name" do
diff --git a/spec/unit/knife/configure_client_spec.rb b/spec/unit/knife/configure_client_spec.rb
index d101780317..de2a5a41e5 100644
--- a/spec/unit/knife/configure_client_spec.rb
+++ b/spec/unit/knife/configure_client_spec.rb
@@ -25,8 +25,8 @@ describe Chef::Knife::ConfigureClient do
Chef::Config[:validation_client_name] = 'chef-validator'
Chef::Config[:validation_key] = '/etc/chef/validation.pem'
- @stdout = StringIO.new
- @knife.ui.stub(:stdout).and_return(@stdout)
+ @stderr = StringIO.new
+ @knife.ui.stub(:stderr).and_return(@stderr)
end
describe 'run' do
@@ -73,11 +73,12 @@ describe Chef::Knife::ConfigureClient do
it 'should print information on what is being configured' do
FileUtils.stub(:mkdir_p)
@knife.run
- @stdout.string.should match /creating client configuration/i
- @stdout.string.should match /writing client\.rb/i
- @stdout.string.should match /writing validation\.pem/i
+ @stderr.string.should match /creating client configuration/i
+ @stderr.string.should match /writing client\.rb/i
+ @stderr.string.should match /writing validation\.pem/i
end
end
end
end
+
diff --git a/spec/unit/knife/cookbook_delete_spec.rb b/spec/unit/knife/cookbook_delete_spec.rb
index f4ba46f513..53b120be71 100644
--- a/spec/unit/knife/cookbook_delete_spec.rb
+++ b/spec/unit/knife/cookbook_delete_spec.rb
@@ -204,7 +204,7 @@ describe Chef::Knife::CookbookDelete do
it 'should output that the cookbook was deleted' do
@knife.stub(:delete_request)
@knife.delete_version_without_confirmation('1.0.0')
- @stdout.string.should match /deleted cookbook\[foobar\]\[1.0.0\]/im
+ @stderr.string.should match /deleted cookbook\[foobar\]\[1.0.0\]/im
end
describe 'with --print-after' do
diff --git a/spec/unit/knife/cookbook_download_spec.rb b/spec/unit/knife/cookbook_download_spec.rb
index efab98f646..6f40a3396b 100644
--- a/spec/unit/knife/cookbook_download_spec.rb
+++ b/spec/unit/knife/cookbook_download_spec.rb
@@ -21,8 +21,8 @@ require 'spec_helper'
describe Chef::Knife::CookbookDownload do
before(:each) do
@knife = Chef::Knife::CookbookDownload.new
- @stdout = StringIO.new
- @knife.ui.stub(:stdout).and_return(@stdout)
+ @stderr = StringIO.new
+ @knife.ui.stub(:stderr).and_return(@stderr)
end
describe 'run' do
@@ -121,10 +121,10 @@ describe Chef::Knife::CookbookDownload do
File.should_receive(:exists?).with('/var/tmp/chef/foobar-1.0.0').and_return(false)
@knife.run
['attributes', 'recipes', 'templates'].each do |segment|
- @stdout.string.should match /downloading #{segment}/im
+ @stderr.string.should match /downloading #{segment}/im
end
- @stdout.string.should match /downloading foobar cookbook version 1\.0\.0/im
- @stdout.string.should match /cookbook downloaded to \/var\/tmp\/chef\/foobar-1\.0\.0/im
+ @stderr.string.should match /downloading foobar cookbook version 1\.0\.0/im
+ @stderr.string.should match /cookbook downloaded to \/var\/tmp\/chef\/foobar-1\.0\.0/im
end
describe 'with -f or --force' do
diff --git a/spec/unit/knife/cookbook_metadata_spec.rb b/spec/unit/knife/cookbook_metadata_spec.rb
index 26ff43829c..1d6568739c 100644
--- a/spec/unit/knife/cookbook_metadata_spec.rb
+++ b/spec/unit/knife/cookbook_metadata_spec.rb
@@ -119,7 +119,7 @@ describe Chef::Knife::CookbookMetadata do
Chef::JSONCompat.should_receive(:to_json_pretty).with(@metadata_mock).
and_return(@json_data)
@knife.generate_metadata_from_file('foobar', "#{@cookbook_dir}/foobar/metadata.rb")
- @stdout.string.should match /generating metadata for foobar from #{@cookbook_dir}\/foobar\/metadata\.rb/im
+ @stderr.string.should match /generating metadata for foobar from #{@cookbook_dir}\/foobar\/metadata\.rb/im
end
{ Chef::Exceptions::ObsoleteDependencySyntax => 'obsolote dependency',
diff --git a/spec/unit/knife/cookbook_site_download_spec.rb b/spec/unit/knife/cookbook_site_download_spec.rb
index faf58f7bc7..7cd71c2211 100644
--- a/spec/unit/knife/cookbook_site_download_spec.rb
+++ b/spec/unit/knife/cookbook_site_download_spec.rb
@@ -25,7 +25,7 @@ describe Chef::Knife::CookbookSiteDownload do
@knife = Chef::Knife::CookbookSiteDownload.new
@knife.name_args = ['apache2']
@noauth_rest = double('no auth rest')
- @stdout = StringIO.new
+ @stderr = StringIO.new
@cookbook_api_url = 'http://cookbooks.opscode.com/api/v1/cookbooks'
@version = '1.0.2'
@version_us = @version.gsub '.', '_'
@@ -33,7 +33,7 @@ describe Chef::Knife::CookbookSiteDownload do
'latest_version' => "#{@cookbook_api_url}/apache2/versions/#{@version_us}",
'replacement' => 'other_apache2' }
- @knife.ui.stub(:stdout).and_return(@stdout)
+ @knife.ui.stub(:stderr).and_return(@stderr)
@knife.stub(:noauth_rest).and_return(@noauth_rest)
@noauth_rest.should_receive(:get_rest).
with("#{@cookbook_api_url}/apache2").
@@ -85,8 +85,8 @@ describe Chef::Knife::CookbookSiteDownload do
with(/.+deprecated.+replaced by other_apache2.+/i)
FileUtils.should_receive(:cp).with(@temp_file.path, @file)
@knife.run
- @stdout.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i
- @stdout.string.should match /cookbook save.+#{Regexp.escape(@file)}/i
+ @stderr.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i
+ @stderr.string.should match /cookbook save.+#{Regexp.escape(@file)}/i
end
end
@@ -94,8 +94,8 @@ describe Chef::Knife::CookbookSiteDownload do
it 'should download the latest version' do
FileUtils.should_receive(:cp).with(@temp_file.path, @file)
@knife.run
- @stdout.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i
- @stdout.string.should match /cookbook save.+#{Regexp.escape(@file)}/i
+ @stderr.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i
+ @stderr.string.should match /cookbook save.+#{Regexp.escape(@file)}/i
end
context 'with -f or --file' do
@@ -107,8 +107,8 @@ describe Chef::Knife::CookbookSiteDownload do
it 'should download the cookbook to the desired file' do
@knife.run
- @stdout.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i
- @stdout.string.should match /cookbook save.+#{Regexp.escape(@file)}/i
+ @stderr.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i
+ @stderr.string.should match /cookbook save.+#{Regexp.escape(@file)}/i
end
end
@@ -139,8 +139,8 @@ describe Chef::Knife::CookbookSiteDownload do
and_return(@temp_file)
FileUtils.should_receive(:cp).with(@temp_file.path, @file)
@knife.run
- @stdout.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i
- @stdout.string.should match /cookbook save.+#{Regexp.escape(@file)}/i
+ @stderr.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i
+ @stderr.string.should match /cookbook save.+#{Regexp.escape(@file)}/i
end
end
diff --git a/spec/unit/knife/cookbook_site_share_spec.rb b/spec/unit/knife/cookbook_site_share_spec.rb
index 28b2a509fd..a46783274b 100644
--- a/spec/unit/knife/cookbook_site_share_spec.rb
+++ b/spec/unit/knife/cookbook_site_share_spec.rb
@@ -34,7 +34,7 @@ describe Chef::Knife::CookbookSiteShare do
@cookbook_loader.stub(:[]).and_return(@cookbook)
Chef::CookbookLoader.stub(:new).and_return(@cookbook_loader)
- @cookbook_uploader = Chef::CookbookUploader.new('herpderp', File.join(CHEF_SPEC_DATA, 'cookbooks'), :rest => "norest")
+ @cookbook_uploader = Chef::CookbookUploader.new('herpderp', :rest => "norest")
Chef::CookbookUploader.stub(:new).and_return(@cookbook_uploader)
@cookbook_uploader.stub(:validate_cookbooks).and_return(true)
Chef::CookbookSiteStreamingUploader.stub(:create_build_dir).and_return(Dir.mktmpdir)
@@ -77,7 +77,7 @@ describe Chef::Knife::CookbookSiteShare do
it 'should make a tarball of the cookbook' do
@knife.should_receive(:shell_out!) do |args|
- args.to_s.should match /tar -czf/
+ args.to_s.should match(/tar -czf/)
end
@knife.run
end
diff --git a/spec/unit/knife/cookbook_upload_spec.rb b/spec/unit/knife/cookbook_upload_spec.rb
index 6a99a80459..e5c9a40cf1 100644
--- a/spec/unit/knife/cookbook_upload_spec.rb
+++ b/spec/unit/knife/cookbook_upload_spec.rb
@@ -61,8 +61,9 @@ describe Chef::Knife::CookbookUpload do
test_cookbook = Chef::CookbookVersion.new('test_cookbook', '/tmp/blah')
cookbook_loader.stub(:each).and_yield("test_cookbook", test_cookbook)
cookbook_loader.stub(:cookbook_names).and_return(["test_cookbook"])
- Chef::CookbookUploader.should_receive(:new).with( kind_of(Array), kind_of(Array),
- {:force=>nil, :concurrency => 3}).and_return(double("Chef::CookbookUploader", :upload_cookbooks=> true))
+ Chef::CookbookUploader.should_receive(:new).
+ with( kind_of(Array), { :force => nil, :concurrency => 3}).
+ and_return(double("Chef::CookbookUploader", :upload_cookbooks=> true))
knife.run
end
end
diff --git a/spec/unit/knife/tag_create_spec.rb b/spec/unit/knife/tag_create_spec.rb
index 82e3ad68cd..bafea8d268 100644
--- a/spec/unit/knife/tag_create_spec.rb
+++ b/spec/unit/knife/tag_create_spec.rb
@@ -9,15 +9,15 @@ describe Chef::Knife::TagCreate do
@node = Chef::Node.new
@node.stub :save
Chef::Node.stub(:load).and_return @node
- @stdout = StringIO.new
- @knife.ui.stub(:stdout).and_return(@stdout)
+ @stderr = StringIO.new
+ @knife.ui.stub(:stderr).and_return(@stderr)
end
describe "run" do
it "can create tags on a node" do
@knife.run
@node.tags.should == ["happytag"]
- @stdout.string.should match /created tags happytag.+node webmonkey.example.com/i
+ @stderr.string.should match /created tags happytag.+node webmonkey.example.com/i
end
end
end
diff --git a/spec/unit/knife/tag_delete_spec.rb b/spec/unit/knife/tag_delete_spec.rb
index 67e3dd3ff0..514228f0a2 100644
--- a/spec/unit/knife/tag_delete_spec.rb
+++ b/spec/unit/knife/tag_delete_spec.rb
@@ -10,8 +10,8 @@ describe Chef::Knife::TagDelete do
@node.stub :save
@node.tags << "sadtag" << "happytag"
Chef::Node.stub(:load).and_return @node
- @stdout = StringIO.new
- @knife.ui.stub(:stdout).and_return(@stdout)
+ @stderr = StringIO.new
+ @knife.ui.stub(:stderr).and_return(@stderr)
end
describe "run" do
@@ -19,7 +19,7 @@ describe Chef::Knife::TagDelete do
@node.tags.should == ["sadtag", "happytag"]
@knife.run
@node.tags.should == ["happytag"]
- @stdout.string.should match /deleted.+sadtag/i
+ @stderr.string.should match /deleted.+sadtag/i
end
end
end
diff --git a/spec/unit/knife/user_create_spec.rb b/spec/unit/knife/user_create_spec.rb
index 039d4659b0..58ef868053 100644
--- a/spec/unit/knife/user_create_spec.rb
+++ b/spec/unit/knife/user_create_spec.rb
@@ -46,7 +46,7 @@ describe Chef::Knife::UserCreate do
Chef::User.should_receive(:new).and_return(@user)
@user.should_receive(:create)
@knife.run
- @stdout.string.should match /created user.+a_user/i
+ @stderr.string.should match /created user.+a_user/i
end
it "sets the password" do
diff --git a/spec/unit/knife_spec.rb b/spec/unit/knife_spec.rb
index 52784741d7..70b60a2f96 100644
--- a/spec/unit/knife_spec.rb
+++ b/spec/unit/knife_spec.rb
@@ -41,7 +41,7 @@ describe Chef::Knife do
Chef::Log.stub(level_sym)
end
Chef::Knife.stub(:puts)
- @stdout = StringIO.new
+ @stderr = StringIO.new
end
describe "selecting a config file" do
@@ -241,7 +241,7 @@ describe Chef::Knife do
end
it "exits if no subcommand matches the CLI args" do
- Chef::Knife.ui.stub(:stdout).and_return(@stdout)
+ Chef::Knife.ui.stub(:stderr).and_return(@stderr)
Chef::Knife.ui.should_receive(:fatal)
lambda {Chef::Knife.run(%w{fuuu uuuu fuuuu})}.should raise_error(SystemExit) { |e| e.status.should_not == 0 }
end
@@ -326,7 +326,7 @@ describe Chef::Knife do
@knife.stub(:run).and_raise(Net::HTTPServerException.new("401 Unauthorized", response))
@knife.run_with_pretty_exceptions
@stderr.string.should match(/ERROR: Failed to authenticate to/)
- @stdout.string.should match(/Response: y u no syncronize your clock\?/)
+ @stderr.string.should match(/Response: y u no syncronize your clock\?/)
end
it "formats 403s nicely" do
@@ -337,7 +337,7 @@ describe Chef::Knife do
@knife.stub(:username).and_return("sadpanda")
@knife.run_with_pretty_exceptions
@stderr.string.should match(%r[ERROR: You authenticated successfully to http.+ as sadpanda but you are not authorized for this action])
- @stdout.string.should match(%r[Response: y u no administrator])
+ @stderr.string.should match(%r[Response: y u no administrator])
end
it "formats 400s nicely" do
@@ -347,7 +347,7 @@ describe Chef::Knife do
@knife.stub(:run).and_raise(Net::HTTPServerException.new("400 Bad Request", response))
@knife.run_with_pretty_exceptions
@stderr.string.should match(%r[ERROR: The data in your request was invalid])
- @stdout.string.should match(%r[Response: y u search wrong])
+ @stderr.string.should match(%r[Response: y u search wrong])
end
it "formats 404s nicely" do
@@ -357,7 +357,7 @@ describe Chef::Knife do
@knife.stub(:run).and_raise(Net::HTTPServerException.new("404 Not Found", response))
@knife.run_with_pretty_exceptions
@stderr.string.should match(%r[ERROR: The object you are looking for could not be found])
- @stdout.string.should match(%r[Response: nothing to see here])
+ @stderr.string.should match(%r[Response: nothing to see here])
end
it "formats 500s nicely" do
@@ -367,7 +367,7 @@ describe Chef::Knife do
@knife.stub(:run).and_raise(Net::HTTPFatalError.new("500 Internal Server Error", response))
@knife.run_with_pretty_exceptions
@stderr.string.should match(%r[ERROR: internal server error])
- @stdout.string.should match(%r[Response: sad trombone])
+ @stderr.string.should match(%r[Response: sad trombone])
end
it "formats 502s nicely" do
@@ -377,7 +377,7 @@ describe Chef::Knife do
@knife.stub(:run).and_raise(Net::HTTPFatalError.new("502 Bad Gateway", response))
@knife.run_with_pretty_exceptions
@stderr.string.should match(%r[ERROR: bad gateway])
- @stdout.string.should match(%r[Response: sadder trombone])
+ @stderr.string.should match(%r[Response: sadder trombone])
end
it "formats 503s nicely" do
@@ -387,7 +387,7 @@ describe Chef::Knife do
@knife.stub(:run).and_raise(Net::HTTPFatalError.new("503 Service Unavailable", response))
@knife.run_with_pretty_exceptions
@stderr.string.should match(%r[ERROR: Service temporarily unavailable])
- @stdout.string.should match(%r[Response: saddest trombone])
+ @stderr.string.should match(%r[Response: saddest trombone])
end
it "formats other HTTP errors nicely" do
@@ -397,15 +397,15 @@ describe Chef::Knife do
@knife.stub(:run).and_raise(Net::HTTPServerException.new("402 Payment Required", response))
@knife.run_with_pretty_exceptions
@stderr.string.should match(%r[ERROR: Payment Required])
- @stdout.string.should match(%r[Response: nobugfixtillyoubuy])
+ @stderr.string.should match(%r[Response: nobugfixtillyoubuy])
end
it "formats NameError and NoMethodError nicely" do
@knife.stub(:run).and_raise(NameError.new("Undefined constant FUUU"))
@knife.run_with_pretty_exceptions
@stderr.string.should match(%r[ERROR: knife encountered an unexpected error])
- @stdout.string.should match(%r[This may be a bug in the 'knife' knife command or plugin])
- @stdout.string.should match(%r[Exception: NameError: Undefined constant FUUU])
+ @stderr.string.should match(%r[This may be a bug in the 'knife' knife command or plugin])
+ @stderr.string.should match(%r[Exception: NameError: Undefined constant FUUU])
end
it "formats missing private key errors nicely" do
@@ -413,7 +413,7 @@ describe Chef::Knife do
@knife.stub(:api_key).and_return("/home/root/.chef/no-key-here.pem")
@knife.run_with_pretty_exceptions
@stderr.string.should match(%r[ERROR: Your private key could not be loaded from /home/root/.chef/no-key-here.pem])
- @stdout.string.should match(%r[Check your configuration file and ensure that your private key is readable])
+ @stderr.string.should match(%r[Check your configuration file and ensure that your private key is readable])
end
it "formats connection refused errors nicely" do
@@ -423,7 +423,7 @@ describe Chef::Knife do
# *nix = Errno::ECONNREFUSED: Connection refused
# win32: Errno::ECONNREFUSED: No connection could be made because the target machine actively refused it.
@stderr.string.should match(%r[ERROR: Network Error: .* - y u no shut up])
- @stdout.string.should match(%r[Check your knife configuration and network settings])
+ @stderr.string.should match(%r[Check your knife configuration and network settings])
end
end
diff --git a/spec/unit/lwrp_spec.rb b/spec/unit/lwrp_spec.rb
index 9a775f2dff..960aff3c36 100644
--- a/spec/unit/lwrp_spec.rb
+++ b/spec/unit/lwrp_spec.rb
@@ -180,6 +180,19 @@ describe "LWRP" do
end
end
+ describe "when #default_action is an array" do
+ let(:lwrp) do
+ Class.new(Chef::Resource::LWRPBase) do
+ actions :eat, :sleep
+ default_action [:eat, :sleep]
+ end
+ end
+
+ it "returns the array of default actions" do
+ expect(lwrp.default_action).to eq([:eat, :sleep])
+ end
+ end
+
describe "when inheriting from LWRPBase" do
let(:parent) do
Class.new(Chef::Resource::LWRPBase) do
diff --git a/spec/unit/mixin/template_spec.rb b/spec/unit/mixin/template_spec.rb
index 3aa0b9ba22..63fa81782e 100644
--- a/spec/unit/mixin/template_spec.rb
+++ b/spec/unit/mixin/template_spec.rb
@@ -76,7 +76,7 @@ describe Chef::Mixin::Template, "render_template" do
describe "with a template resource" do
before :each do
@cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) }
+ Chef::Cookbook::FileVendor.fetch_from_disk(@cookbook_repo)
@node = Chef::Node.new
cl = Chef::CookbookLoader.new(@cookbook_repo)
diff --git a/spec/unit/provider/http_request_spec.rb b/spec/unit/provider/http_request_spec.rb
index 605287fcc3..3077685b97 100644
--- a/spec/unit/provider/http_request_spec.rb
+++ b/spec/unit/provider/http_request_spec.rb
@@ -53,13 +53,13 @@ describe Chef::Provider::HttpRequest do
it "should inflate a message block at runtime" do
@new_resource.message { "return" }
- @http.should_receive(:get).with("http://www.opscode.com/?message=return", {})
+ @http.should_receive(:get).with("http://www.opscode.com/", {})
@provider.run_action(:get)
@new_resource.should be_updated
end
it "should run a GET request" do
- @http.should_receive(:get).with("http://www.opscode.com/?message=is cool", {})
+ @http.should_receive(:get).with("http://www.opscode.com/", {})
@provider.run_action(:get)
@new_resource.should be_updated
end
@@ -112,25 +112,25 @@ describe Chef::Provider::HttpRequest do
it "should inflate a message block at runtime" do
@new_resource.message { "return" }
- @http.should_receive(:head).with("http://www.opscode.com/?message=return", {}).and_return(nil)
+ @http.should_receive(:head).with("http://www.opscode.com/", {}).and_return(nil)
@provider.run_action(:head)
@new_resource.should be_updated
end
it "should run a HEAD request" do
- @http.should_receive(:head).with("http://www.opscode.com/?message=is cool", {}).and_return(nil)
+ @http.should_receive(:head).with("http://www.opscode.com/", {}).and_return(nil)
@provider.run_action(:head)
@new_resource.should be_updated
end
it "should update a HEAD request with empty string response body (CHEF-4762)" do
- @http.should_receive(:head).with("http://www.opscode.com/?message=is cool", {}).and_return("")
+ @http.should_receive(:head).with("http://www.opscode.com/", {}).and_return("")
@provider.run_action(:head)
@new_resource.should be_updated
end
it "should update a HEAD request with nil response body (CHEF-4762)" do
- @http.should_receive(:head).with("http://www.opscode.com/?message=is cool", {}).and_return(nil)
+ @http.should_receive(:head).with("http://www.opscode.com/", {}).and_return(nil)
@provider.run_action(:head)
@new_resource.should be_updated
end
@@ -138,14 +138,14 @@ describe Chef::Provider::HttpRequest do
it "should not update a HEAD request if a not modified response (CHEF-4762)" do
if_modified_since = File.mtime(__FILE__).httpdate
@new_resource.headers "If-Modified-Since" => if_modified_since
- @http.should_receive(:head).with("http://www.opscode.com/?message=is cool", {"If-Modified-Since" => if_modified_since}).and_return(false)
+ @http.should_receive(:head).with("http://www.opscode.com/", {"If-Modified-Since" => if_modified_since}).and_return(false)
@provider.run_action(:head)
@new_resource.should_not be_updated
end
it "should run a HEAD request with If-Modified-Since header" do
@new_resource.headers "If-Modified-Since" => File.mtime(__FILE__).httpdate
- @http.should_receive(:head).with("http://www.opscode.com/?message=is cool", @new_resource.headers)
+ @http.should_receive(:head).with("http://www.opscode.com/", @new_resource.headers)
@provider.run_action(:head)
end
diff --git a/spec/unit/provider/log_spec.rb b/spec/unit/provider/log_spec.rb
index 8f411e461a..f6ff526dd4 100644
--- a/spec/unit/provider/log_spec.rb
+++ b/spec/unit/provider/log_spec.rb
@@ -78,22 +78,4 @@ describe Chef::Provider::Log::ChefLog do
@provider.action_write
end
- it "should not update the resource if the message was not written to the log" do
- Chef::Log.level = :fatal
- @new_resource = Chef::Resource::Log.new(@log_str)
- @new_resource.level :info
- @provider = Chef::Provider::Log::ChefLog.new(@new_resource, @run_context)
- @provider.action_write
- @new_resource.updated.should be_false
- end
-
- it "should update the resource if the message has been written to the log" do
- Chef::Log.level = :debug
- @new_resource = Chef::Resource::Log.new(@log_str)
- @new_resource.level :info
- @provider = Chef::Provider::Log::ChefLog.new(@new_resource, @run_context)
- @provider.action_write
- @new_resource.updated.should be_true
- end
-
end
diff --git a/spec/unit/provider/package_spec.rb b/spec/unit/provider/package_spec.rb
index 33b4f8186a..375a0d0646 100644
--- a/spec/unit/provider/package_spec.rb
+++ b/spec/unit/provider/package_spec.rb
@@ -339,7 +339,7 @@ describe Chef::Provider::Package do
describe "when given a response file" do
before(:each) do
@cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) }
+ Chef::Cookbook::FileVendor.fetch_from_disk(@cookbook_repo)
@node = Chef::Node.new
cl = Chef::CookbookLoader.new(@cookbook_repo)
diff --git a/spec/unit/provider/remote_directory_spec.rb b/spec/unit/provider/remote_directory_spec.rb
index d3f1438f0f..b986e2c8ad 100644
--- a/spec/unit/provider/remote_directory_spec.rb
+++ b/spec/unit/provider/remote_directory_spec.rb
@@ -35,7 +35,7 @@ describe Chef::Provider::RemoteDirectory do
@resource.cookbook('openldap')
@cookbook_repo = ::File.expand_path(::File.join(CHEF_SPEC_DATA, "cookbooks"))
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) }
+ Chef::Cookbook::FileVendor.fetch_from_disk(@cookbook_repo)
@node = Chef::Node.new
cl = Chef::CookbookLoader.new(@cookbook_repo)
diff --git a/spec/unit/provider/template/content_spec.rb b/spec/unit/provider/template/content_spec.rb
index dfc5d21c2a..b419e70519 100644
--- a/spec/unit/provider/template/content_spec.rb
+++ b/spec/unit/provider/template/content_spec.rb
@@ -36,7 +36,7 @@ describe Chef::Provider::Template::Content do
let(:run_context) do
cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) }
+ Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_repo)
cl = Chef::CookbookLoader.new(cookbook_repo)
cl.load_cookbooks
cookbook_collection = Chef::CookbookCollection.new(cl)
diff --git a/spec/unit/provider_spec.rb b/spec/unit/provider_spec.rb
index 363649ec46..9b89fc1888 100644
--- a/spec/unit/provider_spec.rb
+++ b/spec/unit/provider_spec.rb
@@ -61,6 +61,18 @@ describe Chef::Provider do
@provider = Chef::Provider.new(@resource, @run_context)
end
+ it "should mixin shell_out" do
+ expect(@provider.respond_to?(:shell_out)).to be true
+ end
+
+ it "should mixin shell_out!" do
+ expect(@provider.respond_to?(:shell_out!)).to be true
+ end
+
+ it "should mixin shell_out_with_systems_locale" do
+ expect(@provider.respond_to?(:shell_out_with_systems_locale)).to be true
+ end
+
it "should store the resource passed to new as new_resource" do
@provider.new_resource.should eql(@resource)
end
diff --git a/spec/unit/shell/shell_session_spec.rb b/spec/unit/shell/shell_session_spec.rb
index 92a2e5d538..f49c9fc805 100644
--- a/spec/unit/shell/shell_session_spec.rb
+++ b/spec/unit/shell/shell_session_spec.rb
@@ -50,6 +50,7 @@ end
describe Shell::ClientSession do
before do
Chef::Config[:shell_config] = { :override_runlist => [Chef::RunList::RunListItem.new('shell::override')] }
+ @chef_rest = double("Chef::REST")
@session = Shell::ClientSession.instance
@node = Chef::Node.build("foo")
@session.node = @node
@@ -66,6 +67,7 @@ describe Shell::ClientSession do
@expansion = Chef::RunList::RunListExpansion.new(@node.chef_environment, [])
@node.run_list.should_receive(:expand).with(@node.chef_environment).and_return(@expansion)
+ Chef::REST.should_receive(:new).with(Chef::Config[:chef_server_url]).and_return(@chef_rest)
@session.rebuild_context
end