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

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/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
-