chef 12.0.0.alpha.0 → 12.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (207) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +3 -5
  3. data/lib/chef/api_client.rb +1 -1
  4. data/lib/chef/application.rb +16 -8
  5. data/lib/chef/chef_fs/chef_fs_data_store.rb +1 -1
  6. data/lib/chef/chef_fs/command_line.rb +1 -1
  7. data/lib/chef/chef_fs/file_system.rb +1 -1
  8. data/lib/chef/chef_fs/file_system/acl_entry.rb +1 -1
  9. data/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb +3 -3
  10. data/lib/chef/chef_fs/file_system/cookbook_file.rb +2 -2
  11. data/lib/chef/chef_fs/file_system/rest_list_dir.rb +2 -2
  12. data/lib/chef/chef_fs/file_system/rest_list_entry.rb +4 -4
  13. data/lib/chef/config.rb +6 -5
  14. data/lib/chef/config_fetcher.rb +1 -1
  15. data/lib/chef/cookbook/cookbook_version_loader.rb +126 -43
  16. data/lib/chef/cookbook/metadata.rb +102 -53
  17. data/lib/chef/cookbook/syntax_check.rb +1 -1
  18. data/lib/chef/cookbook_loader.rb +62 -14
  19. data/lib/chef/cookbook_site_streaming_uploader.rb +12 -1
  20. data/lib/chef/cookbook_version.rb +13 -4
  21. data/lib/chef/data_bag.rb +28 -15
  22. data/lib/chef/data_bag_item.rb +5 -7
  23. data/lib/chef/digester.rb +5 -9
  24. data/lib/chef/dsl/recipe.rb +14 -0
  25. data/lib/chef/encrypted_data_bag_item.rb +1 -0
  26. data/lib/chef/encrypted_data_bag_item/assertions.rb +57 -0
  27. data/lib/chef/encrypted_data_bag_item/decryptor.rb +52 -28
  28. data/lib/chef/encrypted_data_bag_item/encrypted_data_bag_item_assertions.rb +37 -0
  29. data/lib/chef/encrypted_data_bag_item/encryption_failure.rb +22 -0
  30. data/lib/chef/encrypted_data_bag_item/encryptor.rb +79 -8
  31. data/lib/chef/environment.rb +1 -3
  32. data/lib/chef/exceptions.rb +18 -3
  33. data/lib/chef/formatters/base.rb +7 -0
  34. data/lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb +1 -1
  35. data/lib/chef/handler/json_file.rb +0 -1
  36. data/lib/chef/http/json_output.rb +1 -1
  37. data/lib/chef/json_compat.rb +24 -6
  38. data/lib/chef/knife/bootstrap.rb +2 -2
  39. data/lib/chef/knife/client_delete.rb +1 -1
  40. data/lib/chef/knife/cookbook_site_download.rb +1 -1
  41. data/lib/chef/knife/cookbook_site_list.rb +1 -1
  42. data/lib/chef/knife/cookbook_site_search.rb +1 -1
  43. data/lib/chef/knife/cookbook_site_share.rb +2 -2
  44. data/lib/chef/knife/cookbook_site_show.rb +3 -3
  45. data/lib/chef/knife/cookbook_site_unshare.rb +1 -1
  46. data/lib/chef/knife/core/node_editor.rb +2 -3
  47. data/lib/chef/knife/core/ui.rb +2 -2
  48. data/lib/chef/knife/deps.rb +2 -3
  49. data/lib/chef/mixin/shell_out.rb +1 -1
  50. data/lib/chef/mixin/windows_architecture_helper.rb +1 -0
  51. data/lib/chef/node.rb +1 -2
  52. data/lib/chef/platform/provider_mapping.rb +33 -6
  53. data/lib/chef/provider.rb +0 -2
  54. data/lib/chef/provider/cookbook_file/content.rb +1 -1
  55. data/lib/chef/provider/cron.rb +11 -0
  56. data/lib/chef/provider/deploy.rb +3 -2
  57. data/lib/chef/provider/deploy/revision.rb +2 -2
  58. data/lib/chef/provider/env.rb +1 -1
  59. data/lib/chef/provider/env/windows.rb +5 -9
  60. data/lib/chef/provider/file.rb +84 -33
  61. data/lib/chef/provider/git.rb +2 -1
  62. data/lib/chef/provider/group/aix.rb +17 -2
  63. data/lib/chef/provider/group/dscl.rb +27 -9
  64. data/lib/chef/provider/group/pw.rb +8 -1
  65. data/lib/chef/provider/http_request.rb +4 -4
  66. data/lib/chef/provider/log.rb +4 -14
  67. data/lib/chef/provider/mount/mount.rb +2 -2
  68. data/lib/chef/provider/package/ips.rb +17 -23
  69. data/lib/chef/provider/package/paludis.rb +2 -2
  70. data/lib/chef/provider/package/rpm.rb +2 -2
  71. data/lib/chef/provider/package/rubygems.rb +2 -0
  72. data/lib/chef/provider/package/yum.rb +2 -0
  73. data/lib/chef/provider/package/zypper.rb +1 -1
  74. data/lib/chef/provider/remote_file/cache_control_data.rb +2 -2
  75. data/lib/chef/provider/service/windows.rb +87 -21
  76. data/lib/chef/provider/user/aix.rb +95 -0
  77. data/lib/chef/provider/user/dscl.rb +544 -156
  78. data/lib/chef/provider/user/useradd.rb +1 -0
  79. data/lib/chef/providers.rb +1 -0
  80. data/lib/chef/resource.rb +4 -3
  81. data/lib/chef/resource/freebsd_package.rb +10 -2
  82. data/lib/chef/resource/paludis_package.rb +1 -0
  83. data/lib/chef/resource/scm.rb +10 -0
  84. data/lib/chef/resource/user.rb +27 -0
  85. data/lib/chef/resource/windows_service.rb +53 -0
  86. data/lib/chef/resource_collection.rb +23 -12
  87. data/lib/chef/resource_reporter.rb +10 -10
  88. data/lib/chef/resources.rb +1 -0
  89. data/lib/chef/role.rb +3 -3
  90. data/lib/chef/run_list.rb +6 -3
  91. data/lib/chef/user.rb +1 -1
  92. data/lib/chef/util/diff.rb +1 -2
  93. data/lib/chef/version.rb +1 -1
  94. data/lib/chef/version_constraint.rb +4 -4
  95. data/spec/data/cookbooks/angrybash/metadata.rb +2 -0
  96. data/spec/data/cookbooks/apache2/metadata.rb +2 -0
  97. data/spec/data/cookbooks/borken/metadata.rb +2 -0
  98. data/spec/data/cookbooks/ignorken/metadata.rb +2 -0
  99. data/spec/data/cookbooks/java/metadata.rb +2 -0
  100. data/spec/data/cookbooks/name-mismatch-versionnumber/README.md +4 -0
  101. data/spec/data/cookbooks/name-mismatch-versionnumber/metadata.rb +8 -0
  102. data/spec/data/cookbooks/name-mismatch-versionnumber/recipes/default.rb +8 -0
  103. data/spec/data/cookbooks/openldap/files/default/remotedir/not_a_template.erb +2 -0
  104. data/spec/data/cookbooks/preseed/metadata.rb +2 -0
  105. data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/README.md +4 -0
  106. data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/metadata.rb +13 -0
  107. data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/recipes/default.rb +8 -0
  108. data/spec/data/invalid-metadata-chef-repo/invalid-metadata/README.md +4 -0
  109. data/spec/data/invalid-metadata-chef-repo/invalid-metadata/metadata.rb +10 -0
  110. data/spec/data/invalid-metadata-chef-repo/invalid-metadata/recipes/default.rb +8 -0
  111. data/spec/data/mac_users/10.7-8.plist.xml +559 -0
  112. data/spec/data/mac_users/10.7-8.shadow.xml +11 -0
  113. data/spec/data/mac_users/10.7.plist.xml +559 -0
  114. data/spec/data/mac_users/10.7.shadow.xml +11 -0
  115. data/spec/data/mac_users/10.8.plist.xml +559 -0
  116. data/spec/data/mac_users/10.8.shadow.xml +21 -0
  117. data/spec/data/mac_users/10.9.plist.xml +560 -0
  118. data/spec/data/mac_users/10.9.shadow.xml +21 -0
  119. data/spec/data/object_loader/environments/test.json +2 -0
  120. data/spec/data/object_loader/environments/test_json_class.json +2 -0
  121. data/spec/data/object_loader/nodes/test.json +2 -0
  122. data/spec/data/object_loader/nodes/test_json_class.json +2 -0
  123. data/spec/data/object_loader/roles/test.json +2 -0
  124. data/spec/data/object_loader/roles/test_json_class.json +2 -0
  125. data/spec/functional/resource/bff_spec.rb +1 -1
  126. data/spec/functional/resource/cron_spec.rb +20 -1
  127. data/spec/functional/resource/env_spec.rb +137 -0
  128. data/spec/functional/resource/group_spec.rb +7 -5
  129. data/spec/functional/resource/remote_file_spec.rb +12 -1
  130. data/spec/functional/resource/user/dscl_spec.rb +198 -0
  131. data/spec/functional/resource/{user_spec.rb → user/useradd_spec.rb} +175 -37
  132. data/spec/integration/client/client_spec.rb +6 -4
  133. data/spec/integration/client/ipv6_spec.rb +16 -14
  134. data/spec/integration/knife/chef_fs_data_store_spec.rb +57 -46
  135. data/spec/integration/knife/chef_repo_path_spec.rb +105 -78
  136. data/spec/integration/knife/chef_repository_file_system_spec.rb +100 -84
  137. data/spec/integration/knife/chefignore_spec.rb +76 -46
  138. data/spec/integration/knife/common_options_spec.rb +16 -21
  139. data/spec/integration/knife/cookbook_api_ipv6_spec.rb +3 -3
  140. data/spec/integration/knife/delete_spec.rb +66 -46
  141. data/spec/integration/knife/deps_spec.rb +145 -94
  142. data/spec/integration/knife/diff_spec.rb +176 -110
  143. data/spec/integration/knife/download_spec.rb +229 -133
  144. data/spec/integration/knife/list_spec.rb +62 -54
  145. data/spec/integration/knife/raw_spec.rb +24 -9
  146. data/spec/integration/knife/redirection_spec.rb +2 -2
  147. data/spec/integration/knife/serve_spec.rb +2 -2
  148. data/spec/integration/knife/show_spec.rb +32 -26
  149. data/spec/integration/knife/upload_spec.rb +308 -165
  150. data/spec/integration/recipes/lwrp_inline_resources_spec.rb +10 -8
  151. data/spec/integration/solo/solo_spec.rb +22 -11
  152. data/spec/spec_helper.rb +3 -0
  153. data/spec/support/lib/chef/resource/zen_follower.rb +46 -0
  154. data/spec/support/platform_helpers.rb +12 -0
  155. data/spec/support/shared/functional/file_resource.rb +10 -0
  156. data/spec/support/shared/integration/chef_zero_support.rb +130 -0
  157. data/spec/support/shared/integration/integration_helper.rb +100 -98
  158. data/spec/support/shared/integration/knife_support.rb +0 -1
  159. data/spec/support/shared/unit/provider/file.rb +6 -4
  160. data/spec/support/shared/unit/provider/useradd_based_user_provider.rb +10 -1
  161. data/spec/unit/api_client/registration_spec.rb +83 -74
  162. data/spec/unit/application_spec.rb +32 -9
  163. data/spec/unit/cookbook/cookbook_version_loader_spec.rb +179 -0
  164. data/spec/unit/cookbook/metadata_spec.rb +190 -150
  165. data/spec/unit/cookbook/syntax_check_spec.rb +3 -2
  166. data/spec/unit/cookbook_loader_spec.rb +114 -53
  167. data/spec/unit/{cookbook_site_streaming_uploader.rb → cookbook_site_streaming_uploader_spec.rb} +21 -1
  168. data/spec/unit/data_bag_spec.rb +88 -13
  169. data/spec/unit/deprecation_spec.rb +1 -2
  170. data/spec/unit/encrypted_data_bag_item_spec.rb +145 -9
  171. data/spec/unit/environment_spec.rb +1 -1
  172. data/spec/unit/formatters/base_spec.rb +48 -0
  173. data/spec/unit/json_compat_spec.rb +48 -17
  174. data/spec/unit/knife/client_delete_spec.rb +4 -4
  175. data/spec/unit/knife/client_show_spec.rb +15 -5
  176. data/spec/unit/knife/cookbook_site_download_spec.rb +1 -1
  177. data/spec/unit/knife/cookbook_site_share_spec.rb +3 -3
  178. data/spec/unit/knife/data_bag_from_file_spec.rb +0 -2
  179. data/spec/unit/knife/data_bag_show_spec.rb +23 -14
  180. data/spec/unit/knife/node_show_spec.rb +32 -15
  181. data/spec/unit/knife/role_show_spec.rb +59 -0
  182. data/spec/unit/platform_spec.rb +10 -0
  183. data/spec/unit/provider/deploy_spec.rb +4 -0
  184. data/spec/unit/provider/env_spec.rb +19 -0
  185. data/spec/unit/provider/git_spec.rb +22 -2
  186. data/spec/unit/provider/group/dscl_spec.rb +38 -1
  187. data/spec/unit/provider/group/pw_spec.rb +2 -2
  188. data/spec/unit/provider/http_request_spec.rb +8 -8
  189. data/spec/unit/provider/log_spec.rb +33 -53
  190. data/spec/unit/provider/mount/mount_spec.rb +12 -3
  191. data/spec/unit/provider/package/ips_spec.rb +96 -63
  192. data/spec/unit/provider/package/paludis_spec.rb +5 -5
  193. data/spec/unit/provider/package/rpm_spec.rb +12 -0
  194. data/spec/unit/provider/package/zypper_spec.rb +28 -16
  195. data/spec/unit/provider/service/windows_spec.rb +77 -17
  196. data/spec/unit/provider/user/dscl_spec.rb +659 -264
  197. data/spec/unit/provider/user/useradd_spec.rb +1 -0
  198. data/spec/unit/recipe_spec.rb +41 -0
  199. data/spec/unit/resource/scm_spec.rb +11 -0
  200. data/spec/unit/resource/user_spec.rb +4 -0
  201. data/spec/unit/resource/windows_service_spec.rb +46 -0
  202. data/spec/unit/resource_collection_spec.rb +33 -0
  203. data/spec/unit/resource_reporter_spec.rb +48 -0
  204. data/spec/unit/resource_spec.rb +9 -2
  205. data/spec/unit/role_spec.rb +6 -0
  206. data/spec/unit/version_constraint_spec.rb +28 -0
  207. metadata +61 -4
