chef-server-api 0.9.18 → 0.10.0.beta.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -15,7 +15,6 @@ chef:
15
15
  * ruby-openid
16
16
  * json
17
17
  * erubis
18
- * extlib
19
18
  * stomp
20
19
  * ohai
21
20
 
@@ -45,7 +45,7 @@ class Application < Merb::Controller
45
45
  authenticator.authenticate_request(user_key)
46
46
  rescue Mixlib::Authentication::MissingAuthenticationHeader => e
47
47
  Chef::Log.debug "Authentication failed: #{e.class.name}: #{e.message}\n#{e.backtrace.join("\n")}"
48
- raise Unauthorized, "#{e.class.name}: #{e.message}"
48
+ raise BadRequest, "#{e.class.name}: #{e.message}"
49
49
  rescue StandardError => se
50
50
  Chef::Log.debug "Authentication failed: #{se}, #{se.backtrace.join("\n")}"
51
51
  raise Unauthorized, "Failed to authenticate. Ensure that your client key is valid."
@@ -9,9 +9,9 @@
9
9
  # Licensed under the Apache License, Version 2.0 (the "License");
10
10
  # you may not use this file except in compliance with the License.
11
11
  # You may obtain a copy of the License at
12
- #
12
+ #
13
13
  # http://www.apache.org/licenses/LICENSE-2.0
14
- #
14
+ #
15
15
  # Unless required by applicable law or agreed to in writing, software
16
16
  # distributed under the License is distributed on an "AS IS" BASIS,
17
17
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -23,15 +23,16 @@ require 'chef/cookbook_loader'
23
23
  require 'chef/cookbook/metadata'
24
24
 
25
25
  class Cookbooks < Application
26
-
26
+
27
+ include Merb::CookbookVersionHelper
28
+
27
29
  provides :json
28
30
 
29
31
  before :authenticate_every
30
32
  before :params_helper
31
- before :is_admin, :only => [ :update, :destroy ]
32
33
 
33
34
  attr_accessor :cookbook_name, :cookbook_version
34
-
35
+
35
36
  def params_helper
36
37
  self.cookbook_name = params[:cookbook_name]
37
38
  self.cookbook_version = params[:cookbook_version]
@@ -39,39 +40,47 @@ class Cookbooks < Application
39
40
 
40
41
  include Chef::Mixin::Checksum
41
42
  include Merb::TarballHelper
42
-
43
- def index
44
- cookbook_list = Chef::CookbookVersion.cdb_list_latest.keys.sort
45
- response = Hash.new
46
- cookbook_list.map! do |cookbook_name|
47
- response[cookbook_name] = absolute_url(:cookbook, :cookbook_name => cookbook_name)
48
- end
49
- display response
50
- end
51
43
 
52
- def index_latest
53
- cookbook_list = Chef::CookbookVersion.cdb_list_latest(true)
54
- response = cookbook_list.inject({}) do |res, cv|
55
- res[cv.name] = absolute_url(:cookbook_version, :cookbook_name => cv.name, :cookbook_version => cv.version)
44
+ # returns data in the format of:
45
+ # {"apache2" => {
46
+ # :url => "http://url",
47
+ # :versions => [{:url => "http://url/1.0.0", :version => "1.0.0"}, {:url => "http://url/0.0.1", :version=>"0.0.1"}]
48
+ # }
49
+ # }
50
+ def index
51
+ cookbook_list = Chef::CookbookVersion.cdb_list
52
+ # cookbook_list is in the format of {"apache2" => [0.0.1, 0.0.0]} where the version numbers are DepSelector::Version objects
53
+ num_versions = num_versions!
54
+ display(cookbook_list.inject({}) {|res, (cookbook_name, versions)|
55
+ versions = versions.map{ |x| DepSelector::Version.new(x) }.sort.reverse.map{ |x| x.to_s }
56
+ res[cookbook_name] = expand_cookbook_urls(cookbook_name, versions, num_versions)
56
57
  res
57
- end
58
- display response
58
+ })
59
59
  end
60
60
 
61
61
  def index_recipes
62
- all_cookbooks = Array(Chef::CookbookVersion.cdb_list_latest(true))
63
- all_cookbooks.map! do |cookbook|
64
- cookbook.manifest["recipes"].map { |r| "#{cookbook.name}::#{File.basename(r['name'], ".rb")}" }
62
+ recipes_with_versions = Chef::CookbookVersion.cdb_list(true).inject({}) do|memo, f|
63
+ memo[f.name] ||= {}
64
+ memo[f.name][f.version] = f.recipe_filenames_by_name.keys
65
+ memo
65
66
  end
