chef 11.16.4 → 11.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +2 -2
  3. data/lib/chef/api_client.rb +1 -1
  4. data/lib/chef/chef_fs/chef_fs_data_store.rb +3 -2
  5. data/lib/chef/chef_fs/command_line.rb +3 -2
  6. data/lib/chef/chef_fs/data_handler/group_data_handler.rb +5 -1
  7. data/lib/chef/chef_fs/file_system/acl_entry.rb +2 -1
  8. data/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb +2 -1
  9. data/lib/chef/chef_fs/file_system/rest_list_dir.rb +3 -2
  10. data/lib/chef/chef_fs/file_system/rest_list_entry.rb +5 -4
  11. data/lib/chef/config_fetcher.rb +1 -1
  12. data/lib/chef/cookbook/cookbook_version_loader.rb +4 -4
  13. data/lib/chef/cookbook/metadata.rb +1 -1
  14. data/lib/chef/cookbook_version.rb +2 -2
  15. data/lib/chef/data_bag.rb +1 -1
  16. data/lib/chef/data_bag_item.rb +1 -1
  17. data/lib/chef/encrypted_data_bag_item/decryptor.rb +3 -3
  18. data/lib/chef/environment.rb +1 -1
  19. data/lib/chef/exceptions.rb +19 -2
  20. data/lib/chef/json_compat.rb +64 -45
  21. data/lib/chef/knife/bootstrap.rb +2 -2
  22. data/lib/chef/knife/bootstrap/archlinux-gems.erb +2 -2
  23. data/lib/chef/knife/bootstrap/centos5-gems.erb +2 -2
  24. data/lib/chef/knife/bootstrap/chef-aix.erb +2 -2
  25. data/lib/chef/knife/bootstrap/chef-full.erb +2 -2
  26. data/lib/chef/knife/bootstrap/fedora13-gems.erb +2 -2
  27. data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +2 -2
  28. data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +2 -2
  29. data/lib/chef/knife/bootstrap/ubuntu12.04-gems.erb +2 -2
  30. data/lib/chef/knife/cookbook_site_download.rb +1 -1
  31. data/lib/chef/knife/cookbook_site_install.rb +34 -10
  32. data/lib/chef/knife/cookbook_site_list.rb +1 -1
  33. data/lib/chef/knife/cookbook_site_search.rb +1 -1
  34. data/lib/chef/knife/cookbook_site_share.rb +2 -2
  35. data/lib/chef/knife/cookbook_site_show.rb +3 -3
  36. data/lib/chef/knife/cookbook_site_unshare.rb +1 -1
  37. data/lib/chef/knife/core/subcommand_loader.rb +24 -0
  38. data/lib/chef/knife/deps.rb +3 -2
  39. data/lib/chef/node.rb +1 -1
  40. data/lib/chef/provider/deploy/revision.rb +1 -1
  41. data/lib/chef/provider/dsc_script.rb +32 -5
  42. data/lib/chef/provider/env.rb +25 -10
  43. data/lib/chef/provider/remote_file/cache_control_data.rb +1 -1
  44. data/lib/chef/resource.rb +1 -1
  45. data/lib/chef/resource/dsc_script.rb +2 -16
  46. data/lib/chef/resource_collection.rb +1 -1
  47. data/lib/chef/resource_reporter.rb +3 -3
  48. data/lib/chef/role.rb +1 -1
  49. data/lib/chef/run_list.rb +1 -1
  50. data/lib/chef/user.rb +1 -1
  51. data/lib/chef/util/dsc/local_configuration_manager.rb +15 -11
  52. data/lib/chef/util/powershell/cmdlet_result.rb +2 -2
  53. data/lib/chef/version.rb +1 -2
  54. data/spec/data/bootstrap/test-hints.erb +1 -1
  55. data/spec/data/bootstrap/test.erb +1 -1
  56. data/spec/functional/knife/cookbook_delete_spec.rb +3 -3
  57. data/spec/functional/knife/exec_spec.rb +1 -1
  58. data/spec/functional/resource/dsc_script_spec.rb +92 -47
  59. data/spec/functional/resource/env_spec.rb +3 -4
  60. data/spec/functional/util/powershell/cmdlet_spec.rb +1 -2
  61. data/spec/integration/knife/chef_fs_data_store_spec.rb +1 -1
  62. data/spec/integration/knife/chef_repo_path_spec.rb +6 -1
  63. data/spec/integration/knife/chef_repository_file_system_spec.rb +1 -1
  64. data/spec/integration/knife/chefignore_spec.rb +1 -1
  65. data/spec/integration/knife/common_options_spec.rb +1 -1
  66. data/spec/integration/knife/cookbook_api_ipv6_spec.rb +1 -1
  67. data/spec/integration/knife/delete_spec.rb +1 -1
  68. data/spec/integration/knife/deps_spec.rb +1 -1
  69. data/spec/integration/knife/diff_spec.rb +3 -3
  70. data/spec/integration/knife/download_spec.rb +3 -3
  71. data/spec/integration/knife/list_spec.rb +1 -1
  72. data/spec/integration/knife/raw_spec.rb +11 -1
  73. data/spec/integration/knife/redirection_spec.rb +1 -1
  74. data/spec/integration/knife/serve_spec.rb +1 -1
  75. data/spec/integration/knife/show_spec.rb +1 -1
  76. data/spec/integration/knife/upload_spec.rb +9 -9
  77. data/spec/spec_helper.rb +6 -0
  78. data/spec/support/shared/integration/integration_helper.rb +1 -2
  79. data/spec/support/shared/shared_examples.rb +10 -0
  80. data/spec/tiny_server.rb +2 -1
  81. data/spec/unit/api_client_spec.rb +3 -3
  82. data/spec/unit/chef_fs/data_handler/group_handler_spec.rb +63 -0
  83. data/spec/unit/config_fetcher_spec.rb +1 -1
  84. data/spec/unit/cookbook/metadata_spec.rb +7 -3
  85. data/spec/unit/cookbook_loader_spec.rb +1 -1
  86. data/spec/unit/cookbook_version_spec.rb +4 -0
  87. data/spec/unit/data_bag_item_spec.rb +5 -1
  88. data/spec/unit/data_bag_spec.rb +5 -1
  89. data/spec/unit/deprecation_spec.rb +1 -1
  90. data/spec/unit/encrypted_data_bag_item_spec.rb +14 -7
  91. data/spec/unit/environment_spec.rb +7 -3
  92. data/spec/unit/exceptions_spec.rb +6 -0
  93. data/spec/unit/json_compat_spec.rb +58 -17
  94. data/spec/unit/knife/cookbook_metadata_from_file_spec.rb +0 -1
  95. data/spec/unit/knife/cookbook_site_download_spec.rb +2 -1
  96. data/spec/unit/knife/cookbook_site_install_spec.rb +161 -116
  97. data/spec/unit/knife/cookbook_site_share_spec.rb +6 -6
  98. data/spec/unit/knife/core/bootstrap_context_spec.rb +2 -2
  99. data/spec/unit/knife/core/subcommand_loader_spec.rb +66 -1
  100. data/spec/unit/knife/data_bag_from_file_spec.rb +1 -2
  101. data/spec/unit/node_spec.rb +4 -0
  102. data/spec/unit/provider/dsc_script_spec.rb +134 -105
  103. data/spec/unit/provider/env/windows_spec.rb +2 -2
  104. data/spec/unit/provider/env_spec.rb +76 -11
  105. data/spec/unit/provider/remote_file/cache_control_data_spec.rb +1 -1
  106. data/spec/unit/resource/dsc_script_spec.rb +0 -29
  107. data/spec/unit/resource_collection_spec.rb +5 -1
  108. data/spec/unit/resource_reporter_spec.rb +3 -3
  109. data/spec/unit/resource_spec.rb +5 -1
  110. data/spec/unit/role_spec.rb +4 -0
  111. data/spec/unit/run_list_spec.rb +5 -1
  112. data/spec/unit/user_spec.rb +5 -1
  113. data/spec/unit/util/dsc/local_configuration_manager_spec.rb +15 -10
  114. metadata +11 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e2baecdd27415e458334b145590c6679023dd890