@@ -22,6 +22,8 @@ require 'openssl'
22
22
  require 'ffi_yajl'
23
23
  require 'chef/encrypted_data_bag_item'
24
24
  require 'chef/encrypted_data_bag_item/unsupported_encrypted_data_bag_item_format'
25
+ require 'chef/encrypted_data_bag_item/encryption_failure'
26
+ require 'chef/encrypted_data_bag_item/assertions'
25
27
 
26
28
  class Chef::EncryptedDataBagItem
27
29
 
@@ -40,9 +42,11 @@ class Chef::EncryptedDataBagItem
40
42
  Version1Encryptor.new(value, secret, iv)
41
43
  when 2
42
44
  Version2Encryptor.new(value, secret, iv)
45
+ when 3
46
+ Version3Encryptor.new(value, secret, iv)
43
47
  else
44
48
  raise UnsupportedEncryptedDataBagItemFormat,
45
- "Invalid encrypted data bag format version `#{format_version}'. Supported versions are '1', '2'"
49
+ "Invalid encrypted data bag format version `#{format_version}'. Supported versions are '1', '2', '3'"
46
50
  end
47
51
  end
48
52
 
@@ -50,6 +54,8 @@ class Chef::EncryptedDataBagItem
50
54
  attr_reader :key
51
55
  attr_reader :plaintext_data