66
- all_cookbooks.flatten!
67
- all_cookbooks.sort!
68
- display all_cookbooks
67
+ display recipes_with_versions
69
68
  end
70
69
 
70
+ # GET /cookbooks/:cookbook_name
71
+ #
72
+ # returns data in the format of:
73
+ # {"apache2" => {
74
+ # :url => "http://url",
75
+ # :versions => [{:url => "http://url/1.0.0", :version => "1.0.0"}, {:url => "http://url/0.0.1", :version=>"0.0.1"}]
76
+ # }
77
+ # }
71
78
  def show_versions
72
79
  versions = Chef::CookbookVersion.cdb_by_name(cookbook_name)
73
80
  raise NotFound, "Cannot find a cookbook named #{cookbook_name}" unless versions && versions.size > 0
74
- display versions
81
+ num_versions = num_versions!("all")
82
+ cb_versions = versions[cookbook_name].map{ |x| DepSelector::Version.new(x) }.sort.reverse.map{ |x| x.to_s }
83
+ display({ cookbook_name => expand_cookbook_urls(cookbook_name, cb_versions, num_versions) })
75
84
  end
76
85
 
77
86
  def show
@@ -81,7 +90,7 @@ class Cookbooks < Application
81
90
 
82
91
  def show_file
83
92
  cookbook = get_cookbook_version(cookbook_name, cookbook_version)
84
-
93
+
85
94
  checksum = params[:checksum]
86
95
  raise NotFound, "Cookbook #{cookbook_name} version #{cookbook_version} does not contain a file with checksum #{checksum}" unless cookbook.checksums.keys.include?(checksum)
87
96
 
@@ -99,9 +108,9 @@ class Cookbooks < Application
99
108
  end
100
109
 
101
110
  unless params["inflated_object"].version == cookbook_version
102
- raise(BadRequest, "You said the cookbook was version #{params['inflated_object'].version}, but the URL says it should be #{cookbook_version}.")
111
+ raise(BadRequest, "You said the cookbook was version #{params['inflated_object'].version}, but the URL says it should be #{cookbook_version}.")
103
112
  end
104
-
113
+
105
114
  begin
106
115
  cookbook = Chef::CookbookVersion.cdb_load(cookbook_name, cookbook_version)
107
116
  cookbook.manifest = params['inflated_object'].manifest
@@ -109,29 +118,35 @@ class Cookbooks < Application
109
118
  Chef::Log.debug("Cookbook #{cookbook_name} version #{cookbook_version} does not exist")
110
119
  cookbook = params['inflated_object']
111
120
  end
112
-
121
+
122
+ if cookbook.frozen_version? && params[:force].nil?
123
+ raise Conflict, "The cookbook #{cookbook.name} at version #{cookbook.version} is frozen. Use the 'force' option to override."
124
+ end
125
+
126
+ cookbook.freeze_version if params["inflated_object"].frozen_version?
127
+
113
128
  # ensure that all checksums referred to by the manifest have been uploaded.
114
129
  Chef::CookbookVersion::COOKBOOK_SEGMENTS.each do |segment|
115
130
  next unless cookbook.manifest[segment]
116
131
  cookbook.manifest[segment].each do |manifest_record|
117
132
  checksum = manifest_record[:checksum]
118
133
  path = manifest_record[:path]
119
-
134
+
120
135
  begin
121
136
  checksum_obj = Chef::Checksum.cdb_load(checksum)
122
137
  rescue Chef::Exceptions::CouchDBNotFound => cdbx
123
138
  checksum_obj = nil
124
139
  end
125
-
140
+
126
141
  raise BadRequest, "Manifest has checksum #{checksum} (path #{path}) but it hasn't yet been uploaded" unless checksum_obj
127
142
  end
128
143
  end
129
-
144
+
130
145
  raise InternalServerError, "Error saving cookbook" unless cookbook.cdb_save
131
146
 
132
147
  display cookbook
133
148
  end
134
-
149
+
135
150
  def destroy
136
151
  begin
137
152
  cookbook = get_cookbook_version(cookbook_name, cookbook_version)
@@ -159,6 +174,6 @@ class Cookbooks < Application
159
174
  raise
160
175
  end
161
176
  end
162
-
177
+
163
178
  end
164
179
 
