summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md10
-rw-r--r--CONTRIBUTING.md9
-rw-r--r--DOC_CHANGES.md3
-rw-r--r--chef.gemspec4
-rw-r--r--kitchen-tests/test/fixtures/serverspec_helper.rb3
-rw-r--r--kitchen-tests/test/integration/webapp/serverspec/Gemfile4
-rw-r--r--lib/chef/chef_fs/chef_fs_data_store.rb2
-rw-r--r--lib/chef/chef_fs/command_line.rb2
-rw-r--r--lib/chef/chef_fs/file_system/organization_invites_entry.rb3
-rw-r--r--lib/chef/chef_fs/file_system/organization_members_entry.rb3
-rw-r--r--lib/chef/chef_fs/file_system/rest_list_entry.rb3
-rw-r--r--lib/chef/client.rb2
-rw-r--r--lib/chef/cookbook/cookbook_version_loader.rb2
-rw-r--r--lib/chef/cookbook/metadata.rb119
-rw-r--r--lib/chef/cookbook/syntax_check.rb15
-rw-r--r--lib/chef/cookbook_version.rb85
-rw-r--r--lib/chef/dsl/recipe.rb5
-rw-r--r--lib/chef/http.rb2
-rw-r--r--lib/chef/json_compat.rb4
-rw-r--r--lib/chef/knife.rb3
-rw-r--r--lib/chef/knife/bootstrap/archlinux-gems.erb4
-rw-r--r--lib/chef/knife/bootstrap/chef-aix.erb4
-rw-r--r--lib/chef/knife/bootstrap/chef-full.erb4
-rw-r--r--lib/chef/knife/cookbook_create.rb2
-rw-r--r--lib/chef/knife/cookbook_site_share.rb51
-rw-r--r--lib/chef/knife/core/status_presenter.rb156
-rw-r--r--lib/chef/knife/core/ui.rb2
-rw-r--r--lib/chef/knife/status.rb69
-rw-r--r--lib/chef/mixin/command/unix.rb4
-rw-r--r--lib/chef/platform/provider_mapping.rb5
-rw-r--r--lib/chef/provider/cron/unix.rb22
-rw-r--r--lib/chef/provider/dsc_script.rb34
-rw-r--r--lib/chef/provider/execute.rb5
-rw-r--r--lib/chef/provider/git.rb64
-rw-r--r--lib/chef/provider/lwrp_base.rb20
-rw-r--r--lib/chef/provider/package/freebsd/pkgng.rb2
-rw-r--r--lib/chef/provider/package/freebsd/port.rb10
-rw-r--r--lib/chef/provider/package/pacman.rb6
-rw-r--r--lib/chef/provider/package/paludis.rb2
-rw-r--r--lib/chef/provider/package/rubygems.rb1
-rw-r--r--lib/chef/resource/cookbook_file.rb2
-rw-r--r--lib/chef/resource/dsc_script.rb18
-rw-r--r--lib/chef/resource/freebsd_package.rb23
-rw-r--r--lib/chef/resource/lwrp_base.rb39
-rw-r--r--lib/chef/resource/template.rb2
-rw-r--r--lib/chef/util/powershell/cmdlet_result.rb4
-rw-r--r--spec/data/bootstrap/test-hints.erb2
-rw-r--r--spec/data/bootstrap/test.erb2
-rw-r--r--spec/data/cb_version_cookbooks/cookbook2/files/test.txt0
-rw-r--r--spec/data/cb_version_cookbooks/cookbook2/templates/test.erb0
-rw-r--r--spec/data/cookbooks/ignorken/files/default/not_me.rb2
-rw-r--r--spec/data/cookbooks/ignorken/templates/ubuntu-12.10/not_me.rb2
-rw-r--r--spec/data/cookbooks/openldap/libraries/openldap.rb4
-rw-r--r--spec/data/cookbooks/openldap/libraries/openldap/version.rb3
-rw-r--r--spec/data/lwrp/providers/buck_passer.rb11
-rw-r--r--spec/data/lwrp/resources/foo.rb5
-rw-r--r--spec/data/lwrp_override/providers/buck_passer.rb15
-rw-r--r--spec/data/lwrp_override/resources/foo.rb7
-rw-r--r--spec/functional/knife/cookbook_delete_spec.rb6
-rw-r--r--spec/functional/knife/exec_spec.rb2
-rw-r--r--spec/functional/util/powershell/cmdlet_spec.rb4
-rw-r--r--spec/integration/knife/chef_fs_data_store_spec.rb2
-rw-r--r--spec/integration/knife/chef_repo_path_spec.rb2
-rw-r--r--spec/integration/knife/chef_repository_file_system_spec.rb2
-rw-r--r--spec/integration/knife/chefignore_spec.rb2
-rw-r--r--spec/integration/knife/common_options_spec.rb2
-rw-r--r--spec/integration/knife/cookbook_api_ipv6_spec.rb2
-rw-r--r--spec/integration/knife/delete_spec.rb2
-rw-r--r--spec/integration/knife/deps_spec.rb2
-rw-r--r--spec/integration/knife/diff_spec.rb2
-rw-r--r--spec/integration/knife/download_spec.rb2
-rw-r--r--spec/integration/knife/list_spec.rb2
-rw-r--r--spec/integration/knife/raw_spec.rb2
-rw-r--r--spec/integration/knife/redirection_spec.rb2
-rw-r--r--spec/integration/knife/serve_spec.rb2
-rw-r--r--spec/integration/knife/show_spec.rb2
-rw-r--r--spec/integration/knife/upload_spec.rb7
-rw-r--r--spec/spec_helper.rb6
-rw-r--r--spec/support/shared/integration/integration_helper.rb2
-rw-r--r--spec/support/shared/shared_examples.rb14
-rw-r--r--spec/tiny_server.rb3
-rw-r--r--spec/unit/api_client_spec.rb6
-rw-r--r--spec/unit/config_fetcher_spec.rb3
-rw-r--r--spec/unit/cookbook/cookbook_version_loader_spec.rb5
-rw-r--r--spec/unit/cookbook/metadata_spec.rb49
-rw-r--r--spec/unit/cookbook/syntax_check_spec.rb7
-rw-r--r--spec/unit/cookbook_loader_spec.rb2
-rw-r--r--spec/unit/cookbook_version_spec.rb85
-rw-r--r--spec/unit/data_bag_item_spec.rb6
-rw-r--r--spec/unit/data_bag_spec.rb6
-rw-r--r--spec/unit/encrypted_data_bag_item_spec.rb35
-rw-r--r--spec/unit/environment_spec.rb8
-rw-r--r--spec/unit/exceptions_spec.rb6
-rw-r--r--spec/unit/json_compat_spec.rb14
-rw-r--r--spec/unit/knife/cookbook_site_share_spec.rb65
-rw-r--r--spec/unit/knife/core/bootstrap_context_spec.rb4
-rw-r--r--spec/unit/knife/core/ui_spec.rb28
-rw-r--r--spec/unit/knife/data_bag_from_file_spec.rb2
-rw-r--r--spec/unit/knife/status_spec.rb3
-rw-r--r--spec/unit/knife_spec.rb19
-rw-r--r--spec/unit/lwrp_spec.rb37
-rw-r--r--spec/unit/node_spec.rb7
-rw-r--r--spec/unit/platform_spec.rb12
-rw-r--r--spec/unit/provider/cron/unix_spec.rb138
-rw-r--r--spec/unit/provider/dsc_script_spec.rb239
-rw-r--r--spec/unit/provider/execute_spec.rb28
-rw-r--r--spec/unit/provider/git_spec.rb46
-rw-r--r--spec/unit/provider/package/freebsd/pkgng_spec.rb2
-rw-r--r--spec/unit/provider/package/freebsd/port_spec.rb22
-rw-r--r--spec/unit/provider/package/pacman_spec.rb8
-rw-r--r--spec/unit/provider/package/paludis_spec.rb2
-rw-r--r--spec/unit/provider/package/rubygems_spec.rb420
-rw-r--r--spec/unit/provider/remote_file/cache_control_data_spec.rb2
-rw-r--r--spec/unit/recipe_spec.rb9
-rw-r--r--spec/unit/resource/dsc_script_spec.rb29
-rw-r--r--spec/unit/resource/freebsd_package_spec.rb5
-rw-r--r--spec/unit/resource_collection_spec.rb12
-rw-r--r--spec/unit/resource_reporter_spec.rb6
-rw-r--r--spec/unit/resource_spec.rb6
-rw-r--r--spec/unit/role_spec.rb4
-rw-r--r--spec/unit/run_list_spec.rb6
-rw-r--r--spec/unit/user_spec.rb6
122 files changed, 1554 insertions, 810 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 48cd1d2cc4..5b4bdcd9c0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -74,7 +74,12 @@
Improve the regex for /etc/rc.conf for the FreeBSD service provider
* [**Stanislav Bogatyrev**](https://github.com/realloc):
Fetch recipe_url before loading json_attribs in chef-solo (CHEF-5075)
-* [**Mal Graty**](https://github.com/mal): Workaround for a breaking change in git's shallow-clone behavior. (Issue 1563)
+* [**Mal Graty**](https://github.com/mal):
+ Workaround for a breaking change in git's shallow-clone behavior. (Issue 1563)
+* [**Dave Eddy**](https://github.com/bahamas10):
+ Fix version detection in FreeBSD pkgng provider. (PR 1980)
+* [**Dan Rathbone**](https://github.com/rathers):
+ Fixed gem_package resource to be able to upgrade gems when version is not set.
### Chef Contributions
@@ -145,6 +150,9 @@
* Add escape_glob method to PathHelper, update glob operations.
* Verify x509 properties of certificates in the :trusted_certs_dir during knife ssl check.
* Disable unforked interval chef-client runs.
+* Removed dependencies on the 'json' gem, replaced with ffi-yajl. Use Chef::JSONCompat library for parsing and printing.
+* Restore the deprecation logic of #valid_actions in LWRPs until Chef 13.
+* Now that we don't allow unforked chef-client interval runs, remove the reloading of previously defined LWRPs.
## Last Release: 11.14.2
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e6e9a26cad..f8618ad381 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -159,6 +159,15 @@ In order to decrease the back and forth an issues and help us get to the bottom
[What actually happens after the reproduction steps?]
```
+### Useful Github Queries
+
+Contributions go through a review process to improve code quality and avoid regressions. Managing a large number of contributions requires a workflow to provide queues for work such as triage, code review, and merging. A semi-formal process has evolved over the life of the project. Chef maintains this process pending community development and acceptance of an [RFC](https://github.com/opscode/chef-rfc). These queries will help track contributions through this process:
+
+* [Issues that are not assigned to a team](https://github.com/opscode/chef/issues?q=is%3Aopen+-label%3AAIX+-label%3ABSD+-label%3Awindows+-label%3A%22Chef+Core%22++-label%3A%22Dev+Tools%22+-label%3AUbuntu+-label%3A%22Enterprise+Linux%22+-label%3A%22Ready+For+Merge%22+-label%3AMac+-label%3ASolaris+)
+* [Untriaged Issues](https://github.com/opscode/chef/issues?q=is%3Aopen+is%3Aissue+-label%3ABug+-label%3AEnhancement+-label%3A%22Tech+Cleanup%22+-label%3A%22Ready+For+Merge%22)
+* [PRs to be Reviewed](https://github.com/opscode/chef/labels/Pending%20Maintainer%20Review)
+* [Suitable for First Contribution](https://github.com/opscode/chef/labels/Easy)
+
## <a name="release"></a> Chef Release Cycles
Our primary shipping vehicle is operating system specific packages that includes
diff --git a/DOC_CHANGES.md b/DOC_CHANGES.md
index ceccb77cd0..08c343809a 100644
--- a/DOC_CHANGES.md
+++ b/DOC_CHANGES.md
@@ -467,7 +467,6 @@ PathHelper = Chef::Util::PathHelper
Dir.glob(File.join(PathHelper.escape_glob(path), "*")) # ["#{path}\\apache2", "#{path}\\apt", ...]
Dir[PathHelper.escape_glob(path) + "/*"] # ["#{path}\\apache2", "#{path}\\apt", ...]
```
-
## Mac OS X default package provider is now Homebrew
Per [Chef RFC 016](https://github.com/opscode/chef-rfc/blob/master/rfc016-homebrew-osx-package-provider.md), the default provider for the `package` resource on Mac OS X is now [Homebrew](http://brew.sh). The [homebrew cookbook's](https://supermarket.getchef.com/cookbooks/homebrew) default recipe, or some other method is still required for getting homebrew installed on the system. The cookbook won't be strictly required just to install packages from homebrew on OS X, though. To use this, simply use the `package` resource, or the `homebrew_package` shortcut resource:
@@ -521,4 +520,4 @@ end
```
Chef will then execute the Homebrew command as that user. The `homebrew_user` attribute can only be provided to the
-`homebrew_package` resource, not the `package` resource. \ No newline at end of file
+`homebrew_package` resource, not the `package` resource.
diff --git a/chef.gemspec b/chef.gemspec
index 481b120fe6..075d1fc5d6 100644
--- a/chef.gemspec
+++ b/chef.gemspec
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
s.add_dependency "mixlib-shellout", ">= 2.0.0.rc.0", "< 3.0"
s.add_dependency "ohai", ">= 7.6.0.rc.0"
- s.add_dependency "ffi-yajl", "~> 1.0", ">= 1.0.2"
+ s.add_dependency "ffi-yajl", "~> 1.2"
s.add_dependency "net-ssh", "~> 2.6"
s.add_dependency "net-ssh-multi", "~> 1.1"
# CHEF-3027: The knife-cloud plugins require newer features from highline, core chef should not.
@@ -30,7 +30,7 @@ Gem::Specification.new do |s|
s.add_dependency "erubis", "~> 2.7"
s.add_dependency "diff-lcs", "~> 1.2", ">= 1.2.4"
- s.add_dependency "chef-zero", "~> 3.1"
+ s.add_dependency "chef-zero", "~> 3.2"
s.add_dependency "pry", "~> 0.9"
s.add_dependency 'plist', '~> 3.1.0'
diff --git a/kitchen-tests/test/fixtures/serverspec_helper.rb b/kitchen-tests/test/fixtures/serverspec_helper.rb
index 6e6d71e79b..48963dc45d 100644
--- a/kitchen-tests/test/fixtures/serverspec_helper.rb
+++ b/kitchen-tests/test/fixtures/serverspec_helper.rb
@@ -4,6 +4,7 @@
require 'serverspec'
require 'json'
+require 'ffi_yajl'
set :backend, :exec
@@ -21,7 +22,7 @@ def load_nodestub
platform = 'centos'
platform_version = os[:release].to_i
end
- JSON.parse(IO.read("#{ENV['BUSSER_ROOT']}/../kitchen/data/platforms/#{platform}/#{platform_version}.json"), :symbolize_names => true)
+ FFI_Yajl::Parser.parse(IO.read("#{ENV['BUSSER_ROOT']}/../kitchen/data/platforms/#{platform}/#{platform_version}.json"), :symbolize_names => true)
end
# centos-59 doesn't have /sbin in the default path,
diff --git a/kitchen-tests/test/integration/webapp/serverspec/Gemfile b/kitchen-tests/test/integration/webapp/serverspec/Gemfile
new file mode 100644
index 0000000000..0cb00ce354
--- /dev/null
+++ b/kitchen-tests/test/integration/webapp/serverspec/Gemfile
@@ -0,0 +1,4 @@
+# This Gemfile is only needed so that busser will install gems it needs for serverspec_helper.rb to work
+source "https://rubygems.org"
+
+gem 'ffi-yajl', '~> 1.1' # Go away, JSON gem
diff --git a/lib/chef/chef_fs/chef_fs_data_store.rb b/lib/chef/chef_fs/chef_fs_data_store.rb
index 484ab07390..3813d0edb4 100644
--- a/lib/chef/chef_fs/chef_fs_data_store.rb
+++ b/lib/chef/chef_fs/chef_fs_data_store.rb
@@ -168,7 +168,7 @@ class Chef
end
end
end
- JSON.pretty_generate(result)
+ Chef::JSONCompat.to_json_pretty(result)
else
begin
diff --git a/lib/chef/chef_fs/command_line.rb b/lib/chef/chef_fs/command_line.rb
index 43e8b276e0..8a205eef78 100644
--- a/lib/chef/chef_fs/command_line.rb
+++ b/lib/chef/chef_fs/command_line.rb
@@ -253,7 +253,7 @@ class Chef
def self.canonicalize_json(json_text)
parsed_json = Chef::JSONCompat.parse(json_text)
sorted_json = sort_keys(parsed_json)
- JSON.pretty_generate(sorted_json)
+ Chef::JSONCompat.to_json_pretty(sorted_json)
end
def self.diff_text(old_path, new_path, old_value, new_value)
diff --git a/lib/chef/chef_fs/file_system/organization_invites_entry.rb b/lib/chef/chef_fs/file_system/organization_invites_entry.rb
index cb26326050..5df37085cb 100644
--- a/lib/chef/chef_fs/file_system/organization_invites_entry.rb
+++ b/lib/chef/chef_fs/file_system/organization_invites_entry.rb
@@ -1,5 +1,6 @@
require 'chef/chef_fs/file_system/rest_list_entry'
require 'chef/chef_fs/data_handler/organization_invites_data_handler'
+require 'chef/json_compat'
class Chef
module ChefFS
@@ -34,7 +35,7 @@ class Chef
end
def write(contents)
- desired_invites = minimize_value(JSON.parse(contents, :create_additions => false))
+ desired_invites = minimize_value(Chef::JSONCompat.parse(contents, :create_additions => false))
actual_invites = _read_json.inject({}) { |h,val| h[val['username']] = val['id']; h }
invites = actual_invites.keys
(desired_invites - invites).each do |invite|
diff --git a/lib/chef/chef_fs/file_system/organization_members_entry.rb b/lib/chef/chef_fs/file_system/organization_members_entry.rb
index eb524d5ea2..94393b341f 100644
--- a/lib/chef/chef_fs/file_system/organization_members_entry.rb
+++ b/lib/chef/chef_fs/file_system/organization_members_entry.rb
@@ -1,5 +1,6 @@
require 'chef/chef_fs/file_system/rest_list_entry'
require 'chef/chef_fs/data_handler/organization_members_data_handler'
+require 'chef/json_compat'
class Chef
module ChefFS
@@ -34,7 +35,7 @@ class Chef
end
def write(contents)
- desired_members = minimize_value(JSON.parse(contents, :create_additions => false))
+ desired_members = minimize_value(Chef::JSONCompat.parse(contents, :create_additions => false))
members = minimize_value(_read_json)
(desired_members - members).each do |member|
begin
diff --git a/lib/chef/chef_fs/file_system/rest_list_entry.rb b/lib/chef/chef_fs/file_system/rest_list_entry.rb
index ac47ff4f25..f68794cb0d 100644
--- a/lib/chef/chef_fs/file_system/rest_list_entry.rb
+++ b/lib/chef/chef_fs/file_system/rest_list_entry.rb
@@ -21,6 +21,7 @@ require 'chef/chef_fs/file_system/not_found_error'
require 'chef/chef_fs/file_system/operation_failed_error'
require 'chef/role'
require 'chef/node'
+require 'chef/json_compat'
class Chef
module ChefFS
@@ -172,7 +173,7 @@ class Chef
def api_error_text(response)
begin
- JSON.parse(response.body)['error'].join("\n")
+ Chef::JSONCompat.parse(response.body)['error'].join("\n")
rescue
response.body
end
diff --git a/lib/chef/client.rb b/lib/chef/client.rb
index e531da5768..e8ff352116 100644
--- a/lib/chef/client.rb
+++ b/lib/chef/client.rb
@@ -282,7 +282,7 @@ class Chef
rescue Exception => e
# TODO: munge exception so a semantic failure message can be given to the
# user
- @events.registration_failed(node_name, e, config)
+ @events.registration_failed(client_name, e, config)
raise
end
diff --git a/lib/chef/cookbook/cookbook_version_loader.rb b/lib/chef/cookbook/cookbook_version_loader.rb
index 5481ba7ddc..bcbfcbeec8 100644
--- a/lib/chef/cookbook/cookbook_version_loader.rb
+++ b/lib/chef/cookbook/cookbook_version_loader.rb
@@ -81,7 +81,7 @@ class Chef
load_as(:attribute_filenames, 'attributes', '*.rb')
load_as(:definition_filenames, 'definitions', '*.rb')
load_as(:recipe_filenames, 'recipes', '*.rb')
- load_as(:library_filenames, 'libraries', '*.rb')
+ load_recursively_as(:library_filenames, 'libraries', '*.rb')
load_recursively_as(:template_filenames, "templates", "*")
load_recursively_as(:file_filenames, "files", "*")
load_recursively_as(:resource_filenames, "resources", "*.rb")
diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb
index 3964354d50..54e930135d 100644
--- a/lib/chef/cookbook/metadata.rb
+++ b/lib/chef/cookbook/metadata.rb
@@ -35,28 +35,31 @@ class Chef
# about Chef Cookbooks.
class Metadata
- NAME = 'name'.freeze
- DESCRIPTION = 'description'.freeze
- LONG_DESCRIPTION = 'long_description'.freeze
- MAINTAINER = 'maintainer'.freeze
- MAINTAINER_EMAIL = 'maintainer_email'.freeze
- LICENSE = 'license'.freeze
- PLATFORMS = 'platforms'.freeze
- DEPENDENCIES = 'dependencies'.freeze
- RECOMMENDATIONS = 'recommendations'.freeze
- SUGGESTIONS = 'suggestions'.freeze
- CONFLICTING = 'conflicting'.freeze
- PROVIDING = 'providing'.freeze
- REPLACING = 'replacing'.freeze
- ATTRIBUTES = 'attributes'.freeze
- GROUPINGS = 'groupings'.freeze
- RECIPES = 'recipes'.freeze
- VERSION = 'version'.freeze
+ NAME = 'name'.freeze
+ DESCRIPTION = 'description'.freeze
+ LONG_DESCRIPTION = 'long_description'.freeze
+ MAINTAINER = 'maintainer'.freeze
+ MAINTAINER_EMAIL = 'maintainer_email'.freeze
+ LICENSE = 'license'.freeze
+ PLATFORMS = 'platforms'.freeze
+ DEPENDENCIES = 'dependencies'.freeze
+ RECOMMENDATIONS = 'recommendations'.freeze
+ SUGGESTIONS = 'suggestions'.freeze
+ CONFLICTING = 'conflicting'.freeze
+ PROVIDING = 'providing'.freeze
+ REPLACING = 'replacing'.freeze
+ ATTRIBUTES = 'attributes'.freeze
+ GROUPINGS = 'groupings'.freeze
+ RECIPES = 'recipes'.freeze
+ VERSION = 'version'.freeze
+ SOURCE_URL = 'source_url'.freeze
+ ISSUES_URL = 'issues_url'.freeze
COMPARISON_FIELDS = [ :name, :description, :long_description, :maintainer,
:maintainer_email, :license, :platforms, :dependencies,
:recommendations, :suggestions, :conflicting, :providing,
- :replacing, :attributes, :groupings, :recipes, :version]
+ :replacing, :attributes, :groupings, :recipes, :version,
+ :source_url, :issues_url ]
VERSION_CONSTRAINTS = {:depends => DEPENDENCIES,
:recommends => RECOMMENDATIONS,
@@ -111,6 +114,8 @@ class Chef
@groupings = Mash.new
@recipes = Mash.new
@version = Version.new("0.0.0")
+ @source_url = ''
+ @issues_url = ''
@errors = []
end
@@ -413,7 +418,7 @@ class Chef
end
end
- # Adds an attribute )hat a user needs to configure for this cookbook. Takes
+ # Adds an attribute that a user needs to configure for this cookbook. Takes
# a name (with the / notation for a nested attribute), followed by any of
# these options
#
@@ -443,7 +448,9 @@ class Chef
:type => { :equal_to => [ "string", "array", "hash", "symbol", "boolean", "numeric" ], :default => "string" },
:required => { :equal_to => [ "required", "recommended", "optional", true, false ], :default => "optional" },
:recipes => { :kind_of => [ Array ], :default => [] },
- :default => { :kind_of => [ String, Array, Hash, Symbol, Numeric, TrueClass, FalseClass ] }
+ :default => { :kind_of => [ String, Array, Hash, Symbol, Numeric, TrueClass, FalseClass ] },
+ :source_url => { :kind_of => String },
+ :issues_url => { :kind_of => String }
}
)
options[:required] = remap_required_attribute(options[:required]) unless options[:required].nil?
@@ -469,23 +476,25 @@ class Chef
def to_hash
{
- NAME => self.name,
- DESCRIPTION => self.description,
- LONG_DESCRIPTION => self.long_description,
- MAINTAINER => self.maintainer,
- MAINTAINER_EMAIL => self.maintainer_email,
- LICENSE => self.license,
- PLATFORMS => self.platforms,
- DEPENDENCIES => self.dependencies,
- RECOMMENDATIONS => self.recommendations,
- SUGGESTIONS => self.suggestions,
- CONFLICTING => self.conflicting,
- PROVIDING => self.providing,
- REPLACING => self.replacing,
- ATTRIBUTES => self.attributes,
- GROUPINGS => self.groupings,
- RECIPES => self.recipes,
- VERSION => self.version
+ NAME => self.name,
+ DESCRIPTION => self.description,
+ LONG_DESCRIPTION => self.long_description,
+ MAINTAINER => self.maintainer,
+ MAINTAINER_EMAIL => self.maintainer_email,
+ LICENSE => self.license,
+ PLATFORMS => self.platforms,
+ DEPENDENCIES => self.dependencies,
+ RECOMMENDATIONS => self.recommendations,
+ SUGGESTIONS => self.suggestions,
+ CONFLICTING => self.conflicting,
+ PROVIDING => self.providing,
+ REPLACING => self.replacing,
+ ATTRIBUTES => self.attributes,
+ GROUPINGS => self.groupings,
+ RECIPES => self.recipes,
+ VERSION => self.version,
+ SOURCE_URL => self.source_url,
+ ISSUES_URL => self.issues_url
}
end
@@ -517,6 +526,8 @@ class Chef
@groupings = o[GROUPINGS] if o.has_key?(GROUPINGS)
@recipes = o[RECIPES] if o.has_key?(RECIPES)
@version = o[VERSION] if o.has_key?(VERSION)
+ @source_url = o[SOURCE_URL] if o.has_key?(SOURCE_URL)
+ @issues_url = o[ISSUES_URL] if o.has_key?(ISSUES_URL)
self
end
@@ -531,7 +542,9 @@ class Chef
VERSION_CONSTRAINTS.each do |dependency_type, hash_key|
if dependency_group = o[hash_key]
dependency_group.each do |cb_name, constraints|
- metadata.send(method_name, cb_name, *Array(constraints))
+ if metadata.respond_to?(method_name)
+ metadata.public_send(method_name, cb_name, *Array(constraints))
+ end
end
end
end
@@ -543,6 +556,36 @@ class Chef
from_hash(o)
end
+ # Sets the cookbook's source URL, or returns it.
+ #
+ # === Parameters
+ # maintainer<String>:: The source URL
+ #
+ # === Returns
+ # source_url<String>:: Returns the current source URL.
+ def source_url(arg=nil)
+ set_or_return(
+ :source_url,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
+ # Sets the cookbook's issues URL, or returns it.
+ #
+ # === Parameters
+ # issues_url<String>:: The issues URL
+ #
+ # === Returns
+ # issues_url<String>:: Returns the current issues URL.
+ def issues_url(arg=nil)
+ set_or_return(
+ :issues_url,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
private
def run_validation
diff --git a/lib/chef/cookbook/syntax_check.rb b/lib/chef/cookbook/syntax_check.rb
index 1437785259..96fc7e7b84 100644
--- a/lib/chef/cookbook/syntax_check.rb
+++ b/lib/chef/cookbook/syntax_check.rb
@@ -101,15 +101,24 @@ class Chef
end
def remove_ignored_files(file_list)
- return file_list unless chefignore.ignores.length > 0
+ return file_list if chefignore.ignores.empty?
+
file_list.reject do |full_path|
relative_pn = Chef::Util::PathHelper.relative_path_from(cookbook_path, full_path)
- chefignore.ignored? relative_pn.to_s
+ chefignore.ignored?(relative_pn.to_s)
end
end
+ def remove_uninteresting_ruby_files(file_list)
+ file_list.reject { |f| f =~ %r{#{cookbook_path}/(files|templates)/} }
+ end
+
def ruby_files
- remove_ignored_files Dir[File.join(Chef::Util::PathHelper.escape_glob(cookbook_path), '**', '*.rb')]
+ path = Chef::Util::PathHelper.escape_glob(cookbook_path)
+ files = Dir[File.join(path, '**', '*.rb')]
+ files = remove_ignored_files(files)
+ files = remove_uninteresting_ruby_files(files)
+ files
end
def untested_ruby_files
diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb
index 40aaaf1191..505b403e65 100644
--- a/lib/chef/cookbook_version.rb
+++ b/lib/chef/cookbook_version.rb
@@ -315,13 +315,20 @@ class Chef
else
if segment == :files || segment == :templates
error_message = "Cookbook '#{name}' (#{version}) does not contain a file at any of these locations:\n"
- error_locations = [
- " #{segment}/#{node[:platform]}-#{node[:platform_version]}/#{filename}",
- " #{segment}/#{node[:platform]}/#{filename}",
- " #{segment}/default/#{filename}",
- ]
+ error_locations = if filename.is_a?(Array)
+ filename.map{|name| " #{File.join(segment.to_s, name)}"}
+ else
+ [
+ " #{segment}/#{node[:platform]}-#{node[:platform_version]}/#{filename}",
+ " #{segment}/#{node[:platform]}/#{filename}",
+ " #{segment}/default/#{filename}",
+ " #{segment}/#{filename}",
+ ]
+ end
error_message << error_locations.join("\n")
existing_files = segment_filenames(segment)
+ # Strip the root_dir prefix off all files for readability
+ existing_files.map!{|path| path[root_dir.length+1..-1]} if root_dir
# Show the files that the cookbook does have. If the user made a typo,
# hopefully they'll see it here.
unless existing_files.empty?
@@ -421,38 +428,44 @@ class Chef
def preferences_for_path(node, segment, path)
# only files and templates can be platform-specific
if segment.to_sym == :files || segment.to_sym == :templates
- begin
- platform, version = Chef::Platform.find_platform_and_version(node)
- rescue ArgumentError => e
- # Skip platform/version if they were not found by find_platform_and_version
- if e.message =~ /Cannot find a (?:platform|version)/
- platform = "/unknown_platform/"
- version = "/unknown_platform_version/"
- else
- raise
+ relative_search_path = if path.is_a?(Array)
+ path
+ else
+ begin
+ platform, version = Chef::Platform.find_platform_and_version(node)
+ rescue ArgumentError => e
+ # Skip platform/version if they were not found by find_platform_and_version
+ if e.message =~ /Cannot find a (?:platform|version)/
+ platform = "/unknown_platform/"
+ version = "/unknown_platform_version/"
+ else
+ raise
+ end
end
- end
- fqdn = node[:fqdn]
+ fqdn = node[:fqdn]
- # Break version into components, eg: "5.7.1" => [ "5.7.1", "5.7", "5" ]
- search_versions = []
- parts = version.to_s.split('.')
+ # Break version into components, eg: "5.7.1" => [ "5.7.1", "5.7", "5" ]
+ search_versions = []
+ parts = version.to_s.split('.')
- parts.size.times do
- search_versions << parts.join('.')
- parts.pop
- end
+ parts.size.times do
+ search_versions << parts.join('.')
+ parts.pop
+ end
- # Most specific to least specific places to find the path
- search_path = [ File.join(segment.to_s, "host-#{fqdn}", path) ]
- search_versions.each do |v|
- search_path << File.join(segment.to_s, "#{platform}-#{v}", path)
- end
- search_path << File.join(segment.to_s, platform.to_s, path)
- search_path << File.join(segment.to_s, "default", path)
+ # Most specific to least specific places to find the path
+ search_path = [ File.join("host-#{fqdn}", path) ]
+ search_versions.each do |v|
+ search_path << File.join("#{platform}-#{v}", path)
+ end
+ search_path << File.join(platform.to_s, path)
+ search_path << File.join("default", path)
+ search_path << path
- search_path
+ search_path
+ end
+ relative_search_path.map {|relative_path| File.join(segment.to_s, relative_path)}
else
[File.join(segment, path)]
end
@@ -479,7 +492,7 @@ class Chef
cookbook_version.manifest = o
# We don't need the following step when we decide to stop supporting deprecated operators in the metadata (e.g. <<, >>)
- cookbook_version.manifest["metadata"] = Chef::JSONCompat.from_json(cookbook_version.metadata.to_json)
+ cookbook_version.manifest["metadata"] = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(cookbook_version.metadata))
cookbook_version.freeze_version if o["frozen?"]
cookbook_version
@@ -666,7 +679,13 @@ class Chef
# Check if path is actually under root_path
next if parts[0] == '..'
if segment == :templates || segment == :files
- return [ pathname.to_s, parts[1] ]
+ # Check if pathname looks like files/foo or templates/foo (unscoped)
+ if pathname.each_filename.to_a.length == 2
+ # Use root_default in case the same path exists at root_default and default
+ return [ pathname.to_s, 'root_default' ]
+ else
+ return [ pathname.to_s, parts[1] ]
+ end
else
return [ pathname.to_s, 'default' ]
end
diff --git a/lib/chef/dsl/recipe.rb b/lib/chef/dsl/recipe.rb
index 3282320b8c..476d9db666 100644
--- a/lib/chef/dsl/recipe.rb
+++ b/lib/chef/dsl/recipe.rb
@@ -19,6 +19,7 @@
require 'chef/resource_platform_map'
require 'chef/mixin/convert_to_class_name'
+require 'chef/exceptions'
class Chef
module DSL
@@ -162,6 +163,10 @@ class Chef
end
end
+ def exec(args)
+ raise Chef::Exceptions::ResourceNotFound, "exec was called, but you probably meant to use an execute resource. If not, please call Kernel#exec explicitly. The exec block called was \"#{args}\""
+ end
+
end
end
end
diff --git a/lib/chef/http.rb b/lib/chef/http.rb
index 7f2d00157b..ee951bd675 100644
--- a/lib/chef/http.rb
+++ b/lib/chef/http.rb
@@ -271,7 +271,7 @@ class Chef
elsif redirect_location = redirected_to(response)
if [:GET, :HEAD].include?(method)
follow_redirect do
- send_http_request(method, create_url(redirect_location), headers, body, &response_handler)
+ send_http_request(method, url+redirect_location, headers, body, &response_handler)
end
else
raise Exceptions::InvalidRedirect, "#{method} request was redirected from #{url} to #{redirect_location}. Only GET and HEAD support redirects."
diff --git a/lib/chef/json_compat.rb b/lib/chef/json_compat.rb
index e92d5c36ae..3350da0c13 100644
--- a/lib/chef/json_compat.rb
+++ b/lib/chef/json_compat.rb
@@ -18,9 +18,9 @@
# Wrapper class for interacting with JSON.
require 'ffi_yajl'
-require 'json'
-require 'ffi_yajl/json_gem' # XXX: parts of chef require JSON gem's Hash#to_json monkeypatch
require 'chef/exceptions'
+# We're requiring this to prevent breaking consumers using Hash.to_json
+require 'json'
class Chef
class JSONCompat
diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb
index 6421384f01..0c079792a4 100644
--- a/lib/chef/knife.rb
+++ b/lib/chef/knife.rb
@@ -164,7 +164,6 @@ class Chef
def self.load_config(explicit_config_file)
config_loader = WorkstationConfigLoader.new(explicit_config_file, Chef::Log)
- Chef::Log.debug("Using configuration from #{config_loader.config_location}")
config_loader.load
ui.warn("No knife configuration file found") if config_loader.no_config_found?
@@ -393,6 +392,8 @@ class Chef
merge_configs
apply_computed_config
+ # This has to be after apply_computed_config so that Mixlib::Log is configured
+ Chef::Log.info("Using configuration from #{config[:config_file]}") if config[:config_file]
end
def show_usage
diff --git a/lib/chef/knife/bootstrap/archlinux-gems.erb b/lib/chef/knife/bootstrap/archlinux-gems.erb
index eb134b90d5..581293daa3 100644
--- a/lib/chef/knife/bootstrap/archlinux-gems.erb
+++ b/lib/chef/knife/bootstrap/archlinux-gems.erb
@@ -34,7 +34,7 @@ mkdir -p /etc/chef/ohai/hints
<% @chef_config[:knife][:hints].each do |name, hash| -%>
cat > /etc/chef/ohai/hints/<%= name %>.json <<'EOP'
-<%= hash.to_json %>
+<%= Chef::JSONCompat.to_json(hash) %>
EOP
<% end -%>
<% end -%>
@@ -61,7 +61,7 @@ https_proxy "<%= knife_config[:bootstrap_proxy] %>"
EOP
cat > /etc/chef/first-boot.json <<'EOP'
-<%= first_boot.to_json %>
+<%= Chef::JSONCompat.to_json(first_boot) %>
EOP
<%= start_chef %>'
diff --git a/lib/chef/knife/bootstrap/chef-aix.erb b/lib/chef/knife/bootstrap/chef-aix.erb
index 3a031ee738..013ad1decb 100644
--- a/lib/chef/knife/bootstrap/chef-aix.erb
+++ b/lib/chef/knife/bootstrap/chef-aix.erb
@@ -47,7 +47,7 @@ mkdir -p /etc/chef/ohai/hints
<% @chef_config[:knife][:hints].each do |name, hash| -%>
cat > /etc/chef/ohai/hints/<%= name %>.json <<'EOP'
-<%= hash.to_json %>
+<%= Chef::JSONCompat.to_json(hash) %>
EOP
<% end -%>
<% end -%>
@@ -57,7 +57,7 @@ cat > /etc/chef/client.rb <<'EOP'
EOP
cat > /etc/chef/first-boot.json <<'EOP'
-<%= first_boot.to_json %>
+<%= Chef::JSONCompat.to_json(first_boot) %>
EOP
<%= start_chef %>'
diff --git a/lib/chef/knife/bootstrap/chef-full.erb b/lib/chef/knife/bootstrap/chef-full.erb
index 6edb485f44..dfd5df0071 100644
--- a/lib/chef/knife/bootstrap/chef-full.erb
+++ b/lib/chef/knife/bootstrap/chef-full.erb
@@ -61,7 +61,7 @@ mkdir -p /etc/chef/ohai/hints
<% @chef_config[:knife][:hints].each do |name, hash| -%>
cat > /etc/chef/ohai/hints/<%= name %>.json <<'EOP'
-<%= hash.to_json %>
+<%= Chef::JSONCompat.to_json(hash) %>
EOP
<% end -%>
<% end -%>
@@ -71,7 +71,7 @@ cat > /etc/chef/client.rb <<'EOP'
EOP
cat > /etc/chef/first-boot.json <<'EOP'
-<%= first_boot.to_json %>
+<%= Chef::JSONCompat.to_json(first_boot) %>
EOP
echo "Starting first Chef Client run..."
diff --git a/lib/chef/knife/cookbook_create.rb b/lib/chef/knife/cookbook_create.rb
index f4183a7245..e17a54079f 100644
--- a/lib/chef/knife/cookbook_create.rb
+++ b/lib/chef/knife/cookbook_create.rb
@@ -80,7 +80,7 @@ class Chef
end
def create_cookbook(dir, cookbook_name, copyright, license)
- msg("** Creating cookbook #{cookbook_name}")
+ msg("** Creating cookbook #{cookbook_name} in #{dir}")
FileUtils.mkdir_p "#{File.join(dir, cookbook_name, "attributes")}"
FileUtils.mkdir_p "#{File.join(dir, cookbook_name, "recipes")}"
FileUtils.mkdir_p "#{File.join(dir, cookbook_name, "definitions")}"
diff --git a/lib/chef/knife/cookbook_site_share.rb b/lib/chef/knife/cookbook_site_share.rb
index 7204ccdb1c..b4a7873c71 100644
--- a/lib/chef/knife/cookbook_site_share.rb
+++ b/lib/chef/knife/cookbook_site_share.rb
@@ -31,7 +31,7 @@ class Chef
require 'chef/cookbook_site_streaming_uploader'
end
- banner "knife cookbook site share COOKBOOK CATEGORY (options)"
+ banner "knife cookbook site share COOKBOOK [CATEGORY] (options)"
category "cookbook site"
option :cookbook_path,
@@ -40,17 +40,28 @@ class Chef
:description => "A colon-separated path to look for cookbooks in",
:proc => lambda { |o| Chef::Config.cookbook_path = o.split(":") }
+ option :dry_run,
+ :long => '--dry-run',
+ :short => '-n',
+ :boolean => true,
+ :default => false,
+ :description => "Don't take action, only print what files will be upload to SuperMarket."
+
def run
- if @name_args.length < 2
+ config[:cookbook_path] ||= Chef::Config[:cookbook_path]
+
+ if @name_args.length < 1
show_usage
- ui.fatal("You must specify the cookbook name and the category you want to share this cookbook to.")
- exit 1
+ ui.fatal("You must specify the cookbook name.")
+ exit(1)
+ elsif @name_args.length < 2
+ cookbook_name = @name_args[0]
+ category = get_category(cookbook_name)
+ else
+ cookbook_name = @name_args[0]
+ category = @name_args[1]
end
- config[:cookbook_path] ||= Chef::Config[:cookbook_path]
-
- cookbook_name = @name_args[0]
- category = @name_args[1]
cl = Chef::CookbookLoader.new(config[:cookbook_path])
if cl.cookbook_exists?(cookbook_name)
cookbook = cl[cookbook_name]
@@ -66,6 +77,14 @@ class Chef
exit(1)
end
+ if config[:dry_run]
+ ui.info("Not uploading #{cookbook_name}.tgz due to --dry-run flag.")
+ result = shell_out!("tar -tzf #{cookbook_name}.tgz", :cwd => tmp_cookbook_dir)
+ ui.info(result.stdout)
+ FileUtils.rm_rf tmp_cookbook_dir
+ return
+ end
+
begin
do_upload("#{tmp_cookbook_dir}/#{cookbook_name}.tgz", category, Chef::Config[:node_name], Chef::Config[:client_key])
ui.info("Upload complete!")
@@ -84,6 +103,22 @@ class Chef
end
+ def get_category(cookbook_name)
+ begin
+ data = noauth_rest.get_rest("http://cookbooks.opscode.com/api/v1/cookbooks/#{@name_args[0]}")
+ if !data["category"] && data["error_code"]
+ ui.fatal("Received an error from the Opscode Cookbook site: #{data["error_code"]}. On the first time you upload it, you are required to specify the category you want to share this cookbook to.")
+ exit(1)
+ else
+ data['category']
+ end
+ rescue => e
+ ui.fatal("Unable to reach Opscode Cookbook Site: #{e.message}. Increase log verbosity (-VV) for more information.")
+ Chef::Log.debug("\n#{e.backtrace.join("\n")}")
+ exit(1)
+ end
+ end
+
def do_upload(cookbook_filename, cookbook_category, user_id, user_secret_filename)
uri = "https://supermarket.getchef.com/api/v1/cookbooks"
diff --git a/lib/chef/knife/core/status_presenter.rb b/lib/chef/knife/core/status_presenter.rb
new file mode 100644
index 0000000000..3298d5e4ac
--- /dev/null
+++ b/lib/chef/knife/core/status_presenter.rb
@@ -0,0 +1,156 @@
+#
+# Author:: Nicolas DUPEUX (<nicolas.dupeux@arkea.com>)
+# Copyright:: Copyright (c) 2011 Opscode, 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 'chef/knife/core/text_formatter'
+require 'chef/knife/core/generic_presenter'
+
+class Chef
+ class Knife
+ module Core
+
+ # This module may be included into a knife subcommand class to automatically
+ # add configuration options used by the StatusPresenter
+ module StatusFormattingOptions
+ # :nodoc:
+ # Would prefer to do this in a rational way, but can't be done b/c of
+ # Mixlib::CLI's design :(
+ def self.included(includer)
+ includer.class_eval do
+ option :medium_output,
+ :short => '-m',
+ :long => '--medium',
+ :boolean => true,
+ :default => false,
+ :description => 'Include normal attributes in the output'
+
+ option :long_output,
+ :short => '-l',
+ :long => '--long',
+ :boolean => true,
+ :default => false,
+ :description => 'Include all attributes in the output'
+ end
+ end
+ end
+
+ #==Chef::Knife::Core::StatusPresenter
+ # A customized presenter for Chef::Node objects. Supports variable-length
+ # output formats for displaying node data
+ class StatusPresenter < GenericPresenter
+
+ def format(data)
+ if parse_format_option == :json
+ summarize_json(data)
+ else
+ super
+ end
+ end
+
+ def summarize_json(list)
+ result_list = []
+ list.each do |node|
+ result = {}
+
+ result["name"] = node.name
+ result["chef_environment"] = node.chef_environment
+ ip = (node[:ec2] && node[:ec2][:public_ipv4]) || node[:ipaddress]
+ fqdn = (node[:ec2] && node[:ec2][:public_hostname]) || node[:fqdn]
+ result["ip"] = ip if ip
+ result["fqdn"] = fqdn if fqdn
+ result["run_list"] = node.run_list if config[:run_list]
+ result["ohai_time"] = node[:ohai_time]
+ result["platform"] = node[:platform] if node[:platform]
+ result["platform_version"] = node[:platform_version] if node[:platform_version]
+
+ if config[:long_output]
+ result["default"] = node.default_attrs
+ result["override"] = node.override_attrs
+ result["automatic"] = node.automatic_attrs
+ end
+ result_list << result
+ end
+
+ Chef::JSONCompat.to_json_pretty(result_list)
+ end
+
+ # Converts a Chef::Node object to a string suitable for output to a
+ # terminal. If config[:medium_output] or config[:long_output] are set
+ # the volume of output is adjusted accordingly. Uses colors if enabled
+ # in the ui object.
+ def summarize(list)
+ summarized=''
+ list.each do |data|
+ node = data
+ # special case ec2 with their split horizon whatsis.
+ ip = (node[:ec2] && node[:ec2][:public_ipv4]) || node[:ipaddress]
+ fqdn = (node[:ec2] && node[:ec2][:public_hostname]) || node[:fqdn]
+
+ hours, minutes, seconds = time_difference_in_hms(node["ohai_time"])
+ hours_text = "#{hours} hour#{hours == 1 ? ' ' : 's'}"
+ minutes_text = "#{minutes} minute#{minutes == 1 ? ' ' : 's'}"
+ run_list = "#{node.run_list}" if config[:run_list]
+ if hours > 24
+ color = :red
+ text = hours_text
+ elsif hours >= 1
+ color = :yellow
+ text = hours_text
+ else
+ color = :green
+ text = minutes_text
+ end
+
+ line_parts = Array.new
+ line_parts << @ui.color(text, color) + ' ago' << node.name
+ line_parts << fqdn if fqdn
+ line_parts << ip if ip
+ line_parts << run_list if run_list
+
+ if node['platform']
+ platform = node['platform']
+ if node['platform_version']
+ platform << " #{node['platform_version']}"
+ end
+ line_parts << platform
+ end
+
+ summarized=summarized + line_parts.join(', ') + ".\n"
+ end
+ summarized
+ end
+
+ def key(key_text)
+ ui.color(key_text, :cyan)
+ end
+
+ # :nodoc:
+ # TODO: this is duplicated from StatusHelper in the Webui. dedup.
+ def time_difference_in_hms(unix_time)
+ now = Time.now.to_i
+ difference = now - unix_time.to_i
+ hours = (difference / 3600).to_i
+ difference = difference % 3600
+ minutes = (difference / 60).to_i
+ seconds = (difference % 60)
+ return [hours, minutes, seconds]
+ end
+
+ end
+ end
+ end
+end
diff --git a/lib/chef/knife/core/ui.rb b/lib/chef/knife/core/ui.rb
index 0007480ea2..f3ecfbcae8 100644
--- a/lib/chef/knife/core/ui.rb
+++ b/lib/chef/knife/core/ui.rb
@@ -113,7 +113,7 @@ class Chef
# determined by the value of `config[:color]`. When output is not to a
# terminal, colored output is never used
def color?
- Chef::Config[:color] && stdout.tty? && !Chef::Platform.windows?
+ Chef::Config[:color] && stdout.tty?
end
def ask(*args, &block)
diff --git a/lib/chef/knife/status.rb b/lib/chef/knife/status.rb
index 5906a4a624..93e81f8f03 100644
--- a/lib/chef/knife/status.rb
+++ b/lib/chef/knife/status.rb
@@ -17,13 +17,13 @@
#
require 'chef/knife'
+require 'chef/knife/core/status_presenter'
class Chef
class Knife
class Status < Knife
deps do
- require 'highline'
require 'chef/search/query'
end
@@ -44,74 +44,27 @@ class Chef
:long => "--hide-healthy",
:description => "Hide nodes that have run chef in the last hour"
- def highline
- @h ||= HighLine.new
- end
-
def run
+ ui.use_presenter Knife::Core::StatusPresenter
all_nodes = []
q = Chef::Search::Query.new
- query = @name_args[0] || "*:*"
+ query = @name_args[0] ? @name_args[0].dup : '*:*'
+ if config[:hide_healthy]
+ time = Time.now.to_i
+ query_unhealthy = "NOT ohai_time:[" << (time - 60*60).to_s << " TO " << time.to_s << "]"
+ query << ' AND ' << query_unhealthy << @name_args[0] if @name_args[0]
+ query = query_unhealthy unless @name_args[0]
+ end
q.search(:node, query) do |node|
all_nodes << node
end
- all_nodes.sort { |n1, n2|
+ output(all_nodes.sort { |n1, n2|
if (config[:sort_reverse] || Chef::Config[:knife][:sort_status_reverse])
(n2["ohai_time"] or 0) <=> (n1["ohai_time"] or 0)
else
(n1["ohai_time"] or 0) <=> (n2["ohai_time"] or 0)
end
- }.each do |node|
- if node.has_key?("ec2")
- fqdn = node['ec2']['public_hostname']
- ipaddress = node['ec2']['public_ipv4']
- else
- fqdn = node['fqdn']
- ipaddress = node['ipaddress']
- end
- hours, minutes, seconds = time_difference_in_hms(node["ohai_time"])
- hours_text = "#{hours} hour#{hours == 1 ? ' ' : 's'}"
- minutes_text = "#{minutes} minute#{minutes == 1 ? ' ' : 's'}"
- run_list = "#{node.run_list}" if config[:run_list]
- if hours > 24
- color = :red
- text = hours_text
- elsif hours >= 1
- color = :yellow
- text = hours_text
- else
- color = :green
- text = minutes_text
- end
-
- line_parts = Array.new
- line_parts << @ui.color(text, color) + " ago" << node.name
- line_parts << fqdn if fqdn
- line_parts << ipaddress if ipaddress
- line_parts << run_list if run_list
-
- if node['platform']
- platform = node['platform']
- if node['platform_version']
- platform << " #{node['platform_version']}"
- end
- line_parts << platform
- end
- highline.say(line_parts.join(', ') + '.') unless (config[:hide_healthy] && hours < 1)
- end
-
- end
-
- # :nodoc:
- # TODO: this is duplicated from StatusHelper in the Webui. dedup.
- def time_difference_in_hms(unix_time)
- now = Time.now.to_i
- difference = now - unix_time.to_i
- hours = (difference / 3600).to_i
- difference = difference % 3600
- minutes = (difference / 60).to_i
- seconds = (difference % 60)
- return [hours, minutes, seconds]
+ })
end
end
diff --git a/lib/chef/mixin/command/unix.rb b/lib/chef/mixin/command/unix.rb
index b63a02663b..2bad4e6bcf 100644
--- a/lib/chef/mixin/command/unix.rb
+++ b/lib/chef/mixin/command/unix.rb
@@ -100,9 +100,9 @@ class Chef
begin
if cmd.kind_of?(Array)
- exec(*cmd)
+ Kernel.exec(*cmd)
else
- exec(cmd)
+ Kernel.exec(cmd)
end
raise 'forty-two'
rescue Exception => e
diff --git a/lib/chef/platform/provider_mapping.rb b/lib/chef/platform/provider_mapping.rb
index a812dcd7ad..9e15ea5658 100644
--- a/lib/chef/platform/provider_mapping.rb
+++ b/lib/chef/platform/provider_mapping.rb
@@ -197,13 +197,14 @@ class Chef
},
:suse => {
:default => {
- :service => Chef::Provider::Service::Redhat,
+ :service => Chef::Provider::Service::Systemd,
:cron => Chef::Provider::Cron,
:package => Chef::Provider::Package::Zypper,
:group => Chef::Provider::Group::Gpasswd
},
"< 12.0" => {
- :group => Chef::Provider::Group::Suse
+ :group => Chef::Provider::Group::Suse,
+ :service => Chef::Provider::Service::Redhat
}
},
:oracle => {
diff --git a/lib/chef/provider/cron/unix.rb b/lib/chef/provider/cron/unix.rb
index 5cb1bcda41..350f8bda18 100644
--- a/lib/chef/provider/cron/unix.rb
+++ b/lib/chef/provider/cron/unix.rb
@@ -25,18 +25,21 @@ class Chef
class Provider
class Cron
class Unix < Chef::Provider::Cron
+ include Chef::Mixin::ShellOut
private
def read_crontab
- crontab = nil
- status = popen4("crontab -l #{@new_resource.user}") do |pid, stdin, stdout, stderr|
- crontab = stdout.read
- end
- if status.exitstatus > 1
- raise Chef::Exceptions::Cron, "Error determining state of #{@new_resource.name}, exit: #{status.exitstatus}"
+ crontab = shell_out('/usr/bin/crontab -l', :user => @new_resource.user)
+ status = crontab.status.exitstatus
+
+ Chef::Log.debug crontab.format_for_exception if status > 0
+
+ if status > 1
+ raise Chef::Exceptions::Cron, "Error determining state of #{@new_resource.name}, exit: #{status}"
end
- crontab
+ return nil if status > 0
+ crontab.stdout.chomp << "\n"
end
def write_crontab(crontab)
@@ -47,8 +50,9 @@ class Chef
exit_status = 0
error_message = ""
begin
- status, stdout, stderr = run_command_and_return_stdout_stderr(:command => "/usr/bin/crontab #{tempcron.path}",:user => @new_resource.user)
- exit_status = status.exitstatus
+ crontab_write = shell_out("/usr/bin/crontab #{tempcron.path}", :user => @new_resource.user)
+ stderr = crontab_write.stderr
+ exit_status = crontab_write.status.exitstatus
# solaris9, 10 on some failures for example invalid 'mins' in crontab fails with exit code of zero :(
if stderr && stderr.include?("errors detected in input, no crontab file generated")
error_message = stderr
diff --git a/lib/chef/provider/dsc_script.rb b/lib/chef/provider/dsc_script.rb
index c979800cba..b8ca54f1b8 100644
--- a/lib/chef/provider/dsc_script.rb
+++ b/lib/chef/provider/dsc_script.rb
@@ -47,9 +47,11 @@ class Chef
end
def load_current_resource
- @dsc_resources_info = run_configuration(:test)
- @resource_converged = @dsc_resources_info.all? do |resource|
- !resource.changes_state?
+ if supports_dsc?
+ @dsc_resources_info = run_configuration(:test)
+ @resource_converged = @dsc_resources_info.all? do |resource|
+ !resource.changes_state?
+ end
end
end
@@ -57,8 +59,26 @@ class Chef
true
end
+ def define_resource_requirements
+ requirements.assert(:run) do |a|
+ err = [
+ 'Could not find Dsc on the system',
+ powershell_info_str,
+ "Powershell 4.0 or higher was not detected on your system and is required to use the dsc_script resource.",
+ ]
+ a.assertion { supports_dsc? }
+ a.failure_message Chef::Exceptions::NoProviderAvailable, err.join(' ')
+ a.whyrun err + ["Assuming a previous resource installs Powershell 4.0 or higher."]
+ a.block_action!
+ end
+ end
+
protected
+ def supports_dsc?
+ run_context && Chef::Platform.supports_dsc?(node)
+ end
+
def run_configuration(operation)
config_directory = ::Dir.mktmpdir("chef-dsc-script")
configuration_data_path = get_configuration_data_path(config_directory)
@@ -144,6 +164,14 @@ class Chef
end
end
end
+
+ def powershell_info_str
+ if run_context && run_context.node[:languages] && run_context.node[:languages][:powershell]
+ install_info = "Powershell #{run_context.node[:languages][:powershell][:version]} was found on the system."
+ else
+ install_info = 'Powershell was not found.'
+ end
+ end
end
end
end
diff --git a/lib/chef/provider/execute.rb b/lib/chef/provider/execute.rb
index d469bea769..54632c0684 100644
--- a/lib/chef/provider/execute.rb
+++ b/lib/chef/provider/execute.rb
@@ -50,10 +50,11 @@ class Chef
opts[:umask] = @new_resource.umask if @new_resource.umask
opts[:log_level] = :info
opts[:log_tag] = @new_resource.to_s
- if STDOUT.tty? && !Chef::Config[:daemon] && Chef::Log.info?
+ if STDOUT.tty? && !Chef::Config[:daemon] && Chef::Log.info? && !@new_resource.sensitive
opts[:live_stream] = STDOUT
end
- converge_by("execute #{@new_resource.command}") do
+ description = @new_resource.sensitive ? "sensitive resource" : @new_resource.command
+ converge_by("execute #{description}") do
result = shell_out!(@new_resource.command, opts)
Chef::Log.info("#{@new_resource} ran successfully")
end
diff --git a/lib/chef/provider/git.rb b/lib/chef/provider/git.rb
index c8e615c1f9..2ef119e839 100644
--- a/lib/chef/provider/git.rb
+++ b/lib/chef/provider/git.rb
@@ -64,7 +64,7 @@ class Chef
a.failure_message Chef::Exceptions::UnresolvableGitReference,
"Unable to parse SHA reference for '#{@new_resource.revision}' in repository '#{@new_resource.repository}'. " +
"Verify your (case-sensitive) repository URL and revision.\n" +
- "`git ls-remote` output: #{@resolved_reference}"
+ "`git ls-remote '#{@new_resource.repository}' '#{rev_search_pattern}'` output: #{@resolved_reference}"
end
end
@@ -240,35 +240,55 @@ class Chef
# annotated tags, we have to search for "revision*" and
# post-process. Special handling for 'HEAD' to ignore a tag
# named 'HEAD'.
- rev_pattern = case @new_resource.revision
- when '', 'HEAD'
- 'HEAD'
- else
- @new_resource.revision + '*'
- end
- command = git("ls-remote \"#{@new_resource.repository}\" \"#{rev_pattern}\"")
- @resolved_reference = shell_out!(command, run_options).stdout
- ref_lines = @resolved_reference.split("\n")
- refs = ref_lines.map { |line| line.split("\t") }
- # first try for ^{} indicating the commit pointed to by an
- # annotated tag
- tagged_commit = refs.find { |m| m[1].end_with?("#{@new_resource.revision}^{}") }
+ @resolved_reference = git_ls_remote(rev_search_pattern)
+ refs = @resolved_reference.split("\n").map { |line| line.split("\t") }
+ # First try for ^{} indicating the commit pointed to by an
+ # annotated tag.
# It is possible for a user to create a tag named 'HEAD'.
# Using such a degenerate annotated tag would be very
# confusing. We avoid the issue by disallowing the use of
# annotated tags named 'HEAD'.
- if tagged_commit && rev_pattern != 'HEAD'
- tagged_commit[0]
+ if rev_search_pattern != 'HEAD'
+ found = find_revision(refs, @new_resource.revision, '^{}')
else
- found = refs.find { |m| m[1].end_with?(@new_resource.revision) }
- if found
- found[0]
- else
- nil
- end
+ found = refs_search(refs, 'HEAD')
+ end
+ found = find_revision(refs, @new_resource.revision) if found.empty?
+ found.size == 1 ? found.first[0] : nil
+ end
+
+ def find_revision(refs, revision, suffix="")
+ found = refs_search(refs, rev_match_pattern('refs/tags/', revision) + suffix)
+ found = refs_search(refs, rev_match_pattern('refs/heads/', revision) + suffix) if found.empty?
+ found = refs_search(refs, revision + suffix) if found.empty?
+ found
+ end
+
+ def rev_match_pattern(prefix, revision)
+ if revision.start_with?(prefix)
+ revision
+ else
+ prefix + revision
end
end
+ def rev_search_pattern
+ if ['', 'HEAD'].include? @new_resource.revision
+ 'HEAD'
+ else
+ @new_resource.revision + '*'
+ end
+ end
+
+ def git_ls_remote(rev_pattern)
+ command = git(%Q(ls-remote "#{@new_resource.repository}" "#{rev_pattern}"))
+ shell_out!(command, run_options).stdout
+ end
+
+ def refs_search(refs, pattern)
+ refs.find_all { |m| m[1] == pattern }
+ end
+
private
def run_options(run_opts={})
diff --git a/lib/chef/provider/lwrp_base.rb b/lib/chef/provider/lwrp_base.rb
index 90ce70ae61..135a3f6b7c 100644
--- a/lib/chef/provider/lwrp_base.rb
+++ b/lib/chef/provider/lwrp_base.rb
@@ -81,22 +81,24 @@ class Chef
include Chef::DSL::DataQuery
def self.build_from_file(cookbook_name, filename, run_context)
+ provider_class = nil
provider_name = filename_to_qualified_string(cookbook_name, filename)
- # Add log entry if we override an existing light-weight provider.
class_name = convert_to_class_name(provider_name)
if Chef::Provider.const_defined?(class_name)
- Chef::Log.info("#{class_name} light-weight provider already initialized -- overriding!")
+ Chef::Log.info("#{class_name} light-weight provider is already initialized -- Skipping loading #{filename}!")
+ Chef::Log.debug("Overriding already defined LWRPs is not supported anymore starting with Chef 12.")
+ provider_class = Chef::Provider.const_get(class_name)
+ else
+ provider_class = Class.new(self)
+ provider_class.class_from_file(filename)
+
+ class_name = convert_to_class_name(provider_name)
+ Chef::Provider.const_set(class_name, provider_class)
+ Chef::Log.debug("Loaded contents of #{filename} into a provider named #{provider_name} defined in Chef::Provider::#{class_name}")
end
- provider_class = Class.new(self)
- provider_class.class_from_file(filename)
-
- class_name = convert_to_class_name(provider_name)
- Chef::Provider.const_set(class_name, provider_class)
- Chef::Log.debug("Loaded contents of #{filename} into a provider named #{provider_name} defined in Chef::Provider::#{class_name}")
-
provider_class
end
diff --git a/lib/chef/provider/package/freebsd/pkgng.rb b/lib/chef/provider/package/freebsd/pkgng.rb
index 0741a4d95f..bfe6dca617 100644
--- a/lib/chef/provider/package/freebsd/pkgng.rb
+++ b/lib/chef/provider/package/freebsd/pkgng.rb
@@ -45,7 +45,7 @@ class Chef
def current_installed_version
pkg_info = shell_out!("pkg info \"#{@new_resource.package_name}\"", :env => nil, :returns => [0,70])
- pkg_info.stdout[/^#{Regexp.escape(@new_resource.package_name)}-(.+)/, 1]
+ pkg_info.stdout[/^Version +: (.+)$/, 1]
end
def candidate_version
diff --git a/lib/chef/provider/package/freebsd/port.rb b/lib/chef/provider/package/freebsd/port.rb
index 4b3510f0e9..8b191179f0 100644
--- a/lib/chef/provider/package/freebsd/port.rb
+++ b/lib/chef/provider/package/freebsd/port.rb
@@ -34,7 +34,7 @@ class Chef
end
def current_installed_version
- pkg_info = if supports_pkgng?
+ pkg_info = if @new_resource.supports_pkgng?
shell_out!("pkg info \"#{@new_resource.package_name}\"", :env => nil, :returns => [0,70])
else
shell_out!("pkg_info -E \"#{@new_resource.package_name}*\"", :env => nil, :returns => [0,1])
@@ -53,14 +53,6 @@ class Chef
def port_dir
super(@new_resource.package_name)
end
-
- private
-
- def supports_pkgng?
- with_pkgng = makefile_variable_value('WITH_PKGNG')
- with_pkgng && with_pkgng =~ /yes/i
- end
-
end
end
end
diff --git a/lib/chef/provider/package/pacman.rb b/lib/chef/provider/package/pacman.rb
index 1014ebcaa5..a9ff0edf7f 100644
--- a/lib/chef/provider/package/pacman.rb
+++ b/lib/chef/provider/package/pacman.rb
@@ -62,11 +62,11 @@ class Chef
package_repos = repos.map {|r| Regexp.escape(r) }.join('|')
- status = popen4("pacman -Ss #{@new_resource.package_name}") do |pid, stdin, stdout, stderr|
+ status = popen4("pacman -Sl") do |pid, stdin, stdout, stderr|
stdout.each do |line|
case line
- when /^(#{package_repos})\/#{Regexp.escape(@new_resource.package_name)} (.+)$/
- # $2 contains a string like "4.4.0-1 (kde kdenetwork)" or "3.10-4 (base)"
+ when /^(#{package_repos}) #{Regexp.escape(@new_resource.package_name)} (.+)$/
+ # $2 contains a string like "4.4.0-1" or "3.10-4 [installed]"
# simply split by space and use first token
@candidate_version = $2.split(" ").first
end
diff --git a/lib/chef/provider/package/paludis.rb b/lib/chef/provider/package/paludis.rb
index 7c5245fc97..f363b38e50 100644
--- a/lib/chef/provider/package/paludis.rb
+++ b/lib/chef/provider/package/paludis.rb
@@ -34,7 +34,7 @@ class Chef
installed = false
re = Regexp.new('(.*)[[:blank:]](.*)[[:blank:]](.*)$')
- shell_out!("cave -L warning print-ids -M none -m \"*/#{@new_resource.package_name.split('/').last}\" -f \"%c/%p %v %r\n\"").stdout.each_line do |line|
+ shell_out!("cave -L warning print-ids -M none -m \"#{@new_resource.package_name}\" -f \"%c/%p %v %r\n\"").stdout.each_line do |line|
res = re.match(line)
unless res.nil?
case res[3]
diff --git a/lib/chef/provider/package/rubygems.rb b/lib/chef/provider/package/rubygems.rb
index be0022f4aa..6c7e1c066e 100644
--- a/lib/chef/provider/package/rubygems.rb
+++ b/lib/chef/provider/package/rubygems.rb
@@ -493,6 +493,7 @@ class Chef
def target_version_already_installed?
return false unless @current_resource && @current_resource.version
return false if @current_resource.version.nil?
+ return false if @new_resource.version.nil?
Gem::Requirement.new(@new_resource.version).satisfied_by?(Gem::Version.new(@current_resource.version))
end
diff --git a/lib/chef/resource/cookbook_file.rb b/lib/chef/resource/cookbook_file.rb
index de758aef71..2709cf64f4 100644
--- a/lib/chef/resource/cookbook_file.rb
+++ b/lib/chef/resource/cookbook_file.rb
@@ -40,7 +40,7 @@ class Chef
end
def source(source_filename=nil)
- set_or_return(:source, source_filename, :kind_of => String)
+ set_or_return(:source, source_filename, :kind_of => [ String, Array ])
end
def cookbook(cookbook_name=nil)
diff --git a/lib/chef/resource/dsc_script.rb b/lib/chef/resource/dsc_script.rb
index 2972ace1aa..76ac6659d6 100644
--- a/lib/chef/resource/dsc_script.rb
+++ b/lib/chef/resource/dsc_script.rb
@@ -28,12 +28,8 @@ class Chef
super
@allowed_actions.push(:run)
@action = :run
- if(run_context && Chef::Platform.supports_dsc?(run_context.node))
- @provider = Chef::Provider::DscScript
- else
- raise Chef::Exceptions::NoProviderAvailable,
- "#{powershell_info_str(run_context)}\nPowershell 4.0 or higher was not detected on your system and is required to use the dsc_script resource."
- end
+ @provider = Chef::Provider::DscScript
+ @resource_name = :dsc_script
end
def code(arg=nil)
@@ -125,16 +121,6 @@ class Chef
:kind_of => [ Integer ]
)
end
-
- private
-
- def powershell_info_str(run_context)
- if run_context && run_context.node[:languages] && run_context.node[:languages][:powershell]
- install_info = "Powershell #{run_context.node[:languages][:powershell][:version]} was found on the system."
- else
- install_info = 'Powershell was not found.'
- end
- end
end
end
end
diff --git a/lib/chef/resource/freebsd_package.rb b/lib/chef/resource/freebsd_package.rb
index 70ef62ae8a..40cc63fc55 100644
--- a/lib/chef/resource/freebsd_package.rb
+++ b/lib/chef/resource/freebsd_package.rb
@@ -52,28 +52,27 @@ class Chef
"#{created_as_type}[#{name}]"
end
+ def supports_pkgng?
+ ships_with_pkgng? || !!shell_out!("make -V WITH_PKGNG", :env => nil).stdout.match(/yes/i)
+ end
+
private
+ def ships_with_pkgng?
+ # It was not until __FreeBSD_version 1000017 that pkgng became
+ # the default binary package manager. See '/usr/ports/Mk/bsd.port.mk'.
+ node.automatic[:os_version].to_i >= 1000017
+ end
+
def assign_provider
@provider = if @source.to_s =~ /^ports$/i
Chef::Provider::Package::Freebsd::Port
- elsif ships_with_pkgng? || supports_pkgng?
+ elsif supports_pkgng?
Chef::Provider::Package::Freebsd::Pkgng
else
Chef::Provider::Package::Freebsd::Pkg
end
end
-
- def ships_with_pkgng?
- # It was not until __FreeBSD_version 1000017 that pkgng became
- # the default binary package manager. See '/usr/ports/Mk/bsd.port.mk'.
- node[:os_version].to_i >= 1000017
- end
-
- def supports_pkgng?
- !!shell_out!("make -V WITH_PKGNG", :env => nil).stdout.match(/yes/i)
- end
-
end
end
end
diff --git a/lib/chef/resource/lwrp_base.rb b/lib/chef/resource/lwrp_base.rb
index 5b67941a8b..a4606be842 100644
--- a/lib/chef/resource/lwrp_base.rb
+++ b/lib/chef/resource/lwrp_base.rb
@@ -35,26 +35,24 @@ class Chef
# Evaluates the LWRP resource file and instantiates a new Resource class.
def self.build_from_file(cookbook_name, filename, run_context)
+ resource_class = nil
rname = filename_to_qualified_string(cookbook_name, filename)
- # Add log entry if we override an existing lightweight resource.
class_name = convert_to_class_name(rname)
if Resource.strict_const_defined?(class_name)
- old_class = Resource.send(:remove_const, class_name)
- # CHEF-3432 -- Chef::Resource keeps a list of subclasses; need to
- # remove old ones from the list when replacing.
- resource_classes.delete(old_class)
- Chef::Log.info("#{class_name} lightweight resource already initialized -- overriding!")
- end
-
- resource_class = Class.new(self)
+ Chef::Log.info("#{class_name} light-weight resource is already initialized -- Skipping loading #{filename}!")
+ Chef::Log.debug("Overriding already defined LWRPs is not supported anymore starting with Chef 12.")
+ resource_class = Resource.const_get(class_name)
+ else
+ resource_class = Class.new(self)
- resource_class.resource_name = rname
- resource_class.run_context = run_context
- resource_class.class_from_file(filename)
+ resource_class.resource_name = rname
+ resource_class.run_context = run_context
+ resource_class.class_from_file(filename)
- Chef::Resource.const_set(class_name, resource_class)
- Chef::Log.debug("Loaded contents of #{filename} into a resource named #{rname} defined in Chef::Resource::#{class_name}")
+ Chef::Resource.const_set(class_name, resource_class)
+ Chef::Log.debug("Loaded contents of #{filename} into a resource named #{rname} defined in Chef::Resource::#{class_name}")
+ end
resource_class
end
@@ -112,10 +110,21 @@ class Chef
if action_names.empty?
defined?(@actions) ? @actions : from_superclass(:actions, []).dup
else
- @actions = action_names
+ # BC-compat way for checking if actions have already been defined
+ if defined?(@actions)
+ @actions.push(*action_names)
+ else
+ @actions = action_names
+ end
end
end
+ # @deprecated
+ def self.valid_actions(*args)
+ Chef::Log.warn("`valid_actions' is deprecated, please use actions `instead'!")
+ actions(*args)
+ end
+
# Set the run context on the class. Used to provide access to the node
# during class definition.
def self.run_context=(run_context)
diff --git a/lib/chef/resource/template.rb b/lib/chef/resource/template.rb
index 9cba6f1c38..8473f5b677 100644
--- a/lib/chef/resource/template.rb
+++ b/lib/chef/resource/template.rb
@@ -50,7 +50,7 @@ class Chef
set_or_return(
:source,
file,
- :kind_of => [ String ]
+ :kind_of => [ String, Array ]
)
end
diff --git a/lib/chef/util/powershell/cmdlet_result.rb b/lib/chef/util/powershell/cmdlet_result.rb
index af7b3607cd..246701a7bc 100644
--- a/lib/chef/util/powershell/cmdlet_result.rb
+++ b/lib/chef/util/powershell/cmdlet_result.rb
@@ -16,7 +16,7 @@
# limitations under the License.
#
-require 'json'
+require 'chef/json_compat'
class Chef::Util::Powershell
class CmdletResult
@@ -33,7 +33,7 @@ class Chef::Util::Powershell
def return_value
if output_format == :object
- JSON.parse(@status.stdout)
+ Chef::JSONCompat.parse(@status.stdout)
else
@status.stdout
end
diff --git a/spec/data/bootstrap/test-hints.erb b/spec/data/bootstrap/test-hints.erb
index 29ba710b42..7693fdc7c9 100644
--- a/spec/data/bootstrap/test-hints.erb
+++ b/spec/data/bootstrap/test-hints.erb
@@ -6,7 +6,7 @@ mkdir -p /etc/chef/ohai/hints
<% @chef_config[:knife][:hints].each do |name, hash| -%>
(
cat <<'EOP'
-<%= hash.to_json %>
+<%= Chef::JSONCompat.to_json(hash) %>
EOP
) > /etc/chef/ohai/hints/<%= name %>.json
<% end -%>
diff --git a/spec/data/bootstrap/test.erb b/spec/data/bootstrap/test.erb
index 7cdc7dfdd0..3a383b47d0 100644
--- a/spec/data/bootstrap/test.erb
+++ b/spec/data/bootstrap/test.erb
@@ -1 +1 @@
-<%= first_boot.to_json %> \ No newline at end of file
+<%= Chef::JSONCompat.to_json(first_boot) %>
diff --git a/spec/data/cb_version_cookbooks/cookbook2/files/test.txt b/spec/data/cb_version_cookbooks/cookbook2/files/test.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/spec/data/cb_version_cookbooks/cookbook2/files/test.txt
diff --git a/spec/data/cb_version_cookbooks/cookbook2/templates/test.erb b/spec/data/cb_version_cookbooks/cookbook2/templates/test.erb
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/spec/data/cb_version_cookbooks/cookbook2/templates/test.erb
diff --git a/spec/data/cookbooks/ignorken/files/default/not_me.rb b/spec/data/cookbooks/ignorken/files/default/not_me.rb
new file mode 100644
index 0000000000..8063e32a95
--- /dev/null
+++ b/spec/data/cookbooks/ignorken/files/default/not_me.rb
@@ -0,0 +1,2 @@
+a cat walked on the keyboard one day...
+(*&(*&(*&(*&(*^%$%^%#^^&(*)(*{}}}}}}}}+++++===))))))
diff --git a/spec/data/cookbooks/ignorken/templates/ubuntu-12.10/not_me.rb b/spec/data/cookbooks/ignorken/templates/ubuntu-12.10/not_me.rb
new file mode 100644
index 0000000000..8063e32a95
--- /dev/null
+++ b/spec/data/cookbooks/ignorken/templates/ubuntu-12.10/not_me.rb
@@ -0,0 +1,2 @@
+a cat walked on the keyboard one day...
+(*&(*&(*&(*&(*^%$%^%#^^&(*)(*{}}}}}}}}+++++===))))))
diff --git a/spec/data/cookbooks/openldap/libraries/openldap.rb b/spec/data/cookbooks/openldap/libraries/openldap.rb
new file mode 100644
index 0000000000..6a3f058f95
--- /dev/null
+++ b/spec/data/cookbooks/openldap/libraries/openldap.rb
@@ -0,0 +1,4 @@
+require_relative './openldap/version.rb'
+
+class OpenLDAP
+end
diff --git a/spec/data/cookbooks/openldap/libraries/openldap/version.rb b/spec/data/cookbooks/openldap/libraries/openldap/version.rb
new file mode 100644
index 0000000000..4bff12b01c
--- /dev/null
+++ b/spec/data/cookbooks/openldap/libraries/openldap/version.rb
@@ -0,0 +1,3 @@
+class OpenLDAP
+ VERSION = '8.9.10'
+end
diff --git a/spec/data/lwrp/providers/buck_passer.rb b/spec/data/lwrp/providers/buck_passer.rb
index 1f83e5098b..8d5156af81 100644
--- a/spec/data/lwrp/providers/buck_passer.rb
+++ b/spec/data/lwrp/providers/buck_passer.rb
@@ -1,3 +1,10 @@
-action :buck_stops_here do
- log "This should be overwritten by ../lwrp_override/buck_passer.rb"
+action :pass_buck do
+ lwrp_foo :prepared_thumbs do
+ action :prepare_thumbs
+ provider :lwrp_thumb_twiddler
+ end
+ lwrp_foo :twiddled_thumbs do
+ action :twiddle_thumbs
+ provider :lwrp_thumb_twiddler
+ end
end
diff --git a/spec/data/lwrp/resources/foo.rb b/spec/data/lwrp/resources/foo.rb
index c881c80530..0ee83f0cd0 100644
--- a/spec/data/lwrp/resources/foo.rb
+++ b/spec/data/lwrp/resources/foo.rb
@@ -1,3 +1,4 @@
-actions :never_execute
+actions :prepare_thumbs, :twiddle_thumbs
+default_action :pass_buck
-attribute :ever, :kind_of => String
+attribute :monkey, :kind_of => String
diff --git a/spec/data/lwrp_override/providers/buck_passer.rb b/spec/data/lwrp_override/providers/buck_passer.rb
index 75917a58c9..2061b391dc 100644
--- a/spec/data/lwrp_override/providers/buck_passer.rb
+++ b/spec/data/lwrp_override/providers/buck_passer.rb
@@ -1,10 +1,5 @@
-action :pass_buck do
- lwrp_foo :prepared_thumbs do
- action :prepare_thumbs
- provider :lwrp_thumb_twiddler
- end
- lwrp_foo :twiddled_thumbs do
- action :twiddle_thumbs
- provider :lwrp_thumb_twiddler
- end
-end \ No newline at end of file
+# Starting with Chef 12 reloading an LWRP shouldn't reload the file anymore
+
+action :buck_stops_here do
+ log "This should be overwritten by ../lwrp_override/buck_passer.rb"
+end
diff --git a/spec/data/lwrp_override/resources/foo.rb b/spec/data/lwrp_override/resources/foo.rb
index 0ee83f0cd0..14decb9634 100644
--- a/spec/data/lwrp_override/resources/foo.rb
+++ b/spec/data/lwrp_override/resources/foo.rb
@@ -1,4 +1,5 @@
-actions :prepare_thumbs, :twiddle_thumbs
-default_action :pass_buck
+# Starting with Chef 12 reloading an LWRP shouldn't reload the file anymore
-attribute :monkey, :kind_of => String
+actions :never_execute
+
+attribute :ever, :kind_of => String
diff --git a/spec/functional/knife/cookbook_delete_spec.rb b/spec/functional/knife/cookbook_delete_spec.rb
index ee620bf165..4773fd2185 100644
--- a/spec/functional/knife/cookbook_delete_spec.rb
+++ b/spec/functional/knife/cookbook_delete_spec.rb
@@ -47,7 +47,7 @@ describe Chef::Knife::CookbookDelete do
Chef::Log.level = :debug
@knife.name_args = %w{no-such-cookbook}
- @api.get("/cookbooks/no-such-cookbook", 404, {'error'=>'dear Tim, no. -Sent from my iPad'}.to_json)
+ @api.get("/cookbooks/no-such-cookbook", 404, Chef::JSONCompat.to_json({'error'=>'dear Tim, no. -Sent from my iPad'}))
end
it "logs an error and exits" do
@@ -62,7 +62,7 @@ describe Chef::Knife::CookbookDelete do
before do
@knife.name_args = %w{obsolete-cookbook}
@cookbook_list = {'obsolete-cookbook' => { 'versions' => ['version' => '1.0.0']} }
- @api.get("/cookbooks/obsolete-cookbook", 200, @cookbook_list.to_json)
+ @api.get("/cookbooks/obsolete-cookbook", 200, Chef::JSONCompat.to_json(@cookbook_list))
end
it "asks for confirmation, then deletes the cookbook" do
@@ -105,7 +105,7 @@ describe Chef::Knife::CookbookDelete do
versions = ['1.0.0', '1.1.0', '1.2.0']
with_version = lambda { |version| { 'version' => version } }
@cookbook_list = {'obsolete-cookbook' => { 'versions' => versions.map(&with_version) } }
- @api.get("/cookbooks/obsolete-cookbook", 200, @cookbook_list.to_json)
+ @api.get("/cookbooks/obsolete-cookbook", 200, Chef::JSONCompat.to_json(@cookbook_list))
end
it "deletes all versions of a cookbook when given the '-a' flag" do
diff --git a/spec/functional/knife/exec_spec.rb b/spec/functional/knife/exec_spec.rb
index 455160fd5c..7eb52d01df 100644
--- a/spec/functional/knife/exec_spec.rb
+++ b/spec/functional/knife/exec_spec.rb
@@ -47,7 +47,7 @@ describe Chef::Knife::Exec do
@node = Chef::Node.new
@node.name("ohai-world")
response = {"rows" => [@node],"start" => 0,"total" => 1}
- @api.get(%r{^/search/node}, 200, response.to_json)
+ @api.get(%r{^/search/node}, 200, Chef::JSONCompat.to_json(response))
code = "$output.puts nodes.all"
@knife.config[:exec] = code
@knife.run
diff --git a/spec/functional/util/powershell/cmdlet_spec.rb b/spec/functional/util/powershell/cmdlet_spec.rb
index 63d1ac09b5..b240a5ec12 100644
--- a/spec/functional/util/powershell/cmdlet_spec.rb
+++ b/spec/functional/util/powershell/cmdlet_spec.rb
@@ -16,7 +16,7 @@
# limitations under the License.
#
-require 'json'
+require 'chef/json_compat'
require File.expand_path('../../../../spec_helper', __FILE__)
describe Chef::Util::Powershell::Cmdlet, :windows_only do
@@ -91,7 +91,7 @@ describe Chef::Util::Powershell::Cmdlet, :windows_only do
it "returns json format data", :windows_powershell_dsc_only do
result = cmdlet_alias_requires_switch_or_argument.run({},{},'ls')
expect(result.succeeded?).to eq(true)
- expect(lambda{JSON.parse(result.return_value)}).not_to raise_error
+ expect(lambda{Chef::JSONCompat.parse(result.return_value)}).not_to raise_error
end
end
diff --git a/spec/integration/knife/chef_fs_data_store_spec.rb b/spec/integration/knife/chef_fs_data_store_spec.rb
index c6737e08cb..a4d62673de 100644
--- a/spec/integration/knife/chef_fs_data_store_spec.rb
+++ b/spec/integration/knife/chef_fs_data_store_spec.rb
@@ -22,7 +22,7 @@ require 'chef/knife/show'
require 'chef/knife/raw'
require 'chef/knife/cookbook_upload'
-describe 'ChefFSDataStore tests' do
+describe 'ChefFSDataStore tests', :workstation do
include IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/chef_repo_path_spec.rb b/spec/integration/knife/chef_repo_path_spec.rb
index 90455ed374..874b33901f 100644
--- a/spec/integration/knife/chef_repo_path_spec.rb
+++ b/spec/integration/knife/chef_repo_path_spec.rb
@@ -20,7 +20,7 @@ require 'support/shared/context/config'
require 'chef/knife/list'
require 'chef/knife/show'
-describe 'chef_repo_path tests' do
+describe 'chef_repo_path tests', :workstation do
include IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/chef_repository_file_system_spec.rb b/spec/integration/knife/chef_repository_file_system_spec.rb
index ff86924e22..34afd228f3 100644
--- a/spec/integration/knife/chef_repository_file_system_spec.rb
+++ b/spec/integration/knife/chef_repository_file_system_spec.rb
@@ -19,7 +19,7 @@ require 'support/shared/integration/integration_helper'
require 'chef/knife/list'
require 'chef/knife/show'
-describe 'General chef_repo file system checks' do
+describe 'General chef_repo file system checks', :workstation do
include IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/chefignore_spec.rb b/spec/integration/knife/chefignore_spec.rb
index b09959b581..34bf391f88 100644
--- a/spec/integration/knife/chefignore_spec.rb
+++ b/spec/integration/knife/chefignore_spec.rb
@@ -19,7 +19,7 @@ require 'support/shared/integration/integration_helper'
require 'chef/knife/list'
require 'chef/knife/show'
-describe 'chefignore tests' do
+describe 'chefignore tests', :workstation do
include IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/common_options_spec.rb b/spec/integration/knife/common_options_spec.rb
index 7a48f14ad3..dfc1e024f9 100644
--- a/spec/integration/knife/common_options_spec.rb
+++ b/spec/integration/knife/common_options_spec.rb
@@ -18,7 +18,7 @@
require 'support/shared/integration/integration_helper'
require 'chef/knife/raw'
-describe 'knife common options' do
+describe 'knife common options', :workstation do
include IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/cookbook_api_ipv6_spec.rb b/spec/integration/knife/cookbook_api_ipv6_spec.rb
index c5b5b81abe..e59c8912bd 100644
--- a/spec/integration/knife/cookbook_api_ipv6_spec.rb
+++ b/spec/integration/knife/cookbook_api_ipv6_spec.rb
@@ -18,7 +18,7 @@
require 'support/shared/integration/integration_helper'
require 'chef/mixin/shell_out'
-describe "Knife cookbook API integration with IPv6" do
+describe "Knife cookbook API integration with IPv6", :workstation do
include IntegrationSupport
include Chef::Mixin::ShellOut
diff --git a/spec/integration/knife/delete_spec.rb b/spec/integration/knife/delete_spec.rb
index e56469e102..733a7ef72b 100644
--- a/spec/integration/knife/delete_spec.rb
+++ b/spec/integration/knife/delete_spec.rb
@@ -20,7 +20,7 @@ require 'chef/knife/delete'
require 'chef/knife/list'
require 'chef/knife/raw'
-describe 'knife delete' do
+describe 'knife delete', :workstation do
include IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/deps_spec.rb b/spec/integration/knife/deps_spec.rb
index 2cbb7b8f74..8b4d71906b 100644
--- a/spec/integration/knife/deps_spec.rb
+++ b/spec/integration/knife/deps_spec.rb
@@ -19,7 +19,7 @@ require 'support/shared/integration/integration_helper'
require 'support/shared/context/config'
require 'chef/knife/deps'
-describe 'knife deps' do
+describe 'knife deps', :workstation do
include IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/diff_spec.rb b/spec/integration/knife/diff_spec.rb
index 62b491d6ef..c12ebbcf8f 100644
--- a/spec/integration/knife/diff_spec.rb
+++ b/spec/integration/knife/diff_spec.rb
@@ -18,7 +18,7 @@
require 'support/shared/integration/integration_helper'
require 'chef/knife/diff'
-describe 'knife diff' do
+describe 'knife diff', :workstation do
include IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/download_spec.rb b/spec/integration/knife/download_spec.rb
index 17779d1f47..0c2b907f1e 100644
--- a/spec/integration/knife/download_spec.rb
+++ b/spec/integration/knife/download_spec.rb
@@ -19,7 +19,7 @@ require 'support/shared/integration/integration_helper'
require 'chef/knife/download'
require 'chef/knife/diff'
-describe 'knife download' do
+describe 'knife download', :workstation do
include IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/list_spec.rb b/spec/integration/knife/list_spec.rb
index c9632e146d..3d8b83001d 100644
--- a/spec/integration/knife/list_spec.rb
+++ b/spec/integration/knife/list_spec.rb
@@ -19,7 +19,7 @@ require 'support/shared/integration/integration_helper'
require 'support/shared/context/config'
require 'chef/knife/list'
-describe 'knife list' do
+describe 'knife list', :workstation do
include IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/raw_spec.rb b/spec/integration/knife/raw_spec.rb
index fad69e4e11..2b49d2ebb2 100644
--- a/spec/integration/knife/raw_spec.rb
+++ b/spec/integration/knife/raw_spec.rb
@@ -20,7 +20,7 @@ require 'support/shared/context/config'
require 'chef/knife/raw'
require 'chef/knife/show'
-describe 'knife raw' do
+describe 'knife raw', :workstation do
include IntegrationSupport
include KnifeSupport
include AppServerSupport
diff --git a/spec/integration/knife/redirection_spec.rb b/spec/integration/knife/redirection_spec.rb
index 549a6f6df0..77bda99453 100644
--- a/spec/integration/knife/redirection_spec.rb
+++ b/spec/integration/knife/redirection_spec.rb
@@ -19,7 +19,7 @@ require 'support/shared/integration/integration_helper'
require 'support/shared/context/config'
require 'chef/knife/list'
-describe 'redirection' do
+describe 'redirection', :workstation do
include IntegrationSupport
include KnifeSupport
include AppServerSupport
diff --git a/spec/integration/knife/serve_spec.rb b/spec/integration/knife/serve_spec.rb
index 32e633543d..3c859b794e 100644
--- a/spec/integration/knife/serve_spec.rb
+++ b/spec/integration/knife/serve_spec.rb
@@ -19,7 +19,7 @@ require 'support/shared/integration/integration_helper'
require 'chef/knife/serve'
require 'chef/server_api'
-describe 'knife serve' do
+describe 'knife serve', :workstation do
include IntegrationSupport
include KnifeSupport
include AppServerSupport
diff --git a/spec/integration/knife/show_spec.rb b/spec/integration/knife/show_spec.rb
index 4a71499e87..bc7f1cf6d3 100644
--- a/spec/integration/knife/show_spec.rb
+++ b/spec/integration/knife/show_spec.rb
@@ -19,7 +19,7 @@ require 'support/shared/integration/integration_helper'
require 'support/shared/context/config'
require 'chef/knife/show'
-describe 'knife show' do
+describe 'knife show', :workstation do
include IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/upload_spec.rb b/spec/integration/knife/upload_spec.rb
index 05d33d1a17..dade476889 100644
--- a/spec/integration/knife/upload_spec.rb
+++ b/spec/integration/knife/upload_spec.rb
@@ -19,8 +19,9 @@ require 'support/shared/integration/integration_helper'
require 'chef/knife/upload'
require 'chef/knife/diff'
require 'chef/knife/raw'
+require 'chef/json_compat'
-describe 'knife upload' do
+describe 'knife upload', :workstation do
include IntegrationSupport
include KnifeSupport
@@ -261,7 +262,7 @@ Created /data_bags/x/y.json
EOM
knife('diff --name-status /data_bags').should_succeed <<EOM
EOM
- JSON.parse(knife('raw /data/x/y').stdout, :create_additions => false).keys.sort.should == [ 'foo', 'id' ]
+ Chef::JSONCompat.parse(knife('raw /data/x/y').stdout, :create_additions => false).keys.sort.should == [ 'foo', 'id' ]
end
it 'knife upload /data_bags/x /data_bags/x/y.json uploads x once' do
@@ -284,7 +285,7 @@ Created /data_bags/x
Created /data_bags/x/y.json
EOM
knife('diff --name-status /data_bags').should_succeed ''
- result = JSON.parse(knife('raw /data/x/y').stdout, :create_additions => false)
+ result = Chef::JSONCompat.parse(knife('raw /data/x/y').stdout, :create_additions => false)
result.keys.sort.should == [ 'chef_type', 'data_bag', 'id' ]
result['chef_type'].should == 'aaa'
result['data_bag'].should == 'bbb'
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index ed0a8f89f6..1760aab871 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -97,6 +97,9 @@ RSpec.configure do |config|
config.filter_run :focus => true
config.filter_run_excluding :external => true
+ # Only run these tests on platforms that are also chef workstations
+ config.filter_run_excluding :workstation if solaris?
+
# Tests that randomly fail, but may have value.
config.filter_run_excluding :volatile => true
config.filter_run_excluding :volatile_on_solaris => true if solaris?
@@ -185,3 +188,6 @@ module WEBrick
end
end
end
+
+# Enough stuff needs json serialization that I'm just adding it here for equality asserts
+require 'chef/json_compat'
diff --git a/spec/support/shared/integration/integration_helper.rb b/spec/support/shared/integration/integration_helper.rb
index b42f7f69d9..e6942c62af 100644
--- a/spec/support/shared/integration/integration_helper.rb
+++ b/spec/support/shared/integration/integration_helper.rb
@@ -72,7 +72,7 @@ module IntegrationSupport
File.open(filename, 'w') do |file|
raw = case contents
when Hash, Array
- JSON.pretty_generate(contents)
+ Chef::JSONCompat.to_json_pretty(contents)
else
contents
end
diff --git a/spec/support/shared/shared_examples.rb b/spec/support/shared/shared_examples.rb
new file mode 100644
index 0000000000..b20c65f8b6
--- /dev/null
+++ b/spec/support/shared/shared_examples.rb
@@ -0,0 +1,14 @@
+# For storing any examples shared between multiple tests
+
+# Any object which defines a .to_json should import this test
+shared_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+
+ let(:jsonable) {
+ raise "You must define the subject when including this test"
+ }
+
+ it "should allow consumers to call #to_json or Chef::JSONCompat.to_json" do
+ expect(jsonable.to_json).to eq(Chef::JSONCompat.to_json(jsonable))
+ end
+
+end
diff --git a/spec/tiny_server.rb b/spec/tiny_server.rb
index 7e6ef3a809..a2cfe168d5 100644
--- a/spec/tiny_server.rb
+++ b/spec/tiny_server.rb
@@ -22,7 +22,6 @@ require 'webrick/https'
require 'rack'
#require 'thin'
require 'singleton'
-require 'chef/json_compat'
require 'open-uri'
require 'chef/config'
@@ -152,7 +151,7 @@ module TinyServer
:available_routes => @routes, :request => env}
# Uncomment me for glorious debugging
# pp :not_found => debug_info
- [404, {'Content-Type' => 'application/json'}, [ debug_info.to_json ]]
+ [404, {'Content-Type' => 'application/json'}, [ Chef::JSONCompat.to_json(debug_info) ]]
end
end
diff --git a/spec/unit/api_client_spec.rb b/spec/unit/api_client_spec.rb
index 76fc4afb5c..bd6c5ef7fd 100644
--- a/spec/unit/api_client_spec.rb
+++ b/spec/unit/api_client_spec.rb
@@ -123,6 +123,10 @@ describe Chef::ApiClient do
it "does not include the private key if not present" do
@json.should_not include("private_key")
end
+
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:jsonable) { @client }
+ end
end
describe "when deserializing from JSON" do
@@ -135,7 +139,7 @@ describe Chef::ApiClient do
"validator" => true,
"json_class" => "Chef::ApiClient"
}
- @client = Chef::JSONCompat.from_json(client.to_json)
+ @client = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(client))
end
it "should deserialize to a Chef::ApiClient object" do
diff --git a/spec/unit/config_fetcher_spec.rb b/spec/unit/config_fetcher_spec.rb
index f6d5436a11..31787a0909 100644
--- a/spec/unit/config_fetcher_spec.rb
+++ b/spec/unit/config_fetcher_spec.rb
@@ -1,7 +1,8 @@
require 'spec_helper'
require 'chef/config_fetcher'
+
describe Chef::ConfigFetcher do
- let(:valid_json) { {:a=>"b"}.to_json }
+ let(:valid_json) { Chef::JSONCompat.to_json({:a=>"b"}) }
let(:invalid_json) { %q[{"syntax-error": "missing quote}] }
let(:http) { double("Chef::HTTP::Simple") }
diff --git a/spec/unit/cookbook/cookbook_version_loader_spec.rb b/spec/unit/cookbook/cookbook_version_loader_spec.rb
index 5772c5352d..4ba4e1de57 100644
--- a/spec/unit/cookbook/cookbook_version_loader_spec.rb
+++ b/spec/unit/cookbook/cookbook_version_loader_spec.rb
@@ -57,6 +57,11 @@ describe Chef::Cookbook::CookbookVersionLoader do
expect(loaded_cookbook.recipe_filenames).to include(full_path("/recipes/return.rb"))
end
+ it "loads libraries" do
+ expect(loaded_cookbook.library_filenames).to include(full_path('/libraries/openldap.rb'))
+ expect(loaded_cookbook.library_filenames).to include(full_path('/libraries/openldap/version.rb'))
+ end
+
it "loads static files in the files/ dir" do
expect(loaded_cookbook.file_filenames).to include(full_path("/files/default/remotedir/remotesubdir/remote_subdir_file1.txt"))
expect(loaded_cookbook.file_filenames).to include(full_path("/files/default/remotedir/remotesubdir/remote_subdir_file2.txt"))
diff --git a/spec/unit/cookbook/metadata_spec.rb b/spec/unit/cookbook/metadata_spec.rb
index e61c85b42b..51814320d4 100644
--- a/spec/unit/cookbook/metadata_spec.rb
+++ b/spec/unit/cookbook/metadata_spec.rb
@@ -29,7 +29,8 @@ describe Chef::Cookbook::Metadata do
@fields = [ :name, :description, :long_description, :maintainer,
:maintainer_email, :license, :platforms, :dependencies,
:recommendations, :suggestions, :conflicting, :providing,
- :replacing, :attributes, :groupings, :recipes, :version]
+ :replacing, :attributes, :groupings, :recipes, :version,
+ :source_url, :issues_url ]
end
it "does not depend on object identity for equality" do
@@ -140,6 +141,13 @@ describe Chef::Cookbook::Metadata do
metadata.recipes.should eq(Mash.new)
end
+ it "has an empty source_url string" do
+ metadata.source_url.should eq('')
+ end
+
+ it "has an empty issues_url string" do
+ metadata.issues_url.should eq('')
+ end
end
describe "validation" do
@@ -188,7 +196,9 @@ describe Chef::Cookbook::Metadata do
:license => "Apache v2.0",
:description => "Foobar!",
:long_description => "Much Longer\nSeriously",
- :version => "0.6.0"
+ :version => "0.6.0",
+ :source_url => "http://example.com",
+ :issues_url => "http://example.com/issues"
}
params.sort { |a,b| a.to_s <=> b.to_s }.each do |field, field_value|
describe field do
@@ -333,7 +343,9 @@ describe Chef::Cookbook::Metadata do
"type" => 'string',
"required" => 'recommended',
"recipes" => [ "mysql::server", "mysql::master" ],
- "default" => [ ]
+ "default" => [ ],
+ "source_url" => "http://example.com",
+ "issues_url" => "http://example.com/issues"
}
metadata.attribute("/db/mysql/databases", attrs).should == attrs
end
@@ -356,6 +368,24 @@ describe Chef::Cookbook::Metadata do
}.should raise_error(ArgumentError)
end
+ it "should not accept anything but a string for the source_url" do
+ lambda {
+ metadata.attribute("db/mysql/databases", :source_url => "foo")
+ }.should_not raise_error
+ lambda {
+ metadata.attribute("db/mysql/databases", :source_url => Hash.new)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "should not accept anything but a string for the issues_url" do
+ lambda {
+ metadata.attribute("db/mysql/databases", :issues_url => "foo")
+ }.should_not raise_error
+ lambda {
+ metadata.attribute("db/mysql/databases", :issues_url => Hash.new)
+ }.should raise_error(ArgumentError)
+ end
+
it "should not accept anything but an array of strings for choice" do
lambda {
metadata.attribute("db/mysql/databases", :choice => ['dedicated', 'shared'])
@@ -623,9 +653,13 @@ describe Chef::Cookbook::Metadata do
metadata.version "1.2.3"
end
+ it "should produce the same output from to_json and Chef::JSONCompat" do
+ expect(metadata.to_json).to eq(Chef::JSONCompat.to_json(metadata))
+ end
+
describe "serialize" do
- let(:deserialized_metadata) { Chef::JSONCompat.from_json(metadata.to_json) }
+ let(:deserialized_metadata) { Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(metadata)) }
it "should serialize to a json hash" do
deserialized_metadata.should be_a_kind_of(Hash)
@@ -648,6 +682,8 @@ describe Chef::Cookbook::Metadata do
attributes
recipes
version
+ source_url
+ issues_url
}.each do |t|
it "should include '#{t}'" do
deserialized_metadata[t].should == metadata.send(t.to_sym)
@@ -657,7 +693,7 @@ describe Chef::Cookbook::Metadata do
describe "deserialize" do
- let(:deserialized_metadata) { Chef::Cookbook::Metadata.from_json(metadata.to_json) }
+ let(:deserialized_metadata) { Chef::Cookbook::Metadata.from_json(Chef::JSONCompat.to_json(metadata)) }
it "should deserialize to a Chef::Cookbook::Metadata object" do
@@ -681,6 +717,8 @@ describe Chef::Cookbook::Metadata do
attributes
recipes
version
+ source_url
+ issues_url
}.each do |t|
it "should match '#{t}'" do
deserialized_metadata.send(t.to_sym).should == metadata.send(t.to_sym)
@@ -731,5 +769,4 @@ describe Chef::Cookbook::Metadata do
end
end
-
end
diff --git a/spec/unit/cookbook/syntax_check_spec.rb b/spec/unit/cookbook/syntax_check_spec.rb
index cd1ce96716..4d22e0e920 100644
--- a/spec/unit/cookbook/syntax_check_spec.rb
+++ b/spec/unit/cookbook/syntax_check_spec.rb
@@ -28,10 +28,12 @@ describe Chef::Cookbook::SyntaxCheck do
let(:syntax_check) { Chef::Cookbook::SyntaxCheck.new(cookbook_path) }
let(:open_ldap_cookbook_files) do
- %w{ attributes/default.rb
+ %w{ attributes/default.rb
attributes/smokey.rb
definitions/client.rb
definitions/server.rb
+ libraries/openldap.rb
+ libraries/openldap/version.rb
metadata.rb
recipes/default.rb
recipes/gigantor.rb
@@ -44,9 +46,10 @@ describe Chef::Cookbook::SyntaxCheck do
Chef::Log.level = :warn # suppress "Syntax OK" messages
@attr_files = %w{default.rb smokey.rb}.map { |f| File.join(cookbook_path, 'attributes', f) }
+ @libr_files = %w{openldap.rb openldap/version.rb}.map { |f| File.join(cookbook_path, 'libraries', f) }
@defn_files = %w{client.rb server.rb}.map { |f| File.join(cookbook_path, 'definitions', f)}
@recipes = %w{default.rb gigantor.rb one.rb return.rb}.map { |f| File.join(cookbook_path, 'recipes', f) }
- @ruby_files = @attr_files + @defn_files + @recipes + [File.join(cookbook_path, "metadata.rb")]
+ @ruby_files = @attr_files + @libr_files + @defn_files + @recipes + [File.join(cookbook_path, "metadata.rb")]
basenames = %w{ helpers_via_partial_test.erb
helper_test.erb
openldap_stuff.conf.erb
diff --git a/spec/unit/cookbook_loader_spec.rb b/spec/unit/cookbook_loader_spec.rb
index f40bbd5696..deaf393d7a 100644
--- a/spec/unit/cookbook_loader_spec.rb
+++ b/spec/unit/cookbook_loader_spec.rb
@@ -210,7 +210,7 @@ describe Chef::CookbookLoader do
aa.to_hash["metadata"].recipes.keys.should include("openldap")
expected_desc = "Main Open LDAP configuration"
aa.to_hash["metadata"].recipes["openldap"].should == expected_desc
- raw = aa.to_hash["metadata"].recipes.to_json
+ raw = Chef::JSONCompat.to_json(aa.to_hash["metadata"].recipes)
search_str = "\"openldap\":\""
key_idx = raw.index(search_str)
key_idx.should be > 0
diff --git a/spec/unit/cookbook_version_spec.rb b/spec/unit/cookbook_version_spec.rb
index f20bc3766a..8436e5c480 100644
--- a/spec/unit/cookbook_version_spec.rb
+++ b/spec/unit/cookbook_version_spec.rb
@@ -115,14 +115,13 @@ describe Chef::CookbookVersion do
@cookbook[:provider_filenames] = Dir[File.join(@cookbook_root, 'providers', '**', '*.rb')]
@cookbook[:root_filenames] = Array(File.join(@cookbook_root, 'README.rdoc'))
@cookbook[:metadata_filenames] = Array(File.join(@cookbook_root, 'metadata.json'))
-
end
describe "and a cookbook with the same name" do
before do
# Currently the cookbook loader finds all the files then tells CookbookVersion
# where they are.
- @cookbook_version = Chef::CookbookVersion.new("tatft", @cookbook_root)
+ @cookbook_version = Chef::CookbookVersion.new('tatft', @cookbook_root)
@cookbook_version.attribute_filenames = @cookbook[:attribute_filenames]
@cookbook_version.definition_filenames = @cookbook[:definition_filenames]
@@ -350,6 +349,84 @@ describe Chef::CookbookVersion do
readme["specificity"].should == "default"
end
end
+ end
+
+ describe 'with a cookbook directory named cookbook2 that has unscoped files' do
+ before do
+ @cookbook = Hash.new { |hash, key| hash[key] = [] }
+
+ @cookbook_root = File.join(CHEF_SPEC_DATA, 'cb_version_cookbooks', 'cookbook2')
+
+ # Dunno if the paths here are representitive of what is set by CookbookLoader...
+ @cookbook[:attribute_filenames] = Dir[File.join(@cookbook_root, 'attributes', '**', '*.rb')]
+ @cookbook[:definition_filenames] = Dir[File.join(@cookbook_root, 'definitions', '**', '*.rb')]
+ @cookbook[:file_filenames] = Dir[File.join(@cookbook_root, 'files', '**', '*.*')]
+ @cookbook[:recipe_filenames] = Dir[File.join(@cookbook_root, 'recipes', '**', '*.rb')]
+ @cookbook[:template_filenames] = Dir[File.join(@cookbook_root, 'templates', '**', '*.*')]
+ @cookbook[:library_filenames] = Dir[File.join(@cookbook_root, 'libraries', '**', '*.rb')]
+ @cookbook[:resource_filenames] = Dir[File.join(@cookbook_root, 'resources', '**', '*.rb')]
+ @cookbook[:provider_filenames] = Dir[File.join(@cookbook_root, 'providers', '**', '*.rb')]
+ @cookbook[:root_filenames] = Array(File.join(@cookbook_root, 'README.rdoc'))
+ @cookbook[:metadata_filenames] = Array(File.join(@cookbook_root, 'metadata.json'))
+
+ @cookbook_version = Chef::CookbookVersion.new('cookbook2', @cookbook_root)
+ @cookbook_version.attribute_filenames = @cookbook[:attribute_filenames]
+ @cookbook_version.definition_filenames = @cookbook[:definition_filenames]
+ @cookbook_version.recipe_filenames = @cookbook[:recipe_filenames]
+ @cookbook_version.template_filenames = @cookbook[:template_filenames]
+ @cookbook_version.file_filenames = @cookbook[:file_filenames]
+ @cookbook_version.library_filenames = @cookbook[:library_filenames]
+ @cookbook_version.resource_filenames = @cookbook[:resource_filenames]
+ @cookbook_version.provider_filenames = @cookbook[:provider_filenames]
+ @cookbook_version.root_filenames = @cookbook[:root_filenames]
+ @cookbook_version.metadata_filenames = @cookbook[:metadata_filenames]
+
+ # Used to test file-specificity related file lookups
+ @node = Chef::Node.new
+ @node.set[:platform] = "ubuntu"
+ @node.set[:platform_version] = "13.04"
+ @node.name("testing")
+ end
+
+ it "should see a template" do
+ @cookbook_version.should have_template_for_node(@node, "test.erb")
+ end
+
+ it "should see a template using an array lookup" do
+ @cookbook_version.should have_template_for_node(@node, ["test.erb"])
+ end
+
+ it "should see a template using an array lookup with non-existant elements" do
+ @cookbook_version.should have_template_for_node(@node, ["missing.txt", "test.erb"])
+ end
+
+ it "should see a file" do
+ @cookbook_version.should have_cookbook_file_for_node(@node, "test.txt")
+ end
+
+ it "should see a file using an array lookup" do
+ @cookbook_version.should have_cookbook_file_for_node(@node, ["test.txt"])
+ end
+
+ it "should see a file using an array lookup with non-existant elements" do
+ @cookbook_version.should have_cookbook_file_for_node(@node, ["missing.txt", "test.txt"])
+ end
+
+ it "should not see a non-existant template" do
+ @cookbook_version.should_not have_template_for_node(@node, "missing.erb")
+ end
+
+ it "should not see a non-existant template using an array lookup" do
+ @cookbook_version.should_not have_template_for_node(@node, ["missing.erb"])
+ end
+
+ it "should not see a non-existant file" do
+ @cookbook_version.should_not have_cookbook_file_for_node(@node, "missing.txt")
+ end
+
+ it "should not see a non-existant file using an array lookup" do
+ @cookbook_version.should_not have_cookbook_file_for_node(@node, ["missing.txt"])
+ end
end
@@ -422,4 +499,8 @@ describe Chef::CookbookVersion do
end
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:jsonable) { Chef::CookbookVersion.new("tatft", '/tmp/blah') }
+ end
+
end
diff --git a/spec/unit/data_bag_item_spec.rb b/spec/unit/data_bag_item_spec.rb
index ead0dadfa2..5972d8a239 100644
--- a/spec/unit/data_bag_item_spec.rb
+++ b/spec/unit/data_bag_item_spec.rb
@@ -166,7 +166,7 @@ describe Chef::DataBagItem do
before(:each) do
@data_bag_item.data_bag('mars_volta')
@data_bag_item.raw_data = { "id" => "octahedron", "snooze" => { "finally" => :world_will }}
- @deserial = Chef::JSONCompat.from_json(@data_bag_item.to_json)
+ @deserial = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(@data_bag_item))
end
it "should deserialize to a Chef::DataBagItem object" do
@@ -184,6 +184,10 @@ describe Chef::DataBagItem do
it "should have a matching 'snooze' key" do
@deserial["snooze"].should == { "finally" => "world_will" }
end
+
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:jsonable) { @data_bag_item }
+ end
end
describe "when converting to a string" do
diff --git a/spec/unit/data_bag_spec.rb b/spec/unit/data_bag_spec.rb
index c905277b7c..ff323902eb 100644
--- a/spec/unit/data_bag_spec.rb
+++ b/spec/unit/data_bag_spec.rb
@@ -59,7 +59,7 @@ describe Chef::DataBag do
describe "deserialize" do
before(:each) do
@data_bag.name('mars_volta')
- @deserial = Chef::JSONCompat.from_json(@data_bag.to_json)
+ @deserial = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(@data_bag))
end
it "should deserialize to a Chef::DataBag object" do
@@ -72,6 +72,10 @@ describe Chef::DataBag do
it "should match '#{t}'" do
@deserial.send(t.to_sym).should == @data_bag.send(t.to_sym)
end
+
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:jsonable) { @data_bag }
+ end
end
end
diff --git a/spec/unit/encrypted_data_bag_item_spec.rb b/spec/unit/encrypted_data_bag_item_spec.rb
index 5ee245b9bc..9335889ef3 100644
--- a/spec/unit/encrypted_data_bag_item_spec.rb
+++ b/spec/unit/encrypted_data_bag_item_spec.rb
@@ -168,6 +168,17 @@ describe Chef::EncryptedDataBagItem::Decryptor do
let(:plaintext_data) { {"foo" => "bar"} }
let(:encryption_key) { "passwd" }
let(:decryption_key) { encryption_key }
+ let(:json_wrapped_data) { Chef::JSONCompat.to_json({"json_wrapper" => plaintext_data}) }
+
+ shared_examples "decryption examples" do
+ it "decrypts the encrypted value" do
+ decryptor.decrypted_data.should eq(json_wrapped_data)
+ end
+
+ it "unwraps the encrypted data and returns it" do
+ decryptor.for_decrypted_item.should eq plaintext_data
+ end
+ end
context "when decrypting a version 3 (JSON+aes-256-gcm+random iv+auth tag) encrypted value" do
@@ -179,13 +190,7 @@ describe Chef::EncryptedDataBagItem::Decryptor do
let(:bogus_auth_tag) { "bogus_auth_tag" }
- it "decrypts the encrypted value" do
- decryptor.decrypted_data.should eq({"json_wrapper" => plaintext_data}.to_json)
- end
-
- it "unwraps the encrypted data and returns it" do
- decryptor.for_decrypted_item.should eq plaintext_data
- end
+ include_examples "decryption examples"
it "rejects the data if the authentication tag is wrong" do
encrypted_value["auth_tag"] = bogus_auth_tag
@@ -240,13 +245,7 @@ describe Chef::EncryptedDataBagItem::Decryptor do
Base64.encode64(raw_hmac)
end
- it "decrypts the encrypted value" do
- decryptor.decrypted_data.should eq({"json_wrapper" => plaintext_data}.to_json)
- end
-
- it "unwraps the encrypted data and returns it" do
- decryptor.for_decrypted_item.should eq plaintext_data
- end
+ include_examples "decryption examples"
it "rejects the data if the hmac is wrong" do
encrypted_value["hmac"] = bogus_hmac
@@ -270,13 +269,7 @@ describe Chef::EncryptedDataBagItem::Decryptor do
decryptor.should be_a_instance_of Chef::EncryptedDataBagItem::Decryptor::Version1Decryptor
end
- it "decrypts the encrypted value" do
- decryptor.decrypted_data.should eq({"json_wrapper" => plaintext_data}.to_json)
- end
-
- it "unwraps the encrypted data and returns it" do
- decryptor.for_decrypted_item.should eq plaintext_data
- end
+ include_examples "decryption examples"
describe "and the decryption step returns invalid data" do
it "raises a decryption failure error" do
diff --git a/spec/unit/environment_spec.rb b/spec/unit/environment_spec.rb
index 5a2c400d3c..ffb8fbfeaf 100644
--- a/spec/unit/environment_spec.rb
+++ b/spec/unit/environment_spec.rb
@@ -196,7 +196,7 @@ describe Chef::Environment do
%w{name description cookbook_versions}.each do |t|
it "should include '#{t}'" do
- @json.should =~ /"#{t}":#{Regexp.escape(@environment.send(t.to_sym).to_json)}/
+ @json.should =~ /"#{t}":#{Regexp.escape(Chef::JSONCompat.to_json(@environment.send(t.to_sym)))}/
end
end
@@ -207,6 +207,10 @@ describe Chef::Environment do
it "should include 'chef_type'" do
@json.should =~ /"chef_type":"environment"/
end
+
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:jsonable) { @environment }
+ end
end
describe "from_json" do
@@ -222,7 +226,7 @@ describe Chef::Environment do
"json_class" => "Chef::Environment",
"chef_type" => "environment"
}
- @environment = Chef::JSONCompat.from_json(@data.to_json)
+ @environment = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(@data))
end
it "should return a Chef::Environment" do
diff --git a/spec/unit/exceptions_spec.rb b/spec/unit/exceptions_spec.rb
index 3e7b1ba93f..21b0abb9bf 100644
--- a/spec/unit/exceptions_spec.rb
+++ b/spec/unit/exceptions_spec.rb
@@ -74,5 +74,11 @@ describe Chef::Exceptions do
it "should have an exception class of #{exception} which inherits from #{expected_super_class}" do
lambda{ raise exception }.should raise_error(expected_super_class)
end
+
+ if exception.methods.include?(:to_json)
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:jsonable) { exception }
+ end
+ end
end
end
diff --git a/spec/unit/json_compat_spec.rb b/spec/unit/json_compat_spec.rb
index e355a47faa..65d931df70 100644
--- a/spec/unit/json_compat_spec.rb
+++ b/spec/unit/json_compat_spec.rb
@@ -58,13 +58,17 @@ describe Chef::JSONCompat do
describe "when pretty printing an object that defines #to_json" do
class Foo
def to_json(*a)
- {'foo' => 1234}.to_json(*a)
+ Chef::JSONCompat.to_json({'foo' => 1234, 'bar' => {'baz' => 5678}}, *a)
end
end
it "should work" do
f = Foo.new
- expect(Chef::JSONCompat.to_json_pretty(f)).to eql("{\n \"foo\": 1234\n}\n")
+ expect(Chef::JSONCompat.to_json_pretty(f)).to eql("{\n \"foo\": 1234,\n \"bar\": {\n \"baz\": 5678\n }\n}\n")
+ end
+
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:jsonable) { Foo.new }
end
end
@@ -97,4 +101,10 @@ describe Chef::JSONCompat do
end
end
end
+
+ it "should define .to_json on all classes" do
+ class SomeClass; end
+
+ expect(SomeClass.new.respond_to?(:to_json)).to eq(true)
+ end
end
diff --git a/spec/unit/knife/cookbook_site_share_spec.rb b/spec/unit/knife/cookbook_site_share_spec.rb
index 902e5f6115..b85db98d53 100644
--- a/spec/unit/knife/cookbook_site_share_spec.rb
+++ b/spec/unit/knife/cookbook_site_share_spec.rb
@@ -25,6 +25,8 @@ describe Chef::Knife::CookbookSiteShare do
before(:each) do
@knife = Chef::Knife::CookbookSiteShare.new
+ # Merge default settings in.
+ @knife.merge_configs
@knife.name_args = ['cookbook_name', 'AwesomeSausage']
@cookbook = Chef::CookbookVersion.new('cookbook_name')
@@ -34,6 +36,9 @@ describe Chef::Knife::CookbookSiteShare do
@cookbook_loader.stub(:[]).and_return(@cookbook)
Chef::CookbookLoader.stub(:new).and_return(@cookbook_loader)
+ @noauth_rest = double(Chef::REST)
+ @knife.stub(:noauth_rest).and_return(@noauth_rest)
+
@cookbook_uploader = Chef::CookbookUploader.new('herpderp', :rest => "norest")
Chef::CookbookUploader.stub(:new).and_return(@cookbook_uploader)
@cookbook_uploader.stub(:validate_cookbooks).and_return(true)
@@ -48,6 +53,20 @@ describe Chef::Knife::CookbookSiteShare do
before(:each) do
@knife.stub(:do_upload).and_return(true)
+ @category_response = {
+ "name" => "cookbook_name",
+ "category" => "Testing Category"
+ }
+ @bad_category_response = {
+ "error_code" => "NOT_FOUND",
+ "error_messages" => [
+ "Resource does not exist."
+ ]
+ }
+ end
+
+ it 'should set true to config[:dry_run] as default' do
+ @knife.config[:dry_run].should be_false
end
it 'should should print usage and exit when given no arguments' do
@@ -57,9 +76,23 @@ describe Chef::Knife::CookbookSiteShare do
lambda { @knife.run }.should raise_error(SystemExit)
end
- it 'should print usage and exit when given only 1 argument' do
+ it 'should not fail when given only 1 argument and can determine category' do
@knife.name_args = ['cookbook_name']
- @knife.should_receive(:show_usage)
+ @noauth_rest.should_receive(:get_rest).with("http://cookbooks.opscode.com/api/v1/cookbooks/cookbook_name").and_return(@category_response)
+ @knife.should_receive(:do_upload)
+ @knife.run
+ end
+
+ it 'should print error and exit when given only 1 argument and cannot determine category' do
+ @knife.name_args = ['cookbook_name']
+ @noauth_rest.should_receive(:get_rest).with("http://cookbooks.opscode.com/api/v1/cookbooks/cookbook_name").and_return(@bad_category_response)
+ @knife.ui.should_receive(:fatal)
+ lambda { @knife.run }.should raise_error(SystemExit)
+ end
+
+ it 'should print error and exit when given only 1 argument and Chef::REST throws an exception' do
+ @knife.name_args = ['cookbook_name']
+ @noauth_rest.should_receive(:get_rest).with("http://cookbooks.opscode.com/api/v1/cookbooks/cookbook_name") { raise Errno::ECONNREFUSED, "Connection refused" }
@knife.ui.should_receive(:fatal)
lambda { @knife.run }.should raise_error(SystemExit)
end
@@ -93,6 +126,26 @@ describe Chef::Knife::CookbookSiteShare do
FileUtils.should_receive(:rm_rf)
@knife.run
end
+
+ context "when the --dry-run flag is specified" do
+ before do
+ Chef::CookbookSiteStreamingUploader.stub(:create_build_dir).and_return("/var/tmp/dummy")
+ @knife.config = { :dry_run => true }
+ @knife.stub_chain(:shell_out!, :stdout).and_return('file')
+ end
+
+ it "should list files in the tarball" do
+ expect(@knife).to receive(:shell_out!).with("tar -czf #{@cookbook.name}.tgz #{@cookbook.name}", {:cwd => "/var/tmp/dummy"})
+ expect(@knife).to receive(:shell_out!).with("tar -tzf #{@cookbook.name}.tgz", {:cwd => "/var/tmp/dummy"})
+ @knife.run
+ end
+
+ it "does not upload the cookbook" do
+ allow(@knife).to receive(:shell_out!).and_return(true)
+ expect(@knife).not_to receive(:do_upload)
+ @knife.run
+ end
+ end
end
describe 'do_upload' do
@@ -109,7 +162,7 @@ describe Chef::Knife::CookbookSiteShare do
end
it 'should post the cookbook to "https://supermarket.getchef.com"' do
- response_text = {:uri => 'https://supermarket.getchef.com/cookbooks/cookbook_name'}.to_json
+ response_text = Chef::JSONCompat.to_json({:uri => 'https://supermarket.getchef.com/cookbooks/cookbook_name'})
@upload_response.stub(:body).and_return(response_text)
@upload_response.stub(:code).and_return(201)
Chef::CookbookSiteStreamingUploader.should_receive(:post).with(/supermarket\.getchef\.com/, anything(), anything(), anything())
@@ -117,7 +170,7 @@ describe Chef::Knife::CookbookSiteShare do
end
it 'should alert the user when a version already exists' do
- response_text = {:error_messages => ['Version already exists']}.to_json
+ response_text = Chef::JSONCompat.to_json({:error_messages => ['Version already exists']})
@upload_response.stub(:body).and_return(response_text)
@upload_response.stub(:code).and_return(409)
lambda { @knife.run }.should raise_error(SystemExit)
@@ -125,7 +178,7 @@ describe Chef::Knife::CookbookSiteShare do
end
it 'should pass any errors on to the user' do
- response_text = {:error_messages => ["You're holding it wrong"]}.to_json
+ response_text = Chef::JSONCompat.to_json({:error_messages => ["You're holding it wrong"]})
@upload_response.stub(:body).and_return(response_text)
@upload_response.stub(:code).and_return(403)
lambda { @knife.run }.should raise_error(SystemExit)
@@ -133,7 +186,7 @@ describe Chef::Knife::CookbookSiteShare do
end
it 'should print the body if no errors are exposed on failure' do
- response_text = {:system_error => "Your call was dropped", :reason => "There's a map for that"}.to_json
+ response_text = Chef::JSONCompat.to_json({:system_error => "Your call was dropped", :reason => "There's a map for that"})
@upload_response.stub(:body).and_return(response_text)
@upload_response.stub(:code).and_return(500)
@knife.ui.should_receive(:error).with(/#{Regexp.escape(response_text)}/)#.ordered
diff --git a/spec/unit/knife/core/bootstrap_context_spec.rb b/spec/unit/knife/core/bootstrap_context_spec.rb
index 266991a7dd..cd53088419 100644
--- a/spec/unit/knife/core/bootstrap_context_spec.rb
+++ b/spec/unit/knife/core/bootstrap_context_spec.rb
@@ -95,13 +95,13 @@ EXPECTED
describe "when JSON attributes are given" do
let(:config) { {:first_boot_attributes => {:baz => :quux}} }
it "adds the attributes to first_boot" do
- bootstrap_context.first_boot.to_json.should eq({:baz => :quux, :run_list => run_list}.to_json)
+ Chef::JSONCompat.to_json(bootstrap_context.first_boot).should eq(Chef::JSONCompat.to_json({:baz => :quux, :run_list => run_list}))
end
end
describe "when JSON attributes are NOT given" do
it "sets first_boot equal to run_list" do
- bootstrap_context.first_boot.to_json.should eq({:run_list => run_list}.to_json)
+ Chef::JSONCompat.to_json(bootstrap_context.first_boot).should eq(Chef::JSONCompat.to_json({:run_list => run_list}))
end
end
diff --git a/spec/unit/knife/core/ui_spec.rb b/spec/unit/knife/core/ui_spec.rb
index 9044bc2f2f..ed1037ebd5 100644
--- a/spec/unit/knife/core/ui_spec.rb
+++ b/spec/unit/knife/core/ui_spec.rb
@@ -403,6 +403,34 @@ EOM
@ui.format_cookbook_list_for_display(@item).should == response
end
end
+
+ context "when running on Windows" do
+ before(:each) do
+ stdout = double('StringIO', :tty? => true)
+ @ui.stub(:stdout).and_return(stdout)
+ Chef::Platform.stub(:windows?) { true }
+ Chef::Config.reset
+ end
+
+ after(:each) do
+ Chef::Config.reset
+ end
+
+ it "should have color set to true if knife config has color explicitly set to true" do
+ Chef::Config[:color] = true
+ @ui.config[:color] = true
+ expect(@ui.color?).to eql(true)
+ end
+
+ it "should have color set to false if knife config has color explicitly set to false" do
+ Chef::Config[:color] = false
+ expect(@ui.color?).to eql(false)
+ end
+
+ it "should not have color set to false by default" do
+ expect(@ui.color?).to eql(false)
+ end
+ end
end
describe "confirm" do
diff --git a/spec/unit/knife/data_bag_from_file_spec.rb b/spec/unit/knife/data_bag_from_file_spec.rb
index dba5cc282b..8de046e7a4 100644
--- a/spec/unit/knife/data_bag_from_file_spec.rb
+++ b/spec/unit/knife/data_bag_from_file_spec.rb
@@ -29,7 +29,7 @@ describe Chef::Knife::DataBagFromFile do
Chef::Platform.stub(:windows?) { false }
Chef::Config[:node_name] = "webmonkey.example.com"
FileUtils.mkdir_p([db_folder, db_folder2])
- db_file.write(plain_data.to_json)
+ db_file.write(Chef::JSONCompat.to_json(plain_data))
db_file.flush
allow(knife).to receive(:config).and_return(config)
allow(Chef::Knife::Core::ObjectLoader).to receive(:new).and_return(loader)
diff --git a/spec/unit/knife/status_spec.rb b/spec/unit/knife/status_spec.rb
index 6d8d9d5b25..bb43dd25e5 100644
--- a/spec/unit/knife/status_spec.rb
+++ b/spec/unit/knife/status_spec.rb
@@ -17,7 +17,6 @@
#
require 'spec_helper'
-require 'highline'
describe Chef::Knife::Status do
before(:each) do
@@ -30,7 +29,7 @@ describe Chef::Knife::Status do
Chef::Search::Query.stub(:new).and_return(query)
@knife = Chef::Knife::Status.new
@stdout = StringIO.new
- @knife.stub(:highline).and_return(HighLine.new(StringIO.new, @stdout))
+ @knife.ui.stub(:stdout).and_return(@stdout)
end
describe "run" do
diff --git a/spec/unit/knife_spec.rb b/spec/unit/knife_spec.rb
index 2db6b40b28..6d4763e087 100644
--- a/spec/unit/knife_spec.rb
+++ b/spec/unit/knife_spec.rb
@@ -260,8 +260,25 @@ describe Chef::Knife do
knife_command.configure_chef
knife_command.config[:opt_with_default].should == "from-cli"
end
- end
+ context "verbosity is greater than zero" do
+ let(:fake_config) { "/does/not/exist/knife.rb" }
+
+ before do
+ @knife.config[:verbosity] = 1
+ @knife.config[:config_file] = fake_config
+ config_loader = double("Chef::WorkstationConfigLoader", :load => true, :no_config_found? => false, :chef_config_dir => "/etc/chef", :config_location => fake_config)
+ allow(Chef::WorkstationConfigLoader).to receive(:new).and_return(config_loader)
+ end
+
+ it "prints the path to the configuration file used" do
+ @stdout, @stderr, @stdin = StringIO.new, StringIO.new, StringIO.new
+ @knife.ui = Chef::Knife::UI.new(@stdout, @stderr, @stdin, {})
+ expect(Chef::Log).to receive(:info).with("Using configuration from #{fake_config}")
+ @knife.configure_chef
+ end
+ end
+ end
end
describe "when first created" do
diff --git a/spec/unit/lwrp_spec.rb b/spec/unit/lwrp_spec.rb
index 960aff3c36..452e1da2a4 100644
--- a/spec/unit/lwrp_spec.rb
+++ b/spec/unit/lwrp_spec.rb
@@ -42,7 +42,8 @@ describe "LWRP" do
end
Dir[File.expand_path( "lwrp/resources/*", CHEF_SPEC_DATA)].each do |file|
- Chef::Log.should_receive(:info).with(/overriding/)
+ Chef::Log.should_receive(:info).with(/Skipping/)
+ Chef::Log.should_receive(:debug).with(/anymore/)
Chef::Resource::LWRPBase.build_from_file("lwrp", file, nil)
end
end
@@ -53,16 +54,15 @@ describe "LWRP" do
end
Dir[File.expand_path( "lwrp/providers/*", CHEF_SPEC_DATA)].each do |file|
- Chef::Log.should_receive(:info).with(/overriding/)
+ Chef::Log.should_receive(:info).with(/Skipping/)
+ Chef::Log.should_receive(:debug).with(/anymore/)
Chef::Provider::LWRPBase.build_from_file("lwrp", file, nil)
end
end
- it "removes the old LRWP resource class from the list of resource subclasses [CHEF-3432]" do
- # CHEF-3432 regression test:
- # Chef::Resource keeps a list of all subclasses to assist class inflation
- # for json parsing (see Chef::JSONCompat). When replacing LWRP resources,
- # we need to ensure the old resource class is remove from that list.
+ it "keeps the old LRWP resource class in the list of resource subclasses" do
+ # This was originally CHEF-3432 regression test. But with Chef 12 we are
+ # not replacing the original classes anymore.
Dir[File.expand_path( "lwrp/resources/*", CHEF_SPEC_DATA)].each do |file|
Chef::Resource::LWRPBase.build_from_file("lwrp", file, nil)
end
@@ -71,7 +71,7 @@ describe "LWRP" do
Dir[File.expand_path( "lwrp/resources/*", CHEF_SPEC_DATA)].each do |file|
Chef::Resource::LWRPBase.build_from_file("lwrp", file, nil)
end
- Chef::Resource.resource_classes.should_not include(first_lwr_foo_class)
+ Chef::Resource.resource_classes.should include(first_lwr_foo_class)
end
it "does not attempt to remove classes from higher up namespaces [CHEF-4117]" do
@@ -231,6 +231,27 @@ describe "LWRP" do
expect(child.default_action).to eq(:dont_eat)
end
end
+
+ context "when actions are already defined" do
+ let(:child) do
+ Class.new(parent) do
+ actions :eat
+ actions :sleep
+ actions :drink
+ end
+ end
+
+ def raise_if_deprecated!
+ if Chef::VERSION.split('.').first.to_i > 12
+ raise "This test should be removed and the associated code should be removed!"
+ end
+ end
+
+ it "ammends actions when they are already defined" do
+ raise_if_deprecated!
+ expect(child.actions).to eq([:eat, :sleep, :drink])
+ end
+ end
end
end
diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb
index 21a978a9c9..00879dcb13 100644
--- a/spec/unit/node_spec.rb
+++ b/spec/unit/node_spec.rb
@@ -762,6 +762,13 @@ describe Chef::Node do
end
serialized_node.run_list.should == node.run_list
end
+
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:jsonable) {
+ node.from_file(File.expand_path("nodes/test.example.com.rb", CHEF_SPEC_DATA))
+ node
+ }
+ end
end
describe "to_s" do
diff --git a/spec/unit/platform_spec.rb b/spec/unit/platform_spec.rb
index e8c41cdd77..9a65cbe878 100644
--- a/spec/unit/platform_spec.rb
+++ b/spec/unit/platform_spec.rb
@@ -278,6 +278,18 @@ describe Chef::Platform do
pmap[:package].should eql(Chef::Provider::Package::Ips)
end
+ it "should use the Redhat service provider on SLES11" do
+ 1.upto(3) do |sp|
+ pmap = Chef::Platform.find("SUSE", "11.#{sp}")
+ pmap[:service].should eql(Chef::Provider::Service::Redhat)
+ end
+ end
+
+ it "should use the Systemd service provider on SLES12" do
+ pmap = Chef::Platform.find("SUSE", "12.0")
+ pmap[:service].should eql(Chef::Provider::Service::Systemd)
+ end
+
it "should use the SUSE group provider on SLES11" do
1.upto(3) do |sp|
pmap = Chef::Platform.find("SUSE", "11.#{sp}")
diff --git a/spec/unit/provider/cron/unix_spec.rb b/spec/unit/provider/cron/unix_spec.rb
index 60e09baceb..3d7a5675fc 100644
--- a/spec/unit/provider/cron/unix_spec.rb
+++ b/spec/unit/provider/cron/unix_spec.rb
@@ -21,26 +21,34 @@
require 'spec_helper'
describe Chef::Provider::Cron::Unix do
- before do
- @node = Chef::Node.new
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, {}, @events)
- @new_resource = Chef::Resource::Cron.new("cronhole some stuff")
- @new_resource.user "root"
- @new_resource.minute "30"
- @new_resource.command "/bin/true"
-
- @provider = Chef::Provider::Cron::Unix.new(@new_resource, @run_context)
+
+ subject(:provider) { Chef::Provider::Cron::Unix.new(new_resource, run_context) }
+
+ let(:username) { "root" }
+
+ let(:node) { Chef::Node.new }
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
+ let(:new_resource) do
+ Chef::Resource::Cron.new("cronhole some stuff").tap do |resource|
+ resource.user username
+ resource.minute "30"
+ resource.command "/bin/true"
+ end
end
- it "should inherit from Chef::Provider:Cron" do
- @provider.should be_a(Chef::Provider::Cron)
+ let(:status) { double('Process::Status', :exitstatus => exitstatus) }
+ let(:exitstatus) { 0 }
+ let(:shell_out) { double('Mixlib::ShellOut', :status => status, :stdout => stdout, :stderr => stderr) }
+
+ it "is a Chef::Provider:Cron" do
+ expect(provider).to be_a(Chef::Provider::Cron)
end
describe "read_crontab" do
- before :each do
- @status = double("Status", :exitstatus => 0)
- @stdout = StringIO.new(<<-CRONTAB)
+ let(:stderr) { "" }
+ let(:stdout) do
+ String.new(<<-CRONTAB)
0 2 * * * /some/other/command
# Chef Name: something else
@@ -48,74 +56,84 @@ describe Chef::Provider::Cron::Unix do
# Another comment
CRONTAB
- @provider.stub(:popen4).and_yield(1234, StringIO.new, @stdout, StringIO.new).and_return(@status)
+ end
+
+ before do
+ allow(Chef::Log).to receive(:debug)
+ allow(shell_out).to receive(:format_for_exception).and_return("formatted command output")
+ allow(provider).to receive(:shell_out).with('/usr/bin/crontab -l', :user => username).and_return(shell_out)
end
it "should call crontab -l with the user" do
- @provider.should_receive(:popen4).with("crontab -l #{@new_resource.user}").and_return(@status)
- @provider.send(:read_crontab)
+ provider.send(:read_crontab)
+ expect(provider).to have_received(:shell_out).with('/usr/bin/crontab -l', :user => username)
end
it "should return the contents of the crontab" do
- crontab = @provider.send(:read_crontab)
- crontab.should == <<-CRONTAB
-0 2 * * * /some/other/command
+ crontab = provider.send(:read_crontab)
+ expect(crontab).to eq(stdout)
+ end
-# Chef Name: something else
-* 5 * * * /bin/true
+ context "when the user has no crontab" do
+ let(:exitstatus) { 1 }
-# Another comment
-CRONTAB
- end
+ it "should return nil if the user has no crontab" do
+ expect(provider.send(:read_crontab)).to be_nil
+ end
- it "should return nil if the user has no crontab" do
- status = double("Status", :exitstatus => 1)
- @provider.stub(:popen4).and_return(status)
- @provider.send(:read_crontab).should == nil
+ it "logs the crontab output to debug" do
+ provider.send(:read_crontab)
+ expect(Chef::Log).to have_received(:debug).with("formatted command output")
+ end
end
- it "should raise an exception if another error occurs" do
- status = double("Status", :exitstatus => 2)
- @provider.stub(:popen4).and_return(status)
- lambda do
- @provider.send(:read_crontab)
- end.should raise_error(Chef::Exceptions::Cron, "Error determining state of #{@new_resource.name}, exit: 2")
+ context "when any other error occurs" do
+ let (:exitstatus) { 2 }
+
+ it "should raise an exception if another error occurs" do
+ expect {
+ provider.send(:read_crontab)
+ }.to raise_error(Chef::Exceptions::Cron, "Error determining state of #{new_resource.name}, exit: 2")
+ end
+
+ it "logs the crontab output to debug" do
+ provider.send(:read_crontab) rescue nil
+ expect(Chef::Log).to have_received(:debug).with("formatted command output")
+ end
end
end
describe "write_crontab" do
- before :each do
- @status = double("Status", :exitstatus => 0)
- @provider.stub(:run_command_and_return_stdout_stderr).and_return(@status, String.new, String.new)
- @tempfile = double("foo", :path => "/tmp/foo", :close => true)
- Tempfile.stub(:new).and_return(@tempfile)
- @tempfile.should_receive(:flush)
- @tempfile.should_receive(:chmod).with(420)
- @tempfile.should_receive(:close!)
+ let(:stdout) { "" }
+ let(:stderr) { "" }
+ let(:tempfile) { double("foo", :path => "/tmp/foo", :close => true) }
+
+ before do
+ expect(Tempfile).to receive(:new).and_return(tempfile)
+ expect(tempfile).to receive(:flush)
+ expect(tempfile).to receive(:chmod).with(420)
+ expect(tempfile).to receive(:close!)
+ allow(tempfile).to receive(:<<)
+ allow(provider).to receive(:shell_out).with("/usr/bin/crontab #{tempfile.path}", :user => username).and_return(shell_out)
end
it "should call crontab for the user" do
- @provider.should_receive(:run_command_and_return_stdout_stderr).with(hash_including(:user => @new_resource.user))
- @tempfile.should_receive(:<<).with("Foo")
- @provider.send(:write_crontab, "Foo")
+ provider.send(:write_crontab, "Foo")
+ expect(provider).to have_received(:shell_out).with("/usr/bin/crontab #{tempfile.path}", :user => username)
end
it "should call crontab with a file containing the crontab" do
- @provider.should_receive(:run_command_and_return_stdout_stderr) do |args|
- (args[:command] =~ %r{\A/usr/bin/crontab (/\S+)\z}).should be_true
- $1.should == "/tmp/foo"
- @status
- end
- @tempfile.should_receive(:<<).with("Foo\n# wibble\n wah!!")
- @provider.send(:write_crontab, "Foo\n# wibble\n wah!!")
+ provider.send(:write_crontab, "Foo\n# wibble\n wah!!")
+ expect(tempfile).to have_received(:<<).with("Foo\n# wibble\n wah!!")
end
- it "should raise an exception if the command returns non-zero" do
- @tempfile.should_receive(:<<).with("Foo")
- @status.stub(:exitstatus).and_return(1)
- lambda do
- @provider.send(:write_crontab, "Foo")
- end.should raise_error(Chef::Exceptions::Cron, /Error updating state of #{@new_resource.name}, exit: 1/)
+ context "when writing the crontab fails" do
+ let(:exitstatus) { 1 }
+ it "should raise an exception if the command returns non-zero" do
+ expect {
+ provider.send(:write_crontab, "Foo")
+ }.to raise_error(Chef::Exceptions::Cron, /Error updating state of #{new_resource.name}, exit: 1/)
+ end
end
end
end
diff --git a/spec/unit/provider/dsc_script_spec.rb b/spec/unit/provider/dsc_script_spec.rb
index 8a7a7b5c6a..d8fbee3ff9 100644
--- a/spec/unit/provider/dsc_script_spec.rb
+++ b/spec/unit/provider/dsc_script_spec.rb
@@ -22,123 +22,152 @@ require 'chef/util/dsc/resource_info'
require 'spec_helper'
describe Chef::Provider::DscScript do
- let (:node) {
- node = Chef::Node.new
- node.automatic[:languages][:powershell][:version] = '4.0'
- node
- }
- let (:events) { Chef::EventDispatch::Dispatcher.new }
- let (:run_context) { Chef::RunContext.new(node, {}, events) }
- let (:resource) { Chef::Resource::DscScript.new("script", run_context) }
- let (:provider) do
- Chef::Provider::DscScript.new(resource, run_context)
- end
-
- describe '#load_current_resource' do
- it "describes the resource as converged if there were 0 DSC resources" do
- allow(provider).to receive(:run_configuration).with(:test).and_return([])
- provider.load_current_resource
- provider.instance_variable_get('@resource_converged').should be_true
+ context 'when DSC is available' do
+ let (:node) {
+ node = Chef::Node.new
+ node.automatic[:languages][:powershell][:version] = '4.0'
+ node
+ }
+ let (:events) { Chef::EventDispatch::Dispatcher.new }
+ let (:run_context) { Chef::RunContext.new(node, {}, events) }
+ let (:resource) { Chef::Resource::DscScript.new("script", run_context) }
+ let (:provider) do
+ Chef::Provider::DscScript.new(resource, run_context)
end
- it "describes the resource as not converged if there is 1 DSC resources that is converged" do
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
- provider.load_current_resource
- provider.instance_variable_get('@resource_converged').should be_true
+ describe '#load_current_resource' do
+ it "describes the resource as converged if there were 0 DSC resources" do
+ allow(provider).to receive(:run_configuration).with(:test).and_return([])
+ provider.load_current_resource
+ provider.instance_variable_get('@resource_converged').should be_true
+ end
+
+ it "describes the resource as not converged if there is 1 DSC resources that is converged" do
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
+ provider.load_current_resource
+ provider.instance_variable_get('@resource_converged').should be_true
+ end
+
+ it "describes the resource as not converged if there is 1 DSC resources that is not converged" do
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
+ provider.load_current_resource
+ provider.instance_variable_get('@resource_converged').should be_false
+ end
+
+ it "describes the resource as not converged if there are any DSC resources that are not converged" do
+ dsc_resource_info1 = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
+ dsc_resource_info2 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
+
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info1, dsc_resource_info2])
+ provider.load_current_resource
+ provider.instance_variable_get('@resource_converged').should be_false
+ end
+
+ it "describes the resource as converged if all DSC resources that are converged" do
+ dsc_resource_info1 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
+ dsc_resource_info2 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
+
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info1, dsc_resource_info2])
+ provider.load_current_resource
+ provider.instance_variable_get('@resource_converged').should be_true
+ end
end
- it "describes the resource as not converged if there is 1 DSC resources that is not converged" do
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
- provider.load_current_resource
- provider.instance_variable_get('@resource_converged').should be_false
+ describe '#generate_configuration_document' do
+ # I think integration tests should cover these cases
+
+ it 'uses configuration_document_from_script_path when a dsc script file is given' do
+ allow(provider).to receive(:load_current_resource)
+ resource.command("path_to_script")
+ generator = double('Chef::Util::DSC::ConfigurationGenerator')
+ generator.should_receive(:configuration_document_from_script_path)
+ allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
+ provider.send(:generate_configuration_document, 'tmp', nil)
+ end
+
+ it 'uses configuration_document_from_script_code when a the dsc resource is given' do
+ allow(provider).to receive(:load_current_resource)
+ resource.code("ImADSCResource{}")
+ generator = double('Chef::Util::DSC::ConfigurationGenerator')
+ generator.should_receive(:configuration_document_from_script_code)
+ allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
+ provider.send(:generate_configuration_document, 'tmp', nil)
+ end
+
+ it 'should noop if neither code or command are provided' do
+ allow(provider).to receive(:load_current_resource)
+ generator = double('Chef::Util::DSC::ConfigurationGenerator')
+ generator.should_receive(:configuration_document_from_script_code).with('', anything(), anything())
+ allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
+ provider.send(:generate_configuration_document, 'tmp', nil)
+ end
end
- it "describes the resource as not converged if there are any DSC resources that are not converged" do
- dsc_resource_info1 = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
- dsc_resource_info2 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
-
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info1, dsc_resource_info2])
- provider.load_current_resource
- provider.instance_variable_get('@resource_converged').should be_false
+ describe 'action_run' do
+ it 'should converge the script if it is not converged' do
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
+ allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
+ allow(provider).to receive(:run_configuration).with(:set)
+
+ provider.run_action(:run)
+ resource.should be_updated
+ end
+
+ it 'should not converge if the script is already converged' do
+ allow(provider).to receive(:run_configuration).with(:test).and_return([])
+
+ provider.run_action(:run)
+ resource.should_not be_updated
+ end
end
- it "describes the resource as converged if all DSC resources that are converged" do
- dsc_resource_info1 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
- dsc_resource_info2 = Chef::Util::DSC::ResourceInfo.new('resource', false, ['nothing will change something'])
-
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info1, dsc_resource_info2])
- provider.load_current_resource
- provider.instance_variable_get('@resource_converged').should be_true
+ describe '#generate_description' do
+ it 'removes the resource name from the beginning of any log line from the LCM' do
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', true, ['resourcename doing something', 'lastline'])
+ provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
+ provider.send(:generate_description)[1].should match(/converge DSC resource resourcename by doing something/)
+ end
+
+ it 'ignores the last line' do
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', true, ['resourcename doing something', 'lastline'])
+ provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
+ provider.send(:generate_description)[1].should_not match(/lastline/)
+ end
+
+ it 'reports a dsc resource has not been changed if the LCM reported no change was required' do
+ dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', false, ['resourcename does nothing', 'lastline'])
+ provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
+ provider.send(:generate_description)[1].should match(/converge DSC resource resourcename by doing nothing/)
+ end
end
end
- describe '#generate_configuration_document' do
- # I think integration tests should cover these cases
-
- it 'uses configuration_document_from_script_path when a dsc script file is given' do
- allow(provider).to receive(:load_current_resource)
- resource.command("path_to_script")
- generator = double('Chef::Util::DSC::ConfigurationGenerator')
- generator.should_receive(:configuration_document_from_script_path)
- allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
- provider.send(:generate_configuration_document, 'tmp', nil)
- end
-
- it 'uses configuration_document_from_script_code when a the dsc resource is given' do
- allow(provider).to receive(:load_current_resource)
- resource.code("ImADSCResource{}")
- generator = double('Chef::Util::DSC::ConfigurationGenerator')
- generator.should_receive(:configuration_document_from_script_code)
- allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
- provider.send(:generate_configuration_document, 'tmp', nil)
- end
-
- it 'should noop if neither code or command are provided' do
- allow(provider).to receive(:load_current_resource)
- generator = double('Chef::Util::DSC::ConfigurationGenerator')
- generator.should_receive(:configuration_document_from_script_code).with('', anything(), anything())
- allow(Chef::Util::DSC::ConfigurationGenerator).to receive(:new).and_return(generator)
- provider.send(:generate_configuration_document, 'tmp', nil)
- end
- end
-
- describe 'action_run' do
- it 'should converge the script if it is not converged' do
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resource', true, ['will change something'])
- allow(provider).to receive(:run_configuration).with(:test).and_return([dsc_resource_info])
- allow(provider).to receive(:run_configuration).with(:set)
-
- provider.run_action(:run)
- resource.should be_updated
- end
-
- it 'should not converge if the script is already converged' do
- allow(provider).to receive(:run_configuration).with(:test).and_return([])
-
- provider.run_action(:run)
- resource.should_not be_updated
- end
- end
-
- describe '#generate_description' do
- it 'removes the resource name from the beginning of any log line from the LCM' do
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', true, ['resourcename doing something', 'lastline'])
- provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
- provider.send(:generate_description)[1].should match(/converge DSC resource resourcename by doing something/)
- end
-
- it 'ignores the last line' do
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', true, ['resourcename doing something', 'lastline'])
- provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
- provider.send(:generate_description)[1].should_not match(/lastline/)
- end
+ context 'when Dsc is not available' do
+ let (:node) { Chef::Node.new }
+ let (:events) { Chef::EventDispatch::Dispatcher.new }
+ let (:run_context) { Chef::RunContext.new(node, {}, events) }
+ let (:resource) { Chef::Resource::DscScript.new('script', run_context) }
+ let (:provider) { Chef::Provider::DscScript.new(resource, run_context) }
+
+ describe 'action_run' do
+ ['1.0', '2.0', '3.0'].each do |version|
+ it "raises an exception for powershell version '#{version}'" do
+ node.automatic[:languages][:powershell][:version] = version
+
+ expect {
+ provider.run_action(:run)
+ }.to raise_error(Chef::Exceptions::NoProviderAvailable)
+ end
+ end
+
+ it 'raises an exception if Powershell is not present' do
+ expect {
+ provider.run_action(:run)
+ }.to raise_error(Chef::Exceptions::NoProviderAvailable)
+ end
- it 'reports a dsc resource has not been changed if the LCM reported no change was required' do
- dsc_resource_info = Chef::Util::DSC::ResourceInfo.new('resourcename', false, ['resourcename does nothing', 'lastline'])
- provider.instance_variable_set('@dsc_resources_info', [dsc_resource_info])
- provider.send(:generate_description)[1].should match(/converge DSC resource resourcename by doing nothing/)
end
end
end
diff --git a/spec/unit/provider/execute_spec.rb b/spec/unit/provider/execute_spec.rb
index 78216a89fa..6aa48f1e2a 100644
--- a/spec/unit/provider/execute_spec.rb
+++ b/spec/unit/provider/execute_spec.rb
@@ -36,22 +36,38 @@ describe Chef::Provider::Execute do
STDOUT.stub(:tty?).and_return(true)
end
+ let(:opts) do
+ {
+ timeout: @new_resource.timeout,
+ returns: @new_resource.returns,
+ log_level: :info,
+ log_tag: @new_resource.to_s,
+ live_stream: STDOUT
+ }
+ end
it "should execute foo_resource" do
@provider.stub(:load_current_resource)
- opts = {}
- opts[:timeout] = @new_resource.timeout
- opts[:returns] = @new_resource.returns
- opts[:log_level] = :info
- opts[:log_tag] = @new_resource.to_s
- opts[:live_stream] = STDOUT
@provider.should_receive(:shell_out!).with(@new_resource.command, opts)
+ @provider.should_receive(:converge_by).with("execute foo_resource").and_call_original
Chef::Log.should_not_receive(:warn)
@provider.run_action(:run)
@new_resource.should be_updated
end
+ it "should honor sensitive attribute" do
+ @new_resource.sensitive true
+ @provider = Chef::Provider::Execute.new(@new_resource, @run_context)
+ @provider.stub(:load_current_resource)
+ # Since the resource is sensitive, it should not have :live_stream set
+ @provider.should_receive(:shell_out!).with(@new_resource.command, opts.reject { |k| k == :live_stream })
+ Chef::Log.should_not_receive(:warn)
+ @provider.should_receive(:converge_by).with("execute sensitive resource").and_call_original
+ @provider.run_action(:run)
+ @new_resource.should be_updated
+ end
+
it "should do nothing if the sentinel file exists" do
@provider.stub(:load_current_resource)
File.should_receive(:exists?).with(@new_resource.creates).and_return(true)
diff --git a/spec/unit/provider/git_spec.rb b/spec/unit/provider/git_spec.rb
index ff1c0b0398..02d155efbd 100644
--- a/spec/unit/provider/git_spec.rb
+++ b/spec/unit/provider/git_spec.rb
@@ -106,6 +106,52 @@ describe Chef::Provider::Git do
@provider.target_revision.should eql("663c22a5e41f5ae3193460cca044ed1435029f53")
end
+ it "converts resource.revision from a tag to a SHA using an exact match" do
+ @resource.revision "v1.0"
+ @stdout = ("d03c22a5e41f5ae3193460cca044ed1435029f53\trefs/heads/0.8-alpha\n" +
+ "663c22a5e41f5ae3193460cca044ed1435029f53\trefs/tags/releases/v1.0\n" +
+ "503c22a5e41f5ae3193460cca044ed1435029f53\trefs/tags/v1.0\n")
+ @provider.should_receive(:shell_out!).with(@git_ls_remote + "\"v1.0*\"", {:log_tag=>"git[web2.0 app]"}).and_return(double("ShellOut result", :stdout => @stdout))
+ @provider.target_revision.should eql("503c22a5e41f5ae3193460cca044ed1435029f53")
+ end
+
+ it "converts resource.revision from a tag to a SHA, matching tags first, then heads" do
+ @resource.revision "v1.0"
+ @stdout = ("d03c22a5e41f5ae3193460cca044ed1435029f53\trefs/heads/0.8-alpha\n" +
+ "663c22a5e41f5ae3193460cca044ed1435029f53\trefs/tags/v1.0\n" +
+ "503c22a5e41f5ae3193460cca044ed1435029f53\trefs/heads/v1.0\n")
+ @provider.should_receive(:shell_out!).with(@git_ls_remote + "\"v1.0*\"", {:log_tag=>"git[web2.0 app]"}).and_return(double("ShellOut result", :stdout => @stdout))
+ @provider.target_revision.should eql("663c22a5e41f5ae3193460cca044ed1435029f53")
+ end
+
+ it "converts resource.revision from a tag to a SHA, matching heads if no tags match" do
+ @resource.revision "v1.0"
+ @stdout = ("d03c22a5e41f5ae3193460cca044ed1435029f53\trefs/heads/0.8-alpha\n" +
+ "663c22a5e41f5ae3193460cca044ed1435029f53\trefs/tags/v1.1\n" +
+ "503c22a5e41f5ae3193460cca044ed1435029f53\trefs/heads/v1.0\n")
+ @provider.should_receive(:shell_out!).with(@git_ls_remote + "\"v1.0*\"", {:log_tag=>"git[web2.0 app]"}).and_return(double("ShellOut result", :stdout => @stdout))
+ @provider.target_revision.should eql("503c22a5e41f5ae3193460cca044ed1435029f53")
+ end
+
+ it "converts resource.revision from a tag to a SHA, matching tags first, then heads, then revision" do
+ @resource.revision "refs/pulls/v1.0"
+ @stdout = ("d03c22a5e41f5ae3193460cca044ed1435029f53\trefs/heads/0.8-alpha\n" +
+ "663c22a5e41f5ae3193460cca044ed1435029f53\trefs/tags/v1.0\n" +
+ "805c22a5e41f5ae3193460cca044ed1435029f53\trefs/pulls/v1.0\n" +
+ "503c22a5e41f5ae3193460cca044ed1435029f53\trefs/heads/v1.0\n")
+ @provider.should_receive(:shell_out!).with(@git_ls_remote + "\"refs/pulls/v1.0*\"", {:log_tag=>"git[web2.0 app]"}).and_return(double("ShellOut result", :stdout => @stdout))
+ @provider.target_revision.should eql("805c22a5e41f5ae3193460cca044ed1435029f53")
+ end
+
+ it "converts resource.revision from a tag to a SHA, using full path if provided" do
+ @resource.revision "refs/heads/v1.0"
+ @stdout = ("d03c22a5e41f5ae3193460cca044ed1435029f53\trefs/heads/0.8-alpha\n" +
+ "663c22a5e41f5ae3193460cca044ed1435029f53\trefs/tags/v1.0\n" +
+ "503c22a5e41f5ae3193460cca044ed1435029f53\trefs/heads/v1.0\n")
+ @provider.should_receive(:shell_out!).with(@git_ls_remote + "\"refs/heads/v1.0*\"", {:log_tag=>"git[web2.0 app]"}).and_return(double("ShellOut result", :stdout => @stdout))
+ @provider.target_revision.should eql("503c22a5e41f5ae3193460cca044ed1435029f53")
+ end
+
it "raises an invalid remote reference error if you try to deploy from ``origin'' and assertions are run" do
@resource.revision "origin/"
@provider.action = :checkout
diff --git a/spec/unit/provider/package/freebsd/pkgng_spec.rb b/spec/unit/provider/package/freebsd/pkgng_spec.rb
index 001c9e23ba..c3837a251b 100644
--- a/spec/unit/provider/package/freebsd/pkgng_spec.rb
+++ b/spec/unit/provider/package/freebsd/pkgng_spec.rb
@@ -67,7 +67,7 @@ describe Chef::Provider::Package::Freebsd::Port do
describe "determining current installed version" do
before(:each) do
@provider.stub(:supports_pkgng?)
- @pkg_info = OpenStruct.new(:stdout => "zsh-3.1.7\n")
+ @pkg_info = OpenStruct.new(:stdout => "zsh-3.1.7\nVersion : 3.1.7\n")
end
it "should query pkg database" do
diff --git a/spec/unit/provider/package/freebsd/port_spec.rb b/spec/unit/provider/package/freebsd/port_spec.rb
index e946719451..8725e5440f 100644
--- a/spec/unit/provider/package/freebsd/port_spec.rb
+++ b/spec/unit/provider/package/freebsd/port_spec.rb
@@ -26,7 +26,7 @@ describe Chef::Provider::Package::Freebsd::Port do
@events = Chef::EventDispatch::Dispatcher.new
@run_context = Chef::RunContext.new(@node, {}, @events)
- @new_resource = Chef::Resource::Package.new("zsh")
+ @new_resource = Chef::Resource::FreebsdPackage.new("zsh", @run_context)
@provider = Chef::Provider::Package::Freebsd::Port.new(@new_resource, @run_context)
end
@@ -66,24 +66,34 @@ describe Chef::Provider::Package::Freebsd::Port do
describe "determining current installed version" do
before(:each) do
- @provider.stub(:supports_pkgng?)
@pkg_info = OpenStruct.new(:stdout => "zsh-3.1.7\n")
end
it "should check 'pkg_info' if system uses pkg_* tools" do
- @provider.should_receive(:supports_pkgng?).and_return(false)
+ @new_resource.stub(:supports_pkgng?)
+ @new_resource.should_receive(:supports_pkgng?).and_return(false)
@provider.should_receive(:shell_out!).with('pkg_info -E "zsh*"', :env => nil, :returns => [0,1]).and_return(@pkg_info)
@provider.current_installed_version.should == "3.1.7"
end
- it "should check 'pkg info' if system uses pkgng" do
- @provider.should_receive(:supports_pkgng?).and_return(true)
+ it "should check 'pkg info' if make supports WITH_PKGNG if freebsd version is < 1000017" do
+ pkg_enabled = OpenStruct.new(:stdout => "yes\n")
+ [1000016, 1000000, 901503, 902506, 802511].each do |__freebsd_version|
+ @node.automatic_attrs[:os_version] = __freebsd_version
+ @new_resource.should_receive(:shell_out!).with('make -V WITH_PKGNG', :env => nil).and_return(pkg_enabled)
+ @provider.should_receive(:shell_out!).with('pkg info "zsh"', :env => nil, :returns => [0,70]).and_return(@pkg_info)
+ @provider.current_installed_version.should == "3.1.7"
+ end
+ end
+
+ it "should check 'pkg info' if the freebsd version is greater than or equal to 1000017" do
+ __freebsd_version = 1000017
+ @node.automatic_attrs[:os_version] = __freebsd_version
@provider.should_receive(:shell_out!).with('pkg info "zsh"', :env => nil, :returns => [0,70]).and_return(@pkg_info)
@provider.current_installed_version.should == "3.1.7"
end
end
-
describe "determining candidate version" do
before(:each) do
@port_version = OpenStruct.new(:stdout => "5.0.5\n", :exitstatus => 0)
diff --git a/spec/unit/provider/package/pacman_spec.rb b/spec/unit/provider/package/pacman_spec.rb
index 0c1c487980..ed10513350 100644
--- a/spec/unit/provider/package/pacman_spec.rb
+++ b/spec/unit/provider/package/pacman_spec.rb
@@ -94,10 +94,7 @@ PACMAN
end
it "should set the candidate version if pacman has one" do
- @stdout.stub(:each).and_yield("core/nano 2.2.3-1 (base)").
- and_yield(" Pico editor clone with enhancements").
- and_yield("community/nanoblogger 3.4.1-1").
- and_yield(" NanoBlogger is a small weblog engine written in Bash for the command line")
+ @stdout.stub(:each).and_yield("core nano 2.2.3-1")
@provider.stub(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
@provider.load_current_resource
@provider.candidate_version.should eql("2.2.3-1")
@@ -124,8 +121,7 @@ PACMAN_CONF
::File.stub(:exists?).with("/etc/pacman.conf").and_return(true)
::File.stub(:read).with("/etc/pacman.conf").and_return(@pacman_conf)
- @stdout.stub(:each).and_yield("customrepo/nano 1.2.3-4").
- and_yield(" My custom package")
+ @stdout.stub(:each).and_yield("customrepo nano 1.2.3-4")
@provider.stub(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
@provider.load_current_resource
diff --git a/spec/unit/provider/package/paludis_spec.rb b/spec/unit/provider/package/paludis_spec.rb
index c99600e535..8387bb1252 100644
--- a/spec/unit/provider/package/paludis_spec.rb
+++ b/spec/unit/provider/package/paludis_spec.rb
@@ -59,7 +59,7 @@ PKG_STATUS
end
it "should run pkg info with the package name" do
- @provider.should_receive(:shell_out!).with("cave -L warning print-ids -M none -m \"*/#{@new_resource.package_name.split('/').last}\" -f \"%c/%p %v %r\n\"").and_return(@shell_out)
+ @provider.should_receive(:shell_out!).with("cave -L warning print-ids -M none -m \"#{@new_resource.package_name}\" -f \"%c/%p %v %r\n\"").and_return(@shell_out)
@provider.load_current_resource
end
diff --git a/spec/unit/provider/package/rubygems_spec.rb b/spec/unit/provider/package/rubygems_spec.rb
index d3cb9cf7fa..f4d0cebf62 100644
--- a/spec/unit/provider/package/rubygems_spec.rb
+++ b/spec/unit/provider/package/rubygems_spec.rb
@@ -359,10 +359,12 @@ RBX_GEM_ENV
end
describe Chef::Provider::Package::Rubygems do
+ let(:target_version) { nil }
+
before(:each) do
@node = Chef::Node.new
@new_resource = Chef::Resource::GemPackage.new("rspec-core")
- @spec_version = @new_resource.version RSpec::Core::Version::STRING
+ @spec_version = @new_resource.version(target_version)
@events = Chef::EventDispatch::Dispatcher.new
@run_context = Chef::RunContext.new(@node, {}, @events)
@@ -371,269 +373,281 @@ describe Chef::Provider::Package::Rubygems do
@provider = Chef::Provider::Package::Rubygems.new(@new_resource, @run_context)
end
- it "triggers a gem configuration load so a later one will not stomp its config values" do
- # ugly, is there a better way?
- Gem.instance_variable_get(:@configuration).should_not be_nil
- end
+ describe "when new_resource version is nil" do
+ let(:target_version) { nil }
- it "uses the CurrentGemEnvironment implementation when no gem_binary_path is provided" do
- @provider.gem_env.should be_a_kind_of(Chef::Provider::Package::Rubygems::CurrentGemEnvironment)
+ it "target_version_already_installed? should return false so that we can search for candidates" do
+ @provider.load_current_resource
+ @provider.target_version_already_installed?.should be_false
+ end
end
- it "uses the AlternateGemEnvironment implementation when a gem_binary_path is provided" do
- @new_resource.gem_binary('/usr/weird/bin/gem')
- provider = Chef::Provider::Package::Rubygems.new(@new_resource, @run_context)
- provider.gem_env.gem_binary_location.should == '/usr/weird/bin/gem'
- end
+ describe "when new_resource version is current rspec version" do
+ let(:target_version) { RSpec::Core::Version::STRING }
- it "searches for a gem binary when running on Omnibus on Unix" do
- platform_mock :unix do
- RbConfig::CONFIG.stub(:[]).with('bindir').and_return("/opt/chef/embedded/bin")
- ENV.stub(:[]).with('PATH').and_return("/usr/bin:/usr/sbin:/opt/chef/embedded/bin")
- File.stub(:exists?).with('/usr/bin/gem').and_return(false)
- File.stub(:exists?).with('/usr/sbin/gem').and_return(true)
- File.stub(:exists?).with('/opt/chef/embedded/bin/gem').and_return(true) # should not get here
- provider = Chef::Provider::Package::Rubygems.new(@new_resource, @run_context)
- provider.gem_env.gem_binary_location.should == '/usr/sbin/gem'
+ it "triggers a gem configuration load so a later one will not stomp its config values" do
+ # ugly, is there a better way?
+ Gem.instance_variable_get(:@configuration).should_not be_nil
end
- end
- it "searches for a gem binary when running on Omnibus on Windows" do
- platform_mock :windows do
- RbConfig::CONFIG.stub(:[]).with('bindir').and_return("d:/opscode/chef/embedded/bin")
- ENV.stub(:[]).with('PATH').and_return('C:\windows\system32;C:\windows;C:\Ruby186\bin;d:\opscode\chef\embedded\bin')
- File.stub(:exists?).with('C:\\windows\\system32\\gem').and_return(false)
- File.stub(:exists?).with('C:\\windows\\gem').and_return(false)
- File.stub(:exists?).with('C:\\Ruby186\\bin\\gem').and_return(true)
- File.stub(:exists?).with('d:\\opscode\\chef\\bin\\gem').and_return(false) # should not get here
- File.stub(:exists?).with('d:\\opscode\\chef\\embedded\\bin\\gem').and_return(false) # should not get here
- provider = Chef::Provider::Package::Rubygems.new(@new_resource, @run_context)
- provider.gem_env.gem_binary_location.should == 'C:\Ruby186\bin\gem'
+ it "uses the CurrentGemEnvironment implementation when no gem_binary_path is provided" do
+ @provider.gem_env.should be_a_kind_of(Chef::Provider::Package::Rubygems::CurrentGemEnvironment)
end
- end
-
- it "smites you when you try to use a hash of install options with an explicit gem binary" do
- @new_resource.gem_binary('/foo/bar')
- @new_resource.options(:fail => :burger)
- lambda {Chef::Provider::Package::Rubygems.new(@new_resource, @run_context)}.should raise_error(ArgumentError)
- end
- it "converts the new resource into a gem dependency" do
- @provider.gem_dependency.should == Gem::Dependency.new('rspec-core', @spec_version)
- @new_resource.version('~> 1.2.0')
- @provider.gem_dependency.should == Gem::Dependency.new('rspec-core', '~> 1.2.0')
- end
+ it "uses the AlternateGemEnvironment implementation when a gem_binary_path is provided" do
+ @new_resource.gem_binary('/usr/weird/bin/gem')
+ provider = Chef::Provider::Package::Rubygems.new(@new_resource, @run_context)
+ provider.gem_env.gem_binary_location.should == '/usr/weird/bin/gem'
+ end
- describe "when determining the currently installed version" do
+ it "searches for a gem binary when running on Omnibus on Unix" do
+ platform_mock :unix do
+ RbConfig::CONFIG.stub(:[]).with('bindir').and_return("/opt/chef/embedded/bin")
+ ENV.stub(:[]).with('PATH').and_return("/usr/bin:/usr/sbin:/opt/chef/embedded/bin")
+ File.stub(:exists?).with('/usr/bin/gem').and_return(false)
+ File.stub(:exists?).with('/usr/sbin/gem').and_return(true)
+ File.stub(:exists?).with('/opt/chef/embedded/bin/gem').and_return(true) # should not get here
+ provider = Chef::Provider::Package::Rubygems.new(@new_resource, @run_context)
+ provider.gem_env.gem_binary_location.should == '/usr/sbin/gem'
+ end
+ end
- it "sets the current version to the version specified by the new resource if that version is installed" do
- @provider.load_current_resource
- @provider.current_resource.version.should == @spec_version
+ it "searches for a gem binary when running on Omnibus on Windows" do
+ platform_mock :windows do
+ RbConfig::CONFIG.stub(:[]).with('bindir').and_return("d:/opscode/chef/embedded/bin")
+ ENV.stub(:[]).with('PATH').and_return('C:\windows\system32;C:\windows;C:\Ruby186\bin;d:\opscode\chef\embedded\bin')
+ File.stub(:exists?).with('C:\\windows\\system32\\gem').and_return(false)
+ File.stub(:exists?).with('C:\\windows\\gem').and_return(false)
+ File.stub(:exists?).with('C:\\Ruby186\\bin\\gem').and_return(true)
+ File.stub(:exists?).with('d:\\opscode\\chef\\bin\\gem').and_return(false) # should not get here
+ File.stub(:exists?).with('d:\\opscode\\chef\\embedded\\bin\\gem').and_return(false) # should not get here
+ provider = Chef::Provider::Package::Rubygems.new(@new_resource, @run_context)
+ provider.gem_env.gem_binary_location.should == 'C:\Ruby186\bin\gem'
+ end
end
- it "sets the current version to the highest installed version if the requested version is not installed" do
- @new_resource.version('9000.0.2')
- @provider.load_current_resource
- @provider.current_resource.version.should == @spec_version
+ it "smites you when you try to use a hash of install options with an explicit gem binary" do
+ @new_resource.gem_binary('/foo/bar')
+ @new_resource.options(:fail => :burger)
+ lambda {Chef::Provider::Package::Rubygems.new(@new_resource, @run_context)}.should raise_error(ArgumentError)
end
- it "leaves the current version at nil if the package is not installed" do
- @new_resource.package_name("no-such-gem-should-exist-with-this-name")
- @provider.load_current_resource
- @provider.current_resource.version.should be_nil
+ it "converts the new resource into a gem dependency" do
+ @provider.gem_dependency.should == Gem::Dependency.new('rspec-core', @spec_version)
+ @new_resource.version('~> 1.2.0')
+ @provider.gem_dependency.should == Gem::Dependency.new('rspec-core', '~> 1.2.0')
end
- end
+ describe "when determining the currently installed version" do
- describe "when determining the candidate version to install" do
+ it "sets the current version to the version specified by the new resource if that version is installed" do
+ @provider.load_current_resource
+ @provider.current_resource.version.should == @spec_version
+ end
- it "does not query for available versions when the current version is the target version" do
- @provider.current_resource = @new_resource.dup
- @provider.candidate_version.should be_nil
- end
+ it "sets the current version to the highest installed version if the requested version is not installed" do
+ @new_resource.version('9000.0.2')
+ @provider.load_current_resource
+ @provider.current_resource.version.should == @spec_version
+ end
- it "determines the candidate version by querying the remote gem servers" do
- @new_resource.source('http://mygems.example.com')
- version = Gem::Version.new(@spec_version)
- @provider.gem_env.should_receive(:candidate_version_from_remote).
- with(Gem::Dependency.new('rspec-core', @spec_version), "http://mygems.example.com").
- and_return(version)
- @provider.candidate_version.should == @spec_version
- end
+ it "leaves the current version at nil if the package is not installed" do
+ @new_resource.package_name("no-such-gem-should-exist-with-this-name")
+ @provider.load_current_resource
+ @provider.current_resource.version.should be_nil
+ end
- it "parses the gem's specification if the requested source is a file" do
- @new_resource.package_name('chef-integration-test')
- @new_resource.version('>= 0')
- @new_resource.source(CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem')
- @provider.candidate_version.should == '0.1.0'
end
- end
-
- describe "when installing a gem" do
- before do
- @current_resource = Chef::Resource::GemPackage.new('rspec-core')
- @provider.current_resource = @current_resource
- @gem_dep = Gem::Dependency.new('rspec-core', @spec_version)
- @provider.stub(:load_current_resource)
- end
+ describe "when determining the candidate version to install" do
- describe "in the current gem environment" do
- it "installs the gem via the gems api when no explicit options are used" do
- @provider.gem_env.should_receive(:install).with(@gem_dep, :sources => nil)
- @provider.action_install.should be_true
+ it "does not query for available versions when the current version is the target version" do
+ @provider.current_resource = @new_resource.dup
+ @provider.candidate_version.should be_nil
end
- it "installs the gem via the gems api when a remote source is provided" do
- @new_resource.source('http://gems.example.org')
- sources = ['http://gems.example.org']
- @provider.gem_env.should_receive(:install).with(@gem_dep, :sources => sources)
- @provider.action_install.should be_true
+ it "determines the candidate version by querying the remote gem servers" do
+ @new_resource.source('http://mygems.example.com')
+ version = Gem::Version.new(@spec_version)
+ @provider.gem_env.should_receive(:candidate_version_from_remote).
+ with(Gem::Dependency.new('rspec-core', @spec_version), "http://mygems.example.com").
+ and_return(version)
+ @provider.candidate_version.should == @spec_version
end
- it "installs the gem from file via the gems api when no explicit options are used" do
+ it "parses the gem's specification if the requested source is a file" do
+ @new_resource.package_name('chef-integration-test')
+ @new_resource.version('>= 0')
@new_resource.source(CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem')
- @provider.gem_env.should_receive(:install).with(CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem')
- @provider.action_install.should be_true
+ @provider.candidate_version.should == '0.1.0'
end
- it "installs the gem from file via the gems api when the package is a path and the source is nil" do
- @new_resource = Chef::Resource::GemPackage.new(CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem')
- @provider = Chef::Provider::Package::Rubygems.new(@new_resource, @run_context)
+ end
+
+ describe "when installing a gem" do
+ before do
+ @current_resource = Chef::Resource::GemPackage.new('rspec-core')
@provider.current_resource = @current_resource
- @new_resource.source.should == CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem'
- @provider.gem_env.should_receive(:install).with(CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem')
- @provider.action_install.should be_true
+ @gem_dep = Gem::Dependency.new('rspec-core', @spec_version)
+ @provider.stub(:load_current_resource)
end
- # this catches 'gem_package "foo"' when "./foo" is a file in the cwd, and instead of installing './foo' it fetches the remote gem
- it "installs the gem via the gems api, when the package has no file separator characters in it, but a matching file exists in cwd" do
- ::File.stub(:exists?).and_return(true)
- @new_resource.package_name('rspec-core')
- @provider.gem_env.should_receive(:install).with(@gem_dep, :sources => nil)
- @provider.action_install.should be_true
- end
+ describe "in the current gem environment" do
+ it "installs the gem via the gems api when no explicit options are used" do
+ @provider.gem_env.should_receive(:install).with(@gem_dep, :sources => nil)
+ @provider.action_install.should be_true
+ end
- it "installs the gem by shelling out when options are provided as a String" do
- @new_resource.options('-i /alt/install/location')
- expected ="gem install rspec-core -q --no-rdoc --no-ri -v \"#{@spec_version}\" -i /alt/install/location"
- @provider.should_receive(:shell_out!).with(expected, :env => nil)
- @provider.action_install.should be_true
- end
+ it "installs the gem via the gems api when a remote source is provided" do
+ @new_resource.source('http://gems.example.org')
+ sources = ['http://gems.example.org']
+ @provider.gem_env.should_receive(:install).with(@gem_dep, :sources => sources)
+ @provider.action_install.should be_true
+ end
- it "installs the gem via the gems api when options are given as a Hash" do
- @new_resource.options(:install_dir => '/alt/install/location')
- @provider.gem_env.should_receive(:install).with(@gem_dep, :sources => nil, :install_dir => '/alt/install/location')
- @provider.action_install.should be_true
- end
+ it "installs the gem from file via the gems api when no explicit options are used" do
+ @new_resource.source(CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem')
+ @provider.gem_env.should_receive(:install).with(CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem')
+ @provider.action_install.should be_true
+ end
- describe "at a specific version" do
- before do
- @gem_dep = Gem::Dependency.new('rspec-core', @spec_version)
+ it "installs the gem from file via the gems api when the package is a path and the source is nil" do
+ @new_resource = Chef::Resource::GemPackage.new(CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem')
+ @provider = Chef::Provider::Package::Rubygems.new(@new_resource, @run_context)
+ @provider.current_resource = @current_resource
+ @new_resource.source.should == CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem'
+ @provider.gem_env.should_receive(:install).with(CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem')
+ @provider.action_install.should be_true
end
- it "installs the gem via the gems api" do
+ # this catches 'gem_package "foo"' when "./foo" is a file in the cwd, and instead of installing './foo' it fetches the remote gem
+ it "installs the gem via the gems api, when the package has no file separator characters in it, but a matching file exists in cwd" do
+ ::File.stub(:exists?).and_return(true)
+ @new_resource.package_name('rspec-core')
@provider.gem_env.should_receive(:install).with(@gem_dep, :sources => nil)
@provider.action_install.should be_true
end
- end
- describe "at version specified with comparison operator" do
- it "skips install if current version satisifies requested version" do
- @current_resource.stub(:version).and_return("2.3.3")
- @new_resource.stub(:version).and_return(">=2.3.0")
- @provider.gem_env.should_not_receive(:install)
- @provider.action_install
+ it "installs the gem by shelling out when options are provided as a String" do
+ @new_resource.options('-i /alt/install/location')
+ expected ="gem install rspec-core -q --no-rdoc --no-ri -v \"#{@spec_version}\" -i /alt/install/location"
+ @provider.should_receive(:shell_out!).with(expected, :env => nil)
+ @provider.action_install.should be_true
+ end
+
+ it "installs the gem via the gems api when options are given as a Hash" do
+ @new_resource.options(:install_dir => '/alt/install/location')
+ @provider.gem_env.should_receive(:install).with(@gem_dep, :sources => nil, :install_dir => '/alt/install/location')
+ @provider.action_install.should be_true
end
- it "allows user to specify gem version with fuzzy operator" do
- @current_resource.stub(:version).and_return("2.3.3")
- @new_resource.stub(:version).and_return("~>2.3.0")
+ describe "at a specific version" do
+ before do
+ @gem_dep = Gem::Dependency.new('rspec-core', @spec_version)
+ end
- @provider.gem_env.should_not_receive(:install)
- @provider.action_install
+ it "installs the gem via the gems api" do
+ @provider.gem_env.should_receive(:install).with(@gem_dep, :sources => nil)
+ @provider.action_install.should be_true
+ end
+ end
+ describe "at version specified with comparison operator" do
+ it "skips install if current version satisifies requested version" do
+ @current_resource.stub(:version).and_return("2.3.3")
+ @new_resource.stub(:version).and_return(">=2.3.0")
+
+ @provider.gem_env.should_not_receive(:install)
+ @provider.action_install
+ end
+
+ it "allows user to specify gem version with fuzzy operator" do
+ @current_resource.stub(:version).and_return("2.3.3")
+ @new_resource.stub(:version).and_return("~>2.3.0")
+
+ @provider.gem_env.should_not_receive(:install)
+ @provider.action_install
+ end
end
end
- end
- describe "in an alternate gem environment" do
- it "installs the gem by shelling out to gem install" do
- @new_resource.gem_binary('/usr/weird/bin/gem')
- @provider.should_receive(:shell_out!).with("/usr/weird/bin/gem install rspec-core -q --no-rdoc --no-ri -v \"#{@spec_version}\"", :env=>nil)
- @provider.action_install.should be_true
- end
+ describe "in an alternate gem environment" do
+ it "installs the gem by shelling out to gem install" do
+ @new_resource.gem_binary('/usr/weird/bin/gem')
+ @provider.should_receive(:shell_out!).with("/usr/weird/bin/gem install rspec-core -q --no-rdoc --no-ri -v \"#{@spec_version}\"", :env=>nil)
+ @provider.action_install.should be_true
+ end
- it "installs the gem from file by shelling out to gem install" do
- @new_resource.gem_binary('/usr/weird/bin/gem')
- @new_resource.source(CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem')
- @new_resource.version('>= 0')
- @provider.should_receive(:shell_out!).with("/usr/weird/bin/gem install #{CHEF_SPEC_DATA}/gems/chef-integration-test-0.1.0.gem -q --no-rdoc --no-ri -v \">= 0\"", :env=>nil)
- @provider.action_install.should be_true
- end
+ it "installs the gem from file by shelling out to gem install" do
+ @new_resource.gem_binary('/usr/weird/bin/gem')
+ @new_resource.source(CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem')
+ @new_resource.version('>= 0')
+ @provider.should_receive(:shell_out!).with("/usr/weird/bin/gem install #{CHEF_SPEC_DATA}/gems/chef-integration-test-0.1.0.gem -q --no-rdoc --no-ri -v \">= 0\"", :env=>nil)
+ @provider.action_install.should be_true
+ end
- it "installs the gem from file by shelling out to gem install when the package is a path and the source is nil" do
- @new_resource = Chef::Resource::GemPackage.new(CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem')
- @provider = Chef::Provider::Package::Rubygems.new(@new_resource, @run_context)
- @provider.current_resource = @current_resource
- @new_resource.gem_binary('/usr/weird/bin/gem')
- @new_resource.version('>= 0')
- @new_resource.source.should == CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem'
- @provider.should_receive(:shell_out!).with("/usr/weird/bin/gem install #{CHEF_SPEC_DATA}/gems/chef-integration-test-0.1.0.gem -q --no-rdoc --no-ri -v \">= 0\"", :env=>nil)
- @provider.action_install.should be_true
+ it "installs the gem from file by shelling out to gem install when the package is a path and the source is nil" do
+ @new_resource = Chef::Resource::GemPackage.new(CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem')
+ @provider = Chef::Provider::Package::Rubygems.new(@new_resource, @run_context)
+ @provider.current_resource = @current_resource
+ @new_resource.gem_binary('/usr/weird/bin/gem')
+ @new_resource.version('>= 0')
+ @new_resource.source.should == CHEF_SPEC_DATA + '/gems/chef-integration-test-0.1.0.gem'
+ @provider.should_receive(:shell_out!).with("/usr/weird/bin/gem install #{CHEF_SPEC_DATA}/gems/chef-integration-test-0.1.0.gem -q --no-rdoc --no-ri -v \">= 0\"", :env=>nil)
+ @provider.action_install.should be_true
+ end
end
- end
- end
-
- describe "when uninstalling a gem" do
- before do
- @new_resource = Chef::Resource::GemPackage.new("rspec")
- @current_resource = @new_resource.dup
- @current_resource.version('1.2.3')
- @provider.new_resource = @new_resource
- @provider.current_resource = @current_resource
end
- describe "in the current gem environment" do
- it "uninstalls via the api when no explicit options are used" do
- # pre-reqs for action_remove to actually remove the package:
- @provider.new_resource.version.should be_nil
- @provider.current_resource.version.should_not be_nil
- # the behavior we're testing:
- @provider.gem_env.should_receive(:uninstall).with('rspec', nil)
- @provider.action_remove
+ describe "when uninstalling a gem" do
+ before do
+ @new_resource = Chef::Resource::GemPackage.new("rspec")
+ @current_resource = @new_resource.dup
+ @current_resource.version('1.2.3')
+ @provider.new_resource = @new_resource
+ @provider.current_resource = @current_resource
end
- it "uninstalls via the api when options are given as a Hash" do
- # pre-reqs for action_remove to actually remove the package:
- @provider.new_resource.version.should be_nil
- @provider.current_resource.version.should_not be_nil
- # the behavior we're testing:
- @new_resource.options(:install_dir => '/alt/install/location')
- @provider.gem_env.should_receive(:uninstall).with('rspec', nil, :install_dir => '/alt/install/location')
- @provider.action_remove
- end
+ describe "in the current gem environment" do
+ it "uninstalls via the api when no explicit options are used" do
+ # pre-reqs for action_remove to actually remove the package:
+ @provider.new_resource.version.should be_nil
+ @provider.current_resource.version.should_not be_nil
+ # the behavior we're testing:
+ @provider.gem_env.should_receive(:uninstall).with('rspec', nil)
+ @provider.action_remove
+ end
- it "uninstalls via the gem command when options are given as a String" do
- @new_resource.options('-i /alt/install/location')
- @provider.should_receive(:shell_out!).with("gem uninstall rspec -q -x -I -a -i /alt/install/location", :env=>nil)
- @provider.action_remove
- end
+ it "uninstalls via the api when options are given as a Hash" do
+ # pre-reqs for action_remove to actually remove the package:
+ @provider.new_resource.version.should be_nil
+ @provider.current_resource.version.should_not be_nil
+ # the behavior we're testing:
+ @new_resource.options(:install_dir => '/alt/install/location')
+ @provider.gem_env.should_receive(:uninstall).with('rspec', nil, :install_dir => '/alt/install/location')
+ @provider.action_remove
+ end
+
+ it "uninstalls via the gem command when options are given as a String" do
+ @new_resource.options('-i /alt/install/location')
+ @provider.should_receive(:shell_out!).with("gem uninstall rspec -q -x -I -a -i /alt/install/location", :env=>nil)
+ @provider.action_remove
+ end
- it "uninstalls a specific version of a gem when a version is provided" do
- @new_resource.version('1.2.3')
- @provider.gem_env.should_receive(:uninstall).with('rspec', '1.2.3')
- @provider.action_remove
+ it "uninstalls a specific version of a gem when a version is provided" do
+ @new_resource.version('1.2.3')
+ @provider.gem_env.should_receive(:uninstall).with('rspec', '1.2.3')
+ @provider.action_remove
+ end
end
- end
- describe "in an alternate gem environment" do
- it "uninstalls via the gem command" do
- @new_resource.gem_binary('/usr/weird/bin/gem')
- @provider.should_receive(:shell_out!).with("/usr/weird/bin/gem uninstall rspec -q -x -I -a", :env=>nil)
- @provider.action_remove
+ describe "in an alternate gem environment" do
+ it "uninstalls via the gem command" do
+ @new_resource.gem_binary('/usr/weird/bin/gem')
+ @provider.should_receive(:shell_out!).with("/usr/weird/bin/gem uninstall rspec -q -x -I -a", :env=>nil)
+ @provider.action_remove
+ end
end
end
end
end
-
diff --git a/spec/unit/provider/remote_file/cache_control_data_spec.rb b/spec/unit/provider/remote_file/cache_control_data_spec.rb
index 8e396b1b40..8a849d9d7d 100644
--- a/spec/unit/provider/remote_file/cache_control_data_spec.rb
+++ b/spec/unit/provider/remote_file/cache_control_data_spec.rb
@@ -85,7 +85,7 @@ describe Chef::Provider::RemoteFile::CacheControlData do
cache["etag"] = etag
cache["mtime"] = mtime
cache["checksum"] = last_fetched_checksum
- cache.to_json
+ Chef::JSONCompat.to_json(cache)
end
before do
diff --git a/spec/unit/recipe_spec.rb b/spec/unit/recipe_spec.rb
index c795ba3788..5b6f3ea55b 100644
--- a/spec/unit/recipe_spec.rb
+++ b/spec/unit/recipe_spec.rb
@@ -361,6 +361,15 @@ describe Chef::Recipe do
end
end
+ describe "handle exec calls" do
+ it "should raise ResourceNotFound error if exec is used" do
+ code = <<-CODE
+ exec 'do_not_try_to_exec'
+ CODE
+ lambda { recipe.instance_eval(code) }.should raise_error(Chef::Exceptions::ResourceNotFound)
+ end
+ end
+
describe "from_file" do
it "should load a resource from a ruby file" do
recipe.from_file(File.join(CHEF_SPEC_DATA, "recipes", "test.rb"))
diff --git a/spec/unit/resource/dsc_script_spec.rb b/spec/unit/resource/dsc_script_spec.rb
index cbd502a61c..eb9d19e553 100644
--- a/spec/unit/resource/dsc_script_spec.rb
+++ b/spec/unit/resource/dsc_script_spec.rb
@@ -95,33 +95,4 @@ describe Chef::Resource::DscScript do
expect { dsc_test_resource.configuration_data_script(configuration_data_script) }.to raise_error(ArgumentError)
end
end
-
- context 'when Powershell does not supported Dsc' do
- ['1.0', '2.0', '3.0'].each do |version|
- it "raises an exception for powershell version '#{version}'" do
- node = Chef::Node.new
- node.automatic[:languages][:powershell][:version] = version
- empty_events = Chef::EventDispatch::Dispatcher.new
- dsc_test_run_context = Chef::RunContext.new(node, {}, empty_events)
-
- expect {
- Chef::Resource::DscScript.new(dsc_test_resource_name, dsc_test_run_context)
- }.to raise_error(Chef::Exceptions::NoProviderAvailable)
- end
- end
- end
-
- context 'when Powershell is not present' do
- let (:dsc_test_run_context) {
- node = Chef::Node.new
- empty_events = Chef::EventDispatch::Dispatcher.new
- dsc_test_run_context = Chef::RunContext.new(node, {}, empty_events)
- }
-
- it 'raises an exception if powershell is not present' do
- expect {
- Chef::Resource::DscScript.new(dsc_test_resource_name, dsc_test_run_context)
- }.to raise_error(Chef::Exceptions::NoProviderAvailable)
- end
- end
end
diff --git a/spec/unit/resource/freebsd_package_spec.rb b/spec/unit/resource/freebsd_package_spec.rb
index ae12abac6e..04a6962270 100644
--- a/spec/unit/resource/freebsd_package_spec.rb
+++ b/spec/unit/resource/freebsd_package_spec.rb
@@ -57,7 +57,7 @@ describe Chef::Resource::FreebsdPackage do
describe "if __Freebsd_version is greater than or equal to 1000017" do
it "should be Freebsd::Pkgng" do
[1000017, 1000018, 1000500, 1001001, 1100000].each do |__freebsd_version|
- @node.normal[:os_version] = __freebsd_version
+ @node.automatic_attrs[:os_version] = __freebsd_version
@resource.after_created
@resource.provider.should == Chef::Provider::Package::Freebsd::Pkgng
end
@@ -79,8 +79,7 @@ describe Chef::Resource::FreebsdPackage do
@resource.stub(:shell_out!).with("make -V WITH_PKGNG", :env => nil).and_return(pkg_enabled)
[1000016, 1000000, 901503, 902506, 802511].each do |__freebsd_version|
- @node[:os_version] == __freebsd_version
- @node.normal[:os_version] = __freebsd_version
+ @node.automatic_attrs[:os_version] = __freebsd_version
@resource.after_created
@resource.provider.should == Chef::Provider::Package::Freebsd::Pkg
end
diff --git a/spec/unit/resource_collection_spec.rb b/spec/unit/resource_collection_spec.rb
index eddd92e098..cf119f1ab0 100644
--- a/spec/unit/resource_collection_spec.rb
+++ b/spec/unit/resource_collection_spec.rb
@@ -278,12 +278,20 @@ describe Chef::ResourceCollection do
json.should =~ /json_class/
json.should =~ /instance_vars/
end
+
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:jsonable) { @rc }
+ end
end
describe "self.from_json" do
- it "should deserialize itself from json" do
+ it "should not respond to this method" do
+ expect(@rc.respond_to?(:from_json)).to eq(false)
+ end
+
+ it "should convert from json using the CHEF::JSONCompat library" do
@rc << @resource
- json = @rc.to_json
+ json = Chef::JSONCompat.to_json(@rc)
s_rc = Chef::JSONCompat.from_json(json)
s_rc.should be_a_kind_of(Chef::ResourceCollection)
s_rc[0].name.should eql(@resource.name)
diff --git a/spec/unit/resource_reporter_spec.rb b/spec/unit/resource_reporter_spec.rb
index fe6a895b5a..1a89cbdce1 100644
--- a/spec/unit/resource_reporter_spec.rb
+++ b/spec/unit/resource_reporter_spec.rb
@@ -421,7 +421,7 @@ describe Chef::ResourceReporter do
it "includes the run_list" do
@report.should have_key("run_list")
- @report["run_list"].should == @run_status.node.run_list.to_json
+ @report["run_list"].should == Chef::JSONCompat.to_json(@run_status.node.run_list)
end
it "includes the end_time" do
@@ -484,7 +484,7 @@ describe Chef::ResourceReporter do
it "includes the exception trace in the event data" do
@report["data"]["exception"].should have_key("backtrace")
- @report["data"]["exception"]["backtrace"].should == @backtrace.to_json
+ @report["data"]["exception"]["backtrace"].should == Chef::JSONCompat.to_json(@backtrace)
end
it "includes the error inspector output in the event data" do
@@ -701,7 +701,7 @@ describe Chef::ResourceReporter do
})
data_stream = Zlib::GzipReader.new(StringIO.new(data))
data = data_stream.read
- data.should eq(@expected_data.to_json)
+ data.should eq(Chef::JSONCompat.to_json(@expected_data))
response
end
diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb
index e85633eaab..692345c943 100644
--- a/spec/unit/resource_spec.rb
+++ b/spec/unit/resource_spec.rb
@@ -336,6 +336,10 @@ describe Chef::Resource do
json.should =~ /json_class/
json.should =~ /instance_vars/
end
+
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:jsonable) { @resource }
+ end
end
describe "to_hash" do
@@ -354,7 +358,7 @@ describe Chef::Resource do
describe "self.json_create" do
it "should deserialize itself from json" do
- json = @resource.to_json
+ json = Chef::JSONCompat.to_json(@resource)
serialized_node = Chef::JSONCompat.from_json(json)
serialized_node.should be_a_kind_of(Chef::Resource)
serialized_node.name.should eql(@resource.name)
diff --git a/spec/unit/role_spec.rb b/spec/unit/role_spec.rb
index f3fa7e1868..1a108c4247 100644
--- a/spec/unit/role_spec.rb
+++ b/spec/unit/role_spec.rb
@@ -216,6 +216,10 @@ describe Chef::Role do
end
end
+
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:jsonable) { @role }
+ end
end
describe "when created from JSON", :json => true do
diff --git a/spec/unit/run_list_spec.rb b/spec/unit/run_list_spec.rb
index 220e4ea4a6..cc7e29af0f 100644
--- a/spec/unit/run_list_spec.rb
+++ b/spec/unit/run_list_spec.rb
@@ -304,7 +304,11 @@ describe Chef::RunList do
end
it "converts to json by converting its array form" do
- @run_list.to_json.should == ["recipe[nagios::client]", "role[production]", "recipe[apache2]"].to_json
+ Chef::JSONCompat.to_json(@run_list).should == Chef::JSONCompat.to_json(["recipe[nagios::client]", "role[production]", "recipe[apache2]"])
+ end
+
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:jsonable) { @run_list }
end
end
diff --git a/spec/unit/user_spec.rb b/spec/unit/user_spec.rb
index 08bde33d7b..2f2299c5bd 100644
--- a/spec/unit/user_spec.rb
+++ b/spec/unit/user_spec.rb
@@ -154,6 +154,10 @@ describe Chef::User do
it "does not include the password if not present" do
@json.should_not include("password")
end
+
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:jsonable) { @user }
+ end
end
describe "when deserializing from JSON" do
@@ -163,7 +167,7 @@ describe Chef::User do
"private_key" => "pandas",
"password" => "password",
"admin" => true }
- @user = Chef::User.from_json(user.to_json)
+ @user = Chef::User.from_json(Chef::JSONCompat.to_json(user))
end
it "should deserialize to a Chef::User object" do