52
56
 
57
+ include Chef::EncryptedDataBagItem::Assertions
58
+
53
59
  # Create a new Encryptor for +data+, which will be encrypted with the given
54
60
  # +key+.
55
61
  #
@@ -65,6 +71,11 @@ class Chef::EncryptedDataBagItem
65
71
  @iv = iv && Base64.decode64(iv)
66
72
  end
67
73
 
74
+ # Returns the used encryption algorithm
75
+ def algorithm
76
+ ALGORITHM
77
+ end
78
+
68
79
  # Returns a wrapped and encrypted version of +plaintext_data+ suitable for
69
80
  # using as the value in an encrypted data bag item.
70
81
  def for_encrypted_item
@@ -72,27 +83,28 @@ class Chef::EncryptedDataBagItem
72
83
  "encrypted_data" => encrypted_data,
73
84
  "iv" => Base64.encode64(iv),
74
85
  "version" => 1,
75
- "cipher" => ALGORITHM
86
+ "cipher" => algorithm
76
87
  }
77
88
  end
78
89
 
79
90
  # Generates or returns the IV.
80
91
  def iv
81
- # Generated IV comes from OpenSSL::Cipher::Cipher#random_iv
92
+ # Generated IV comes from OpenSSL::Cipher#random_iv
82
93
  # This gets generated when +openssl_encryptor+ gets created.
