chef 12.0.0.alpha.1 → 12.0.0.alpha.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/lib/chef/application.rb +8 -1
  3. data/lib/chef/application/apply.rb +4 -0
  4. data/lib/chef/application/client.rb +7 -7
  5. data/lib/chef/application/solo.rb +21 -13
  6. data/lib/chef/chef_fs/chef_fs_data_store.rb +60 -6
  7. data/lib/chef/chef_fs/config.rb +78 -4
  8. data/lib/chef/chef_fs/data_handler/acl_data_handler.rb +2 -2
  9. data/lib/chef/chef_fs/data_handler/client_data_handler.rb +1 -1
  10. data/lib/chef/chef_fs/data_handler/container_data_handler.rb +1 -1
  11. data/lib/chef/chef_fs/data_handler/cookbook_data_handler.rb +1 -1
  12. data/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb +1 -1
  13. data/lib/chef/chef_fs/data_handler/data_handler_base.rb +76 -2
  14. data/lib/chef/chef_fs/data_handler/environment_data_handler.rb +1 -1
  15. data/lib/chef/chef_fs/data_handler/group_data_handler.rb +1 -1
  16. data/lib/chef/chef_fs/data_handler/node_data_handler.rb +1 -1
  17. data/lib/chef/chef_fs/data_handler/organization_data_handler.rb +30 -0
  18. data/lib/chef/chef_fs/data_handler/organization_invites_data_handler.rb +17 -0
  19. data/lib/chef/chef_fs/data_handler/organization_members_data_handler.rb +17 -0
  20. data/lib/chef/chef_fs/data_handler/role_data_handler.rb +1 -1
  21. data/lib/chef/chef_fs/data_handler/user_data_handler.rb +2 -1
  22. data/lib/chef/chef_fs/file_system.rb +0 -1
  23. data/lib/chef/chef_fs/file_system/acl_entry.rb +1 -1
  24. data/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_dir.rb +1 -1
  25. data/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb +5 -1
  26. data/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb +73 -13
  27. data/lib/chef/chef_fs/file_system/chef_server_root_dir.rb +44 -5
  28. data/lib/chef/chef_fs/file_system/cookbook_dir.rb +1 -1
  29. data/lib/chef/chef_fs/file_system/cookbooks_dir.rb +3 -3
  30. data/lib/chef/chef_fs/file_system/org_entry.rb +34 -0
  31. data/lib/chef/chef_fs/file_system/organization_invites_entry.rb +58 -0
  32. data/lib/chef/chef_fs/file_system/organization_members_entry.rb +57 -0
  33. data/lib/chef/chef_fs/file_system/rest_list_entry.rb +13 -4
  34. data/lib/chef/chef_fs/knife.rb +1 -1
  35. data/lib/chef/client.rb +8 -2
  36. data/lib/chef/config.rb +75 -57
  37. data/lib/chef/config_fetcher.rb +6 -21
  38. data/lib/chef/dsl/data_query.rb +48 -3
  39. data/lib/chef/dsl/platform_introspection.rb +42 -0
  40. data/lib/chef/dsl/reboot_pending.rb +6 -3
  41. data/lib/chef/encrypted_data_bag_item.rb +1 -1
  42. data/lib/chef/encrypted_data_bag_item/encryptor.rb +12 -0
  43. data/lib/chef/exceptions.rb +2 -0
  44. data/lib/chef/http/basic_client.rb +14 -0
  45. data/lib/chef/http/json_output.rb +7 -2
  46. data/lib/chef/knife.rb +36 -121
  47. data/lib/chef/knife/bootstrap.rb +68 -54
  48. data/lib/chef/knife/bootstrap/archlinux-gems.erb +6 -1
  49. data/lib/chef/knife/bootstrap/chef-aix.erb +5 -0
  50. data/lib/chef/knife/bootstrap/chef-full.erb +5 -1
  51. data/lib/chef/knife/core/bootstrap_context.rb +70 -29
  52. data/lib/chef/knife/search.rb +56 -12
  53. data/lib/chef/knife/serve.rb +1 -1
  54. data/lib/chef/local_mode.rb +10 -4
  55. data/lib/chef/mixin/deep_merge.rb +6 -3
  56. data/lib/chef/mixin/shell_out.rb +33 -17
  57. data/lib/chef/null_logger.rb +72 -0
  58. data/lib/chef/platform.rb +2 -1
  59. data/lib/chef/platform/provider_mapping.rb +1 -1
  60. data/lib/chef/platform/rebooter.rb +54 -0
  61. data/lib/chef/provider/ifconfig.rb +15 -16
  62. data/lib/chef/provider/link.rb +1 -1
  63. data/lib/chef/provider/mount/mount.rb +1 -1
  64. data/lib/chef/provider/mount/solaris.rb +102 -64
  65. data/lib/chef/provider/package/aix.rb +4 -12
  66. data/lib/chef/provider/package/ips.rb +8 -12
  67. data/lib/chef/provider/package/macports.rb +4 -12
  68. data/lib/chef/provider/package/pacman.rb +2 -6
  69. data/lib/chef/provider/package/portage.rb +2 -6
  70. data/lib/chef/provider/package/rpm.rb +4 -12
  71. data/lib/chef/provider/package/solaris.rb +4 -12
  72. data/lib/chef/provider/reboot.rb +69 -0
  73. data/lib/chef/provider/service/debian.rb +10 -10
  74. data/lib/chef/provider/service/freebsd.rb +89 -73
  75. data/lib/chef/provider/service/gentoo.rb +2 -2
  76. data/lib/chef/provider/service/init.rb +6 -4
  77. data/lib/chef/provider/service/insserv.rb +3 -3
  78. data/lib/chef/provider/service/macosx.rb +2 -2
  79. data/lib/chef/provider/service/simple.rb +6 -4
  80. data/lib/chef/provider/service/solaris.rb +1 -1
  81. data/lib/chef/provider/service/systemd.rb +9 -9
  82. data/lib/chef/provider/service/upstart.rb +6 -6
  83. data/lib/chef/provider/subversion.rb +6 -6
  84. data/lib/chef/provider/user/dscl.rb +32 -28
  85. data/lib/chef/provider/user/windows.rb +6 -6
  86. data/lib/chef/provider/whyrun_safe_ruby_block.rb +1 -1
  87. data/lib/chef/providers.rb +1 -0
  88. data/lib/chef/recipe.rb +0 -1
  89. data/lib/chef/resource.rb +3 -5
  90. data/lib/chef/resource/mount.rb +9 -0
  91. data/lib/chef/resource/reboot.rb +48 -0
  92. data/lib/chef/resources.rb +1 -0
  93. data/lib/chef/run_context.rb +25 -0
  94. data/lib/chef/search/query.rb +122 -14
  95. data/lib/chef/util/path_helper.rb +54 -6
  96. data/lib/chef/util/windows/net_user.rb +4 -1
  97. data/lib/chef/version.rb +1 -1
  98. data/lib/chef/win32/api/file.rb +1 -5
  99. data/lib/chef/win32/api/net.rb +1 -0
  100. data/lib/chef/workstation_config_loader.rb +177 -0
  101. data/spec/functional/http/simple_spec.rb +57 -1
  102. data/spec/functional/mixin/shell_out_spec.rb +2 -2
  103. data/spec/functional/provider/whyrun_safe_ruby_block_spec.rb +51 -0
  104. data/spec/functional/rebooter_spec.rb +105 -0
  105. data/spec/functional/resource/deploy_revision_spec.rb +0 -4
  106. data/spec/functional/resource/file_spec.rb +26 -3
  107. data/spec/functional/resource/group_spec.rb +5 -3
  108. data/spec/functional/resource/link_spec.rb +16 -16
  109. data/spec/functional/resource/reboot_spec.rb +103 -0
  110. data/spec/integration/client/client_spec.rb +4 -8
  111. data/spec/integration/client/ipv6_spec.rb +1 -1
  112. data/spec/integration/knife/cookbook_api_ipv6_spec.rb +3 -2
  113. data/spec/integration/knife/delete_spec.rb +39 -0
  114. data/spec/integration/knife/deps_spec.rb +30 -20
  115. data/spec/integration/knife/download_spec.rb +77 -1
  116. data/spec/integration/knife/list_spec.rb +221 -0
  117. data/spec/integration/knife/raw_spec.rb +1 -1
  118. data/spec/integration/knife/show_spec.rb +2 -2
  119. data/spec/integration/knife/upload_spec.rb +154 -1
  120. data/spec/support/pedant/run_pedant.rb +0 -1
  121. data/spec/support/shared/functional/http.rb +8 -1
  122. data/spec/support/shared/integration/integration_helper.rb +11 -19
  123. data/spec/support/shared/unit/platform_introspector.rb +22 -0
  124. data/spec/unit/application/apply.rb +11 -1
  125. data/spec/unit/application/solo_spec.rb +19 -3
  126. data/spec/unit/chef_fs/config_spec.rb +58 -0
  127. data/spec/unit/config_fetcher_spec.rb +1 -3
  128. data/spec/unit/config_spec.rb +247 -220
  129. data/spec/unit/dsl/data_query_spec.rb +165 -23
  130. data/spec/unit/dsl/reboot_pending_spec.rb +1 -7
  131. data/spec/unit/encrypted_data_bag_item_spec.rb +1 -1
  132. data/spec/unit/knife/bootstrap_spec.rb +354 -182
  133. data/spec/unit/knife/core/bootstrap_context_spec.rb +67 -30
  134. data/spec/unit/knife_spec.rb +3 -30
  135. data/spec/unit/mixin/deep_merge_spec.rb +14 -0
  136. data/spec/unit/mixin/shell_out_spec.rb +134 -64
  137. data/spec/unit/provider/ifconfig/debian_spec.rb +19 -9
  138. data/spec/unit/provider/ifconfig/redhat_spec.rb +16 -14
  139. data/spec/unit/provider/ifconfig_spec.rb +3 -3
  140. data/spec/unit/provider/link_spec.rb +5 -5
  141. data/spec/unit/provider/mount/mount_spec.rb +10 -1
  142. data/spec/unit/provider/mount/solaris_spec.rb +185 -11
  143. data/spec/unit/provider/package/aix_spec.rb +5 -17
  144. data/spec/unit/provider/package/ips_spec.rb +8 -21
  145. data/spec/unit/provider/package/macports_spec.rb +12 -12
  146. data/spec/unit/provider/package/pacman_spec.rb +4 -12
  147. data/spec/unit/provider/package/portage_spec.rb +5 -15
  148. data/spec/unit/provider/package/rpm_spec.rb +7 -22
  149. data/spec/unit/provider/package/solaris_spec.rb +5 -16
  150. data/spec/unit/provider/service/arch_service_spec.rb +8 -14
  151. data/spec/unit/provider/service/debian_service_spec.rb +1 -1
  152. data/spec/unit/provider/service/freebsd_service_spec.rb +457 -225
  153. data/spec/unit/provider/service/gentoo_service_spec.rb +2 -2
  154. data/spec/unit/provider/service/init_service_spec.rb +10 -10
  155. data/spec/unit/provider/service/insserv_service_spec.rb +3 -4
  156. data/spec/unit/provider/service/invokercd_service_spec.rb +8 -9
  157. data/spec/unit/provider/service/macosx_spec.rb +5 -5
  158. data/spec/unit/provider/service/simple_service_spec.rb +4 -6
  159. data/spec/unit/provider/service/solaris_smf_service_spec.rb +1 -3
  160. data/spec/unit/provider/service/systemd_service_spec.rb +20 -20
  161. data/spec/unit/provider/service/upstart_service_spec.rb +15 -17
  162. data/spec/unit/provider/subversion_spec.rb +5 -6
  163. data/spec/unit/provider/user/dscl_spec.rb +2 -1
  164. data/spec/unit/provider/user/windows_spec.rb +7 -0
  165. data/spec/unit/provider/whyrun_safe_ruby_block_spec.rb +2 -2
  166. data/spec/unit/resource/mount_spec.rb +9 -0
  167. data/spec/unit/resource_spec.rb +0 -4
  168. data/spec/unit/rest_spec.rb +1 -1
  169. data/spec/unit/run_context_spec.rb +15 -0
  170. data/spec/unit/search/query_spec.rb +196 -40
  171. data/spec/unit/util/path_helper_spec.rb +111 -28
  172. data/spec/unit/workstation_config_loader_spec.rb +283 -0
  173. metadata +36 -20
  174. data/lib/chef/knife/bootstrap/centos5-gems.erb +0 -62
  175. data/lib/chef/knife/bootstrap/fedora13-gems.erb +0 -44
  176. data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +0 -53
  177. data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +0 -48
  178. data/lib/chef/knife/bootstrap/ubuntu12.04-gems.erb +0 -46
  179. data/spec/support/shared/integration/chef_zero_support.rb +0 -130
  180. data/spec/unit/knife/config_file_selection_spec.rb +0 -135
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 52f66afbe3a2085850ce9ab0d1e32644753864d9
4
- data.tar.gz: bcc5aff93e2dcacec5086cf79a21fe2fd9652561
3
+ metadata.gz: b36dd2de3b06d6acb17dfd3c2d1f7beb0ba6d837
4
+ data.tar.gz: 1037ea4cbd93f2f6e1a4939537da08ab24f216fa
5
5
  SHA512:
