chef-server-api 0.8.16 → 0.9.0.a3
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.
- data/Rakefile +13 -9
- data/app/controllers/application.rb +19 -202
- data/app/controllers/clients.rb +5 -5
- data/app/controllers/cookbooks.rb +79 -155
- data/app/controllers/{data.rb → data_bags.rb} +4 -4
- data/app/controllers/data_item.rb +1 -1
- data/app/controllers/exceptions.rb +1 -1
- data/app/controllers/main.rb +6 -6
- data/app/controllers/nodes.rb +72 -10
- data/app/controllers/roles.rb +3 -3
- data/app/controllers/sandboxes.rb +179 -0
- data/app/controllers/search.rb +8 -8
- data/app/controllers/users.rb +17 -17
- data/app/helpers/tarball_helper.rb +84 -54
- data/app/views/layout/chef_server_api.html.haml +1 -1
- data/bin/chef-server +75 -0
- data/config/environments/development.rb +6 -0
- data/config/init.rb +55 -12
- data/config/rack.rb +5 -0
- data/config/router.rb +81 -5
- data/lib/chef-server-api.rb +2 -158
- data/lib/chef-server-api/version.rb +3 -0
- metadata +56 -43
- data/app/helpers/application_helper.rb +0 -163
- data/app/helpers/exceptions_helper.rb +0 -6
- data/app/helpers/global_helpers.rb +0 -25
- data/app/helpers/nodes_helper.rb +0 -26
- data/app/helpers/roles_helper.rb +0 -5
- data/lib/chef-server-api/merbtasks.rb +0 -103
- data/lib/chef-server-api/slicetasks.rb +0 -20
- data/lib/chef-server-api/spectasks.rb +0 -53
- data/stubs/app/controllers/application.rb +0 -2
- data/stubs/app/controllers/main.rb +0 -2
data/Rakefile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/lib/chef-server-api/version'
|
2
|
+
|
1
3
|
require 'rubygems'
|
2
4
|
require 'rake/gempackagetask'
|
3
5
|
|
@@ -5,7 +7,6 @@ require 'merb-core'
|
|
5
7
|
require 'merb-core/tasks/merb'
|
6
8
|
|
7
9
|
GEM_NAME = "chef-server-api"
|
8
|
-
CHEF_SERVER_VERSION="0.8.16"
|
9
10
|
AUTHOR = "Opscode"
|
10
11
|
EMAIL = "chef@opscode.com"
|
11
12
|
HOMEPAGE = "http://wiki.opscode.com/display/chef"
|
@@ -13,7 +14,7 @@ SUMMARY = "A systems integration framework, built to bring the benefits of confi
|
|
13
14
|
|
14
15
|
spec = Gem::Specification.new do |s|
|
15
16
|
s.name = GEM_NAME
|
16
|
-
s.version =
|
17
|
+
s.version = ChefServerApi::VERSION
|
17
18
|
s.platform = Gem::Platform::RUBY
|
18
19
|
s.has_rdoc = true
|
19
20
|
s.extra_rdoc_files = ["README.rdoc", "LICENSE" ]
|
@@ -23,16 +24,20 @@ spec = Gem::Specification.new do |s|
|
|
23
24
|
s.email = EMAIL
|
24
25
|
s.homepage = HOMEPAGE
|
25
26
|
|
26
|
-
s.add_dependency "merb-core", "~> 1.
|
27
|
-
s.add_dependency "merb-slices", "~> 1.
|
28
|
-
s.add_dependency "merb-assets", "~> 1.
|
29
|
-
s.add_dependency "merb-helpers", "~> 1.
|
27
|
+
s.add_dependency "merb-core", "~> 1.1.0"
|
28
|
+
s.add_dependency "merb-slices", "~> 1.1.0"
|
29
|
+
s.add_dependency "merb-assets", "~> 1.1.0"
|
30
|
+
s.add_dependency "merb-helpers", "~> 1.1.0"
|
31
|
+
s.add_dependency "merb-param-protection", "~> 1.1.0"
|
30
32
|
|
31
33
|
s.add_dependency "json", "<= 1.4.2"
|
32
34
|
|
33
35
|
s.add_dependency "uuidtools", "~> 2.1.1"
|
34
36
|
|
35
37
|
s.add_dependency "thin"
|
38
|
+
|
39
|
+
s.bindir = "bin"
|
40
|
+
s.executables = %w( chef-server )
|
36
41
|
|
37
42
|
s.require_path = 'lib'
|
38
43
|
s.files = %w(LICENSE README.rdoc Rakefile) + Dir.glob("{config,lib,spec,app,public,stubs}/**/*")
|
@@ -44,12 +49,12 @@ end
|
|
44
49
|
|
45
50
|
desc "Install the gem"
|
46
51
|
task :install => :package do
|
47
|
-
sh %{gem install pkg/#{GEM_NAME}-#{
|
52
|
+
sh %{gem install pkg/#{GEM_NAME}-#{ChefServerApi::VERSION} --no-rdoc --no-ri}
|
48
53
|
end
|
49
54
|
|
50
55
|
desc "Uninstall the gem"
|
51
56
|
task :uninstall do
|
52
|
-
sh %{gem uninstall #{GEM_NAME} -x -v #{
|
57
|
+
sh %{gem uninstall #{GEM_NAME} -x -v #{ChefServerApi::VERSION} }
|
53
58
|
end
|
54
59
|
|
55
60
|
desc "Create a gemspec file"
|
@@ -58,4 +63,3 @@ task :gemspec do
|
|
58
63
|
file.puts spec.to_ruby
|
59
64
|
end
|
60
65
|
end
|
61
|
-
|
@@ -1,16 +1,17 @@
|
|
1
1
|
#
|
2
|
-
#
|
3
2
|
# Author:: Adam Jacob (<adam@opscode.com>)
|
4
3
|
# Author:: Christopher Brown (<cb@opscode.com>)
|
5
|
-
#
|
4
|
+
# Author:: Christopher Walters (<cw@opscode.com>)
|
5
|
+
# Author:: Tim Hinderliter (<tim@opscode.com>)
|
6
|
+
# Copyright:: Copyright (c) 2008-2010 Opscode, Inc.
|
6
7
|
# License:: Apache License, Version 2.0
|
7
8
|
#
|
8
9
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
10
|
# you may not use this file except in compliance with the License.
|
10
11
|
# You may obtain a copy of the License at
|
11
|
-
#
|
12
|
+
#
|
12
13
|
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
-
#
|
14
|
+
#
|
14
15
|
# Unless required by applicable law or agreed to in writing, software
|
15
16
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
17
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -18,43 +19,14 @@
|
|
18
19
|
# limitations under the License.
|
19
20
|
#
|
20
21
|
|
21
|
-
require "chef
|
22
|
-
require "chef
|
22
|
+
require "chef/mixin/checksum"
|
23
|
+
require "chef/cookbook_loader"
|
23
24
|
require "mixlib/authentication/signatureverification"
|
24
25
|
|
25
|
-
class
|
26
|
+
class Application < Merb::Controller
|
26
27
|
|
27
28
|
include Chef::Mixin::Checksum
|
28
29
|
|
29
|
-
controller_for_slice
|
30
|
-
|
31
|
-
# Generate the absolute url for a slice - takes the slice's :path_prefix into account.
|
32
|
-
#
|
33
|
-
# @param slice_name<Symbol>
|
34
|
-
# The name of the slice - in identifier_sym format (underscored).
|
35
|
-
# @param *args<Array[Symbol,Hash]>
|
36
|
-
# There are several possibilities regarding arguments:
|
37
|
-
# - when passing a Hash only, the :default route of the current
|
38
|
-
# slice will be used
|
39
|
-
# - when a Symbol is passed, it's used as the route name
|
40
|
-
# - a Hash with additional params can optionally be passed
|
41
|
-
#
|
42
|
-
# @return <String> A uri based on the requested slice.
|
43
|
-
#
|
44
|
-
# @example absolute_slice_url(:awesome, :format => 'html')
|
45
|
-
# @example absolute_slice_url(:forum, :posts, :format => 'xml')
|
46
|
-
def absolute_slice_url(slice_name, *args)
|
47
|
-
options = {}
|
48
|
-
if args.length == 1 && args[0].respond_to?(:keys)
|
49
|
-
options = args[0]
|
50
|
-
else
|
51
|
-
options = extract_options_from_args!(args) || {}
|
52
|
-
end
|
53
|
-
protocol = options.delete(:protocol) || request.protocol
|
54
|
-
host = options.delete(:host) || request.host
|
55
|
-
protocol + "://" + host + slice_url(slice_name, *args)
|
56
|
-
end
|
57
|
-
|
58
30
|
def authenticate_every
|
59
31
|
authenticator = Mixlib::Authentication::SignatureVerification.new
|
60
32
|
|
@@ -79,12 +51,12 @@ class ChefServerApi::Application < Merb::Controller
|
|
79
51
|
|
80
52
|
auth
|
81
53
|
end
|
82
|
-
|
83
|
-
def is_admin
|
54
|
+
|
55
|
+
def is_admin
|
84
56
|
if @auth_user.admin
|
85
57
|
true
|
86
58
|
else
|
87
|
-
raise
|
59
|
+
raise Forbidden, "You are not allowed to take this action."
|
88
60
|
end
|
89
61
|
end
|
90
62
|
|
@@ -92,18 +64,18 @@ class ChefServerApi::Application < Merb::Controller
|
|
92
64
|
if @auth_user.admin || @auth_user.name == Chef::Config[:validation_client_name]
|
93
65
|
true
|
94
66
|
else
|
95
|
-
raise
|
67
|
+
raise Forbidden, "You are not allowed to take this action."
|
96
68
|
end
|
97
69
|
end
|
98
70
|
|
99
|
-
def
|
71
|
+
def admin_or_requesting_node
|
100
72
|
if @auth_user.admin || @auth_user.name == params[:id]
|
101
73
|
true
|
102
74
|
else
|
103
|
-
raise
|
75
|
+
raise Forbidden, "You are not the correct node (auth_user name: #{@auth_user.name}, params[:id]: #{params[:id]}), or are not an API administrator (admin: #{@auth_user.admin})."
|
104
76
|
end
|
105
77
|
end
|
106
|
-
|
78
|
+
|
107
79
|
# Store the URI of the current request in the session.
|
108
80
|
#
|
109
81
|
# We can return to this location by calling #redirect_back_or_default.
|
@@ -118,169 +90,14 @@ class ChefServerApi::Application < Merb::Controller
|
|
118
90
|
session[:return_to] = nil
|
119
91
|
redirect loc
|
120
92
|
end
|
121
|
-
|
122
|
-
def access_denied
|
123
|
-
case content_type
|
124
|
-
when :html
|
125
|
-
store_location
|
126
|
-
redirect slice_url(:openid_consumer), :message => { :error => "You don't have access to that, please login."}
|
127
|
-
else
|
128
|
-
raise Unauthorized, "You must authenticate first!"
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
# Load a cookbook and return a hash with a list of all the files of a
|
133
|
-
# given segment (attributes, recipes, definitions, libraries)
|
134
|
-
#
|
135
|
-
# === Parameters
|
136
|
-
# cookbook_id<String>:: The cookbook to load
|
137
|
-
# segment<Symbol>:: :attributes, :recipes, :definitions, :libraries
|
138
|
-
#
|
139
|
-
# === Returns
|
140
|
-
# <Hash>:: A hash consisting of the short name of the file in :name, and the full path
|
141
|
-
# to the file in :file.
|
142
|
-
def load_cookbook_segment(cookbook, segment)
|
143
|
-
files_list = segment_files(segment, cookbook)
|
144
|
-
|
145
|
-
files = Hash.new
|
146
|
-
files_list.each do |f|
|
147
|
-
full = File.expand_path(f)
|
148
|
-
name = File.basename(full)
|
149
|
-
files[name] = {
|
150
|
-
:name => name,
|
151
|
-
:file => full,
|
152
|
-
}
|
153
|
-
end
|
154
|
-
files
|
155
|
-
end
|
156
|
-
|
157
|
-
def segment_files(segment, cookbook)
|
158
|
-
files_list = nil
|
159
|
-
case segment
|
160
|
-
when :attributes
|
161
|
-
files_list = cookbook.attribute_files
|
162
|
-
when :recipes
|
163
|
-
files_list = cookbook.recipe_files
|
164
|
-
when :definitions
|
165
|
-
files_list = cookbook.definition_files
|
166
|
-
when :libraries
|
167
|
-
files_list = cookbook.lib_files
|
168
|
-
when :providers
|
169
|
-
files_list = cookbook.provider_files
|
170
|
-
when :resources
|
171
|
-
files_list = cookbook.resource_files
|
172
|
-
when :files
|
173
|
-
files_list = cookbook.remote_files
|
174
|
-
when :templates
|
175
|
-
files_list = cookbook.template_files
|
176
|
-
else
|
177
|
-
raise ArgumentError, "segment must be one of :attributes, :recipes, :definitions, :remote_files, :template_files, :resources, :providers or :libraries"
|
178
|
-
end
|
179
|
-
files_list
|
180
|
-
end
|
181
|
-
|
182
|
-
def specific_cookbooks(node_name, cl)
|
183
|
-
valid_cookbooks = Hash.new
|
184
|
-
begin
|
185
|
-
node = Chef::Node.cdb_load(node_name)
|
186
|
-
recipes, default_attrs, override_attrs = node.run_list.expand('couchdb')
|
187
|
-
rescue Net::HTTPServerException
|
188
|
-
recipes = []
|
189
|
-
end
|
190
|
-
recipes.each do |recipe|
|
191
|
-
valid_cookbooks = expand_cookbook_deps(valid_cookbooks, cl, recipe)
|
192
|
-
end
|
193
|
-
valid_cookbooks
|
194
|
-
end
|
195
93
|
|
196
|
-
def
|
197
|
-
|
198
|
-
if recipe =~ /^(.+)::/
|
199
|
-
cookbook = $1
|
200
|
-
end
|
201
|
-
Chef::Log.debug("Node requires #{cookbook}")
|
202
|
-
valid_cookbooks[cookbook] = true
|
203
|
-
cl.metadata[cookbook.to_sym].dependencies.each do |dep, versions|
|
204
|
-
expand_cookbook_deps(valid_cookbooks, cl, dep) unless valid_cookbooks[dep]
|
205
|
-
end
|
206
|
-
valid_cookbooks
|
207
|
-
end
|
208
|
-
|
209
|
-
def load_cookbook_files(cookbook)
|
210
|
-
response = {
|
211
|
-
:recipes => Array.new,
|
212
|
-
:definitions => Array.new,
|
213
|
-
:libraries => Array.new,
|
214
|
-
:attributes => Array.new,
|
215
|
-
:files => Array.new,
|
216
|
-
:templates => Array.new,
|
217
|
-
:resources => Array.new,
|
218
|
-
:providers => Array.new
|
219
|
-
}
|
220
|
-
[ :resources, :providers, :recipes, :definitions, :libraries, :attributes, :files, :templates ].each do |segment|
|
221
|
-
segment_files(segment, cookbook).each do |sf|
|
222
|
-
next if File.directory?(sf)
|
223
|
-
file_name = nil
|
224
|
-
file_url = nil
|
225
|
-
file_specificity = nil
|
226
|
-
|
227
|
-
if segment == :templates || segment == :files
|
228
|
-
mo = sf.match("cookbooks/#{cookbook.name}/#{segment}/(.+?)/(.+)")
|
229
|
-
unless mo
|
230
|
-
Chef::Log.debug("Skipping file #{sf}, as it doesn't have a proper segment.")
|
231
|
-
next
|
232
|
-
end
|
233
|
-
specificity = mo[1]
|
234
|
-
file_name = mo[2]
|
235
|
-
url_options = { :cookbook_id => cookbook.name.to_s, :segment => segment, :id => file_name }
|
236
|
-
|
237
|
-
case specificity
|
238
|
-
when "default"
|
239
|
-
when /^host-(.+)$/
|
240
|
-
url_options[:fqdn] = $1
|
241
|
-
when /^(.+)-(.+)$/
|
242
|
-
url_options[:platform] = $1
|
243
|
-
url_options[:version] = $2
|
244
|
-
when /^(.+)$/
|
245
|
-
url_options[:platform] = $1
|
246
|
-
end
|
247
|
-
|
248
|
-
file_specificity = specificity
|
249
|
-
file_url = absolute_slice_url(:cookbook_segment, url_options)
|
250
|
-
else
|
251
|
-
mo = sf.match("cookbooks/#{cookbook.name}/#{segment}/(.+)")
|
252
|
-
file_name = mo[1]
|
253
|
-
url_options = { :cookbook_id => cookbook.name.to_s, :segment => segment, :id => file_name }
|
254
|
-
file_url = absolute_slice_url(:cookbook_segment, url_options)
|
255
|
-
end
|
256
|
-
rs = {
|
257
|
-
:name => file_name,
|
258
|
-
:uri => file_url,
|
259
|
-
:checksum => checksum(sf)
|
260
|
-
}
|
261
|
-
rs[:specificity] = file_specificity if file_specificity
|
262
|
-
response[segment] << rs
|
263
|
-
end
|
264
|
-
end
|
265
|
-
response
|
94
|
+
def access_denied
|
95
|
+
raise Unauthorized, "You must authenticate first!"
|
266
96
|
end
|
267
97
|
|
268
|
-
def load_all_files(node_name=nil)
|
269
|
-
cl = Chef::CookbookLoader.new
|
270
|
-
valid_cookbooks = node_name ? specific_cookbooks(node_name, cl) : {}
|
271
|
-
cookbook_list = Hash.new
|
272
|
-
cl.each do |cookbook|
|
273
|
-
if node_name
|
274
|
-
next unless valid_cookbooks[cookbook.name.to_s]
|
275
|
-
end
|
276
|
-
cookbook_list[cookbook.name.to_s] = load_cookbook_files(cookbook)
|
277
|
-
end
|
278
|
-
cookbook_list
|
279
|
-
end
|
280
|
-
|
281
98
|
def get_available_recipes
|
282
|
-
|
283
|
-
available_recipes =
|
99
|
+
all_cookbooks_list = Chef::CookbookVersion.cdb_list(true)
|
100
|
+
available_recipes = all_cookbooks_list.sort{ |a,b| a.name.to_s <=> b.name.to_s }.inject([]) do |result, element|
|
284
101
|
element.recipes.sort.each do |r|
|
285
102
|
if r =~ /^(.+)::default$/
|
286
103
|
result << $1
|
data/app/controllers/clients.rb
CHANGED
@@ -19,18 +19,18 @@
|
|
19
19
|
|
20
20
|
require 'chef/api_client'
|
21
21
|
|
22
|
-
class
|
22
|
+
class Clients < Application
|
23
23
|
provides :json
|
24
24
|
|
25
25
|
before :authenticate_every
|
26
26
|
before :is_admin, :only => [ :index, :update, :destroy ]
|
27
27
|
before :is_admin_or_validator, :only => [ :create ]
|
28
|
-
before :
|
28
|
+
before :admin_or_requesting_node, :only => [ :show ]
|
29
29
|
|
30
30
|
# GET /clients
|
31
31
|
def index
|
32
32
|
@list = Chef::ApiClient.cdb_list(true)
|
33
|
-
display(@list.inject({}) { |result, element| result[element.name] =
|
33
|
+
display(@list.inject({}) { |result, element| result[element.name] = absolute_url(:client, :id => element.name); result })
|
34
34
|
end
|
35
35
|
|
36
36
|
# GET /clients/:id
|
@@ -72,8 +72,8 @@ class ChefServerApi::Clients < ChefServerApi::Application
|
|
72
72
|
@client.cdb_save
|
73
73
|
|
74
74
|
self.status = 201
|
75
|
-
headers['Location'] =
|
76
|
-
display({ :uri =>
|
75
|
+
headers['Location'] = absolute_url(:client, @client.name)
|
76
|
+
display({ :uri => absolute_url(:client, @client.name), :private_key => @client.private_key })
|
77
77
|
end
|
78
78
|
|
79
79
|
# PUT /clients/:id
|
@@ -2,7 +2,8 @@
|
|
2
2
|
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
3
|
# Author:: Christopher Brown (<cb@opscode.com>)
|
4
4
|
# Author:: Christopher Walters (<cw@opscode.com>)
|
5
|
-
#
|
5
|
+
# Author:: Tim Hinderliter (<tim@opscode.com>)
|
6
|
+
# Copyright:: Copyright (c) 2008, 2009, 2010 Opscode, Inc.
|
6
7
|
# License:: Apache License, Version 2.0
|
7
8
|
#
|
8
9
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -21,192 +22,115 @@
|
|
21
22
|
require 'chef' / 'cookbook_loader'
|
22
23
|
require 'chef' / 'cookbook' / 'metadata'
|
23
24
|
|
24
|
-
class
|
25
|
+
class Cookbooks < Application
|
25
26
|
|
26
27
|
provides :json
|
27
28
|
|
28
29
|
before :authenticate_every
|
30
|
+
before :params_helper
|
31
|
+
|
32
|
+
attr_accessor :cookbook_name, :cookbook_version
|
33
|
+
|
34
|
+
def params_helper
|
35
|
+
self.cookbook_name = params[:cookbook_name]
|
36
|
+
self.cookbook_version = params[:cookbook_version]
|
37
|
+
end
|
29
38
|
|
30
39
|
include Chef::Mixin::Checksum
|
31
|
-
include Merb::
|
40
|
+
include Merb::TarballHelper
|
32
41
|
|
33
42
|
def index
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
43
|
+
cookbook_list = Chef::CookbookVersion.cdb_list
|
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)
|
38
48
|
end
|
39
|
-
display
|
49
|
+
display response
|
40
50
|
end
|
41
51
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
rescue ArgumentError => e
|
47
|
-
raise NotFound, "Cannot find a cookbook named #{params[:id]}"
|
48
|
-
end
|
49
|
-
results = load_cookbook_files(cookbook)
|
50
|
-
results[:name] = cookbook.name.to_s
|
51
|
-
results[:metadata] = cl.metadata[cookbook.name.to_sym]
|
52
|
-
display results
|
53
|
-
end
|
54
|
-
|
55
|
-
def show_segment
|
56
|
-
cl = Chef::CookbookLoader.new
|
57
|
-
begin
|
58
|
-
cookbook = cl[params[:cookbook_id]]
|
59
|
-
rescue ArgumentError => e
|
60
|
-
raise NotFound, "Cannot find a cookbook named #{params[:cookbook_id]}"
|
61
|
-
end
|
62
|
-
cookbook_files = load_cookbook_files(cookbook)
|
63
|
-
raise NotFound unless cookbook_files.has_key?(params[:segment].to_sym)
|
64
|
-
|
65
|
-
if params[:id]
|
66
|
-
case params[:segment]
|
67
|
-
when "templates","files"
|
68
|
-
if params[:recursive]
|
69
|
-
serve_directory_preferred(cookbook, params[:segment], cookbook_files[params[:segment].to_sym])
|
70
|
-
else
|
71
|
-
serve_segment_preferred(cookbook, params[:segment], cookbook_files[params[:segment].to_sym])
|
72
|
-
end
|
73
|
-
else
|
74
|
-
serve_segment_file(cookbook, params[:segment], cookbook_files[params[:segment].to_sym])
|
75
|
-
end
|
76
|
-
else
|
77
|
-
display cookbook_files[params[:segment].to_sym]
|
78
|
-
end
|
52
|
+
def show_versions
|
53
|
+
versions = Chef::CookbookVersion.cdb_by_name(cookbook_name)
|
54
|
+
raise NotFound, "Cannot find a cookbook named #{cookbook_name}" unless versions && versions.size > 0
|
55
|
+
display versions
|
79
56
|
end
|
80
57
|
|
81
|
-
def
|
58
|
+
def show
|
59
|
+
cookbook = get_cookbook_version(cookbook_name, cookbook_version)
|
60
|
+
display cookbook.generate_manifest_with_urls { |opts| absolute_url(:cookbook_file, opts) }
|
61
|
+
end
|
82
62
|
|
83
|
-
|
63
|
+
def show_file
|
64
|
+
cookbook = get_cookbook_version(cookbook_name, cookbook_version)
|
84
65
|
|
85
|
-
|
86
|
-
|
87
|
-
Chef::Log.debug("Looking for a file with name `#{params[:id]}' and specificity #{pref}")
|
88
|
-
to_send = files.detect do |file|
|
89
|
-
Chef::Log.debug("#{pref.inspect} #{file.inspect}")
|
90
|
-
file[:name] == params[:id] && file[:specificity] == pref
|
91
|
-
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
66
|
+
checksum = params[:checksum]
|
67
|
+
raise NotFound, "Cookbook #{cookbook_name} version #{cookbook_version} does not contain a file with checksum #{checksum}" unless cookbook.checksums.keys.include?(checksum)
|
95
68
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
raise NotModified, "File #{to_send[:name]} has not changed"
|
101
|
-
else
|
102
|
-
file_name = nil
|
103
|
-
segment_files(segment.to_sym, cookbook).each do |f|
|
104
|
-
if f =~ /#{to_send[:specificity]}\/#{to_send[:name]}$/
|
105
|
-
file_name = File.expand_path(f)
|
106
|
-
break
|
107
|
-
end
|
108
|
-
end
|
109
|
-
raise NotFound, "Cannot find the real file for #{to_send[:specificity]} #{to_send[:name]} - this is a 42 error (shouldn't ever happen)" unless file_name
|
110
|
-
send_file(file_name)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def serve_directory_preferred(cookbook, segment, files)
|
115
|
-
preferred_dir_contents = []
|
116
|
-
preferences.each do |preference|
|
117
|
-
preferred_dir_contents = files.select { |file| file[:name] =~ /^#{params[:id]}/ && file[:specificity] == preference }
|
118
|
-
break unless preferred_dir_contents.empty?
|
119
|
-
end
|
120
|
-
|
121
|
-
raise NotFound, "Cannot find a suitable directory for #{params[:id]}" if preferred_dir_contents.empty?
|
122
|
-
|
123
|
-
display preferred_dir_contents.map { |file| file[:name].sub(/^#{params[:id]}/, '') }
|
124
|
-
end
|
125
|
-
|
126
|
-
def preferences
|
127
|
-
["host-#{params[:fqdn]}",
|
128
|
-
"#{params[:platform]}-#{params[:version]}",
|
129
|
-
"#{params[:platform]}",
|
130
|
-
"default"]
|
69
|
+
filename = checksum_location(checksum)
|
70
|
+
raise InternalServerError, "File with checksum #{checksum} not found in the repository (this should not happen)" unless File.exists?(filename)
|
71
|
+
|
72
|
+
send_file(filename)
|
131
73
|
end
|
132
74
|
|
133
|
-
def
|
134
|
-
|
135
|
-
raise
|
136
|
-
|
137
|
-
|
138
|
-
if current_checksum == params[:checksum]
|
139
|
-
raise NotModified, "File #{to_send[:name]} has not changed"
|
140
|
-
else
|
141
|
-
file_name = nil
|
142
|
-
segment_files(segment.to_sym, cookbook).each do |f|
|
143
|
-
next unless File.basename(f) == to_send[:name]
|
144
|
-
file_name = File.expand_path(f)
|
145
|
-
end
|
146
|
-
raise NotFound, "Cannot find the real file for #{to_send[:name]} - this is a 42 error (shouldn't ever happen)" unless file_name
|
147
|
-
send_file(file_name)
|
75
|
+
def update
|
76
|
+
raise(BadRequest, "You didn't pass me a valid object!") unless params.has_key?('inflated_object')
|
77
|
+
raise(BadRequest, "You didn't pass me a Chef::CookbookVersion object!") unless params['inflated_object'].kind_of?(Chef::CookbookVersion)
|
78
|
+
unless params["inflated_object"].name == cookbook_name
|
79
|
+
raise(BadRequest, "You said the cookbook was named #{params['inflated_object'].name}, but the URL says it should be #{cookbook_name}.")
|
148
80
|
end
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
# validate name and file parameters and throw an error if a cookbook with the same name already exists
|
153
|
-
raise BadRequest, "missing required parameter: name" unless params[:name]
|
154
|
-
desired_name = params[:name]
|
155
|
-
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/
|
156
|
-
begin
|
157
|
-
validate_file_parameter(desired_name, params[:file])
|
158
|
-
rescue FileParameterException => te
|
159
|
-
raise BadRequest, te.message
|
81
|
+
|
82
|
+
unless params["inflated_object"].version == cookbook_version
|
83
|
+
raise(BadRequest, "You said the cookbook was version #{params['inflated_object'].version}, but the URL says it should be #{cookbook_version}.")
|
160
84
|
end
|
161
85
|
|
162
86
|
begin
|
163
|
-
Chef::
|
164
|
-
|
165
|
-
rescue
|
87
|
+
cookbook = Chef::CookbookVersion.cdb_load(cookbook_name, cookbook_version)
|
88
|
+
cookbook.manifest = params['inflated_object'].manifest
|
89
|
+
rescue Chef::Exceptions::CouchDBNotFound => e
|
90
|
+
Chef::Log.debug("Cookbook #{cookbook_name} version #{cookbook_version} does not exist")
|
91
|
+
cookbook = params['inflated_object']
|
166
92
|
end
|
167
93
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
94
|
+
# ensure that all checksums referred to by the manifest have been uploaded.
|
95
|
+
Chef::CookbookVersion::COOKBOOK_SEGMENTS.each do |segment|
|
96
|
+
next unless cookbook.manifest[segment]
|
97
|
+
cookbook.manifest[segment].each do |manifest_record|
|
98
|
+
checksum = manifest_record[:checksum]
|
99
|
+
path = manifest_record[:path]
|
100
|
+
|
101
|
+
begin
|
102
|
+
checksum_obj = Chef::Checksum.cdb_load(checksum)
|
103
|
+
rescue Chef::Exceptions::CouchDBNotFound => cdbx
|
104
|
+
checksum_obj = nil
|
105
|
+
end
|
106
|
+
|
107
|
+
raise BadRequest, "Manifest has checksum #{checksum} (path #{path}) but it hasn't yet been uploaded" unless checksum_obj
|
108
|
+
end
|
109
|
+
end
|
182
110
|
|
183
|
-
|
111
|
+
raise InternalServerError, "Error saving cookbook" unless cookbook.cdb_save
|
112
|
+
|
113
|
+
display cookbook
|
184
114
|
end
|
185
115
|
|
186
|
-
def
|
187
|
-
cookbook_name = params[:cookbook_id]
|
188
|
-
cookbook_path = cookbook_location(cookbook_name)
|
189
|
-
raise NotFound, "Cannot find cookbook named #{cookbook_name}" unless File.directory? cookbook_path
|
116
|
+
def destroy
|
190
117
|
begin
|
191
|
-
|
192
|
-
rescue
|
193
|
-
raise
|
118
|
+
cookbook = get_cookbook_version(cookbook_name, cookbook_version)
|
119
|
+
rescue ArgumentError => e
|
120
|
+
raise NotFound, "Cannot find a cookbook named #{cookbook_name} with version #{cookbook_version}"
|
194
121
|
end
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
display Hash.new
|
122
|
+
|
123
|
+
display cookbook.cdb_destroy
|
199
124
|
end
|
200
|
-
|
201
|
-
def destroy
|
202
|
-
cookbook_name = params[:id]
|
203
|
-
cookbook_path = cookbook_location(cookbook_name)
|
204
|
-
raise NotFound, "Cannot find cookbook named #{cookbook_name}" unless File.directory? cookbook_path
|
205
125
|
|
206
|
-
|
207
|
-
FileUtils.rm_f(cookbook_tarball_location(cookbook_name))
|
126
|
+
private
|
208
127
|
|
209
|
-
|
128
|
+
def get_cookbook_version(name, version)
|
129
|
+
begin
|
130
|
+
Chef::CookbookVersion.cdb_load(name, version)
|
131
|
+
rescue Chef::Exceptions::CouchDBNotFound => e
|
132
|
+
raise NotFound, "Cannot find a cookbook named #{name} with version #{version}"
|
133
|
+
end
|
210
134
|
end
|
211
135
|
|
212
136
|
end
|