83
94
  openssl_encryptor if @iv.nil?
84
95
  @iv
85
96
  end
86
97
 
87
- # Generates (and memoizes) an OpenSSL::Cipher::Cipher object and configures
98
+ # Generates (and memoizes) an OpenSSL::Cipher object and configures
88
99
  # it for the specified iv and encryption key.
89
100
  def openssl_encryptor
90
101
  @openssl_encryptor ||= begin
91
- encryptor = OpenSSL::Cipher::Cipher.new(ALGORITHM)
102
+ encryptor = OpenSSL::Cipher.new(algorithm)
92
103
  encryptor.encrypt
104
+ # We must set key before iv: https://bugs.ruby-lang.org/issues/8221
105
+ encryptor.key = OpenSSL::Digest::SHA256.digest(key)
93
106
  @iv ||= encryptor.random_iv
94
107
  encryptor.iv = @iv
95
- encryptor.key = Digest::SHA256.digest(key)
96
108
  encryptor
97
109
  end
98
110
  end
@@ -125,18 +137,77 @@ class Chef::EncryptedDataBagItem
125
137
  "hmac" => hmac,
126
138
  "iv" => Base64.encode64(iv),
127
139
  "version" => 2,
128
- "cipher" => ALGORITHM
140
+ "cipher" => algorithm
129
141
  }
