chef 0.7.16 → 0.8.2

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 (180) hide show
  1. data/README.rdoc +11 -10
  2. data/bin/chef-client +2 -2
  3. data/bin/chef-solo +1 -1
  4. data/bin/knife +27 -0
  5. data/bin/shef +49 -0
  6. data/distro/README +2 -0
  7. data/distro/{debian → common}/man/man1/chef-indexer.1 +0 -0
  8. data/distro/{debian → common}/man/man1/chef-server.1 +0 -0
  9. data/distro/{debian → common}/man/man8/chef-client.8 +0 -0
  10. data/distro/{debian → common}/man/man8/chef-solo.8 +0 -0
  11. data/distro/common/man/man8/knife.8 +375 -0
  12. data/distro/redhat/etc/init.d/chef-client +8 -4
  13. data/distro/redhat/etc/init.d/chef-server +16 -15
  14. data/distro/redhat/etc/init.d/chef-server-webui +78 -0
  15. data/distro/redhat/etc/init.d/chef-solr +76 -0
  16. data/distro/redhat/etc/init.d/chef-solr-indexer +75 -0
  17. data/distro/redhat/etc/sysconfig/chef-client +10 -0
  18. data/distro/redhat/etc/sysconfig/chef-server +10 -0
  19. data/distro/redhat/etc/sysconfig/chef-server-webui +10 -0
  20. data/distro/redhat/etc/sysconfig/chef-solr +9 -0
  21. data/distro/redhat/etc/sysconfig/chef-solr-indexer +7 -0
  22. data/distro/suse/etc/init.d/chef-client +121 -0
  23. data/lib/chef.rb +1 -1
  24. data/lib/chef/api_client.rb +263 -0
  25. data/lib/chef/application.rb +1 -1
  26. data/lib/chef/application/client.rb +21 -3
  27. data/lib/chef/application/knife.rb +144 -0
  28. data/lib/chef/application/server.rb +2 -1
  29. data/lib/chef/application/solo.rb +9 -2
  30. data/lib/chef/cache.rb +61 -0
  31. data/lib/chef/cache/checksum.rb +70 -0
  32. data/lib/chef/certificate.rb +154 -0
  33. data/lib/chef/client.rb +123 -220
  34. data/lib/chef/compile.rb +9 -21
  35. data/lib/chef/config.rb +67 -10
  36. data/lib/chef/cookbook.rb +49 -22
  37. data/lib/chef/cookbook/metadata.rb +85 -5
  38. data/lib/chef/cookbook_loader.rb +4 -4
  39. data/lib/chef/couchdb.rb +99 -30
  40. data/lib/chef/daemon.rb +1 -1
  41. data/lib/chef/data_bag.rb +215 -0
  42. data/lib/chef/data_bag_item.rb +219 -0
  43. data/lib/chef/exceptions.rb +3 -0
  44. data/lib/chef/index_queue.rb +29 -0
  45. data/lib/chef/index_queue/amqp_client.rb +106 -0
  46. data/lib/chef/index_queue/consumer.rb +76 -0
  47. data/lib/chef/index_queue/indexable.rb +74 -0
  48. data/lib/chef/knife.rb +309 -0
  49. data/lib/chef/knife/client_bulk_delete.rb +40 -0
  50. data/lib/chef/knife/client_create.rb +62 -0
  51. data/lib/chef/knife/client_delete.rb +37 -0
  52. data/lib/chef/knife/client_edit.rb +37 -0
  53. data/lib/chef/knife/client_list.rb +40 -0
  54. data/lib/chef/knife/client_reregister.rb +48 -0
  55. data/lib/chef/knife/client_show.rb +42 -0
  56. data/lib/chef/knife/configure.rb +123 -0
  57. data/lib/chef/knife/cookbook_bulk_delete.rb +46 -0
  58. data/lib/chef/knife/cookbook_delete.rb +41 -0
  59. data/lib/chef/knife/cookbook_download.rb +57 -0
  60. data/lib/chef/knife/cookbook_list.rb +41 -0
  61. data/lib/chef/knife/cookbook_metadata.rb +87 -0
  62. data/lib/chef/knife/cookbook_show.rb +75 -0
  63. data/lib/chef/knife/cookbook_upload.rb +179 -0
  64. data/lib/chef/knife/data_bag_create.rb +43 -0
  65. data/lib/chef/knife/data_bag_delete.rb +43 -0
  66. data/lib/chef/knife/data_bag_edit.rb +49 -0
  67. data/lib/chef/knife/data_bag_list.rb +42 -0
  68. data/lib/chef/knife/data_bag_show.rb +40 -0
  69. data/lib/chef/knife/ec2_instance_data.rb +46 -0
  70. data/lib/chef/knife/index_rebuild.rb +51 -0
  71. data/lib/chef/knife/node_bulk_delete.rb +43 -0
  72. data/lib/chef/knife/node_create.rb +39 -0
  73. data/lib/chef/knife/node_delete.rb +36 -0
  74. data/lib/chef/knife/node_edit.rb +36 -0
  75. data/lib/chef/knife/node_from_file.rb +42 -0
  76. data/lib/chef/knife/node_list.rb +41 -0
  77. data/lib/chef/knife/node_run_list_add.rb +64 -0
  78. data/lib/chef/knife/node_run_list_remove.rb +45 -0
  79. data/lib/chef/knife/node_show.rb +46 -0
  80. data/lib/chef/knife/role_bulk_delete.rb +44 -0
  81. data/lib/chef/knife/role_create.rb +44 -0
  82. data/lib/chef/knife/role_delete.rb +36 -0
  83. data/lib/chef/knife/role_edit.rb +37 -0
  84. data/lib/chef/knife/role_from_file.rb +46 -0
  85. data/lib/chef/knife/role_list.rb +40 -0
  86. data/lib/chef/knife/role_show.rb +43 -0
  87. data/lib/chef/knife/search.rb +94 -0
  88. data/lib/chef/knife/ssh.rb +170 -0
  89. data/lib/chef/log.rb +30 -8
  90. data/lib/chef/mixin/checksum.rb +2 -7
  91. data/lib/chef/mixin/command.rb +32 -13
  92. data/lib/chef/mixin/convert_to_class_name.rb +15 -0
  93. data/lib/chef/mixin/deep_merge.rb +199 -11
  94. data/lib/chef/mixin/generate_url.rb +18 -9
  95. data/lib/chef/mixin/language.rb +29 -1
  96. data/lib/chef/mixin/language_include_attribute.rb +56 -0
  97. data/lib/chef/mixin/language_include_recipe.rb +53 -0
  98. data/lib/chef/mixin/params_validate.rb +25 -12
  99. data/lib/chef/mixin/recipe_definition_dsl_core.rb +2 -0
  100. data/lib/chef/mixin/template.rb +11 -1
  101. data/lib/chef/mixin/xml_escape.rb +87 -0
  102. data/lib/chef/node.rb +144 -122
  103. data/lib/chef/openid_registration.rb +12 -5
  104. data/lib/chef/platform.rb +89 -47
  105. data/lib/chef/provider/breakpoint.rb +36 -0
  106. data/lib/chef/provider/cron.rb +5 -6
  107. data/lib/chef/provider/deploy.rb +43 -10
  108. data/lib/chef/provider/deploy/revision.rb +2 -3
  109. data/lib/chef/provider/erl_call.rb +72 -0
  110. data/lib/chef/provider/file.rb +8 -4
  111. data/lib/chef/provider/git.rb +10 -5
  112. data/lib/chef/provider/group/dscl.rb +128 -0
  113. data/lib/chef/provider/http_request.rb +6 -2
  114. data/lib/chef/provider/ifconfig.rb +1 -0
  115. data/lib/chef/provider/link.rb +1 -1
  116. data/lib/chef/provider/log.rb +53 -0
  117. data/lib/chef/provider/mdadm.rb +88 -0
  118. data/lib/chef/provider/mount/mount.rb +1 -1
  119. data/lib/chef/provider/package.rb +1 -1
  120. data/lib/chef/provider/package/easy_install.rb +106 -0
  121. data/lib/chef/provider/package/pacman.rb +101 -0
  122. data/lib/chef/provider/package/portage.rb +1 -1
  123. data/lib/chef/provider/package/rpm.rb +10 -8
  124. data/lib/chef/provider/package/yum-dump.py +22 -3
  125. data/lib/chef/provider/package/yum.rb +32 -8
  126. data/lib/chef/provider/package/zypper.rb +132 -0
  127. data/lib/chef/provider/remote_directory.rb +58 -49
  128. data/lib/chef/provider/remote_file.rb +1 -1
  129. data/lib/chef/provider/route.rb +136 -80
  130. data/lib/chef/provider/ruby_block.rb +18 -1
  131. data/lib/chef/provider/service/arch.rb +109 -0
  132. data/lib/chef/provider/service/freebsd.rb +0 -1
  133. data/lib/chef/provider/service/simple.rb +2 -3
  134. data/lib/chef/provider/service/upstart.rb +191 -0
  135. data/lib/chef/provider/subversion.rb +12 -4
  136. data/lib/chef/provider/template.rb +85 -53
  137. data/lib/chef/provider/user.rb +1 -1
  138. data/lib/chef/provider/user/dscl.rb +277 -0
  139. data/lib/chef/provider/user/useradd.rb +1 -0
  140. data/lib/chef/recipe.rb +2 -41
  141. data/lib/chef/resource.rb +9 -3
  142. data/lib/chef/resource/breakpoint.rb +35 -0
  143. data/lib/chef/resource/deploy.rb +16 -2
  144. data/lib/chef/resource/easy_install_package.rb +41 -0
  145. data/lib/chef/resource/erl_call.rb +83 -0
  146. data/lib/chef/resource/freebsd_package.rb +35 -0
  147. data/lib/chef/resource/log.rb +62 -0
  148. data/lib/chef/resource/mdadm.rb +82 -0
  149. data/lib/chef/resource/pacman_package.rb +33 -0
  150. data/lib/chef/resource/ruby_block.rb +21 -2
  151. data/lib/chef/resource/scm.rb +8 -0
  152. data/lib/chef/resource/subversion.rb +1 -0
  153. data/lib/chef/resource/user.rb +5 -2
  154. data/lib/chef/resource/yum_package.rb +36 -0
  155. data/lib/chef/resource_collection.rb +17 -9
  156. data/lib/chef/resource_collection/stepable_iterator.rb +124 -0
  157. data/lib/chef/rest.rb +166 -81
  158. data/lib/chef/role.rb +114 -38
  159. data/lib/chef/run_list.rb +15 -6
  160. data/lib/chef/runner.rb +13 -11
  161. data/lib/chef/search/query.rb +60 -0
  162. data/lib/chef/shef.rb +220 -0
  163. data/lib/chef/shef/ext.rb +297 -0
  164. data/lib/chef/shef/shef_session.rb +175 -0
  165. data/lib/chef/streaming_cookbook_uploader.rb +187 -0
  166. data/lib/chef/tasks/chef_repo.rake +53 -155
  167. data/lib/chef/util/file_edit.rb +94 -96
  168. data/lib/chef/webui_user.rb +233 -0
  169. metadata +219 -63
  170. data/distro/debian/etc/init.d/chef-indexer +0 -175
  171. data/distro/redhat/etc/chef/client.rb +0 -16
  172. data/distro/redhat/etc/chef/indexer.rb +0 -10
  173. data/distro/redhat/etc/chef/server.rb +0 -22
  174. data/distro/redhat/etc/init.d/chef-indexer +0 -76
  175. data/lib/chef/application/indexer.rb +0 -141
  176. data/lib/chef/queue.rb +0 -145
  177. data/lib/chef/search.rb +0 -88
  178. data/lib/chef/search/result.rb +0 -64
  179. data/lib/chef/search_index.rb +0 -77
  180. data/lib/chef/util/fileedit.rb +0 -121
