Skip to content

Commit 9417a3e

Browse files
sdelanoSeth Falcon
authored andcommitted
environments cookbooks api
1 parent 11997f0 commit 9417a3e

5 files changed

Lines changed: 111 additions & 13 deletions

File tree

‎chef-server-api/app/controllers/environments.rb‎

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,19 +77,27 @@ def update
7777
def destroy
7878
begin
7979
env = Chef::Environment.cdb_load(params[:id])
80-
rescue
80+
rescue Chef::Exceptions::CouchDBNotFound
8181
raise NotFound, "Cannot load environment #{params[:id]}"
8282
end
8383
env.cdb_destroy
8484
display(env)
8585
end
8686

87-
# GET /environments/:id/nodes
88-
def nodes
89-
node_list = Chef::Node.cdb_list_by_environment(params[:id])
90-
display(node_list.inject({}) do |r,n|
91-
r[n] = absolute_url(:node, n); r
92-
end)
87+
# GET /environments/:environment_id/cookbooks
88+
def list_cookbooks
89+
begin
90+
filtered_cookbooks = Chef::Environment.cdb_load_filtered_cookbook_versions(params[:environment_id])
91+
rescue Chef::Exceptions::CouchDBNotFound
92+
raise NotFound, "Cannot load environment #{params[:environment_id]}"
93+
end
94+
display(filtered_cookbooks.inject({}) {|res, (k,v)| res[v.name] = absolute_url(:cookbook_version, :cookbook_name=>v.name, :cookbook_version=>v.version); res})
95+
end
96+
97+
# GET /environments/:environment_id/nodes
98+
def list_nodes
99+
node_list = Chef::Node.cdb_list_by_environment(params[:environment_id])
100+
display(node_list.inject({}) {|r,n| r[n] = absolute_url(:node, n); r}
93101
end
94102

95103
private

‎chef-server-api/app/controllers/nodes.rb‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def cookbooks
9292
private
9393

9494
def load_all_files
95-
all_cookbooks = Chef::CookbookVersion.cdb_list(true).inject({}) {|hsh,record| hsh[record.name] = record ; hsh}
95+
all_cookbooks = Chef::Environment.cdb_load_filtered_cookbook_versions(@node.chef_environment)
9696

9797
included_cookbooks = cookbooks_for_node(all_cookbooks)
9898
nodes_cookbooks = Hash.new

‎chef-server-api/config/router.rb‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,10 @@
3030
resources :roles
3131

3232
# Environments
33-
resources :environments
34-
match('/environments/:id/nodes',
35-
:id => /^[\-[:alnum:]_]+$/,
36-
:method => 'get').
37-
to(:controller => "environments", :action => "nodes")
33+
resources :environments do |e|
34+
e.match("/cookbooks", :method => "get").to(:controller=>"environments", :action=>"list_cookbooks")
35+
e.match("/nodes", :method => "get").to(:controller=>"environments", :action=>"list_nodes")
36+
end
3837

3938
# Status
4039
match("/status").to(:controller => "status", :action => "index").name(:status)

‎chef/lib/chef/environment.rb‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,23 @@ def self.create_design_document(couchdb=nil)
210210
(couchdb || Chef::CouchDB.new).create_design_document("environments", DESIGN_DOCUMENT)
211211
end
212212

213+
def self.cdb_load_filtered_cookbook_versions(name, couchdb=nil)
214+
cvs = begin
215+
name.nil? ? Hash.new : Chef::Environment.cdb_load(name, couchdb).cookbook_versions.inject({}) {|res, (k,v)| res[k] = Gem::Requirement.new(v); res}
216+
rescue Chef::Exceptions::CouchDBNotFound => e
217+
raise e
218+
end
219+
220+
# inject all cookbooks into the hash while filtering out restricted versions
221+
Chef::CookbookVersion.cdb_list(true, couchdb).inject({}) do |res, cookbook|
222+
version = Gem::Version.new(cookbook.version)
223+
requirement_satisfied = cvs.has_key?(cookbook.name) ? cvs[cookbook.name].satisfied_by?(version) : true
224+
newest_version = res.has_key?(cookbook.name) ? version > Gem::Version.new(res[cookbook.name].version) : true
225+
res[cookbook.name] = cookbook if requirement_satisfied && newest_version
226+
res
227+
end
228+
end
229+
213230
def to_s
214231
@name
215232
end

‎chef/spec/unit/environment_spec.rb‎

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,80 @@
203203
end
204204
end
205205

206+
describe "self.cdb_load_filtered_cookbook_versions" do
207+
before(:each) do
208+
@environment.name "prod"
209+
@environment.cookbook_versions({
210+
"apt" => "1.0.0",
211+
"apache2" => "2.0.0"
212+
})
213+
Chef::Environment.stub!(:cdb_load).and_return @environment
214+
215+
@all_cookbooks = []
216+
@all_cookbooks << begin
217+
cv = Chef::CookbookVersion.new("apt")
218+
cv.version = "1.0.0"
219+
cv
220+
end
221+
@all_cookbooks << begin
222+
cv = Chef::CookbookVersion.new("apt")
223+
cv.version = "1.1.0"
224+
cv
225+
end
226+
@all_cookbooks << begin
227+
cv = Chef::CookbookVersion.new("apache2")
228+
cv.version = "2.0.0"
229+
cv
230+
end
231+
@all_cookbooks << begin
232+
cv = Chef::CookbookVersion.new("god")
233+
cv.version = "4.2.0"
234+
cv
235+
end
236+
Chef::CookbookVersion.stub!(:cdb_list).and_return @all_cookbooks
237+
end
238+
239+
it "should load the environment" do
240+
Chef::Environment.should_receive(:cdb_load).with("prod", nil)
241+
Chef::Environment.cdb_load_filtered_cookbook_versions("prod")
242+
end
243+
244+
it "should load all the cookbook versions" do
245+
Chef::CookbookVersion.should_receive(:cdb_list)
246+
Chef::Environment.cdb_load_filtered_cookbook_versions("prod")
247+
end
248+
249+
it "should restrict the cookbook versions, as specified in the environment" do
250+
res = Chef::Environment.cdb_load_filtered_cookbook_versions("prod")
251+
res["apt"].version.should == "1.0.0"
252+
res["apache2"].version.should == "2.0.0"
253+
res["god"].version.should == "4.2.0"
254+
end
255+
256+
it "should succeed if the environment is nil" do
257+
Chef::Environment.should_not_receive(:cdb_load)
258+
res = Chef::Environment.cdb_load_filtered_cookbook_versions(nil)
259+
res["apt"].version.should == "1.1.0"
260+
res["apache2"].version.should == "2.0.0"
261+
res["god"].version.should == "4.2.0"
262+
end
263+
264+
it "should produce correct results, regardless of the cookbook order in couch" do
265+
# a bug present before the environments feature defaulted to the last CookbookVersion
266+
# object for a cookbook as returned from couchdb when fetching cookbooks for a node
267+
# this is a regression test
268+
@all_cookbooks << begin
269+
cv = Chef::CookbookVersion.new("god")
270+
cv.version = "0.0.1"
271+
cv
272+
end
273+
res = Chef::Environment.cdb_load_filtered_cookbook_versions("prod")
274+
res["apt"].version.should == "1.0.0"
275+
res["apache2"].version.should == "2.0.0"
276+
res["god"].version.should == "4.2.0"
277+
end
278+
end
279+
206280
describe "self.validate_cookbook_versions" do
207281
before(:each) do
208282
@cookbook_versions = {

0 commit comments

Comments
 (0)