chef 0.9.18 → 0.10.0.beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. data/README.rdoc +0 -3
  2. data/distro/arch/etc/rc.d/chef-server +0 -4
  3. data/distro/arch/etc/rc.d/chef-server-webui +0 -4
  4. data/distro/arch/etc/rc.d/chef-solr +0 -4
  5. data/distro/arch/etc/rc.d/chef-solr-indexer +0 -4
  6. data/lib/chef.rb +3 -3
  7. data/lib/chef/api_client.rb +1 -1
  8. data/lib/chef/application.rb +11 -1
  9. data/lib/chef/application/client.rb +18 -22
  10. data/lib/chef/application/knife.rb +28 -29
  11. data/lib/chef/application/solo.rb +14 -12
  12. data/lib/chef/client.rb +112 -54
  13. data/lib/chef/config.rb +4 -0
  14. data/lib/chef/cookbook/chefignore.rb +66 -0
  15. data/lib/chef/cookbook/cookbook_collection.rb +6 -5
  16. data/lib/chef/cookbook/cookbook_version_loader.rb +151 -0
  17. data/lib/chef/cookbook/file_system_file_vendor.rb +10 -8
  18. data/lib/chef/cookbook/metadata.rb +200 -108
  19. data/lib/chef/cookbook_loader.rb +39 -163
  20. data/lib/chef/cookbook_uploader.rb +100 -78
  21. data/lib/chef/cookbook_version.rb +92 -47
  22. data/lib/chef/cookbook_version_selector.rb +163 -0
  23. data/lib/chef/couchdb.rb +9 -1
  24. data/lib/chef/data_bag.rb +1 -1
  25. data/lib/chef/data_bag_item.rb +1 -1
  26. data/lib/chef/encrypted_data_bag_item.rb +126 -0
  27. data/lib/chef/environment.rb +386 -0
  28. data/lib/chef/exceptions.rb +82 -1
  29. data/lib/chef/index_queue/amqp_client.rb +15 -12
  30. data/lib/chef/index_queue/indexable.rb +38 -4
  31. data/lib/chef/json_compat.rb +3 -3
  32. data/lib/chef/knife.rb +97 -202
  33. data/lib/chef/knife/bootstrap.rb +27 -61
  34. data/lib/chef/knife/bootstrap/archlinux-gems.erb +4 -2
  35. data/lib/chef/knife/bootstrap/centos5-gems.erb +6 -15
  36. data/lib/chef/knife/bootstrap/fedora13-gems.erb +3 -4
  37. data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +2 -2
  38. data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +6 -5
  39. data/lib/chef/knife/client_bulk_delete.rb +6 -3
  40. data/lib/chef/knife/client_create.rb +13 -10
  41. data/lib/chef/knife/client_delete.rb +10 -7
  42. data/lib/chef/knife/client_edit.rb +9 -6
  43. data/lib/chef/knife/client_list.rb +8 -5
  44. data/lib/chef/knife/client_reregister.rb +9 -6
  45. data/lib/chef/knife/client_show.rb +9 -6
  46. data/lib/chef/knife/configure.rb +15 -19
  47. data/lib/chef/knife/configure_client.rb +4 -4
  48. data/lib/chef/knife/cookbook_bulk_delete.rb +11 -8
  49. data/lib/chef/knife/cookbook_create.rb +120 -55
  50. data/lib/chef/knife/cookbook_delete.rb +18 -12
  51. data/lib/chef/knife/cookbook_download.rb +10 -6
  52. data/lib/chef/knife/cookbook_list.rb +15 -6
  53. data/lib/chef/knife/cookbook_metadata.rb +41 -21
  54. data/lib/chef/knife/cookbook_metadata_from_file.rb +4 -0
  55. data/lib/chef/knife/cookbook_show.rb +16 -5
  56. data/lib/chef/knife/cookbook_site_download.rb +2 -2
  57. data/lib/chef/knife/cookbook_site_share.rb +18 -13
  58. data/lib/chef/knife/cookbook_site_unshare.rb +7 -4
  59. data/lib/chef/knife/cookbook_site_vendor.rb +21 -18
  60. data/lib/chef/knife/cookbook_test.rb +14 -14
  61. data/lib/chef/knife/cookbook_upload.rb +91 -40
  62. data/lib/chef/knife/data_bag_create.rb +41 -6
  63. data/lib/chef/knife/data_bag_delete.rb +5 -3
  64. data/lib/chef/knife/data_bag_edit.rb +55 -11
  65. data/lib/chef/knife/data_bag_from_file.rb +47 -7
  66. data/lib/chef/knife/data_bag_list.rb +4 -1
  67. data/lib/chef/knife/data_bag_show.rb +44 -4
  68. data/lib/chef/knife/environment_create.rb +53 -0
  69. data/lib/chef/knife/environment_delete.rb +45 -0
  70. data/lib/chef/knife/environment_edit.rb +45 -0
  71. data/lib/chef/knife/environment_from_file.rb +39 -0
  72. data/lib/chef/knife/environment_list.rb +42 -0
  73. data/lib/chef/knife/environment_show.rb +46 -0
  74. data/lib/chef/knife/exec.rb +1 -1
  75. data/lib/chef/knife/index_rebuild.rb +8 -9
  76. data/lib/chef/knife/node_bulk_delete.rb +9 -6
  77. data/lib/chef/knife/node_create.rb +9 -6
  78. data/lib/chef/knife/node_delete.rb +10 -7
  79. data/lib/chef/knife/node_edit.rb +129 -10
  80. data/lib/chef/knife/node_from_file.rb +10 -7
  81. data/lib/chef/knife/node_list.rb +11 -6
  82. data/lib/chef/knife/node_run_list_add.rb +10 -7
  83. data/lib/chef/knife/node_run_list_remove.rb +9 -6
  84. data/lib/chef/knife/node_show.rb +15 -7
  85. data/lib/chef/knife/recipe_list.rb +4 -3
  86. data/lib/chef/knife/role_bulk_delete.rb +9 -6
  87. data/lib/chef/knife/role_create.rb +9 -6
  88. data/lib/chef/knife/role_delete.rb +10 -7
  89. data/lib/chef/knife/role_edit.rb +11 -8
  90. data/lib/chef/knife/role_from_file.rb +10 -7
  91. data/lib/chef/knife/role_list.rb +8 -5
  92. data/lib/chef/knife/role_show.rb +11 -8
  93. data/lib/chef/knife/search.rb +33 -10
  94. data/lib/chef/knife/ssh.rb +33 -61
  95. data/lib/chef/knife/status.rb +7 -4
  96. data/lib/chef/knife/subcommand_loader.rb +101 -0
  97. data/lib/chef/knife/tag_create.rb +31 -0
  98. data/lib/chef/knife/tag_delete.rb +31 -0
  99. data/lib/chef/knife/tag_list.rb +29 -0
  100. data/lib/chef/knife/ui.rb +229 -0
  101. data/lib/chef/knife/windows_bootstrap.rb +8 -5
  102. data/lib/chef/log.rb +5 -59
  103. data/lib/chef/mash.rb +211 -0
  104. data/lib/chef/mixins.rb +1 -2
  105. data/lib/chef/nil_argument.rb +3 -0
  106. data/lib/chef/node.rb +96 -34
  107. data/lib/chef/platform.rb +27 -0
  108. data/lib/chef/provider/cookbook_file.rb +21 -20
  109. data/lib/chef/provider/deploy/revision.rb +3 -0
  110. data/lib/chef/provider/file.rb +20 -11
  111. data/lib/chef/provider/git.rb +26 -26
  112. data/lib/chef/provider/group/aix.rb +70 -0
  113. data/lib/chef/provider/group/groupadd.rb +7 -4
  114. data/lib/chef/provider/group/usermod.rb +1 -1
  115. data/lib/chef/provider/package.rb +28 -28
  116. data/lib/chef/provider/package/dpkg.rb +1 -1
  117. data/lib/chef/provider/package/portage.rb +50 -39
  118. data/lib/chef/provider/package/rubygems.rb +1 -1
  119. data/lib/chef/provider/package/zypper.rb +3 -20
  120. data/lib/chef/provider/remote_directory.rb +0 -2
  121. data/lib/chef/provider/remote_file.rb +2 -3
  122. data/lib/chef/provider/service/arch.rb +28 -35
  123. data/lib/chef/provider/service/simple.rb +1 -1
  124. data/lib/chef/provider/subversion.rb +22 -22
  125. data/lib/chef/providers.rb +1 -0
  126. data/lib/chef/recipe.rb +10 -12
  127. data/lib/chef/resource.rb +49 -42
  128. data/lib/chef/resource/gem_package.rb +7 -3
  129. data/lib/chef/resource/git.rb +5 -5
  130. data/lib/chef/resource/package.rb +7 -7
  131. data/lib/chef/resource/scm.rb +2 -1
  132. data/lib/chef/resource/solaris_package.rb +0 -1
  133. data/lib/chef/resource/yum_package.rb +0 -1
  134. data/lib/chef/rest.rb +7 -16
  135. data/lib/chef/rest/rest_request.rb +0 -16
  136. data/lib/chef/role.rb +67 -13
  137. data/lib/chef/run_context.rb +37 -21
  138. data/lib/chef/run_list.rb +30 -15
  139. data/lib/chef/run_list/run_list_expansion.rb +41 -20
  140. data/lib/chef/run_list/run_list_item.rb +20 -6
  141. data/lib/chef/run_list/versioned_recipe_list.rb +68 -0
  142. data/lib/chef/runner.rb +7 -15
  143. data/lib/chef/search/query.rb +12 -7
  144. data/lib/chef/shef.rb +6 -7
  145. data/lib/chef/shef/shef_session.rb +40 -35
  146. data/lib/chef/shell_out.rb +22 -201
  147. data/lib/chef/shell_out/unix.rb +224 -0
  148. data/lib/chef/shell_out/windows.rb +95 -0
  149. data/lib/chef/solr_query.rb +187 -0
  150. data/lib/chef/solr_query/lucene.treetop +145 -0
  151. data/lib/chef/solr_query/lucene_nodes.rb +285 -0
  152. data/lib/chef/solr_query/query_transform.rb +65 -0
  153. data/lib/chef/solr_query/solr_http_request.rb +118 -0
  154. data/lib/chef/version.rb +4 -2
  155. data/lib/chef/version_class.rb +70 -0
  156. data/lib/chef/version_constraint.rb +116 -0
  157. metadata +68 -37
  158. data/lib/chef/cookbook/metadata/version.rb +0 -87
  159. data/lib/chef/knife/bluebox_images_list.rb +0 -54
  160. data/lib/chef/knife/bluebox_server_create.rb +0 -157
  161. data/lib/chef/knife/bluebox_server_delete.rb +0 -63
  162. data/lib/chef/knife/bluebox_server_list.rb +0 -59
  163. data/lib/chef/knife/ec2_instance_data.rb +0 -46
  164. data/lib/chef/knife/ec2_server_create.rb +0 -218
  165. data/lib/chef/knife/ec2_server_delete.rb +0 -87
  166. data/lib/chef/knife/ec2_server_list.rb +0 -89
  167. data/lib/chef/knife/rackspace_server_create.rb +0 -184
  168. data/lib/chef/knife/rackspace_server_delete.rb +0 -57
  169. data/lib/chef/knife/rackspace_server_list.rb +0 -59
  170. data/lib/chef/knife/slicehost_images_list.rb +0 -53
  171. data/lib/chef/knife/slicehost_server_create.rb +0 -103
  172. data/lib/chef/knife/slicehost_server_delete.rb +0 -61
  173. data/lib/chef/knife/slicehost_server_list.rb +0 -64
  174. data/lib/chef/knife/terremark_server_create.rb +0 -152
  175. data/lib/chef/knife/terremark_server_delete.rb +0 -87
  176. data/lib/chef/knife/terremark_server_list.rb +0 -77
  177. data/lib/chef/mixin/find_preferred_file.rb +0 -92