@@ -1,5 +1,7 @@
1
1
  #
2
2
  # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Author:: Nuo Yan (<nuo@opscode.com>)
4
+ # Author:: Christopher Brown (<cb@opscode.com>)
3
5
  # Copyright:: Copyright (c) 2008 Opscode, Inc.
4
6
  # License:: Apache License, Version 2.0
5
7
  #
@@ -20,6 +22,8 @@ require 'chef/config'
20
22
  require 'chef/mixin/params_validate'
21
23
  require 'chef/mixin/from_file'
22
24
  require 'chef/couchdb'
25
+ require 'chef/run_list'
26
+ require 'chef/index_queue'
23
27
  require 'extlib'
24
28
  require 'json'
25
29
 
@@ -28,9 +32,10 @@ class Chef
28
32
 
29
33
  include Chef::Mixin::FromFile
30
34
  include Chef::Mixin::ParamsValidate
35
+ include Chef::IndexQueue::Indexable
31
36
 
32
37
  DESIGN_DOCUMENT = {
33
- "version" => 3,
38
+ "version" => 6,
34
39
  "language" => "javascript",
35
40
  "views" => {
36
41
  "all" => {
@@ -50,21 +55,36 @@ class Chef
50
55
  }
51
56
  }
52
57
  EOJS
53
- },
54
- },
58
+ }
59
+ }
55
60
  }
