chef 0.8.16 → 0.9.0.a3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of chef might be problematic. Click here for more details.

Files changed (185) hide show
  1. data/bin/shef +1 -0
  2. data/distro/common/man/man1/chef-server-webui.1 +106 -0
  3. data/distro/common/man/man1/chef-server.1 +0 -1
  4. data/distro/common/man/man1/chef-solr-indexer.1 +55 -0
  5. data/distro/common/man/man1/chef-solr.1 +55 -0
  6. data/distro/common/man/man8/chef-client.8 +4 -2
  7. data/distro/common/man/man8/chef-solo.8 +1 -2
  8. data/distro/common/man/man8/chef-solr-rebuild.8 +37 -0
  9. data/distro/common/man/man8/knife.8 +668 -266
  10. data/distro/common/man/man8/shef.8 +45 -0
  11. data/distro/common/markdown/README +3 -0
  12. data/distro/common/markdown/knife.mkd +520 -0
  13. data/distro/debian/etc/default/chef-client +4 -0
  14. data/distro/debian/etc/default/chef-server +6 -0
  15. data/distro/debian/etc/default/chef-server-webui +6 -0
  16. data/distro/debian/etc/default/chef-solr +4 -0
  17. data/distro/debian/etc/default/chef-solr-indexer +4 -0
  18. data/distro/debian/etc/init.d/chef-client +41 -41
  19. data/distro/debian/etc/init.d/chef-server +10 -10
  20. data/distro/debian/etc/init.d/chef-server-webui +121 -0
  21. data/distro/debian/etc/init.d/chef-solr +177 -0
  22. data/distro/debian/etc/init.d/chef-solr-indexer +176 -0
  23. data/distro/redhat/etc/init.d/chef-client +76 -48
  24. data/distro/redhat/etc/init.d/chef-server +85 -51
  25. data/distro/redhat/etc/init.d/chef-server-webui +85 -51
  26. data/distro/redhat/etc/init.d/chef-solr +77 -49
  27. data/distro/redhat/etc/init.d/chef-solr-indexer +77 -48
  28. data/distro/redhat/etc/logrotate.d/chef-client +8 -0
  29. data/distro/redhat/etc/logrotate.d/chef-server +8 -0
  30. data/distro/redhat/etc/logrotate.d/chef-server-webui +8 -0
  31. data/distro/redhat/etc/logrotate.d/chef-solr +8 -0
  32. data/distro/redhat/etc/logrotate.d/chef-solr-indexer +8 -0
  33. data/distro/redhat/etc/sysconfig/chef-client +9 -4
  34. data/distro/redhat/etc/sysconfig/chef-server +10 -6
  35. data/distro/redhat/etc/sysconfig/chef-server-webui +10 -6
  36. data/distro/redhat/etc/sysconfig/chef-solr +3 -4
  37. data/distro/redhat/etc/sysconfig/chef-solr-indexer +3 -3
  38. data/lib/chef.rb +16 -5
  39. data/lib/chef/application/knife.rb +2 -2
  40. data/lib/chef/application/solo.rb +1 -7
  41. data/lib/chef/cache/checksum.rb +12 -5
  42. data/lib/chef/cache/file_cache_by_checksum.rb +52 -0
  43. data/lib/chef/checksum.rb +115 -0
  44. data/lib/chef/client.rb +193 -185
  45. data/lib/chef/config.rb +9 -1
  46. data/lib/chef/cookbook/cookbook_collection.rb +43 -0
  47. data/lib/chef/cookbook/file_system_file_vendor.rb +53 -0
  48. data/lib/chef/cookbook/file_vendor.rb +47 -0
  49. data/lib/chef/cookbook/metadata.rb +34 -35
  50. data/lib/chef/cookbook/metadata/version.rb +1 -1
  51. data/lib/chef/cookbook_loader.rb +70 -45
  52. data/lib/chef/cookbook_version.rb +760 -0
  53. data/lib/chef/couchdb.rb +8 -5
  54. data/lib/chef/data_bag_item.rb +5 -5
  55. data/lib/chef/exceptions.rb +10 -0
  56. data/lib/chef/file_access_control.rb +134 -0
  57. data/lib/chef/handler.rb +62 -0
  58. data/lib/chef/handler/json_file.rb +47 -0
  59. data/lib/chef/knife.rb +14 -2
  60. data/lib/chef/knife/bootstrap.rb +126 -0
  61. data/lib/chef/knife/cookbook_bulk_delete.rb +1 -1
  62. data/lib/chef/knife/cookbook_delete.rb +4 -4
  63. data/lib/chef/knife/cookbook_download.rb +57 -26
  64. data/lib/chef/knife/cookbook_metadata.rb +2 -2
  65. data/lib/chef/knife/cookbook_show.rb +30 -11
  66. data/lib/chef/knife/cookbook_upload.rb +113 -86
  67. data/lib/chef/knife/ec2_server_create.rb +146 -0
  68. data/lib/chef/knife/ec2_server_delete.rb +84 -0
  69. data/lib/chef/knife/ec2_server_list.rb +82 -0
  70. data/lib/chef/knife/status.rb +51 -0
  71. data/lib/chef/mixin/language_include_attribute.rb +16 -11
  72. data/lib/chef/mixin/language_include_recipe.rb +15 -16
  73. data/lib/chef/mixin/recipe_definition_dsl_core.rb +17 -20
  74. data/lib/chef/mixin/shell_out.rb +38 -0
  75. data/lib/chef/mixins.rb +1 -1
  76. data/lib/chef/node.rb +190 -63
  77. data/lib/chef/node/attribute.rb +92 -78
  78. data/lib/chef/platform.rb +24 -4
  79. data/lib/chef/provider.rb +28 -10
  80. data/lib/chef/provider/breakpoint.rb +2 -2
  81. data/lib/chef/provider/cookbook_file.rb +96 -0
  82. data/lib/chef/provider/cron.rb +2 -2
  83. data/lib/chef/provider/deploy.rb +12 -10
  84. data/lib/chef/provider/env.rb +152 -0
  85. data/lib/chef/provider/env/windows.rb +75 -0
  86. data/lib/chef/provider/file.rb +10 -14
  87. data/lib/chef/provider/group.rb +15 -2
  88. data/lib/chef/provider/group/dscl.rb +17 -25
  89. data/lib/chef/provider/group/gpasswd.rb +6 -3
  90. data/lib/chef/provider/group/pw.rb +3 -7
  91. data/lib/chef/provider/group/windows.rb +79 -0
  92. data/lib/chef/provider/link.rb +4 -5
  93. data/lib/chef/provider/mdadm.rb +25 -18
  94. data/lib/chef/provider/mount/mount.rb +28 -27
  95. data/lib/chef/provider/package.rb +35 -35
  96. data/lib/chef/provider/package/dpkg.rb +13 -10
  97. data/lib/chef/provider/package/easy_install.rb +6 -6
  98. data/lib/chef/provider/package/freebsd.rb +17 -51
  99. data/lib/chef/provider/package/rpm.rb +1 -1
  100. data/lib/chef/provider/package/rubygems.rb +391 -74
  101. data/lib/chef/provider/package/yum.rb +2 -2
  102. data/lib/chef/provider/package/zypper.rb +2 -1
  103. data/lib/chef/provider/remote_directory.rb +60 -83
  104. data/lib/chef/provider/remote_file.rb +17 -66
  105. data/lib/chef/provider/script.rb +20 -9
  106. data/lib/chef/provider/service.rb +23 -30
  107. data/lib/chef/provider/service/arch.rb +3 -3
  108. data/lib/chef/provider/service/debian.rb +22 -17
  109. data/lib/chef/provider/service/freebsd.rb +4 -4
  110. data/lib/chef/provider/service/init.rb +2 -2
  111. data/lib/chef/provider/service/redhat.rb +14 -16
  112. data/lib/chef/provider/service/simple.rb +7 -3
  113. data/lib/chef/provider/service/solaris.rb +85 -0
  114. data/lib/chef/provider/service/upstart.rb +12 -7
  115. data/lib/chef/provider/service/windows.rb +2 -2
  116. data/lib/chef/provider/template.rb +133 -118
  117. data/lib/chef/provider/user.rb +34 -17
  118. data/lib/chef/provider/user/dscl.rb +117 -114
  119. data/lib/chef/provider/user/windows.rb +124 -0
  120. data/lib/chef/providers.rb +7 -0
  121. data/lib/chef/recipe.rb +39 -20
  122. data/lib/chef/resource.rb +47 -52
  123. data/lib/chef/resource/apt_package.rb +4 -4
  124. data/lib/chef/resource/bash.rb +4 -4
  125. data/lib/chef/resource/cookbook_file.rb +45 -0
  126. data/lib/chef/resource/cron.rb +3 -3
  127. data/lib/chef/resource/csh.rb +4 -4
  128. data/lib/chef/resource/deploy.rb +3 -3
  129. data/lib/chef/resource/directory.rb +4 -4
  130. data/lib/chef/resource/dpkg_package.rb +4 -4
  131. data/lib/chef/resource/easy_install_package.rb +3 -3
  132. data/lib/chef/resource/env.rb +58 -0
  133. data/lib/chef/resource/erl_call.rb +3 -3
  134. data/lib/chef/resource/execute.rb +3 -3
  135. data/lib/chef/resource/file.rb +3 -3
  136. data/lib/chef/resource/freebsd_package.rb +3 -3
  137. data/lib/chef/resource/gem_package.rb +17 -9
  138. data/lib/chef/resource/git.rb +3 -3
  139. data/lib/chef/resource/group.rb +3 -3
  140. data/lib/chef/resource/http_request.rb +4 -4
  141. data/lib/chef/resource/ifconfig.rb +3 -3
  142. data/lib/chef/resource/link.rb +3 -3
  143. data/lib/chef/resource/log.rb +2 -2
  144. data/lib/chef/resource/macports_package.rb +2 -2
  145. data/lib/chef/resource/mdadm.rb +3 -3
  146. data/lib/chef/resource/mount.rb +2 -2
  147. data/lib/chef/resource/package.rb +4 -4
  148. data/lib/chef/resource/pacman_package.rb +4 -4
  149. data/lib/chef/resource/perl.rb +4 -4
  150. data/lib/chef/resource/portage_package.rb +4 -4
  151. data/lib/chef/resource/python.rb +4 -4
  152. data/lib/chef/resource/remote_directory.rb +3 -3
  153. data/lib/chef/resource/remote_file.rb +26 -3
  154. data/lib/chef/resource/route.rb +3 -3
  155. data/lib/chef/resource/ruby.rb +3 -3
  156. data/lib/chef/resource/ruby_block.rb +3 -2
  157. data/lib/chef/resource/scm.rb +7 -5
  158. data/lib/chef/resource/script.rb +4 -4
  159. data/lib/chef/resource/service.rb +3 -3
  160. data/lib/chef/resource/subversion.rb +4 -2
  161. data/lib/chef/resource/template.rb +3 -3
  162. data/lib/chef/resource/user.rb +3 -3
  163. data/lib/chef/resource/yum_package.rb +3 -3
  164. data/lib/chef/resource_collection.rb +9 -5
  165. data/lib/chef/resources.rb +2 -0
  166. data/lib/chef/rest.rb +4 -0
  167. data/lib/chef/role.rb +2 -0
  168. data/lib/chef/run_context.rb +108 -0
  169. data/lib/chef/run_list.rb +75 -98
  170. data/lib/chef/run_list/run_list_expansion.rb +156 -0
  171. data/lib/chef/run_list/run_list_item.rb +71 -0
  172. data/lib/chef/runner.rb +58 -61
  173. data/lib/chef/sandbox.rb +147 -0
  174. data/lib/chef/shef.rb +4 -3
  175. data/lib/chef/shef/ext.rb +12 -4
  176. data/lib/chef/shef/shef_session.rb +27 -23
  177. data/lib/chef/shell_out.rb +375 -0
  178. data/lib/chef/util/windows.rb +56 -0
  179. data/lib/chef/util/windows/net_group.rb +101 -0
  180. data/lib/chef/util/windows/net_user.rb +198 -0
  181. data/lib/chef/version.rb +20 -0
  182. metadata +112 -22
  183. data/lib/chef/compile.rb +0 -158
  184. data/lib/chef/cookbook.rb +0 -201
  185. data/lib/chef/mixin/generate_url.rb +0 -58
