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
@@ -36,14 +36,14 @@ class Chef
36
36
  # If we have a definition that matches, we want to use that instead. This should
37
37
  # let you do some really crazy over-riding of "native" types, if you really want
38
38
  # to.
39
- if @definitions.has_key?(method_symbol)
39
+ if run_context.definitions.has_key?(method_symbol)
40
40
  # This dupes the high level object, but we still need to dup the params
41
- new_def = @definitions[method_symbol].dup
41
+ new_def = run_context.definitions[method_symbol].dup
42
42
  new_def.params = new_def.params.dup
43
- new_def.node = @node
43
+ new_def.node = run_context.node
44
44
  # This sets up the parameter overrides
45
45
  new_def.instance_eval(&block) if block
46
- new_recipe = Chef::Recipe.new(@cookbook_name, @recipe_name, @node, @collection, @definitions, @cookbook_loader)
46
+ new_recipe = Chef::Recipe.new(cookbook_name, @recipe_name, run_context)
47
47
  new_recipe.params = new_def.params
48
48
  new_recipe.params[:name] = args[0]
49
49
  new_recipe.instance_eval(&new_def.recipe)
@@ -51,32 +51,29 @@ class Chef
51
51
  # Otherwise, we're rocking the regular resource call route.
52
52
  method_name = method_symbol.to_s
53
53
  rname = convert_to_class_name(method_name)
54
-
54
+
55
+ super unless Chef::Resource.const_defined?(rname)
56
+ raise ArgumentError, "You must supply a name when declaring a #{method_name} resource" unless args.size > 0
57
+
55
58
  # If we have a resource like this one, we want to steal its state
56
- resource = begin
57
- args << @collection
58
- args << @node
59
- Chef::Resource.const_get(rname).new(*args)
60
- rescue NameError => e
61
- if e.to_s =~ /Chef::Resource/
62
- raise NameError, "Cannot find #{rname} for #{method_name}\nOriginal exception: #{e.class}: #{e.message}"
63
- else
64
- raise e
65
- end
66
- end
59
+ args << run_context
60
+ resource = Chef::Resource.const_get(rname).new(*args)
67
61
  resource.load_prior_resource
68
- resource.cookbook_name = @cookbook_name
69
- resource.recipe_name = @recipe_name
62
+ resource.cookbook_name = cookbook_name
63
+ # TODO: 5/21/2010 cw/dan: do we need recipe_name for
64
+ # anything? it's not even possible that this ivar is set on
65
+ # Chef::Provider.
66
+ # resource.recipe_name = @recipe_name
70
67
  resource.params = @params
71
68
  # Determine whether this resource is being created in the context of an enclosing Provider
72
69
  resource.enclosing_provider = self.is_a?(Chef::Provider) ? self : nil
73
70
  resource.instance_eval(&block) if block
74
71
 
75
- @collection.insert(resource)
72
+ run_context.resource_collection.insert(resource)
76
73
  resource
77
74
  end
78
75
  end
79
76
 
80
77
  end
81
78
  end
82
- end
79
+ end
@@ -0,0 +1,38 @@
1
+ #
2
+ # Author:: Daniel DeLeo (<dan@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/shell_out'
19
+
20
+ class Chef
21
+ module Mixin
22
+ module ShellOut
23
+
24
+ def shell_out(*command_args)
25
+ cmd = Chef::ShellOut.new(*command_args)
26
+ cmd.run_command
27
+ cmd
28
+ end
29
+
30
+ def shell_out!(*command_args)
31
+ cmd = Chef::ShellOut.new(*command_args)
32
+ cmd.run_command
33
+ cmd.error!
34
+ cmd
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,3 +1,4 @@
1
+ require 'chef/mixin/shell_out'
1
2
  require 'chef/mixin/check_helper'
2
3
  require 'chef/mixin/checksum'
3
4
  require 'chef/mixin/command'
@@ -6,7 +7,6 @@ require 'chef/mixin/create_path'
6
7
  require 'chef/mixin/deep_merge'
7
8
  require 'chef/mixin/find_preferred_file'
8
9
  require 'chef/mixin/from_file'
9
- require 'chef/mixin/generate_url'
10
10
  require 'chef/mixin/language'
11
11
  require 'chef/mixin/language_include_attribute'
12
12
  require 'chef/mixin/language_include_recipe'
@@ -1,7 +1,9 @@
1
1
  #
2
2
  # Author:: Adam Jacob (<adam@opscode.com>)
3
3
  # Author:: Christopher Brown (<cb@opscode.com>)
