runa-chef 0.8.0.1

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 (216) hide show
  1. data/LICENSE +201 -0
  2. data/README.rdoc +136 -0
  3. data/bin/chef-client +26 -0
  4. data/bin/chef-solo +26 -0
  5. data/bin/knife +27 -0
  6. data/bin/shef +45 -0
  7. data/distro/README +2 -0
  8. data/distro/common/man/man1/chef-indexer.1 +42 -0
  9. data/distro/common/man/man1/chef-server.1 +108 -0
  10. data/distro/common/man/man8/chef-client.8 +61 -0
  11. data/distro/common/man/man8/chef-solo.8 +58 -0
  12. data/distro/common/man/man8/knife.8 +359 -0
  13. data/distro/debian/etc/init.d/chef-client +175 -0
  14. data/distro/debian/etc/init.d/chef-indexer +175 -0
  15. data/distro/debian/etc/init.d/chef-server +120 -0
  16. data/distro/redhat/etc/init.d/chef-client +78 -0
  17. data/distro/redhat/etc/init.d/chef-indexer +76 -0
  18. data/distro/redhat/etc/init.d/chef-server +78 -0
  19. data/distro/redhat/etc/sysconfig/chef-client +10 -0
  20. data/distro/redhat/etc/sysconfig/chef-indexer +8 -0
  21. data/distro/redhat/etc/sysconfig/chef-server +10 -0
  22. data/distro/suse/etc/init.d/chef-client +121 -0
  23. data/lib/chef.rb +49 -0
  24. data/lib/chef/api_client.rb +269 -0
  25. data/lib/chef/application.rb +98 -0
  26. data/lib/chef/application/agent.rb +18 -0
  27. data/lib/chef/application/client.rb +214 -0
  28. data/lib/chef/application/knife.rb +138 -0
  29. data/lib/chef/application/server.rb +19 -0
  30. data/lib/chef/application/solo.rb +214 -0
  31. data/lib/chef/cache.rb +61 -0
  32. data/lib/chef/cache/checksum.rb +70 -0
  33. data/lib/chef/certificate.rb +154 -0
  34. data/lib/chef/client.rb +323 -0
  35. data/lib/chef/compile.rb +158 -0
  36. data/lib/chef/config.rb +195 -0
  37. data/lib/chef/cookbook.rb +198 -0
  38. data/lib/chef/cookbook/metadata.rb +487 -0
  39. data/lib/chef/cookbook/metadata/version.rb +87 -0
  40. data/lib/chef/cookbook_loader.rb +180 -0
  41. data/lib/chef/couchdb.rb +273 -0
  42. data/lib/chef/daemon.rb +170 -0
  43. data/lib/chef/data_bag.rb +216 -0
  44. data/lib/chef/data_bag_item.rb +227 -0
  45. data/lib/chef/exceptions.rb +39 -0
  46. data/lib/chef/file_cache.rb +205 -0
  47. data/lib/chef/knife.rb +300 -0
  48. data/lib/chef/knife/client_bulk_delete.rb +41 -0
  49. data/lib/chef/knife/client_create.rb +55 -0
  50. data/lib/chef/knife/client_delete.rb +37 -0
  51. data/lib/chef/knife/client_edit.rb +37 -0
  52. data/lib/chef/knife/client_list.rb +40 -0
  53. data/lib/chef/knife/client_reregister.rb +48 -0
  54. data/lib/chef/knife/client_show.rb +42 -0
  55. data/lib/chef/knife/configure.rb +84 -0
  56. data/lib/chef/knife/cookbook_bulk_delete.rb +47 -0
  57. data/lib/chef/knife/cookbook_delete.rb +41 -0
  58. data/lib/chef/knife/cookbook_download.rb +57 -0
  59. data/lib/chef/knife/cookbook_list.rb +41 -0
  60. data/lib/chef/knife/cookbook_metadata.rb +87 -0
  61. data/lib/chef/knife/cookbook_show.rb +75 -0
  62. data/lib/chef/knife/cookbook_upload.rb +173 -0
  63. data/lib/chef/knife/data_bag_create.rb +43 -0
  64. data/lib/chef/knife/data_bag_delete.rb +43 -0
  65. data/lib/chef/knife/data_bag_edit.rb +49 -0
  66. data/lib/chef/knife/data_bag_list.rb +42 -0
  67. data/lib/chef/knife/data_bag_show.rb +40 -0
  68. data/lib/chef/knife/ec2_instance_data.rb +46 -0
  69. data/lib/chef/knife/node_bulk_delete.rb +44 -0
  70. data/lib/chef/knife/node_create.rb +39 -0
  71. data/lib/chef/knife/node_delete.rb +36 -0
  72. data/lib/chef/knife/node_edit.rb +36 -0
  73. data/lib/chef/knife/node_from_file.rb +42 -0
  74. data/lib/chef/knife/node_list.rb +41 -0
  75. data/lib/chef/knife/node_run_list_add.rb +64 -0
  76. data/lib/chef/knife/node_run_list_remove.rb +45 -0
  77. data/lib/chef/knife/node_show.rb +46 -0
  78. data/lib/chef/knife/role_bulk_delete.rb +45 -0
  79. data/lib/chef/knife/role_create.rb +44 -0
  80. data/lib/chef/knife/role_delete.rb +36 -0
  81. data/lib/chef/knife/role_edit.rb +37 -0
  82. data/lib/chef/knife/role_from_file.rb +46 -0
  83. data/lib/chef/knife/role_list.rb +40 -0
  84. data/lib/chef/knife/role_show.rb +43 -0
  85. data/lib/chef/knife/search.rb +94 -0
  86. data/lib/chef/log.rb +39 -0
  87. data/lib/chef/mixin/check_helper.rb +31 -0
  88. data/lib/chef/mixin/checksum.rb +32 -0
  89. data/lib/chef/mixin/command.rb +390 -0
  90. data/lib/chef/mixin/convert_to_class_name.rb +57 -0
  91. data/lib/chef/mixin/create_path.rb +56 -0
  92. data/lib/chef/mixin/deep_merge.rb +33 -0
  93. data/lib/chef/mixin/find_preferred_file.rb +92 -0
  94. data/lib/chef/mixin/from_file.rb +50 -0
  95. data/lib/chef/mixin/generate_url.rb +58 -0
  96. data/lib/chef/mixin/language.rb +107 -0
  97. data/lib/chef/mixin/language_include_attribute.rb +56 -0
  98. data/lib/chef/mixin/language_include_recipe.rb +53 -0
  99. data/lib/chef/mixin/params_validate.rb +197 -0
  100. data/lib/chef/mixin/recipe_definition_dsl_core.rb +79 -0
  101. data/lib/chef/mixin/template.rb +94 -0
  102. data/lib/chef/nanite.rb +100 -0
  103. data/lib/chef/node.rb +463 -0
  104. data/lib/chef/node/attribute.rb +412 -0
  105. data/lib/chef/openid_registration.rb +181 -0
  106. data/lib/chef/platform.rb +268 -0
  107. data/lib/chef/provider.rb +101 -0
  108. data/lib/chef/provider/breakpoint.rb +36 -0
  109. data/lib/chef/provider/cron.rb +184 -0
  110. data/lib/chef/provider/deploy.rb +314 -0
  111. data/lib/chef/provider/deploy/revision.rb +70 -0
  112. data/lib/chef/provider/deploy/timestamped.rb +33 -0
  113. data/lib/chef/provider/directory.rb +72 -0
  114. data/lib/chef/provider/erl_call.rb +72 -0
  115. data/lib/chef/provider/execute.rb +58 -0
  116. data/lib/chef/provider/file.rb +195 -0
  117. data/lib/chef/provider/git.rb +203 -0
  118. data/lib/chef/provider/group.rb +120 -0
  119. data/lib/chef/provider/group/dscl.rb +128 -0
  120. data/lib/chef/provider/group/gpasswd.rb +50 -0
  121. data/lib/chef/provider/group/groupadd.rb +78 -0
  122. data/lib/chef/provider/group/pw.rb +88 -0
  123. data/lib/chef/provider/group/usermod.rb +57 -0
  124. data/lib/chef/provider/http_request.rb +106 -0
  125. data/lib/chef/provider/ifconfig.rb +131 -0
  126. data/lib/chef/provider/link.rb +157 -0
  127. data/lib/chef/provider/mdadm.rb +88 -0
  128. data/lib/chef/provider/mount.rb +117 -0
  129. data/lib/chef/provider/mount/mount.rb +208 -0
  130. data/lib/chef/provider/package.rb +160 -0
  131. data/lib/chef/provider/package/apt.rb +110 -0
  132. data/lib/chef/provider/package/dpkg.rb +109 -0
  133. data/lib/chef/provider/package/easy_install.rb +106 -0
  134. data/lib/chef/provider/package/freebsd.rb +153 -0
  135. data/lib/chef/provider/package/macports.rb +105 -0
  136. data/lib/chef/provider/package/portage.rb +124 -0
  137. data/lib/chef/provider/package/rpm.rb +99 -0
  138. data/lib/chef/provider/package/rubygems.rb +136 -0
  139. data/lib/chef/provider/package/yum-dump.py +125 -0
  140. data/lib/chef/provider/package/yum.rb +175 -0
  141. data/lib/chef/provider/package/zypper.rb +132 -0
  142. data/lib/chef/provider/remote_directory.rb +126 -0
  143. data/lib/chef/provider/remote_file.rb +141 -0
  144. data/lib/chef/provider/route.rb +118 -0
  145. data/lib/chef/provider/ruby_block.rb +33 -0
  146. data/lib/chef/provider/script.rb +42 -0
  147. data/lib/chef/provider/service.rb +135 -0
  148. data/lib/chef/provider/service/debian.rb +64 -0
  149. data/lib/chef/provider/service/freebsd.rb +156 -0
  150. data/lib/chef/provider/service/gentoo.rb +54 -0
  151. data/lib/chef/provider/service/init.rb +71 -0
  152. data/lib/chef/provider/service/redhat.rb +62 -0
  153. data/lib/chef/provider/service/simple.rb +114 -0
  154. data/lib/chef/provider/subversion.rb +156 -0
  155. data/lib/chef/provider/template.rb +175 -0
  156. data/lib/chef/provider/user.rb +170 -0
  157. data/lib/chef/provider/user/dscl.rb +280 -0
  158. data/lib/chef/provider/user/pw.rb +113 -0
  159. data/lib/chef/provider/user/useradd.rb +108 -0
  160. data/lib/chef/recipe.rb +105 -0
  161. data/lib/chef/resource.rb +380 -0
  162. data/lib/chef/resource/apt_package.rb +34 -0
  163. data/lib/chef/resource/bash.rb +33 -0
  164. data/lib/chef/resource/breakpoint.rb +35 -0
  165. data/lib/chef/resource/cron.rb +179 -0
  166. data/lib/chef/resource/csh.rb +33 -0
  167. data/lib/chef/resource/deploy.rb +359 -0
  168. data/lib/chef/resource/deploy_revision.rb +35 -0
  169. data/lib/chef/resource/directory.rb +76 -0
  170. data/lib/chef/resource/dpkg_package.rb +34 -0
  171. data/lib/chef/resource/easy_install_package.rb +41 -0
  172. data/lib/chef/resource/erl_call.rb +83 -0
  173. data/lib/chef/resource/execute.rb +127 -0
  174. data/lib/chef/resource/file.rb +84 -0
  175. data/lib/chef/resource/gem_package.rb +41 -0
  176. data/lib/chef/resource/git.rb +36 -0
  177. data/lib/chef/resource/group.rb +70 -0
  178. data/lib/chef/resource/http_request.rb +52 -0
  179. data/lib/chef/resource/ifconfig.rb +134 -0
  180. data/lib/chef/resource/link.rb +78 -0
  181. data/lib/chef/resource/macports_package.rb +29 -0
  182. data/lib/chef/resource/mdadm.rb +82 -0
  183. data/lib/chef/resource/mount.rb +135 -0
  184. data/lib/chef/resource/package.rb +80 -0
  185. data/lib/chef/resource/perl.rb +33 -0
  186. data/lib/chef/resource/portage_package.rb +33 -0
  187. data/lib/chef/resource/python.rb +33 -0
  188. data/lib/chef/resource/remote_directory.rb +91 -0
  189. data/lib/chef/resource/remote_file.rb +60 -0
  190. data/lib/chef/resource/route.rb +135 -0
  191. data/lib/chef/resource/ruby.rb +33 -0
  192. data/lib/chef/resource/ruby_block.rb +39 -0
  193. data/lib/chef/resource/scm.rb +137 -0
  194. data/lib/chef/resource/script.rb +51 -0
  195. data/lib/chef/resource/service.rb +134 -0
  196. data/lib/chef/resource/subversion.rb +34 -0
  197. data/lib/chef/resource/template.rb +60 -0
  198. data/lib/chef/resource/timestamped_deploy.rb +31 -0
  199. data/lib/chef/resource/user.rb +101 -0
  200. data/lib/chef/resource_collection.rb +212 -0
  201. data/lib/chef/resource_collection/stepable_iterator.rb +124 -0
  202. data/lib/chef/resource_definition.rb +67 -0
  203. data/lib/chef/rest.rb +298 -0
  204. data/lib/chef/role.rb +301 -0
  205. data/lib/chef/run_list.rb +164 -0
  206. data/lib/chef/runner.rb +130 -0
  207. data/lib/chef/search/query.rb +71 -0
  208. data/lib/chef/shef.rb +220 -0
  209. data/lib/chef/shef/ext.rb +297 -0
  210. data/lib/chef/shef/shef_session.rb +175 -0
  211. data/lib/chef/streaming_cookbook_uploader.rb +185 -0
  212. data/lib/chef/tasks/chef_repo.rake +245 -0
  213. data/lib/chef/util/file_edit.rb +125 -0
  214. data/lib/chef/util/fileedit.rb +121 -0
  215. data/lib/chef/webui_user.rb +231 -0
  216. metadata +398 -0
