From 3f415b11dfb1c494a45a0a83d69196cd75924cf1 Mon Sep 17 00:00:00 2001 From: Lamont Granquist Date: Mon, 11 Aug 2014 17:36:52 -0700 Subject: remove JSON gem usage should fully convert to using ffi-yajl there are still issues with JSON gem monkeypatching interacting with chef-zero and the spec tests so we keep the requires here for the json gem and the ffi_yajl/json_gem here. when ohai and chef-zero are fixed, we an just require ffi_yajl. --- CHANGELOG.md | 1 + lib/chef/api_client.rb | 2 +- lib/chef/chef_fs/chef_fs_data_store.rb | 2 +- lib/chef/chef_fs/command_line.rb | 2 +- lib/chef/chef_fs/file_system/acl_entry.rb | 2 +- .../chef_repository_file_system_entry.rb | 6 ++--- lib/chef/chef_fs/file_system/rest_list_dir.rb | 4 +-- lib/chef/chef_fs/file_system/rest_list_entry.rb | 8 +++--- lib/chef/config_fetcher.rb | 2 +- lib/chef/cookbook/cookbook_version_loader.rb | 8 +++--- lib/chef/cookbook/metadata.rb | 4 +-- lib/chef/cookbook_version.rb | 5 ++-- lib/chef/data_bag.rb | 7 +++--- lib/chef/data_bag_item.rb | 12 ++++----- lib/chef/encrypted_data_bag_item/decryptor.rb | 7 +++--- lib/chef/environment.rb | 4 +-- lib/chef/exceptions.rb | 11 +++++--- lib/chef/handler/json_file.rb | 1 - lib/chef/json_compat.rb | 29 +++++++++++++++++----- lib/chef/knife/bootstrap.rb | 4 +-- lib/chef/knife/cookbook_site_share.rb | 2 +- lib/chef/knife/deps.rb | 5 ++-- lib/chef/node.rb | 3 +-- lib/chef/provider/deploy/revision.rb | 2 +- .../provider/remote_file/cache_control_data.rb | 2 +- lib/chef/resource.rb | 4 +-- lib/chef/resource_collection.rb | 10 +++++--- lib/chef/resource_reporter.rb | 6 ++--- lib/chef/role.rb | 2 +- lib/chef/run_list.rb | 9 ++++--- lib/chef/user.rb | 2 +- lib/chef/util/diff.rb | 3 +-- spec/support/shared/integration/knife_support.rb | 1 - spec/unit/deprecation_spec.rb | 3 +-- 34 files changed, 94 insertions(+), 81 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfefc0c597..e82557504e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased: +* chef/json_compat now throws its own exceptions not JSON gem exceptions * Fix a bug in the experimental Policyfile mode that caused errors when using templates. * Disable JSON encoding of request body when non-JSON content type is 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..b2435d8201 100644 --- a/lib/chef/chef_fs/chef_fs_data_store.rb +++ b/lib/chef/chef_fs/chef_fs_data_store.rb @@ -269,7 +269,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) 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..43e8b276e0 100644 --- a/lib/chef/chef_fs/command_line.rb +++ b/lib/chef/chef_fs/command_line.rb @@ -251,7 +251,7 @@ 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) sorted_json = sort_keys(parsed_json) JSON.pretty_generate(sorted_json) end diff --git a/lib/chef/chef_fs/file_system/acl_entry.rb b/lib/chef/chef_fs/file_system/acl_entry.rb index 8edc02d5c5..1bd03a6095 100644 --- a/lib/chef/chef_fs/file_system/acl_entry.rb +++ b/lib/chef/chef_fs/file_system/acl_entry.rb @@ -37,7 +37,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), 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..6ccdc2cf5f 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 @@ -41,7 +41,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)) rescue Chef::Log.error("Could not read #{path_for_printing} into a Chef object: #{$!}") end @@ -60,10 +60,10 @@ class Chef end def minimize(file_contents, entry) - object = JSONCompat.from_json(file_contents, :create_additions => false) + object = Chef::JSONCompat.from_json(file_contents) object = data_handler.normalize(object, entry) object = data_handler.minimize(object, entry) - JSONCompat.to_json_pretty(object) + Chef::JSONCompat.to_json_pretty(object) end def children 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..672fa444f1 100644 --- a/lib/chef/chef_fs/file_system/rest_list_dir.rb +++ b/lib/chef/chef_fs/file_system/rest_list_dir.rb @@ -61,8 +61,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) + 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..67252a6f2f 100644 --- a/lib/chef/chef_fs/file_system/rest_list_entry.rb +++ b/lib/chef/chef_fs/file_system/rest_list_entry.rb @@ -128,8 +128,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) + 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 +145,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) + 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 32574c75e2..8d3f8b84aa 100644 --- a/lib/chef/cookbook/metadata.rb +++ b/lib/chef/cookbook/metadata.rb @@ -24,6 +24,7 @@ require 'chef/mixin/params_validate' require 'chef/log' require 'chef/version_class' require 'chef/version_constraint' +require 'chef/json_compat' class Chef class Cookbook @@ -441,7 +442,7 @@ class Chef end def to_json(*a) - self.to_hash.to_json(*a) + Chef::JSONCompat.to_json(to_hash, *a) end def self.from_hash(o) @@ -651,6 +652,5 @@ INVALID end end - end end diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb index 778a6043bf..4482f778c1 100644 --- a/lib/chef/cookbook_version.rb +++ b/lib/chef/cookbook_version.rb @@ -405,7 +405,6 @@ class Chef records_by_pref[best_pref] end - # Given a node, segment and path (filename or directory name), # return the priority-ordered list of preference locations to # look. @@ -458,9 +457,9 @@ class Chef end def to_json(*a) - result = self.to_hash + result = to_hash result['json_class'] = self.class.name - result.to_json(*a) + Chef::JSONCompat.to_json(result, *a) end def self.json_create(o) diff --git a/lib/chef/data_bag.rb b/lib/chef/data_bag.rb index 1133aa3e73..99808d0609 100644 --- a/lib/chef/data_bag.rb +++ b/lib/chef/data_bag.rb @@ -54,16 +54,16 @@ class Chef def to_hash result = { - "name" => @name, + 'name' => @name, 'json_class' => self.class.name, - "chef_type" => "data_bag", + 'chef_type' => 'data_bag', } result end # 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 @@ -164,4 +164,3 @@ class Chef end end - diff --git a/lib/chef/data_bag_item.rb b/lib/chef/data_bag_item.rb index 07dd15a1dc..6f0ae65478 100644 --- a/lib/chef/data_bag_item.rb +++ b/lib/chef/data_bag_item.rb @@ -112,13 +112,13 @@ class Chef # Serialize this object as a hash def to_json(*a) result = { - "name" => self.object_name, + "name" => object_name, "json_class" => self.class.name, - "chef_type" => "data_bag_item", - "data_bag" => self.data_bag, - "raw_data" => self.raw_data + "chef_type" => "data_bag_item", + "data_bag" => data_bag, + "raw_data" => raw_data } - result.to_json(*a) + Chef::JSONCompat.to_json(result, *a) end def self.from_hash(h) @@ -210,5 +210,3 @@ class Chef end end - - diff --git a/lib/chef/encrypted_data_bag_item/decryptor.rb b/lib/chef/encrypted_data_bag_item/decryptor.rb index 0fe323870b..97a166b932 100644 --- a/lib/chef/encrypted_data_bag_item/decryptor.rb +++ b/lib/chef/encrypted_data_bag_item/decryptor.rb @@ -17,7 +17,7 @@ # require 'yaml' -require 'ffi_yajl' +require 'chef/json_compat' require 'openssl' require 'base64' require 'digest/sha2' @@ -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. @@ -197,7 +197,6 @@ class Chef::EncryptedDataBagItem assert_aead_requirements_met!(algorithm) end - # Returns the used decryption algorithm def algorithm AEAD_ALGORITHM diff --git a/lib/chef/environment.rb b/lib/chef/environment.rb index 5c719ca285..33dfb52403 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) @@ -140,7 +140,6 @@ class Chef self end - def update_attributes_from_params(params) unless params[:default_attributes].nil? || params[:default_attributes].size == 0 default_attributes(Chef::JSONCompat.from_json(params[:default_attributes])) @@ -213,7 +212,6 @@ class Chef end end - def self.json_create(o) environment = new environment.name(o["name"]) diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb index 26d9f612f1..bd6d887884 100644 --- a/lib/chef/exceptions.rb +++ b/lib/chef/exceptions.rb @@ -195,7 +195,6 @@ class Chef end end - end # Exception class for collecting multiple failures. Used when running # delayed notifications so that chef can process each delayed @@ -263,7 +262,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 @@ -298,7 +297,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 @@ -339,5 +338,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/handler/json_file.rb b/lib/chef/handler/json_file.rb index 3473db1838..405c91795e 100644 --- a/lib/chef/handler/json_file.rb +++ b/lib/chef/handler/json_file.rb @@ -58,7 +58,6 @@ class Chef end end - end end end diff --git a/lib/chef/json_compat.rb b/lib/chef/json_compat.rb index 0f182508b9..ddccfe5fcb 100644 --- a/lib/chef/json_compat.rb +++ b/lib/chef/json_compat.rb @@ -20,6 +20,7 @@ require 'ffi_yajl' require 'json' require 'ffi_yajl/json_gem' # XXX: parts of chef require JSON gem's Hash#to_json monkeypatch +require 'chef/exceptions' class Chef class JSONCompat @@ -41,15 +42,24 @@ class Chef class < 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 @@ -89,14 +99,21 @@ class Chef end def to_json(obj, opts = nil) - obj.to_json(opts) + begin + FFI_Yajl::Encoder.encode(obj, opts) + rescue FFI_Yajl::EndodeError => 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 @@ -131,7 +148,7 @@ class Chef when /^Chef::Resource/ Chef::Resource.find_subclass_by_name(json_class) else - raise JSON::ParserError, "Unsupported `json_class` type '#{json_class}'" + raise Chef::Exceptions::JSON::ParseError, "Unsupported `json_class` type '#{json_class}'" 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/cookbook_site_share.rb b/lib/chef/knife/cookbook_site_share.rb index 330f3cb229..b360cad728 100644 --- a/lib/chef/knife/cookbook_site_share.rb +++ b/lib/chef/knife/cookbook_site_share.rb @@ -87,7 +87,7 @@ class Chef def do_upload(cookbook_filename, cookbook_category, user_id, user_secret_filename) uri = "http://cookbooks.opscode.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/deps.rb b/lib/chef/knife/deps.rb index b2a39a0725..4b23468962 100644 --- a/lib/chef/knife/deps.rb +++ b/lib/chef/knife/deps.rb @@ -77,7 +77,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) result = [] if node['chef_environment'] && node['chef_environment'] != '_default' result << "/environments/#{node['chef_environment']}.json" @@ -88,7 +88,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) result = [] if role['run_list'] dependencies_from_runlist(role['run_list']).each do |dependency| @@ -138,4 +138,3 @@ class Chef end end end - diff --git a/lib/chef/node.rb b/lib/chef/node.rb index 17ec1d0f0a..327da67b1c 100644 --- a/lib/chef/node.rb +++ b/lib/chef/node.rb @@ -181,7 +181,6 @@ class Chef attributes.override end - def override_attrs attributes.override end @@ -416,7 +415,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/remote_file/cache_control_data.rb b/lib/chef/provider/remote_file/cache_control_data.rb index 8331f3d31a..75b2a5535a 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, Chef::Exceptions::JSON::ParseError false end diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb index 6c8e0434a0..6adf937f53 100644 --- a/lib/chef/resource.rb +++ b/lib/chef/resource.rb @@ -134,7 +134,6 @@ F extend Chef::Mixin::ConvertToClassName - if Module.method(:const_defined?).arity == 1 def self.strict_const_defined?(const) const_defined?(const) @@ -277,7 +276,6 @@ F end end - def updated=(true_or_false) Chef::Log.warn("Chef::Resource#updated=(true|false) is deprecated. Please call #updated_by_last_action(true|false) instead.") Chef::Log.warn("Called from:") @@ -544,7 +542,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_collection.rb b/lib/chef/resource_collection.rb index a528a18aed..2cbd61cb0c 100644 --- a/lib/chef/resource_collection.rb +++ b/lib/chef/resource_collection.rb @@ -158,7 +158,6 @@ class Chef # compat. alias_method :resources, :find - # Returns true if +query_object+ is a valid string for looking up a # resource, or raises InvalidResourceSpecification if not. # === Arguments @@ -189,16 +188,19 @@ class Chef end # Serialize this object as a hash - def to_json(*a) + def to_hash instance_vars = Hash.new self.instance_variables.each do |iv| instance_vars[iv] = self.instance_variable_get(iv) end - results = { + { 'json_class' => self.class.name, 'instance_vars' => instance_vars } - results.to_json(*a) + end + + def to_json(*a) + Chef::JSONCompat.to_json(to_hash, *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..01e32ffc98 100644 --- a/lib/chef/run_list.rb +++ b/lib/chef/run_list.rb @@ -85,8 +85,12 @@ class Chef @run_list_items.join(", ") end - def to_json(*args) - to_a.map { |item| item.to_s}.to_json(*args) + def for_json + to_a.map { |item| item.to_s } + end + + def to_json(*a) + Chef::JSONCompat.to_json(for_json, *a) end def empty? @@ -158,6 +162,5 @@ class Chef end end - end end 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/diff.rb b/lib/chef/util/diff.rb index 7bce52d874..3117484a71 100644 --- a/lib/chef/util/diff.rb +++ b/lib/chef/util/diff.rb @@ -82,7 +82,7 @@ class Chef end end end - + # produces a unified-output-format diff with 3 lines of context # ChefFS uses udiff() directly def udiff(old_file, new_file) @@ -185,4 +185,3 @@ class Chef end end end - diff --git a/spec/support/shared/integration/knife_support.rb b/spec/support/shared/integration/knife_support.rb index 036972e18e..fd12998152 100644 --- a/spec/support/shared/integration/knife_support.rb +++ b/spec/support/shared/integration/knife_support.rb @@ -63,7 +63,6 @@ module KnifeSupport Chef::Config[:verbosity] = ( DEBUG ? 2 : 0 ) instance.config[:config_file] = File.join(CHEF_SPEC_DATA, "null_config.rb") - # Configure chef with a (mostly) blank knife.rb # We set a global and then mutate it in our stub knife.rb so we can be # extra sure that we're not loading someone's real knife.rb and then diff --git a/spec/unit/deprecation_spec.rb b/spec/unit/deprecation_spec.rb index 8617cb3cb3..c5ab41fbab 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) @@ -83,4 +83,3 @@ describe Chef::Deprecation do end end - -- cgit v1.2.1