4
- data.tar.gz: c0eea714604dad7549a052fa6b5f7f92e2d69719
3
+ metadata.gz: 5488cfa9cadb8915b16300d713c7e9fa84280a9b
4
+ data.tar.gz: 2e972fcb90079442701054cc60e32f4702aaa622
5
5
  SHA512:
6
- metadata.gz: 3e980d795b418fe8f8307b57beee2fe8db0ba6a7ee1b32bf85186c1c38e101479c54b9bba2629a10f3f1575289abad80cde84f85a0c20ad02ee874dc342f1e87
7
- data.tar.gz: 40e039ba23e69e2f179defe5c72bbd4478fcc4a0fda5d16b64f0a5338226303af57855075013d720c487fdec73ad0604293efee314067761e58dcfca15b41124
6
+ metadata.gz: f4b29699fee5b775cb9f6da9dbd0bc431fef26da46da9d3bf3dddd1678039a337da941820992a5821fef270b96eb961ce2ecae726763f5e073c034270c25d6b7
7
+ data.tar.gz: 09699de226ec45815de423131cff4f006ec7ab8b05ea7abdd8da6b3ad9103bf7de4c0c08c898119152d5afdaf1902907a822dcfc9844ae8a027106383d554631
data/Rakefile CHANGED
@@ -41,8 +41,8 @@ end
41
41
 
