chef-server-webui 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.
Files changed (68) hide show
  1. data/README.rdoc +0 -4
  2. data/Rakefile +10 -0
  3. data/app/controllers/application.rb +34 -6
  4. data/app/controllers/cookbooks.rb +125 -35
  5. data/app/controllers/environments.rb +235 -0
  6. data/app/controllers/nodes.rb +26 -19
  7. data/app/controllers/roles.rb +37 -44
  8. data/app/controllers/search.rb +13 -13
  9. data/app/helpers/application_helper.rb +34 -0
  10. data/app/views/cookbooks/_cookbook_content.html.haml +7 -0
  11. data/app/views/cookbooks/index.html.haml +22 -7
  12. data/app/views/cookbooks/show.html.haml +8 -50
  13. data/app/views/environments/_form.html.erb +91 -0
  14. data/app/views/environments/_navigation.html.haml +9 -0
  15. data/app/views/environments/_version_selector.html.erb +8 -0
  16. data/app/views/environments/edit.html.erb +17 -0
  17. data/app/views/environments/index.html.haml +26 -0
  18. data/app/views/environments/new.html.erb +17 -0
  19. data/app/views/environments/show.html.haml +31 -0
  20. data/app/views/layout/application.html.haml +22 -13
  21. data/app/views/layout/login.html.haml +2 -2
  22. data/app/views/nodes/_form.html.erb +69 -0
  23. data/app/views/nodes/index.html.haml +6 -2
  24. data/app/views/nodes/show.html.haml +4 -1
  25. data/app/views/roles/_form.html.erb +92 -0
  26. data/app/views/roles/_run_lists.html.erb +26 -0
  27. data/app/views/roles/edit.html.haml +1 -1
  28. data/app/views/roles/new.html.haml +1 -1
  29. data/app/views/roles/show.html.haml +10 -7
  30. data/app/views/status/index.html.haml +2 -1
  31. data/bin/chef-server-webui +1 -0
  32. data/config/router.rb +14 -8
  33. data/lib/chef-server-webui/version.rb +1 -1
  34. data/public/javascripts/chef.js +206 -49
  35. data/public/javascripts/cookbook_constraint_ctrl.js +191 -0
  36. data/public/javascripts/cookbook_versions.js +75 -0
  37. data/public/javascripts/jquery-1.4.4.min.js +167 -0
  38. data/public/javascripts/jquery.suggest.js +250 -0
  39. data/public/stylesheets/base.css +30 -24
  40. data/public/stylesheets/chef.css +212 -45
  41. data/public/stylesheets/jquery.suggest.css +28 -0
  42. data/public/stylesheets/jsonedit_main.css +26 -10
  43. data/public/stylesheets/themes/djime-cerulean/style.css +31 -18
  44. metadata +22 -29
  45. data/app/controllers/cookbook_attributes.rb +0 -41
  46. data/app/controllers/cookbook_definitions.rb +0 -41
  47. data/app/controllers/cookbook_files.rb +0 -39
  48. data/app/controllers/cookbook_libraries.rb +0 -41
  49. data/app/controllers/cookbook_recipes.rb +0 -40
  50. data/app/controllers/cookbook_templates.rb +0 -57
  51. data/app/helpers/cookbook_attributes_helper.rb +0 -7
  52. data/app/helpers/cookbook_definitions_helper.rb +0 -8
  53. data/app/helpers/cookbook_files_helper.rb +0 -8
  54. data/app/helpers/cookbook_libraries_helper.rb +0 -7
  55. data/app/helpers/cookbook_recipes_helper.rb +0 -8
  56. data/app/helpers/cookbook_templates_helper.rb +0 -8
  57. data/app/helpers/exceptions_helper.rb +0 -6
  58. data/app/helpers/global_helpers.rb +0 -39
  59. data/app/helpers/nodes_helper.rb +0 -43
  60. data/app/helpers/openid_consumer_helper.rb +0 -8
  61. data/app/helpers/openid_register_helper.rb +0 -8
  62. data/app/helpers/openid_server_helper.rb +0 -6
  63. data/app/helpers/openid_server_helpers.rb +0 -32
  64. data/app/helpers/roles_helper.rb +0 -5
  65. data/app/helpers/search_entries_helper.rb +0 -8
  66. data/app/helpers/search_helper.rb +0 -44
  67. data/app/views/nodes/_form.html.haml +0 -52
  68. data/app/views/roles/_form.html.haml +0 -52