130
142
  end
131
143
 
132
144
  # Generates an HMAC-SHA2-256 of the encrypted data (encrypt-then-mac)
133
145
  def hmac
134
146
  @hmac ||= begin
135
- digest = OpenSSL::Digest::Digest.new("sha256")
147
+ digest = OpenSSL::Digest.new("sha256")
136
148
  raw_hmac = OpenSSL::HMAC.digest(digest, key, encrypted_data)
137
149
  Base64.encode64(raw_hmac)
138
150
  end
139
151
  end
140
152
  end
153
+
154
+ class Version3Encryptor < Version1Encryptor
155
+ include Chef::EncryptedDataBagItem::Assertions
156
+
157
+ def initialize(plaintext_data, key, iv=nil)
158
+ super
159
+ assert_aead_requirements_met!(algorithm)
160
+ @auth_tag = nil
161
+ end
162
+
163
+ # Returns a wrapped and encrypted version of +plaintext_data+ suitable for
164
+ # using as the value in an encrypted data bag item.
165
+ def for_encrypted_item
166
+ {
167
+ "encrypted_data" => encrypted_data,
168
+ "iv" => Base64.encode64(iv),
169
+ "auth_tag" => Base64.encode64(auth_tag),
170
+ "version" => 3,
171
+ "cipher" => algorithm
172
+ }
173
+ end
174
+
175
+ # Returns the used encryption algorithm
176
+ def algorithm
177
+ AEAD_ALGORITHM
178
+ end
179
+
180
+ # Returns a wrapped and encrypted version of +plaintext_data+ suitable for
181
+ # Returns the auth_tag.
182
+ def auth_tag
183
+ # Generated auth_tag comes from OpenSSL::Cipher#auth_tag
184
+ # This must be generated after the data is encrypted
185
+ if @auth_tag.nil?
186
+ raise EncryptionFailure, "Internal Error: GCM authentication tag read before encryption"
187
+ end
188
+ @auth_tag
189
+ end
190
+
191
+ # Generates (and memoizes) an OpenSSL::Cipher object and configures
192
+ # it for the specified iv and encryption key using AEAD
193
+ def openssl_encryptor
194
+ @openssl_encryptor ||= begin
195
+ encryptor = super
196
+ encryptor.auth_data = ''
197
+ encryptor
198
+ end
199
+ end
200
+
201
+ # Encrypts, Base64 encodes +serialized_data+ and gets the authentication tag
202
+ def encrypted_data
203
+ @encrypted_data ||= begin
204
+ enc_data_b64 = super
205
+ @auth_tag = openssl_encryptor.auth_tag
206
+ enc_data_b64
207
+ end
208
+ end
209
+
210
+ end
211
+
141
212
  end
