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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7aa601e3546aa66544577c191a175c15d0245784
4
- data.tar.gz: 1f5dc8c5ff2c69754c7626970c0cf033944b654c
3
+ metadata.gz: 52f66afbe3a2085850ce9ab0d1e32644753864d9
4
+ data.tar.gz: bcc5aff93e2dcacec5086cf79a21fe2fd9652561
5
5
  SHA512:
6
- metadata.gz: d6370007d5d100d435c67914bd46d9fd7ccfc73ce0fb3e9ee7236b7eaa5289eac0ba7184ffe059abf3785be50bbe552dfbaa6e69fa7cc9851ee30862320e1d4a
7
- data.tar.gz: 175f59eb669f8814b72b1a391003132b8addb5e8b6de42d7bf77bb0c53a9e122d69268bde97f947370a96155ca7a864db259dc980d80bd131f9ace189d264894
6
+ metadata.gz: a40b8ba07c5997375d554bd31cbede4c177c624b116f688b4e063b60093707d8245173aa7ecefcd092892f5cb351a651e29fa00d22ffd528c9e073494e3cc91a
7
+ data.tar.gz: cd4e29fbccd881017e98e09cc75bc075a88c8a1c057e3cdbb481642387e77cb771e71fb9fc92d521bedaac326de9c26d34997f2e113371bc634d88122bdbf16f
@@ -11,9 +11,7 @@ We utilize **Github Issues** for issue tracking and contributions. You can contr
11
11
 
12
12
  We have a 3 step process that utilizes **Github Issues**:
13
13
 
