chef-server-api 0.9.0.a4 → 0.9.0.a6

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.
@@ -19,8 +19,8 @@
19
19
  # limitations under the License.
20
20
  #
21
21
 
22
- require 'chef' / 'cookbook_loader'
23
- require 'chef' / 'cookbook' / 'metadata'
22
+ require 'chef/cookbook_loader'
23
+ require 'chef/cookbook/metadata'
24
24
 
25
25
  class Cookbooks < Application
26
26
 
@@ -40,13 +40,33 @@ class Cookbooks < Application
40
40
  include Merb::TarballHelper
41
41
 
42
42
  def index
43
- cookbook_list = Chef::CookbookVersion.cdb_list
43
+ cookbook_list = Chef::CookbookVersion.cdb_list_latest.keys.sort
44
44
  response = Hash.new
45
- cookbook_list.each do |cookbook_name|
46
- cookbook_name =~ /^(.+)-(\d+\.\d+\.\d+)$/
47
- response[$1] = absolute_url(:cookbook, :cookbook_name => $1)
45
+ cookbook_list.map! do |cookbook_name|
46
+ response[cookbook_name] = absolute_url(:cookbook, :cookbook_name => cookbook_name)
48
47
  end
49
- display response
48
+ display response
49
+ end
50
+
51
+ #FIXME: this is different from the rest of our API, but in a useful way...
52
+ def index_latest
53
+ cookbook_list = Chef::CookbookVersion.cdb_list_latest(true)
54
+ response = Hash.new
55
+ cookbook_list.map! do |cookbook_name, cookbook_version|
56
+ response[cookbook_name]={ :url=>absolute_url(:cookbook, :cookbook_name => cookbook_name, :cookbook_version => cookbook_version),
57
+ :cookbook_name => cookbook_name, :cookbook_version=>cookbook_version}
58
+ end
59
+ display response
60
+ end
61
+
62
+ def index_recipes #FIXME: is this cool to do w/ access control on platform?
63
+ all_cookbooks = Array(Chef::CookbookVersion.cdb_list_latest(true))
64
+ all_cookbooks.map! do |cookbook|
65
+ cookbook.manifest["recipes"].map { |r| "#{cookbook.name}::#{r['name']}" }
66
+ end
67
+ all_cookbooks.flatten!
68
+ all_cookbooks.sort!
69
+ display all_cookbooks
50
70
  end
51
71
 
52
72
  def show_versions
@@ -88,27 +88,14 @@ class Sandboxes < Application
88
88
  end
89
89
 
90
90
  def upload_checksum
91
- sandbox_guid = params[:sandbox_id]
92
- checksum = params[:checksum]
91
+ sandbox_file = ChefServerApi::SandboxFile.new(self.request.env["rack.input"], params)
92
+ raise BadRequest, sandbox_file.error if sandbox_file.invalid_params?
93
+ raise NotFound, sandbox_file.error if sandbox_file.invalid_sandbox?
94
+ raise BadRequest, sandbox_file.error if sandbox_file.invalid_file?
93
95
 
94
- existing_sandbox = Chef::Sandbox.cdb_load(sandbox_guid)
95
- raise NotFound, "cannot find sandbox with guid #{sandbox_guid}" unless existing_sandbox
96
- raise NotFound, "checksum #{checksum} isn't a part of sandbox #{sandbox_guid}" unless existing_sandbox.checksums.member?(checksum)
97
-
98
- Tempfile.open("sandbox") do |src|
99
- src.write(self.request.env["rack.input"].string)
100
- src.close
101
-
102
- observed_checksum = Chef::Cache::Checksum.generate_md5_checksum_for_file(src.path)
103
-
104
- raise BadRequest, "Checksum did not match: expected #{checksum}, observed #{observed_checksum}" unless observed_checksum == checksum
105
-
106
- dest = sandbox_checksum_location(sandbox_guid, checksum)
107
- Chef::Log.info("upload_checksum: move #{src} to #{dest}")
108
- FileUtils.mv(src.path, dest)
109
- end
96
+ sandbox_file.commit_to(sandbox_checksum_location(sandbox_file.sandbox_id, sandbox_file.expected_checksum))
110
97
 