data/README.rdoc CHANGED
@@ -34,8 +34,6 @@ Install these via your platform's preferred method; for example apt, yum, ports,
34
34
 
35
35
  * Git
36
36
  * CouchDB
37
- * libxml2 development package (for webrat)
38
- * libxslt develoment package (for webrat)
39
37
 
40
38
  Install the following RubyGems.
41
39
 
@@ -43,9 +41,7 @@ Install the following RubyGems.
43
41
  * rake
44
42
  * rspec
45
43
  * cucumber
46
- * webrat
47
44
  * merb-core
48
- * roman-merb_cucumber
49
45
 
50
46
  Ohai is also by Opscode and available on GitHub, http://github.com/opscode/ohai/tree/master.
51
47
 
data/Rakefile CHANGED
@@ -39,3 +39,13 @@ task :gemspec do
39
39
  end
40
40
  end
41
41
 
42
+ desc "Create a new Balsamiq Mockups project"
43
+ task :new_mockup, :name do |t, args|
44
+ if args[:name].nil?
45
+ puts "You must supply a name for your mockups project directory: `rake new_mockup[project-name]`"
46
+ exit
47
+ end
48
+ src = "mockups/base-mockup/."
49
+ dest = "mockups/#{args[:name]}"
50
+ FileUtils.cp_r src, dest
51
+ end
@@ -25,6 +25,8 @@ class Application < Merb::Controller
25
25
 
26
26
  include Chef::Mixin::Checksum
27
27
 
28
+ before :load_environments
29
+
28
30
  # Check if the user is logged in and if the user still exists
29
31
  def login_required
30
32
  if session[:user]
@@ -48,7 +50,7 @@ class Application < Merb::Controller
48
50
  end
49
51
 
50
52
  def cleanup_session
51
- [:user,:level].each { |n| session.delete(n) }
53
+ [:user,:level, :environment].each { |n| session.delete(n) }
52
54
  end
53
55
 
54
56
  def logout_and_redirect_to_login
@@ -111,6 +113,10 @@ class Application < Merb::Controller
111
113
  end
112
114
  end
113
115
 
116
+ def load_environments
117
+ @environments = Chef::Environment.list.keys.sort
118
+ end
119
+
114
120
  # Load a cookbook and return a hash with a list of all the files of a
115
121
  # given segment (attributes, recipes, definitions, libraries)
116
122
  #
@@ -169,9 +175,9 @@ class Application < Merb::Controller
169
175
  def append_tree(name, html, node, count, parent)
170
176
  to_do = node
171
177
  #to_do = node.kind_of?(Chef::Node) ? node.attribute : node
172
- Chef::Log.error("I have #{to_do.inspect}")
178
+ Chef::Log.debug("I have #{to_do.inspect}")
173
179
  to_do.sort{ |a,b| a[0] <=> b[0] }.each do |key, value|
174
- Chef::Log.error("I am #{key.inspect} #{value.inspect}")
180
+ Chef::Log.debug("I am #{key.inspect} #{value.inspect}")
175
181
  to_send = Array.new
176
182
  count += 1
177
183
  is_parent = false
@@ -253,13 +259,35 @@ class Application < Merb::Controller
253
259
  end
254
260
  end
255
261
 
256
- def get_available_recipes
257
- r = Chef::REST.new(Chef::Config[:chef_server_url])
258
- r.get_rest('cookbooks/_recipes')
262
+ def list_available_recipes_for(environment)
263
+ Chef::Environment.load_filtered_recipe_list(environment)
259
264
  end
260
265
 
261
266
  def convert_newline_to_br(string)
262
267
  string.to_s.gsub(/\n/, '<br />') unless string.nil?
263
268
  end
264
269
 