42
42
  desc "Build it, tag it and ship it"
43
43
  task :ship => :gem do
44
- sh("git tag #{Chef::VERSION}")
45
- sh("git push opscode --tags")
44
+ #sh("git tag #{Chef::VERSION}")
45
+ #sh("git push opscode --tags")
46
46
  Dir[File.expand_path("../pkg/*.gem", __FILE__)].reverse.each do |built_gem|
47
47
  sh("gem push #{built_gem}")
48
48
  end
@@ -121,7 +121,7 @@ class Chef
121
121
  #
122
122
  # @return [String] the JSON string.
123
123
  def to_json(*a)
124
- to_hash.to_json(*a)
124
+ Chef::JSONCompat.to_json(to_hash, *a)
125
125
  end
126
126
 
127
127
  def self.json_create(o)
@@ -23,6 +23,7 @@ require 'chef/chef_fs/file_pattern'
23
23
  require 'chef/chef_fs/file_system'
24
24
  require 'chef/chef_fs/file_system/not_found_error'
25
25
  require 'chef/chef_fs/file_system/memory_root'
26
+ require 'chef/json_compat'
26
27
  require 'fileutils'
27
28
 
28
29
  class Chef
@@ -114,7 +115,7 @@ class Chef
114
115
  end
115
116
  end
116
117
  end
117
- JSON.pretty_generate(result)
118
+ Chef::JSONCompat.to_json_pretty(result)
118
119
 
119
120
  else
120
121
  begin
@@ -269,7 +270,7 @@ class Chef
269
270
 
270
271
  # Create a little Chef::ChefFS memory filesystem with the data
271
272
  cookbook_fs = Chef::ChefFS::FileSystem::MemoryRoot.new('uploading')
272
- cookbook = JSON.parse(data, :create_additions => false)
273
+ cookbook = Chef::JSONCompat.parse(data, :create_additions => false)
273
274
  cookbook.each_pair do |key, value|
274
275
  if value.is_a?(Array)
275
276
  value.each do |file|
@@ -19,6 +19,7 @@
19
19
  require 'chef/chef_fs/file_system'
20
20
  require 'chef/chef_fs/file_system/operation_failed_error'
21
21
  require 'chef/chef_fs/file_system/operation_not_allowed_error'