56
61
 
57
- attr_accessor :couchdb_rev
62
+ attr_accessor :couchdb_rev, :couchdb
63
+ attr_reader :couchdb_id
58
64
 
59
65
  # Create a new Chef::Role object.
60
- def initialize()
66
+ def initialize(couchdb=nil)
61
67
  @name = ''
62
68
  @description = ''
63
69
  @default_attributes = Mash.new
64
70
  @override_attributes = Mash.new
65
- @recipes = Array.new
71
+ @run_list = Chef::RunList.new
66
72
  @couchdb_rev = nil
67
- @couchdb = Chef::CouchDB.new
73
+ @couchdb_id = nil
74
+ @couchdb = couchdb || Chef::CouchDB.new
75
+ end
76
+
77
+ def couchdb_id=(value)
78
+ @couchdb_id = value
79
+ self.index_id = value
80
+ end
81
+
82
+ def chef_server_rest
83
+ Chef::REST.new(Chef::Config[:chef_server_url])
84
+ end
85
+
86
+ def self.chef_server_rest
87
+ Chef::REST.new(Chef::Config[:chef_server_url])
68
88
  end
69
89
 
70
90
  def name(arg=nil)
@@ -83,18 +103,17 @@ class Chef
83
103
  )
84
104
  end
85
105
 