6
- metadata.gz: a40b8ba07c5997375d554bd31cbede4c177c624b116f688b4e063b60093707d8245173aa7ecefcd092892f5cb351a651e29fa00d22ffd528c9e073494e3cc91a
7
- data.tar.gz: cd4e29fbccd881017e98e09cc75bc075a88c8a1c057e3cdbb481642387e77cb771e71fb9fc92d521bedaac326de9c26d34997f2e113371bc634d88122bdbf16f
6
+ metadata.gz: eb14cff2fbd9f333009de5a2cbe3e6b63b9f5ee537f04f2cbab77ab247ad12764708ba935948aae9e796f4dd0c5d295338f1eb4d44bd857f0d49510acbea5053
7
+ data.tar.gz: c19b61ef0c8c931fab94fcf8e94c0f7a392ef57badcb43c2a347d5bd9517489a3cb8a41c7896bf520d0af2d4c1b92efdbb59482651f227ac785fcc8e47ea4364
@@ -46,6 +46,7 @@ class Chef::Application
46
46
  configure_chef
47
47
  configure_logging
48
48
  configure_proxy_environment_variables
49
+ configure_encoding
49
50
  end
50
51
 
51
52
  # Get this party started
@@ -81,10 +82,11 @@ class Chef::Application
81
82
 