4
- # Copyright:: Copyright (c) 2008 Opscode, Inc.
4
+ # Author:: Christopher Walters (<cw@opscode.com>)
5
+ # Author:: Tim Hinderliter (<tim@opscode.com>)
6
+ # Copyright:: Copyright (c) 2008-2010 Opscode, Inc.
5
7
  # License:: Apache License, Version 2.0
6
8
  #
7
9
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,6 +20,7 @@
18
20
  #
19
21
 
20
22
  require 'chef/config'
23
+ require 'chef/cookbook/cookbook_collection'
21
24
  require 'chef/mixin/check_helper'
22
25
  require 'chef/mixin/params_validate'
23
26
  require 'chef/mixin/from_file'
@@ -33,10 +36,15 @@ require 'json'
33
36
 
34
37
  class Chef
35
38
  class Node
36
-
37
- attr_accessor :attribute, :recipe_list, :couchdb, :couchdb_rev, :run_state, :run_list, :override_attrs, :default_attrs, :cookbook_loader
38
- attr_reader :node
39
+
40
+ attr_accessor :recipe_list, :couchdb, :couchdb_rev, :run_state, :run_list
41
+ attr_accessor :override_attrs, :default_attrs, :normal_attrs, :automatic_attrs
39
42
  attr_reader :couchdb_id
43
+
44
+ # TODO: 5/18/2010 cw/timh. cookbook_collection should be removed
45
+ # from here and for any place it's needed, it should be accessed
46
+ # through a Chef::RunContext
47
+ attr_accessor :cookbook_collection
40
48
 
41
49
  include Chef::Mixin::CheckHelper
42
50
  include Chef::Mixin::FromFile
@@ -130,11 +138,11 @@ class Chef
130
138
  # Create a new Chef::Node object.
131
139
  def initialize(couchdb=nil)
132
140
  @name = nil
133
- @node = self
134
-
135
- @attribute = Mash.new
141
+
142
+ @normal_attrs = Mash.new
136
143
  @override_attrs = Mash.new
137
144
  @default_attrs = Mash.new
145
+ @automatic_attrs = Mash.new
138
146
  @run_list = Chef::RunList.new
139
147
 
140
148
  @couchdb_rev = nil
@@ -146,22 +154,26 @@ class Chef
146
154
  :seen_recipes => Hash.new,
147
155
  :seen_attributes => Hash.new
148
156
  }
157
+ # TODO: 5/20/2010 need this here as long as other objects try to access
158
+ # the cookbook collection via Node, otherwise get NoMethodError on nil.
159
+ @cookbook_collection = CookbookCollection.new
149
160
  end
150
161
 
151
162
  def couchdb_id=(value)
152
163
  @couchdb_id = value
153
- self.index_id = value
164
+ @index_id = value
154
165
  end
155
-
156
- def chef_server_rest
157
- Chef::REST.new(Chef::Config[:chef_server_url])
166
+
167
+ # Used by DSL
168
+ def node
169
+ self
158
170
  end
159
171
 
160
- def self.chef_server_rest
172
+ def chef_server_rest
161
173
  Chef::REST.new(Chef::Config[:chef_server_url])
162
174
  end
163
175
 
164
- # Find a recipe for this Chef::Node by fqdn. Will search first for
176
+ # Find a recipe for this Chef::Node by fqdn. Will search first for
165
177
  # Chef::Config["node_path"]/fqdn.rb, then hostname.rb, then default.rb.
166
178
  #
167
179
  # Returns a new Chef::Node object.
@@ -183,48 +195,102 @@ class Chef
183
195
  def name(arg=nil)
184
196
  if arg != nil
185
197
  validate(
186
- {:name => arg },
187
- {:name => { :kind_of => String,
188
- :cannot_be => :blank}
189
- })
198
+ {:name => arg },
199
+ {:name => { :kind_of => String,
200
+ :cannot_be => :blank}
201
+ })
190
202
  @name = arg
191
203
  else
192
204
  @name
193
205
  end
194
206
  end
195
207
 
208
+ # Used by the DSL
209
+ def attribute
210
+ construct_attributes
211
+ end
212
+
213
+ def construct_attributes
214
+ Chef::Node::Attribute.new(normal_attrs, default_attrs, override_attrs, automatic_attrs)
215
+ end
216
+
217
+ def attribute=(value)
218
+ self.normal_attrs = value
219
+ end
220
+
196
221
  # Return an attribute of this node. Returns nil if the attribute is not found.
197
222
  def [](attrib)
198
- Chef::Node::Attribute.new(@attribute, @default_attrs, @override_attrs)[attrib]
223
+ construct_attributes[attrib]
199
224
  end
200
225
 