@@ -0,0 +1,207 @@
1
+ #
2
+ # Author:: Stephen Delano (<stephen@opscode.com>)
3
+ # Author:: Tim Hinderliter (<tim@opscode.com>)
4
+ # Copyright:: Copyright (c) 2010, 2011 Opscode, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require 'chef/environment'
21
+ require 'chef/cookbook_version_selector'
22
+
23
+ class Environments < Application
24
+
25
+ include Merb::CookbookVersionHelper
26
+
27
+ provides :json
28
+
29
+ before :authenticate_every
30
+ before :is_admin, :only => [ :create, :update, :destroy ]
31
+
32
+ # GET /environments
33
+ def index
34
+ environment_list = Chef::Environment.cdb_list(true)
35
+ display(environment_list.inject({}) { |res, env| res[env.name] = absolute_url(:environment, env.name); res })
36
+ end
37
+
38
+ # GET /environments/:id
39
+ def show
40
+ begin
41
+ environment = Chef::Environment.cdb_load(params[:id])
42
+ rescue Chef::Exceptions::CouchDBNotFound => e
43
+ raise NotFound, "Cannot load environment #{params[:id]}"
44
+ end
45
+ environment.couchdb_rev = nil
46
+ display environment
47
+ end
48
+
49
+ # POST /environments
50
+ def create
51
+ env = params["inflated_object"]
52
+ exists = true
53
+ begin
54
+ Chef::Environment.cdb_load(env.name)
55
+ rescue Chef::Exceptions::CouchDBNotFound
56
+ exists = false
57
+ end
58
+ raise Conflict, "Environment already exists" if exists
59
+
60
+ env.cdb_save
61
+ self.status = 201
62
+ display({:uri => absolute_url(:environment, env.name)})
63
+ end
64
+
65
+ # PUT /environments/:id
66
+ def update
67
+ raise MethodNotAllowed if params[:id] == "_default"
68
+ begin
69
+ env = Chef::Environment.cdb_load(params[:id])
70
+ rescue Chef::Exceptions::CouchDBNotFound
71
+ raise NotFound, "Cannot load environment #{params[:id]}"
72
+ end
73
+
74
+ env.update_from!(params["inflated_object"])
75
+ env.cdb_save
76
+ env.couchdb_rev = nil
77
+ self.status = 200
78
+ display(env)
79
+ end
80
+
81
+ # DELETE /environments/:id
82
+ def destroy
83
+ raise MethodNotAllowed if params[:id] == "_default"
84
+ begin
85
+ env = Chef::Environment.cdb_load(params[:id])
86
+ rescue Chef::Exceptions::CouchDBNotFound
87
+ raise NotFound, "Cannot load environment #{params[:id]}"
88
+ end
89
+ env.cdb_destroy
90
+ display(env)
91
+ end
92
+
93
+ # GET /environments/:environment_id/cookbooks
94
+ # returns data in the format of:
95
+ # {"apache2" => {
96
+ # :url => "http://url",
97
+ # :versions => [{:url => "http://url/1.0.0", :version => "1.0.0"}, {:url => "http://url/0.0.1", :version=>"0.0.1"}]
98
+ # }
99
+ # }
100
+ def list_cookbooks
101
+ begin
102
+ filtered_cookbooks = Chef::Environment.cdb_load_filtered_cookbook_versions(params[:environment_id])
103
+ rescue Chef::Exceptions::CouchDBNotFound
104
+ raise NotFound, "Cannot load environment #{params[:environment_id]}"
105
+ end
106
+ num_versions = num_versions!
107
+ display(filtered_cookbooks.inject({}) {|res, (cookbook_name,versions)|
108
+ versions.map!{|v| v.version.to_s}
109
+ res[cookbook_name] = expand_cookbook_urls(cookbook_name, versions, num_versions)
110
+ res
111
+ })
112
+ end
113
+
114
+ # GET /environments/:environment_id/cookbooks/:cookbook_id
115
+ # returns data in the format of:
116
+ # {"apache2" => {
117
+ # :url => "http://url",
118
+ # :versions => [{:url => "http://url/1.0.0", :version => "1.0.0"}, {:url => "http://url/0.0.1", :version=>"0.0.1"}]
119
+ # }
120
+ # }
121
+ def cookbook
122
+ cookbook_name = params[:cookbook_id]
123
+ begin
124
+ filtered_cookbooks = Chef::Environment.cdb_load_filtered_cookbook_versions(params[:environment_id])
125
+ rescue Chef::Exceptions::CouchDBNotFound
126
+ raise NotFound, "Cannot load environment #{params[:environment_id]}"
127
+ end
128
+ raise NotFound, "Cannot load cookbook #{cookbook_name}" unless filtered_cookbooks.has_key?(cookbook_name)
129
+ versions = filtered_cookbooks[cookbook_name].map{|v| v.version.to_s}
130
+ num_versions = num_versions!("all")
131
+ display({ cookbook_name => expand_cookbook_urls(cookbook_name, versions, num_versions) })
132
+ end
133
+
134
+ # GET /environments/:environment/recipes
135
+ def list_recipes
136
+ display(Chef::Environment.cdb_load_filtered_recipe_list(params[:environment_id]))
137
+ end
138
+
139
+ # GET /environments/:environment_id/nodes
140
+ def list_nodes
141
+ node_list = Chef::Node.cdb_list_by_environment(params[:environment_id])
142
+ display(node_list.inject({}) {|r,n| r[n] = absolute_url(:node, n); r})
143
+ end
144
+
145
+ # GET /environments/:environment_id/roles/:role_id
146
+ def role
147
+ begin
148
+ role = Chef::Role.cdb_load(params[:role_id])
149
+ rescue Chef::Exceptions::CouchDBNotFound
150
+ raise NotFound, "Cannot load role #{params[:role_id]}"
151
+ end
152
+ display("run_list" => role.env_run_lists[params[:environment_id]])
153
+ end
154
+
155
+ # POST /environments/:environment_id/cookbook_versions
156
+ #
157
+ # Take the given run_list and return the versions of cookbooks that would
158
+ # be used after applying the constraints of the given environment.
159
+ #
160
+ # INPUT:
161
+ # :run_list = an Array of String's, e.g.,
162
+ # ["recipe[apache2]", "recipe[runit]"]
163
+ #
164
+ # OUT:
165
+ # Hash of cookbook names cookbook manifest
166
+ #
167
+ # NOTE: This method is a POST, not because it's a mutator (it's idempotent),
168
+ # but the run_list can likely exceed Merb's query string limit for GET
169
+ # of 1024 characters.
170
+ def cookbook_versions_for_run_list
171
+ begin
172
+ # not possible to be nil due to the route to get us to this API
173
+ # endpoint
174
+ environment_input = params[:environment_id]
175
+
176
+ run_list_input = params[:run_list]
177
+ raise BadRequest, "Missing param: run_list" unless run_list_input
178
+ raise BadRequest, "Param run_list is not an Array: #{run_list_input.class}" unless run_list_input.is_a?(Array)
179
+
180
+ # Convert the input array of strings to a RunList containing
181
+ # RunListItem's.
182
+ run_list = Chef::RunList.new
183
+ run_list_input.each do |run_list_item_string|
184
+ run_list << run_list_item_string
185
+ end
186
+
187
+ # Expand the run list in the scope of the specified environment.
188
+ names_to_cookbook_version = Chef::CookbookVersionSelector.expand_to_cookbook_versions(run_list, environment_input)
189
+ rescue Chef::Exceptions::CouchDBNotFound
190
+ raise NotFound, "Cannot load environment #{params[:environment_id]}"
191
+ rescue Chef::Exceptions::CookbookVersionSelection::InvalidRunListItems => e
192
+ raise PreconditionFailed, e.to_json
193
+ rescue Chef::Exceptions::CookbookVersionSelection::UnsatisfiableRunListItem => e
194
+ raise PreconditionFailed, e.to_json
195
+ end
196
+
197
+ # Convert from
198
+ # name => CookbookVersion
199
+ # to
200
+ # name => cookbook manifest
201
+ # and display.
202
+ display(names_to_cookbook_version.inject({}) do |res, (cookbook_name, cookbook_version)|
203
+ res[cookbook_name] = cookbook_version.generate_manifest_with_urls {|opts| absolute_url(:cookbook_file, opts) }
204
+ res
205
+ end)
206
+ end
207
+ end
@@ -1,18 +1,25 @@
1
1
  class Main < Application