@@ -0,0 +1,8 @@
1
+ /var/log/chef/client.log {
2
+ rotate 12
3
+ weekly
4
+ compress
5
+ postrotate
6
+ /etc/init.d/chef-client condrestart >/dev/null || :
7
+ endscript
8
+ }
@@ -0,0 +1,8 @@
1
+ /var/log/chef/server.log {
2
+ rotate 12
3
+ weekly
4
+ compress
5
+ postrotate
6
+ /etc/init.d/chef-server condrestart >/dev/null || :
7
+ endscript
8
+ }
@@ -0,0 +1,8 @@
1
+ /var/log/chef/server-webui.log {
2
+ rotate 12
3
+ weekly
4
+ compress
5
+ postrotate
6
+ /etc/init.d/chef-server-webui condrestart >/dev/null || :
7
+ endscript
8
+ }
@@ -0,0 +1,8 @@
1
+ /var/log/chef/solr.log {
2
+ rotate 12
3
+ weekly
4
+ compress
5
+ postrotate
6
+ /etc/init.d/chef-solr condrestart >/dev/null || :
7
+ endscript
8
+ }
@@ -0,0 +1,8 @@
1
+ /var/log/chef/solr-indexer.log {
2
+ rotate 12
3
+ weekly
4
+ compress
5
+ postrotate
6
+ /etc/init.d/chef-solr-indexer condrestart >/dev/null || :
7
+ endscript
8
+ }
@@ -1,10 +1,15 @@
1
1
  # Configuration file for the chef-client service