201
226
  # Set an attribute of this node
202
227
  def []=(attrib, value)
203
- Chef::Node::Attribute.new(@attribute, @default_attrs, @override_attrs)[attrib] = value
228
+ construct_attributes[attrib] = value
204
229
  end
205
230
 
206
231
  def store(attrib, value)
207
232
  self[attrib] = value
208
233
  end
209
234
 
210
- # Set an attribute of this node, but auto-vivifiy any Mashes that might
235
+ # Set a normal attribute of this node, but auto-vivifiy any Mashes that
236
+ # might be missing
237
+ def normal
238
+ attrs = construct_attributes
239
+ attrs.set_type = :normal
240
+ attrs.auto_vivifiy_on_read = true
241
+ attrs
242
+ end
243
+
244
+ alias_method :set, :normal
245
+
246
+ # Set a normal attribute of this node, auto-vivifiying any mashes that are
247
+ # missing, but if the final value already exists, don't set it
248
+ def normal_unless
249
+ attrs = construct_attributes
250
+ attrs.set_type = :normal
251
+ attrs.auto_vivifiy_on_read = true
252
+ attrs.set_unless_value_present = true
253
+ attrs
254
+ end
255
+ alias_method :set_unless, :normal_unless
256
+
257
+ # Set a default of this node, but auto-vivifiy any Mashes that might
211
258
  # be missing
212
- def set
213
- attrs = Chef::Node::Attribute.new(@attribute, @default_attrs, @override_attrs)
259
+ def default
260
+ attrs = construct_attributes
261
+ attrs.set_type = :default
214
262
  attrs.auto_vivifiy_on_read = true
215
263
  attrs
216
264
  end
217
265
 
218
- # Set an attribute of this node, auto-vivifiying any mashes that are
266
+ # Set a default attribute of this node, auto-vivifiying any mashes that are
219
267
  # missing, but if the final value already exists, don't set it
220
- def set_unless
221
- attrs = Chef::Node::Attribute.new(@attribute, @default_attrs, @override_attrs)
268
+ def default_unless
269
+ attrs = construct_attributes
270
+ attrs.set_type = :default
222
271
  attrs.auto_vivifiy_on_read = true
223
272
  attrs.set_unless_value_present = true
224
273
  attrs
225
274
  end
226
275
 
227
- alias_method :default, :set_unless
276
+ # Set an override attribute of this node, but auto-vivifiy any Mashes that
277
+ # might be missing
278
+ def override
279
+ attrs = construct_attributes
280
+ attrs.set_type = :override
281
+ attrs.auto_vivifiy_on_read = true
282
+ attrs
283
+ end
284
+
285
+ # Set an override attribute of this node, auto-vivifiying any mashes that
286
+ # are missing, but if the final value already exists, don't set it
287
+ def override_unless
288
+ attrs = construct_attributes
289
+ attrs.set_type = :override
290
+ attrs.auto_vivifiy_on_read = true
291
+ attrs.set_unless_value_present = true
292
+ attrs
293
+ end
228
294
 
229
295
  # Return true if this Node has a given attribute, false if not. Takes either a symbol or
230
296
  # a string.
@@ -232,34 +298,43 @@ class Chef
232
298
  # Only works on the top level. Preferred way is to use the normal [] style
233
299
  # lookup and call attribute?()
234
300
  def attribute?(attrib)
235
- Chef::Node::Attribute.new(@attribute, @default_attrs, @override_attrs).attribute?(attrib)
301
+ construct_attributes.attribute?(attrib)
236
302
  end
237
303
 
238
304
  # Yield each key of the top level to the block.
239
305
  def each(&block)
240
- Chef::Node::Attribute.new(@attribute, @default_attrs, @override_attrs).each(&block)
306
+ construct_attributes.each(&block)
241
307
  end
242
308
 
243
309
  # Iterates over each attribute, passing the attribute and value to the block.
244
310
  def each_attribute(&block)
245
- Chef::Node::Attribute.new(@attribute, @default_attrs, @override_attrs).each_attribute(&block)
311
+ construct_attributes.each_attribute(&block)
246
312
  end
247
313
 
248
- # Set an attribute based on the missing method. If you pass an argument, we'll use that
249
- # to set the attribute values. Otherwise, we'll wind up just returning the attributes
250
- # value.
314
+ # Encouraged to only get used for lookups - while you can do sets from here, it's not as explicit
315
+ # as using the normal/default/override interface.
251
316
  def method_missing(symbol, *args)