82
83
  # Parse the config file
83
84
  def load_config_file
84
- config_fetcher = Chef::ConfigFetcher.new(config[:config_file], Chef::Config.config_file_jail)
85
+ config_fetcher = Chef::ConfigFetcher.new(config[:config_file])
85
86
  if config[:config_file].nil?
86
87
  Chef::Log.warn("No config file found or specified on command line, using command line options.")
87
88
  elsif config_fetcher.config_missing?
89
+ pp config_missing: true
88
90
  Chef::Log.warn("*****************************************")
89
91
  Chef::Log.warn("Did not find config file: #{config[:config_file]}, using command line options.")
90
92
  Chef::Log.warn("*****************************************")
@@ -174,6 +176,11 @@ class Chef::Application
174
176
  configure_no_proxy
175
177
  end
176
178
 
179
+ # Sets the default external encoding to UTF-8 (users can change this, but they shouldn't)
180
+ def configure_encoding
181
+ Encoding.default_external = Chef::Config[:ruby_encoding]
182
+ end
183
+
177
184
  # Called prior to starting the application, by the run method
178
185
  def setup_application
179
186
  raise Chef::Exceptions::Application, "#{self.to_s}: you must override setup_application"
@@ -134,6 +134,10 @@ class Chef::Application::Apply < Chef::Application
134
134
  @recipe_text = STDIN.read