2
2
 
3
- #PIDFILE=/var/run/chef/client.pid
4
3
  #CONFIG=/etc/chef/client.rb
5
- #CHEF_USER=root
6
- #CHEF_GROUP=root
4
+ #PIDFILE=/var/run/chef/client.pid
5
+ #LOCKFILE=/var/lock/subsys/chef-client
6
+ #LOGFILE=/var/log/chef/client.log
7
+ # Sleep interval between runs.
8
+ # This value is in seconds.
7
9
  #INTERVAL=1800
10
+ # Maximum amount of random delay before starting a run. Prevents every client
11
+ # from contacting the server at the exact same time.
12
+ # This value is in seconds.
8
13
  #SPLAY=20
9
- #LOGFILE=/var/log/chef/client.log
14
+ # Any additional chef-client options.
10
15
  #OPTIONS=
@@ -1,10 +1,14 @@
1
1
  # Configuration file for the chef-server service
2
2
 
3
- #CHILDPIDFILES=/var/run/chef/server.%s.pid
4
- #PIDFILE=/var/run/chef/server.pid
5
3
  #CONFIG=/etc/chef/server.rb
6
- #CHEF_USER=chef
7
- #CHEF_GROUP=chef
8
- #CLUSTER_NODES=1
9
- #LOGFILE=/var/log/chef/merb.%s.log
4
+ #PIDFILE=/var/run/chef/server.pid
5
+ #LOCKFILE=/var/lock/subsys/chef-server
6
+ #LOGFILE=/var/log/chef/server.log
7
+ #PORT=4000
8
+ #ENVIRONMENT=production
9
+ #ADAPTER=thin
10
+ #CHILDPIDFILES=/var/run/chef/server.%s.pid
11
+ #SERVER_USER=chef
12
+ #SERVER_GROUP=chef
13
+ # Any additional chef-server options.
10
14
  #OPTIONS=
@@ -1,10 +1,14 @@
1
1
  # Configuration file for the chef-server-webui service
2
2
 
3
- #CHILDPIDFILES=/var/run/chef/server-webui.%s.pid
3
+ #CONFIG=/etc/chef/webui.rb
4
4
  #PIDFILE=/var/run/chef/server-webui.pid
5
- #CONFIG=/etc/chef/server.rb
6
- #CHEF_USER=chef
7
- #CHEF_GROUP=chef
8
- #CLUSTER_NODES=1
9
- #LOGFILE=/var/log/chef/merb-webui.%s.log
5
+ #LOCKFILE=/var/lock/subsys/chef-server-webui
6
+ #LOGFILE=/var/log/chef/server-webui.log
7
+ #PORT=4040
8
+ #ENVIRONMENT=production
9
+ #ADAPTER=thin
10
+ #CHILDPIDFILES=/var/run/chef/server-webui.%s.pid
11
+ #SERVER_USER=chef
12
+ #SERVER_GROUP=chef
13
+ # Any additional chef-server-webui options.
10
14
  #OPTIONS=
@@ -1,9 +1,8 @@
1
1
  # Configuration file for the chef-solr service
2
2
 
3
+ #CONFIG=/etc/chef/solr.rb
3
4
  #PIDFILE=/var/run/chef/solr.pid
4
- #CONFIG=/etc/chef/server.rb
5
- #CHEF_USER=chef
6
- #CHEF_GROUP=chef
5
+ #LOCKFILE=/var/lock/subsys/chef-solr
7
6
  #LOGFILE=/var/log/chef/solr.log
8
- # options for Java. Need to start with -j followed by options..
7
+ # Options for Java. Need to start with -j followed by options.
9
8
  #OPTIONS="-j "
@@ -1,7 +1,7 @@
1
1
  # Configuration file for the chef-solr-indexer service
2
2
 
3
3
  #PIDFILE=/var/run/chef/solr-indexer.pid
4
- #CONFIG=/etc/chef/server.rb
5
- #CHEF_USER=chef
6
- #CHEF_GROUP=chef
4
+ #CONFIG=/etc/chef/solr-indexer.rb
7
5
  #LOGFILE=/var/log/chef/solr-indexer.log
6
+ # Any additional chef-solr-indexer options.
7
+ #OPTIONS=
@@ -16,22 +16,22 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
+ require 'chef/version'
20
+
19
21
  require 'extlib'
20
22
  require 'chef/exceptions'
21
23
  require 'chef/log'
22
24
  require 'chef/config'
23
25
  require 'chef/providers'
24
26
  require 'chef/resources'
27
+ require 'chef/shell_out'
25
28
 
26
- require 'chef/compile'
27
29
  require 'chef/daemon'
28
- require 'chef/runner'
29
30
  require 'chef/webui_user'
30
31
  require 'chef/openid_registration'
31
32
 
32
- class Chef
33
- VERSION = "0.8.16"
34
- end
33
+ require 'chef/handler'
34
+ require 'chef/handler/json_file'
35
35
 
