chef 11.12.8 → 11.14.0.alpha.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -2
  3. data/distro/common/html/_sources/index.txt +6 -0
  4. data/distro/common/html/_sources/knife_ssl_check.txt +41 -0
  5. data/distro/common/html/_sources/knife_ssl_fetch.txt +41 -0
  6. data/distro/common/html/_static/basic.css +2 -5
  7. data/distro/common/html/_static/doctools.js +5 -14
  8. data/distro/common/html/_static/jquery.js +2 -154
  9. data/distro/common/html/_static/pygments.css +2 -2
  10. data/distro/common/html/_static/searchtools.js +212 -150
  11. data/distro/common/html/_static/underscore.js +29 -21
  12. data/distro/common/html/_static/websupport.js +1 -1
  13. data/distro/common/html/ctl_chef_client.html +15 -18
  14. data/distro/common/html/ctl_chef_server.html +7 -7
  15. data/distro/common/html/ctl_chef_shell.html +6 -6
  16. data/distro/common/html/ctl_chef_solo.html +7 -8
  17. data/distro/common/html/index.html +34 -24
  18. data/distro/common/html/knife.html +23 -24
  19. data/distro/common/html/knife_bootstrap.html +13 -9
  20. data/distro/common/html/knife_client.html +10 -11
  21. data/distro/common/html/knife_common_options.html +6 -7
  22. data/distro/common/html/knife_configure.html +3 -4
  23. data/distro/common/html/knife_cookbook.html +18 -11
  24. data/distro/common/html/knife_cookbook_site.html +14 -14
  25. data/distro/common/html/knife_data_bag.html +24 -23
  26. data/distro/common/html/knife_delete.html +4 -5
  27. data/distro/common/html/knife_deps.html +4 -5
  28. data/distro/common/html/knife_diff.html +6 -7
  29. data/distro/common/html/knife_download.html +12 -13
  30. data/distro/common/html/knife_edit.html +4 -5
  31. data/distro/common/html/knife_environment.html +8 -9
  32. data/distro/common/html/knife_exec.html +9 -10
  33. data/distro/common/html/knife_index_rebuild.html +4 -5
  34. data/distro/common/html/knife_list.html +8 -9
  35. data/distro/common/html/knife_node.html +34 -33
  36. data/distro/common/html/knife_raw.html +2 -3
  37. data/distro/common/html/knife_recipe_list.html +3 -4
  38. data/distro/common/html/knife_role.html +30 -29
  39. data/distro/common/html/knife_search.html +7 -7
  40. data/distro/common/html/knife_show.html +4 -5
  41. data/distro/common/html/knife_ssh.html +2 -3
  42. data/distro/common/html/knife_ssl_check.html +148 -0
  43. data/distro/common/html/knife_ssl_fetch.html +152 -0
  44. data/distro/common/html/knife_status.html +4 -5
  45. data/distro/common/html/knife_tag.html +2 -3
  46. data/distro/common/html/knife_upload.html +5 -6
  47. data/distro/common/html/knife_user.html +9 -10
  48. data/distro/common/html/knife_using.html +12 -12
  49. data/distro/common/html/knife_xargs.html +11 -12
  50. data/distro/common/html/search.html +1 -2
  51. data/distro/common/html/searchindex.js +1 -1
  52. data/distro/common/man/man1/chef-shell.1 +19 -11
  53. data/distro/common/man/man1/knife-bootstrap.1 +35 -19
  54. data/distro/common/man/man1/knife-client.1 +111 -28
  55. data/distro/common/man/man1/knife-configure.1 +30 -14
  56. data/distro/common/man/man1/knife-cookbook-site.1 +105 -22
  57. data/distro/common/man/man1/knife-cookbook.1 +164 -23
  58. data/distro/common/man/man1/knife-data-bag.1 +157 -33
  59. data/distro/common/man/man1/knife-delete.1 +21 -17
  60. data/distro/common/man/man1/knife-deps.1 +60 -16
  61. data/distro/common/man/man1/knife-diff.1 +37 -17
  62. data/distro/common/man/man1/knife-download.1 +68 -24
  63. data/distro/common/man/man1/knife-edit.1 +19 -15
  64. data/distro/common/man/man1/knife-environment.1 +105 -17
  65. data/distro/common/man/man1/knife-exec.1 +78 -18
  66. data/distro/common/man/man1/knife-index-rebuild.1 +16 -8
  67. data/distro/common/man/man1/knife-list.1 +39 -23
  68. data/distro/common/man/man1/knife-node.1 +170 -22
  69. data/distro/common/man/man1/knife-raw.1 +33 -13
  70. data/distro/common/man/man1/knife-recipe-list.1 +17 -5
  71. data/distro/common/man/man1/knife-role.1 +86 -18
  72. data/distro/common/man/man1/knife-search.1 +80 -16
  73. data/distro/common/man/man1/knife-show.1 +30 -14
  74. data/distro/common/man/man1/knife-ssh.1 +54 -14
  75. data/distro/common/man/man1/knife-ssl-check.1 +207 -0
  76. data/distro/common/man/man1/knife-ssl-fetch.1 +207 -0
  77. data/distro/common/man/man1/knife-status.1 +48 -12
  78. data/distro/common/man/man1/knife-tag.1 +30 -10
  79. data/distro/common/man/man1/knife-upload.1 +72 -20
  80. data/distro/common/man/man1/knife-user.1 +79 -23
  81. data/distro/common/man/man1/knife-xargs.1 +61 -53
  82. data/distro/common/man/man8/chef-client.8 +87 -29
  83. data/distro/common/man/man8/chef-solo.8 +36 -15
  84. data/lib/chef/application.rb +19 -14
  85. data/lib/chef/application/client.rb +5 -0
  86. data/lib/chef/application/solo.rb +5 -0
  87. data/lib/chef/application/windows_service_manager.rb +3 -0
  88. data/lib/chef/chef_fs/chef_fs_data_store.rb +72 -24
  89. data/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_dir.rb +20 -4
  90. data/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbooks_dir.rb +20 -1
  91. data/lib/chef/chef_fs/file_system/file_system_entry.rb +10 -2
  92. data/lib/chef/client.rb +2 -3
  93. data/lib/chef/config.rb +34 -8
  94. data/lib/chef/cookbook/cookbook_version_loader.rb +45 -4
  95. data/lib/chef/cookbook_version.rb +38 -30
  96. data/lib/chef/dsl/recipe.rb +4 -1
  97. data/lib/chef/event_dispatch/base.rb +14 -0
  98. data/lib/chef/event_dispatch/events_output_stream.rb +29 -0
  99. data/lib/chef/exceptions.rb +8 -0
  100. data/lib/chef/formatters/base.rb +16 -45
  101. data/lib/chef/formatters/doc.rb +51 -26
  102. data/lib/chef/formatters/indentable_output_stream.rb +165 -0
  103. data/lib/chef/knife/node_environment_set.rb +54 -0
  104. data/lib/chef/knife/user_create.rb +1 -1
  105. data/lib/chef/monkey_patches/pathname.rb +32 -0
  106. data/lib/chef/node.rb +1 -1
  107. data/lib/chef/platform/provider_mapping.rb +345 -338
  108. data/lib/chef/policy_builder/expand_node_object.rb +1 -1
  109. data/lib/chef/policy_builder/policyfile.rb +1 -1
  110. data/lib/chef/provider.rb +1 -0
  111. data/lib/chef/provider/git.rb +1 -1
  112. data/lib/chef/provider/link.rb +2 -2
  113. data/lib/chef/provider/remote_file/content.rb +1 -1
  114. data/lib/chef/provider/remote_file/local_file.rb +8 -2
  115. data/lib/chef/provider/service/arch.rb +0 -1
  116. data/lib/chef/provider/service/debian.rb +0 -2
  117. data/lib/chef/provider/service/freebsd.rb +2 -1
  118. data/lib/chef/provider/service/gentoo.rb +1 -1
  119. data/lib/chef/provider/service/init.rb +0 -1
  120. data/lib/chef/provider/service/insserv.rb +0 -2
  121. data/lib/chef/provider/service/invokercd.rb +0 -2
  122. data/lib/chef/provider/service/macosx.rb +2 -1
  123. data/lib/chef/provider/service/redhat.rb +0 -1
  124. data/lib/chef/provider/service/simple.rb +1 -0
  125. data/lib/chef/provider/service/solaris.rb +1 -0
  126. data/lib/chef/provider/service/systemd.rb +1 -1
  127. data/lib/chef/provider/service/upstart.rb +1 -1
  128. data/lib/chef/provider/user.rb +9 -9
  129. data/lib/chef/provider/user/solaris.rb +2 -0
  130. data/lib/chef/resource.rb +1 -0
  131. data/lib/chef/resource/remote_file.rb +32 -6
  132. data/lib/chef/run_context.rb +22 -0
  133. data/lib/chef/run_lock.rb +43 -4
  134. data/lib/chef/version.rb +2 -2
  135. data/spec/functional/http/simple_spec.rb +84 -0
  136. data/spec/functional/resource/remote_file_spec.rb +107 -43
  137. data/spec/functional/rest_spec.rb +94 -0
  138. data/spec/functional/run_lock_spec.rb +1 -1
  139. data/spec/functional/win32/service_manager_spec.rb +6 -0
  140. data/spec/integration/knife/chef_fs_data_store_spec.rb +2 -0
  141. data/spec/integration/recipes/lwrp_inline_resources_spec.rb +76 -0
  142. data/spec/spec_helper.rb +2 -0
  143. data/spec/support/mock/platform.rb +7 -0
  144. data/spec/support/pedant/pedant_config.rb +121 -0
  145. data/spec/support/pedant/run_pedant.rb +63 -0
  146. data/spec/support/pedant/stickywicket.pem +27 -0
  147. data/spec/support/shared/functional/http.rb +242 -0
  148. data/spec/support/shared/unit/api_error_inspector.rb +2 -2
  149. data/spec/unit/api_client_spec.rb +2 -2
  150. data/spec/unit/application/client_spec.rb +6 -1
  151. data/spec/unit/application/knife_spec.rb +4 -0
  152. data/spec/unit/application/solo_spec.rb +2 -0
  153. data/spec/unit/application_spec.rb +7 -0
  154. data/spec/unit/client_spec.rb +16 -0
  155. data/spec/unit/config_spec.rb +3 -20
  156. data/spec/unit/cookbook_version_spec.rb +224 -122
  157. data/spec/unit/formatters/error_inspectors/compile_error_inspector_spec.rb +2 -2
  158. data/spec/unit/formatters/error_inspectors/cookbook_resolve_error_inspector_spec.rb +2 -2
  159. data/spec/unit/formatters/error_inspectors/cookbook_sync_error_inspector_spec.rb +2 -2
  160. data/spec/unit/formatters/error_inspectors/resource_failure_inspector_spec.rb +2 -2
  161. data/spec/unit/formatters/error_inspectors/run_list_expansion_error_inspector_spec.rb +2 -2
  162. data/spec/unit/handler_spec.rb +0 -1
  163. data/spec/unit/knife/client_bulk_delete_spec.rb +3 -0
  164. data/spec/unit/knife/cookbook_bulk_delete_spec.rb +2 -0
  165. data/spec/unit/knife/cookbook_metadata_spec.rb +2 -2
  166. data/spec/unit/knife/cookbook_site_install_spec.rb +3 -1
  167. data/spec/unit/knife/cookbook_upload_spec.rb +10 -10
  168. data/spec/unit/knife/node_environment_set_spec.rb +80 -0
  169. data/spec/unit/knife/user_create_spec.rb +6 -4
  170. data/spec/unit/knife/user_edit_spec.rb +5 -0
  171. data/spec/unit/knife_spec.rb +3 -0
  172. data/spec/unit/mixin/securable_spec.rb +18 -20
  173. data/spec/unit/node/attribute_spec.rb +15 -2
  174. data/spec/unit/node/immutable_collections_spec.rb +4 -4
  175. data/spec/unit/provider/cron_spec.rb +14 -14
  176. data/spec/unit/provider/git_spec.rb +4 -4
  177. data/spec/unit/provider/group_spec.rb +1 -1
  178. data/spec/unit/provider/ohai_spec.rb +2 -2
  179. data/spec/unit/provider/remote_file/content_spec.rb +58 -35
  180. data/spec/unit/provider/remote_file/local_file_spec.rb +23 -0
  181. data/spec/unit/provider/service/solaris_smf_service_spec.rb +13 -13
  182. data/spec/unit/resource/mount_spec.rb +0 -1
  183. data/spec/unit/resource/remote_file_spec.rb +29 -0
  184. data/spec/unit/resource_spec.rb +1 -1
  185. data/spec/unit/run_context_spec.rb +7 -0
  186. data/spec/unit/run_lock_spec.rb +98 -0
  187. data/spec/unit/version_constraint_spec.rb +1 -1
  188. metadata +164 -151
  189. data/distro/common/html/_static/chef.css +0 -507
  190. data/distro/common/html/_static/chef_logo.png +0 -0
  191. data/lib/chef/checksum/storage.rb +0 -18
  192. data/lib/chef/checksum/storage/filesystem.rb +0 -56
  193. data/spec/unit/checksum/storage/filesystem_spec.rb +0 -70