111
- url = absolute_url(:sandbox_checksum, :sandbox_id => sandbox_guid, :checksum => checksum)
98
+ url = absolute_url(:sandbox_checksum, sandbox_file.resource_params)
112
99
  result = { 'uri' => url }
113
100
  display result
114
101
  end
@@ -0,0 +1,117 @@
1
+ #
2
+ # Author:: Daniel DeLeo (<dan@opscode.com>)
3
+ # Copyright:: Copyright (c) 2010 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/sandbox'
20
+ require 'chef/exceptions'
21
+ require 'chef/cache/checksum'
22
+
23
+ module ChefServerApi
24
+ class SandboxFile
25
+ attr_reader :sandbox_id
26
+ attr_reader :expected_checksum
27
+ attr_reader :error
28
+
29
+ def initialize(input, params={})
30
+ @input = input
31
+ @sandbox_id = params[:sandbox_id]
32
+ @expected_checksum = params[:checksum]
33
+ @sandbox_loaded = false
34
+ @error = nil
35
+ end
36
+
37
+ def resource_params
38
+ {:sandbox_id => sandbox_id, :checksum => expected_checksum}
39
+ end
40
+
41
+ def sandbox
42
+ unless @sandbox_loaded
43
+ load_sandbox
44
+ @sandbox_loaded = true
45
+ end
46
+ @sandbox
47
+ end
48
+
49
+ def commit_to(destination_file_path)
50
+ if @input.respond_to?(:path) && @input.path
51
+ commit_tempfile_to(destination_file_path)
52
+ else
53
+ commit_stringio_to(destination_file_path)
54
+ end
55
+ end
56
+
57
+ def actual_checksum
58
+ @actual_checksum ||= begin
59
+ @input.rewind
60
+ Chef::Cache::Checksum.instance.generate_md5_checksum(@input)
61
+ end
62
+ end
63
+
64
+ def invalid_file?
65
+ if expected_checksum != actual_checksum
66
+ @error = "Uploaded file is invalid: expected a md5 sum '#{expected_checksum}', but it was '#{actual_checksum}'"
67
+ else
68
+ false
69
+ end
70
+ end
71
+
72
+ def invalid_params?
73
+ if @sandbox_id.nil?
74
+ @error = "Cannot upload file with checksum '#{expected_checksum}': you must provide a sandbox_id"
75
+ elsif @expected_checksum.nil?
76
+ @error = "Cannot upload file to sandbox '#{sandbox_id}': you must provide the file's checksum"
77
+ else
78
+ false
79
+ end
80
+ end
81
+
82
+ def invalid_sandbox?
83
+ if sandbox.nil?
84
+ @error = "Cannot find sandbox with id '#{sandbox_id}' in the database"
85
+ elsif !sandbox.member?(@expected_checksum)
86
+ @error = "Cannot upload file: checksum '#{expected_checksum}' isn't a part of sandbox '#{sandbox_id}'"
87
+ else
88
+ false
89
+ end
90
+ end
91
+
92
+ private
93
+
94
+ def load_sandbox
95
+ @sandbox = Chef::Sandbox.cdb_load(@sandbox_id)
96
+ rescue Chef::Exceptions::CouchDBNotFound
97
+ @sandbox = nil
98
+ end
99
+
100
+ def commit_stringio_to(destination_file_path)
101
+ Tempfile.open("sandbox") do |src|
102
+ src.write(@input.string)
103
+ src.close
104
+ Chef::Log.info("upload_checksum: move #{src.path} to #{destination_file_path}")
105
+ FileUtils.mv(src.path, destination_file_path)
106
+ end
107
+ end
108
+
109
+ def commit_tempfile_to(destination_file_path)
110
+ Chef::Log.debug("Sandbox file provided as tempfile: #{@input.inspect}")
111
+ Chef::Log.info("upload_checksum: move #{@input.path} to #{destination_file_path}")
112
+ FileUtils.mv(@input.path, destination_file_path)
113
+ end
114
+
115
+ end
116
+
117
+ end
data/config/router.rb CHANGED
@@ -31,6 +31,8 @@ Merb::Router.prepare do
31
31
  :method => 'get'