252
- Chef::Node::Attribute.new(@attribute, @default_attrs, @override_attrs).send(symbol, *args)
317
+ attrs = construct_attributes
318
+ attrs.set_type = :normal
319
+ attrs.send(symbol, *args)
253
320
  end
254
321
 
255
322
  # Returns true if this Node expects a given recipe, false if not.
256
- def recipe?(recipe_name)
257
- @run_list.include?(recipe_name) || @run_state[:seen_recipes].include?(recipe_name)
258
- end
259
-
323
+ #
324
+ # First, the run list is consulted to see whether the recipe is
325
+ # explicitly included. If it's not there, it looks in
326
+ # run_state[:seen_recipes], which is populated by include_recipe
327
+ # statements in the DSL (and thus would not be in the run list).
328
+ #
329
+ # NOTE: We believe this is dead code, but if it's not, please
330
+ # email chef-dev@opscode.com. [cw,timh]
331
+ # def recipe?(recipe_name)
332
+ # run_list.include?(recipe_name) || run_state[:seen_recipes].include?(recipe_name)
333
+ # end
334
+
260
335
  # Returns true if this Node expects a given role, false if not.
261
336
  def role?(role_name)
262
- @run_list.include?("role[#{role_name}]")
337
+ run_list.include?("role[#{role_name}]")
263
338
  end
264
339
 
265
340
  # Returns an Array of roles and recipes, in the order they will be applied.
@@ -275,7 +350,7 @@ class Chef
275
350
 
276
351
  # Returns true if this Node expects a given role, false if not.
277
352
  def run_list?(item)
278
- @run_list.detect { |r| r == item } ? true : false
353
+ run_list.detect { |r| r == item } ? true : false
279
354
  end
280
355
 
281
356
  def consume_attributes(attrs)
@@ -288,7 +363,7 @@ class Chef
288
363
  Chef::Log.info("Replacing the run_list with #{new_run_list.inspect} from JSON")
289
364
  run_list(new_run_list)
290
365
  end
291
- Chef::Mixin::DeepMerge.merge(@attribute, attrs)
366
+ Chef::Mixin::DeepMerge.merge(@normal_attrs, attrs)
292
367
 
293
368
  self[:tags] = Array.new unless attribute?(:tags)
294
369
  end
@@ -296,29 +371,30 @@ class Chef
296
371
  # Transform the node to a Hash
297
372
  def to_hash
298
373
  index_hash = Hash.new
299
- self.each do |k, v|
300
- index_hash[k] = v
301
- end
302
374
  index_hash["chef_type"] = "node"
303
- index_hash["name"] = @name
304
- index_hash["recipe"] = @run_list.recipes if @run_list.recipes.length > 0
305
- index_hash["role"] = @run_list.roles if @run_list.roles.length > 0
306
- index_hash["run_list"] = @run_list.run_list if @run_list.run_list.length > 0
375
+ index_hash["name"] = name
376
+ attribute.each do |key, value|
377
+ index_hash[key] = value
378
+ end
379
+ index_hash["recipe"] = run_list.recipe_names if run_list.recipe_names.length > 0
380
+ index_hash["role"] = run_list.role_names if run_list.role_names.length > 0
381
+ index_hash["run_list"] = run_list.run_list if run_list.run_list.length > 0
307
382
  index_hash
308
383
  end
309
384
 
310
385
  # Serialize this object as a hash
311
386
  def to_json(*a)
312
387
  result = {
313
- "name" => @name,
388
+ "name" => name,
314
389
  'json_class' => self.class.name,
315
- "attributes" => @attribute,
390
+ "automatic" => automatic_attrs,
391
+ "normal" => normal_attrs,
316
392
  "chef_type" => "node",
317
- "defaults" => @default_attrs,
318
- "overrides" => @override_attrs,
319
- "run_list" => @run_list.run_list,
393
+ "default" => default_attrs,
394
+ "override" => override_attrs,
395
+ "run_list" => run_list.run_list
320
396
  }
321
- result["_rev"] = @couchdb_rev if @couchdb_rev
397
+ result["_rev"] = couchdb_rev if couchdb_rev
322
398
  result.to_json(*a)
323
399
  end
324
400
 
@@ -326,10 +402,14 @@ class Chef
326
402
  def self.json_create(o)
327
403
  node = new
328
404
  node.name(o["name"])
329
- o["attributes"].each { |k,v| node[k] = v }
330
405
 