@@ -0,0 +1,211 @@
1
+ # Copyright (c) 2009 Dan Kubb
2
+
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ # ---
23
+ # ---
24
+
25
+ # Some portions of blank.rb and mash.rb are verbatim copies of software
26
+ # licensed under the MIT license. That license is included below:
27
+
28
+ # Copyright (c) 2005-2008 David Heinemeier Hansson
29
+
30
+ # Permission is hereby granted, free of charge, to any person obtaining
31
+ # a copy of this software and associated documentation files (the
32
+ # "Software"), to deal in the Software without restriction, including
33
+ # without limitation the rights to use, copy, modify, merge, publish,
34
+ # distribute, sublicense, and/or sell copies of the Software, and to
35
+ # permit persons to whom the Software is furnished to do so, subject to
36
+ # the following conditions:
37
+
38
+ # The above copyright notice and this permission notice shall be
39
+ # included in all copies or substantial portions of the Software.
40
+
41
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
42
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
43
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
44
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
45
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
46
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
47
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48
+
49
+ # This class has dubious semantics and we only have it so that people can write
50
+ # params[:key] instead of params['key'].
51
+ class Mash < Hash
52
+
53
+ # @param constructor<Object>
54
+ # The default value for the mash. Defaults to an empty hash.
55
+ #
56
+ # @details [Alternatives]
57
+ # If constructor is a Hash, a new mash will be created based on the keys of
58
+ # the hash and no default value will be set.
59
+ def initialize(constructor = {})
60
+ if constructor.is_a?(Hash)
61
+ super()
62
+ update(constructor)
63
+ else
64
+ super(constructor)
65
+ end
66
+ end
67
+
68
+ # @param key<Object> The default value for the mash. Defaults to nil.
69
+ #
70
+ # @details [Alternatives]
71
+ # If key is a Symbol and it is a key in the mash, then the default value will
72
+ # be set to the value matching the key.
73
+ def default(key = nil)
74
+ if key.is_a?(Symbol) && include?(key = key.to_s)
75
+ self[key]
76
+ else
77
+ super
78
+ end
79
+ end
80
+
81
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
82
+ alias_method :regular_update, :update unless method_defined?(:regular_update)
83
+
84
+ # @param key<Object> The key to set.
85
+ # @param value<Object>
86
+ # The value to set the key to.
87
+ #
88
+ # @see Mash#convert_key
89
+ # @see Mash#convert_value
90
+ def []=(key, value)
91
+ regular_writer(convert_key(key), convert_value(value))
92
+ end
93
+
94
+ # @param other_hash<Hash>
95
+ # A hash to update values in the mash with. The keys and the values will be
96
+ # converted to Mash format.
97
+ #
98
+ # @return [Mash] The updated mash.
99
+ def update(other_hash)
100
+ other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
101
+ self
102
+ end
103
+
104
+ alias_method :merge!, :update
105
+
106
+ # @param key<Object> The key to check for. This will be run through convert_key.
107
+ #
108
+ # @return [Boolean] True if the key exists in the mash.
109
+ def key?(key)
110
+ super(convert_key(key))
111
+ end
112
+
113
+ # def include? def has_key? def member?
114
+ alias_method :include?, :key?
115
+ alias_method :has_key?, :key?
116
+ alias_method :member?, :key?
117
+
118
+ # @param key<Object> The key to fetch. This will be run through convert_key.
119
+ # @param *extras<Array> Default value.
120
+ #
121
+ # @return [Object] The value at key or the default value.
122
+ def fetch(key, *extras)
123
+ super(convert_key(key), *extras)
124
+ end
125
+
126
+ # @param *indices<Array>
127
+ # The keys to retrieve values for. These will be run through +convert_key+.
128
+ #
129
+ # @return [Array] The values at each of the provided keys
130
+ def values_at(*indices)
131
+ indices.collect {|key| self[convert_key(key)]}
132
+ end
133
+
134
+ # @param hash<Hash> The hash to merge with the mash.
135
+ #
136
+ # @return [Mash] A new mash with the hash values merged in.
137
+ def merge(hash)
138
+ self.dup.update(hash)
139
+ end
140
+
141
+ # @param key<Object>
142
+ # The key to delete from the mash.\
143
+ def delete(key)
144
+ super(convert_key(key))
145
+ end
146
+
147
+ # @param *rejected<Array[(String, Symbol)] The mash keys to exclude.
148
+ #
149
+ # @return [Mash] A new mash without the selected keys.
150
+ #
151
+ # @example
152
+ # { :one => 1, :two => 2, :three => 3 }.except(:one)
153
+ # #=> { "two" => 2, "three" => 3 }
154
+ def except(*keys)
155
+ super(*keys.map {|k| convert_key(k)})
156
+ end
157
+
158
+ # Used to provide the same interface as Hash.
159
+ #
160
+ # @return [Mash] This mash unchanged.
161
+ def stringify_keys!; self end
162
+
163
+ # @return [Hash] The mash as a Hash with symbolized keys.
164
+ def symbolize_keys
165
+ h = Hash.new(default)
166
+ each { |key, val| h[key.to_sym] = val }
167
+ h
168
+ end
169
+
170
+ # @return [Hash] The mash as a Hash with string keys.
171
+ def to_hash
172
+ Hash.new(default).merge(self)
173
+ end
174
+
175
+ # @return [Mash] Convert a Hash into a Mash
176
+ # The input Hash's default value is maintained
177
+ def self.from_hash(hash)
178
+ mash = Mash.new(hash)
179
+ mash.default = hash.default
180
+ mash
181
+ end
182
+
183
+ protected
184
+ # @param key<Object> The key to convert.
185
+ #
186
+ # @param [Object]
187
+ # The converted key. If the key was a symbol, it will be converted to a
188
+ # string.
189
+ #
190
+ # @api private
191
+ def convert_key(key)
192
+ key.kind_of?(Symbol) ? key.to_s : key
193
+ end
194
+
195
+ # @param value<Object> The value to convert.
196
+ #
197
+ # @return [Object]
198
+ # The converted value. A Hash or an Array of hashes, will be converted to
199
+ # their Mash equivalents.
200
+ #
201
+ # @api private
202
+ def convert_value(value)
203
+ if value.class == Hash
204
+ Mash.from_hash(value)
205
+ elsif value.is_a?(Array)
206
+ value.collect { |e| convert_value(e) }
207
+ else
208
+ value
209
+ end
210
+ end
211
+ end
@@ -5,7 +5,6 @@ require 'chef/mixin/command'
5
5
  require 'chef/mixin/convert_to_class_name'