22
+ require 'chef/json_compat'
22
23
  require 'chef/util/diff'
23
24
 
24
25
  class Chef
@@ -251,9 +252,9 @@ class Chef
251
252
  end
252
253
 
253
254
  def self.canonicalize_json(json_text)
254
- parsed_json = JSON.parse(json_text, :create_additions => false)
255
+ parsed_json = Chef::JSONCompat.parse(json_text, :create_additions => false)
255
256
  sorted_json = sort_keys(parsed_json)
256
- JSON.pretty_generate(sorted_json)
257
+ Chef::JSONCompat.to_json_pretty(sorted_json)
257
258
  end
258
259
 
259
260
  def self.diff_text(old_path, new_path, old_value, new_value)
@@ -36,7 +36,11 @@ class Chef
36
36
  result
37
37
  end
38
38
 
39
- def preserve_key(key)
39
+ def normalize_for_post(group, entry)
40
+ normalize_for_put(group, entry)
41
+ end
42
+
43
+ def preserve_key?(key)
40
44
  return key == 'name'
41
45
  end
42
46
 
@@ -20,6 +20,7 @@ require 'chef/chef_fs/file_system/rest_list_entry'
20
20
  require 'chef/chef_fs/file_system/not_found_error'
21
21
  require 'chef/chef_fs/file_system/operation_not_allowed_error'
22
22
  require 'chef/chef_fs/file_system/operation_failed_error'
23
+ require 'chef/json_compat'
23
24
 
24
25
  class Chef
25
26
  module ChefFS
@@ -37,7 +38,7 @@ class Chef
37
38
 
38
39
  def write(file_contents)
39
40
  # ACL writes are fun.
40
- acls = data_handler.normalize(JSON.parse(file_contents, :create_additions => false), self)
41
+ acls = data_handler.normalize(Chef::JSONCompat.parse(file_contents, :create_additions => false), self)
41
42
  PERMISSIONS.each do |permission|
42
43
  begin
43
44
  rest.put("#{api_path}/#{permission}", { permission => acls[permission] })
@@ -19,6 +19,7 @@
19
19
 
20
20
  require 'chef/chef_fs/file_system/file_system_entry'
21
21
  require 'chef/chef_fs/file_system/not_found_error'
22
+ require 'chef/json_compat'
22
23
 
23
24
  class Chef
24
25
  module ChefFS
@@ -41,7 +42,7 @@ class Chef
41
42
 
42
43
  def chef_object
43
44
  begin
44
- return data_handler.chef_object(JSON.parse(read, :create_additions => false))
45
+ return data_handler.chef_object(Chef::JSONCompat.parse(read, :create_additions => false))
45
46
  rescue
46
47
  Chef::Log.error("Could not read #{path_for_printing} into a Chef object: #{$!}")
47
48
  end
@@ -19,6 +19,7 @@
19
19
  require 'chef/chef_fs/file_system/base_fs_dir'
20
20
  require 'chef/chef_fs/file_system/rest_list_entry'
21
21
  require 'chef/chef_fs/file_system/not_found_error'
22
+ require 'chef/json_compat'
22
23
 
23
24
  class Chef
24
25
  module ChefFS
@@ -61,8 +62,8 @@ class Chef
61
62
 
62
63
  def create_child(name, file_contents)
63
64
  begin
64
- object = JSON.parse(file_contents, :create_additions => false)
65
- rescue JSON::ParserError => e
65
+ object = Chef::JSONCompat.parse(file_contents, :create_additions => false)
66
+ rescue Chef::Exceptions::JSON::ParseError => e
66
67
  raise Chef::ChefFS::FileSystem::OperationFailedError.new(:create_child, self, e), "Parse error reading JSON creating child '#{name}': #{e}"
67
68
  end
68
69
 
@@ -19,6 +19,7 @@
19
19
  require 'chef/chef_fs/file_system/base_fs_object'
20
20
  require 'chef/chef_fs/file_system/not_found_error'
21
21
  require 'chef/chef_fs/file_system/operation_failed_error'