135
135
  temp_recipe_file
136
136
  else
137
+ if !ARGV[0]
138
+ puts opt_parser
139
+ Chef::Application.exit! "No recipe file provided", 1
140
+ end
137
141
  @recipe_filename = ARGV[0]
138
142
  @recipe_text,@recipe_fh = read_recipe_file @recipe_filename
139
143
  end
@@ -24,6 +24,7 @@ require 'chef/daemon'
24
24
  require 'chef/log'
25
25
  require 'chef/config_fetcher'
26
26
  require 'chef/handler/error_report'
27
+ require 'chef/workstation_config_loader'
27
28
 
28
29
  class Chef::Application::Client < Chef::Application
29
30
 
@@ -219,9 +220,10 @@ class Chef::Application::Client < Chef::Application
219
220
  :long => "--chef-zero-port PORT",
220
221
  :description => "Port (or port range) to start chef-zero on. Port ranges like 1000,1010 or 8889-9999 will try all given ports until one works."
221
222
 
222
- option :config_file_jail,
223
- :long => "--config-file-jail PATH",
224
- :description => "Directory under which config files are allowed to be loaded (no client.rb or knife.rb outside this path will be loaded)."
223
+ option :disable_config,
224
+ :long => "--disable-config",
225
+ :description => "Refuse to load a config file and use defaults. This is for development and not a stable API",
226
+ :boolean => true
225
227
 
226
228
  option :run_lock_timeout,
227
229
  :long => "--run-lock-timeout SECONDS",
@@ -273,11 +275,9 @@ class Chef::Application::Client < Chef::Application
273
275
  end
274
276
 
275
277
  def load_config_file
276
- Chef::Config.config_file_jail = config[:config_file_jail] if config[:config_file_jail]
277
- if !config.has_key?(:config_file)
278
+ if !config.has_key?(:config_file) && !config[:disable_config]
278
279
  if config[:local_mode]
279
- require 'chef/knife'
280
- config[:config_file] = Chef::Knife.locate_config_file
280
+ config[:config_file] = Chef::WorkstationConfigLoader.new(nil, Chef::Log).config_location
281
281
  else
282
282
  config[:config_file] = Chef::Config.platform_specific_path("/etc/chef/client.rb")
283
283
  end
@@ -185,24 +185,22 @@ class Chef::Application::Solo < Chef::Application
185
185
  Chef::Config[:interval] ||= 1800
186
186
  end
187
187
 
188
- if Chef::Config[:json_attribs]
189
- config_fetcher = Chef::ConfigFetcher.new(Chef::Config[:json_attribs])
190
- @chef_client_json = config_fetcher.fetch_json
191
- end
192
-
193
188
  if Chef::Config[:recipe_url]
