Skip to content

Commit 02cd1c5

Browse files
adamhjkdanielsdeleo
authored andcommitted
REST methods added, knife show/delete complete
1 parent 5e7f24c commit 02cd1c5

3 files changed

Lines changed: 57 additions & 59 deletions

File tree

chef-server-api/app/controllers/cookbooks.rb

Lines changed: 10 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,13 @@ class Cookbooks < Application
3131
include Merb::TarballHelper
3232

3333
def index
34-
cl = Chef::CookbookLoader.new
35-
cookbook_list = Hash.new
36-
cl.each do |cookbook|
37-
cookbook_list[cookbook.name] = absolute_url(:cookbook, :id => cookbook.name.to_s)
34+
cookbook_list = Chef::Cookbook.cdb_list
35+
response = Hash.new
36+
cookbook_list.each do |cookbook_name|
37+
cookbook_name =~ /^(.+)-(\d+\.\d+\.\d+)$/
38+
response[$1] = absolute_slice_url(:cookbook, :id => $1)
3839
end
39-
display cookbook_list
40+
display response
4041
end
4142

4243
def show
@@ -51,14 +52,13 @@ def show
5152

5253
def show_versions
5354
begin
54-
cookbook = Chef::Cookbook.cdb_load(params[:id], params[:version])
55+
cookbook_versions = Chef::Cookbook.cdb_by_version(params[:id])
5556
rescue ArgumentError => e
56-
raise NotFound, "Cannot find a cookbook named #{params[:id]} with version #{params[:version]}"
57+
raise NotFound, "Cannot find a cookbook named #{params[:id]}"
5758
rescue Chef::Exceptions::CouchDBNotFound => e
58-
raise NotFound, "Cannot find a cookbook named #{params[:id]} with version #{params[:version]}"
59+
raise NotFound, "Cannot find a cookbook named #{params[:id]}"
5960
end
60-
cookbook.generate_manifest { |opts| absolute_slice_url(:cookbook_segment, opts) }
61-
display cookbook
61+
display cookbook_versions
6262
end
6363

6464
def show_segment
@@ -157,40 +157,6 @@ def serve_segment_file(cookbook, segment, files)
157157
end
158158
end
159159

160-
def create
161-
# validate name and file parameters and throw an error if a cookbook with the same name already exists
162-
raise BadRequest, "missing required parameter: name" unless params[:name]
163-
desired_name = params[:name]
164-
raise BadRequest, "invalid parameter: name must be at least one character long and contain only letters, numbers, periods (.), underscores (_), and hyphens (-)" unless desired_name =~ /\A[\w.-]+\Z/
165-
begin
166-
validate_file_parameter(desired_name, params[:file])
167-
rescue FileParameterException => te
168-
raise BadRequest, te.message
169-
end
170-
171-
begin
172-
Chef::CookbookLoader.new[desired_name]
173-
raise BadRequest, "Cookbook with the name #{desired_name} already exists"
174-
rescue ArgumentError
175-
end
176-
177-
expand_tarball_and_put_in_repository(desired_name, params[:file][:tempfile])
178-
179-
# construct successful response
180-
self.status = 201
181-
location = absolute_url(:cookbook, :id => desired_name)
182-
headers['Location'] = location
183-
result = { 'uri' => location }
184-
display result
185-
end
186-
187-
def get_tarball
188-
cookbook_name = params[:cookbook_id]
189-
expected_location = cookbook_location(cookbook_name)
190-
raise NotFound, "Cannot find cookbook named #{cookbook_name} at #{expected_location}. Note: Tarball generation only applies to cookbooks under the first directory in the server's Chef::Config.cookbook_path variable and does to apply overrides." unless File.directory? expected_location
191-
send_file(get_or_create_cookbook_tarball_location(cookbook_name))
192-
end
193-
194160
def update
195161
cookbook_name = params[:id]
196162
cookbook_version = params[:version]

chef/lib/chef/cookbook.rb

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

chef/lib/chef/knife/cookbook_show.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,16 @@ class CookbookShow < Knife
4444
def run
4545
case @name_args.length
4646
when 4 # We are showing a specific file
47-
arguments = { :id => @name_args[2] }
47+
arguments = { :id => @name_args[3] }
4848
arguments[:fqdn] = config[:fqdn] if config.has_key?(:fqdn)
4949
arguments[:platform] = config[:platform] if config.has_key?(:platform)
5050
arguments[:version] = config[:platform_version] if config.has_key?(:platform_version)
51-
result = rest.get_rest("cookbooks/#{@name_args[0]}/#{@name_args[1]}?#{make_query_params(arguments)}")
51+
result = rest.get_rest("cookbooks/#{@name_args[0]}/#{@name_args[1]}/#{@name_args[2]}?#{make_query_params(arguments)}")
5252
pretty_print(result)
5353
when 3 # We are showing a specific part of the cookbook
54-
result = rest.get_rest("cookbooks/#{@name_args[0]}")
55-
output(result[@name_args[1]])
54+
cookbook_version = @name_args[1] == 'latest' ? '_latest' : @name_args[1]
55+
result = rest.get_rest("cookbooks/#{@name_args[0]}/#{cookbook_version}")
56+
output(result.manifest[@name_args[2]])
5657
when 2 # We are showing the whole cookbook data
5758
cookbook_version = @name_args[1] == 'latest' ? '_latest' : @name_args[1]
5859
output(rest.get_rest("cookbooks/#{@name_args[0]}/#{cookbook_version}"))

0 commit comments

Comments
 (0)