22
+ require 'chef/json_compat'
22
23
  require 'chef/role'
23
24
  require 'chef/node'
24
25
 
@@ -128,8 +129,8 @@ class Chef
128
129
  value = minimize_value(value)
129
130
  value_json = Chef::JSONCompat.to_json_pretty(value)
130
131
  begin
131
- other_value = JSON.parse(other_value_json, :create_additions => false)
132
- rescue JSON::ParserError => e
132
+ other_value = Chef::JSONCompat.parse(other_value_json, :create_additions => false)
133
+ rescue Chef::Exceptions::JSON::ParseError => e
133
134
  Chef::Log.warn("Parse error reading #{other.path_for_printing} as JSON: #{e}")
134
135
  return [ nil, value_json, other_value_json ]
135
136
  end
@@ -145,8 +146,8 @@ class Chef
145
146
 
146
147
  def write(file_contents)
147
148
  begin
148
- object = JSON.parse(file_contents, :create_additions => false)
149
- rescue JSON::ParserError => e
149
+ object = Chef::JSONCompat.parse(file_contents, :create_additions => false)
150
+ rescue Chef::Exceptions::JSON::ParseError => e
150
151
  raise Chef::ChefFS::FileSystem::OperationFailedError.new(:write, self, e), "Parse error reading JSON: #{e}"
151
152
  end
152
153
 
@@ -18,7 +18,7 @@ class Chef
18
18
  config_data = read_config
19
19
  begin
20
20
  Chef::JSONCompat.from_json(config_data)
21
- rescue FFI_Yajl::ParseError => error
21
+ rescue Chef::Exceptions::JSON::ParseError => error
22
22
  Chef::Application.fatal!("Could not parse the provided JSON file (#{config_location}): " + error.message, 2)
23
23
  end
24
24
  end
@@ -170,7 +170,7 @@ class Chef
170
170
  def apply_ruby_metadata(file)
171
171
  begin
172
172
  @metadata.from_file(file)
173
- rescue JSON::ParserError
173
+ rescue Chef::Exceptions::JSON::ParseError
174
174
  Chef::Log.error("Error evaluating metadata.rb for #@cookbook_name in " + file)
175
175
  raise
176
176
  end
@@ -179,7 +179,7 @@ class Chef
179
179
  def apply_json_metadata(file)
180
180
  begin
181
181
  @metadata.from_json(IO.read(file))
182
- rescue JSON::ParserError
182
+ rescue Chef::Exceptions::JSON::ParseError
183
183
  Chef::Log.error("Couldn't parse cookbook metadata JSON for #@cookbook_name in " + file)
184
184
  raise
185
185
  end
@@ -189,7 +189,7 @@ class Chef
189
189
  begin
190
190
  data = Chef::JSONCompat.from_json(IO.read(file), :create_additions => false)
191
191
  @metadata.from_hash(data['metadata'])
192
- rescue JSON::ParserError
192
+ rescue Chef::Exceptions::JSON::ParseError
193
193
  Chef::Log.error("Couldn't parse cookbook metadata JSON for #@cookbook_name in " + file)
194
194
  raise
195
195
  end
@@ -200,7 +200,7 @@ class Chef
200
200
  begin
201
201
  data = Chef::JSONCompat.from_json(IO.read(uploaded_cookbook_version_file), :create_additions => false)
202
202
  @frozen = data['frozen?']
203
- rescue JSON::ParserError
203
+ rescue Chef::Exceptions::JSON::ParseError
204
204
  Chef::Log.error("Couldn't parse cookbook metadata JSON for #@cookbook_name in #{uploaded_cookbook_version_file}")
205
205
  raise
206
206
  end
@@ -441,7 +441,7 @@ class Chef
441
441
  end
442
442
 
443
443
  def to_json(*a)
444
- self.to_hash.to_json(*a)
444
+ Chef::JSONCompat.to_json(self.to_hash, *a)
445
445
  end
446
446
 