@@ -43,7 +43,7 @@ class Chef
43
43
  map { |child_name| make_child(child_name) }.
44
44
  select do |entry|
45
45
  # empty cookbooks and cookbook directories are ignored
46
- if entry.children.size == 0
46
+ if !entry.can_upload?
47
47
  Chef::Log.warn("Cookbook '#{entry.name}' is empty or entirely chefignored at #{entry.path_for_printing}")
48
48
  false
49
49
  else
@@ -59,6 +59,25 @@ class Chef
59
59
  is_dir && !name.start_with?('.')
60
60
  end
61
61
 
62
+ def write_cookbook(cookbook_path, cookbook_version_json, from_fs)
63
+ cookbook_name = File.basename(cookbook_path)
64
+ child = make_child(cookbook_name)
65
+
66
+ # Use the copy/diff algorithm to copy it down so we don't destroy
67
+ # chefignored data. This is terribly un-thread-safe.
68
+ Chef::ChefFS::FileSystem.copy_to(Chef::ChefFS::FilePattern.new("/#{cookbook_path}"), from_fs, child, nil, {:purge => true})
69
+
70
+ # Write out .uploaded-cookbook-version.json
71
+ cookbook_file_path = File.join(file_path, cookbook_name)
72
+ if !File.exists?(cookbook_file_path)
73
+ FileUtils.mkdir_p(cookbook_file_path)
74
+ end
75
+ uploaded_cookbook_version_path = File.join(cookbook_file_path, Chef::Cookbook::CookbookVersionLoader::UPLOADED_COOKBOOK_VERSION_FILE)
76
+ File.open(uploaded_cookbook_version_path, 'w') do |file|
77
+ file.write(cookbook_version_json)
78
+ end
79
+ end
80
+
62
81
  protected