2
2
 
3
- before :authenticate_every
4
3
  provides :html, :json
5
4
 
6
5
  def index
7
- display(
8
- {
9
- absolute_url(:nodes) => "Manage Nodes",
10
- absolute_url(:roles) => "Manage Roles",
11
- absolute_url(:cookbooks) => "Manage Cookbooks",
12
- absolute_url(:data) => "Manage Data Bags",
13
- absolute_url(:search) => "Search"
14
- }
15
- )
6
+ case content_type
7
+ when :json
8
+ display absolute_url(:nodes) => "Manage Nodes",
9
+ absolute_url(:roles) => "Manage Roles",
10
+ absolute_url(:cookbooks) => "Manage Cookbooks",
11
+ absolute_url(:data) => "Manage Data Bags",
12
+ absolute_url(:search) => "Search"
13
+ else
14
+ @webui_url = if Chef::Config[:chef_webui_url]
15
+ Chef::Config[:chef_webui_url]
16
+ elsif request.host =~ /(.*):4000/
17
+ absolute_url(:top, :host => "#{$1}:4040")
18
+ else
19
+ nil
20
+ end
21
+ render
22
+ end
16
23
  end
17
24
 
18
25
  end
@@ -7,9 +7,9 @@
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
8
8
  # you may not use this file except in compliance with the License.