14
- 1. Sign our
15
- [Individual Contributor License Agreement (CLA)](https://secure.echosign.com/public/hostedForm?formid=PJIF5694K6L)
16
- or [Corporate CLA](https://secure.echosign.com/public/hostedForm?formid=PIE6C7AX856) online once.
14
+ 1. Sign or be added to an existing [Contributor License Agreement (CLA)](https://supermarket.getchef.com/become-a-contributor).
17
15
  2. Create a Github Pull Request.
18
16
  3. Do [Code Review](#cr) with the **Chef Engineering Team** or **Chef Core Committers** on the pull request.
19
17
 
@@ -83,10 +81,10 @@ To make a good faith effort to ensure these criteria are met, Chef requires an I
83
81
  It only takes a few minutes to complete a CLA, and you retain the copyright to your contribution.
84
82
 
85
83
  You can complete our
86
- [Individual CLA](https://secure.echosign.com/public/hostedForm?formid=PJIF5694K6L) online.
84
+ [Individual CLA](https://supermarket.getchef.com/icla-signatures/new) online.
87
85
  If you're contributing on behalf of your employer and they retain the copyright for your works,
88
86
  have your employer fill out our
89
- [Corporate CLA](https://secure.echosign.com/public/hostedForm?formid=PIE6C7AX856) instead.
87
+ [Corporate CLA](https://supermarket.getchef.com/ccla-signatures/new) instead.
90
88
 
91
89
  ### Chef Obvious Fix Policy
92
90
 
@@ -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)
@@ -73,7 +73,6 @@ class Chef::Application
73
73
  end
74
74
  end
75
75
 
76
-
77
76
  # Parse configuration (options and config file)
78
77
  def configure_chef
79
78
  parse_options
@@ -219,30 +218,39 @@ class Chef::Application
219
218
  # Set ENV['http_proxy']
220
219
  def configure_http_proxy
221
220
  if http_proxy = Chef::Config[:http_proxy]
222
- env['http_proxy'] = configure_proxy("http", http_proxy,
223
- Chef::Config[:http_proxy_user], Chef::Config[:http_proxy_pass])
221
+ http_proxy_string = configure_proxy("http", http_proxy,
222
+ Chef::Config[:http_proxy_user], Chef::Config[:http_proxy_pass])
223
+ env['http_proxy'] = http_proxy_string unless env['http_proxy']
224
+ env['HTTP_PROXY'] = http_proxy_string unless env['HTTP_PROXY']
224
225
  end
225
226
  end
226
227
 
227
228
  # Set ENV['https_proxy']
228
229
  def configure_https_proxy
229
230
  if https_proxy = Chef::Config[:https_proxy]
230
- env['https_proxy'] = configure_proxy("https", https_proxy,
231
- Chef::Config[:https_proxy_user], Chef::Config[:https_proxy_pass])
231
+ https_proxy_string = configure_proxy("https", https_proxy,
232
+ Chef::Config[:https_proxy_user], Chef::Config[:https_proxy_pass])
233
+ env['https_proxy'] = https_proxy_string unless env['https_proxy']
234
+ env['HTTPS_PROXY'] = https_proxy_string unless env['HTTPS_PROXY']
232
235
  end
233
236
  end
234
237
 
235
238
  # Set ENV['ftp_proxy']
236
239
  def configure_ftp_proxy
237
240
  if ftp_proxy = Chef::Config[:ftp_proxy]
238
- env['ftp_proxy'] = configure_proxy("ftp", ftp_proxy,
241
+ ftp_proxy_string = configure_proxy("ftp", ftp_proxy,
239
242
  Chef::Config[:ftp_proxy_user], Chef::Config[:ftp_proxy_pass])
243
+ env['ftp_proxy'] = ftp_proxy_string unless env['ftp_proxy']
244
+ env['FTP_PROXY'] = ftp_proxy_string unless env['FTP_PROXY']
240
245
  end
241
246
  end
242
247
 
243
248
  # Set ENV['no_proxy']
244
249
  def configure_no_proxy
245
- env['no_proxy'] = Chef::Config[:no_proxy] if Chef::Config[:no_proxy]
250
+ if Chef::Config[:no_proxy]
251
+ env['no_proxy'] = Chef::Config[:no_proxy] unless env['no_proxy']
252
+ env['NO_PROXY'] = Chef::Config[:no_proxy] unless env['NO_PROXY']
253
+ end
246
254
  end
247
255
 
248
256
  # Builds a proxy uri. Examples:
@@ -256,7 +264,7 @@ class Chef::Application
256
264
  # pass = password
257
265
  def configure_proxy(scheme, path, user, pass)
258
266
  begin
259
- path = "#{scheme}://#{path}" unless path.start_with?(scheme)
267
+ path = "#{scheme}://#{path}" unless path.include?('://')
260
268
  # URI.split returns the following parts:
261
269
  # [scheme, userinfo, host, port, registry, path, opaque, query, fragment]
262
270
  parts = URI.split(URI.encode(path))
@@ -269,7 +269,7 @@ class Chef
269
269
 
270
270
  # Create a little Chef::ChefFS memory filesystem with the data
271
271
  cookbook_fs = Chef::ChefFS::FileSystem::MemoryRoot.new('uploading')
272
- cookbook = JSON.parse(data, :create_additions => false)
272
+ cookbook = Chef::JSONCompat.parse(data)
273
273
  cookbook.each_pair do |key, value|
274
274
  if value.is_a?(Array)
275
275
  value.each do |file|
@@ -251,7 +251,7 @@ class Chef
251
251
  end
252
252
 
253
253
  def self.canonicalize_json(json_text)
254
- parsed_json = JSON.parse(json_text, :create_additions => false)
254
+ parsed_json = Chef::JSONCompat.parse(json_text)
255
255
  sorted_json = sort_keys(parsed_json)
256
256
  JSON.pretty_generate(sorted_json)
257
257
  end
@@ -369,7 +369,7 @@ class Chef
369
369
  end
370
370
  else
371
371
  if dest_entry.dir?
372
- ui.error("File #{src_path} is a directory while file #{dest_path} is a regular file\n") if ui
372
+ ui.error("File #{src_path} is a regular file while file #{dest_path} is a directory\n") if ui
373
373
  return
374
374
  else
375
375
 
@@ -37,7 +37,7 @@ class Chef
37
37
 
38
38
  def write(file_contents)
39
39
  # ACL writes are fun.
40
- acls = data_handler.normalize(JSON.parse(file_contents, :create_additions => false), self)
40
+ acls = data_handler.normalize(Chef::JSONCompat.parse(file_contents), self)
41
41
  PERMISSIONS.each do |permission|
42
42
  begin
43
43
  rest.put("#{api_path}/#{permission}", { permission => acls[permission] })
@@ -41,7 +41,7 @@ class Chef
41
41
 
42
42
  def chef_object
43
43
  begin
44
- return data_handler.chef_object(JSON.parse(read, :create_additions => false))
44
+ return data_handler.chef_object(Chef::JSONCompat.parse(read))
45
45
  rescue
46
46
  Chef::Log.error("Could not read #{path_for_printing} into a Chef object: #{$!}")
47
47
  end
@@ -60,10 +60,10 @@ class Chef
60
60
  end
61
61
 
62
62
  def minimize(file_contents, entry)
63
- object = JSONCompat.from_json(file_contents, :create_additions => false)
63
+ object = Chef::JSONCompat.from_json(file_contents)
64
64
  object = data_handler.normalize(object, entry)
65
65
  object = data_handler.minimize(object, entry)
66
- JSONCompat.to_json_pretty(object)
66
+ Chef::JSONCompat.to_json_pretty(object)
67
67
  end
68
68
 
69
69
  def children
@@ -18,7 +18,7 @@
18
18
 
19
19
  require 'chef/chef_fs/file_system/base_fs_object'
20
20
  require 'chef/http/simple'
21
- require 'digest/md5'
21
+ require 'openssl'
22
22
 
23
23
  class Chef
24
24
  module ChefFS
@@ -74,7 +74,7 @@ class Chef
74
74
  private
75
75
 
76
76
  def calc_checksum(value)
77
- Digest::MD5.hexdigest(value)
77
+ OpenSSL::Digest::MD5.hexdigest(value)
78
78
  end
79
79
  end
80
80
  end
@@ -61,8 +61,8 @@ class Chef
61
61
 
62
62
  def create_child(name, file_contents)
63
63
  begin
64
- object = JSON.parse(file_contents, :create_additions => false)
65
- rescue JSON::ParserError => e
64
+ object = Chef::JSONCompat.parse(file_contents)
65
+ rescue Chef::Exceptions::JSON::ParseError => e
66
66
  raise Chef::ChefFS::FileSystem::OperationFailedError.new(:create_child, self, e), "Parse error reading JSON creating child '#{name}': #{e}"
67
67
  end
68
68
 
@@ -128,8 +128,8 @@ class Chef
128
128
  value = minimize_value(value)
129
129
  value_json = Chef::JSONCompat.to_json_pretty(value)
130
130
  begin
131
- other_value = JSON.parse(other_value_json, :create_additions => false)
132
- rescue JSON::ParserError => e
131
+ other_value = Chef::JSONCompat.parse(other_value_json)
132
+ rescue Chef::Exceptions::JSON::ParseError => e
133
133
  Chef::Log.warn("Parse error reading #{other.path_for_printing} as JSON: #{e}")
134
134
  return [ nil, value_json, other_value_json ]
135
135
  end
@@ -145,8 +145,8 @@ class Chef
145
145
 
146
146
  def write(file_contents)
147
147
  begin
148
- object = JSON.parse(file_contents, :create_additions => false)
149
- rescue JSON::ParserError => e
148
+ object = Chef::JSONCompat.parse(file_contents)
149
+ rescue Chef::Exceptions::JSON::ParseError => e
150
150
  raise Chef::ChefFS::FileSystem::OperationFailedError.new(:write, self, e), "Parse error reading JSON: #{e}"
151
151
  end
152
152
 
@@ -432,7 +432,8 @@ class Chef
432
432
  # format. Version "2" is available which adds encrypt-then-mac protection.
433
433
  # To maintain compatibility, versions other than 1 must be opt-in.
434
434
  #
435
- # Set this to `2` if you have chef-client 11.6.0+ in your infrastructure:
435
+ # Set this to `2` if you have chef-client 11.6.0+ in your infrastructure.
436
+ # Set this to `3` if you have chef-client 11.?.0+, ruby 2 and OpenSSL >= 1.0.1 in your infrastructure. (TODO)
436
437
  default :data_bag_encrypt_version, 1
437
438
 
438
439
  # When reading data bag items, any supported version is accepted. However,
@@ -455,15 +456,15 @@ class Chef
455
456
  default :validation_client_name, "chef-validator"
456
457
 
457
458
  # When creating a new client via the validation_client account, Chef 11
458
- # servers allow the client to generate a key pair locally and sent the
459
+ # servers allow the client to generate a key pair locally and send the
459
460
  # public key to the server. This is more secure and helps offload work from
460
461
  # the server, enhancing scalability. If enabled and the remote server
461
462
  # implements only the Chef 10 API, client registration will not work
462
463
  # properly.
463
464
  #
464
- # The default value is `false` (Server generates client keys). Set to
465
- # `true` to enable client-side key generation.
466
- default(:local_key_generation) { false }
465
+ # The default value is `true`. Set to `false` to disable client-side key
466
+ # generation (server generates client keys).
467
+ default(:local_key_generation) { true }
467
468
 
468
469
  # Zypper package provider gpg checks. Set to true to enable package
469
470
  # gpg signature checking. This will be default in the
@@ -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
@@ -18,21 +18,29 @@ class Chef
18
18
 
19
19
  UPLOADED_COOKBOOK_VERSION_FILE = ".uploaded-cookbook-version.json".freeze
20
20
 
21
- attr_reader :cookbook_name
22
21
  attr_reader :cookbook_settings
23
22
  attr_reader :cookbook_paths
24
23
  attr_reader :metadata_filenames
25
24
  attr_reader :frozen
26
25
  attr_reader :uploaded_cookbook_version_file
27
26
 
27
+ attr_reader :cookbook_path
28
+
29
+ # The cookbook's name as inferred from its directory.
30
+ attr_reader :inferred_cookbook_name
31
+
32
+ attr_reader :metadata_error
33
+
28
34
  def initialize(path, chefignore=nil)
29
35
  @cookbook_path = File.expand_path( path ) # cookbook_path from which this was loaded
30
36
  # We keep a list of all cookbook paths that have been merged in
31
- @cookbook_paths = [ @cookbook_path ]
32
- @cookbook_name = File.basename( path )
37
+ @cookbook_paths = [ cookbook_path ]
38
+
39
+ @inferred_cookbook_name = File.basename( path )
33
40
  @chefignore = chefignore
34
- @metadata = Hash.new
41
+ @metadata = nil
35
42
  @relative_path = /#{Regexp.escape(@cookbook_path)}\/(.+)$/
43
+ @metadata_loaded = false
36
44
  @cookbook_settings = {
37
45
  :attribute_filenames => {},
38
46
  :definition_filenames => {},
@@ -46,9 +54,29 @@ class Chef
46
54
  }
47
55
 
48
56
  @metadata_filenames = []
57
+ @metadata_error = nil
58
+ end
59
+
60
+ # Load the cookbook. Raises an error if the cookbook_path given to the
61
+ # constructor doesn't point to a valid cookbook.
62
+ def load!
63
+ file_paths_map = load
64
+
65
+ if empty?
66
+ raise Exceptions::CookbookNotFoundInRepo, "The directory #{cookbook_path} does not contain a cookbook"
67
+ end
68
+ file_paths_map
49
69
  end
50
70
 
51
- def load_cookbooks
71
+ # Load the cookbook. Does not raise an error if given a non-cookbook
72
+ # directory as the cookbook_path. This behavior is provided for
73
+ # compatibility, it is recommended to use #load! instead.
74
+ def load
75
+ metadata # force lazy evaluation to occur
76
+
77
+ # re-raise any exception that occurred when reading the metadata
78
+ raise_metadata_error!
79
+
52
80
  load_as(:attribute_filenames, 'attributes', '*.rb')
53
81
  load_as(:definition_filenames, 'definitions', '*.rb')
54
82
  load_as(:recipe_filenames, 'recipes', '*.rb')
@@ -61,31 +89,37 @@ class Chef
61
89
 
62
90
  remove_ignored_files
63
91
 
64
- if File.exists?(File.join(@cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE))
65
- @uploaded_cookbook_version_file = File.join(@cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE)
92
+ if empty?
93
+ Chef::Log.warn "found a directory #{cookbook_name} in the cookbook path, but it contains no cookbook files. skipping."
94
+ end
95
+ @cookbook_settings
96
+ end
97
+
98
+ alias :load_cookbooks :load
99
+
100
+ def metadata_filenames
101
+ return @metadata_filenames unless @metadata_filenames.empty?
102
+ if File.exists?(File.join(cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE))
103
+ @uploaded_cookbook_version_file = File.join(cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE)
66
104
  end
67
105
 
68
- if File.exists?(File.join(@cookbook_path, "metadata.rb"))
69
- @metadata_filenames << File.join(@cookbook_path, "metadata.rb")
70
- elsif File.exists?(File.join(@cookbook_path, "metadata.json"))
71
- @metadata_filenames << File.join(@cookbook_path, "metadata.json")
106
+ if File.exists?(File.join(cookbook_path, "metadata.rb"))
107
+ @metadata_filenames << File.join(cookbook_path, "metadata.rb")
108
+ elsif File.exists?(File.join(cookbook_path, "metadata.json"))
109
+ @metadata_filenames << File.join(cookbook_path, "metadata.json")
72
110
  elsif @uploaded_cookbook_version_file
73
111
  @metadata_filenames << @uploaded_cookbook_version_file
74
112
  end
75
113
 
76
114
  # Set frozen based on .uploaded-cookbook-version.json
77
115
  set_frozen
78
-
79
- if empty?
80
- Chef::Log.warn "found a directory #{cookbook_name} in the cookbook path, but it contains no cookbook files. skipping."
81
- end
82
- @cookbook_settings
116
+ @metadata_filenames
83
117
  end
84
118
 
85
119
  def cookbook_version
86
120
  return nil if empty?
87
121
 
88
- Chef::CookbookVersion.new(@cookbook_name.to_sym, *@cookbook_paths).tap do |c|
122
+ Chef::CookbookVersion.new(cookbook_name, *cookbook_paths).tap do |c|
89
123
  c.attribute_filenames = cookbook_settings[:attribute_filenames].values
90
124
  c.definition_filenames = cookbook_settings[:definition_filenames].values
91
125
  c.recipe_filenames = cookbook_settings[:recipe_filenames].values
@@ -95,16 +129,32 @@ class Chef
95
129
  c.resource_filenames = cookbook_settings[:resource_filenames].values
96
130
  c.provider_filenames = cookbook_settings[:provider_filenames].values
97
131
  c.root_filenames = cookbook_settings[:root_filenames].values
98
- c.metadata_filenames = @metadata_filenames
99
- c.metadata = metadata(c)
132
+ c.metadata_filenames = metadata_filenames
133
+ c.metadata = metadata
134
+
100
135
  c.freeze_version if @frozen
101
136
  end
102
137
  end
103
138
 
139
+ def cookbook_name
140
+ # The `name` attribute is now required in metadata, so
141
+ # inferred_cookbook_name generally should not be used. Per CHEF-2923,
142
+ # we have to not raise errors in cookbook metadata immediately, so that
143
+ # users can still `knife cookbook upload some-cookbook` when an
144
+ # unrelated cookbook has an error in its metadata. This situation
145
+ # could prevent us from reading the `name` attribute from the metadata
146
+ # entirely, but the name is used as a hash key in CookbookLoader, so we
147
+ # fall back to the inferred name here.
148
+ (metadata.name || @inferred_cookbook_name).to_sym
149
+ end
150
+
104
151
  # Generates the Cookbook::Metadata object
105
- def metadata(cookbook_version)
106
- @metadata = Chef::Cookbook::Metadata.new(cookbook_version)
107
- @metadata_filenames.each do |metadata_file|
152
+ def metadata
153
+ return @metadata unless @metadata.nil?
154
+
155
+ @metadata = Chef::Cookbook::Metadata.new
156
+
157
+ metadata_filenames.each do |metadata_file|
108
158
  case metadata_file
109
159
  when /\.rb$/
110
160
  apply_ruby_metadata(metadata_file)
@@ -116,51 +166,75 @@ class Chef
116
166
  raise RuntimeError, "Invalid metadata file: #{metadata_file} for cookbook: #{cookbook_version}"
117
167
  end
118
168
  end
169
+
170
+ @metadata
171
+
172
+ # Rescue errors so that users can upload cookbooks via `knife cookbook
173
+ # upload` even if some cookbooks in their chef-repo have errors in
174
+ # their metadata. We only rescue StandardError because you have to be
175
+ # doing something *really* terrible to raise an exception that inherits
176
+ # directly from Exception in your metadata.rb file.
177
+ rescue StandardError => e
178
+ @metadata_error = e
119
179
  @metadata
120
180
  end
121
181
 
182
+ def raise_metadata_error!
183
+ raise @metadata_error unless @metadata_error.nil?
184
+ # Metadata won't be valid if the cookbook is empty. If the cookbook is
185
+ # actually empty, a metadata error here would be misleading, so don't
186
+ # raise it (if called by #load!, a different error is raised).
187
+ if !empty? && !metadata.valid?
188
+ message = "Cookbook loaded at path(s) [#{@cookbook_paths.join(', ')}] has invalid metadata: #{metadata.errors.join('; ')}"
189
+ raise Exceptions::MetadataNotValid, message
190
+ end
191
+ false
192
+ end
193
+
122
194
  def empty?
123
- @cookbook_settings.values.all? { |files_hash| files_hash.empty? } && @metadata_filenames.size == 0
195
+ cookbook_settings.values.all? { |files_hash| files_hash.empty? } && metadata_filenames.size == 0
124
196
  end
125
197
 
126
198
  def merge!(other_cookbook_loader)
127
199
  other_cookbook_settings = other_cookbook_loader.cookbook_settings
128
- @cookbook_settings.each do |file_type, file_list|
200
+ cookbook_settings.each do |file_type, file_list|
129
201
  file_list.merge!(other_cookbook_settings[file_type])
130
202
  end
131
- @metadata_filenames.concat(other_cookbook_loader.metadata_filenames)
203
+ metadata_filenames.concat(other_cookbook_loader.metadata_filenames)
132
204
  @cookbook_paths += other_cookbook_loader.cookbook_paths
133
205
  @frozen = true if other_cookbook_loader.frozen
206
+ @metadata = nil # reset metadata so it gets reloaded and all metadata files applied.
207
+ self
134
208
  end
135
209
 
136
210
  def chefignore
137
- @chefignore ||= Chefignore.new(File.basename(@cookbook_path))
211
+ @chefignore ||= Chefignore.new(File.basename(cookbook_path))
138
212
  end
139
213
 
140
214
  def load_root_files
141
- Dir.glob(File.join(@cookbook_path, '*'), File::FNM_DOTMATCH).each do |file|
215
+ Dir.glob(File.join(cookbook_path, '*'), File::FNM_DOTMATCH).each do |file|
142
216
  next if File.directory?(file)
143
217
  next if File.basename(file) == UPLOADED_COOKBOOK_VERSION_FILE
144
- @cookbook_settings[:root_filenames][file[@relative_path, 1]] = file
218
+ cookbook_settings[:root_filenames][file[@relative_path, 1]] = file
145
219
  end
146
220
  end
147
221
 
148
222
  def load_recursively_as(category, category_dir, glob)
149
- file_spec = File.join(@cookbook_path, category_dir, '**', glob)
223
+ file_spec = File.join(cookbook_path, category_dir, '**', glob)
150
224
  Dir.glob(file_spec, File::FNM_DOTMATCH).each do |file|
151
225
  next if File.directory?(file)
152
- @cookbook_settings[category][file[@relative_path, 1]] = file
226
+ cookbook_settings[category][file[@relative_path, 1]] = file
153
227
  end
154
228
  end
155
229
 
156
230
  def load_as(category, *path_glob)
157
- Dir[File.join(@cookbook_path, *path_glob)].each do |file|
158
- @cookbook_settings[category][file[@relative_path, 1]] = file
231
+ Dir[File.join(cookbook_path, *path_glob)].each do |file|
232
+ cookbook_settings[category][file[@relative_path, 1]] = file
159
233
  end
160
234
  end
161
235
 
162
236
  def remove_ignored_files
163
- @cookbook_settings.each_value do |file_list|
237
+ cookbook_settings.each_value do |file_list|
164
238
  file_list.reject! do |relative_path, full_path|
165
239
  chefignore.ignored?(relative_path)
166
240
  end
@@ -170,8 +244,8 @@ class Chef
170
244
  def apply_ruby_metadata(file)
171
245
  begin
172
246
  @metadata.from_file(file)
173
- rescue JSON::ParserError
174
- Chef::Log.error("Error evaluating metadata.rb for #@cookbook_name in " + file)
247
+ rescue Chef::Exceptions::JSON::ParseError
248
+ Chef::Log.error("Error evaluating metadata.rb for #@inferred_cookbook_name in " + file)
175
249
  raise
176
250
  end
177
251
  end
@@ -179,18 +253,27 @@ class Chef
179
253
  def apply_json_metadata(file)
180
254
  begin
181
255
  @metadata.from_json(IO.read(file))
182
- rescue JSON::ParserError
183
- Chef::Log.error("Couldn't parse cookbook metadata JSON for #@cookbook_name in " + file)
256
+ rescue Chef::Exceptions::JSON::ParseError
257
+ Chef::Log.error("Couldn't parse cookbook metadata JSON for #@inferred_cookbook_name in " + file)
184
258
  raise
185
259
  end
186
260
  end
187
261
 
188
262
  def apply_json_cookbook_version_metadata(file)
189
263
  begin
190
- data = Chef::JSONCompat.from_json(IO.read(file), :create_additions => false)
264
+ data = Chef::JSONCompat.parse(IO.read(file))
191
265
  @metadata.from_hash(data['metadata'])
192
- rescue JSON::ParserError
193
- Chef::Log.error("Couldn't parse cookbook metadata JSON for #@cookbook_name in " + file)
266
+ # the JSON cookbok metadata file is only used by chef-zero.
267
+ # The Chef Server API currently does not enforce that the metadata
268
+ # have a `name` field, but that will cause an error when attempting
269
+ # to load the cookbook. To keep compatibility, we fake it by setting
270
+ # the metadata name from the cookbook version object's name.
271
+ #
272
+ # This behavior can be removed if/when Chef Server enforces that the
273
+ # metadata contains a name key.
274
+ @metadata.name(data['cookbook_name']) unless data['metadata'].key?('name')
275
+ rescue Chef::Exceptions::JSON::ParseError
276
+ Chef::Log.error("Couldn't parse cookbook metadata JSON for #@inferred_cookbook_name in " + file)
194
277
  raise
195
278
  end
196
279
  end
@@ -198,10 +281,10 @@ class Chef
198
281
  def set_frozen
199
282
  if uploaded_cookbook_version_file
200
283
  begin
201
- data = Chef::JSONCompat.from_json(IO.read(uploaded_cookbook_version_file), :create_additions => false)
284
+ data = Chef::JSONCompat.parse(IO.read(uploaded_cookbook_version_file))
202
285
  @frozen = data['frozen?']
203
- rescue JSON::ParserError
204
- Chef::Log.error("Couldn't parse cookbook metadata JSON for #@cookbook_name in #{uploaded_cookbook_version_file}")
286
+ rescue Chef::Exceptions::JSON::ParseError
287
+ Chef::Log.error("Couldn't parse cookbook metadata JSON for #@inferred_cookbook_name in #{uploaded_cookbook_version_file}")
205
288
  raise
206
289
  end
207
290
  end