6
6
  require 'chef/mixin/create_path'
7
7
  require 'chef/mixin/deep_merge'
8
- require 'chef/mixin/find_preferred_file'
9
8
  require 'chef/mixin/from_file'
10
9
  require 'chef/mixin/language'
11
10
  require 'chef/mixin/language_include_attribute'
@@ -13,4 +12,4 @@ require 'chef/mixin/language_include_recipe'
13
12
  require 'chef/mixin/params_validate'
14
13
  require 'chef/mixin/recipe_definition_dsl_core'
15
14
  require 'chef/mixin/template'
16
- require 'chef/mixin/xml_escape'
15
+ require 'chef/mixin/xml_escape'
@@ -0,0 +1,3 @@
1
+ class Chef
2
+ NIL_ARGUMENT = Object.new
3
+ end
@@ -3,7 +3,7 @@
3
3
  # Author:: Christopher Brown (<cb@opscode.com>)
4
4
  # Author:: Christopher Walters (<cw@opscode.com>)
5
5
  # Author:: Tim Hinderliter (<tim@opscode.com>)
6
- # Copyright:: Copyright (c) 2008-2010 Opscode, Inc.
6
+ # Copyright:: Copyright (c) 2008-2011 Opscode, Inc.
7
7
  # License:: Apache License, Version 2.0