331
- node.default_attrs = Mash.new(o["defaults"]) if o.has_key?("defaults")
332
- node.override_attrs = Mash.new(o["overrides"]) if o.has_key?("overrides")
406
+ if o.has_key?("attributes")
407
+ node.normal_attrs = o["attributes"]
408
+ end
409
+ node.automatic_attrs = Mash.new(o["automatic"]) if o.has_key?("automatic")
410
+ node.normal_attrs = Mash.new(o["normal"]) if o.has_key?("normal")
411
+ node.default_attrs = Mash.new(o["default"]) if o.has_key?("default")
412
+ node.override_attrs = Mash.new(o["override"]) if o.has_key?("override")
333
413
 
334
414
  if o.has_key?("run_list")
335
415
  node.run_list.reset!(o["run_list"])
@@ -382,23 +462,25 @@ class Chef
382
462
 
383
463
  # Remove this node from the CouchDB
384
464
  def cdb_destroy
385
- @couchdb.delete("node", @name, @couchdb_rev)
465
+ couchdb.delete("node", name, couchdb_rev)
386
466
  end
387
467
 
388
468
  # Remove this node via the REST API
389
469
  def destroy
390
- chef_server_rest.delete_rest("nodes/#{@name}")
470
+ chef_server_rest.delete_rest("nodes/#{name}")
391
471
  end
392
472
 
393
473
  # Save this node to the CouchDB
394
474
  def cdb_save
395
- @couchdb_rev = @couchdb.store("node", @name, self)["rev"]
475
+ @couchdb_rev = couchdb.store("node", name, self)["rev"]
396
476
  end
397
477
 
398
478
  # Save this node via the REST API
399
479
  def save
480
+ # Try PUT. If the node doesn't yet exist, PUT will return 404,
481
+ # so then POST to create.
400
482
  begin
401
- chef_server_rest.put_rest("nodes/#{@name}", self)
483
+ chef_server_rest.put_rest("nodes/#{name}", self)
402
484
  rescue Net::HTTPServerException => e
403
485
  raise e unless e.response.code == "404"
404
486
  chef_server_rest.post_rest("nodes", self)
@@ -416,11 +498,56 @@ class Chef
416
498
  def self.create_design_document(couchdb=nil)
417
499
  (couchdb || Chef::CouchDB.new).create_design_document("nodes", DESIGN_DOCUMENT)
418
500
  end
419
-
420
- # As a string
501
+
421
502
  def to_s
422
- "node[#{@name}]"
503
+ "node[#{name}]"
504
+ end
505
+
506
+ # Load all attribute files for all cookbooks associated with this
507
+ # node.
508
+ def load_attributes
509
+ cookbook_collection.values.each do |cookbook|
510
+ cookbook.segment_filenames(:attributes).each do |segment_filename|
511
+ Chef::Log.debug("node #{name} loading cookbook #{cookbook.name}'s attribute file #{segment_filename}")
512
+ self.from_file(segment_filename)
513
+ end
514
+ end
515
+ end
516
+
517
+ # Used by DSL.
518
+ # Loads the attribute file specified by the short name of the
519
+ # file, e.g., loads specified cookbook's
520
+ # "attributes/mailservers.rb"
521
+ # if passed
522
+ # "mailservers"
523
+ def load_attribute_by_short_filename(name, src_cookbook_name)
524
+ src_cookbook = cookbook_collection[src_cookbook_name]
525
+ raise Chef::Exceptions::CookbookNotFound, "could not find cookbook #{src_cookbook_name} while loading attribute #{name}" unless src_cookbook
526
+
527
+ attribute_filename = src_cookbook.attribute_filenames_by_short_filename[name]
528
+ raise Chef::Exceptions::AttributeNotFound, "could not find filename for attribute #{name} in cookbook #{src_cookbook_name}" unless attribute_filename
529
+
530
+ self.from_file(attribute_filename)
531
+ self
423
532
  end
424
533
 
534
+ # Expands the node's run list and deep merges the default and
535
+ # override attributes.
536
+ #
537
+ # Returns the fully-expanded list of recipes.
538
+ #
539
+ # TODO: timh/cw, 5-14-2010: Should this method exist? Should we
540
+ # instead modify default_attrs and override_attrs whenever our
541
+ # run_list is mutated? Or perhaps do something smarter like
542
+ # on-demand generation of default_attrs and override_attrs,
543
+ # invalidated only when run_list is mutated?
544
+ def expand_node!
545
+ # This call should only be called on a chef-client run.
546
+ recipes, expanded_default_attrs, expanded_override_attrs = run_list.expand('server')
547
+ self.default_attrs = Chef::Mixin::DeepMerge.merge(default_attrs, expanded_default_attrs)
548
+ self.override_attrs = Chef::Mixin::DeepMerge.merge(override_attrs, expanded_override_attrs)
549
+ recipes
550
+ end
551
+
425
552
  end
426
553
  end