447
447
  def self.from_hash(o)
@@ -459,7 +459,7 @@ class Chef
459
459
  def to_json(*a)
460
460
  result = self.to_hash
461
461
  result['json_class'] = self.class.name
462
- result.to_json(*a)
462
+ Chef::JSONCompat.to_json(result, *a)
463
463
  end
464
464
 
465
465
  def self.json_create(o)
@@ -469,7 +469,7 @@ class Chef
469
469
  cookbook_version.manifest = o
470
470
 
471
471
  # We don't need the following step when we decide to stop supporting deprecated operators in the metadata (e.g. <<, >>)
472
- cookbook_version.manifest["metadata"] = Chef::JSONCompat.from_json(cookbook_version.metadata.to_json)
472
+ cookbook_version.manifest["metadata"] = Chef::JSONCompat.from_json(Chef::JSONCompat.to_json(cookbook_version.metadata))
473
473
 
474
474
  cookbook_version.freeze_version if o["frozen?"]
475
475
  cookbook_version
@@ -63,7 +63,7 @@ class Chef
63
63
 
64
64
  # Serialize this object as a hash
65
65
  def to_json(*a)
66
- to_hash.to_json(*a)
66
+ Chef::JSONCompat.to_json(to_hash, *a)
67
67
  end
68
68
 
69
69
  def chef_server_rest
@@ -118,7 +118,7 @@ class Chef
118
118
  "data_bag" => self.data_bag,
119
119
  "raw_data" => self.raw_data
120
120
  }
121
- result.to_json(*a)
121
+ Chef::JSONCompat.to_json(result, *a)
122
122
  end
123
123
 
124
124
  def self.from_hash(h)
@@ -17,10 +17,10 @@
17
17
  #
18
18
 
19
19
  require 'yaml'
20
- require 'ffi_yajl'
21
20
  require 'openssl'
22
21
  require 'base64'
23
22
  require 'digest/sha2'
23
+ require 'chef/json_compat'
24
24
  require 'chef/encrypted_data_bag_item'
25
25
  require 'chef/encrypted_data_bag_item/unsupported_encrypted_data_bag_item_format'
26
26
  require 'chef/encrypted_data_bag_item/unacceptable_encrypted_data_bag_item_format'
@@ -121,8 +121,8 @@ class Chef::EncryptedDataBagItem
121
121
  end
122
122
 
123
123
  def for_decrypted_item
124
- FFI_Yajl::Parser.parse(decrypted_data)["json_wrapper"]
125
- rescue FFI_Yajl::ParseError
124
+ Chef::JSONCompat.parse(decrypted_data)["json_wrapper"]
125
+ rescue Chef::Exceptions::JSON::ParseError
126
126
  # convert to a DecryptionFailure error because the most likely scenario
127
127
  # here is that the decryption step was unsuccessful but returned bad
128
128
  # data rather than raising an error.
@@ -129,7 +129,7 @@ class Chef
129
129
  end
130
130
 
131
131
  def to_json(*a)
132
- to_hash.to_json(*a)
132
+ Chef::JSONCompat.to_json(to_hash, *a)
133
133
  end
134
134
 
135
135
  def update_from!(o)
@@ -134,6 +134,17 @@ class Chef
134
134
  # Version constraints are not allowed in chef-solo
135
135
  class IllegalVersionConstraint < NotImplementedError; end
136
136
 
137
+ class MetadataNotValid < StandardError; end
138
+ class MetadataNotFound < StandardError
139
+ attr_reader :install_path
140
+ attr_reader :cookbook_name
141
+ def initialize(install_path, cookbook_name)
142
+ @install_path = install_path
143
+ @cookbook_name = cookbook_name
144
+ super "No metadata.rb or metadata.json found for cookbook #{@cookbook_name} in #{@install_path}"
145
+ end
146
+ end
147
+
137
148
  # File operation attempted but no permissions to perform it
138
149
  class InsufficientPermissions < RuntimeError; end
139
150
 