63
82
 
64
83
  def make_child(child_name)
@@ -18,8 +18,9 @@
18
18
 
19
19
  require 'chef/chef_fs/file_system/base_fs_dir'
20
20
  require 'chef/chef_fs/file_system/rest_list_dir'
21
- require 'chef/chef_fs/file_system/not_found_error'
21
+ require 'chef/chef_fs/file_system/already_exists_error'
22
22
  require 'chef/chef_fs/file_system/must_delete_recursively_error'
23
+ require 'chef/chef_fs/file_system/not_found_error'
23
24
  require 'chef/chef_fs/path_utils'
24
25
  require 'fileutils'
25
26
 
@@ -48,15 +49,18 @@ class Chef
48
49
 
49
50
  def create_child(child_name, file_contents=nil)
50
51
  child = make_child(child_name)
52
+ if child.exists?
53
+ raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, child)
54
+ end
51
55
  if file_contents
52
56
  child.write(file_contents)
53
57
  else
54
58
  begin
55
59
  Dir.mkdir(child.file_path)
56
60
  rescue Errno::EEXIST
61
+ raise Chef::ChefFS::FileSystem::AlreadyExistsError.new(:create_child, child)
57
62
  end
58
63
  end
59
- @children = nil
60
64
  child
61
65
  end