86
- def recipes(*arg)
87
- arg.flatten!
88
- if arg.length == 0
89
- @recipes
90
- else
91
- arg.each do |entry|
92
- raise ArgumentError, 'Recipes must be strings!' unless entry.kind_of?(String)
93
- end
94
- @recipes = arg
95
- end
106
+ def run_list(*args)
107
+ (args.length > 0) ? @run_list.reset!(args) : @run_list
96
108
  end
97
109
 
110
+ alias_method :recipes, :run_list
111
+
112
+ # def recipes(*args)
113
+ # Chef::Log.warn "Chef::Role#recipes method is deprecated. Please use Chef::Role#run_list"
114
+ # run_list(*args)
115
+ # end
116
+
98
117
  def default_attributes(arg=nil)
99
118
  set_or_return(
100
119
  :default_attributes,
@@ -119,9 +138,9 @@ class Chef
119
138
  "default_attributes" => @default_attributes,
120
139
  "override_attributes" => @override_attributes,
121
140
  "chef_type" => "role",
122
- "recipes" => @recipes,
141
+ "run_list" => @run_list.run_list
123
142
  }
124
- result["_rev"] = @couchdb_rev if @couchdb_rev
143
+ result["_rev"] = couchdb_rev if couchdb_rev
125
144
  result
126
145
  end
127
146
 
@@ -137,56 +156,113 @@ class Chef
137
156
  role.description(o["description"])
138
157
  role.default_attributes(o["default_attributes"])
139
158
  role.override_attributes(o["override_attributes"])
140
- role.recipes(o["recipes"])
159
+ role.run_list(if o.has_key?("run_list")
160
+ o["run_list"]
161
+ else
162
+ o["recipes"]
163
+ end)
141
164
  role.couchdb_rev = o["_rev"] if o.has_key?("_rev")
165
+ role.index_id = role.couchdb_id
166
+ role.couchdb_id = o["_id"] if o.has_key?("_id")
142
167
  role
143
168
  end
144
169
 
145
170
  # List all the Chef::Role objects in the CouchDB. If inflate is set to true, you will get
146
171
  # the full list of all Roles, fully inflated.
172
+ def self.cdb_list(inflate=false, couchdb=nil)
173
+ rs = (couchdb || Chef::CouchDB.new).list("roles", inflate)
174
+ lookup = (inflate ? "value" : "key")
175
+ rs["rows"].collect { |r| r[lookup] }
176
+ end
177
+
178
+ # Get the list of all roles from the API.
147
179
  def self.list(inflate=false)
148
- rs = Chef::CouchDB.new.list("roles", inflate)
149
180
  if inflate
150
- rs["rows"].collect { |r| r["value"] }
181
+ response = Hash.new
182
+ Chef::Search::Query.new.search(:role) do |n|
183
+ response[n.name] = n unless n.nil?
184
+ end
185
+ response
151
186
  else
152
- rs["rows"].collect { |r| r["key"] }
187
+ chef_server_rest.get_rest("roles")
153
188
  end
154
189
  end
155
190
 
156
191
  # Load a role by name from CouchDB
192
+ def self.cdb_load(name, couchdb=nil)
193
+ (couchdb || Chef::CouchDB.new).load("role", name)
194
+ end
195
+
196
+ # Load a role by name from the API
157
197
  def self.load(name)
158
- Chef::CouchDB.new.load("role", name)
198
+ chef_server_rest.get_rest("roles/#{name}")
199
+ end
200
+
201
+ def self.exists?(rolename, couchdb)
202
+ begin
203
+ self.cdb_load(rolename, couchdb)
204
+ rescue Chef::Exceptions::CouchDBNotFound
205
+ nil
206
+ end
159
207
  end
160
208
 
161
209
  # Remove this role from the CouchDB