@@ -0,0 +1,301 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Author:: Nuo Yan (<nuo@opscode.com>)
4
+ # Copyright:: Copyright (c) 2008 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
+ require 'chef/config'
21
+ require 'chef/mixin/params_validate'
22
+ require 'chef/mixin/from_file'
23
+ require 'chef/couchdb'
24
+ require 'chef/run_list'
25
+ require 'extlib'
26
+ require 'json'
27
+
28
+ class Chef
29
+ class Role
30
+
31
+ include Chef::Mixin::FromFile
32
+ include Chef::Mixin::ParamsValidate
33
+
34
+ DESIGN_DOCUMENT = {
35
+ "version" => 6,
36
+ "language" => "javascript",
37
+ "views" => {
38
+ "all" => {
39
+ "map" => <<-EOJS
40
+ function(doc) {
41
+ if (doc.chef_type == "role") {
42
+ emit(doc.name, doc);
43
+ }
44
+ }
45
+ EOJS
46
+ },
47
+ "all_id" => {
48
+ "map" => <<-EOJS
49
+ function(doc) {
50
+ if (doc.chef_type == "role") {
51
+ emit(doc.name, doc.name);
52
+ }
53
+ }
54
+ EOJS
55
+ }
56
+ }
57
+ }
58
+
59
+ attr_accessor :couchdb_rev, :couchdb_id
60
+
61
+ # Create a new Chef::Role object.
62
+ def initialize
63
+ @name = ''
64
+ @description = ''
65
+ @default_attributes = Mash.new
66
+ @override_attributes = Mash.new
67
+ @run_list = Chef::RunList.new
68
+ @couchdb_rev = nil
69
+ @couchdb_id = nil
70
+ @couchdb = Chef::CouchDB.new
71
+ end
72
+
73
+ def name(arg=nil)
74
+ set_or_return(
75
+ :name,
76
+ arg,
77
+ :regex => /^[\-[:alnum:]_]+$/
78
+ )
79
+ end
80
+
81
+ def description(arg=nil)
82
+ set_or_return(
83
+ :description,
84
+ arg,
85
+ :kind_of => String
86
+ )
87
+ end
88
+
89
+ def run_list(*args)
90
+ if args.length > 0
91
+ @run_list.reset(args)
92
+ else
93
+ @run_list
94
+ end
95
+ end
96
+
97
+ def recipes(*args)
98
+ if args.length > 0
99
+ @run_list.reset(args)
100
+ else
101
+ @run_list.recipes
102
+ end
103
+ end
104
+
105
+ def default_attributes(arg=nil)
106
+ set_or_return(
107
+ :default_attributes,
108
+ arg,
109
+ :kind_of => Hash
110
+ )
111
+ end
112
+
113
+ def override_attributes(arg=nil)
114
+ set_or_return(
115
+ :override_attributes,
116
+ arg,
117
+ :kind_of => Hash
118
+ )
119
+ end
120
+
121
+ def to_hash
122
+ result = {
123
+ "name" => @name,
124
+ "description" => @description,
125
+ 'json_class' => self.class.name,
126
+ "default_attributes" => @default_attributes,
127
+ "override_attributes" => @override_attributes,
128
+ "chef_type" => "role",
129
+ "run_list" => @run_list.run_list
130
+ }
131
+ result["_rev"] = @couchdb_rev if @couchdb_rev
132
+ result
133
+ end
134
+
135
+ # Serialize this object as a hash
136
+ def to_json(*a)
137
+ to_hash.to_json(*a)
138
+ end
139
+
140
+ # Create a Chef::Role from JSON
141
+ def self.json_create(o)
142
+ role = new
143
+ role.name(o["name"])
144
+ role.description(o["description"])
145
+ role.default_attributes(o["default_attributes"])
146
+ role.override_attributes(o["override_attributes"])
147
+ if o.has_key?("run_list")
148
+ role.run_list(o["run_list"]) if o.has_key?("run_list")
149
+ else
150
+ role.run_list(o["recipes"])
151
+ end
152
+ role.couchdb_rev = o["_rev"] if o.has_key?("_rev")
153
+ role.couchdb_id = o["_id"] if o.has_key?("_id")
154
+ role
155
+ end
156
+
157
+ # List all the Chef::Role objects in the CouchDB. If inflate is set to true, you will get
158
+ # the full list of all Roles, fully inflated.
159
+ def self.cdb_list(inflate=false)
160
+ couchdb = Chef::CouchDB.new
161
+ rs = couchdb.list("roles", inflate)
162
+ if inflate
163
+ rs["rows"].collect { |r| r["value"] }
164
+ else
165
+ rs["rows"].collect { |r| r["key"] }
166
+ end
167
+ end
168
+
169
+ # Get the list of all roles from the API.
170
+ def self.list(inflate=false)
171
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
172
+ if inflate
173
+ response = Hash.new
174
+ Chef::Search::Query.new.search(:role) do |n|
175
+ response[n.name] = n unless n.nil?
176
+ end
177
+ response
178
+ else
179
+ r.get_rest("roles")
180
+ end
181
+ end
182
+
183
+ # Load a role by name from CouchDB
184
+ def self.cdb_load(name)
185
+ couchdb = Chef::CouchDB.new
186
+ couchdb.load("role", name)
187
+ end
188
+
189
+ # Load a role by name from the API
190
+ def self.load(name)
191
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
192
+ r.get_rest("roles/#{name}")
193
+ end
194
+
195
+ # Remove this role from the CouchDB
196
+ def cdb_destroy
197
+ @couchdb.delete("role", @name, @couchdb_rev)
198
+
199
+ if Chef::Config[:couchdb_version] == 0.9
200
+ rs = @couchdb.get_view("nodes", "by_run_list", :startkey => "role[#{@name}]", :endkey => "role[#{@name}]", :include_docs => true)
201
+ rs["rows"].each do |row|
202
+ node = row["doc"]
203
+ node.run_list.remove("role[#{@name}]")
204
+ node.cdb_save
205
+ end
206
+ else
207
+ Chef::Node.cdb_list.each do |node|
208
+ n = Chef::Node.cdb_load(node)
209
+ n.run_list.remove("role[#{@name}]")
210
+ n.cdb_save
211
+ end
212
+ end
213
+ end
214
+
215
+ # Remove this role via the REST API
216
+ def destroy
217
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
218
+ r.delete_rest("roles/#{@name}")
219
+
220
+ Chef::Node.list.each do |node|
221
+ n = Chef::Node.load(node[0])
222
+ n.run_list.remove("role[#{@name}]")
223
+ n.save
224
+ end
225
+
226
+ end
227
+
228
+ # Save this role to the CouchDB
229
+ def cdb_save
230
+ results = @couchdb.store("role", @name, self)
231
+ @couchdb_rev = results["rev"]
232
+ end
233
+
234
+ # Save this role via the REST API
235
+ def save
236
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
237
+ begin
238
+ r.put_rest("roles/#{@name}", self)
239
+ rescue Net::HTTPServerException => e
240
+ if e.response.code == "404"
241
+ r.post_rest("roles", self)
242
+ else
243
+ raise e
244
+ end
245
+ end
246
+ self
247
+ end
248
+
249
+ # Create the role via the REST API
250
+ def create
251
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
252
+ r.post_rest("roles", self)
253
+ self
254
+ end
255
+
256
+ # Set up our CouchDB design document
257
+ def self.create_design_document
258
+ couchdb = Chef::CouchDB.new
259
+ couchdb.create_design_document("roles", DESIGN_DOCUMENT)
260
+ end
261
+
262
+ # As a string
263
+ def to_s
264
+ "role[#{@name}]"
265
+ end
266
+
267
+ # Load a role from disk - prefers to load the JSON, but will happily load
268
+ # the raw rb files as well.
269
+ def self.from_disk(name, force=nil)
270
+ js_file = File.join(Chef::Config[:role_path], "#{name}.json")
271
+ rb_file = File.join(Chef::Config[:role_path], "#{name}.rb")
272
+
273
+ if File.exists?(js_file) || force == "json"
274
+ JSON.parse(IO.read(js_file))
275
+ elsif File.exists?(rb_file) || force == "ruby"
276
+ role = Chef::Role.new
277
+ role.name(name)
278
+ role.from_file(rb_file)
279
+ role
280
+ end
281
+ end
282
+
283
+ # Sync all the json roles with couchdb from disk
284
+ def self.sync_from_disk_to_couchdb
285
+ Dir[File.join(Chef::Config[:role_path], "*.json")].each do |role_file|
286
+ short_name = File.basename(role_file, ".json")
287
+ Chef::Log.warn("Loading #{short_name}")
288
+ r = Chef::Role.from_disk(short_name, "json")
289
+ begin
290
+ couch_role = Chef::Role.cdb_load(short_name)
291
+ r.couchdb_rev = couch_role.couchdb_rev
292
+ Chef::Log.debug("Replacing role #{short_name} with data from #{role_file}")
293
+ rescue Chef::Exceptions::CouchDBNotFound
294
+ Chef::Log.debug("Creating role #{short_name} with data from #{role_file}")
295
+ end
296
+ r.cdb_save
297
+ end
298
+ end
299
+
300
+ end
301
+ end
@@ -0,0 +1,164 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Copyright:: Copyright (c) 2008, 2009 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/mixin/deep_merge'
19
+
20
+ class Chef
21
+ class RunList
22
+ include Enumerable
23
+
24
+ attr_reader :recipes, :roles, :run_list
25
+
26
+ def initialize
27
+ @run_list = Array.new
28
+ @recipes = Array.new
29
+ @roles = Array.new
30
+ @seen_roles = Array.new
31
+ end
32
+
33
+ def <<(item)
34
+ type, entry, fentry = parse_entry(item)
35
+ case type
36
+ when 'recipe'
37
+ @recipes << entry unless @recipes.include?(entry)
38
+ when 'role'
39
+ @roles << entry unless @roles.include?(entry)
40
+ end
41
+ @run_list << fentry unless @run_list.include?(fentry)
42
+ self
43
+ end
44
+
45
+ def ==(*isequal)
46
+ check_array = nil
47
+ if isequal[0].kind_of?(Chef::RunList)
48
+ check_array = isequal[0].run_list
49
+ else
50
+ check_array = isequal.flatten
51
+ end
52
+
53
+ return false if check_array.length != @run_list.length
54
+
55
+ check_array.each_index do |i|
56
+ to_check = check_array[i]
57
+ type, name, fname = parse_entry(to_check)
58
+ return false if @run_list[i] != fname
59
+ end
60
+
61
+ true
62
+ end
63
+
64
+ def to_s
65
+ @run_list.join(", ")
66
+ end
67
+
68
+ def empty?
69
+ @run_list.length == 0 ? true : false
70
+ end
71
+
72
+ def [](pos)
73
+ @run_list[pos]
74
+ end
75
+
76
+ def []=(pos, item)
77
+ type, entry, fentry = parse_entry(item)
78
+ @run_list[pos] = fentry
79
+ end
80
+
81
+ def each(&block)
82
+ @run_list.each { |i| block.call(i) }
83
+ end
84
+
85
+ def each_index(&block)
86
+ @run_list.each_index { |i| block.call(i) }
87
+ end
88
+
89
+ def include?(item)
90
+ type, entry, fentry = parse_entry(item)
91
+ @run_list.include?(fentry)
92
+ end
93
+
94
+ def reset(*args)
95
+ @run_list = Array.new
96
+ @recipes = Array.new
97
+ @roles = Array.new
98
+ args.flatten.each do |item|
99
+ if item.kind_of?(Chef::RunList)
100
+ item.each { |r| self << r }
101
+ else
102
+ self << item
103
+ end
104
+ end
105
+ self
106
+ end
107
+
108
+ def remove(item)
109
+ type, entry, fentry = parse_entry(item)
110
+ @run_list.delete_if { |i| i == fentry }
111
+ if type == "recipe"
112
+ @recipes.delete_if { |i| i == entry }
113
+ elsif type == "role"
114
+ @roles.delete_if { |i| i == entry }
115
+ end
116
+ self
117
+ end
118
+
119
+ def expand(from='server')
120
+ recipes = Array.new
121
+ default_attrs = Mash.new
122
+ override_attrs = Mash.new
123
+
124
+ @run_list.each do |entry|
125
+ type, name, fname = parse_entry(entry)
126
+ case type
127
+ when 'recipe'
128
+ recipes << name unless recipes.include?(name)
129
+ when 'role'
130
+ role = nil
131
+ next if @seen_roles.include?(name)
132
+ if from == 'disk' || Chef::Config[:solo]
133
+ # Load the role from disk
134
+ role = Chef::Role.from_disk("#{name}")
135
+ elsif from == 'server'
136
+ # Load the role from the server
137
+ r = Chef::REST.new(Chef::Config[:role_url])
138
+ role = r.get_rest("roles/#{name}")
139
+ elsif from == 'couchdb'
140
+ # Load the role from couchdb
141
+ role = Chef::Role.cdb_load(name)
142
+ end
143
+ @seen_roles << name
144
+ rec, d, o = role.run_list.expand(from)
145
+ rec.each { |r| recipes << r unless recipes.include?(r) }
146
+ default_attrs = Chef::Mixin::DeepMerge.merge(default_attrs, Chef::Mixin::DeepMerge.merge(role.default_attributes,d))
147
+ override_attrs = Chef::Mixin::DeepMerge.merge(override_attrs, Chef::Mixin::DeepMerge.merge(role.override_attributes, o))
148
+ end
149
+ end
150
+ return recipes, default_attrs, override_attrs
151
+ end
152
+
153
+ def parse_entry(entry)
154
+ case entry
155
+ when /^(.+)\[(.+)\]$/
156
+ [ $1, $2, entry ]
157
+ else
158
+ [ 'recipe', entry, "recipe[#{entry}]" ]
159
+ end
160
+ end
161
+
162
+ end
163
+ end
164
+