9
9
  # You may obtain a copy of the License at
10
- #
10
+ #
11
11
  # http://www.apache.org/licenses/LICENSE-2.0
12
- #
12
+ #
13
13
  # Unless required by applicable law or agreed to in writing, software
14
14
  # distributed under the License is distributed on an "AS IS" BASIS,
15
15
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,17 +17,20 @@
17
17
  # limitations under the License.
18
18
  #
19
19
 
20
- require 'chef' / 'node'
20
+ require 'chef/node'
21
+ require 'chef/version_class'
22
+ require 'chef/version_constraint'
23
+ require 'chef/cookbook_version_selector'
21
24
 
22
25
  class Nodes < Application
23
-
26
+
24
27
  provides :json
25
-
26
- before :authenticate_every
28
+
29
+ before :authenticate_every
27
30
  before :admin_or_requesting_node, :only => [ :update, :destroy, :cookbooks ]
28
-
31
+
29
32
  def index
30
- @node_list = Chef::Node.cdb_list
33
+ @node_list = Chef::Node.cdb_list
31
34
  display(@node_list.inject({}) do |r,n|
32
35
  r[n] = absolute_url(:node, n); r
33
36
  end)
@@ -46,7 +49,7 @@ class Nodes < Application
46
49
  def create
47
50
  @node = params["inflated_object"]
48
51
  begin
49
- Chef::Node.cdb_load(@node.name)
52
+ Chef::Node.cdb_load(@node.name)
50
53
  raise Conflict, "Node already exists"
51
54
  rescue Chef::Exceptions::CouchDBNotFound
52
55
  end
@@ -62,12 +65,7 @@ class Nodes < Application
62
65
  raise NotFound, "Cannot load node #{params[:id]}"
63
66
  end
64
67
 
65
- updated = params['inflated_object']
66
- @node.run_list.reset!(updated.run_list)
67
- @node.automatic_attrs = updated.automatic_attrs
68
- @node.normal_attrs = updated.normal_attrs
69
- @node.override_attrs = updated.override_attrs
70
- @node.default_attrs = updated.default_attrs
68
+ @node.update_from!(params['inflated_object'])
71
69
  @node.cdb_save
72
70
  @node.couchdb_rev = nil
73
71
  display(@node)
@@ -76,7 +74,7 @@ class Nodes < Application
76
74
  def destroy
77
75
  begin
78
76
  @node = Chef::Node.cdb_load(params[:id])
79
- rescue Chef::Exceptions::CouchDBNotFound => e
77
+ rescue Chef::Exceptions::CouchDBNotFound => e
80
78
  raise NotFound, "Cannot load node #{params[:id]}"
81
79
  end
82
80
  @node.cdb_destroy
@@ -84,86 +82,34 @@ class Nodes < Application
84
82
  display @node
85
83
  end
86
84
 
85
+ # Return a hash, cookbook_name => cookbook manifest, of the cookbooks
86
+ # appropriate for this node, using its run_list and environment.
87
87
  def cookbooks
88
88
  begin
89
89
  @node = Chef::Node.cdb_load(params[:id])
90
- rescue Chef::Exceptions::CouchDBNotFound => e
90
+ rescue Chef::Exceptions::CouchDBNotFound => e
91
91
  raise NotFound, "Cannot load node #{params[:id]}"
92
92
  end
93
93
 