36
36
  # Adds a Dir.glob to Ruby 1.8.5, for compat
37
37
  if RUBY_VERSION < "1.8.6" || RUBY_PLATFORM =~ /mswin|mingw32|windows/
@@ -51,3 +51,14 @@ if RUBY_VERSION < "1.8.6" || RUBY_PLATFORM =~ /mswin|mingw32|windows/
51
51
  end
52
52
  end
53
53
  end
54
+
55
+
56
+ # On ruby 1.9, Strings are aware of multibyte characters, so #size and length
57
+ # give the actual number of characters. In Chef::REST, we need the bytesize
58
+ # so we can correctly set the Content-Length headers, but ruby 1.8.6 and lower
59
+ # don't define String#bytesize. Monkey patching time!
60
+ class String
61
+ unless method_defined?(:bytesize)
62
+ alias :bytesize :size
63
+ end
64
+ end
@@ -36,7 +36,6 @@ class Chef::Application::Knife < Chef::Application
36
36
  option :config_file,
37
37
  :short => "-c CONFIG",
38
38
  :long => "--config CONFIG",
39
- :default => File.join(ENV['HOME'], '.chef', 'knife.rb'),
40
39
  :description => "The configuration file to use"
41
40
 
42
41
  option :log_level,
@@ -96,7 +95,7 @@ class Chef::Application::Knife < Chef::Application
96
95
  :description => "Show the data after a destructive operation"
97
96
 
98
97
  option :format,
99
- :short => "-f FORMAT",
98
+ :short => "-F FORMAT",
100
99
  :long => "--format FORMAT",
101
100
  :description => "Which format to use for output",
102
101
  :default => "json"
@@ -114,6 +113,7 @@ class Chef::Application::Knife < Chef::Application
114
113
  validate_and_parse_options
115
114
  knife = Chef::Knife.find_command(ARGV, self.class.options)
116
115
  knife.run
116
+ exit 0
117
117
  end
118
118
 
119
119
  private
@@ -95,12 +95,6 @@ class Chef::Application::Solo < Chef::Application
95
95
  :description => "The splay time for running at intervals, in seconds",
96
96
  :proc => lambda { |s| s.to_i }
97
97
 
98
- option :json_attribs,
99
- :short => "-j JSON_ATTRIBS",
100
- :long => "--json-attributes JSON_ATTRIBS",
101
- :description => "Load attributes from a JSON file or URL",
102
- :proc => nil
103
-
104
98
  option :recipe_url,
105
99
  :short => "-r RECIPE_URL",
106
100
  :long => "--recipe-url RECIPE_URL",
@@ -195,7 +189,7 @@ class Chef::Application::Solo < Chef::Application
195
189
  sleep splay
196
190
  end
197
191
 
198
- @chef_solo.run_solo
192
+ @chef_solo.run
199
193
 
200
194
  if Chef::Config[:interval]
201
195
  Chef::Log.debug("Sleeping for #{Chef::Config[:interval]} seconds")
@@ -19,6 +19,7 @@
19
19
  #
20
20
 
21
21
  require 'chef/cache'
22
+ require 'digest/md5'
22
23
 
23
24
  class Chef
24
25
  class Cache
@@ -44,7 +45,7 @@ class Chef
44
45
  end
45
46
 
46
47
  def generate_checksum(key, file, fstat)
47
- checksum = checksum_file(file)
48
+ checksum = checksum_file(file, Digest::SHA256.new)
48
49
  moneta.store(key, {"mtime" => fstat.mtime.to_f, "checksum" => checksum})
49
50
  checksum
50
51
  end
@@ -52,19 +53,25 @@ class Chef
52
53
  def generate_key(file, group="chef")
53
54
  "#{group}-file-#{file.gsub(/(#{File::SEPARATOR}|\.)/, '-')}"
54
55
  end
55
-
56
+
57
+ def self.generate_md5_checksum_for_file(*args)
58
+ instance.generate_md5_checksum_for_file(*args)
59
+ end
60
+
61
+ def generate_md5_checksum_for_file(file)
62
+ checksum_file(file, Digest::MD5.new)
63
+ end
64
+
56
65
  private
57
66
 
58
67
  def file_unchanged?(cached, fstat)
59
68
  cached["mtime"].to_f == fstat.mtime.to_f
60
69
  end
61
70
 
62
- def checksum_file(file)
63
- digest = Digest::SHA256.new
71
+ def checksum_file(file, digest)
64
72
  IO.foreach(file) {|line| digest.update(line) }
65
73
  digest.hexdigest
66
74
  end
67
-
68
75
  end
69
76
  end
70
77
  end
