summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--CHANGELOG.md7
-rw-r--r--chef.gemspec4
-rw-r--r--lib/chef/api_client.rb2
-rw-r--r--lib/chef/chef_fs/chef_fs_data_store.rb5
-rw-r--r--lib/chef/chef_fs/command_line.rb5
-rw-r--r--lib/chef/chef_fs/file_system/acl_entry.rb3
-rw-r--r--lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb3
-rw-r--r--lib/chef/chef_fs/file_system/rest_list_dir.rb5
-rw-r--r--lib/chef/chef_fs/file_system/rest_list_entry.rb9
-rw-r--r--lib/chef/config_fetcher.rb2
-rw-r--r--lib/chef/cookbook/cookbook_version_loader.rb8
-rw-r--r--lib/chef/cookbook/metadata.rb2
-rw-r--r--lib/chef/cookbook_version.rb4
-rw-r--r--lib/chef/data_bag.rb2
-rw-r--r--lib/chef/data_bag_item.rb2
-rw-r--r--lib/chef/encrypted_data_bag_item/decryptor.rb6
-rw-r--r--lib/chef/environment.rb2
-rw-r--r--lib/chef/exceptions.rb10
-rw-r--r--lib/chef/json_compat.rb109
-rw-r--r--lib/chef/knife/bootstrap.rb4
-rw-r--r--lib/chef/knife/bootstrap/archlinux-gems.erb4
-rw-r--r--lib/chef/knife/bootstrap/centos5-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/bootstrap/fedora13-gems.erb4
-rw-r--r--lib/chef/knife/bootstrap/ubuntu10.04-apt.erb4
-rw-r--r--lib/chef/knife/bootstrap/ubuntu10.04-gems.erb4
-rw-r--r--lib/chef/knife/bootstrap/ubuntu12.04-gems.erb4
-rw-r--r--lib/chef/knife/cookbook_site_download.rb2
-rw-r--r--lib/chef/knife/cookbook_site_list.rb2
-rw-r--r--lib/chef/knife/cookbook_site_search.rb2
-rw-r--r--lib/chef/knife/cookbook_site_share.rb4
-rw-r--r--lib/chef/knife/cookbook_site_show.rb6
-rw-r--r--lib/chef/knife/cookbook_site_unshare.rb2
-rw-r--r--lib/chef/knife/deps.rb5
-rw-r--r--lib/chef/node.rb2
-rw-r--r--lib/chef/provider/deploy/revision.rb2
-rw-r--r--lib/chef/provider/dsc_script.rb37
-rw-r--r--lib/chef/provider/env.rb35
-rw-r--r--lib/chef/provider/remote_file/cache_control_data.rb2
-rw-r--r--lib/chef/resource.rb2
-rw-r--r--lib/chef/resource/dsc_script.rb18
-rw-r--r--lib/chef/resource_collection.rb2
-rw-r--r--lib/chef/resource_reporter.rb6
-rw-r--r--lib/chef/role.rb2
-rw-r--r--lib/chef/run_list.rb2
-rw-r--r--lib/chef/user.rb2
-rw-r--r--lib/chef/util/dsc/local_configuration_manager.rb26
-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/functional/knife/cookbook_delete_spec.rb6
-rw-r--r--spec/functional/knife/exec_spec.rb2
-rw-r--r--spec/functional/resource/dsc_script_spec.rb139
-rwxr-xr-xspec/functional/resource/env_spec.rb7
-rw-r--r--spec/functional/util/powershell/cmdlet_spec.rb3
-rw-r--r--spec/integration/knife/chef_fs_data_store_spec.rb2
-rw-r--r--spec/integration/knife/chef_repo_path_spec.rb7
-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.rb6
-rw-r--r--spec/integration/knife/download_spec.rb6
-rw-r--r--spec/integration/knife/list_spec.rb2
-rw-r--r--spec/integration/knife/raw_spec.rb12
-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.rb18
-rw-r--r--spec/spec_helper.rb6
-rw-r--r--spec/support/shared/integration/integration_helper.rb3
-rw-r--r--spec/support/shared/shared_examples.rb10
-rw-r--r--spec/tiny_server.rb3
-rw-r--r--spec/unit/api_client_spec.rb6
-rw-r--r--spec/unit/config_fetcher_spec.rb2
-rw-r--r--spec/unit/cookbook/metadata_spec.rb10
-rw-r--r--spec/unit/cookbook_loader_spec.rb2
-rw-r--r--spec/unit/cookbook_version_spec.rb4
-rw-r--r--spec/unit/data_bag_item_spec.rb6
-rw-r--r--spec/unit/data_bag_spec.rb6
-rw-r--r--spec/unit/deprecation_spec.rb2
-rw-r--r--spec/unit/encrypted_data_bag_item_spec.rb21
-rw-r--r--spec/unit/environment_spec.rb10
-rw-r--r--spec/unit/exceptions_spec.rb6
-rw-r--r--spec/unit/json_compat_spec.rb75
-rw-r--r--spec/unit/knife/cookbook_metadata_from_file_spec.rb1
-rw-r--r--spec/unit/knife/cookbook_site_download_spec.rb3
-rw-r--r--spec/unit/knife/cookbook_site_share_spec.rb12
-rw-r--r--spec/unit/knife/core/bootstrap_context_spec.rb4
-rw-r--r--spec/unit/knife/data_bag_from_file_spec.rb3
-rw-r--r--spec/unit/node_spec.rb4
-rw-r--r--spec/unit/provider/dsc_script_spec.rb239
-rw-r--r--spec/unit/provider/env/windows_spec.rb4
-rw-r--r--spec/unit/provider/env_spec.rb87
-rw-r--r--spec/unit/provider/remote_file/cache_control_data_spec.rb2
-rw-r--r--spec/unit/resource/dsc_script_spec.rb29
-rw-r--r--spec/unit/resource_collection_spec.rb6
-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
-rw-r--r--spec/unit/util/dsc/local_configuration_manager_spec.rb25
107 files changed, 776 insertions, 467 deletions
diff --git a/.travis.yml b/.travis.yml
index 5c45a016b6..f1146a4aaa 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,7 +13,6 @@ before_install:
matrix:
include:
- - rvm: 1.8.7-p374
- rvm: 1.9.3
- rvm: 2.0.0
- rvm: 2.1.1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 13ecaf592c..77df6610b6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
## Unreleased:
+* Removed dependencies on the 'json' gem, replaced with ffi-yajl. Use Chef::JSONCompat library for parsing and printing.
+* [Issue 2027](https://github.com/opscode/chef/issues/2027) Allow recipe using `dsc_script` opportunity to install Powershell 4 or higher
+* [Issue 2169](https://github.com/opscode/chef/issues/2169) Attempt to converge DSC configurations with resources that do not correctly support what-if
+
## Last Release: 11.16.4
* Windows omnibus installer security updates for redistributed bash.exe / sh.exe
@@ -13,7 +17,8 @@
## Release: 11.16.2
-* This is a packaging-only release there are no code changes
+* [**Phil Dibowitz**](https://github.com/jaymzh):
+ Fix a regression in whyrun_safe_ruby_block.
## Release: 11.16.0
diff --git a/chef.gemspec b/chef.gemspec
index 7c53618a51..36412aa679 100644
--- a/chef.gemspec
+++ b/chef.gemspec
@@ -29,7 +29,7 @@ Gem::Specification.new do |s|
# it's the version I had when I tested.
s.add_dependency "mime-types", "~> 1.16"
- s.add_dependency "ffi-yajl", "~> 1.0"
+ 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.
@@ -37,7 +37,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", "~> 2.1", ">= 2.1.4"
+ s.add_dependency "chef-zero", "~> 2.2", ">= 2.2.1"
s.add_dependency "pry", "~> 0.9"
s.add_dependency 'plist', '~> 3.1.0'
diff --git a/lib/chef/api_client.rb b/lib/chef/api_client.rb
index 7b7fd99ff7..334fb23f38 100644
--- a/lib/chef/api_client.rb
+++ b/lib/chef/api_client.rb
@@ -121,7 +121,7 @@ class Chef
#
# @return [String] the JSON string.
def to_json(*a)
- to_hash.to_json(*a)
+ Chef::JSONCompat.to_json(to_hash, *a)
end
def self.json_create(o)
diff --git a/lib/chef/chef_fs/chef_fs_data_store.rb b/lib/chef/chef_fs/chef_fs_data_store.rb
index b84fc1945d..a88bf0c256 100644
--- a/lib/chef/chef_fs/chef_fs_data_store.rb
+++ b/lib/chef/chef_fs/chef_fs_data_store.rb
@@ -23,6 +23,7 @@ require 'chef/chef_fs/file_pattern'
require 'chef/chef_fs/file_system'
require 'chef/chef_fs/file_system/not_found_error'
require 'chef/chef_fs/file_system/memory_root'
+require 'chef/json_compat'
require 'fileutils'
class Chef
@@ -114,7 +115,7 @@ class Chef
end
end
end
- JSON.pretty_generate(result)
+ Chef::JSONCompat.to_json_pretty(result)
else
begin
@@ -269,7 +270,7 @@ class Chef
# Create a little Chef::ChefFS memory filesystem with the data
cookbook_fs = Chef::ChefFS::FileSystem::MemoryRoot.new('uploading')
- cookbook = JSON.parse(data, :create_additions => false)
+ cookbook = Chef::JSONCompat.parse(data, :create_additions => false)
cookbook.each_pair do |key, value|
if value.is_a?(Array)
value.each do |file|
diff --git a/lib/chef/chef_fs/command_line.rb b/lib/chef/chef_fs/command_line.rb
index 967c59ecae..5fa770089b 100644
--- a/lib/chef/chef_fs/command_line.rb
+++ b/lib/chef/chef_fs/command_line.rb
@@ -19,6 +19,7 @@
require 'chef/chef_fs/file_system'
require 'chef/chef_fs/file_system/operation_failed_error'
require 'chef/chef_fs/file_system/operation_not_allowed_error'
+require 'chef/json_compat'
require 'chef/util/diff'
class Chef
@@ -251,9 +252,9 @@ class Chef
end
def self.canonicalize_json(json_text)
- parsed_json = JSON.parse(json_text, :create_additions => false)
+ parsed_json = Chef::JSONCompat.parse(json_text, :create_additions => false)
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/acl_entry.rb b/lib/chef/chef_fs/file_system/acl_entry.rb
index 8edc02d5c5..1659b557ba 100644
--- a/lib/chef/chef_fs/file_system/acl_entry.rb
+++ b/lib/chef/chef_fs/file_system/acl_entry.rb
@@ -20,6 +20,7 @@ require 'chef/chef_fs/file_system/rest_list_entry'
require 'chef/chef_fs/file_system/not_found_error'
require 'chef/chef_fs/file_system/operation_not_allowed_error'
require 'chef/chef_fs/file_system/operation_failed_error'
+require 'chef/json_compat'
class Chef
module ChefFS
@@ -37,7 +38,7 @@ class Chef
def write(file_contents)
# ACL writes are fun.
- acls = data_handler.normalize(JSON.parse(file_contents, :create_additions => false), self)
+ acls = data_handler.normalize(Chef::JSONCompat.parse(file_contents, :create_additions => false), self)
PERMISSIONS.each do |permission|
begin
rest.put("#{api_path}/#{permission}", { permission => acls[permission] })
diff --git a/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb b/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb
index 3d3f58201e..d22d11b0f3 100644
--- a/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb
+++ b/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb
@@ -19,6 +19,7 @@
require 'chef/chef_fs/file_system/file_system_entry'
require 'chef/chef_fs/file_system/not_found_error'
+require 'chef/json_compat'
class Chef
module ChefFS
@@ -41,7 +42,7 @@ class Chef
def chef_object
begin
- return data_handler.chef_object(JSON.parse(read, :create_additions => false))
+ return data_handler.chef_object(Chef::JSONCompat.parse(read, :create_additions => false))
rescue
Chef::Log.error("Could not read #{path_for_printing} into a Chef object: #{$!}")
end
diff --git a/lib/chef/chef_fs/file_system/rest_list_dir.rb b/lib/chef/chef_fs/file_system/rest_list_dir.rb
index b7ee51d284..273caa3478 100644
--- a/lib/chef/chef_fs/file_system/rest_list_dir.rb
+++ b/lib/chef/chef_fs/file_system/rest_list_dir.rb
@@ -19,6 +19,7 @@
require 'chef/chef_fs/file_system/base_fs_dir'
require 'chef/chef_fs/file_system/rest_list_entry'
require 'chef/chef_fs/file_system/not_found_error'
+require 'chef/json_compat'
class Chef
module ChefFS
@@ -61,8 +62,8 @@ class Chef
def create_child(name, file_contents)
begin
- object = JSON.parse(file_contents, :create_additions => false)
- rescue JSON::ParserError => e
+ object = Chef::JSONCompat.parse(file_contents, :create_additions => false)
+ rescue Chef::Exceptions::JSON::ParseError => e
raise Chef::ChefFS::FileSystem::OperationFailedError.new(:create_child, self, e), "Parse error reading JSON creating child '#{name}': #{e}"
end
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 0d5557de1d..345fab63be 100644
--- a/lib/chef/chef_fs/file_system/rest_list_entry.rb
+++ b/lib/chef/chef_fs/file_system/rest_list_entry.rb
@@ -19,6 +19,7 @@
require 'chef/chef_fs/file_system/base_fs_object'
require 'chef/chef_fs/file_system/not_found_error'
require 'chef/chef_fs/file_system/operation_failed_error'
+require 'chef/json_compat'
require 'chef/role'
require 'chef/node'
@@ -128,8 +129,8 @@ class Chef
value = minimize_value(value)
value_json = Chef::JSONCompat.to_json_pretty(value)
begin
- other_value = JSON.parse(other_value_json, :create_additions => false)
- rescue JSON::ParserError => e
+ other_value = Chef::JSONCompat.parse(other_value_json, :create_additions => false)
+ rescue Chef::Exceptions::JSON::ParseError => e
Chef::Log.warn("Parse error reading #{other.path_for_printing} as JSON: #{e}")
return [ nil, value_json, other_value_json ]
end
@@ -145,8 +146,8 @@ class Chef
def write(file_contents)
begin
- object = JSON.parse(file_contents, :create_additions => false)
- rescue JSON::ParserError => e
+ object = Chef::JSONCompat.parse(file_contents, :create_additions => false)
+ rescue Chef::Exceptions::JSON::ParseError => e
raise Chef::ChefFS::FileSystem::OperationFailedError.new(:write, self, e), "Parse error reading JSON: #{e}"
end
diff --git a/lib/chef/config_fetcher.rb b/lib/chef/config_fetcher.rb
index c1fd262656..1d0693eaa2 100644
--- a/lib/chef/config_fetcher.rb
+++ b/lib/chef/config_fetcher.rb
@@ -18,7 +18,7 @@ class Chef
config_data = read_config
begin
Chef::JSONCompat.from_json(config_data)
- rescue FFI_Yajl::ParseError => error
+ rescue Chef::Exceptions::JSON::ParseError => error
Chef::Application.fatal!("Could not parse the provided JSON file (#{config_location}): " + error.message, 2)
end
end
diff --git a/lib/chef/cookbook/cookbook_version_loader.rb b/lib/chef/cookbook/cookbook_version_loader.rb
index 4e92b74ae9..fac8c80993 100644
--- a/lib/chef/cookbook/cookbook_version_loader.rb
+++ b/lib/chef/cookbook/cookbook_version_loader.rb
@@ -170,7 +170,7 @@ class Chef
def apply_ruby_metadata(file)
begin
@metadata.from_file(file)
- rescue JSON::ParserError
+ rescue Chef::Exceptions::JSON::ParseError
Chef::Log.error("Error evaluating metadata.rb for #@cookbook_name in " + file)
raise
end
@@ -179,7 +179,7 @@ class Chef
def apply_json_metadata(file)
begin
@metadata.from_json(IO.read(file))
- rescue JSON::ParserError
+ rescue Chef::Exceptions::JSON::ParseError
Chef::Log.error("Couldn't parse cookbook metadata JSON for #@cookbook_name in " + file)
raise
end
@@ -189,7 +189,7 @@ class Chef
begin
data = Chef::JSONCompat.from_json(IO.read(file), :create_additions => false)
@metadata.from_hash(data['metadata'])
- rescue JSON::ParserError
+ rescue Chef::Exceptions::JSON::ParseError
Chef::Log.error("Couldn't parse cookbook metadata JSON for #@cookbook_name in " + file)
raise
end
@@ -200,7 +200,7 @@ class Chef
begin
data = Chef::JSONCompat.from_json(IO.read(uploaded_cookbook_version_file), :create_additions => false)
@frozen = data['frozen?']
- rescue JSON::ParserError
+ rescue Chef::Exceptions::JSON::ParseError
Chef::Log.error("Couldn't parse cookbook metadata JSON for #@cookbook_name in #{uploaded_cookbook_version_file}")
raise
end
diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb
index 7da1ae70de..21ab72e1cd 100644
--- a/lib/chef/cookbook/metadata.rb
+++ b/lib/chef/cookbook/metadata.rb
@@ -441,7 +441,7 @@ class Chef
end
def to_json(*a)
- self.to_hash.to_json(*a)
+ Chef::JSONCompat.to_json(self.to_hash, *a)
end
def self.from_hash(o)
diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb
index 3d8b9fb908..f9775c4d8d 100644
--- a/lib/chef/cookbook_version.rb
+++ b/lib/chef/cookbook_version.rb
@@ -459,7 +459,7 @@ class Chef
def to_json(*a)
result = self.to_hash
result['json_class'] = self.class.name
- result.to_json(*a)
+ Chef::JSONCompat.to_json(result, *a)
end
def self.json_create(o)
@@ -469,7 +469,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
diff --git a/lib/chef/data_bag.rb b/lib/chef/data_bag.rb
index 639d71a74d..f50aa93d2d 100644
--- a/lib/chef/data_bag.rb
+++ b/lib/chef/data_bag.rb
@@ -63,7 +63,7 @@ class Chef
# Serialize this object as a hash
def to_json(*a)
- to_hash.to_json(*a)
+ Chef::JSONCompat.to_json(to_hash, *a)
end
def chef_server_rest
diff --git a/lib/chef/data_bag_item.rb b/lib/chef/data_bag_item.rb
index 07dd15a1dc..3772f9ea1c 100644
--- a/lib/chef/data_bag_item.rb
+++ b/lib/chef/data_bag_item.rb
@@ -118,7 +118,7 @@ class Chef
"data_bag" => self.data_bag,
"raw_data" => self.raw_data
}
- result.to_json(*a)
+ Chef::JSONCompat.to_json(result, *a)
end
def self.from_hash(h)
diff --git a/lib/chef/encrypted_data_bag_item/decryptor.rb b/lib/chef/encrypted_data_bag_item/decryptor.rb
index 69b8d62e3b..503a8f3099 100644
--- a/lib/chef/encrypted_data_bag_item/decryptor.rb
+++ b/lib/chef/encrypted_data_bag_item/decryptor.rb
@@ -17,10 +17,10 @@
#
require 'yaml'
-require 'ffi_yajl'
require 'openssl'
require 'base64'
require 'digest/sha2'
+require 'chef/json_compat'
require 'chef/encrypted_data_bag_item'
require 'chef/encrypted_data_bag_item/unsupported_encrypted_data_bag_item_format'
require 'chef/encrypted_data_bag_item/unacceptable_encrypted_data_bag_item_format'
@@ -121,8 +121,8 @@ class Chef::EncryptedDataBagItem
end
def for_decrypted_item
- FFI_Yajl::Parser.parse(decrypted_data)["json_wrapper"]
- rescue FFI_Yajl::ParseError
+ Chef::JSONCompat.parse(decrypted_data)["json_wrapper"]
+ rescue Chef::Exceptions::JSON::ParseError
# convert to a DecryptionFailure error because the most likely scenario
# here is that the decryption step was unsuccessful but returned bad
# data rather than raising an error.
diff --git a/lib/chef/environment.rb b/lib/chef/environment.rb
index 5c719ca285..3620ee0b7c 100644
--- a/lib/chef/environment.rb
+++ b/lib/chef/environment.rb
@@ -129,7 +129,7 @@ class Chef
end
def to_json(*a)
- to_hash.to_json(*a)
+ Chef::JSONCompat.to_json(to_hash, *a)
end
def update_from!(o)
diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb
index 9ea40f71f6..2e7a92ab6f 100644
--- a/lib/chef/exceptions.rb
+++ b/lib/chef/exceptions.rb
@@ -267,7 +267,7 @@ class Chef
"non_existent_cookbooks" => non_existent_cookbooks,
"cookbooks_with_no_versions" => cookbooks_with_no_matching_versions
}
- result.to_json(*a)
+ Chef::JSONCompat.to_json(result, *a)
end
end
@@ -302,7 +302,7 @@ class Chef
"non_existent_cookbooks" => non_existent_cookbooks,
"most_constrained_cookbooks" => most_constrained_cookbooks
}
- result.to_json(*a)
+ Chef::JSONCompat.to_json(result, *a)
end
end
@@ -337,5 +337,11 @@ class Chef
end
class BadProxyURI < RuntimeError; end
+
+ # Raised by Chef::JSONCompat
+ class JSON
+ class EncodeError < RuntimeError; end
+ class ParseError < RuntimeError; end
+ end
end
end
diff --git a/lib/chef/json_compat.rb b/lib/chef/json_compat.rb
index 2dbb607d9b..9db358b5b9 100644
--- a/lib/chef/json_compat.rb
+++ b/lib/chef/json_compat.rb
@@ -18,7 +18,9 @@
# Wrapper class for interacting with JSON.
require 'ffi_yajl'
-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
@@ -40,15 +42,24 @@ class Chef
class <<self
+ # API to use to avoid create_addtions
+ def parse(source, opts = {})
+ begin
+ FFI_Yajl::Parser.parse(source, opts)
+ rescue FFI_Yajl::ParseError => e
+ raise Chef::Exceptions::JSON::ParseError, e.message
+ end
+ end
+
# Just call the JSON gem's parse method with a modified :max_nesting field
def from_json(source, opts = {})
- obj = ::FFI_Yajl::Parser.parse(source)
+ obj = parse(source, opts)
# JSON gem requires top level object to be a Hash or Array (otherwise
# you get the "must contain two octets" error). Yajl doesn't impose the
# same limitation. For compatibility, we re-impose this condition.
unless obj.kind_of?(Hash) or obj.kind_of?(Array)
- raise JSON::ParserError, "Top level JSON object must be a Hash or Array. (actual: #{obj.class})"
+ raise Chef::Exceptions::JSON::ParseError, "Top level JSON object must be a Hash or Array. (actual: #{obj.class})"
end
# The old default in the json gem (which we are mimicing because we
@@ -66,17 +77,17 @@ class Chef
# to an instance of Chef classes if desired.
def map_to_rb_obj(json_obj)
case json_obj
- when Hash
- mapped_hash = map_hash_to_rb_obj(json_obj)
- if json_obj.has_key?(JSON_CLASS) && (class_to_inflate = class_for_json_class(json_obj[JSON_CLASS]))
- class_to_inflate.json_create(mapped_hash)
+ when Hash
+ mapped_hash = map_hash_to_rb_obj(json_obj)
+ if json_obj.has_key?(JSON_CLASS) && (class_to_inflate = class_for_json_class(json_obj[JSON_CLASS]))
+ class_to_inflate.json_create(mapped_hash)
+ else
+ mapped_hash
+ end
+ when Array
+ json_obj.map {|e| map_to_rb_obj(e) }
else
- mapped_hash
- end
- when Array
- json_obj.map {|e| map_to_rb_obj(e) }
- else
- json_obj
+ json_obj
end
end
@@ -88,52 +99,60 @@ class Chef
end
def to_json(obj, opts = nil)
- obj.to_json(opts)
+ begin
+ FFI_Yajl::Encoder.encode(obj, opts)
+ rescue FFI_Yajl::EncodeError => e
+ raise Chef::Exceptions::JSON::EncodeError, e.message
+ end
end
def to_json_pretty(obj, opts = nil)
- ::JSON.pretty_generate(obj, opts)
+ opts ||= {}
+ options_map = {}
+ options_map[:pretty] = true
+ options_map[:indent] = opts[:indent] if opts.has_key?(:indent)
+ to_json(obj, options_map).chomp
end
-
# Map +json_class+ to a Class object. We use a +case+ instead of a Hash
# assigned to a constant because otherwise this file could not be loaded
# until all the constants were defined, which means you'd have to load
# the world to get json, which would make knife very slow.
def class_for_json_class(json_class)
case json_class
- when CHEF_APICLIENT
- Chef::ApiClient
- when CHEF_CHECKSUM
- Chef::Checksum
- when CHEF_COOKBOOKVERSION
- Chef::CookbookVersion
- when CHEF_DATABAG
- Chef::DataBag
- when CHEF_DATABAGITEM
- Chef::DataBagItem
- when CHEF_ENVIRONMENT
- Chef::Environment
- when CHEF_NODE
- Chef::Node
- when CHEF_ROLE
- Chef::Role
- when CHEF_SANDBOX
- # a falsey return here will disable object inflation/"create
- # additions" in the caller. In Chef 11 this is correct, we just have
- # a dummy Chef::Sandbox class for compat with Chef 10 servers.
- false
- when CHEF_RESOURCE
- Chef::Resource
- when CHEF_RESOURCECOLLECTION
- Chef::ResourceCollection
- when /^Chef::Resource/
- Chef::Resource.find_subclass_by_name(json_class)
- else
- raise JSON::ParserError, "Unsupported `json_class` type '#{json_class}'"
+ when CHEF_APICLIENT
+ Chef::ApiClient
+ when CHEF_CHECKSUM
+ Chef::Checksum
+ when CHEF_COOKBOOKVERSION
+ Chef::CookbookVersion
+ when CHEF_DATABAG
+ Chef::DataBag
+ when CHEF_DATABAGITEM
+ Chef::DataBagItem
+ when CHEF_ENVIRONMENT
+ Chef::Environment
+ when CHEF_NODE
+ Chef::Node
+ when CHEF_ROLE
+ Chef::Role
+ when CHEF_SANDBOX
+ # a falsey return here will disable object inflation/"create
+ # additions" in the caller. In Chef 11 this is correct, we just have
+ # a dummy Chef::Sandbox class for compat with Chef 10 servers.
+ false
+ when CHEF_RESOURCE
+ Chef::Resource
+ when CHEF_RESOURCECOLLECTION
+ Chef::ResourceCollection
+ when /^Chef::Resource/
+ Chef::Resource.find_subclass_by_name(json_class)
+ else
+ raise Chef::Exceptions::JSON::ParseError, "Unsupported `json_class` type '#{json_class}'"
end
end
end
end
end
+
diff --git a/lib/chef/knife/bootstrap.rb b/lib/chef/knife/bootstrap.rb
index 46cacbd3e0..d3d45bad4b 100644
--- a/lib/chef/knife/bootstrap.rb
+++ b/lib/chef/knife/bootstrap.rb
@@ -126,7 +126,7 @@ class Chef
:short => "-j JSON_ATTRIBS",
:long => "--json-attributes",
:description => "A JSON string to be added to the first run of chef-client",
- :proc => lambda { |o| JSON.parse(o) },
+ :proc => lambda { |o| Chef::JSONCompat.parse(o) },
:default => {}
option :host_key_verify,
@@ -141,7 +141,7 @@ class Chef
:proc => Proc.new { |h|
Chef::Config[:knife][:hints] ||= Hash.new
name, path = h.split("=")
- Chef::Config[:knife][:hints][name] = path ? JSON.parse(::File.read(path)) : Hash.new }
+ Chef::Config[:knife][:hints][name] = path ? Chef::JSONCompat.parse(::File.read(path)) : Hash.new }
option :secret,
:short => "-s SECRET",
diff --git a/lib/chef/knife/bootstrap/archlinux-gems.erb b/lib/chef/knife/bootstrap/archlinux-gems.erb
index ab2aa7a7f1..35133e23e5 100644
--- a/lib/chef/knife/bootstrap/archlinux-gems.erb
+++ b/lib/chef/knife/bootstrap/archlinux-gems.erb
@@ -29,7 +29,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 -%>
@@ -56,7 +56,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/centos5-gems.erb b/lib/chef/knife/bootstrap/centos5-gems.erb
index 6aacc47179..30418eca2d 100644
--- a/lib/chef/knife/bootstrap/centos5-gems.erb
+++ b/lib/chef/knife/bootstrap/centos5-gems.erb
@@ -46,7 +46,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 -%>
@@ -56,7 +56,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-aix.erb b/lib/chef/knife/bootstrap/chef-aix.erb
index 59993b478a..3985415d73 100644
--- a/lib/chef/knife/bootstrap/chef-aix.erb
+++ b/lib/chef/knife/bootstrap/chef-aix.erb
@@ -42,7 +42,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 -%>
@@ -52,7 +52,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 c953a7e433..cffe7007e9 100644
--- a/lib/chef/knife/bootstrap/chef-full.erb
+++ b/lib/chef/knife/bootstrap/chef-full.erb
@@ -57,7 +57,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 -%>
@@ -67,7 +67,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/bootstrap/fedora13-gems.erb b/lib/chef/knife/bootstrap/fedora13-gems.erb
index 0aabc31085..431d2bdb00 100644
--- a/lib/chef/knife/bootstrap/fedora13-gems.erb
+++ b/lib/chef/knife/bootstrap/fedora13-gems.erb
@@ -28,7 +28,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 -%>
@@ -38,7 +38,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/ubuntu10.04-apt.erb b/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb
index 4549b94d2b..d95de60149 100644
--- a/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb
+++ b/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb
@@ -28,7 +28,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 -%>
@@ -47,7 +47,7 @@ echo 'https_proxy "knife_config[:bootstrap_proxy]"' >> /etc/chef/client.rb
<% end -%>
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/ubuntu10.04-gems.erb b/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb
index 62ff7c857e..8e41c8f059 100644
--- a/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb
+++ b/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb
@@ -32,7 +32,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 -%>
@@ -42,7 +42,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/ubuntu12.04-gems.erb b/lib/chef/knife/bootstrap/ubuntu12.04-gems.erb
index 8e9c6583d0..b6a5aee7e7 100644
--- a/lib/chef/knife/bootstrap/ubuntu12.04-gems.erb
+++ b/lib/chef/knife/bootstrap/ubuntu12.04-gems.erb
@@ -30,7 +30,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 -%>
@@ -40,7 +40,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/cookbook_site_download.rb b/lib/chef/knife/cookbook_site_download.rb
index 645b1728e6..de6e21d0d2 100644
--- a/lib/chef/knife/cookbook_site_download.rb
+++ b/lib/chef/knife/cookbook_site_download.rb
@@ -58,7 +58,7 @@ class Chef
private
def cookbooks_api_url
- 'http://cookbooks.opscode.com/api/v1/cookbooks'
+ 'https://supermarket.getchef.com/api/v1/cookbooks'
end
def current_cookbook_data
diff --git a/lib/chef/knife/cookbook_site_list.rb b/lib/chef/knife/cookbook_site_list.rb
index fe83b71388..6fcf7e6064 100644
--- a/lib/chef/knife/cookbook_site_list.rb
+++ b/lib/chef/knife/cookbook_site_list.rb
@@ -41,7 +41,7 @@ class Chef
end
def get_cookbook_list(items=10, start=0, cookbook_collection={})
- cookbooks_url = "http://cookbooks.opscode.com/api/v1/cookbooks?items=#{items}&start=#{start}"
+ cookbooks_url = "https://supermarket.getchef.com/api/v1/cookbooks?items=#{items}&start=#{start}"
cr = noauth_rest.get_rest(cookbooks_url)
cr["items"].each do |cookbook|
cookbook_collection[cookbook["cookbook_name"]] = cookbook
diff --git a/lib/chef/knife/cookbook_site_search.rb b/lib/chef/knife/cookbook_site_search.rb
index b636276cba..ec4d196ee3 100644
--- a/lib/chef/knife/cookbook_site_search.rb
+++ b/lib/chef/knife/cookbook_site_search.rb
@@ -29,7 +29,7 @@ class Chef
end
def search_cookbook(query, items=10, start=0, cookbook_collection={})
- cookbooks_url = "http://cookbooks.opscode.com/api/v1/search?q=#{query}&items=#{items}&start=#{start}"
+ cookbooks_url = "https://supermarket.getchef.com/api/v1/search?q=#{query}&items=#{items}&start=#{start}"
cr = noauth_rest.get_rest(cookbooks_url)
cr["items"].each do |cookbook|
cookbook_collection[cookbook["cookbook_name"]] = cookbook
diff --git a/lib/chef/knife/cookbook_site_share.rb b/lib/chef/knife/cookbook_site_share.rb
index 4dcce42d7f..eaa30ea743 100644
--- a/lib/chef/knife/cookbook_site_share.rb
+++ b/lib/chef/knife/cookbook_site_share.rb
@@ -85,9 +85,9 @@ class Chef
end
def do_upload(cookbook_filename, cookbook_category, user_id, user_secret_filename)
- uri = "http://cookbooks.opscode.com/api/v1/cookbooks"
+ uri = "https://supermarket.getchef.com/api/v1/cookbooks"
- category_string = { 'category'=>cookbook_category }.to_json
+ category_string = Chef::JSONCompat.to_json({ 'category'=>cookbook_category })
http_resp = Chef::CookbookSiteStreamingUploader.post(uri, user_id, user_secret_filename, {
:tarball => File.open(cookbook_filename),
diff --git a/lib/chef/knife/cookbook_site_show.rb b/lib/chef/knife/cookbook_site_show.rb
index d15098e915..c520c00621 100644
--- a/lib/chef/knife/cookbook_site_show.rb
+++ b/lib/chef/knife/cookbook_site_show.rb
@@ -31,14 +31,14 @@ class Chef
def get_cookbook_data
case @name_args.length
when 1
- noauth_rest.get_rest("http://cookbooks.opscode.com/api/v1/cookbooks/#{@name_args[0]}")
+ noauth_rest.get_rest("https://supermarket.getchef.com/api/v1/cookbooks/#{@name_args[0]}")
when 2
- noauth_rest.get_rest("http://cookbooks.opscode.com/api/v1/cookbooks/#{@name_args[0]}/versions/#{name_args[1].gsub('.', '_')}")
+ noauth_rest.get_rest("https://supermarket.getchef.com/api/v1/cookbooks/#{@name_args[0]}/versions/#{name_args[1].gsub('.', '_')}")
end
end
def get_cookbook_list(items=10, start=0, cookbook_collection={})
- cookbooks_url = "http://cookbooks.opscode.com/api/v1/cookbooks?items=#{items}&start=#{start}"
+ cookbooks_url = "https://supermarket.getchef.com/api/v1/cookbooks?items=#{items}&start=#{start}"
cr = noauth_rest.get_rest(cookbooks_url)
cr["items"].each do |cookbook|
cookbook_collection[cookbook["cookbook_name"]] = cookbook
diff --git a/lib/chef/knife/cookbook_site_unshare.rb b/lib/chef/knife/cookbook_site_unshare.rb
index a2828549a0..f095885f15 100644
--- a/lib/chef/knife/cookbook_site_unshare.rb
+++ b/lib/chef/knife/cookbook_site_unshare.rb
@@ -41,7 +41,7 @@ class Chef
confirm "Do you really want to unshare the cookbook #{@cookbook_name}"
begin
- rest.delete_rest "http://cookbooks.opscode.com/api/v1/cookbooks/#{@name_args[0]}"
+ rest.delete_rest "https://supermarket.getchef.com/api/v1/cookbooks/#{@name_args[0]}"
rescue Net::HTTPServerException => e
raise e unless e.message =~ /Forbidden/
ui.error "Forbidden: You must be the maintainer of #{@cookbook_name} to unshare it."
diff --git a/lib/chef/knife/deps.rb b/lib/chef/knife/deps.rb
index b2a39a0725..89fd42124f 100644
--- a/lib/chef/knife/deps.rb
+++ b/lib/chef/knife/deps.rb
@@ -9,6 +9,7 @@ class Chef
deps do
require 'chef/chef_fs/file_system'
+ require 'chef/json_compat'
require 'chef/run_list'
end
@@ -77,7 +78,7 @@ class Chef
return entry.chef_object.metadata.dependencies.keys.map { |cookbook| "/cookbooks/#{cookbook}" }
elsif entry.parent && entry.parent.path == '/nodes'
- node = JSON.parse(entry.read, :create_additions => false)
+ node = Chef::JSONCompat.parse(entry.read, :create_additions => false)
result = []
if node['chef_environment'] && node['chef_environment'] != '_default'
result << "/environments/#{node['chef_environment']}.json"
@@ -88,7 +89,7 @@ class Chef
result
elsif entry.parent && entry.parent.path == '/roles'
- role = JSON.parse(entry.read, :create_additions => false)
+ role = Chef::JSONCompat.parse(entry.read, :create_additions => false)
result = []
if role['run_list']
dependencies_from_runlist(role['run_list']).each do |dependency|
diff --git a/lib/chef/node.rb b/lib/chef/node.rb
index 17ec1d0f0a..261c4a3f10 100644
--- a/lib/chef/node.rb
+++ b/lib/chef/node.rb
@@ -416,7 +416,7 @@ class Chef
# Serialize this object as a hash
def to_json(*a)
- for_json.to_json(*a)
+ Chef::JSONCompat.to_json(for_json, *a)
end
def for_json
diff --git a/lib/chef/provider/deploy/revision.rb b/lib/chef/provider/deploy/revision.rb
index f1eb171cd7..89710088d1 100644
--- a/lib/chef/provider/deploy/revision.rb
+++ b/lib/chef/provider/deploy/revision.rb
@@ -97,7 +97,7 @@ class Chef
end
def save_cache(cache)
- Chef::FileCache.store("revision-deploys/#{new_resource.name}", cache.to_json)
+ Chef::FileCache.store("revision-deploys/#{new_resource.name}", Chef::JSONCompat.to_json(cache))
cache
end
diff --git a/lib/chef/provider/dsc_script.rb b/lib/chef/provider/dsc_script.rb
index 5d7322842c..b88cb78fbe 100644
--- a/lib/chef/provider/dsc_script.rb
+++ b/lib/chef/provider/dsc_script.rb
@@ -46,9 +46,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
@@ -56,8 +58,26 @@ class Chef
true
end
+ def define_resource_requirements
+ requirements.assert(:run) do |a|
+ err = [
+ 'Could not find PowerShell DSC support 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)
@@ -77,9 +97,8 @@ class Chef
end
def get_augmented_configuration_flags(configuration_data_path)
- updated_flags = nil
+ updated_flags = @dsc_resource.flags.nil? ? {} : @dsc_resource.flags.dup
if configuration_data_path
- updated_flags = @dsc_resource.flags.nil? ? {} : @dsc_resource.flags.dup
Chef::Util::PathHelper.validate_path(configuration_data_path)
updated_flags[:configurationdata] = configuration_data_path
end
@@ -143,6 +162,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/env.rb b/lib/chef/provider/env.rb
index e857d74d68..600cac1e6b 100644
--- a/lib/chef/provider/env.rb
+++ b/lib/chef/provider/env.rb
@@ -58,20 +58,22 @@ class Chef
# ==== Returns
# <true>:: If a change is required
# <false>:: If a change is not required
- def compare_value
+ def requires_modify_or_create?
if @new_resource.delim
#e.g. check for existing value within PATH
- not @current_resource.value.split(@new_resource.delim).any? do |val|
- val == @new_resource.value
+ not new_values.all? do |val|
+ current_values.include? val
end
else
@new_resource.value != @current_resource.value
end
end
+ alias_method :compare_value, :requires_modify_or_create?
+
def action_create
if @key_exists
- if compare_value
+ if requires_modify_or_create?
modify_env
Chef::Log.info("#{@new_resource} altered")
@new_resource.updated_by_last_action(true)
@@ -91,13 +93,14 @@ class Chef
# after we removed the element.
def delete_element
return false unless @new_resource.delim #no delim: delete the key
- if compare_value
+ needs_delete = new_values.any? { |v| current_values.include?(v) }
+ if !needs_delete
Chef::Log.debug("#{@new_resource} element '#{@new_resource.value}' does not exist")
return true #do not delete the key
else
new_value =
- @current_resource.value.split(@new_resource.delim).select { |item|
- item != @new_resource.value
+ current_values.select { |item|
+ not new_values.include?(item)
}.join(@new_resource.delim)
if new_value.empty?
@@ -122,7 +125,7 @@ class Chef
def action_modify
if @key_exists
- if compare_value
+ if requires_modify_or_create?
modify_env
Chef::Log.info("#{@new_resource} modified")
@new_resource.updated_by_last_action(true)
@@ -142,11 +145,23 @@ class Chef
def modify_env
if @new_resource.delim
- #e.g. add to PATH
- @new_resource.value << @new_resource.delim << @current_resource.value
+ values = new_values.reject do |v|
+ current_values.include?(v)
+ end
+ @new_resource.value((values + [@current_resource.value]).join(@new_resource.delim))
end
create_env
end
+
+ # Returns the current values to split by delimiter
+ def current_values
+ @current_values ||= @current_resource.value.split(@new_resource.delim)
+ end
+
+ # Returns the new values to split by delimiter
+ def new_values
+ @new_values ||= @new_resource.value.split(@new_resource.delim)
+ end
end
end
end
diff --git a/lib/chef/provider/remote_file/cache_control_data.rb b/lib/chef/provider/remote_file/cache_control_data.rb
index 0add74f50a..95b2bc6a1b 100644
--- a/lib/chef/provider/remote_file/cache_control_data.rb
+++ b/lib/chef/provider/remote_file/cache_control_data.rb
@@ -140,7 +140,7 @@ class Chef
def load_data
Chef::JSONCompat.from_json(load_json_data)
- rescue Chef::Exceptions::FileNotFound, FFI_Yajl::ParseError, JSON::ParserError
+ rescue Chef::Exceptions::FileNotFound, FFI_Yajl::ParseError, Chef::Exceptions::JSON::ParseError
false
end
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index f6283e4033..a112e3b463 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -544,7 +544,7 @@ F
# Serialize this object as a hash
def to_json(*a)
results = as_json
- results.to_json(*a)
+ Chef::JSONCompat.to_json(results, *a)
end
def to_hash
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_collection.rb b/lib/chef/resource_collection.rb
index a528a18aed..3097707a13 100644
--- a/lib/chef/resource_collection.rb
+++ b/lib/chef/resource_collection.rb
@@ -198,7 +198,7 @@ class Chef
'json_class' => self.class.name,
'instance_vars' => instance_vars
}
- results.to_json(*a)
+ Chef::JSONCompat.to_json(results, *a)
end
def self.json_create(o)
diff --git a/lib/chef/resource_reporter.rb b/lib/chef/resource_reporter.rb
index 046e4e82c6..a19f26125e 100644
--- a/lib/chef/resource_reporter.rb
+++ b/lib/chef/resource_reporter.rb
@@ -230,7 +230,7 @@ class Chef
resource_history_url = "reports/nodes/#{node_name}/runs/#{run_id}"
Chef::Log.info("Sending resource update report (run-id: #{run_id})")
Chef::Log.debug run_data.inspect
- compressed_data = encode_gzip(run_data.to_json)
+ compressed_data = encode_gzip(Chef::JSONCompat.to_json(run_data))
Chef::Log.debug("Sending compressed run data...")
# Since we're posting compressed data we can not directly call post_rest which expects JSON
reporting_url = @rest_client.create_url(resource_history_url)
@@ -273,7 +273,7 @@ class Chef
resource_record.for_json
end
run_data["status"] = @status
- run_data["run_list"] = @run_status.node.run_list.to_json
+ run_data["run_list"] = Chef::JSONCompat.to_json(@run_status.node.run_list)
run_data["total_res_count"] = @total_res_count.to_s
run_data["data"] = {}
run_data["start_time"] = start_time.to_s
@@ -283,7 +283,7 @@ class Chef
exception_data = {}
exception_data["class"] = exception.inspect
exception_data["message"] = exception.message
- exception_data["backtrace"] = exception.backtrace.to_json
+ exception_data["backtrace"] = Chef::JSONCompat.to_json(exception.backtrace)
exception_data["description"] = @error_descriptions
run_data["data"]["exception"] = exception_data
end
diff --git a/lib/chef/role.rb b/lib/chef/role.rb
index 57f3a2aa29..aeea873051 100644
--- a/lib/chef/role.rb
+++ b/lib/chef/role.rb
@@ -143,7 +143,7 @@ class Chef
# Serialize this object as a hash
def to_json(*a)
- to_hash.to_json(*a)
+ Chef::JSONCompat.to_json(to_hash, *a)
end
def update_from!(o)
diff --git a/lib/chef/run_list.rb b/lib/chef/run_list.rb
index 684c5e19fc..d0ba342e2c 100644
--- a/lib/chef/run_list.rb
+++ b/lib/chef/run_list.rb
@@ -86,7 +86,7 @@ class Chef
end
def to_json(*args)
- to_a.map { |item| item.to_s}.to_json(*args)
+ Chef::JSONCompat.to_json(to_a.map { |item| item.to_s}, *args)
end
def empty?
diff --git a/lib/chef/user.rb b/lib/chef/user.rb
index e2ef45dc5c..6569a97f00 100644
--- a/lib/chef/user.rb
+++ b/lib/chef/user.rb
@@ -73,7 +73,7 @@ class Chef
end
def to_json(*a)
- to_hash.to_json(*a)
+ Chef::JSONCompat.to_json(to_hash, *a)
end
def destroy
diff --git a/lib/chef/util/dsc/local_configuration_manager.rb b/lib/chef/util/dsc/local_configuration_manager.rb
index 4a56b6a397..f498a2bfea 100644
--- a/lib/chef/util/dsc/local_configuration_manager.rb
+++ b/lib/chef/util/dsc/local_configuration_manager.rb
@@ -29,7 +29,7 @@ class Chef::Util::DSC
def test_configuration(configuration_document)
status = run_configuration_cmdlet(configuration_document)
- handle_what_if_exception!(status.stderr) unless status.succeeded?
+ log_what_if_exception(status.stderr) unless status.succeeded?
configuration_update_required?(status.return_value)
end
@@ -78,18 +78,22 @@ $ProgressPreference = 'SilentlyContinue';start-dscconfiguration -path #{@configu
EOH
end
- def handle_what_if_exception!(what_if_exception_output)
- if what_if_exception_output.gsub(/\s+/, ' ') =~ /A parameter cannot be found that matches parameter name 'Whatif'/i
- # LCM returns an error if any of the resources do not support the opptional What-If
- Chef::Log::warn("Received error while testing configuration due to resource not supporting 'WhatIf'")
- elsif output_has_dsc_module_failure?(what_if_exception_output)
- Chef::Log::warn("Received error while testing configuration due to a module for an imported resource possibly not being fully installed:\n#{what_if_exception_output.gsub(/\s+/, ' ')}")
- else
- raise Chef::Exceptions::PowershellCmdletException, "Powershell Cmdlet failed: #{what_if_exception_output.gsub(/\s+/, ' ')}"
- end
+ def log_what_if_exception(what_if_exception_output)
+ if whatif_not_supported?(what_if_exception_output)
+ # LCM returns an error if any of the resources do not support the opptional What-If
+ Chef::Log::warn("Received error while testing configuration due to resource not supporting 'WhatIf'")
+ elsif dsc_module_import_failure?(what_if_exception_output)
+ Chef::Log::warn("Received error while testing configuration due to a module for an imported resource possibly not being fully installed:\n#{what_if_exception_output.gsub(/\s+/, ' ')}")
+ else
+ Chef::Log::warn("Received error while testing configuration:\n#{what_if_exception_output.gsub(/\s+/, ' ')}")
+ end
+ end
+
+ def whatif_not_supported?(what_if_exception_output)
+ !! (what_if_exception_output.gsub(/[\r\n]+/, '').gsub(/\s+/, ' ') =~ /A parameter cannot be found that matches parameter name 'Whatif'/i)
end
- def output_has_dsc_module_failure?(what_if_output)
+ def dsc_module_import_failure?(what_if_output)
!! (what_if_output =~ /\sCimException/ &&
what_if_output =~ /ProviderOperationExecutionFailure/ &&
what_if_output =~ /\smodule\s+is\s+installed/)
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/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/resource/dsc_script_spec.rb b/spec/functional/resource/dsc_script_spec.rb
index fa13296c02..a736949c6b 100644
--- a/spec/functional/resource/dsc_script_spec.rb
+++ b/spec/functional/resource/dsc_script_spec.rb
@@ -81,17 +81,28 @@ describe Chef::Resource::DscScript, :windows_powershell_dsc_only do
let(:test_registry_value) { 'Registration' }
let(:test_registry_data1) { 'LL927' }
let(:test_registry_data2) { 'LL928' }
- let(:dsc_code) { <<-EOH
+ let(:reg_key_name_param_name) { 'testregkeyname' }
+ let(:reg_key_value_param_name) { 'testregvaluename' }
+ let(:registry_embedded_parameters) { "$#{reg_key_name_param_name} = '#{test_registry_key}';$#{reg_key_value_param_name} = '#{test_registry_value}'"}
+ let(:dsc_reg_code) { <<-EOH
+ #{registry_embedded_parameters}
Registry "ChefRegKey"
{
- Key = '#{test_registry_key}'
- ValueName = '#{test_registry_value}'
+ Key = $#{reg_key_name_param_name}
+ ValueName = $#{reg_key_value_param_name}
ValueData = '#{test_registry_data}'
Ensure = 'Present'
}
EOH
}
+ let(:dsc_code) { dsc_reg_code }
+ let(:dsc_reg_script) { <<-EOH
+ param($testregkeyname, $testregvaluename)
+ #{dsc_reg_code}
+EOH
+ }
+
let(:dsc_user_prefix) { 'dsc' }
let(:dsc_user_suffix) { 'chefx' }
let(:dsc_user) {"#{dsc_user_prefix}_usr_#{dsc_user_suffix}" }
@@ -175,7 +186,7 @@ environment "whatsmydir"
Ensure = 'Present'
}
EOH
- }
+}
let(:dsc_config_name) {
dsc_test_resource_base.name
@@ -227,41 +238,79 @@ environment 'removethis'
EOH
removal_resource.run_action(:run)
end
- let(:dsc_code) { dsc_environment_config }
- it 'should not raise an exception if the cwd is not etc' do
- dsc_test_resource.cwd(dsc_environment_no_fail_not_etc_directory)
- expect {dsc_test_resource.run_action(:run)}.not_to raise_error
- end
- it 'should raise an exception if the cwd is etc' do
- dsc_test_resource.cwd(dsc_environment_fail_etc_directory)
- expect {dsc_test_resource.run_action(:run)}.to raise_error(Chef::Exceptions::PowershellCmdletException)
- begin
- dsc_test_resource.run_action(:run)
- rescue Chef::Exceptions::PowershellCmdletException => e
- expect(e.message).to match(exception_message_signature)
+ describe 'when the DSC configuration contains code that raises an exception if cwd has a specific value' do
+ let(:dsc_code) { dsc_environment_config }
+ it 'should not raise an exception if the cwd is not etc' do
+ dsc_test_resource.cwd(dsc_environment_no_fail_not_etc_directory)
+ expect {dsc_test_resource.run_action(:run)}.not_to raise_error
+ end
+
+ it 'should raise an exception if the cwd is etc' do
+ dsc_test_resource.cwd(dsc_environment_fail_etc_directory)
+ expect {dsc_test_resource.run_action(:run)}.to raise_error(Chef::Exceptions::PowershellCmdletException)
+ begin
+ dsc_test_resource.run_action(:run)
+ rescue Chef::Exceptions::PowershellCmdletException => e
+ expect(e.message).to match(exception_message_signature)
+ end
end
end
end
shared_examples_for 'a parameterized DSC configuration script' do
- context 'when specifying environment variables in the environment attribute' do
- let(:dsc_user_prefix_code) { dsc_user_prefix_env_code }
- let(:dsc_user_suffix_code) { dsc_user_suffix_env_code }
- it_behaves_like 'a dsc_script with configuration that uses environment variables'
+ let(:dsc_user_prefix_code) { dsc_user_prefix_env_code }
+ let(:dsc_user_suffix_code) { dsc_user_suffix_env_code }
+ it_behaves_like 'a dsc_script with configuration that uses environment variables'
+ end
+
+ shared_examples_for 'a dsc_script without configuration data that takes parameters' do
+ context 'when configuration data is not specified' do
+
+ before(:each) do
+ test_key_resource = Chef::Resource::RegistryKey.new(test_registry_key, dsc_test_run_context)
+ test_key_resource.recursive(true)
+ test_key_resource.run_action(:delete_key)
+ end
+
+ after(:each) do
+ test_key_resource = Chef::Resource::RegistryKey.new(test_registry_key, dsc_test_run_context)
+ test_key_resource.recursive(true)
+ test_key_resource.run_action(:delete_key)
+ end
+
+ let(:test_registry_data) { test_registry_data1 }
+ let(:dsc_parameterized_env_param_value) { "val" + Random::rand.to_s }
+
+ it 'should have a default value of nil for the configuration_data attribute' do
+ expect(dsc_test_resource.configuration_data).to eql(nil)
+ end
+
+ it 'should have a default value of nil for the configuration_data_path attribute' do
+ expect(dsc_test_resource.configuration_data_script).to eql(nil)
+ end
+
+ let(:dsc_test_resource) { dsc_resource_from_path }
+ let(:registry_embedded_parameters) { '' }
+ let(:dsc_code) { dsc_reg_script }
+
+ it 'should set a registry key according to parameters passed to the configuration' do
+ dsc_test_resource.configuration_name(config_name_value)
+ dsc_test_resource.flags({:"#{reg_key_name_param_name}" => test_registry_key, :"#{reg_key_value_param_name}" => test_registry_value})
+ expect(dsc_test_resource.registry_key_exists?(test_registry_key)).to eq(false)
+ dsc_test_resource.run_action(:run)
+ expect(dsc_test_resource.registry_key_exists?(test_registry_key)).to eq(true)
+ expect(dsc_test_resource.registry_value_exists?(test_registry_key, {:name => test_registry_value, :type => :string, :data => test_registry_data})).to eq(true)
+ end
end
end
shared_examples_for 'a dsc_script with configuration data' do
- context 'when using the configuration_data attribute' do
- let(:configuration_data_attribute) { 'configuration_data' }
- it_behaves_like 'a dsc_script with configuration data set via an attribute'
- end
+ let(:configuration_data_attribute) { 'configuration_data' }
+ it_behaves_like 'a dsc_script with configuration data set via an attribute'
- context 'when using the configuration_data_script attribute' do
- let(:configuration_data_attribute) { 'configuration_data_script' }
- it_behaves_like 'a dsc_script with configuration data set via an attribute'
- end
+ let(:configuration_data_attribute) { 'configuration_data_script' }
+ it_behaves_like 'a dsc_script with configuration data set via an attribute'
end
shared_examples_for 'a dsc_script with configuration data set via an attribute' do
@@ -282,33 +331,28 @@ EOH
end
shared_examples_for 'a dsc_script with configuration data that takes parameters' do
- context 'when script code takes parameters for configuration' do
- let(:dsc_user_code) { dsc_user_param_code }
- let(:config_param_section) { config_params }
- let(:config_flags) {{:"#{dsc_user_prefix_param_name}" => "#{dsc_user_prefix}", :"#{dsc_user_suffix_param_name}" => "#{dsc_user_suffix}"}}
- it 'does not directly contain the user name' do
- configuration_script_content = ::File.open(dsc_test_resource.command) do | file |
- file.read
- end
- expect(configuration_script_content.include?(dsc_user)).to be(false)
+ let(:dsc_user_code) { dsc_user_param_code }
+ let(:config_param_section) { config_params }
+ let(:config_flags) {{:"#{dsc_user_prefix_param_name}" => "#{dsc_user_prefix}", :"#{dsc_user_suffix_param_name}" => "#{dsc_user_suffix}"}}
+ it 'does not directly contain the user name' do
+ configuration_script_content = ::File.open(dsc_test_resource.command) do | file |
+ file.read
end
- it_behaves_like 'a dsc_script with configuration data'
+ expect(configuration_script_content.include?(dsc_user)).to be(false)
end
-
+ it_behaves_like 'a dsc_script with configuration data'
end
shared_examples_for 'a dsc_script with configuration data that uses environment variables' do
- context 'when script code uses environment variables' do
- let(:dsc_user_code) { dsc_user_env_code }
+ let(:dsc_user_code) { dsc_user_env_code }
- it 'does not directly contain the user name' do
- configuration_script_content = ::File.open(dsc_test_resource.command) do | file |
- file.read
- end
- expect(configuration_script_content.include?(dsc_user)).to be(false)
+ it 'does not directly contain the user name' do
+ configuration_script_content = ::File.open(dsc_test_resource.command) do | file |
+ file.read
end
- it_behaves_like 'a dsc_script with configuration data'
+ expect(configuration_script_content.include?(dsc_user)).to be(false)
end
+ it_behaves_like 'a dsc_script with configuration data'
end
context 'when supplying configuration through the configuration attribute' do
@@ -333,5 +377,6 @@ EOH
it_behaves_like 'a dsc_script with configuration data'
it_behaves_like 'a dsc_script with configuration data that uses environment variables'
it_behaves_like 'a dsc_script with configuration data that takes parameters'
+ it_behaves_like 'a dsc_script without configuration data that takes parameters'
end
end
diff --git a/spec/functional/resource/env_spec.rb b/spec/functional/resource/env_spec.rb
index 24fe5e1dff..cf77fef703 100755
--- a/spec/functional/resource/env_spec.rb
+++ b/spec/functional/resource/env_spec.rb
@@ -126,7 +126,8 @@ describe Chef::Resource::Env, :windows_only do
context 'when using PATH' do
let(:random_name) { Time.now.to_i }
let(:env_val) { "#{env_value_expandable}_#{random_name}"}
- let(:path_before) { test_resource.provider_for_action(test_resource.action).env_value('PATH') }
+ let!(:path_before) { test_resource.provider_for_action(test_resource.action).env_value('PATH') || '' }
+ let!(:env_path_before) { ENV['PATH'] }
it 'should expand PATH' do
path_before.should_not include(env_val)
@@ -142,9 +143,7 @@ describe Chef::Resource::Env, :windows_only do
test_resource.key_name('PATH')
test_resource.value(path_before)
test_resource.run_action(:create)
- if test_resource.provider_for_action(test_resource.action).env_value('PATH') != path_before
- raise 'Failed to cleanup after ourselves'
- end
+ ENV['PATH'] = env_path_before
end
end
diff --git a/spec/functional/util/powershell/cmdlet_spec.rb b/spec/functional/util/powershell/cmdlet_spec.rb
index 63d1ac09b5..ca142e66b6 100644
--- a/spec/functional/util/powershell/cmdlet_spec.rb
+++ b/spec/functional/util/powershell/cmdlet_spec.rb
@@ -16,7 +16,6 @@
# limitations under the License.
#
-require 'json'
require File.expand_path('../../../../spec_helper', __FILE__)
describe Chef::Util::Powershell::Cmdlet, :windows_only do
@@ -91,7 +90,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 e8a3b3dde5..e50d39317d 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
extend IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/chef_repo_path_spec.rb b/spec/integration/knife/chef_repo_path_spec.rb
index 72d2ffbf75..7d2e27a260 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
extend IntegrationSupport
include KnifeSupport
@@ -287,6 +287,7 @@ EOM
knife('show --local /clients/blah.json').should_succeed <<EOM
/clients/blah.json:
{
+
}
EOM
end
@@ -374,6 +375,7 @@ EOM
knife('show --local /environments/blah.json').should_succeed <<EOM
/environments/blah.json:
{
+
}
EOM
end
@@ -386,6 +388,7 @@ EOM
knife('show --local /nodes/blah.json').should_succeed <<EOM
/nodes/blah.json:
{
+
}
EOM
end
@@ -398,6 +401,7 @@ EOM
knife('show --local /roles/blah.json').should_succeed <<EOM
/roles/blah.json:
{
+
}
EOM
end
@@ -410,6 +414,7 @@ EOM
knife('show --local /users/blah.json').should_succeed <<EOM
/users/blah.json:
{
+
}
EOM
end
diff --git a/spec/integration/knife/chef_repository_file_system_spec.rb b/spec/integration/knife/chef_repository_file_system_spec.rb
index 68ca5f89f4..37f458ed68 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
extend IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/chefignore_spec.rb b/spec/integration/knife/chefignore_spec.rb
index 4c3d2fa3aa..05a9e83447 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
extend IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/common_options_spec.rb b/spec/integration/knife/common_options_spec.rb
index e6b90613e5..9abee507af 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
extend IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/cookbook_api_ipv6_spec.rb b/spec/integration/knife/cookbook_api_ipv6_spec.rb
index ad7d5e857f..596913b0ef 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
extend IntegrationSupport
include Chef::Mixin::ShellOut
diff --git a/spec/integration/knife/delete_spec.rb b/spec/integration/knife/delete_spec.rb
index 8d9b972ca4..88fb2d7aee 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
extend IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/deps_spec.rb b/spec/integration/knife/deps_spec.rb
index 7f434f844d..d8a4170175 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
extend IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/diff_spec.rb b/spec/integration/knife/diff_spec.rb
index 2e36f39c82..debd96dc43 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
extend IntegrationSupport
include KnifeSupport
@@ -275,7 +275,7 @@ EOM
when_the_repository 'has an environment with bad JSON' do
file 'environments/x.json', '{'
it 'knife diff reports an error and does a textual diff' do
- knife('diff /environments/x.json').should_succeed(/- "name": "x"/, :stderr => "WARN: Parse error reading #{path_to('environments/x.json')} as JSON: A JSON text must at least contain two octets!\n")
+ knife('diff /environments/x.json').should_succeed(/- "name": "x"/, :stderr => /WARN: Parse error reading #{path_to('environments/x.json')} as JSON: parse error: premature EOF\n/)
end
end
end
@@ -528,7 +528,7 @@ EOM
when_the_repository 'has an environment with bad JSON' do
file 'environments/x.json', '{'
it 'knife diff reports an error and does a textual diff' do
- knife('diff /environments/x.json').should_succeed(/- "name": "x"/, :stderr => "WARN: Parse error reading #{path_to('environments/x.json')} as JSON: A JSON text must at least contain two octets!\n")
+ knife('diff /environments/x.json').should_succeed(/- "name": "x"/, :stderr => /WARN: Parse error reading #{path_to('environments/x.json')} as JSON: parse error: premature EOF\n/)
end
end
end
diff --git a/spec/integration/knife/download_spec.rb b/spec/integration/knife/download_spec.rb
index f266b47b1b..484a93253b 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
extend IntegrationSupport
include KnifeSupport
@@ -496,7 +496,7 @@ EOM
when_the_repository 'has an environment with bad JSON' do
file 'environments/x.json', '{'
it 'knife download succeeds' do
- knife('download /environments/x.json').should_succeed "Updated /environments/x.json\n", :stderr => "WARN: Parse error reading #{path_to('environments/x.json')} as JSON: A JSON text must at least contain two octets!\n"
+ knife('download /environments/x.json').should_succeed "Updated /environments/x.json\n", :stderr => /WARN: Parse error reading #{path_to('environments/x.json')} as JSON: parse error: premature EOF\n/
knife('diff --name-status /environments/x.json').should_succeed ''
end
end
@@ -946,7 +946,7 @@ EOM
when_the_repository 'has an environment with bad JSON' do
file 'environments/x.json', '{'
it 'knife download succeeds' do
- knife('download /environments/x.json').should_succeed "Updated /environments/x.json\n", :stderr => "WARN: Parse error reading #{path_to('environments/x.json')} as JSON: A JSON text must at least contain two octets!\n"
+ knife('download /environments/x.json').should_succeed "Updated /environments/x.json\n", :stderr => /WARN: Parse error reading #{path_to('environments/x.json')} as JSON: parse error: premature EOF\n/
knife('diff --name-status /environments/x.json').should_succeed ''
end
end
diff --git a/spec/integration/knife/list_spec.rb b/spec/integration/knife/list_spec.rb
index b9e72c5573..a39060d5aa 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
extend IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/raw_spec.rb b/spec/integration/knife/raw_spec.rb
index 2a9b5d8904..c66073a7ce 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
extend IntegrationSupport
include KnifeSupport
include AppServerSupport
@@ -44,12 +44,16 @@ describe 'knife raw' do
"chef_type": "node",
"chef_environment": "_default",
"override": {
+
},
"normal": {
+
},
"default": {
+
},
"automatic": {
+
},
"run_list": [
@@ -70,13 +74,16 @@ EOM
"json_class": "Chef::Role",
"chef_type": "role",
"default_attributes": {
+
},
"override_attributes": {
+
},
"run_list": [
],
"env_run_lists": {
+
}
}
EOM
@@ -111,13 +118,16 @@ EOM
"json_class": "Chef::Role",
"chef_type": "role",
"default_attributes": {
+
},
"override_attributes": {
+
},
"run_list": [
],
"env_run_lists": {
+
}
}
EOM
diff --git a/spec/integration/knife/redirection_spec.rb b/spec/integration/knife/redirection_spec.rb
index ebfd40966e..732634a411 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
extend IntegrationSupport
include KnifeSupport
include AppServerSupport
diff --git a/spec/integration/knife/serve_spec.rb b/spec/integration/knife/serve_spec.rb
index 6f8d046518..6d1aef22e5 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
extend IntegrationSupport
include KnifeSupport
include AppServerSupport
diff --git a/spec/integration/knife/show_spec.rb b/spec/integration/knife/show_spec.rb
index 5b15110e41..06410e0232 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
extend IntegrationSupport
include KnifeSupport
diff --git a/spec/integration/knife/upload_spec.rb b/spec/integration/knife/upload_spec.rb
index 46b804205f..630653fbcf 100644
--- a/spec/integration/knife/upload_spec.rb
+++ b/spec/integration/knife/upload_spec.rb
@@ -20,7 +20,7 @@ require 'chef/knife/upload'
require 'chef/knife/diff'
require 'chef/knife/raw'
-describe 'knife upload' do
+describe 'knife upload', :workstation do
extend IntegrationSupport
include KnifeSupport
@@ -237,7 +237,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
@@ -256,7 +256,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'
@@ -528,8 +528,8 @@ EOM
when_the_repository 'has an environment with bad JSON' do
file 'environments/x.json', '{'
it 'knife upload tries and fails' do
- knife('upload /environments/x.json').should_fail "WARN: Parse error reading #{path_to('environments/x.json')} as JSON: A JSON text must at least contain two octets!\nERROR: /environments/x.json failed to write: Parse error reading JSON: A JSON text must at least contain two octets!\n"
- knife('diff --name-status /environments/x.json').should_succeed "M\t/environments/x.json\n", :stderr => "WARN: Parse error reading #{path_to('environments/x.json')} as JSON: A JSON text must at least contain two octets!\n"
+ knife('upload /environments/x.json').should_fail /WARN: Parse error reading #{path_to('environments/x.json')} as JSON: parse error: premature EOF\n.+ERROR: \/environments\/x.json failed to write: Parse error reading JSON: parse error: premature EOF\n/m
+ knife('diff --name-status /environments/x.json').should_succeed "M\t/environments/x.json\n", :stderr => /WARN: Parse error reading #{path_to('environments/x.json')} as JSON: parse error: premature EOF\n/
end
end
@@ -554,7 +554,7 @@ EOM
when_the_repository 'has an environment with bad JSON' do
file 'environments/x.json', '{'
it 'knife upload tries and fails' do
- knife('upload /environments/x.json').should_fail "ERROR: /environments failed to create_child: Parse error reading JSON creating child 'x.json': A JSON text must at least contain two octets!\n"
+ knife('upload /environments/x.json').should_fail /ERROR: \/environments failed to create_child: Parse error reading JSON creating child 'x.json': parse error: premature EOF\n/
knife('diff --name-status /environments/x.json').should_succeed "A\t/environments/x.json\n"
end
end
@@ -1007,8 +1007,8 @@ EOM
when_the_repository 'has an environment with bad JSON' do
file 'environments/x.json', '{'
it 'knife upload tries and fails' do
- knife('upload /environments/x.json').should_fail "WARN: Parse error reading #{path_to('environments/x.json')} as JSON: A JSON text must at least contain two octets!\nERROR: /environments/x.json failed to write: Parse error reading JSON: A JSON text must at least contain two octets!\n"
- knife('diff --name-status /environments/x.json').should_succeed "M\t/environments/x.json\n", :stderr => "WARN: Parse error reading #{path_to('environments/x.json')} as JSON: A JSON text must at least contain two octets!\n"
+ knife('upload /environments/x.json').should_fail /WARN: Parse error reading #{path_to('environments/x.json')} as JSON: parse error: premature EOF\n.+ERROR: \/environments\/x.json failed to write: Parse error reading JSON: parse error: premature EOF\n/m
+ knife('diff --name-status /environments/x.json').should_succeed "M\t/environments/x.json\n", :stderr => /WARN: Parse error reading #{path_to('environments/x.json')} as JSON: parse error: premature EOF\n/
end
end
@@ -1033,7 +1033,7 @@ EOM
when_the_repository 'has an environment with bad JSON' do
file 'environments/x.json', '{'
it 'knife upload tries and fails' do
- knife('upload /environments/x.json').should_fail "ERROR: /environments failed to create_child: Parse error reading JSON creating child 'x.json': A JSON text must at least contain two octets!\n"
+ knife('upload /environments/x.json').should_fail /ERROR: \/environments failed to create_child: Parse error reading JSON creating child 'x.json': parse error: premature EOF\n/
knife('diff --name-status /environments/x.json').should_succeed "A\t/environments/x.json\n"
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index e73010d2b5..c43a16cd99 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?
@@ -182,3 +185,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 abed4c2715..d262e58b48 100644
--- a/spec/support/shared/integration/integration_helper.rb
+++ b/spec/support/shared/integration/integration_helper.rb
@@ -21,7 +21,6 @@ require 'tmpdir'
require 'fileutils'
require 'chef/config'
require 'chef_zero/rspec'
-require 'json'
require 'support/shared/integration/knife_support'
require 'support/shared/integration/app_server_support'
require 'spec_helper'
@@ -69,7 +68,7 @@ module IntegrationSupport
File.open(filename, 'w') do |file|
raw = case contents
when Hash
- JSON.pretty_generate(contents)
+ Chef::JSONCompat.to_json_pretty(contents)
when Array
contents.join("\n")
else
diff --git a/spec/support/shared/shared_examples.rb b/spec/support/shared/shared_examples.rb
new file mode 100644
index 0000000000..ccdd8cf316
--- /dev/null
+++ b/spec/support/shared/shared_examples.rb
@@ -0,0 +1,10 @@
+# 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
+
+ it "should allow consumers to call #to_json or Chef::JSONCompat.to_json" do
+ expect(subject.to_json).to eq(Chef::JSONCompat.to_json(subject))
+ end
+
+end
diff --git a/spec/tiny_server.rb b/spec/tiny_server.rb
index 7e6ef3a809..848e2f1133 100644
--- a/spec/tiny_server.rb
+++ b/spec/tiny_server.rb
@@ -25,6 +25,7 @@ require 'singleton'
require 'chef/json_compat'
require 'open-uri'
require 'chef/config'
+require 'chef/json_compat'
module TinyServer
@@ -152,7 +153,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..14dcc60467 100644
--- a/spec/unit/api_client_spec.rb
+++ b/spec/unit/api_client_spec.rb
@@ -92,7 +92,7 @@ describe Chef::ApiClient do
before(:each) do
@client.name("black")
@client.public_key("crowes")
- @json = @client.to_json
+ @json = Chef::JSONCompat.to_json(@client)
end
it "serializes as a JSON object" do
@@ -117,7 +117,7 @@ describe Chef::ApiClient do
it "includes the private key when present" do
@client.private_key("monkeypants")
- @client.to_json.should include(%q{"private_key":"monkeypants"})
+ Chef::JSONCompat.to_json(@client).should include(%q{"private_key":"monkeypants"})
end
it "does not include the private key if not present" do
@@ -135,7 +135,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 c29521806a..66681b85ab 100644
--- a/spec/unit/config_fetcher_spec.rb
+++ b/spec/unit/config_fetcher_spec.rb
@@ -1,7 +1,7 @@
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/metadata_spec.rb b/spec/unit/cookbook/metadata_spec.rb
index 8e98610183..24c9a48b81 100644
--- a/spec/unit/cookbook/metadata_spec.rb
+++ b/spec/unit/cookbook/metadata_spec.rb
@@ -582,7 +582,7 @@ describe Chef::Cookbook::Metadata do
@meta.version "1.2.3"
end
- describe "serialize" do
+ describe "#to_json" do
before(:each) do
@serial = Chef::JSONCompat.from_json(@meta.to_json)
end
@@ -613,11 +613,15 @@ describe Chef::Cookbook::Metadata do
@serial[t].should == @meta.send(t.to_sym)
end
end
+
+ it "should produce the same output from to_json and Chef::JSONCompat" do
+ expect(@meta.to_json).to eq(Chef::JSONCompat.to_json(@meta))
+ end
end
- describe "deserialize" do
+ describe "::from_json" do
before(:each) do
- @deserial = Chef::Cookbook::Metadata.from_json(@meta.to_json)
+ @deserial = Chef::Cookbook::Metadata.from_json(Chef::JSONCompat.to_json(@meta))
end
it "should deserialize to a Chef::Cookbook::Metadata object" do
diff --git a/spec/unit/cookbook_loader_spec.rb b/spec/unit/cookbook_loader_spec.rb
index 4c21c124e0..2bcba07eb2 100644
--- a/spec/unit/cookbook_loader_spec.rb
+++ b/spec/unit/cookbook_loader_spec.rb
@@ -181,7 +181,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..ea36dcc6d8 100644
--- a/spec/unit/cookbook_version_spec.rb
+++ b/spec/unit/cookbook_version_spec.rb
@@ -420,6 +420,10 @@ describe Chef::CookbookVersion do
end
end
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:subject) { Chef::CookbookVersion.new("tatft", '/tmp/blah') }
+ end
+
end
end
diff --git a/spec/unit/data_bag_item_spec.rb b/spec/unit/data_bag_item_spec.rb
index ead0dadfa2..f28450ef72 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(:subject) { @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 4ac843c869..b1c4b0ea6f 100644
--- a/spec/unit/data_bag_spec.rb
+++ b/spec/unit/data_bag_spec.rb
@@ -58,7 +58,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
@@ -73,6 +73,10 @@ describe Chef::DataBag do
end
end
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:subject) { @data_bag }
+ end
+
end
describe "when saving" do
diff --git a/spec/unit/deprecation_spec.rb b/spec/unit/deprecation_spec.rb
index 8617cb3cb3..6a405c2bb6 100644
--- a/spec/unit/deprecation_spec.rb
+++ b/spec/unit/deprecation_spec.rb
@@ -46,7 +46,7 @@ describe Chef::Deprecation do
end
method_snapshot_file = File.join(CHEF_SPEC_DATA, "file-providers-method-snapshot-chef-11-4.json")
- method_snapshot = JSON.parse(File.open(method_snapshot_file).read())
+ method_snapshot = Chef::JSONCompat.parse(File.open(method_snapshot_file).read())
method_snapshot.each do |class_name, old_methods|
class_object = class_from_string(class_name)
diff --git a/spec/unit/encrypted_data_bag_item_spec.rb b/spec/unit/encrypted_data_bag_item_spec.rb
index 1e662a0b7c..998b493514 100644
--- a/spec/unit/encrypted_data_bag_item_spec.rb
+++ b/spec/unit/encrypted_data_bag_item_spec.rb
@@ -100,6 +100,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 2 (JSON+aes-256-cbc+hmac-sha256+random iv) encrypted value" do
let(:encrypted_value) do
@@ -112,6 +123,8 @@ describe Chef::EncryptedDataBagItem::Decryptor do
Base64.encode64(raw_hmac)
end
+ include_examples "decryption examples"
+
it "rejects the data if the hmac is wrong" do
encrypted_value["hmac"] = bogus_hmac
lambda { decryptor.for_decrypted_item }.should raise_error(Chef::EncryptedDataBagItem::DecryptionFailure)
@@ -134,13 +147,7 @@ describe Chef::EncryptedDataBagItem::Decryptor do
decryptor.should be_a_kind_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 0e230e46ed..bb4ece0a47 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(:subject) { @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
@@ -420,7 +424,7 @@ describe Chef::Environment do
"description" => "desc",
"chef_type" => "environment"
}
- IO.should_receive(:read).with(File.join(Chef::Config[:environment_path], 'foo.json')).and_return(JSON.dump(environment_hash))
+ IO.should_receive(:read).with(File.join(Chef::Config[:environment_path], 'foo.json')).and_return(Chef::JSONCompat.to_json(environment_hash))
environment = Chef::Environment.load('foo')
environment.should be_a_kind_of(Chef::Environment)
diff --git a/spec/unit/exceptions_spec.rb b/spec/unit/exceptions_spec.rb
index 3e7b1ba93f..c7bfc63e6b 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(:subject) { exception }
+ end
+ end
end
end
diff --git a/spec/unit/json_compat_spec.rb b/spec/unit/json_compat_spec.rb
index cce31b0c7c..2d10df874f 100644
--- a/spec/unit/json_compat_spec.rb
+++ b/spec/unit/json_compat_spec.rb
@@ -21,49 +21,90 @@ require 'chef/json_compat'
describe Chef::JSONCompat do
- describe "with JSON containing an existing class" do
- let(:json){'{"json_class": "Chef::Role"}'}
+ describe "#from_json with JSON containing an existing class" do
+ let(:json) { '{"json_class": "Chef::Role"}' }
+
it "returns an instance of the class instead of a Hash" do
- Chef::JSONCompat.from_json(json).class.should eq Chef::Role
+ expect(Chef::JSONCompat.from_json(json).class).to eq Chef::Role
+ end
+ end
+
+ describe "#from_json with JSON containing comments" do
+ let(:json) { %Q{{\n/* comment */\n// comment 2\n"json_class": "Chef::Role"}} }
+
+ it "returns an instance of the class instead of a Hash" do
+ expect(Chef::JSONCompat.from_json(json).class).to eq Chef::Role
+ end
+ end
+
+ describe "#parse with JSON containing comments" do
+ let(:json) { %Q{{\n/* comment */\n// comment 2\n"json_class": "Chef::Role"}} }
+
+ it "returns a Hash" do
+ expect(Chef::JSONCompat.parse(json).class).to eq Hash
end
end
describe 'with JSON containing "Chef::Sandbox" as a json_class value' do
require 'chef/sandbox' # Only needed for this test
- let(:json){'{"json_class": "Chef::Sandbox", "arbitrary": "data"}'}
+
+ let(:json) { '{"json_class": "Chef::Sandbox", "arbitrary": "data"}' }
+
it "returns a Hash, because Chef::Sandbox is a dummy class" do
- Chef::JSONCompat.from_json(json).should eq({"json_class" => "Chef::Sandbox", "arbitrary" => "data"})
+ expect(Chef::JSONCompat.from_json(json)).to eq({"json_class" => "Chef::Sandbox", "arbitrary" => "data"})
end
end
- describe "with a file with 300 or less nested entries" do
- before(:all) do
- @json = IO.read(File.join(CHEF_SPEC_DATA, 'big_json.json'))
- @hash = Chef::JSONCompat.from_json(@json)
+ describe "when pretty printing an object that defines #to_json" do
+ class Foo
+ def to_json(*a)
+ Chef::JSONCompat.to_json({'bar' => {'baz' => 5678}}, *a)
+ end
end
+ it "should work" do
+ f = Foo.new
+ expect(Chef::JSONCompat.to_json_pretty(f)).to eql("{\n \"bar\": {\n \"baz\": 5678\n }\n}\n")
+ end
+
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:subject) { Foo.new }
+ end
+ end
+
+ describe "with a file with 300 or less nested entries" do
+ let(:json) { IO.read(File.join(CHEF_SPEC_DATA, 'big_json.json')) }
+ let(:hash) { Chef::JSONCompat.from_json(json) }
+
describe "when a big json file is loaded" do
it "should create a Hash from the file" do
- @hash.should be_kind_of(Hash)
+ expect(hash).to be_kind_of(Hash)
end
+
it "should has 'test' as a 300th nested value" do
- @hash['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key'].should == 'test'
+ expect(hash['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']).to eq('test')
end
end
end
+
describe "with a file with more than 300 nested entries" do
- before(:all) do
- @json = IO.read(File.join(CHEF_SPEC_DATA, 'big_json_plus_one.json'))
- @hash = Chef::JSONCompat.from_json(@json, {:max_nesting => 301})
- end
+ let(:json) { IO.read(File.join(CHEF_SPEC_DATA, 'big_json_plus_one.json')) }
+ let(:hash) { Chef::JSONCompat.from_json(json, {:max_nesting => 301}) }
describe "when a big json file is loaded" do
it "should create a Hash from the file" do
- @hash.should be_kind_of(Hash)
+ expect(hash).to be_kind_of(Hash)
end
+
it "should has 'test' as a 301st nested value" do
- @hash['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key'].should == 'test'
+ expect(hash['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']['key']).to eq('test')
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_metadata_from_file_spec.rb b/spec/unit/knife/cookbook_metadata_from_file_spec.rb
index 68ab6740ab..3a1dd9b21e 100644
--- a/spec/unit/knife/cookbook_metadata_from_file_spec.rb
+++ b/spec/unit/knife/cookbook_metadata_from_file_spec.rb
@@ -27,7 +27,6 @@ describe Chef::Knife::CookbookMetadataFromFile do
@tgt = File.expand_path(File.join(CHEF_SPEC_DATA, "metadata", "quick_start", "metadata.json"))
@knife = Chef::Knife::CookbookMetadataFromFile.new
@knife.name_args = [ @src ]
- @knife.stub(:to_json_pretty).and_return(true)
@md = Chef::Cookbook::Metadata.new
Chef::Cookbook::Metadata.stub(:new).and_return(@md)
$stdout.stub(:write)
diff --git a/spec/unit/knife/cookbook_site_download_spec.rb b/spec/unit/knife/cookbook_site_download_spec.rb
index faf58f7bc7..1b0f9f53d3 100644
--- a/spec/unit/knife/cookbook_site_download_spec.rb
+++ b/spec/unit/knife/cookbook_site_download_spec.rb
@@ -26,7 +26,8 @@ describe Chef::Knife::CookbookSiteDownload do
@knife.name_args = ['apache2']
@noauth_rest = double('no auth rest')
@stdout = StringIO.new
- @cookbook_api_url = 'http://cookbooks.opscode.com/api/v1/cookbooks'
+ @stderr = StringIO.new
+ @cookbook_api_url = 'https://supermarket.getchef.com/api/v1/cookbooks'
@version = '1.0.2'
@version_us = @version.gsub '.', '_'
@current_data = { 'deprecated' => false,
diff --git a/spec/unit/knife/cookbook_site_share_spec.rb b/spec/unit/knife/cookbook_site_share_spec.rb
index 28b2a509fd..77dce9b175 100644
--- a/spec/unit/knife/cookbook_site_share_spec.rb
+++ b/spec/unit/knife/cookbook_site_share_spec.rb
@@ -108,16 +108,16 @@ describe Chef::Knife::CookbookSiteShare do
File.stub(:open).and_return(true)
end
- it 'should post the cookbook to "http://cookbooks.opscode.com"' do
- response_text = {:uri => 'http://cookbooks.opscode.com/cookbooks/cookbook_name'}.to_json
+ it 'should post the cookbook to "https://supermarket.getchef.com"' do
+ response_text = {:uri => 'https://supermarket.getchef.com/cookbooks/cookbook_name'}.to_json
@upload_response.stub(:body).and_return(response_text)
@upload_response.stub(:code).and_return(201)
- Chef::CookbookSiteStreamingUploader.should_receive(:post).with(/cookbooks\.opscode\.com/, anything(), anything(), anything())
+ Chef::CookbookSiteStreamingUploader.should_receive(:post).with(/supermarket\.getchef\.com/, anything(), anything(), anything())
@knife.run
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 +125,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 +133,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 9cabc59719..57c1934439 100644
--- a/spec/unit/knife/core/bootstrap_context_spec.rb
+++ b/spec/unit/knife/core/bootstrap_context_spec.rb
@@ -116,13 +116,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/data_bag_from_file_spec.rb b/spec/unit/knife/data_bag_from_file_spec.rb
index 8537045164..0e53a67619 100644
--- a/spec/unit/knife/data_bag_from_file_spec.rb
+++ b/spec/unit/knife/data_bag_from_file_spec.rb
@@ -21,7 +21,6 @@ require 'spec_helper'
require 'chef/data_bag_item'
require 'chef/encrypted_data_bag_item'
require 'tempfile'
-require 'json'
Chef::Knife::DataBagFromFile.load_deps
@@ -46,7 +45,7 @@ describe Chef::Knife::DataBagFromFile do
"greeting" => "hello",
"nested" => { "a1" => [1, 2, 3], "a2" => { "b1" => true }}
}
- @db_file.write(@plain_data.to_json)
+ @db_file.write(Chef::JSONCompat.to_json(@plain_data))
@db_file.flush
@knife.instance_variable_set(:@name_args, ['bag_name', @db_file.path])
end
diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb
index 21a978a9c9..ccecfca2f0 100644
--- a/spec/unit/node_spec.rb
+++ b/spec/unit/node_spec.rb
@@ -762,6 +762,10 @@ 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(:subject) { node.from_file(File.expand_path("nodes/test.example.com.rb", CHEF_SPEC_DATA)) }
+ end
end
describe "to_s" do
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/env/windows_spec.rb b/spec/unit/provider/env/windows_spec.rb
index 2ea137c1d9..84582d8b4d 100644
--- a/spec/unit/provider/env/windows_spec.rb
+++ b/spec/unit/provider/env/windows_spec.rb
@@ -53,7 +53,7 @@ describe Chef::Provider::Env::Windows, :windows_only do
end
it "should update the ruby ENV object when it updates the value" do
- provider.should_receive(:compare_value).and_return(true)
+ provider.should_receive(:requires_modify_or_create?).and_return(true)
new_resource.value("foobar")
provider.action_modify
expect(ENV['CHEF_WINDOWS_ENV_TEST']).to eql('foobar')
@@ -92,7 +92,7 @@ describe Chef::Provider::Env::Windows, :windows_only do
end
it "replaces Windows system variables" do
- provider.should_receive(:compare_value).and_return(true)
+ provider.should_receive(:requires_modify_or_create?).and_return(true)
provider.should_receive(:expand_path).with(system_root).and_return(system_root_value)
provider.action_modify
expect(ENV['PATH']).to eql(system_root_value)
diff --git a/spec/unit/provider/env_spec.rb b/spec/unit/provider/env_spec.rb
index 0bc5117e48..f8803f9bb6 100644
--- a/spec/unit/provider/env_spec.rb
+++ b/spec/unit/provider/env_spec.rb
@@ -88,20 +88,20 @@ describe Chef::Provider::Env do
it "should check to see if the values are the same if the key exists" do
@provider.key_exists = true
- @provider.should_receive(:compare_value).and_return(false)
+ @provider.should_receive(:requires_modify_or_create?).and_return(false)
@provider.action_create
end
it "should call modify_env if the key exists and values are not equal" do
@provider.key_exists = true
- @provider.stub(:compare_value).and_return(true)
+ @provider.stub(:requires_modify_or_create?).and_return(true)
@provider.should_receive(:modify_env).and_return(true)
@provider.action_create
end
it "should set the new_resources updated flag when it updates an existing value" do
@provider.key_exists = true
- @provider.stub(:compare_value).and_return(true)
+ @provider.stub(:requires_modify_or_create?).and_return(true)
@provider.stub(:modify_env).and_return(true)
@provider.action_create
@new_resource.should be_updated
@@ -147,20 +147,20 @@ describe Chef::Provider::Env do
end
it "should call modify_group if the key exists and values are not equal" do
- @provider.should_receive(:compare_value).and_return(true)
+ @provider.should_receive(:requires_modify_or_create?).and_return(true)
@provider.should_receive(:modify_env).and_return(true)
@provider.action_modify
end
it "should set the new resources updated flag to true if modify_env is called" do
- @provider.stub(:compare_value).and_return(true)
+ @provider.stub(:requires_modify_or_create?).and_return(true)
@provider.stub(:modify_env).and_return(true)
@provider.action_modify
@new_resource.should be_updated
end
it "should not call modify_env if the key exists but the values are equal" do
- @provider.should_receive(:compare_value).and_return(false)
+ @provider.should_receive(:requires_modify_or_create?).and_return(false)
@provider.should_not_receive(:modify_env)
@provider.action_modify
end
@@ -198,9 +198,31 @@ describe Chef::Provider::Env do
@provider.delete_element.should eql(true)
@new_resource.should be_updated
end
+
+ context "when new_resource's value contains the delimiter" do
+ it "should return false if all the elements are deleted" do
+ # This indicates that the entire key needs to be deleted
+ @new_resource.value("C:/foo/bin;C:/bar/bin")
+ @provider.delete_element.should eql(false)
+ @new_resource.should_not be_updated # This will be updated in action_delete
+ end
+
+ it "should return true if any, but not all, of the elements are deleted" do
+ @new_resource.value("C:/foo/bin;C:/notbaz/bin")
+ @provider.should_receive(:create_env)
+ @provider.delete_element.should eql(true)
+ @new_resource.should be_updated
+ end
+
+ it "should return true if none of the elements are deleted" do
+ @new_resource.value("C:/notfoo/bin;C:/notbaz/bin")
+ @provider.delete_element.should eql(true)
+ @new_resource.should_not be_updated
+ end
+ end
end
- describe "compare_value" do
+ describe "requires_modify_or_create?" do
before(:each) do
@new_resource.value("C:/bar")
@current_resource = @new_resource.clone
@@ -208,25 +230,68 @@ describe Chef::Provider::Env do
end
it "should return false if the values are equal" do
- @provider.compare_value.should be_false
+ @provider.requires_modify_or_create?.should be_false
end
it "should return true if the values not are equal" do
@new_resource.value("C:/elsewhere")
- @provider.compare_value.should be_true
+ @provider.requires_modify_or_create?.should be_true
end
it "should return false if the current value contains the element" do
@new_resource.delim(";")
@current_resource.value("C:/bar;C:/foo;C:/baz")
- @provider.compare_value.should be_false
+ @provider.requires_modify_or_create?.should be_false
end
it "should return true if the current value does not contain the element" do
@new_resource.delim(";")
@current_resource.value("C:/biz;C:/foo/bin;C:/baz")
- @provider.compare_value.should be_true
+ @provider.requires_modify_or_create?.should be_true
+ end
+
+ context "when new_resource's value contains the delimiter" do
+ it "should return false if all the current values are contained" do
+ @new_resource.value("C:/biz;C:/baz")
+ @new_resource.delim(";")
+ @current_resource.value("C:/biz;C:/foo/bin;C:/baz")
+ @provider.requires_modify_or_create?.should be_false
+ end
+
+ it "should return true if any of the new values are not contained" do
+ @new_resource.value("C:/biz;C:/baz;C:/bin")
+ @new_resource.delim(";")
+ @current_resource.value("C:/biz;C:/foo/bin;C:/baz")
+ @provider.requires_modify_or_create?.should be_true
+ end
+ end
+ end
+
+ describe "modify_env" do
+ before(:each) do
+ @provider.stub(:create_env).and_return(true)
+ @new_resource.delim ";"
+
+ @current_resource = Chef::Resource::Env.new("FOO")
+ @current_resource.value "C:/foo/bin"
+ @provider.current_resource = @current_resource
+ end
+
+ it "should not modify the variable passed to the resource" do
+ new_value = "C:/bar/bin"
+ passed_value = new_value.dup
+ @new_resource.value(passed_value)
+ @provider.modify_env
+ passed_value.should == new_value
+ end
+
+ it "should only add values not already contained when a delimiter is provided" do
+ @new_resource.value("C:/foo;C:/bar;C:/baz")
+ @new_resource.delim(";")
+ @current_resource.value("C:/foo/bar;C:/bar;C:/baz")
+ @provider.modify_env
+ @new_resource.value.should eq("C:/foo;C:/foo/bar;C:/bar;C:/baz")
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/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_collection_spec.rb b/spec/unit/resource_collection_spec.rb
index cf62f5ff40..cc9cc83923 100644
--- a/spec/unit/resource_collection_spec.rb
+++ b/spec/unit/resource_collection_spec.rb
@@ -245,12 +245,16 @@ 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(:subject) { @rc }
+ end
end
describe "self.from_json" do
it "should deserialize itself from json" 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 70941e4e82..d10f3ca27b 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(:subject) { @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 05ebf282db..42819cda21 100644
--- a/spec/unit/role_spec.rb
+++ b/spec/unit/role_spec.rb
@@ -215,6 +215,10 @@ describe Chef::Role do
end
end
+
+ include_examples "to_json equalivent to Chef::JSONCompat.to_json" do
+ let(:subject) { @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..d2f0e01811 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(:subject) { @run_list }
end
end
diff --git a/spec/unit/user_spec.rb b/spec/unit/user_spec.rb
index 08bde33d7b..055512444b 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(:subject) { @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
diff --git a/spec/unit/util/dsc/local_configuration_manager_spec.rb b/spec/unit/util/dsc/local_configuration_manager_spec.rb
index fb6664bd40..eb27e9e94e 100644
--- a/spec/unit/util/dsc/local_configuration_manager_spec.rb
+++ b/spec/unit/util/dsc/local_configuration_manager_spec.rb
@@ -32,7 +32,7 @@ EOH
}
let(:no_whatif_lcm_output) { <<-EOH
-Start-DscConfiguration : A parameter cannot be found that matches parameter name 'whatif'.
+Start-DscConfiguration : A parameter cannot be found\r\n that matches parameter name 'whatif'.
At line:1 char:123
+ run-somecommand -whatif
+ ~~~~~~~~
@@ -77,8 +77,13 @@ EOH
let(:lcm_standard_error) { no_whatif_lcm_output }
let(:lcm_cmdlet_success) { false }
+ it 'returns true when passed to #whatif_not_supported?' do
+ expect(lcm.send(:whatif_not_supported?, no_whatif_lcm_output)).to be_true
+ end
+
it 'should should return a (possibly empty) array of ResourceInfo instances' do
expect(Chef::Log).to receive(:warn)
+ expect(lcm).to receive(:whatif_not_supported?).and_call_original
test_configuration_result = nil
expect {test_configuration_result = lcm.test_configuration('config')}.not_to raise_error
expect(test_configuration_result.class).to be(Array)
@@ -92,7 +97,7 @@ EOH
it 'should log a warning if the message is formatted as expected when a resource import failure occurs' do
expect(Chef::Log).to receive(:warn)
- expect(lcm).to receive(:output_has_dsc_module_failure?).and_call_original
+ expect(lcm).to receive(:dsc_module_import_failure?).and_call_original
test_configuration_result = nil
expect {test_configuration_result = lcm.test_configuration('config')}.not_to raise_error
end
@@ -105,29 +110,29 @@ EOH
end
end
- context 'that fails due to an PowerShell cmdlet error that cannot be handled' do
+ context 'that fails due to an unknown PowerShell cmdlet error' do
let(:lcm_standard_output) { 'some output' }
let(:lcm_standard_error) { 'Abort, Retry, Fail?' }
let(:lcm_cmdlet_success) { false }
- it 'should raise a Chef::Exceptions::PowershellCmdletException' do
- expect(Chef::Log).not_to receive(:warn)
- expect(lcm).to receive(:output_has_dsc_module_failure?).and_call_original
- expect {lcm.test_configuration('config')}.to raise_error(Chef::Exceptions::PowershellCmdletException)
+ it 'should log a warning' do
+ expect(Chef::Log).to receive(:warn)
+ expect(lcm).to receive(:dsc_module_import_failure?).and_call_original
+ expect {lcm.test_configuration('config')}.not_to raise_error
end
end
end
it 'should identify a correctly formatted error message as a resource import failure' do
- expect(lcm.send(:output_has_dsc_module_failure?, dsc_resource_import_failure_output)).to be(true)
+ expect(lcm.send(:dsc_module_import_failure?, dsc_resource_import_failure_output)).to be(true)
end
it 'should not identify an incorrectly formatted error message as a resource import failure' do
- expect(lcm.send(:output_has_dsc_module_failure?, dsc_resource_import_failure_output.gsub('module', 'gibberish'))).to be(false)
+ expect(lcm.send(:dsc_module_import_failure?, dsc_resource_import_failure_output.gsub('module', 'gibberish'))).to be(false)
end
it 'should not identify a message without a CimException reference as a resource import failure' do
- expect(lcm.send(:output_has_dsc_module_failure?, dsc_resource_import_failure_output.gsub('CimException', 'ArgumentException'))).to be(false)
+ expect(lcm.send(:dsc_module_import_failure?, dsc_resource_import_failure_output.gsub('CimException', 'ArgumentException'))).to be(false)
end
end
end