194
189
  cookbooks_path = Array(Chef::Config[:cookbook_path]).detect{|e| e =~ /\/cookbooks\/*$/ }
195
190
  recipes_path = File.expand_path(File.join(cookbooks_path, '..'))
196
191
 
197
192
  Chef::Log.debug "Creating path #{recipes_path} to extract recipes into"
198
- FileUtils.mkdir_p recipes_path
199
- path = File.join(recipes_path, 'recipes.tgz')
200
- File.open(path, 'wb') do |f|
201
- open(Chef::Config[:recipe_url]) do |r|
202
- f.write(r.read)
203
- end
204
- end
205
- Chef::Mixin::Command.run_command(:command => "tar zxvf #{path} -C #{recipes_path}")
193
+ FileUtils.mkdir_p(recipes_path)
194
+ tarball_path = File.join(recipes_path, 'recipes.tgz')
195
+ fetch_recipe_tarball(Chef::Config[:recipe_url], tarball_path)
196
+ Chef::Mixin::Command.run_command(:command => "tar zxvf #{tarball_path} -C #{recipes_path}")
197
+ end
198
+
199
+ # json_attribs shuld be fetched after recipe_url tarball is unpacked.
200
+ # Otherwise it may fail if points to local file from tarball.
201
+ if Chef::Config[:json_attribs]
202
+ config_fetcher = Chef::ConfigFetcher.new(Chef::Config[:json_attribs])
203
+ @chef_client_json = config_fetcher.fetch_json
206
204
  end
207
205
  end
208
206
 
@@ -246,4 +244,14 @@ class Chef::Application::Solo < Chef::Application
246
244
  end
247
245
  end
248
246
 
247
+ private
248
+
249
+ def fetch_recipe_tarball(url, path)
250
+ Chef::Log.debug("Download recipes tarball from #{url} to #{path}")
251
+ File.open(path, 'wb') do |f|
252
+ open(url) do |r|
253
+ f.write(r.read)
254
+ end
255
+ end
256
+ end
249
257
  end
@@ -27,7 +27,61 @@ require 'fileutils'
27
27
 
28
28
  class Chef
29
29
  module ChefFS
30
+ #
31
+ # Translation layer between chef-zero's DataStore (a place where it expects
32
+ # files to be stored) and ChefFS (the user's repository directory layout).
33
+ #
34
+ # chef-zero expects the data store to store files *its* way--for example, it
35
+ # expects get("nodes/blah") to return the JSON text for the blah node, and
36
+ # it expects get("cookbooks/blah/1.0.0") to return the JSON definition of
37
+ # the blah cookbook version 1.0.0.
38
+ #
39
+ # The repository is defined the way the *user* wants their layout. These
40
+ # two things are very similar in layout (for example, nodes are stored under
41
+ # the nodes/ directory and their filename is the name of the node).
42
+ #
43
+ # However, there are a few differences that make this more than just a raw
44
+ # file store:
45
+ #
46
+ # 1. Cookbooks are stored much differently.
47
+ # - chef-zero places JSON text with the checksums for the cookbook at
48
+ # /cookbooks/NAME/VERSION, and expects the JSON to contain URLs to the
49
+ # actual files, which are stored elsewhere.
50
+ # - The repository contains an actual directory with just the cookbook
51
+ # files and a metadata.rb containing a version #. There is no JSON to
52
+ # be found.
53
+ # - Further, if versioned_cookbooks is false, that directory is named
54
+ # /cookbooks/NAME and only one version exists. If versioned_cookbooks
55
+ # is true, the directory is named /cookbooks/NAME-VERSION.
56
+ # - Therefore, ChefFSDataStore calculates the cookbook JSON by looking at
57
+ # the files in the cookbook and checksumming them, and reading metadata.rb
58
+ # for the version and dependency information.
59
+ # - ChefFSDataStore also modifies the cookbook file URLs so that they point
60
+ # to /file_store/repo/<filename> (the path to the actual file under the
61
+ # repository root). For example, /file_store/repo/apache2/metadata.rb or
62
+ # /file_store/repo/cookbooks/apache2/recipes/default.rb).
63
+ #
64
+ # 2. Sandboxes don't exist in the repository.
65
+ # - ChefFSDataStore lets cookbooks be uploaded into a temporary memory
66
+ # storage, and when the cookbook is committed, copies the files onto the
67
+ # disk in the correct place (/cookbooks/apache2/recipes/default.rb).
68
+ # 3. Data bags:
69
+ # - The Chef server expects data bags in /data/BAG/ITEM
70
+ # - The repository stores data bags in /data_bags/BAG/ITEM
71
+ #
72
+ # 4. JSON filenames are generally NAME.json in the repository (e.g. /nodes/foo.json).
73
+ #
30
74
  class ChefFSDataStore
75
+ #
76
+ # Create a new ChefFSDataStore
77
+ #
78
+ # ==== Arguments
79
+ #
80
+ # [chef_fs]
81
+ # A +ChefFS::FileSystem+ object representing the repository root.
82
+ # Generally will be a +ChefFS::FileSystem::ChefRepositoryFileSystemRoot+
83
+ # object, created from +ChefFS::Config.local_fs+.
84
+ #
31
85
  def initialize(chef_fs)
32
86
  @chef_fs = chef_fs
33
87
  @memory_store = ChefZero::DataStore::MemoryStore.new
@@ -103,7 +157,7 @@ class Chef
103
157
  value.each do |file|
104
158
  if file.is_a?(Hash) && file.has_key?('checksum')
105
159
  relative = ['file_store', 'repo', 'cookbooks']
106
- if Chef::Config.versioned_cookbooks
160
+ if chef_fs.versioned_cookbooks
107
161
  relative << "#{path[1]}-#{path[2]}"
108
162
  else
109
163
  relative << path[1]
@@ -190,7 +244,7 @@ class Chef
190
244
  elsif path[0] == 'cookbooks' && path.length == 1
191
245
  with_entry(path) do |entry|
192
246
  begin
193
- if Chef::Config.versioned_cookbooks
247
+ if chef_fs.versioned_cookbooks
194
248
  # /cookbooks/name-version -> /cookbooks/name
195
249
  entry.children.map { |child| split_name_version(child.name)[0] }.uniq
196
250
  else
@@ -203,7 +257,7 @@ class Chef
203
257
  end
204
258
 
205
259
  elsif path[0] == 'cookbooks' && path.length == 2
206
- if Chef::Config.versioned_cookbooks
260
+ if chef_fs.versioned_cookbooks
207
261
  result = with_entry([ 'cookbooks' ]) do |entry|
208
262
  # list /cookbooks/name = filter /cookbooks/name-version down to name
209
263
  entry.children.map { |child| split_name_version(child.name) }.
@@ -261,7 +315,7 @@ class Chef
261
315
  end
262
316
 
263
317
  def write_cookbook(path, data, *options)
264
- if Chef::Config.versioned_cookbooks
318
+ if chef_fs.versioned_cookbooks
265
319
  cookbook_path = File.join('cookbooks', "#{path[1]}-#{path[2]}")
266
320
  else
267
321
  cookbook_path = File.join('cookbooks', path[1])
@@ -318,7 +372,7 @@ class Chef
318
372
  elsif path[0] == 'cookbooks'
319
373
  if path.length == 2
320
374
  raise ChefZero::DataStore::DataNotFoundError.new(path)
321
- elsif Chef::Config.versioned_cookbooks
375
+ elsif chef_fs.versioned_cookbooks
322
376
  if path.length >= 3
323
377
  # cookbooks/name/version -> cookbooks/name-version
324
378
  path = [ path[0], "#{path[1]}-#{path[2]}" ] + path[3..-1]
@@ -351,7 +405,7 @@ class Chef
351
405
  end
352
406
 
353
407
  elsif path[0] == 'cookbooks'
354
- if Chef::Config.versioned_cookbooks
408
+ if chef_fs.versioned_cookbooks
355
409
  # cookbooks/name-version/... -> cookbooks/name/version/...
356
410
  if path.length >= 2
357
411
  name, version = split_name_version(path[1])
@@ -22,17 +22,87 @@ require 'chef/chef_fs/path_utils'
22
22
  class Chef
23
23
  module ChefFS
24
24
  #
25
- # Helpers to take Chef::Config and create chef_fs and local_fs from it
25
+ # Helpers to take Chef::Config and create chef_fs and local_fs (ChefFS
26
+ # objects representing the server and local repository, respectively).
26
27
  #
27
28
  class Config
28
- def initialize(chef_config = Chef::Config, cwd = Dir.pwd, options = {})
29
+ #
30
+ # Create a new Config object which can produce a chef_fs and local_fs.
31
+ #
32
+ # ==== Arguments
33
+ #
34
+ # [chef_config]
35
+ # A hash that looks suspiciously like +Chef::Config+. These hash keys
36
+ # include:
37
+ #
38
+ # :chef_repo_path::
39
+ # The root where all local chef object data is stored. Mirrors
40
+ # +Chef::Config.chef_repo_path+
41
+ # :cookbook_path, node_path, ...::
42
+ # Paths to cookbooks/, nodes/, data_bags/, etc. Mirrors
43
+ # +Chef::Config.cookbook_path+, etc. Defaults to
44
+ # +<chef_repo_path>/cookbooks+, etc.
45
+ # :repo_mode::
46
+ # The directory format on disk. 'everything', 'hosted_everything' and
47
+ # 'static'. Default: autodetected based on whether the URL has
48
+ # "/organizations/NAME."
49
+ # :versioned_cookbooks::
50
+ # If true, the repository contains cookbooks with versions in their
51
+ # name (apache2-1.0.0). If false, the repository just has one version
52
+ # of each cookbook and the directory has the cookbook name (apache2).
53
+ # Default: +false+
54
+ # :chef_server_url::
55
+ # The URL to the Chef server, e.g. https://api.opscode.com/organizations/foo.
56
+ # Used as the server for the remote chef_fs, and to "guess" repo_mode
57
+ # if not specified.
58
+ # :node_name:: The username to authenticate to the Chef server with.
59
+ # :client_key:: The private key for the user for authentication
60
+ # :environment:: The environment in which you are presently working
61
+ # :repo_mode::
62
+ # The repository mode, :hosted_everything, :everything or :static.
63
+ # This determines the set of subdirectories the Chef server will offer
64
+ # up.
65
+ # :versioned_cookbooks:: Whether or not to include versions in cookbook names
66
+ #
67
+ # [cwd]
68
+ # The current working directory to base relative Chef paths from.
69
+ # Defaults to +Dir.pwd+.
70
+ #
71
+ # [options]
72
+ # A hash of other, not-suspiciously-like-chef-config options:
73
+ # :cookbook_version::
74
+ # When downloading cookbooks, download this cookbook version instead
75
+ # of the latest.
76
+ #
77
+ # [ui]
78
+ # The object to print output to, with "output", "warn" and "error"
79
+ # (looks a little like a Chef::Knife::UI object, obtainable from
80
+ # Chef::Knife.ui).
81
+ #
82
+ # ==== Example
83
+ #
84
+ # require 'chef/chef_fs/config'
85
+ # config = Chef::ChefFS::Config.new
86
+ # config.chef_fs.child('cookbooks').children.each do |cookbook|
87
+ # puts "Cookbook on server: #{cookbook.name}"
88
+ # end
89
+ # config.local_fs.child('cookbooks').children.each do |cookbook|
90
+ # puts "Local cookbook: #{cookbook.name}"
91
+ # end
92
+ #
93
+ def initialize(chef_config = Chef::Config, cwd = Dir.pwd, options = {}, ui = nil)
29
94
  @chef_config = chef_config
30
95
  @cwd = cwd
31
96
  @cookbook_version = options[:cookbook_version]
32
97
 
98
+ if @chef_config[:repo_mode] == 'everything' && is_hosted? && !ui.nil?
99
+ ui.warn %Q{You have repo_mode set to 'everything', but your chef_server_url
100
+ looks like it might be a hosted setup. If this is the case please use
101
+ hosted_everything or allow repo_mode to default}
102
+ end
33
103
  # Default to getting *everything* from the server.
34
104
  if !@chef_config[:repo_mode]
35
- if @chef_config[:chef_server_url] =~ /\/+organizations\/.+/
105
+ if is_hosted?
36
106
  @chef_config[:repo_mode] = 'hosted_everything'
37
107
  else
38
108
  @chef_config[:repo_mode] = 'everything'
@@ -44,6 +114,10 @@ class Chef
44
114
  attr_reader :cwd
45
115
  attr_reader :cookbook_version
46
116
 
117
+ def is_hosted?
118
+ @chef_config[:chef_server_url] =~ /\/+organizations\/.+/
119
+ end
120
+
47
121
  def chef_fs
48
122
  @chef_fs ||= create_chef_fs
49
123
  end
@@ -59,7 +133,7 @@ class Chef
59
133
 
60
134
  def create_local_fs
61
135
  require 'chef/chef_fs/file_system/chef_repository_file_system_root_dir'
62
- Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir.new(object_paths)
136
+ Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir.new(object_paths, Array(chef_config[:chef_repo_path]).flatten, @chef_config)
63
137
  end
64
138
 
65
139
  # Returns the given real path's location relative to the server root.
@@ -4,9 +4,9 @@ class Chef
4
4
  module ChefFS
5
5
  module DataHandler
6
6
  class AclDataHandler < DataHandlerBase
7
- def normalize(node, entry)
7
+ def normalize(acl, entry)
8
8
  # Normalize the order of the keys for easier reading
9
- result = normalize_hash(node, {
9
+ result = normalize_hash(acl, {
10
10
  'create' => {},
11
11
  'read' => {},
12
12
  'update' => {},
@@ -22,7 +22,7 @@ class Chef
22
22
  result
23
23
  end
24
24
 
25
- def preserve_key(key)
25
+ def preserve_key?(key)
26
26
  return key == 'name'
27
27
  end
28
28
 
@@ -11,7 +11,7 @@ class Chef
11
11
  })
12
12
  end
13
13
 
14
- def preserve_key(key)
14
+ def preserve_key?(key)
15
15
  return key == 'containername'
16
16
  end
17
17
 
@@ -23,7 +23,7 @@ class Chef
23
23
  })
24
24
  end
25
25
 
26
- def preserve_key(key)
26
+ def preserve_key?(key)
27
27
  return key == 'cookbook_name' || key == 'version'
28
28
  end
29
29
 
@@ -34,7 +34,7 @@ class Chef
34
34
  normalize_for_post(data_bag_item, entry)
35
35
  end
36
36
 
37
- def preserve_key(key)
37
+ def preserve_key?(key)
38
38
  return key == 'id'
39
39
  end
40
40
 
@@ -1,17 +1,32 @@
1
1
  class Chef
2
2
  module ChefFS
3
3
  module DataHandler
4
+ #
5
+ # The base class for all *DataHandlers.
6
+ #
7
+ # DataHandlers' job is to know the innards of Chef objects and manipulate
8
+ # JSON for them, adding defaults and formatting them.
9
+ #
4
10
  class DataHandlerBase
11
+ #
12
+ # Remove all default values from a Chef object's JSON so that the only
13
+ # thing you see are the values that have been explicitly set.
14
+ # Achieves this by calling normalize({}, entry) to get the list of
15
+ # defaults, and subtracting anything that is the same.
16
+ #
5
17
  def minimize(object, entry)
6
18
  default_object = default(entry)
7
19
  object.each_pair do |key, value|
8
- if default_object[key] == value && !preserve_key(key)
20
+ if default_object[key] == value && !preserve_key?(key)
9
21
  object.delete(key)
10
22
  end
11
23
  end
12
24
  object
13
25
  end
14
26
 
27
+ #
28
+ # Takes a name like blah.json and removes the .json from it.
29
+ #
15
30
  def remove_dot_json(name)
16
31
  if name.length < 5 || name[-5,5] != ".json"
17
32
  raise "Invalid name #{path}: must end in .json"
@@ -19,14 +34,34 @@ class Chef
19
34
  name[0,name.length-5]
20
35
  end
21
36
 
22
- def preserve_key(key)
37
+ #
38
+ # Return true if minimize() should preserve a key even if it is the same
39
+ # as the default. Often used for ids and names.
40
+ #
41
+ def preserve_key?(key)
23
42
  false
24
43
  end
25
44
 
45
+ #
46
+ # Get the default value for an entry. Calls normalize({}, entry).
47
+ #
26
48
  def default(entry)
27
49
  normalize({}, entry)
28
50
  end
29
51
 
52
+ #
53
+ # Utility function to help subclasses do normalize(). Pass in a hash
54
+ # and a list of keys with defaults, and normalize will:
55
+ #
56
+ # 1. Fill in the defaults
57
+ # 2. Put the actual values in the order of the defaults
58
+ # 3. Move any other values to the end
59
+ #
60
+ # == Example
61
+ #
62
+ # normalize_hash({x: 100, c: 2, a: 1}, { a: 10, b: 20, c: 30})
63
+ # -> { a: 1, b: 20, c: 2, x: 100}
64
+ #
30
65
  def normalize_hash(object, defaults)
31
66
  # Make a normalized result in the specified order for diffing
32
67
  result = {}
@@ -39,14 +74,25 @@ class Chef
39
74
  result
40
75
  end
41
76
 
77
+ # Specialized function to normalize an object before POSTing it, since
78
+ # some object types want slightly different values on POST.
79
+ # If not overridden, this just calls normalize()
42
80
  def normalize_for_post(object, entry)
43
81
  normalize(object, entry)
44
82
  end
45
83
 
84
+ # Specialized function to normalize an object before PUTing it, since
85
+ # some object types want slightly different values on PUT.
86
+ # If not overridden, this just calls normalize().
46
87
  def normalize_for_put(object, entry)
47
88
  normalize(object, entry)
48
89
  end
49
90
 
91
+ #
92
+ # normalize a run list (an array of run list items).
93
+ # Leaves recipe[name] and role[name] alone, and translates
94
+ # name to recipe[name]. Then calls uniq on the result.
95
+ #
50
96
  def normalize_run_list(run_list)
51
97
  run_list.map{|item|
52
98
  case item.to_s
@@ -60,22 +106,46 @@ class Chef
60
106
  }.uniq
61
107
  end
62
108
 
109
+ #
110
+ # Bring in an instance of this object from Ruby. (Like roles/x.rb)
111
+ #
63
112
  def from_ruby(ruby)
64
113
  chef_class.from_file(ruby).to_hash
65
114
  end
66
115
 
116
+ #
117
+ # Turn a JSON hash into a bona fide Chef object (like Chef::Node).
118
+ #
67
119
  def chef_object(object)
68
120
  chef_class.json_create(object)
69
121
  end
70
122
 
123
+ #
124
+ # Write out the Ruby file for this instance. (Like roles/x.rb)
125
+ #
71
126
  def to_ruby(object)
72
127
  raise NotImplementedError
73
128
  end
74
129
 
130
+ #
131
+ # Get the class for instances of this type. Must be overridden.
132
+ #
75
133
  def chef_class
76
134
  raise NotImplementedError
77
135
  end
78
136
 
137
+ #
138
+ # Helper to write out a Ruby file for a JSON hash. Writes out only
139
+ # the keys specified in "keys"; anything else must be emitted by the
140
+ # caller.
141
+ #
142
+ # == Example
143
+ #
144
+ # to_ruby_keys({"name" => "foo", "environment" => "desert", "foo": "bar"}, [ "name", "environment" ])
145
+ # ->
146
+ # 'name "foo"
147
+ # environment "desert"'
148
+ #
79
149
  def to_ruby_keys(object, keys)
80
150
  result = ''
81
151
  keys.each do |key|
@@ -115,6 +185,10 @@ class Chef
115
185
  result
116
186
  end
117
187
 
188
+ #
189
+ # Verify that the JSON hash for this type has a key that matches its name.
190
+ # Calls the on_error block with the error, if there is one.
191
+ #
118
192
  def verify_integrity(object, entry, &on_error)
119
193
  base_name = remove_dot_json(entry.name)
120
194
  if object['name'] != base_name