142
213
  end
@@ -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)
@@ -140,7 +140,6 @@ class Chef
140
140
  self
141
141
  end
142
142
 
143
-
144
143
  def update_attributes_from_params(params)
145
144
  unless params[:default_attributes].nil? || params[:default_attributes].size == 0
146
145
  default_attributes(Chef::JSONCompat.from_json(params[:default_attributes]))
@@ -213,7 +212,6 @@ class Chef
213
212
  end
214
213
  end
215
214
 
216
-
217
215
  def self.json_create(o)
218
216
  environment = new
219
217
  environment.name(o["name"])
@@ -83,6 +83,7 @@ class Chef
83
83
  class RequestedUIDUnavailable < RuntimeError; end
84
84
  class InvalidHomeDirectory < ArgumentError; end
85
85
  class DsclCommandFailed < RuntimeError; end
86
+ class PlistUtilCommandFailed < RuntimeError; end
86
87
  class UserIDNotFound < ArgumentError; end
87
88
  class GroupIDNotFound < ArgumentError; end
88
89
  class ConflictingMembersInGroup < ArgumentError; end
@@ -115,6 +116,7 @@ class Chef
115
116
  class Win32ArchitectureIncorrect < RuntimeError; end
116
117
  class ObsoleteDependencySyntax < ArgumentError; end
117
118
  class InvalidDataBagPath < ArgumentError; end
119
+ class DuplicateDataBagItem < RuntimeError; end
118
120
 
119
121
  # A different version of a cookbook was added to a
120
122
  # VersionedRecipeList than the one already there.
@@ -131,6 +133,8 @@ class Chef
131
133
  # Version constraints are not allowed in chef-solo
132
134
  class IllegalVersionConstraint < NotImplementedError; end
133
135
 
136
+ class MetadataNotValid < StandardError; end
137
+
134
138
  # File operation attempted but no permissions to perform it
135
139
  class InsufficientPermissions < RuntimeError; end
136
140
 
@@ -194,7 +198,6 @@ class Chef
194
198
  end
195
199
  end
196
200
 
197
-
198
201
  end
199
202
  # Exception class for collecting multiple failures. Used when running
200
203
  # delayed notifications so that chef can process each delayed
@@ -262,7 +265,7 @@ class Chef
262
265
  "non_existent_cookbooks" => non_existent_cookbooks,
263
266
  "cookbooks_with_no_versions" => cookbooks_with_no_matching_versions
264
267
  }
265
- result.to_json(*a)
268
+ Chef::JSONCompat.to_json(result, *a)
266
269
  end
267
270
  end
268
271
 
@@ -297,7 +300,7 @@ class Chef
297
300
  "non_existent_cookbooks" => non_existent_cookbooks,
298
301
  "most_constrained_cookbooks" => most_constrained_cookbooks
299
302
  }
300
- result.to_json(*a)
303
+ Chef::JSONCompat.to_json(result, *a)
301
304
  end
302
305
  end
303
306
 
@@ -331,6 +334,18 @@ class Chef
331
334
  end
332
335
  end