@@ -0,0 +1,52 @@
1
+ #
2
+ # Author:: Tim Hinderliter (<tim@opscode.com>)
3
+ # Author:: Christopher Walters (<cw@opscode.com>)
4
+ # Copyright:: Copyright (c) 2010 Opscode, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ class Chef
21
+ class Cache
22
+ class FileCacheByChecksum
23
+ attr_reader :basedir
24
+
25
+ def initialize(basedir = Chef::Config[:file_cache_path])
26
+ @basedir = basedir
27
+ end
28
+
29
+ # returns path
30
+ def get_path(checksum)
31
+ path = checksum_path(checksum)
32
+
33
+ File.exists?(path) ? path : nil
34
+ end
35
+
36
+ # path = path to tempfile as input
37
+ # returns destination path
38
+ def put(checksum, src_path)
39
+ dest_path = checksum_path(checksum)
40
+ FileUtils.mkdir_p(File.dirname(dest_path))
41
+
42
+ FileUtils.cp(src_path, dest_path)
43
+
44
+ dest_path
45
+ end
46
+
47
+ def checksum_path(checksum)
48
+ File.join(basedir, checksum[0..1], checksum)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,115 @@
1
+ #
2
+ # Author:: Tim Hinderliter (<tim@opscode.com>)
3
+ # Copyright:: Copyright (c) 2010 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require 'chef/log'
19
+ require 'uuidtools'
20
+
21
+
22
+ # Checksum for an individual file; e.g., used for sandbox/cookbook uploading
23
+ # to track which files the system already manages.
24
+ class Chef
25
+ class Checksum
26
+ attr_accessor :checksum, :create_time
27
+ attr_accessor :couchdb_id, :couchdb_rev
28
+
29
+ DESIGN_DOCUMENT = {
30
+ "version" => 1,
31
+ "language" => "javascript",
32
+ "views" => {
33
+ "all" => {
34
+ "map" => <<-EOJS
35
+ function(doc) {
36
+ if (doc.chef_type == "checksum") {
37
+ emit(doc.checksum, doc);
38
+ }
39
+ }
40
+ EOJS
41
+ },
42
+ }
43
+ }
44
+
45
+ # Creates a new Chef::Checksum object.
46
+ #
47
+ # === Returns
48
+ # object<Chef::Checksum>:: Duh. :)
49
+ def initialize(checksum=nil, couchdb=nil)
50
+ @create_time = Time.now.iso8601
51
+ @checksum = checksum
52
+ end
53
+
54
+ def to_json(*a)
55
+ result = {
56
+ :checksum => checksum,
57
+ :create_time => create_time,
58
+ :json_class => self.class.name,
59
+ :chef_type => 'checksum',
60
+
61
+ # For Chef::CouchDB (id_to_name, name_to_id)
62
+ :name => checksum
63
+ }
64
+ result.to_json(*a)
65
+ end
66
+
67
+ def self.json_create(o)
68
+ checksum = new(o['checksum'])
69
+ checksum.create_time = o['create_time']
70
+
71
+ if o.has_key?('_rev')
72
+ checksum.couchdb_rev = o["_rev"]
73
+ o.delete("_rev")
74
+ end
75
+ if o.has_key?("_id")
76
+ checksum.couchdb_id = o["_id"]
77
+ o.delete("_id")
78
+ end
79
+ checksum
80
+ end
81
+
82
+ ##
83
+ # Couchdb
84
+ ##
85
+
86
+ def self.create_design_document(couchdb=nil)
87
+ (couchdb || Chef::CouchDB.new).create_design_document("checksums", DESIGN_DOCUMENT)
88
+ end
89
+
90
+ def self.cdb_list(inflate=false, couchdb=nil)
91
+ rs = (couchdb || Chef::CouchDB.new).list("checksums", inflate)
92
+ lookup = (inflate ? "value" : "key")
93
+ rs["rows"].collect { |r| r[lookup] }
94
+ end
95
+
96
+ def self.cdb_all_checksums(couchdb = nil)
97
+ rs = (couchdb || Chef::CouchDB.new).list("checksums", true)
98
+ rs["rows"].inject({}) { |hash_result, r| hash_result[r['key']] = 1; hash_result }
99
+ end
100
+
101
+ def self.cdb_load(checksum, couchdb=nil)
102
+ # Probably want to look for a view here at some point
103
+ (couchdb || Chef::CouchDB.new).load("checksum", checksum)
104
+ end
105
+
106
+ def cdb_destroy(couchdb=nil)
107
+ (couchdb || Chef::CouchDB.new).delete("checksum", checksum, @couchdb_rev)
108
+ end
109
+
110
+ def cdb_save(couchdb=nil)
111
+ @couchdb_rev = (couchdb || Chef::CouchDB.new).store("checksum", checksum, self)["rev"]
112
+ end
113
+
114
+ end
115
+ end
@@ -2,7 +2,8 @@
2
2
  # Author:: Adam Jacob (<adam@opscode.com>)
3
3
  # Author:: Christopher Walters (<cw@opscode.com>)
4
4
  # Author:: Christopher Brown (<cb@opscode.com>)
5
- # Copyright:: Copyright (c) 2008 Opscode, Inc.
5
+ # Author:: Tim Hinderliter (<tim@opscode.com>)
6
+ # Copyright:: Copyright (c) 2008-2010 Opscode, Inc.
6
7
  # License:: Apache License, Version 2.0
7
8
  #
8
9
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,25 +20,24 @@
19
20
 
20
21
  require 'chef/config'
21
22
  require 'chef/mixin/params_validate'
22
- require 'chef/mixin/generate_url'
23
- require 'chef/mixin/checksum'
24
23
  require 'chef/log'
25
24
  require 'chef/rest'
26
25
  require 'chef/platform'
27
26
  require 'chef/node'
28
27
  require 'chef/role'
29
28
  require 'chef/file_cache'
30
- require 'chef/compile'
29
+ require 'chef/run_context'
31
30
  require 'chef/runner'
31
+ require 'chef/cookbook/cookbook_collection'
32
+ require 'chef/cookbook/file_vendor'
33
+ require 'chef/cookbook/file_system_file_vendor'
32
34
  require 'ohai'
33
35
 
34
36
  class Chef
35
37
  class Client
36
-
37
- include Chef::Mixin::GenerateURL
38
- include Chef::Mixin::Checksum
39
-
40
- attr_accessor :node, :registration, :json_attribs, :node_name, :ohai, :rest
38
+ # TODO: timh/cw: 5-19-2010: json_attribs should be moved to RunContext?
39
+ attr_accessor :node, :registration, :json_attribs, :node_name, :ohai, :rest, :runner
40
+ attr_reader :node_exists
41
41
 
42
42
  # Creates a new Chef::Client.
43
43
  def initialize()
@@ -46,72 +46,95 @@ class Chef
46
46
  @json_attribs = nil
47
47
  @node_name = nil
48
48
  @node_exists = true
49
+ @runner = nil
49
50
  @ohai = Ohai::System.new
50
51
  Chef::Log.verbose = Chef::Config[:verbose_logging]
51
52
  Mixlib::Authentication::Log.logger = Ohai::Log.logger = Chef::Log.logger
52
53
  @ohai_has_run = false
53
- @rest = if File.exists?(Chef::Config[:client_key])
54
- Chef::REST.new(Chef::Config[:chef_server_url])
55
- else
56
- Chef::REST.new(Chef::Config[:chef_server_url], nil, nil)
57
- end
58
54
  end
59
55
 
60
56
  # Do a full run for this Chef::Client. Calls:
61
- #
57
+ #
58
+ # * run_ohai - Collect information about the system
62
59
  # * build_node - Get the last known state, merge with local changes
