2626class Chef
2727 class Cookbook
2828 include Chef ::Mixin ::ConvertToClassName
29+ include Chef ::Mixin ::Checksum
30+ include Chef ::IndexQueue ::Indexable
2931
30- attr_accessor :definition_files , :template_files , :remote_files ,
31- :lib_files , :resource_files , :provider_files , :name
32- attr_reader :recipe_files , :attribute_files
32+ attr_accessor :definition_files , :template_files , :remote_files ,
33+ :lib_files , :resource_files , :provider_files , :name , :manifest ,
34+ :metadata , :metadata_files , :status , :couchdb_rev , :couchdb , :version
35+ attr_reader :recipe_files , :attribute_files , :couchdb_id
36+
37+ DESIGN_DOCUMENT = {
38+ "version" => 1 ,
39+ "language" => "javascript" ,
40+ "views" => {
41+ "all" => {
42+ "map" => <<-EOJS
43+ function(doc) {
44+ if (doc.chef_type == "cookbook") {
45+ emit(doc.name, doc);
46+ }
47+ }
48+ EOJS
49+ } ,
50+ "all_id" => {
51+ "map" => <<-EOJS
52+ function(doc) {
53+ if (doc.chef_type == "cookbook") {
54+ emit(doc.name, doc.name);
55+ }
56+ }
57+ EOJS
58+ }
59+ }
60+ }
3361
3462 # Creates a new Chef::Cookbook object.
3563 #
3664 # === Returns
3765 # object<Chef::Cookbook>:: Duh. :)
38- def initialize ( name )
66+ def initialize ( name , couchdb = nil )
3967 @name = name
4068 @attribute_files = Array . new
4169 @attribute_names = Hash . new
@@ -47,6 +75,18 @@ def initialize(name)
4775 @lib_files = Array . new
4876 @resource_files = Array . new
4977 @provider_files = Array . new
78+ @metadata_files = Array . new
79+ @couchdb_id = nil
80+ @couchdb = couchdb || Chef ::CouchDB . new
81+ @couchdb_rev = nil
82+ @status = :ready
83+ @manifest = nil
84+ @version = nil
85+ @metadata = { }
86+ end
87+
88+ def full_name
89+ "#{ name } -#{ version } "
5090 end
5191
5292 # Loads all the library files in this cookbook via require.
@@ -172,6 +212,159 @@ def load_recipe(name, node, collection=nil, definitions=nil, cookbook_loader=nil
172212 recipe
173213 end
174214
215+ def segment_files ( segment )
216+ files_list = nil
217+ case segment
218+ when :attributes
219+ files_list = attribute_files
220+ when :recipes
221+ files_list = recipe_files
222+ when :definitions
223+ files_list = definition_files
224+ when :libraries
225+ files_list = lib_files
226+ when :providers
227+ files_list = provider_files
228+ when :resources
229+ files_list = resource_files
230+ when :files
231+ files_list = remote_files
232+ when :templates
233+ files_list = template_files
234+ else
235+ raise ArgumentError , "segment must be one of :attributes, :recipes, :definitions, :remote_files, :template_files, :resources, :providers or :libraries"
236+ end
237+ files_list
238+ end
239+
240+ def to_json ( *a )
241+ result = self . manifest ? self . manifest : self . generate_manifest
242+ result [ 'json_class' ] = self . class . name
243+ result [ 'chef_type' ] = 'cookbook'
244+ result [ "_rev" ] = @couchdb_rev if @couchdb_rev
245+ result . to_json ( *a )
246+ end
247+
248+ def self . json_create ( o )
249+ cookbook = new ( o [ "cookbook_name" ] )
250+ if o . has_key? ( '_rev' )
251+ cookbook . couchdb_rev = o [ "_rev" ] if o . has_key? ( "_rev" )
252+ o . delete ( "_rev" )
253+ end
254+ if o . has_key? ( "_id" )
255+ cookbook . couchdb_id = o [ "_id" ] if o . has_key? ( "_id" )
256+ cookbook . index_id = cookbook . couchdb_id
257+ o . delete ( "_id" )
258+ end
259+ cookbook . manifest = o
260+ cookbook . metadata = o [ "metadata" ]
261+ cookbook . version = o [ "version" ]
262+ cookbook
263+ end
264+
265+ def generate_manifest ( &url_generation )
266+ response = {
267+ :recipes => Array . new ,
268+ :definitions => Array . new ,
269+ :libraries => Array . new ,
270+ :attributes => Array . new ,
271+ :files => Array . new ,
272+ :templates => Array . new ,
273+ :resources => Array . new ,
274+ :providers => Array . new
275+ }
276+ [ :resources , :providers , :recipes , :definitions , :libraries , :attributes , :files , :templates ] . each do |segment |
277+ segment_files ( segment ) . each do |sf |
278+ next if File . directory? ( sf )
279+
280+ file_name = nil
281+ file_url = nil
282+ file_specificity = nil
283+ url_options = nil
284+
285+ if segment == :templates || segment == :files
286+ mo = sf . match ( "cookbooks/#{ name } /#{ segment } /(.+?)/(.+)" )
287+ unless mo
288+ Chef ::Log . debug ( "Skipping file #{ sf } , as it doesn't have a proper segment." )
289+ next
290+ end
291+ specificity = mo [ 1 ]
292+ file_name = mo [ 2 ]
293+ url_options = { :cookbook_id => name . to_s , :segment => segment , :id => file_name }
294+
295+ case specificity
296+ when "default"
297+ when /^host-(.+)$/
298+ url_options [ :fqdn ] = $1
299+ when /^(.+)-(.+)$/
300+ url_options [ :platform ] = $1
301+ url_options [ :version ] = $2
302+ when /^(.+)$/
303+ url_options [ :platform ] = $1
304+ end
305+
306+ file_specificity = specificity
307+ else
308+ mo = sf . match ( "cookbooks/#{ name } /#{ segment } /(.+)" )
309+ file_name = mo [ 1 ]
310+ url_options = { :cookbook_id => name . to_s , :segment => segment , :id => file_name }
311+ end
312+
313+ if url_generation
314+ file_url = url_generation . call ( url_options )
315+ else
316+ file_url = nil
317+ end
318+
319+ rs = {
320+ :name => file_name ,
321+ :uri => file_url ,
322+ :path => sf . match ( "cookbooks/#{ name } /(#{ segment } /.+)" ) [ 1 ] ,
323+ :checksum => checksum ( sf )
324+ }
325+ rs [ :specificity ] = file_specificity if file_specificity
326+ response [ segment ] << rs
327+ end
328+ end
329+ response [ :cookbook_name ] = name . to_s
330+ response [ :metadata ] = metadata
331+ response [ :version ] = metadata . version
332+ @version = metadata . version
333+ response [ :name ] = full_name
334+ @manifest = response
335+ end
336+
337+ ##
338+ # Couchdb
339+ ##
340+
341+ def self . create_design_document ( couchdb = nil )
342+ ( couchdb || Chef ::CouchDB . new ) . create_design_document ( "cookbooks" , DESIGN_DOCUMENT )
343+ end
344+
345+ def self . cdb_list ( inflate = false , couchdb = nil )
346+ rs = ( couchdb || Chef ::CouchDB . new ) . list ( "cookbooks" , inflate )
347+ lookup = ( inflate ? "value" : "key" )
348+ rs [ "rows" ] . collect { |r | r [ lookup ] }
349+ end
350+
351+ def self . cdb_load ( name , couchdb = nil )
352+ ( couchdb || Chef ::CouchDB . new ) . load ( "cookbook" , full_name )
353+ end
354+
355+ def cdb_destroy
356+ ( couchdb || Chef ::CouchDB . new ) . delete ( "cookbook" , full_name , @couchdb_rev )
357+ end
358+
359+ def cdb_save
360+ @couchdb_rev = @couchdb . store ( "cookbook" , full_name , self ) [ "rev" ]
361+ end
362+
363+ def couchdb_id = ( value )
364+ @couchdb_id = value
365+ self . index_id = value
366+ end
367+
175368 private
176369
177370 def shorten_name ( name )
0 commit comments