Skip to content

Commit e9c7c8a

Browse files
sdelanoSeth Falcon
authored andcommitted
return all cookbooks available for an environment
1 parent 6e18824 commit e9c7c8a

5 files changed

Lines changed: 58 additions & 12 deletions

File tree

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,14 @@ def list_cookbooks
9393
rescue Chef::Exceptions::CouchDBNotFound
9494
raise NotFound, "Cannot load environment #{params[:environment_id]}"
9595
end
96-
display(filtered_cookbooks.inject({}) {|res, (k,v)| res[v.name] = absolute_url(:cookbook_version, :cookbook_name=>v.name, :cookbook_version=>v.version); res})
96+
display(filtered_cookbooks.inject({}) {|res, (cookbook_name,versions)|
97+
# TODO:
98+
# For now, we are only displaying the last cookbook in the sorted list (the newest version).
99+
# We should display every cookbook version that is available in a given environment
100+
# [stephen 9/2/10]
101+
res[cookbook_name] = absolute_url(:cookbook_version, :cookbook_name=>cookbook_name, :cookbook_version=>versions.last.version)
102+
res
103+
})
97104
end
98105

99106
# GET /environments/:environment_id/nodes

chef/lib/chef/cookbook_version.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,11 @@ def couchdb_id=(value)
823823
@index_id = value
824824
end
825825

826+
def <=>(o)
827+
raise Chef::Exceptions::CookbookVersionNameMismatch if self.name != o.name
828+
Gem::Version.new(self.version) <=> Gem::Version.new(o.version)
829+
end
830+
826831
private
827832

828833
# For each filename, produce a mapping of base filename (i.e. recipe name

chef/lib/chef/environment.rb

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

213+
# Loads the set of Chef::CookbookVersion objects available to a given environment
214+
# === Returns
215+
# Hash
216+
# i.e.
217+
# {
218+
# "coobook_name" => [ Chef::CookbookVersion ... ] ## the array of CookbookVersions is sorted lowest to highest
219+
# }
213220
def self.cdb_load_filtered_cookbook_versions(name, couchdb=nil)
214221
cvs = begin
215222
Chef::Environment.cdb_load(name, couchdb).cookbook_versions.inject({}) {|res, (k,v)| res[k] = Gem::Requirement.new(v); res}
216223
rescue Chef::Exceptions::CouchDBNotFound => e
217224
raise e
218225
end
219226

220-
# inject all cookbooks into the hash while filtering out restricted versions
221-
Chef::CookbookVersion.cdb_list(true, couchdb).inject({}) do |res, cookbook|
227+
# inject all cookbooks into the hash while filtering out restricted versions, then sort the individual arrays
228+
Chef::CookbookVersion.cdb_list(true, couchdb).inject({}) {|res, cookbook|
222229
version = Gem::Version.new(cookbook.version)
223230
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
231+
res[cookbook.name] = (res[cookbook.name] || []) << cookbook if requirement_satisfied
226232
res
227-
end
233+
}.inject({}) {|res, (cookbook_name, versions)|
234+
res[cookbook_name] = versions.sort
235+
res
236+
}
228237
end
229238

230239
def to_s

chef/spec/unit/cookbook_version_spec.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,5 +263,23 @@
263263

264264
end
265265

266+
describe "<=>" do
267+
it "should sort based on the version number" do
268+
one = Chef::CookbookVersion.new("apt")
269+
one.version = "1.0"
270+
two = Chef::CookbookVersion.new("apt")
271+
two.version = "2.0"
272+
(one <=> two).should == -1
273+
(two <=> one).should == 1
274+
end
275+
276+
it "should not allow you to sort cookbooks with different names" do
277+
apt = Chef::CookbookVersion.new "apt"
278+
apt.version = "1.0"
279+
god = Chef::CookbookVersion.new "god"
280+
god.version = "2.0"
281+
lambda {apt <=> god}.should raise_error(Chef::Exceptions::CookbookVersionNameMismatch)
282+
end
283+
end
266284

267285
end

chef/spec/unit/environment_spec.rb

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,9 @@
248248

249249
it "should restrict the cookbook versions, as specified in the environment" do
250250
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"
251+
res["apt"].detect {|cb| cb.version == "1.0.0"}.should_not == nil
252+
res["apache2"].detect {|cb| cb.version == "2.0.0"}.should_not == nil
253+
res["god"].detect {|cb| cb.version == "4.2.0"}.should_not == nil
254254
end
255255

256256
it "should produce correct results, regardless of the cookbook order in couch" do
@@ -263,9 +263,16 @@
263263
cv
264264
end
265265
res = Chef::Environment.cdb_load_filtered_cookbook_versions("prod")
266-
res["apt"].version.should == "1.0.0"
267-
res["apache2"].version.should == "2.0.0"
268-
res["god"].version.should == "4.2.0"
266+
res["apt"].detect {|cb| cb.version == "1.0.0"}.should_not == nil
267+
res["apache2"].detect {|cb| cb.version == "2.0.0"}.should_not == nil
268+
res["god"].detect {|cb| cb.version == "4.2.0"}.should_not == nil
269+
end
270+
271+
it "should return all versions of a cookbook that meet the version requirement" do
272+
@environment.cookbook "apt", ">= 1.0.0"
273+
res = Chef::Environment.cdb_load_filtered_cookbook_versions("prod")
274+
res["apt"].detect {|cb| cb.version == "1.0.0"}.should_not == nil
275+
res["apt"].detect {|cb| cb.version == "1.1.0"}.should_not == nil
269276
end
270277
end
271278

0 commit comments

Comments
 (0)