162
- def destroy
163
- @couchdb.delete("role", @name, @couchdb_rev)
210
+ def cdb_destroy
211
+ couchdb.delete("role", @name, couchdb_rev)
164
212
 
165
213
  if Chef::Config[:couchdb_version] == 0.9
166
- rs = @couchdb.get_view("nodes", "by_run_list", :startkey => "role[#{@name}]", :endkey => "role[#{@name}]", :include_docs => true)
214
+ rs = couchdb.get_view("nodes", "by_run_list", :startkey => "role[#{@name}]", :endkey => "role[#{@name}]", :include_docs => true)
167
215
  rs["rows"].each do |row|
168
216
  node = row["doc"]
169
217
  node.run_list.remove("role[#{@name}]")
170
- node.save
218
+ node.cdb_save
171
219
  end
172
220
  else
173
- Chef::Node.list.each do |node|
174
- n = Chef::Node.load(node)
221
+ Chef::Node.cdb_list.each do |node|
222
+ n = Chef::Node.cdb_load(node)
175
223
  n.run_list.remove("role[#{@name}]")
176
- n.save
224
+ n.cdb_save
177
225
  end
178
226
  end
179
227
  end
180
228
 
229
+ # Remove this role via the REST API
230
+ def destroy
231
+ chef_server_rest.delete_rest("roles/#{@name}")
232
+
233
+ Chef::Node.list.each do |node|
234
+ n = Chef::Node.load(node[0])
235
+ n.run_list.remove("role[#{@name}]")
236
+ n.save
237
+ end
238
+
239
+ end
240
+
181
241
  # Save this role to the CouchDB
242
+ def cdb_save
243
+ self.couchdb_rev = couchdb.store("role", @name, self)["rev"]
244
+ end
245
+
246
+ # Save this role via the REST API
182
247
  def save
183
- results = @couchdb.store("role", @name, self)
184
- @couchdb_rev = results["rev"]
248
+ begin
249
+ chef_server_rest.put_rest("roles/#{@name}", self)
250
+ rescue Net::HTTPServerException => e
251
+ raise e unless e.response.code == "404"
252
+ chef_server_rest.post_rest("roles", self)
253
+ end
254
+ self
185
255
  end
186
256
 
257
+ # Create the role via the REST API
258
+ def create
259
+ chef_server_rest.post_rest("roles", self)
260
+ self
261
+ end
262
+
187
263
  # Set up our CouchDB design document
188
- def self.create_design_document
189
- Chef::CouchDB.new.create_design_document("roles", DESIGN_DOCUMENT)
264
+ def self.create_design_document(couchdb=nil)
265
+ (couchdb || Chef::CouchDB.new).create_design_document("roles", DESIGN_DOCUMENT)
190
266
  end
191
267
 
192
268
  # As a string
@@ -217,13 +293,13 @@ class Chef
217
293
  Chef::Log.warn("Loading #{short_name}")
218
294
  r = Chef::Role.from_disk(short_name, "json")
219
295
  begin
220
- couch_role = Chef::Role.load(short_name)
296
+ couch_role = Chef::Role.cdb_load(short_name)
221
297
  r.couchdb_rev = couch_role.couchdb_rev
222
298
  Chef::Log.debug("Replacing role #{short_name} with data from #{role_file}")
223
- rescue Net::HTTPServerException
299
+ rescue Chef::Exceptions::CouchDBNotFound
224
300
  Chef::Log.debug("Creating role #{short_name} with data from #{role_file}")
225
301
  end
226
- r.save
302
+ r.cdb_save
227
303
  end
228
304
  end
229
305
 
@@ -27,6 +27,7 @@ class Chef
27
27
  @run_list = Array.new
28
28
  @recipes = Array.new
29
29
  @roles = Array.new
30
+ @seen_roles = Array.new
30
31
  end
31
32
 
32
33
  def <<(item)
@@ -60,6 +61,10 @@ class Chef
60
61
  true
61
62
  end
62
63
 
64
+ def to_s
65
+ @run_list.join(", ")
66
+ end
67
+
63
68
  def empty?
64
69
  @run_list.length == 0 ? true : false
65
70
  end
@@ -86,7 +91,7 @@ class Chef
86
91
  @run_list.include?(fentry)
87
92
  end
88
93
 
89
- def reset(*args)
94
+ def reset!(*args)
90
95
  @run_list = Array.new
91
96
  @recipes = Array.new
92
97
  @roles = Array.new
@@ -111,7 +116,8 @@ class Chef
111
116
  self
112
117
  end
113
118
 