94
- display(load_all_files(params[:id]))
95
- end
96
-
97
- private
98
-
99
- def load_all_files(node_name)
100
- all_cookbooks = Chef::CookbookVersion.cdb_list(true).inject({}) do |res, cookbook|
101
- version = Gem::Version.new cookbook.version
102
- newest_version = res.has_key?(cookbook.name) ? version > Gem::Version.new(res[cookbook.name].version) : true
103
- res[cookbook.name] = cookbook if newest_version
104
- res
105
- end
106
-
107
- included_cookbooks = cookbooks_for_node(node_name, all_cookbooks)
108
- nodes_cookbooks = Hash.new
109
- included_cookbooks.each do |cookbook_name, cookbook|
110
- next unless cookbook
111
-
112
- nodes_cookbooks[cookbook_name.to_s] = cookbook.generate_manifest_with_urls{|opts| absolute_url(:cookbook_file, opts) }
113
- end
114
-
115
- nodes_cookbooks
116
- end
117
-
118
- # returns name -> CookbookVersion for all cookbooks included on the given node.
119
- def cookbooks_for_node(node_name, all_cookbooks)
120
- # get node's explicit dependencies
121
- node = Chef::Node.cdb_load(node_name)
122
-
123
- # expand returns a RunListExpansion which contains recipes, default and override attrs [cb]
124
- recipes = node.run_list.expand('couchdb').recipes
125
-
126
- # walk run list and accumulate included dependencies
127
- recipes.inject({}) do |included_cookbooks, recipe|
128
- expand_cookbook_deps(included_cookbooks, all_cookbooks, recipe)
129
- included_cookbooks
130
- end
131
- end
132
-
133
- # Accumulates transitive cookbook dependencies no more than once in included_cookbooks
134
- # included_cookbooks == hash of name -> CookbookVersion, which is used for returning
135
- # result as well as for tracking which cookbooks we've already
136
- # recursed into
137
- # all_cookbooks == hash of name -> CookbookVersion, all cookbooks available
138
- # run_list_items == name of cookbook to include
139
- def expand_cookbook_deps(included_cookbooks, all_cookbooks, run_list_item)
140
- # determine the run list item's parent cookbook, which might be run_list_item in the default case
141
- cookbook_name = (run_list_item[/^(.+)::/, 1] || run_list_item.to_s)
142
- Chef::Log.debug("Node requires #{cookbook_name}")
143
-
144
- # include its dependencies
145
- included_cookbooks[cookbook_name] = all_cookbooks[cookbook_name]
146
- if !all_cookbooks[cookbook_name]
147
- return false
148
- # NOTE [dan/cw] We don't think changing this to an exception breaks stuff.
149
- # Chef::Log.warn "#{__FILE__}:#{__LINE__}: in expand_cookbook_deps, cookbook/role #{cookbook_name} could not be found, ignoring it in cookbook expansion"
150
- # return included_cookbooks
94
+ # Get the mapping of cookbook_name => CookbookVersion applicable to
95
+ # this node's run_list and its environment.
96
+ begin
97
+ included_cookbooks = Chef::CookbookVersionSelector.expand_to_cookbook_versions(@node.run_list, @node.chef_environment)
98
+ rescue Chef::Exceptions::CookbookVersionSelection::InvalidRunListItems => e
99
+ raise PreconditionFailed, e.to_json
100
+ rescue Chef::Exceptions::CookbookVersionSelection::UnsatisfiableRunListItem => e
101
+ raise PreconditionFailed, e.to_json
151
102
  end
152
103
 
153
- # TODO: 5/27/2010 cw: implement dep_version_constraints according to
154
- # http://wiki.opscode.com/display/chef/Metadata#Metadata-depends,
155
- all_cookbooks[cookbook_name].metadata.dependencies.each do |depname, dep_version_constraints|
156
- # recursively expand dependencies into included_cookbooks unless
157
- # we've already done it
158
- unless included_cookbooks[depname]
159
- unless expand_cookbook_deps(included_cookbooks, all_cookbooks, depname)
160
- raise PreconditionFailed, "cookbook #{cookbook_name} depends on cookbook #{depname}, but #{depname} does not exist"
161
-
162
- end
163
- end
164
- end
165
- true
104
+ # Convert from
105
+ # name => CookbookVersion
106
+ # to
107
+ # name => cookbook manifest
108
+ # and display.
109
+ display(included_cookbooks.inject({}) do |acc, (cookbook_name, cookbook_version)|
110
+ acc[cookbook_name.to_s] = cookbook_version.generate_manifest_with_urls{|opts| absolute_url(:cookbook_file, opts) }
111
+ acc
112
+ end)
166
113
  end
167
114
 
168
115
  end
169
-