8
8
  #
9
9
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,26 +21,28 @@
21
21
 
22
22
  require 'chef/config'
23
23
  require 'chef/cookbook/cookbook_collection'
24
+ require 'chef/nil_argument'
24
25
  require 'chef/mixin/check_helper'
25
26
  require 'chef/mixin/params_validate'
26
27
  require 'chef/mixin/from_file'
27
28
  require 'chef/mixin/language_include_attribute'
28
29
  require 'chef/mixin/deep_merge'
30
+ require 'chef/environment'
29
31
  require 'chef/couchdb'
30
32
  require 'chef/rest'
31
33
  require 'chef/run_list'
32
34
  require 'chef/node/attribute'
33
35
  require 'chef/index_queue'
34
- require 'extlib'
36
+ require 'chef/mash'
35
37
  require 'chef/json_compat'
36
38
 
37
39
  class Chef
38
40
  class Node
39
-
41
+
40
42
  attr_accessor :recipe_list, :couchdb, :couchdb_rev, :run_state, :run_list
41
43
  attr_accessor :override_attrs, :default_attrs, :normal_attrs, :automatic_attrs
42
44
  attr_reader :couchdb_id
43
-
45
+
44
46
  # TODO: 5/18/2010 cw/timh. cookbook_collection should be removed