114
- def expand(from='server')
119
+ def expand(from='server', couchdb=nil)
120
+ couchdb = couchdb ? couchdb : Chef::CouchDB.new
115
121
  recipes = Array.new
116
122
  default_attrs = Mash.new
117
123
  override_attrs = Mash.new
@@ -123,6 +129,7 @@ class Chef
123
129
  recipes << name unless recipes.include?(name)
124
130
  when 'role'
125
131
  role = nil
132
+ next if @seen_roles.include?(name)
126
133
  if from == 'disk' || Chef::Config[:solo]
127
134
  # Load the role from disk
128
135
  role = Chef::Role.from_disk("#{name}")
@@ -132,11 +139,13 @@ class Chef
132
139
  role = r.get_rest("roles/#{name}")
133
140
  elsif from == 'couchdb'
134
141
  # Load the role from couchdb
135
- role = Chef::Role.load(name)
142
+ role = Chef::Role.cdb_load(name, couchdb)
136
143
  end
137
- role.recipes.each { |r| recipes << r unless recipes.include?(r) }
138
- default_attrs = Chef::Mixin::DeepMerge.merge(default_attrs, role.default_attributes)
139
- override_attrs = Chef::Mixin::DeepMerge.merge(override_attrs, role.override_attributes)
144
+ @seen_roles << name
145
+ rec, d, o = role.run_list.expand(from)
146
+ rec.each { |r| recipes << r unless recipes.include?(r) }
147
+ default_attrs = Chef::Mixin::DeepMerge.merge(default_attrs, Chef::Mixin::DeepMerge.merge(role.default_attributes,d))
148
+ override_attrs = Chef::Mixin::DeepMerge.merge(override_attrs, Chef::Mixin::DeepMerge.merge(role.override_attributes, o))
140
149
  end
141
150
  end
142
151
  return recipes, default_attrs, override_attrs
@@ -48,8 +48,7 @@ class Chef
48
48
  end
49
49
 
50
50
  def build_provider(resource)
51
- provider_klass = resource.provider
52
- provider_klass ||= Chef::Platform.find_provider_for_node(@node, resource)
51
+ provider_klass = Chef::Platform.find_provider_for_node(@node, resource)
53
52
  Chef::Log.debug("#{resource} using #{provider_klass.to_s}")
54
53
  provider = provider_klass.new(@node, resource, @collection, @definitions, @cookbook_loader)
55
54
  provider.load_current_resource
@@ -71,7 +70,10 @@ class Chef
71
70
  if resource.actions[action].has_key?(:delayed)
72
71
  resource.actions[action][:delayed].each do |r|
73
72
  @delayed_actions[r] = Hash.new unless @delayed_actions.has_key?(r)
74
- @delayed_actions[r][action] = Array.new unless @delayed_actions[r].has_key?(action)
73
+ unless @delayed_actions[r].has_key?(action)
74
+ @ordered_delayed_actions << [r, action]
75
+ @delayed_actions[r][action] = Array.new
76
+ end
75
77
  @delayed_actions[r][action] << lambda {
76
78
  Chef::Log.info("#{resource} sending #{action} action to #{r} (delayed)")
77
79
  }
@@ -84,6 +86,7 @@ class Chef
84
86
  def converge
85
87
 
86
88
  @delayed_actions = Hash.new
89
+ @ordered_delayed_actions = []
87
90
 
88
91
  @collection.execute_each_resource do |resource|
89
92
  begin
@@ -91,7 +94,7 @@ class Chef
91
94
 
92
95
  # Check if this resource has an only_if block - if it does, skip it.
93
96
  if resource.only_if
94
- unless Chef::Mixin::Command.only_if(resource.only_if)
97
+ unless Chef::Mixin::Command.only_if(resource.only_if, resource.only_if_args)
95
98
  Chef::Log.debug("Skipping #{resource} due to only_if")
96
99
  next
97
100
  end
@@ -99,7 +102,7 @@ class Chef
99
102
 
100
103
  # Check if this resource has a not_if block - if it does, skip it.
101
104
  if resource.not_if
102
- unless Chef::Mixin::Command.not_if(resource.not_if)
105
+ unless Chef::Mixin::Command.not_if(resource.not_if, resource.not_if_args)
103
106
  Chef::Log.debug("Skipping #{resource} due to not_if")
104
107
  next
105
108
  end
@@ -111,17 +114,16 @@ class Chef
111
114
  run_action(resource, ra)
112
115
  end
113
116
  rescue => e
114
- Chef::Log.error("#{resource} (#{resource.source_line}) had an error:\n#{e}\n#{e.backtrace}")
117
+ Chef::Log.error("#{resource} (#{resource.source_line}) had an error:\n#{e}\n#{e.backtrace.join("\n")}")
115
118
  raise e unless resource.ignore_failure
