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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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