333
336
 
337
+ class ChecksumMismatch < RuntimeError
338
+ def initialize(res_cksum, cont_cksum)
339
+ super "Checksum on resource (#{res_cksum}) does not match checksum on content (#{cont_cksum})"
340
+ end
341
+ end
342
+
334
343
  class BadProxyURI < RuntimeError; end
344
+
345
+ # Raised by Chef::JSONCompat
346
+ class JSON
347
+ class EncodeError < RuntimeError; end
348
+ class ParseError < RuntimeError; end
349
+ end
335
350
  end
336
351
  end
@@ -93,6 +93,13 @@ class Chef
93
93
 
94
94
  def indent_by(amount)
95
95
  @output.indent += amount
96
+ if @output.indent < 0
97
+ # This is left commented out for now. We need to uncomment it and fix at least one bug in
98
+ # the formatter, and then leave this line uncommented in the future.
99
+ #Chef::Log.warn "Internal Formatter Error -- Attempt to indent by negative number of spaces"
100
+ @output.indent = 0
101
+ end
102
+ @output.indent
96
103
  end
97
104
 
98
105
  # Input: a Formatters::ErrorDescription object.
@@ -56,7 +56,7 @@ class Chef
56
56
  # * could be no read on the node
57
57
  error_description.section("Authorization Error",<<-E)
58
58
  This client is not authorized to read some of the information required to
59
- access its coobooks (HTTP 403).
59
+ access its cookbooks (HTTP 403).
60
60
 
61
61
  To access its cookbooks, a client needs to be able to read its environment and
62
62
  all of the cookbooks in its expanded run list.
@@ -58,7 +58,6 @@ class Chef
58
58
  end
59
59
  end
60
60
 
61
-
62
61
  end
63
62
  end
64
63
  end
@@ -50,7 +50,7 @@ class Chef
50
50
  if @inflate_json_class
51
51
  return_value = Chef::JSONCompat.from_json(http_response.body.chomp)
52
52
  else
53
- return_value = Chef::JSONCompat.from_json(http_response.body.chomp, :create_additions => false)
53
+ return_value = Chef::JSONCompat.parse(http_response.body.chomp)
54
54
  end
55
55
  end
56
56
  [http_response, rest_request, return_value]
@@ -18,7 +18,9 @@
18
18
  # Wrapper class for interacting with JSON.
19
19
 
20
20
  require 'ffi_yajl'
21
+ require 'json'
21
22
  require 'ffi_yajl/json_gem' # XXX: parts of chef require JSON gem's Hash#to_json monkeypatch
23
+ require 'chef/exceptions'
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
@@ -88,14 +99,21 @@ 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
@@ -130,7 +148,7 @@ class Chef
130
148
  when /^Chef::Resource/
131
149
  Chef::Resource.find_subclass_by_name(json_class)
132
150
  else
133
- raise JSON::ParserError, "Unsupported `json_class` type '#{json_class}'"
151
+ raise Chef::Exceptions::JSON::ParseError, "Unsupported `json_class` type '#{json_class}'"
134
152
  end
135
153
  end
136
154
 
@@ -126,7 +126,7 @@ class Chef
126
126
  :short => "-j JSON_ATTRIBS",
127
127
  :long => "--json-attributes",
128
128
  :description => "A JSON string to be added to the first run of chef-client",
129
- :proc => lambda { |o| JSON.parse(o) },
129
+ :proc => lambda { |o| Chef::JSONCompat.parse(o) },
130
130
  :default => {}
131
131
 
132
132
  option :host_key_verify,
@@ -141,7 +141,7 @@ class Chef
141
141
  :proc => Proc.new { |h|
142
142
  Chef::Config[:knife][:hints] ||= Hash.new
143
143
  name, path = h.split("=")
144
- Chef::Config[:knife][:hints][name] = path ? JSON.parse(::File.read(path)) : Hash.new }
144
+ Chef::Config[:knife][:hints][name] = path ? Chef::JSONCompat.parse(::File.read(path)) : Hash.new }
145
145
 
146
146
  option :secret,
147
147
  :short => "-s SECRET",