116
119
  end
117
120
  end
118
121
 
119
122
  # Run all our :delayed actions
120
- @delayed_actions.each do |resource, action_hash|
121
- action_hash.each do |action, log_array|
122
- log_array.each { |l| l.call } # Call each log message
123
- run_action(resource, action)
124
- end
123
+ @ordered_delayed_actions.each do |resource, action|
124
+ log_array = @delayed_actions[resource][action]
125
+ log_array.each { |l| l.call } # Call each log message
126
+ run_action(resource, action)
125
127
  end
126
128
 
127
129
  true
@@ -0,0 +1,60 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Copyright:: Copyright (c) 2008 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
+
19
+ require 'chef/config'
20
+ require 'uri'
21
+
22
+ class Chef
23
+ class Search
24
+ class Query
25
+
26
+ attr_accessor :rest
27
+
28
+ def initialize(url=nil)
29
+ @rest = Chef::REST.new(url ||Chef::Config[:search_url])
30
+ end
31
+
32
+ # Search Solr for objects of a given type, for a given query. If you give
33
+ # it a block, it will handle the paging for you dynamically.
34
+ def search(type, query="*:*", sort=nil, start=0, rows=20, &block)
35
+ raise ArgumentError, "Type must be a string or a symbol!" unless (type.kind_of?(String) || type.kind_of?(Symbol))
36
+
37
+ response = @rest.get_rest("search/#{type}?q=#{escape(query)}&sort=#{escape(sort)}&start=#{escape(start)}&rows=#{escape(rows)}")
38
+ if block
39
+ response["rows"].each { |o| block.call(o) unless o.nil?}
40
+ unless (response["start"] + response["rows"].length) >= response["total"]
41
+ nstart = response["start"] + rows
42
+ search(type, query, sort, nstart, rows, &block)
43
+ end
44
+ true
45
+ else
46
+ [ response["rows"], response["start"], response["total"] ]
47
+ end
48
+ end
49
+
50
+ def list_indexes
51
+ response = @rest.get_rest("search")
52
+ end
53
+
54
+ private
55
+ def escape(s)
56
+ s && URI.escape(s.to_s)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,220 @@
1
+ # Author:: Daniel DeLeo (<dan@kallistec.com>)
2
+ # Copyright:: Copyright (c) 2009 Daniel DeLeo
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require "singleton"
19
+ require "pp"
20
+ require "etc"
21
+ require "mixlib/cli"
22
+
23
+ require "chef/client"
24
+ require "chef/config"
25
+
26
+ require "chef/shef/shef_session"
27
+ require "chef/shef/ext"
28
+
29
+
30
+ module Shef
31
+ LEADERS = Hash.new("")
32
+ LEADERS[Chef::Recipe] = ":recipe"
33
+ LEADERS[Chef::Node] = ":attributes"
34
+
35
+ class << self
36
+ attr_accessor :client_type, :options
37
+ end
38
+
39
+ # Shef assumes it's running whenever it is defined
40
+ def self.running?
41
+ true
42
+ end
43
+
44
+ # Set the irb_conf object to something other than IRB.conf
45
+ # usful for testing.
46
+ def self.irb_conf=(conf_hash)
47
+ @irb_conf = conf_hash
48
+ end
49
+
50
+ def self.irb_conf
51
+ @irb_conf || IRB.conf
52
+ end
53
+
54
+ def self.configure_irb
55
+ irb_conf[:HISTORY_FILE] = "~/.shef_history"
56
+ irb_conf[:SAVE_HISTORY] = 1000
57
+
58
+ irb_conf[:IRB_RC] = lambda do |conf|
59
+ m = conf.main
60
+ leader = LEADERS[m.class]
61
+
62
+ def m.help
63
+ shef_help
64
+ end
65
+
66
+ conf.prompt_c = "chef#{leader} > "
67
+ conf.return_format = " => %s \n"
68
+ conf.prompt_i = "chef#{leader} > "
69
+ conf.prompt_n = "chef#{leader} ?> "
70
+ conf.prompt_s = "chef#{leader}%l> "
71
+ end
72
+ end
73
+
74
+ def self.session
75
+ client_type.instance.reset! unless client_type.instance.node_built?
76
+ client_type.instance
77
+ end
78
+
79
+ def self.init
80
+ parse_json
81
+ configure_irb
82
+
83
+ session # trigger ohai run + session load
84
+
85
+ session.node.consume_attributes(@json_attribs)
86
+
87
+ greeting = begin
88
+ " #{Etc.getlogin}@#{Shef.session.node.name}"
89
+ rescue NameError
90
+ ""
91
+ end
92
+
93
+ version
94
+ puts
95
+
96
+ puts "run `help' for help, `exit' or ^D to quit."
97
+ puts
98
+ puts "Ohai2u#{greeting}!"
99
+ end
100
+
101
+ def self.parse_json
102
+ if Chef::Config[:json_attribs]
103
+ begin
104
+ json_io = open(Chef::Config[:json_attribs])
105
+ rescue SocketError => error
106
+ fatal!("I cannot connect to #{Chef::Config[:json_attribs]}", 2)
107
+ rescue Errno::ENOENT => error
108
+ fatal!("I cannot find #{Chef::Config[:json_attribs]}", 2)
109
+ rescue Errno::EACCES => error
110
+ fatal!("Permissions are incorrect on #{Chef::Config[:json_attribs]}. Please chmod a+r #{Chef::Config[:json_attribs]}", 2)
111
+ rescue Exception => error
112
+ fatal!("Got an unexpected error reading #{Chef::Config[:json_attribs]}: #{error.message}", 2)
113
+ end
114
+
115
+ begin
116
+ @json_attribs = JSON.parse(json_io.read)
117
+ rescue JSON::ParserError => error
118
+ fatal!("Could not parse the provided JSON file (#{Chef::Config[:json_attribs]})!: " + error.message, 2)
119
+ end
120
+ end
121
+ end
122
+
123
+ def self.fatal!(message, exit_status)
124
+ Chef::Log.fatal(message)
125
+ exit exit_status
126
+ end
127
+
128
+ def self.client_type
129
+ type = Shef::StandAloneSession
130
+ type = Shef::SoloSession if Chef::Config[:solo]
131
+ type = Shef::ClientSession if Chef::Config[:client]
132
+ type
133
+ end
134
+
135
+ def self.parse_opts
136
+ @options = Options.new
137
+ @options.parse_opts
138
+ end
139
+
140
+ class Options
141
+ include Mixlib::CLI
142
+
143
+ option :config_file,
144
+ :short => "-c CONFIG",
145
+ :long => "--config CONFIG",
146
+ :description => "The configuration file to use"
147
+
148
+ option :help,
149
+ :short => "-h",
150
+ :long => "--help",
151
+ :description => "Show this message",
152
+ :on => :tail,
153
+ :boolean => true,
154
+ :show_options => true,
155
+ :exit => 0
156
+
157
+ option :standalone,
158
+ :short => "-a",
159
+ :long => "--standalone",
160
+ :description => "standalone shef session",
161
+ :default => true,
162
+ :boolean => true
163
+
164
+ option :solo,
165
+ :short => "-s",
166
+ :long => "--solo",
167
+ :description => "chef-solo shef session",
168
+ :boolean => true
169
+
170
+ option :client,
171
+ :short => "-z",
172
+ :long => "--client",
173
+ :description => "chef-client shef session",
174
+ :boolean => true
175
+
176
+ option :json_attribs,
177
+ :short => "-j JSON_ATTRIBS",
178
+ :long => "--json-attributes JSON_ATTRIBS",
179
+ :description => "Load attributes from a JSON file or URL",
180
+ :proc => nil
181
+
182
+ option :chef_server_url,
183
+ :short => "-S CHEFSERVERURL",
184
+ :long => "--server CHEFSERVERURL",
185
+ :description => "The chef server URL",
186
+ :proc => nil
187
+
188
+ option :version,
189
+ :short => "-v",
190
+ :long => "--version",
191
+ :description => "Show chef version",
192
+ :boolean => true,
193
+ :proc => lambda {|v| puts "Chef: #{::Chef::VERSION}"},
194
+ :exit => 0
195
+
196
+ def self.setup!
197
+ self.new.parse_opts
198
+ end
199
+
200
+ def parse_opts
201
+ parse_options
202
+ config[:config_file] = config_file_for_shef_mode
203
+ config_msg = config[:config_file] || "none (standalone shef session)"
204
+ puts "loading configuration: #{config_msg}"
205
+ Chef::Config.from_file(config[:config_file]) if !config[:config_file].nil? && File.exists?(config[:config_file]) && File.readable?(config[:config_file])
206
+ Chef::Config.merge!(config)
207
+ end
208
+
209
+ private
210
+
211
+ def config_file_for_shef_mode
212
+ return config[:config_file] if config[:config_file]
213
+ return "/etc/chef/solo.rb" if config[:solo]
214
+ return "/etc/chef/client.rb" if config[:client]
215
+ nil
216
+ end
217
+
218
+ end
219
+
220
+ end