@@ -267,7 +278,7 @@ class Chef
267
278
  "non_existent_cookbooks" => non_existent_cookbooks,
268
279
  "cookbooks_with_no_versions" => cookbooks_with_no_matching_versions
269
280
  }
270
- result.to_json(*a)
281
+ Chef::JSONCompat.to_json(result, *a)
271
282
  end
272
283
  end
273
284
 
@@ -302,7 +313,7 @@ class Chef
302
313
  "non_existent_cookbooks" => non_existent_cookbooks,
303
314
  "most_constrained_cookbooks" => most_constrained_cookbooks
304
315
  }
305
- result.to_json(*a)
316
+ Chef::JSONCompat.to_json(result, *a)
306
317
  end
307
318
  end
308
319
 
@@ -337,5 +348,11 @@ class Chef
337
348
  end
338
349
 
339
350
  class BadProxyURI < RuntimeError; end
351
+
352
+ # Raised by Chef::JSONCompat
353
+ class JSON
354
+ class EncodeError < RuntimeError; end
355
+ class ParseError < RuntimeError; end
356
+ end
340
357
  end
341
358
  end
@@ -18,7 +18,9 @@
18
18
  # Wrapper class for interacting with JSON.
19
19
 
20
20
  require 'ffi_yajl'
21
- require 'ffi_yajl/json_gem' # XXX: parts of chef require JSON gem's Hash#to_json monkeypatch
21
+ require 'chef/exceptions'
22
+ # We're requiring this to prevent breaking consumers using Hash.to_json
23
+ require 'json'
22
24
 
23
25
  class Chef
24
26
  class JSONCompat
@@ -40,15 +42,24 @@ class Chef
40
42
 
41
43
  class <<self
42
44
 
45
+ # API to use to avoid create_addtions
46
+ def parse(source, opts = {})
47
+ begin
48
+ FFI_Yajl::Parser.parse(source, opts)
49
+ rescue FFI_Yajl::ParseError => e
50
+ raise Chef::Exceptions::JSON::ParseError, e.message
51
+ end
52
+ end
53
+
43
54
  # Just call the JSON gem's parse method with a modified :max_nesting field
44
55
  def from_json(source, opts = {})
45
- obj = ::FFI_Yajl::Parser.parse(source)
56
+ obj = parse(source, opts)
46
57
 
47
58
  # JSON gem requires top level object to be a Hash or Array (otherwise
48
59
  # you get the "must contain two octets" error). Yajl doesn't impose the
49
60
  # same limitation. For compatibility, we re-impose this condition.
50
61
  unless obj.kind_of?(Hash) or obj.kind_of?(Array)
51
- raise JSON::ParserError, "Top level JSON object must be a Hash or Array. (actual: #{obj.class})"
62
+ raise Chef::Exceptions::JSON::ParseError, "Top level JSON object must be a Hash or Array. (actual: #{obj.class})"
52
63
  end
53
64
 
54
65
  # The old default in the json gem (which we are mimicing because we
@@ -66,17 +77,17 @@ class Chef
66
77
  # to an instance of Chef classes if desired.
67
78
  def map_to_rb_obj(json_obj)
68
79
  case json_obj
69
- when Hash
70
- mapped_hash = map_hash_to_rb_obj(json_obj)
71
- if json_obj.has_key?(JSON_CLASS) && (class_to_inflate = class_for_json_class(json_obj[JSON_CLASS]))
72
- class_to_inflate.json_create(mapped_hash)
80
+ when Hash
81
+ mapped_hash = map_hash_to_rb_obj(json_obj)
82
+ if json_obj.has_key?(JSON_CLASS) && (class_to_inflate = class_for_json_class(json_obj[JSON_CLASS]))
83
+ class_to_inflate.json_create(mapped_hash)
84
+ else
85
+ mapped_hash
86
+ end
87
+ when Array
88
+ json_obj.map {|e| map_to_rb_obj(e) }
73
89
  else