@@ -47,7 +47,7 @@ class Chef
47
47
  object = Chef::ApiClient.load(@client_name)
48
48
  if object.validator
49
49
  unless config[:delete_validators]
50
- ui.fatal("You must specify --force to delete the validator client #{@client_name}")
50
+ ui.fatal("You must specify --delete-validators to delete the validator client #{@client_name}")
51
51
  exit 2
52
52
  end
53
53
  end
@@ -58,7 +58,7 @@ class Chef
58
58
 
59
59
  private
60
60
  def cookbooks_api_url
61
- 'http://cookbooks.opscode.com/api/v1/cookbooks'
61
+ 'https://supermarket.getchef.com/api/v1/cookbooks'
62
62
  end
63
63
 
64
64
  def current_cookbook_data
@@ -41,7 +41,7 @@ class Chef
41
41
  end
42
42
 
43
43
  def get_cookbook_list(items=10, start=0, cookbook_collection={})
44
- cookbooks_url = "http://cookbooks.opscode.com/api/v1/cookbooks?items=#{items}&start=#{start}"
44
+ cookbooks_url = "https://supermarket.getchef.com/api/v1/cookbooks?items=#{items}&start=#{start}"
45
45
  cr = noauth_rest.get_rest(cookbooks_url)
46
46
  cr["items"].each do |cookbook|
47
47
  cookbook_collection[cookbook["cookbook_name"]] = cookbook
@@ -29,7 +29,7 @@ class Chef
29
29
  end
30
30
 
31
31
  def search_cookbook(query, items=10, start=0, cookbook_collection={})
32
- cookbooks_url = "http://cookbooks.opscode.com/api/v1/search?q=#{query}&items=#{items}&start=#{start}"
32
+ cookbooks_url = "https://supermarket.getchef.com/api/v1/search?q=#{query}&items=#{items}&start=#{start}"
33
33
  cr = noauth_rest.get_rest(cookbooks_url)
34
34
  cr["items"].each do |cookbook|
35
35
  cookbook_collection[cookbook["cookbook_name"]] = cookbook
@@ -85,9 +85,9 @@ class Chef
85
85
  end
86
86
 
87
87
  def do_upload(cookbook_filename, cookbook_category, user_id, user_secret_filename)
88
- uri = "http://cookbooks.opscode.com/api/v1/cookbooks"
88
+ uri = "https://supermarket.getchef.com/api/v1/cookbooks"
89
89
 
90
- category_string = { 'category'=>cookbook_category }.to_json
90
+ category_string = Chef::JSONCompat.to_json({ 'category'=>cookbook_category })
91
91
 
92
92
  http_resp = Chef::CookbookSiteStreamingUploader.post(uri, user_id, user_secret_filename, {
93
93
  :tarball => File.open(cookbook_filename),
@@ -31,14 +31,14 @@ class Chef
31
31
  def get_cookbook_data
32
32
  case @name_args.length
33
33
  when 1
34
- noauth_rest.get_rest("http://cookbooks.opscode.com/api/v1/cookbooks/#{@name_args[0]}")
34
+ noauth_rest.get_rest("https://supermarket.getchef.com/api/v1/cookbooks/#{@name_args[0]}")
35
35
  when 2
36
- noauth_rest.get_rest("http://cookbooks.opscode.com/api/v1/cookbooks/#{@name_args[0]}/versions/#{name_args[1].gsub('.', '_')}")
36
+ noauth_rest.get_rest("https://supermarket.getchef.com/api/v1/cookbooks/#{@name_args[0]}/versions/#{name_args[1].gsub('.', '_')}")
37
37
  end
38
38
  end
39
39
 
40
40
  def get_cookbook_list(items=10, start=0, cookbook_collection={})
41
- cookbooks_url = "http://cookbooks.opscode.com/api/v1/cookbooks?items=#{items}&start=#{start}"
41
+ cookbooks_url = "https://supermarket.getchef.com/api/v1/cookbooks?items=#{items}&start=#{start}"
42
42
  cr = noauth_rest.get_rest(cookbooks_url)
43
43
  cr["items"].each do |cookbook|
44
44
  cookbook_collection[cookbook["cookbook_name"]] = cookbook