270
+ def format_exception(exception)
271
+ require 'pp'
272
+ pretty_params = StringIO.new
273
+ PP.pp({:request_params => params}, pretty_params)
274
+ "#{exception.class.name}: #{exception.message}\n#{pretty_params.string}\n#{exception.backtrace.join("\n")}"
275
+ end
276
+
277
+ def conflict?(exception)
278
+ exception.kind_of?(Net::HTTPServerException) && exception.message =~ /409/
279
+ end
280
+
281
+ def forbidden?(exception)
282
+ exception.kind_of?(Net::HTTPServerException) && exception.message =~ /403/
283
+ end
284
+
285
+ def not_found?(exception)
286
+ exception.kind_of?(Net::HTTPServerException) && exception.message =~ /404/
287
+ end
288
+
289
+ def bad_request?(exception)
290
+ exception.kind_of?(Net::HTTPServerException) && exception.message =~ /400/
291
+ end
292
+
265
293
  end
@@ -2,15 +2,16 @@
2
2
  # Author:: Adam Jacob (<adam@opscode.com>)
3
3
  # Author:: Christopher Brown (<cb@opscode.com>)
4
4
  # Author:: Nuo Yan (<nuo@opscode.com>)
5
- # Copyright:: Copyright (c) 2008 Opscode, Inc.
5
+ # Author:: Seth Falcon (<seth@opscode.com>)
6
+ # Copyright:: Copyright (c) 2008-2011 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.
@@ -22,44 +23,44 @@ require 'chef/cookbook_loader'
22
23
  require 'chef/cookbook_version'
23
24
 
24
25
  class Cookbooks < Application
25
-
26
+
26
27
  provides :html
27
28
  before :login_required
28
29
  before :params_helper
29
-
30
+
30
31
  attr_reader :cookbook_id
31
32
  def params_helper
32
33
  @cookbook_id = params[:id] || params[:cookbook_id]
33
34
  end
34
-
35
+
35
36
  def index
36
- @cl = begin
37
- Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("cookbooks")
38
- rescue => e
39
- Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}")
40
- @_message = {:error => $!}
41
- {}
42
- end
43
- render
37
+ @cl = fetch_cookbook_versions(6)
38
+ display @cl
44
39
  end
45
40
 
46
41
  def show
47
42
  begin
48
- # array of versions, sorted from large to small e.g. ["0.20.0", "0.1.0"]
49
- versions = Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("cookbooks/#{cookbook_id}")[cookbook_id].sort!{|x,y| y <=> x }
50
- # if version is not specified in the url, get the most recent version, otherwise get the specified version
51
- version = if params[:cb_version].nil? || params[:cb_version].empty?
52
- versions.first
53
- else
54
- params[:cb_version]
55
- end
56
-
57
- @cookbook = Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("cookbooks/#{cookbook_id}/#{version}")
58
-
59
- # by default always show the largest version number (assuming largest means most recent)
60
- @other_versions = versions - [version]
43
+ all_books = fetch_cookbook_versions("all", :cookbook => cookbook_id)
44
+ @versions = all_books[cookbook_id].map { |v| v["version"] }
45
+ if params[:cb_version] == "_latest"
46
+ redirect(url(:show_specific_version_cookbook,
47
+ :cookbook_id => cookbook_id,
48
+ :cb_version => @versions.first))
49
+ return
50
+ end
51
+ @version = params[:cb_version]
52
+ if !@versions.include?(@version)
53
+ msg = { :warning => ["Cookbook #{cookbook_id} (#{params[:cb_version]})",
54
+ "is not available in the #{session[:environment]}",
55
+ "environment."
56
+ ].join(" ") }
57
+ redirect(url(:cookbooks), :message => msg)
58
+ return
59
+ end
60
+ cookbook_url = "cookbooks/#{cookbook_id}/#{@version}"
61
+ rest = Chef::REST.new(Chef::Config[:chef_server_url])
62
+ @cookbook = rest.get_rest(cookbook_url)
61
63
  raise NotFound unless @cookbook
62
-
63
64
  @manifest = @cookbook.manifest
64
65
  display @cookbook
65
66
  rescue => e
@@ -67,14 +68,31 @@ class Cookbooks < Application
67
68
  @_message = {:error => $!}
68
69
  @cl = {}
69
70
  render :index