63
- # * register - Make sure we have an openid
64
- # * authenticate - Authenticate with our openid
65
- # * sync_library_files - Populate the local cache with all the library files
66
- # * sync_provider_files - Populate the local cache with all the provider files
67
- # * sync_resource_files - Populate the local cache with all the resource files
68
- # * sync_attribute_files - Populate the local cache with all the attribute files
69
- # * sync_definitions - Populate the local cache with all the definitions
70
- # * sync_recipes - Populate the local cache with all the recipes
71
- # * do_attribute_files - Populate the local cache with all attributes, and execute them
72
- # * save_node - Store the new node configuration
73
- # * converge - Bring this system up to date, based on the local cache
74
- # * save_node - Store the node again, in case convergence altered future state
60
+ # * register - If not in solo mode, make sure the server knows about this client
61
+ # * sync_cookbooks - If not in solo mode, populate the local cache with the node's cookbooks
62
+ # * converge - Bring this system up to date
75
63
  #
76
64
  # === Returns
77
65
  # true:: Always returns true.
78
66
  def run
79
- start_time = Time.now
80
- Chef::Log.info("Starting Chef Run")
81
-
67
+ self.runner = nil
68
+ run_context = nil
69
+
70
+ run_ohai
82
71
  determine_node_name
83
- register
84
- build_node(@node_name)
85
- save_node
86
- sync_cookbooks
87
- converge
88
- save_node
72
+ register unless Chef::Config[:solo]
73
+ build_node
89
74
 
90
- end_time = Time.now
91
- Chef::Log.info("Chef Run complete in #{end_time - start_time} seconds")
92
- true
75
+ begin
76
+ start_time = Time.now
77
+ Chef::Log.info("Starting Chef Run")
78
+
79
+ if Chef::Config[:solo]
80
+ Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest) }
81
+ run_context = Chef::RunContext.new(node, Chef::CookbookCollection.new(Chef::CookbookLoader.new))
82
+ assert_cookbook_path_not_empty(run_context)
83
+ converge(run_context)
84
+ else
85
+ save_node
86
+
87
+ # Note: When we move to lazily loading all cookbook files,
88
+ # replace sync_cookbooks with a method that simply gets the
89
+ # cookbook manifests from the remote server (and their
90
+ # download URLs) from the server and feeds them to
91
+ # RemoteFileVendors. [cw/tim-5/11/2010, 5/23/2010]
92
+ Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest) }
93
+ # Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::RemoteFileVendor.new(manifest) }
94
+ sync_cookbooks
95
+ run_context = Chef::RunContext.new(node, Chef::CookbookCollection.new(Chef::CookbookLoader.new))
96
+ assert_cookbook_path_not_empty(run_context)
97
+ save_node
98
+
99
+ converge(run_context)
100
+ save_node
101
+ end
102
+
103
+ end_time = Time.now
104
+ elapsed_time = end_time - start_time
105
+ Chef::Log.info("Chef Run complete in #{elapsed_time} seconds")
106
+ run_report_handlers(start_time, end_time, elapsed_time)
107
+ true
108
+ rescue Exception => e
109
+ run_exception_handlers(node, runner ? runner : run_context, start_time, end_time, elapsed_time, e)
110
+ Chef::Log.error("Re-raising exception: #{e.class} - #{e.message}\n#{e.backtrace.join("\n ")}")
111
+ raise
112
+ end
93
113
  end
94
-
95
- # Similar to Chef::Client#run, but instead of talking to the Chef server,
96
- # simply runs in a standalone ("solo") mode.
97
- #
98
- # Someday, we'll have chef_chewbacca.
99
- #
100
- # === Returns
101
- # true:: Always returns true.
102
- def run_solo
103
- start_time = Time.now
104
- Chef::Log.info("Starting Chef Solo Run")
105
114
 
106
- determine_node_name
107
- build_node(@node_name, true)
108
- converge(true)
109
-
110
- end_time = Time.now
111
- Chef::Log.info("Chef Run complete in #{end_time - start_time} seconds")
112
- true
115
+ def run_report_handlers(start_time, end_time, elapsed_time)
116
+ if Chef::Config[:report_handlers].length > 0
117
+ Chef::Log.info("Running report handlers")
118
+ Chef::Config[:report_handlers].each do |handler|
119
+ handler.report(node, runner, start_time, end_time, elapsed_time)
120
+ end
121
+ Chef::Log.info("Report handlers complete")
122
+ end
113
123
  end
114
124
 
125
+ def run_exception_handlers(node, runner, start_time, end_time, elapsed_time, exception)
126
+ if Chef::Config[:exception_handlers].length > 0
127
+ end_time ||= Time.now
128
+ elapsed_time ||= end_time - start_time
129
+ Chef::Log.error("Received exception: #{exception.message}")
130
+ Chef::Log.error("Running exception handlers")
131
+ Chef::Config[:exception_handlers].each do |handler|
132
+ handler.report(node, runner, start_time, end_time, elapsed_time, exception)
133
+ end
134
+ Chef::Log.error("Exception handlers complete")
135
+ end
136
+ end
137
+
115
138
  def run_ohai
116
139
  if ohai.keys
117
140
  ohai.refresh_plugins
@@ -121,55 +144,53 @@ class Chef
121
144
  end
122
145
 
123
146
  def determine_node_name
124
- run_ohai
125
147
  unless node_name
126
148
  if Chef::Config[:node_name]
127
- @node_name = Chef::Config[:node_name]
149
+ self.node_name = Chef::Config[:node_name]
128
150
  else
129
- @node_name ||= ohai[:fqdn] ? ohai[:fqdn] : ohai[:hostname]
130
- Chef::Config[:node_name] = @node_name
151
+ self.node_name = ohai[:fqdn] ? ohai[:fqdn] : ohai[:hostname]
152
+ Chef::Config[:node_name] = node_name
131
153
  end
154
+
155
+ raise RuntimeError, "Unable to determine node name from ohai" unless node_name
132
156
  end
133
- @node_name
157
+ node_name
134
158
  end
135
-
159
+
136
160
  # Builds a new node object for this client. Starts with querying for the FQDN of the current
137
161
  # host (unless it is supplied), then merges in the facts from Ohai.
138
162
  #
139
- # === Parameters
140
- # node_name<String>:: The name of the node to build - defaults to nil
141
- #
142
163
  # === Returns
143
164
  # node<Chef::Node>:: Returns the created node object, also stored in @node