74
- mapped_hash
75
- end
76
- when Array
77
- json_obj.map {|e| map_to_rb_obj(e) }
78
- else
79
- json_obj
90
+ json_obj
80
91
  end
81
92
  end
82
93
 
@@ -88,52 +99,60 @@ class Chef
88
99
  end
89
100
 
90
101
  def to_json(obj, opts = nil)
91
- obj.to_json(opts)
102
+ begin
103
+ FFI_Yajl::Encoder.encode(obj, opts)
104
+ rescue FFI_Yajl::EncodeError => e
105
+ raise Chef::Exceptions::JSON::EncodeError, e.message
106
+ end
92
107
  end
93
108
 
94
109
  def to_json_pretty(obj, opts = nil)
95
- ::JSON.pretty_generate(obj, opts)
110
+ opts ||= {}
111
+ options_map = {}
112
+ options_map[:pretty] = true
113
+ options_map[:indent] = opts[:indent] if opts.has_key?(:indent)
114
+ to_json(obj, options_map).chomp
96
115
  end
97
116
 
98
-
99
117
  # Map +json_class+ to a Class object. We use a +case+ instead of a Hash
100
118
  # assigned to a constant because otherwise this file could not be loaded
101
119
  # until all the constants were defined, which means you'd have to load
102
120
  # the world to get json, which would make knife very slow.
103
121
  def class_for_json_class(json_class)
104
122
  case json_class
105
- when CHEF_APICLIENT
106
- Chef::ApiClient
107
- when CHEF_CHECKSUM
108
- Chef::Checksum
109
- when CHEF_COOKBOOKVERSION
110
- Chef::CookbookVersion
111
- when CHEF_DATABAG
112
- Chef::DataBag
113
- when CHEF_DATABAGITEM
114
- Chef::DataBagItem
115
- when CHEF_ENVIRONMENT
116
- Chef::Environment
117
- when CHEF_NODE
118
- Chef::Node
119
- when CHEF_ROLE
120
- Chef::Role
121
- when CHEF_SANDBOX
122
- # a falsey return here will disable object inflation/"create
123
- # additions" in the caller. In Chef 11 this is correct, we just have
124
- # a dummy Chef::Sandbox class for compat with Chef 10 servers.
125
- false
126
- when CHEF_RESOURCE
127
- Chef::Resource
128
- when CHEF_RESOURCECOLLECTION
129
- Chef::ResourceCollection
130
- when /^Chef::Resource/
131
- Chef::Resource.find_subclass_by_name(json_class)
132
- else
133
- raise JSON::ParserError, "Unsupported `json_class` type '#{json_class}'"
123
+ when CHEF_APICLIENT
124
+ Chef::ApiClient
125
+ when CHEF_CHECKSUM
126
+ Chef::Checksum
127
+ when CHEF_COOKBOOKVERSION
128
+ Chef::CookbookVersion
129
+ when CHEF_DATABAG
130
+ Chef::DataBag
131
+ when CHEF_DATABAGITEM
132
+ Chef::DataBagItem
133
+ when CHEF_ENVIRONMENT
134
+ Chef::Environment
135
+ when CHEF_NODE
136
+ Chef::Node
137
+ when CHEF_ROLE
138
+ Chef::Role
139
+ when CHEF_SANDBOX
140
+ # a falsey return here will disable object inflation/"create
141
+ # additions" in the caller. In Chef 11 this is correct, we just have
142
+ # a dummy Chef::Sandbox class for compat with Chef 10 servers.
143
+ false
144
+ when CHEF_RESOURCE
145
+ Chef::Resource
146
+ when CHEF_RESOURCECOLLECTION
147
+ Chef::ResourceCollection
148
+ when /^Chef::Resource/
149
+ Chef::Resource.find_subclass_by_name(json_class)
150
+ else
151
+ raise Chef::Exceptions::JSON::ParseError, "Unsupported `json_class` type '#{json_class}'"
134
152
  end
135
153
  end
136
154
 
137
155
  end
138
156
  end
139
157
  end
158
+