70
- end
71
+ end
72
+ end
73
+
74
+ # GET /cookbooks/cookbook_id
75
+ # provides :json, for the javascript on the environments web form.
76
+ def cb_versions
77
+ provides :json
78
+ use_envs = session[:environment] && !params[:ignore_environments]
79
+ num_versions = params[:num_versions] || "all"
80
+ all_books = fetch_cookbook_versions(num_versions, :cookbook => cookbook_id,
81
+ :use_envs => use_envs)
82
+ display({ cookbook_id => all_books[cookbook_id] })
71
83
  end
72
-
84
+
85
+ ## ------
86
+ ## Helpers
87
+ ##
88
+ ## TODO: move these to a cookbooks helper module
89
+ ## ------
90
+
73
91
  def recipe_files
74
- # node = params.has_key?('node') ? params[:node] : nil
92
+ # node = params.has_key?('node') ? params[:node] : nil
75
93
  # @recipe_files = load_all_files(:recipes, node)
76
94
  r = Chef::REST.new(Chef::Config[:chef_server_url])
77
- @recipe_files = r.get_rest("cookbooks/#{params[:id]}/recipes")
95
+ @recipe_files = r.get_rest("cookbooks/#{params[:id]}/recipes")
78
96
  display @recipe_files
79
97
  end
80
98
 
@@ -83,17 +101,89 @@ class Cookbooks < Application
83
101
  @recipe_files = r.get_rest("cookbooks/#{params[:id]}/attributes")
84
102
  display @attribute_files
85
103
  end
86
-
104
+
87
105
  def definition_files
88
106
  r = Chef::REST.new(Chef::Config[:chef_server_url])
89
107
  @recipe_files = r.get_rest("cookbooks/#{params[:id]}/definitions")
90
108
  display @definition_files
91
109
  end
92
-
110
+
93
111
  def library_files
94
112
  r = Chef::REST.new(Chef::Config[:chef_server_url])
95
113
  @recipe_files = r.get_rest("cookbooks/#{params[:id]}/libraries")
96
114
  display @lib_files
97
115
  end
98
-
116
+
117
+ def more_versions_link(cookbook)
118
+ link_to("+", "JavaScript:void(0);",
119
+ :title => "show other versions of #{cookbook}",
120
+ :data => cookbook,
121
+ :class => "cookbook_version_toggle")
122
+ end
123
+
124
+ def all_versions_link(cookbook)
125
+ link_to("show all versions...", "JavaScript:void(0);",
126
+ :class => "show_all",
127
+ :id => "#{cookbook}_show_all",
128
+ :data => cookbook,
129
+ :title => "show all versions of #{cookbook}")
130
+ end
131
+
132
+ def cookbook_link(version)
133
+ url(:show_specific_version_cookbook,
134
+ :cookbook_id => @cookbook_id, :cb_version => version)
135
+ end
136
+
137
+ def cookbook_parts
138
+ Chef::CookbookVersion::COOKBOOK_SEGMENTS.map do |p|
139
+ part = p.to_s
140
+ case part
141
+ when "files"
142
+ [part, "plain"]
143
+ else
144
+ [part, "ruby"]
145
+ end
146
+ end.sort { |a, b| a[0] <=> b[0] }
147
+ end
148
+
149
+ def highlight_content(url, type)
150
+ case type
151
+ when "plain"
152
+ show_plain_file(url)
153
+ else
154
+ syntax_highlight(url)
155
+ end
156
+ end
157
+
158
+ private
159
+
160
+ def fetch_cookbook_versions(num_versions, options={})
161
+ opts = { :use_envs => true, :cookbook => nil }.merge(options)
162
+ url = if opts[:use_envs]
163
+ env = session[:environment] || "_default"
164
+ "environments/#{env}/cookbooks"
165
+ else
166
+ "cookbooks"
167
+ end
168
+ # we want to display at most 5 versions, but we ask for 6. This
169
+ # tells us if we should display a 'show all' button or not.
170
+ url += "/#{opts[:cookbook]}" if opts[:cookbook]
171
+ url += "?num_versions=#{num_versions}"
172
+ begin
173
+ result = Chef::REST.new(Chef::Config[:chef_server_url]).get_rest(url)
174
+ result.inject({}) do |ans, (name, cb)|
175
+ cb["versions"].each do |v|
176
+ v["url"] = url(:show_specific_version_cookbook, :cookbook_id => name,
177
+ :cb_version => v["version"])
178
+ end
179
+ ans[name] = cb["versions"]
180
+ ans
181
+ end
182
+ rescue => e
183
+ Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}")
184
+ @_message = {:error => $!}
185
+ {}
186
+ end
187
+ end
188
+
99
189
  end