144
- def build_node(node_name=nil, solo=false)
145
- node_name ||= determine_node_name
146
- raise RuntimeError, "Unable to determine node name from ohai" unless node_name
147
- Chef::Log.debug("Building node object for #{@node_name}")
148
-
149
- unless solo
150
- @node = begin
151
- rest.get_rest("nodes/#{@node_name}")
152
- rescue Net::HTTPServerException => e
153
- raise unless e.message =~ /^404/
154
- end
155
- end
165
+ def build_node
166
+ Chef::Log.debug("Building node object for #{node_name}")
156
167
 
157
- unless @node
158
- @node_exists = false
159
- @node ||= Chef::Node.new
160
- @node.name(node_name)
168
+ unless Chef::Config[:solo]
169
+ self.node = begin
170
+ rest.get_rest("nodes/#{node_name}")
171
+ rescue Net::HTTPServerException => e
172
+ raise unless e.message =~ /^404/
173
+ end
161
174
  end
162
175
 
163
- @node.consume_attributes(@json_attribs)
164
-
165
- ohai.each do |field, value|
166
- Chef::Log.debug("Ohai Attribute: #{field} - #{value.inspect}")
167
- @node[field] = value
176
+ unless node
177
+ @node_exists = false
178
+ self.node = Chef::Node.new
179
+ node.name(node_name)
168
180
  end
169
- platform, version = Chef::Platform.find_platform_and_version(@node)
181
+
182
+ node.consume_attributes(json_attribs)
183
+
184
+ node.automatic_attrs = ohai.data
185
+
186
+ platform, version = Chef::Platform.find_platform_and_version(node)
170
187
  Chef::Log.debug("Platform is #{platform} version #{version}")
171
- @node[:platform] = platform
172
- @node[:platform_version] = version
188
+ @node.automatic_attrs[:platform] = platform
189
+ @node.automatic_attrs[:platform_version] = version
190
+ # We clear defaults and overrides, so that any deleted attributes between runs are
191
+ # still gone.
192
+ @node.default_attrs = Mash.new
193
+ @node.override_attrs = Mash.new
173
194
  @node
174
195
  end
175
196
 
@@ -181,10 +202,10 @@ class Chef
181
202
  Chef::Log.debug("Client key #{Chef::Config[:client_key]} is present - skipping registration")
182
203
  else
183
204
  Chef::Log.info("Client key #{Chef::Config[:client_key]} is not present - registering")
184
- Chef::REST.new(Chef::Config[:client_url], Chef::Config[:validation_client_name], Chef::Config[:validation_key]).register(@node_name, Chef::Config[:client_key])
205
+ Chef::REST.new(Chef::Config[:client_url], Chef::Config[:validation_client_name], Chef::Config[:validation_key]).register(node_name, Chef::Config[:client_key])
185
206
  end
186
207
  # We now have the client key, and should use it from now on.
187
- self.rest = Chef::REST.new(Chef::Config[:chef_server_url])
208
+ self.rest = Chef::REST.new(Chef::Config[:chef_server_url], node_name, Chef::Config[:client_key])
188
209
  end
189
210
 
190
211
  # Update the file caches for a given cache segment. Takes a segment name
@@ -194,71 +215,52 @@ class Chef
194
215
  # === Parameters
195
216
  # segment<String>:: The cache segment to update
196
217
  # remote_list<Hash>:: A cookbooks/_attribute_files style remote file listing
197
- def update_file_cache(cookbook_name, parts)
198
- Chef::Log.debug("Synchronizing cookbook #{cookbook_name}")
218
+ def sync_cookbook_file_cache(cookbook)
219
+ Chef::Log.debug("Synchronizing cookbook #{cookbook.name}")
199
220
 
200
- file_canonical = Hash.new
221
+ filenames_seen = Hash.new
201
222
 
202
- [ "recipes", "attributes", "definitions", "libraries", "resources", "providers" ].each do |segment|
203
- remote_list = parts.has_key?(segment) ? parts[segment] : []
204
-
205
- # segement = cookbook segment
206
- # remote_list = list of file hashes
207
- #
208
- # We need the list of known good attribute files, so we can delete any that are
209
- # just laying about.
223
+ Chef::CookbookVersion::COOKBOOK_SEGMENTS.each do |segment|
224
+ cookbook.manifest[segment].each do |manifest_record|
225
+ # segment = cookbook segment
226
+ # remote_list = list of file hashes
227
+ #
228
+ # We need the list of known good attribute files, so we can delete any that are
229
+ # just laying about.
210
230
 
211
- remote_list.each do |rf|
212
- cache_file = File.join("cookbooks", cookbook_name, segment, rf['name'])
213
- file_canonical[cache_file] = true
231
+ cache_filename = File.join("cookbooks", cookbook.name, manifest_record['path'])
232
+ filenames_seen[cache_filename] = true
214
233
 
215
- # For back-compat between older clients and new chef servers
216
- rf['checksum'] ||= nil
217
-
218
234
  current_checksum = nil
219
- if Chef::FileCache.has_key?(cache_file)
220
- current_checksum = checksum(Chef::FileCache.load(cache_file, false))
235
+ if Chef::FileCache.has_key?(cache_filename)
236
+ current_checksum = Chef::CookbookVersion.checksum_cookbook_file(Chef::FileCache.load(cache_filename, false))
221
237
  end
222
-
223
- if current_checksum != rf['checksum']
224
- rf_url = generate_cookbook_url(
225
- rf['name'],
226
- cookbook_name,
227
- segment,
228
- @node,
229
- current_checksum ? { 'checksum' => current_checksum } : nil
230
- )
231
-
232
- changed = true
233
- begin
234
- raw_file = rest.get_rest(rf_url, true)
235
- rescue Net::HTTPRetriableError => e
236
- if e.response.kind_of?(Net::HTTPNotModified)
237
- changed = false
238
- Chef::Log.debug("Cache file #{cache_file} is unchanged")
239
- else
240
- raise e
241
- end
242
- end
243
-
244
- if changed
245
- Chef::Log.info("Storing updated #{cache_file} in the cache.")
246
- Chef::FileCache.move_to(raw_file.path, cache_file)
247
- end
238
+
239
+ # If the checksums are different between on-disk (current) and on-server
240
+ # (remote, per manifest), do the update. This will also execute if there
241
+ # is no current checksum.
242
+ if current_checksum != manifest_record['checksum']
243
+ raw_file = rest.get_rest(manifest_record[:url], true)
244
+
245
+ Chef::Log.info("Storing updated #{cache_filename} in the cache.")
246
+ Chef::FileCache.move_to(raw_file.path, cache_filename)
247
+ else
248
248
  end
