@@ -35,7 +35,7 @@ class Cookbook
3535 attr_reader :recipe_files , :attribute_files , :couchdb_id
3636
3737 DESIGN_DOCUMENT = {
38- "version" => 1 ,
38+ "version" => 5 ,
3939 "language" => "javascript" ,
4040 "views" => {
4141 "all" => {
@@ -56,11 +56,20 @@ class Cookbook
5656 }
5757 EOJS
5858 } ,
59+ "all_with_version" => {
60+ "map" => <<-EOJS
61+ function(doc) {
62+ if (doc.chef_type == "cookbook") {
63+ emit(doc.cookbook_name, doc.version);
64+ }
65+ }
66+ EOJS
67+ } ,
5968 "all_latest_version" => {
6069 "map" => %q@
6170 function(doc) {
6271 if (doc.chef_type == "cookbook") {
63- emit(doc.cookbook_name, [ doc.cookbook_name, doc. version] );
72+ emit(doc.cookbook_name, doc.version);
6473 }
6574 }
6675 @ ,
@@ -128,11 +137,12 @@ def initialize(name, couchdb=nil)
128137 end
129138
130139 def version
131- @metadata [ ' version' ]
140+ @metadata . version
132141 end
133142
134143 def version = ( new_version )
135- @metadata [ 'version' ] = new_version
144+ @manifest [ "version" ] = new_version
145+ @metadata . version ( new_version )
136146 end
137147
138148 def full_name
@@ -309,7 +319,6 @@ def self.json_create(o)
309319 cookbook . manifest = o
310320 # We want the Chef::Cookbook::Metadata object to always be inflated
311321 cookbook . metadata = Chef ::Cookbook ::Metadata . from_hash ( o [ "metadata" ] )
312- cookbook . version = o [ "version" ]
313322 cookbook
314323 end
315324
@@ -319,7 +328,7 @@ def display_manifest(&url_generation)
319328 if manifest . has_key? ( segment )
320329 manifest [ segment ] . each do |segment_item |
321330 puts segment_item . inspect
322- url_options = { :cookbook_id => name . to_s , :segment => segment , :id => segment_item [ "name" ] }
331+ url_options = { :cookbook_id => name . to_s , :segment => segment , :id => segment_item [ "name" ] , :cookbook_version => version }
323332 set_specificity_arguments ( segment_item [ "specificity" ] , url_options )
324333 segment_item [ "uri" ] = url_generation . call ( url_options )
325334 end
@@ -371,7 +380,7 @@ def generate_manifest(&url_generation)
371380 end
372381 specificity = mo [ 1 ]
373382 file_name = mo [ 2 ]
374- url_options = { :cookbook_id => name . to_s , :segment => segment , :id => file_name }
383+ url_options = { :cookbook_id => name . to_s , :segment => segment , :id => file_name , :cookbook_version => version }
375384 set_specificity_arguments ( specificity , url_options )
376385 file_specificity = specificity
377386 else
@@ -400,7 +409,7 @@ def generate_manifest(&url_generation)
400409 end
401410 response [ :cookbook_name ] = name . to_s
402411 response [ :metadata ] = metadata
403- response [ :version ] = metadata [ ' version' ]
412+ response [ :version ] = metadata . version
404413 response [ :name ] = full_name
405414 @manifest = response
406415 end
@@ -416,15 +425,32 @@ def self.chef_server_rest
416425 Chef ::REST . new ( Chef ::Config [ :chef_server_url ] )
417426 end
418427
419- # Save this cookbook via the REST API
420428 def save
421429 chef_server_rest . put_rest ( "cookbooks/#{ @name } /#{ version } " , self )
422430 self
423431 end
432+ alias :create :save
433+
434+ def destroy
435+ chef_server_rest . delete_rest ( "cookbooks/#{ @name } /#{ version } " )
436+ self
437+ end
438+
439+ def self . load ( name , version = "_latest" )
440+ version = "_latest" if version == "latest"
441+ Chef ::REST . new ( Chef ::Config [ :chef_server_url ] ) . get_rest ( "cookbooks/#{ name } /#{ version } " )
442+ end
424443
425444 ##
426445 # Couchdb
427446 ##
447+
448+ def self . cdb_by_version ( cookbook_name = nil , couchdb = nil )
449+ cdb = couchdb || Chef ::CouchDB . new
450+ options = cookbook_name ? { :startkey => cookbook_name , :endkey => cookbook_name } : { }
451+ rs = cdb . get_view ( "cookbooks" , "all_with_version" , options )
452+ rs [ "rows" ] . inject ( { } ) { |memo , row | memo . has_key? ( row [ "key" ] ) ? memo [ row [ "key" ] ] << row [ "value" ] : memo [ row [ "key" ] ] = [ row [ "value" ] ] ; memo }
453+ end
428454
429455 def self . create_design_document ( couchdb = nil )
430456 ( couchdb || Chef ::CouchDB . new ) . create_design_document ( "cookbooks" , DESIGN_DOCUMENT )
@@ -437,8 +463,13 @@ def self.cdb_list(inflate=false, couchdb=nil)
437463 end
438464
439465 def self . cdb_load ( name , version = 'latest' , couchdb = nil )
440- # Probably want to look for a view here at some point
441- ( couchdb || Chef ::CouchDB . new ) . load ( "cookbook" , "#{ name } -#{ version } " )
466+ cdb = couchdb || Chef ::CouchDB . new
467+ if version == "latest" || version == "_latest"
468+ rs = cdb . get_view ( "cookbooks" , "all_latest_version" , :key => name , :descending => true , :group => true , :reduce => true ) [ "rows" ] . first
469+ cdb . load ( "cookbook" , "#{ rs [ "key" ] } -#{ rs [ "value" ] } " )
470+ else
471+ cdb . load ( "cookbook" , "#{ name } -#{ version } " )
472+ end
442473 end
443474
444475 def cdb_destroy
0 commit comments