@@ -0,0 +1,235 @@
1
+ #
2
+ # Author:: Stephen Delano (<stephen@opscode.com>)
3
+ # Copyright:: Copyright (c) 2010 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/environment'
20
+
21
+ class Environments < Application
22
+
23
+ provides :html
24
+ before :login_required
25
+ before :require_admin, :only => [:create, :update, :destroy]
26
+
27
+ # GET /environments
28
+ def index
29
+ @environment_list = begin
30
+ Chef::Environment.list
31
+ rescue => e
32
+ Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}")
33
+ @_message = "Could not list environments"
34
+ {}
35
+ end
36
+ render
37
+ end
38
+
39
+ # GET /environments/:id
40
+ def show
41
+ load_environment
42
+ render
43
+ end
44
+
45
+ # GET /environemnts/new
46
+ def new
47
+ @environment = Chef::Environment.new
48
+ load_cookbooks
49
+ render :new
50
+ end
51
+
52
+ # POST /environments
53
+ def create
54
+ @environment = Chef::Environment.new
55
+ if @environment.update_from_params(processed_params=process_params)
56
+ begin
57
+ @environment.create
58
+ redirect(url(:environments), :message => { :notice => "Created Environment #{@environment.name}" })
59
+ rescue Net::HTTPServerException => e
60
+ if conflict?(e)
61
+ Chef::Log.debug("Got 409 conflict creating environment #{params[:name]}\n#{format_exception(e)}")
62
+ redirect(url(:new_environment), :message => { :error => "An environment with that name already exists"})
63
+ elsif forbidden?(e)
64
+ # Currently it's not possible to get 403 here. I leave the code here for completeness and may be useful in the future.[nuo]
65
+ Chef::Log.debug("Got 403 forbidden creating environment #{params[:name]}\n#{format_exception(e)}")
66
+ redirect(url(:new_environment), :message => { :error => "Permission Denied. You do not have permission to create an environment."})
67
+ else
68
+ Chef::Log.error("Error communicating with the API server\n#{format_exception(e)}")
69
+ raise
70
+ end
71
+ end
72
+ else
73
+ load_cookbooks
74
+ # By rendering :new, the view shows errors from @environment.invalid_fields
75
+ render :new
76
+ end
77
+ end
78
+
79
+ # GET /environments/:id/edit
80
+ def edit
81
+ load_environment
82
+ if @environment.name == "_default"
83
+ msg = { :warning => "The '_default' environment cannot be edited." }
84
+ redirect(url(:environments), :message => msg)
85
+ return
86
+ end
87
+ load_cookbooks
88
+ render
89
+ end
90
+
91
+ # PUT /environments/:id
92
+ def update
93
+ load_environment
94
+ if @environment.update_from_params(process_params(params[:id]))
95
+ begin
96
+ @environment.save
97
+ redirect(url(:environment, @environment.name), :message => { :notice => "Updated Environment #{@environment.name}" })
98
+ rescue Net::HTTPServerException => e
99
+ if forbidden?(e)
100
+ # Currently it's not possible to get 403 here. I leave the code here for completeness and may be useful in the future.[nuo]
101
+ Chef::Log.debug("Got 403 forbidden updating environment #{params[:name]}\n#{format_exception(e)}")
102
+ redirect(url(:edit_environment), :message => { :error => "Permission Denied. You do not have permission to update an environment."})
103
+ else
104
+ Chef::Log.error("Error communicating with the API server\n#{format_exception(e)}")
105
+ raise
106
+ end
107
+ end
108
+ else
109
+ load_cookbooks
110
+ # By rendering :new, the view shows errors from @environment.invalid_fields
111
+ render :edit
112
+ end
113
+ end
114
+
115
+ # DELETE /environments/:id
116
+ def destroy
117
+ begin
118
+ @environment = Chef::Environment.load(params[:id])
119
+ @environment.destroy
120
+ redirect(absolute_url(:environments), :message => { :notice => "Environment #{@environment.name} deleted successfully." }, :permanent => true)
121
+ rescue => e
122
+ Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}")
123
+ @environment_list = Chef::Environment.list()
124
+ @_message = {:error => "Could not delete environment #{params[:id]}: #{e.message}"}
125
+ render :index
126
+ end
127
+ end
128
+
129
+ # GET /environments/:environment_id/cookbooks
130
+ def list_cookbooks
131
+ # TODO: rescue loading the environment
132
+ @environment = Chef::Environment.load(params[:environment_id])
133
+ @cookbooks = begin
134
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
135
+ r.get_rest("/environments/#{params[:environment_id]}/cookbooks").inject({}) do |res, (cookbook, url)|
136
+ # we just want the cookbook name and the version
137
+ res[cookbook] = url.split('/').last
138
+ res
139
+ end
140
+ rescue => e
141
+ Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}")
142
+ @_message = "Could not load cookbooks for environment #{params[:environment_id]}"
143
+ {}
144
+ end
145
+ render
146
+ end
147
+
148
+ # GET /environments/:environment_id/nodes
149
+ def list_nodes
150
+ # TODO: rescue loading the environment
151
+ @environment = Chef::Environment.load(params[:environment_id])
152
+ @nodes = begin
153
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
154
+ r.get_rest("/environments/#{params[:environment_id]}/nodes").keys.sort
155
+ rescue => e
156
+ Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}")
157
+ @_message = "Could not load nodes for environment #{params[:environment_id]}"
158
+ []
159
+ end
160
+ render
161
+ end
162
+
163
+ # GET /environments/:environment/recipes
164
+ def list_recipes
165
+ provides :json
166
+ display(:recipes => list_available_recipes_for(params[:environment_id]))
167
+ end
168
+
169
+ # GET /environments/:environment_id/set
170
+ def select_environment
171
+ name = params[:environment_id]
172
+ referer = request.referer || "/nodes"
173
+ if name == '_none'
174
+ session[:environment] = nil
175
+ else
176
+ # TODO: check if environment exists
177
+ session[:environment] = name
178
+ end
179
+ redirect referer
180
+ end
181
+
182
+ private
183
+
184
+ def load_environment
185
+ @environment = begin
186
+ Chef::Environment.load(params[:id])
187
+ rescue Net::HTTPServerException => e
188
+ Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}")
189
+ @_message = "Could not load environment #{params[:id]}"
190
+ @environment = Chef::Environment.new
191
+ false
192
+ end
193
+ end
194
+
195
+ def load_cookbooks
196
+ begin
197
+ # @cookbooks is a hash, keys are cookbook names, values are their URIs.
198
+ @cookbooks = Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("cookbooks").keys.sort
199
+ rescue Net::HTTPServerException => e
200
+ Chef::Log.error(format_exception(e))
201
+ redirect(url(:new_environment), :message => { :error => "Could not load the list of available cookbooks."})
202
+ end
203
+ end
204
+
205
+ def process_params(name=params[:name])
206
+ {:name => name, :description => params[:description], :attributes => params[:attributes], :cookbook_version => search_params_for_cookbook_version_constraints}
207
+ end
208
+
209
+ def search_params_for_cookbook_version_constraints
210
+ cookbook_version_constraints = {}
211
+ index = 0
212
+ params.each do |k,v|
213
+ cookbook_name_box_id = k[/cookbook_name_(\d+)/, 1]
214
+ unless cookbook_name_box_id.nil? || v.nil? || v.empty?
215
+ cookbook_version_constraints[index] = v + " " + params["operator_#{cookbook_name_box_id}"] + " " + params["cookbook_version_#{cookbook_name_box_id}"].strip # e.g. {"0" => "foo > 0.3.0"}
216
+ index = index + 1
217
+ end
218
+ end
219
+ Chef::Log.debug("cookbook version constraints are: #{cookbook_version_constraints.inspect}")
220
+ cookbook_version_constraints
221
+ end
222
+
223
+ def cookbook_version_constraints
224
+ @environment.cookbook_versions.inject({}) do |ans, (cb, vc)|
225
+ op, version = vc.split(" ")
226
+ ans[cb] = { "version" => version, "op" => op }
227
+ ans
228
+ end
229
+ end
230
+
231
+ def constraint_operators
232
+ %w(~> >= > = < <=)
233
+ end
234
+
235
+ end