249
249
  end
250
-
251
250
  end
252
251
 
253
- Chef::FileCache.list.each do |cache_file|
254
- if cache_file =~ /^cookbooks\/#{cookbook_name}\/(recipes|attributes|definitions|libraries|resources|providers)\//
255
- unless file_canonical[cache_file]
256
- Chef::Log.info("Removing #{cache_file} from the cache; it is no longer on the server.")
257
- Chef::FileCache.delete(cache_file)
258
- end
252
+ filenames_seen
253
+ end
254
+
255
+ def cleanup_file_cache(valid_cache_entries)
256
+ # Delete each file in the cache that we didn't encounter in the
257
+ # manifest.
258
+ Chef::FileCache.list.each do |cache_filename|
259
+ unless valid_cache_entries[cache_filename]
260
+ Chef::Log.info("Removing #{cache_filename} from the cache; it is no longer on the server.")
261
+ Chef::FileCache.delete(cache_filename)
259
262
  end
260
263
  end
261
-
262
264
  end
263
265
 
264
266
  # Synchronizes all the cookbooks from the chef-server.
@@ -267,8 +269,10 @@ class Chef
267
269
  # true:: Always returns true
268
270
  def sync_cookbooks
269
271
  Chef::Log.debug("Synchronizing cookbooks")
270
- cookbook_hash = rest.get_rest("nodes/#{@node_name}/cookbooks")
272
+ cookbook_hash = rest.get_rest("nodes/#{node_name}/cookbooks")
271
273
  Chef::Log.debug("Cookbooks to load: #{cookbook_hash.inspect}")
274
+
275
+ # Remove all cookbooks no longer relevant to this node
272
276
  Chef::FileCache.list.each do |cache_file|
273
277
  if cache_file =~ /^cookbooks\/(.+?)\//
274
278
  unless cookbook_hash.has_key?($1)
@@ -277,9 +281,17 @@ class Chef
277
281
  end
278
282
  end
279
283
  end
280
- cookbook_hash.each do |cookbook_name, parts|
281
- update_file_cache(cookbook_name, parts)
284
+
285
+ # Synchronize each of the node's cookbooks
286
+ valid_cache_entries = cookbook_hash.values.inject({}) do |memo, cookbook|
287
+ memo.merge!(sync_cookbook_file_cache(cookbook))
288
+ memo
282
289
  end
290
+
291
+ cleanup_file_cache(valid_cache_entries)
292
+
293
+ # register the file cache path in the cookbook path so that CookbookLoader actually picks up the synced cookbooks
294
+ Chef::Config[:cookbook_path] = File.join(Chef::Config[:file_cache_path], "cookbooks")
283
295
  end
284
296
 
285
297
  # Updates the current node configuration on the server.
@@ -287,31 +299,39 @@ class Chef
287
299
  # === Returns
288
300
  # true:: Always returns true
289
301
  def save_node
290
- Chef::Log.debug("Saving the current state of node #{@node_name}")
291
- @node = begin
292
- if @node_exists
293
- rest.put_rest("nodes/#{@node_name}", @node)
294
- else
295
- result = rest.post_rest("nodes", @node)
296
- @node_exists = true
297
- rest.get_rest(result['uri'])
298
- end
299
- rescue
300
- nil
301
- end
302
+ Chef::Log.debug("Saving the current state of node #{node_name}")
303
+ self.node = if node_exists
304
+ rest.put_rest("nodes/#{node_name}", node)
305
+ else
306
+ result = rest.post_rest("nodes", node)
307
+ @node_exists = true
308
+ rest.get_rest(result['uri'])
309
+ end
302
310
  end
303
-
304
- # Compiles the full list of recipes for the server, and passes it to an instance of
305
- # Chef::Runner.converge.
311
+
312
+ # Converges the node.
306
313
  #
307
314
  # === Returns
308
315
  # true:: Always returns true
309
- def converge(solo=false)
310
- Chef::Log.debug("Compiling recipes for node #{@node_name}")
311
- unless solo
312
- Chef::Config[:cookbook_path] = File.join(Chef::Config[:file_cache_path], "cookbooks")
313
- Chef::Log.warn("Node #{@node_name} has an empty run list.") if @node.run_list.empty?
314
- else
316
+ def converge(run_context)
317
+ Chef::Log.debug("Converging node #{node_name}")
318
+ self.runner = Chef::Runner.new(run_context)
319
+ runner.converge
320
+ true
321
+ end
322
+
323
+ private
324
+
325
+ def directory_not_empty?(path)
326
+ File.exists?(path) && (Dir.entries(path).size > 2)
327
+ end
328
+
329
+ def is_last_element?(index, object)
330
+ object.kind_of?(Array) ? index == object.size - 1 : true
331
+ end
332
+
333
+ def assert_cookbook_path_not_empty(run_context)
334
+ if Chef::Config[:solo]
315
335
  # Check for cookbooks in the path given
316
336
  # Chef::Config[:cookbook_path] can be a string or an array
317
337
  # if it's an array, go through it and check each one, raise error at the last one if no files are found
@@ -325,23 +345,11 @@ class Chef
325
345
  raise Chef::Exceptions::CookbookNotFound, msg if is_last_element?(index, Chef::Config[:cookbook_path])
326
346
  end
327
347
  end
348
+ else
349
+ Chef::Log.warn("Node #{node_name} has an empty run list.") if run_context.node.run_list.empty?
328
350
  end
329
- compile = Chef::Compile.new(@node)
330
-
331
- Chef::Log.debug("Converging node #{@node_name}")
332
- Chef::Runner.new(@node, compile.collection, compile.definitions, compile.cookbook_loader).converge
333
- true
334
- end
335
-
336
- private
337
-
338
- def directory_not_empty?(path)
339
- File.exists?(path) && (Dir.entries(path).size > 2)
340
- end
341
-
342
- def is_last_element?(index, object)
343
- object.kind_of?(Array) ? index == object.size - 1 : true
344
- end
345
351
 
352
+ end
346
353
  end
347
354
  end
355
+