62
66
 
@@ -75,6 +79,10 @@ class Chef
75
79
  end
76
80
  end
77
81
 
82
+ def exists?
83
+ File.exists?(file_path)
84
+ end
85
+
78
86
  def read
79
87
  begin
80
88
  File.open(file_path, "rb") {|f| f.read}
@@ -496,7 +496,7 @@ class Chef
496
496
  if Chef::Config[:ssl_verify_mode] == :verify_none and !Chef::Config[:verify_api_cert]
497
497
  Chef::Log.warn(<<-WARN)
498
498
 
499
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
499
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
500
500
  SSL validation of HTTPS requests is disabled. HTTPS connections are still
501
501
  encrypted, but chef is not able to detect forged replies or man in the middle
502
502
  attacks.
@@ -518,7 +518,7 @@ To check your SSL configuration, or troubleshoot errors, you can use the
518
518
  knife ssl check -c #{Chef::Config.config_file}
519
519
  ```
520
520
 
521
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
521
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
522
522
  WARN
523
523
  end
524
524
  end
@@ -530,4 +530,3 @@ end
530
530
  require 'chef/cookbook_loader'
531
531
  require 'chef/cookbook_version'
532
532
  require 'chef/cookbook/synchronizer'
533
-
@@ -85,7 +85,7 @@ class Chef
85
85
  def self.platform_specific_path(path)
86
86
  if on_windows?
87
87
  # turns /etc/chef/client.rb into C:/chef/client.rb
88
- system_drive = ENV['SYSTEMDRIVE'] ? ENV['SYSTEMDRIVE'] : ""
88
+ system_drive = env['SYSTEMDRIVE'] ? env['SYSTEMDRIVE'] : ""
89
89
  path = File.join(system_drive, path.split('/')[2..-1])
90
90
  # ensure all forward slashes are backslashes
91
91
  path.gsub!(File::SEPARATOR, (File::ALT_SEPARATOR || '\\'))
@@ -489,17 +489,21 @@ class Chef
489
489
  default :hints, {}
490
490
  end
491
491
 
492
- # Those lists of regular expressions define what chef considers a
493
- # valid user and group name
494
- if RUBY_PLATFORM =~ /mswin|mingw|windows/
492
+ def self.set_defaults_for_windows
493
+ # Those lists of regular expressions define what chef considers a
494
+ # valid user and group name
495
495
  # From http://technet.microsoft.com/en-us/library/cc776019(WS.10).aspx
496
-
497
496
  principal_valid_regex_part = '[^"\/\\\\\[\]\:;|=,+*?<>]+'
498
497
  default :user_valid_regex, [ /^(#{principal_valid_regex_part}\\)?#{principal_valid_regex_part}$/ ]
499
498
  default :group_valid_regex, [ /^(#{principal_valid_regex_part}\\)?#{principal_valid_regex_part}$/ ]
500
499
 
501
500
  default :fatal_windows_admin_check, false
502
- else
501
+ end
502
+
503
+ def self.set_defaults_for_nix
504
+ # Those lists of regular expressions define what chef considers a
505
+ # valid user and group name
506
+ #
503
507
  # user/group cannot start with '-', '+' or '~'
504
508
  # user/group cannot contain ':', ',' or non-space-whitespace or null byte
505
509
  # everything else is allowed (UTF-8, spaces, etc) and we delegate to your O/S useradd program to barf or not
@@ -508,9 +512,26 @@ class Chef
508
512
  default :group_valid_regex, [ /^[^-+~:,\t\r\n\f\0]+[^:,\t\r\n\f\0]*$/ ]
509
513
  end
510
514
 
515
+ # Those lists of regular expressions define what chef considers a
516
+ # valid user and group name
517
+ if on_windows?
518
+ set_defaults_for_windows
519
+ else
520
+ set_defaults_for_nix
521
+ end
522
+
523
+ # This provides a hook which rspec can stub so that we can avoid twiddling
524
+ # global state in tests.
525
+ def self.env
526
+ ENV
527
+ end
528
+
529
+ def self.windows_home_path
530
+ windows_home_path = env['SYSTEMDRIVE'] + env['HOMEPATH'] if env['SYSTEMDRIVE'] && env['HOMEPATH']
531
+ end
532
+
511
533
  # returns a platform specific path to the user home dir
512
- windows_home_path = ENV['SYSTEMDRIVE'] + ENV['HOMEPATH'] if ENV['SYSTEMDRIVE'] && ENV['HOMEPATH']
513
- default :user_home, (ENV['HOME'] || windows_home_path || ENV['USERPROFILE'])
534
+ default( :user_home ) { env['HOME'] || windows_home_path || env['USERPROFILE'] }
514
535
 
515
536
  # Enable file permission fixup for selinux. Fixup will be done
516
537
  # only if selinux is enabled in the system.
@@ -526,6 +547,11 @@ class Chef
526
547
  # the directory that files are going to reside.
527
548
  default :file_staging_uses_destdir, false
528
549
 
550
+ # Exit if another run is in progress and the chef-client is unable to
551
+ # get the lock before time expires. If nil, no timeout is enforced. (Exits
552
+ # immediately if 0.)
553
+ default :run_lock_timeout, nil
554
+
529
555
  # If installed via an omnibus installer, this gives the path to the
530
556
  # "embedded" directory which contains all of the software packaged with
531
557
  # omnibus. This is used to locate the cacert.pem file on windows.
@@ -17,13 +17,19 @@ class Chef
17
17
  :resource_filenames,
18
18
  :provider_filenames]
19
19
 
20
+ UPLOADED_COOKBOOK_VERSION_FILE = ".uploaded-cookbook-version.json".freeze
20
21
 
21
22
  attr_reader :cookbook_name
22
23
  attr_reader :cookbook_settings
24
+ attr_reader :cookbook_paths
23
25
  attr_reader :metadata_filenames
26
+ attr_reader :frozen
27
+ attr_reader :uploaded_cookbook_version_file
24
28
 
25
29
  def initialize(path, chefignore=nil)
26
- @cookbook_path = File.expand_path( path )
30
+ @cookbook_path = File.expand_path( path ) # cookbook_path from which this was loaded
31
+ # We keep a list of all cookbook paths that have been merged in
32
+ @cookbook_paths = [ @cookbook_path ]
27
33
  @cookbook_name = File.basename( path )
28
34
  @chefignore = chefignore
29
35
  @metadata = Hash.new
@@ -56,12 +62,21 @@ class Chef
56
62
 
57
63
  remove_ignored_files
58
64
 
65
+ if File.exists?(File.join(@cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE))
66
+ @uploaded_cookbook_version_file = File.join(@cookbook_path, UPLOADED_COOKBOOK_VERSION_FILE)
67
+ end
68
+
59
69
  if File.exists?(File.join(@cookbook_path, "metadata.rb"))
60
70
  @metadata_filenames << File.join(@cookbook_path, "metadata.rb")
61
71
  elsif File.exists?(File.join(@cookbook_path, "metadata.json"))
62
72
  @metadata_filenames << File.join(@cookbook_path, "metadata.json")
73
+ elsif @uploaded_cookbook_version_file
74
+ @metadata_filenames << @uploaded_cookbook_version_file
63
75
  end
64
76
 
77
+ # Set frozen based on .uploaded-cookbook-version.json
78
+ set_frozen
79
+
65
80
  if empty?
66
81
  Chef::Log.warn "found a directory #{cookbook_name} in the cookbook path, but it contains no cookbook files. skipping."
67
82
  end
@@ -71,8 +86,7 @@ class Chef
71
86
  def cookbook_version
72
87
  return nil if empty?
73
88
 
74
- Chef::CookbookVersion.new(@cookbook_name.to_sym).tap do |c|
75
- c.root_dir = @cookbook_path
89
+ Chef::CookbookVersion.new(@cookbook_name.to_sym, *@cookbook_paths).tap do |c|
76
90
  c.attribute_filenames = cookbook_settings[:attribute_filenames].values
77
91
  c.definition_filenames = cookbook_settings[:definition_filenames].values
78
92
  c.recipe_filenames = cookbook_settings[:recipe_filenames].values
@@ -84,6 +98,7 @@ class Chef
84
98
  c.root_filenames = cookbook_settings[:root_filenames].values
85
99
  c.metadata_filenames = @metadata_filenames
86
100
  c.metadata = metadata(c)
101
+ c.freeze_version if @frozen
87
102
  end
88
103
  end
89
104
 
@@ -94,6 +109,8 @@ class Chef
94
109
  case metadata_file
95
110
  when /\.rb$/
96
111
  apply_ruby_metadata(metadata_file)
112
+ when @uploaded_cookbook_version_file
113
+ apply_json_cookbook_version_metadata(metadata_file)
97
114
  when /\.json$/
98
115
  apply_json_metadata(metadata_file)
99
116
  else
@@ -104,7 +121,7 @@ class Chef
104
121
  end
105
122
 
106
123
  def empty?
107
- @cookbook_settings.values.all? { |files_hash| files_hash.empty? }
124
+ @cookbook_settings.values.all? { |files_hash| files_hash.empty? } && @metadata_filenames.size == 0
108
125
  end
109
126
 
110
127
  def merge!(other_cookbook_loader)
@@ -113,6 +130,8 @@ class Chef
113
130
  file_list.merge!(other_cookbook_settings[file_type])
114
131
  end
115
132
  @metadata_filenames.concat(other_cookbook_loader.metadata_filenames)
133
+ @cookbook_paths += other_cookbook_loader.cookbook_paths
134
+ @frozen = true if other_cookbook_loader.frozen
116
135
  end
117
136
 
118
137
  def chefignore
@@ -122,6 +141,7 @@ class Chef
122
141
  def load_root_files
123
142
  Dir.glob(File.join(@cookbook_path, '*'), File::FNM_DOTMATCH).each do |file|
124
143
  next if File.directory?(file)
144
+ next if File.basename(file) == UPLOADED_COOKBOOK_VERSION_FILE
125
145
  @cookbook_settings[:root_filenames][file[@relative_path, 1]] = file
126
146
  end
127
147
  end
@@ -166,6 +186,27 @@ class Chef
166
186
  end
167
187
  end
168
188
 
189
+ def apply_json_cookbook_version_metadata(file)
190
+ begin
191
+ data = Chef::JSONCompat.from_json(IO.read(file), :create_additions => false)
192
+ @metadata.from_hash(data['metadata'])
193
+ rescue JSON::ParserError
194
+ Chef::Log.error("Couldn't parse cookbook metadata JSON for #@cookbook_name in " + file)
195
+ raise
196
+ end
197
+ end
198
+
199
+ def set_frozen
200
+ if uploaded_cookbook_version_file
201
+ begin
202
+ data = Chef::JSONCompat.from_json(IO.read(uploaded_cookbook_version_file), :create_additions => false)
203
+ @frozen = data['frozen?']
204
+ rescue JSON::ParserError
205
+ Chef::Log.error("Couldn't parse cookbook metadata JSON for #@cookbook_name in #{uploaded_cookbook_version_file}")
206
+ raise
207
+ end
208
+ end
209
+ end
169
210
  end
170
211
  end
171
212
  end
@@ -26,6 +26,8 @@ require 'chef/recipe'
26
26
  require 'chef/cookbook/file_vendor'
27
27
  require 'chef/cookbook/metadata'
28
28
  require 'chef/version_class'
29
+ require 'pathname'
30
+ require 'chef/monkey_patches/pathname'
29
31
 
30
32
  class Chef
31
33
 
@@ -42,7 +44,7 @@ class Chef
42
44
 
43
45
  COOKBOOK_SEGMENTS = [ :resources, :providers, :recipes, :definitions, :libraries, :attributes, :files, :templates, :root_files ]
44
46
 
45
- attr_accessor :root_dir
47
+ attr_accessor :root_paths
46
48
  attr_accessor :definition_filenames
47
49
  attr_accessor :template_filenames
48
50
  attr_accessor :file_filenames
@@ -66,6 +68,11 @@ class Chef
66
68
  attr_reader :recipe_filenames_by_name
67
69
  attr_reader :attribute_filenames_by_short_filename
68
70
 
71
+ # The first root path is the primary cookbook dir, from which metadata is loaded
72
+ def root_dir
73
+ root_paths[0]
74
+ end
75
+
69
76
  # This is the one and only method that knows how cookbook files'
70
77
  # checksums are generated.
71
78
  def self.checksum_cookbook_file(filepath)
@@ -83,8 +90,9 @@ class Chef
83
90
  #
84
91
  # === Returns
85
92
  # object<Chef::CookbookVersion>:: Duh. :)
86
- def initialize(name)
93
+ def initialize(name, *root_paths)
87
94
  @name = name
95
+ @root_paths = root_paths
88
96
  @frozen = false
89
97
  @attribute_filenames = Array.new
90
98
  @definition_filenames = Array.new
@@ -96,7 +104,6 @@ class Chef
96
104
  @resource_filenames = Array.new
97
105
  @provider_filenames = Array.new
98
106
  @metadata_filenames = Array.new
99
- @root_dir = nil
100
107
  @root_filenames = Array.new
101
108
  @status = :ready
102
109
  @manifest = nil
@@ -481,11 +488,11 @@ class Chef
481
488
  end
482
489
 
483
490
  def metadata_json_file
484
- File.join(root_dir, "metadata.json")
491
+ File.join(root_paths[0], "metadata.json")
485
492
  end
486
493
 
487
494
  def metadata_rb_file
488
- File.join(root_dir, "metadata.rb")
495
+ File.join(root_paths[0], "metadata.rb")
489
496
  end
490
497
 
491
498
  def reload_metadata!
@@ -605,42 +612,26 @@ class Chef
605
612
  })
606
613
  checksums_to_on_disk_paths = {}
607
614
 
615
+ if !root_paths || root_paths.size == 0
616
+ Chef::Log.error("Cookbook #{name} does not have root_paths! Cannot generate manifest.")
617
+ raise "Cookbook #{name} does not have root_paths! Cannot generate manifest."
618
+ end
619
+
608
620
  COOKBOOK_SEGMENTS.each do |segment|
609
621
  segment_filenames(segment).each do |segment_file|
610
622
  next if File.directory?(segment_file)
611
623
 
612
- file_name = nil
613
- path = nil
614
- specificity = "default"
615
-
616
- if segment == :root_files
617
- matcher = segment_file.match(".+/#{Regexp.escape(name.to_s)}/(.+)")
618
- file_name = matcher[1]
619
- path = file_name
620
- elsif segment == :templates || segment == :files
621
- matcher = segment_file.match("/#{Regexp.escape(name.to_s)}/(#{Regexp.escape(segment.to_s)}/(.+?)/(.+))")
622
- unless matcher
623
- Chef::Log.debug("Skipping file #{segment_file}, as it isn't in any of the proper directories (platform-version, platform or default)")
624
- Chef::Log.debug("You probably need to move #{segment_file} into the 'default' sub-directory")
625
- next
626
- end
627
- path = matcher[1]
628
- specificity = matcher[2]
629
- file_name = matcher[3]
630
- else
631
- matcher = segment_file.match("/#{Regexp.escape(name.to_s)}/(#{Regexp.escape(segment.to_s)}/(.+))")
632
- path = matcher[1]
633
- file_name = matcher[2]
634
- end
624
+ path, specificity = parse_segment_file_from_root_paths(segment, segment_file)
625
+ file_name = File.basename(path)
635
626
 
636
627
  csum = self.class.checksum_cookbook_file(segment_file)
637
628
  checksums_to_on_disk_paths[csum] = segment_file
638
629
  rs = Mash.new({
639
630
  :name => file_name,
640
631
  :path => path,
641
- :checksum => csum
632
+ :checksum => csum,
633
+ :specificity => specificity
642
634
  })
643
- rs[:specificity] = specificity
644
635
 
645
636
  manifest[segment] << rs
646
637
  end
@@ -656,6 +647,23 @@ class Chef
656
647
  @manifest_records_by_path = extract_manifest_records_by_path(manifest)
657
648
  end
658
649
 
650
+ def parse_segment_file_from_root_paths(segment, segment_file)
651
+ root_paths.each do |root_path|
652
+ pathname = Pathname.new(segment_file).relative_path_from(Pathname.new(root_path))
653
+
654
+ parts = pathname.each_filename.take(2)
655
+ # Check if path is actually under root_path
656
+ next if parts[0] == '..'
657
+ if segment == :templates || segment == :files
658
+ return [ pathname.to_s, parts[1] ]
659
+ else
660
+ return [ pathname.to_s, 'default' ]
661
+ end
662
+ end
663
+ Chef::Log.error("Cookbook file #{segment_file} not under cookbook root paths #{root_paths.inspect}.")
664
+ raise "Cookbook file #{segment_file} not under cookbook root paths #{root_paths.inspect}."
665
+ end
666
+
659
667
  def file_vendor
660
668
  unless @file_vendor
661
669
  @file_vendor = Chef::Cookbook::FileVendor.create_from_manifest(manifest)
@@ -17,7 +17,6 @@
17
17
  # limitations under the License.
18
18
  #
19
19
 
20
- require 'chef/resource'
21
20
  require 'chef/resource_platform_map'
22
21
  require 'chef/mixin/convert_to_class_name'
23
22
 
@@ -152,6 +151,10 @@ class Chef
152
151
  end
153
152
  end
154
153
 
154
+ # We require this at the BOTTOM of this file to avoid circular requires (it is used
155
+ # at runtime but not load time)
156
+ require 'chef/resource'
157
+
155
158
  # **DEPRECATED**
156
159
  # This used to be part of chef/mixin/recipe_definition_dsl_core. Load the file to activate the deprecation code.
157
160
  require 'chef/mixin/recipe_definition_dsl_core'