45
47
  # from here and for any place it's needed, it should be accessed
46
48
  # through a Chef::RunContext
@@ -53,7 +55,7 @@ class Chef
53
55
  include Chef::IndexQueue::Indexable
54
56
 
55
57
  DESIGN_DOCUMENT = {
56
- "version" => 9,
58
+ "version" => 11,
57
59
  "language" => "javascript",
58
60
  "views" => {
59
61
  "all" => {
@@ -78,7 +80,7 @@ class Chef
78
80
  "map" => <<-EOJS
79
81
  function(doc) {
80
82
  if (doc.chef_type == "node") {
81
- var to_emit = { "name": doc.name };
83
+ var to_emit = { "name": doc.name, "chef_environment": doc.chef_environment };
82
84
  if (doc["attributes"]["fqdn"]) {
83
85
  to_emit["fqdn"] = doc["attributes"]["fqdn"];
84
86
  } else {
@@ -131,6 +133,16 @@ class Chef
131
133
  }
132
134
  }
133
135
  EOJS
136
+ },
137
+ "by_environment" => {
138
+ "map" => <<-EOJS
139
+ function(doc) {
140
+ if (doc.chef_type == "node") {
141
+ var env = (doc['chef_environment'] == null ? "_default" : doc['chef_environment']);
142
+ emit(env, doc.name);
143
+ }
144
+ }
145
+ EOJS
134
146
  }
135
147
  },
136
148
  }
@@ -138,7 +150,8 @@ class Chef
138
150
  # Create a new Chef::Node object.
139
151
  def initialize(couchdb=nil)
140
152
  @name = nil
141
-
153
+
154
+ @chef_environment = '_default'
142
155
  @normal_attrs = Mash.new
143
156
  @override_attrs = Mash.new
144
157
  @default_attrs = Mash.new
@@ -163,7 +176,7 @@ class Chef
163
176
  @couchdb_id = value
164
177
  @index_id = value
165
178
  end
166
-
179
+
167
180
  # Used by DSL
168
181
  def node
169
182
  self
@@ -173,7 +186,7 @@ class Chef
173
186
  Chef::REST.new(Chef::Config[:chef_server_url])
174
187
  end
175
188
 
176
- # Find a recipe for this Chef::Node by fqdn. Will search first for
189
+ # Find a recipe for this Chef::Node by fqdn. Will search first for
177
190
  # Chef::Config["node_path"]/fqdn.rb, then hostname.rb, then default.rb.
178
191
  #
179
192
  # Returns a new Chef::Node object.
@@ -206,11 +219,19 @@ class Chef
206
219
  end
207
220
  end
208
221
 
222
+ def chef_environment(arg=nil)
223
+ set_or_return(
224
+ :chef_environment,
225
+ arg,
226
+ { :regex => /^[\-[:alnum:]_]+$/, :kind_of => String }
227
+ )
228
+ end
229
+
209
230
  # Used by the DSL
210
231
  def attribute
211
232
  construct_attributes
212
233
  end
213
-
234
+
214
235
  def construct_attributes
215
236
  Chef::Node::Attribute.new(normal_attrs, default_attrs, override_attrs, automatic_attrs)
216
237
  end
@@ -218,7 +239,7 @@ class Chef
218
239
  def attribute=(value)
219
240
  self.normal_attrs = value
220
241
  end
221
-
242
+
222
243
  # Return an attribute of this node. Returns nil if the attribute is not found.
223
244
  def [](attrib)
224
245
  construct_attributes[attrib]
@@ -235,7 +256,7 @@ class Chef
235
256
 
236
257
  # Set a normal attribute of this node, but auto-vivifiy any Mashes that
237
258
  # might be missing
238
- def normal
259
+ def normal
239
260
  attrs = construct_attributes
240
261
  attrs.set_type = :normal
241
262
  attrs.auto_vivifiy_on_read = true
@@ -254,10 +275,10 @@ class Chef
254
275
  attrs
255
276
  end
256
277
  alias_method :set_unless, :normal_unless
257
-
278
+
258
279
  # Set a default of this node, but auto-vivifiy any Mashes that might
259
280
  # be missing
260
- def default
281
+ def default
261
282
  attrs = construct_attributes
262
283
  attrs.set_type = :default
263
284
  attrs.auto_vivifiy_on_read = true
@@ -276,7 +297,7 @@ class Chef
276
297
 
277
298
  # Set an override attribute of this node, but auto-vivifiy any Mashes that
278
299
  # might be missing
279
- def override
300
+ def override
280
301
  attrs = construct_attributes
281
302
  attrs.set_type = :override
282
303
  attrs.auto_vivifiy_on_read = true
@@ -330,7 +351,7 @@ class Chef
330
351
  def recipe?(recipe_name)
331
352
  run_list.include?(recipe_name) || run_state[:seen_recipes].include?(recipe_name)
332
353
  end
333
-
354
+
334
355
  # Returns true if this Node expects a given role, false if not.
335
356
  def role?(role_name)
336
357
  run_list.include?("role[#{role_name}]")
@@ -370,7 +391,13 @@ class Chef
370
391
  normal_attrs_to_merge = consume_run_list(attrs)
371
392
  Chef::Log.debug("Applying attributes from json file")
372
393
  @normal_attrs = Chef::Mixin::DeepMerge.merge(@normal_attrs,normal_attrs_to_merge)
373
- self[:tags] = Array.new unless attribute?(:tags)
394
+ self.tags # make sure they're defined
395
+ end
396
+
397
+ # Lazy initializer for tags attribute
398
+ def tags
399
+ self[:tags] = [] unless attribute?(:tags)
400
+ self[:tags]
374
401
  end
375
402
 
376
403
  # Extracts the run list from +attrs+ and applies it. Returns the remaining attributes
@@ -386,37 +413,44 @@ class Chef
386
413
  attrs
387
414
  end
388
415
 
389
- # Clear defaults and overrides, so that any deleted attributes between runs are
390
- # still gone.
416
+ # Clear defaults and overrides, so that any deleted attributes
417
+ # between runs are still gone.
391
418
  def reset_defaults_and_overrides
392
419
  @default_attrs = Mash.new
393
420
  @override_attrs = Mash.new
394
421
  end
395
422
 
396
- # Expands the node's run list and deep merges the default and
397
- # override attributes. Also applies stored attributes (from json provided
423
+ # Expands the node's run list and sets the default and override
424
+ # attributes. Also applies stored attributes (from json provided
398
425
  # on the command line)
399
426
  #
400
- # Returns the fully-expanded list of recipes.
427
+ # Returns the fully-expanded list of recipes, a RunListExpansion.
401
428
  #
429
+ #--
402
430
  # TODO: timh/cw, 5-14-2010: Should this method exist? Should we
403
431
  # instead modify default_attrs and override_attrs whenever our
404
432
  # run_list is mutated? Or perhaps do something smarter like
405
433
  # on-demand generation of default_attrs and override_attrs,
406
434
  # invalidated only when run_list is mutated?
407
- def expand!
408
- # This call should only be called on a chef-client run.
409
- expansion = run_list.expand('server')
435
+ def expand!(data_source = 'server')
436
+ expansion = run_list.expand(chef_environment, data_source)
410
437
  raise Chef::Exceptions::MissingRole if expansion.errors?
411
438
 
412
- self[:tags] = Array.new unless attribute?(:tags)
413
- @default_attrs = Chef::Mixin::DeepMerge.merge(default_attrs, expansion.default_attrs)
414
- @override_attrs = Chef::Mixin::DeepMerge.merge(override_attrs, expansion.override_attrs)
439
+ self.tags # make sure they're defined
415
440
 
416
441
  @automatic_attrs[:recipes] = expansion.recipes
417
442
  @automatic_attrs[:roles] = expansion.roles
418
443
 
419
- expansion.recipes
444
+ expansion
445
+ end
446
+
447
+ # Apply the default and overrides attributes from the expansion
448
+ # passed in, which came from roles.
449
+ def apply_expansion_attributes(expansion)
450
+ @default_attrs = Chef::Mixin::DeepMerge.merge(default_attrs, expansion.default_attrs)
451
+ environment_attrs = chef_environment == "_default" ? {} : Chef::Environment.load(chef_environment).attributes
452
+ overrides_before_environments = Chef::Mixin::DeepMerge.merge(override_attrs, expansion.override_attrs)
453
+ @override_attrs = Chef::Mixin::DeepMerge.merge(overrides_before_environments, environment_attrs)
420
454
  end
421
455
 
422
456
  # Transform the node to a Hash
@@ -424,6 +458,7 @@ class Chef
424
458
  index_hash = Hash.new
425
459
  index_hash["chef_type"] = "node"
426
460
  index_hash["name"] = name
461
+ index_hash["chef_environment"] = chef_environment
427
462
  attribute.each do |key, value|
428
463
  index_hash[key] = value
429
464
  end
@@ -437,6 +472,7 @@ class Chef
437
472
  def to_json(*a)
438
473
  result = {
439
474
  "name" => name,
475
+ "chef_environment" => chef_environment,
440
476
  'json_class' => self.class.name,
441
477
  "automatic" => automatic_attrs,
442
478
  "normal" => normal_attrs,
@@ -449,11 +485,21 @@ class Chef
449
485
  result.to_json(*a)
450
486
  end
451
487
 
488
+ def update_from!(o)
489
+ run_list.reset!(o.run_list)
490
+ @automatic_attrs = o.automatic_attrs
491
+ @normal_attrs = o.normal_attrs
492
+ @override_attrs = o.override_attrs
493
+ @default_attrs = o.default_attrs
494
+ chef_environment(o.chef_environment)
495
+ self
496
+ end
497
+
452
498
  # Create a Chef::Node from JSON
453
499
  def self.json_create(o)
454
500
  node = new
455
501
  node.name(o["name"])
456
-
502
+ node.chef_environment(o["chef_environment"])
457
503
  if o.has_key?("attributes")
458
504
  node.normal_attrs = o["attributes"]
459
505
  end
@@ -473,6 +519,21 @@ class Chef
473
519
  node
474
520
  end
475
521
 
522
+ def self.cdb_list_by_environment(environment, inflate=false, couchdb=nil)
523
+ rs = (couchdb || Chef::CouchDB.new).get_view("nodes", "by_environment", :include_docs => inflate, :startkey => environment, :endkey => environment)
524
+ inflate ? rs["rows"].collect {|r| r["doc"]} : rs["rows"].collect {|r| r["value"]}
525
+ end
526
+
527
+ def self.list_by_environment(environment, inflate=false)
528
+ if inflate
529
+ response = Hash.new
530
+ Chef::Search::Query.new.search(:node, "chef_environment:#{environment}") {|n| response[n.name] = n unless n.nil?}
531
+ response
532
+ else
533
+ Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("environments/#{environment}/nodes")
534
+ end
535
+ end
536
+
476
537
  # List all the Chef::Node objects in the CouchDB. If inflate is set to true, you will get
477
538
  # the full list of all Nodes, fully inflated.
478
539
  def self.cdb_list(inflate=false, couchdb=nil)
@@ -517,6 +578,7 @@ class Chef
517
578
  def self.build(node_name)
518
579
  node = new
519
580
  node.name(node_name)
581
+ node.chef_environment(Chef::Config[:environment]) unless Chef::Config[:environment].nil? || Chef::Config[:environment].chop.empty?
520
582
  node
521
583
  end
522
584
 
@@ -563,11 +625,11 @@ class Chef
563
625
  def self.create_design_document(couchdb=nil)
564
626
  (couchdb || Chef::CouchDB.new).create_design_document("nodes", DESIGN_DOCUMENT)
565
627
  end
566
-
628
+
567
629
  def to_s
568
630
  "node[#{name}]"
569
631
  end
570
-
632
+
571
633
  # Load all attribute files for all cookbooks associated with this
572
634
  # node.
573
635
  def load_attributes
@@ -578,7 +640,7 @@ class Chef
578
640
  end
579
641
  end
580
642
  end
581
-
643
+
582
644
  # Used by DSL.
583
645
  # Loads the attribute file specified by the short name of the
584
646
  # file, e.g., loads specified cookbook's
@@ -588,7 +650,7 @@ class Chef
588
650
  def load_attribute_by_short_filename(name, src_cookbook_name)
589
651
  src_cookbook = cookbook_collection[src_cookbook_name]
590
652
  raise Chef::Exceptions::CookbookNotFound, "could not find cookbook #{src_cookbook_name} while loading attribute #{name}" unless src_cookbook
591
-
653
+
592
654
  attribute_filename = src_cookbook.attribute_filenames_by_short_filename[name]
593
655
  raise Chef::Exceptions::AttributeNotFound, "could not find filename for attribute #{name} in cookbook #{src_cookbook_name}" unless attribute_filename
594
656