32
32
  ).to(:controller => "cookbooks", :action => "index")
33
33
 
34
+ match("/cookbooks/_recipes", :method=>'get').to(:controller=>'cookbooks',:action=>'index_recipes')
35
+
34
36
  match("/cookbooks/:cookbook_name/:cookbook_version",
35
37
  :method => 'put',
36
38
  :cookbook_name => /[\w\.]+/,
@@ -1,3 +1,3 @@
1
1
  module ChefServerApi
2
- VERSION = '0.9.0.a4'
2
+ VERSION = '0.9.0.a6'
3
3
  end
data/spec/spec.opts ADDED
@@ -0,0 +1,3 @@
1
+ -c
2
+ -b
3
+ -fs
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ $:.unshift File.expand_path(File.dirname(__FILE__) + '/../app')
3
+ $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+ $:.unshift File.expand_path(File.dirname(__FILE__) + '/../../chef/lib')
5
+
6
+ require 'chef'
@@ -0,0 +1,135 @@
1
+ #
2
+ # Author:: Daniel DeLeo (<dan@opscode.com>)
3
+ # Copyright:: Copyright (c) 2010 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 File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
20
+ require 'models/sandbox_file'
21
+
22
+ describe ChefServerApi::SandboxFile do
23
+ before do
24
+ @input = StringIO.new
25
+ @params = {:sandbox_id => '1234', :checksum => '2342'}
26
+ @sandbox_file = ChefServerApi::SandboxFile.new(@input, @params)
27
+ end
28
+
29
+ describe "when first created" do
30
+ it "gets a sandbox guid from the parameters" do
31
+ @sandbox_file.sandbox_id.should == '1234'
32
+ end
33
+
34
+ it "gets a checksum from the provided parameters" do
35
+ @sandbox_file.expected_checksum.should == '2342'
36
+ end
37
+
38
+ it "returns the parameters that idendify the resource in the api" do
39
+ @sandbox_file.resource_params.should == {:sandbox_id => '1234', :checksum => '2342'}
40
+ end
41
+
42
+ it "loads an existing sandbox from couchdb" do
43
+ Chef::Sandbox.should_receive(:cdb_load).with('1234').once.and_return(:ohai2u)
44
+ @sandbox_file.sandbox.should == :ohai2u
45
+ @sandbox_file.sandbox.should == :ohai2u
46
+ end
47
+
48
+ # BadRequest in the controller
49
+ it "is invalid if no sandbox_id is given" do
50
+ @params.delete(:sandbox_id)
51
+ sandbox_file = ChefServerApi::SandboxFile.new(@input, @params)
52
+ sandbox_file.invalid_params?.should_not be_false
53
+ sandbox_file.invalid_params?.should == "Cannot upload file with checksum '2342': you must provide a sandbox_id"
54
+ end
55
+
56
+ # BadRequest in the controller
57
+ it "is invalid if no expected checksum is given" do
58
+ @params.delete(:checksum)
59
+ sandbox_file = ChefServerApi::SandboxFile.new(@input, @params)
60
+ sandbox_file.invalid_params?.should_not be_false
61
+ sandbox_file.invalid_params?.should == "Cannot upload file to sandbox '1234': you must provide the file's checksum"
62
+ end
63
+
64
+ it "considers the params valid when both the checksum and sandbox_id are provided" do
65
+ @sandbox_file.invalid_params?.should be_false
66
+ end
67
+
68
+ # NotFound in the controller
69
+ it "is invalid if the provided sandbox_id doesn't exist in the database" do
70
+ err = Chef::Exceptions::CouchDBNotFound.new "Cannot find sandbox 1234 in CouchDB!"
71
+ Chef::Sandbox.should_receive(:cdb_load).with('1234').once.and_raise(err)
72
+ @sandbox_file.invalid_sandbox?.should == "Cannot find sandbox with id '1234' in the database"
73
+ end
74
+
75
+ # NotFound in the controller
76
+ it "is invalid if the sandbox exists, but the given checksum isn't a member of it" do
77
+ sandbox = Chef::Sandbox.new('1234')
78
+ sandbox.checksums << 'not-2342'
79
+ Chef::Sandbox.should_receive(:cdb_load).with('1234').once.and_return(sandbox)
80
+ @sandbox_file.invalid_sandbox?.should == "Cannot upload file: checksum '2342' isn't a part of sandbox '1234'"
81
+ end
82
+
83
+ it "is valid when the sandbox exists and the checksum is a member of it" do
84
+ sandbox = Chef::Sandbox.new('1234')
85
+ sandbox.checksums << '2342'
86
+ Chef::Sandbox.should_receive(:cdb_load).with('1234').once.and_return(sandbox)
87
+ @sandbox_file.invalid_sandbox?.should be_false
88
+ end
89
+
90
+ end
91
+
92
+ context "when created with valid parameters and a valid sandbox" do
93
+ before do
94
+ @sandbox = Chef::Sandbox.new('1234')
95
+ @sandbox_file.stub!(:sandbox).and_return(@sandbox)
96
+ @input.string.replace("riseofthemachines\nriseofthechefs\n")
97
+ end
98
+
99
+ it "checksums the uploaded data" do
100
+ @sandbox_file.actual_checksum.should == '0e157ac1e2dd73191b76067fb6b4bceb'
101
+ end
102
+
103
+ # BadRequest in the controller
104
+ it "considers the uploaded file invalid if its checksum doesn't match" do
105
+ message = "Uploaded file is invalid: expected a md5 sum '2342', but it was '0e157ac1e2dd73191b76067fb6b4bceb'"
106
+ @sandbox_file.invalid_file?.should == message
107
+ end
108
+
109
+ it "is valid if the expected and actual checksums match" do
110
+ @sandbox_file.expected_checksum.replace('0e157ac1e2dd73191b76067fb6b4bceb')
111
+ @sandbox_file.invalid_file?.should be_false
112
+ end
113
+
114
+ context "and a string io for input" do
115
+ it "writes the StringIO's contents to a tempfile, then moves it into place" do
116
+ @tempfile = StringIO.new
117
+ @tempfile.stub!(:path).and_return("/tmpfile/source")
118
+ Tempfile.should_receive(:open).with("sandbox").and_yield(@tempfile)
119
+ FileUtils.should_receive(:mv).with("/tmpfile/source", "/tmp/final_home")
120
+ @sandbox_file.commit_to('/tmp/final_home')
121
+ @tempfile.string.should == "riseofthemachines\nriseofthechefs\n"
122
+ end
123
+ end
124
+
125
+ context "and a tempfile for input" do
126
+ it "moves the tempfile into place" do
127
+ @input.stub!(:path).and_return('/existing/tempfile')
128
+ FileUtils.should_receive(:mv).with("/existing/tempfile", "/tmp/final_home")
129
+ @sandbox_file.commit_to('/tmp/final_home')
130
+ end
131
+ end
132
+
133
+ end
134
+
135
+ end
metadata CHANGED
@@ -6,8 +6,8 @@ version: !ruby/object:Gem::Version
6
6
  - 0
7
7
  - 9
8
8
  - 0
9
- - a4
10
- version: 0.9.0.a4
9
+ - a6
10
+ version: 0.9.0.a6
11
11
  platform: ruby
12
12
  authors:
13
13
  - Opscode
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-04 00:00:00 -07:00
18
+ date: 2010-06-07 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -155,6 +155,9 @@ files:
155
155
  - config/router.rb
156
156
  - lib/chef-server-api/version.rb
157
157
  - lib/chef-server-api.rb
158
+ - spec/spec.opts
159
+ - spec/spec_helper.rb
160
+ - spec/unit/sandbox_file_spec.rb
158
161
  - app/controllers/application.rb
159
162
  - app/controllers/clients.rb
160
163
  - app/controllers/cookbooks.rb
@@ -168,6 +171,7 @@ files:
168
171
  - app/controllers/search.rb
169
172
  - app/controllers/users.rb
170
173
  - app/helpers/tarball_helper.rb
174
+ - app/models/sandbox_file.rb
171
175
  - app/views/exceptions/bad_request.json.erb
172
176
  - app/views/exceptions/internal_server_error.html.erb
173
177
  - app/views/exceptions/not_acceptable.html.haml