chef-server-webui 0.8.16 → 0.9.0.a3

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 (80) hide show
  1. data/Rakefile +14 -10
  2. data/app/controllers/application.rb +111 -128
  3. data/app/controllers/clients.rb +10 -10
  4. data/app/controllers/cookbook_attributes.rb +1 -1
  5. data/app/controllers/cookbook_definitions.rb +1 -1
  6. data/app/controllers/cookbook_files.rb +1 -1
  7. data/app/controllers/cookbook_libraries.rb +1 -1
  8. data/app/controllers/cookbook_recipes.rb +1 -1
  9. data/app/controllers/cookbook_templates.rb +1 -1
  10. data/app/controllers/cookbooks.rb +21 -3
  11. data/app/controllers/databag_items.rb +6 -6
  12. data/app/controllers/databags.rb +3 -3
  13. data/app/controllers/main.rb +1 -1
  14. data/app/controllers/nodes.rb +21 -21
  15. data/app/controllers/openid_consumer.rb +9 -9
  16. data/app/controllers/roles.rb +3 -3
  17. data/app/controllers/search.rb +1 -1
  18. data/app/controllers/search_entries.rb +1 -1
  19. data/app/controllers/status.rb +1 -1
  20. data/app/controllers/users.rb +7 -7
  21. data/app/helpers/application_helper.rb +1 -156
  22. data/app/helpers/global_helpers.rb +20 -16
  23. data/app/helpers/nodes_helper.rb +24 -22
  24. data/app/helpers/openid_server_helpers.rb +13 -10
  25. data/app/helpers/search_helper.rb +44 -38
  26. data/app/helpers/status_helper.rb +10 -3
  27. data/app/views/clients/_navigation.html.haml +5 -5
  28. data/app/views/clients/edit.html.haml +1 -1
  29. data/app/views/clients/index.html.haml +4 -4
  30. data/app/views/clients/new.html.haml +1 -1
  31. data/app/views/cookbooks/index.html.haml +1 -1
  32. data/app/views/cookbooks/show.html.haml +25 -16
  33. data/app/views/databag_items/_form.html.haml +1 -1
  34. data/app/views/databag_items/_navigation.html.haml +5 -5
  35. data/app/views/databag_items/edit.html.haml +1 -1
  36. data/app/views/databag_items/new.html.haml +1 -1
  37. data/app/views/databags/_item_navigation.html.haml +4 -4
  38. data/app/views/databags/_navigation.html.haml +5 -5
  39. data/app/views/databags/edit.html.haml +1 -1
  40. data/app/views/databags/index.html.haml +3 -3
  41. data/app/views/databags/new.html.haml +1 -1
  42. data/app/views/databags/show.html.haml +3 -3
  43. data/app/views/layout/{chef_server_webui.html.haml → application.html.haml} +11 -11
  44. data/app/views/layout/login.html.haml +1 -1
  45. data/app/views/nodes/_form.html.haml +1 -1
  46. data/app/views/nodes/_navigation.html.haml +5 -5
  47. data/app/views/nodes/edit.html.haml +1 -1
  48. data/app/views/nodes/index.html.haml +6 -6
  49. data/app/views/nodes/new.html.haml +1 -1
  50. data/app/views/nodes/show.html.haml +4 -5
  51. data/app/views/openid_consumer/index.html.haml +2 -2
  52. data/app/views/openid_register/index.html.haml +4 -4
  53. data/app/views/openid_register/show.html.haml +1 -1
  54. data/app/views/roles/_form.html.haml +1 -1
  55. data/app/views/roles/_navigation.html.haml +5 -5
  56. data/app/views/roles/edit.html.haml +1 -1
  57. data/app/views/roles/index.html.haml +4 -4
  58. data/app/views/roles/new.html.haml +1 -1
  59. data/app/views/roles/show.html.haml +3 -4
  60. data/app/views/search/_search_form.html.haml +1 -1
  61. data/app/views/search/index.html.haml +1 -1
  62. data/app/views/search/show.html.haml +1 -1
  63. data/app/views/status/index.html.haml +9 -12
  64. data/app/views/users/_form.html.haml +1 -1
  65. data/app/views/users/_navigation.html.haml +5 -5
  66. data/app/views/users/edit.html.haml +1 -1
  67. data/app/views/users/index.html.haml +3 -3
  68. data/app/views/users/login.html.haml +1 -1
  69. data/app/views/users/new.html.haml +1 -1
  70. data/bin/chef-server-webui +72 -0
  71. data/config.ru +10 -74
  72. data/config/init.rb +30 -11
  73. data/config/rack.rb +5 -0
  74. data/config/router.rb +62 -5
  75. data/lib/chef-server-webui.rb +2 -155
  76. data/lib/chef-server-webui/version.rb +3 -0
  77. data/public/javascripts/drop_down_menu.js +22 -0
  78. metadata +60 -48
  79. data/stubs/app/controllers/application.rb +0 -2
  80. data/stubs/app/controllers/main.rb +0 -2
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__) + '/lib/chef-server-webui/version'
2
+
1
3
  require 'rubygems'
2
4
  require 'rake/gempackagetask'
3
5
 
@@ -5,7 +7,6 @@ require 'merb-core'
5
7
  require 'merb-core/tasks/merb'
6
8
 
7
9
  GEM_NAME = "chef-server-webui"
8
- CHEF_SERVER_VERSION="0.8.16"
9
10
  AUTHOR = "Opscode"
10
11
  EMAIL = "chef@opscode.com"
11
12
  HOMEPAGE = "http://wiki.opscode.com/display/chef"
@@ -13,7 +14,7 @@ SUMMARY = "A systems integration framework, built to bring the benefits of confi
13
14
 
14
15
  spec = Gem::Specification.new do |s|
15
16
  s.name = GEM_NAME
16
- s.version = CHEF_SERVER_VERSION
17
+ s.version = ChefServerWebui::VERSION
17
18
  s.platform = Gem::Platform::RUBY
18
19
  s.has_rdoc = true
19
20
  s.extra_rdoc_files = ["README.rdoc", "LICENSE" ]
@@ -23,17 +24,20 @@ spec = Gem::Specification.new do |s|
23
24
  s.email = EMAIL
24
25
  s.homepage = HOMEPAGE
25
26
 
26
- s.add_dependency "merb-core", "~> 1.0.0"
27
- s.add_dependency "merb-slices", "~> 1.0.0"
28
- s.add_dependency "merb-assets", "~> 1.0.0"
29
- s.add_dependency "merb-helpers", "~> 1.0.0"
30
- s.add_dependency "merb-haml", "~> 1.0.0"
31
- s.add_dependency "merb-param-protection", "~> 1.0.0"
27
+ s.add_dependency "merb-core", "~> 1.0"
28
+ s.add_dependency "merb-slices", "~> 1.0"
29
+ s.add_dependency "merb-assets", "~> 1.0"
30
+ s.add_dependency "merb-helpers", "~> 1.0"
31
+ s.add_dependency "merb-haml", "~> 1.0"
32
+ s.add_dependency "merb-param-protection", "~> 1.0"
32
33
 
33
34
  s.add_dependency "json", "<= 1.4.2"
34
35
 
35
36
  %w{thin haml ruby-openid coderay}.each { |g| s.add_dependency g}
36
37
 
38
+ s.bindir = "bin"
39
+ s.executables = %w( chef-server-webui )
40
+
37
41
  s.require_path = 'lib'
38
42
  s.files = %w(LICENSE README.rdoc Rakefile config.ru) + Dir.glob("{bin,config,lib,spec,app,public,stubs}/**/*")
39
43
  end
@@ -44,12 +48,12 @@ end
44
48
 
45
49
  desc "Install the gem"
46
50
  task :install => :package do
47
- sh %{gem install pkg/#{GEM_NAME}-#{CHEF_SERVER_VERSION} --no-rdoc --no-ri}
51
+ sh %{gem install pkg/#{GEM_NAME}-#{ChefServerWebui::VERSION} --no-rdoc --no-ri}
48
52
  end
49
53
 
50
54
  desc "Uninstall the gem"
51
55
  task :uninstall do
52
- sh %{gem uninstall #{GEM_NAME} -x -v #{CHEF_SERVER_VERSION} }
56
+ sh %{gem uninstall #{GEM_NAME} -x -v #{ChefServerWebui::VERSION} }
53
57
  end
54
58
 
55
59
  desc "Create a gemspec file"
@@ -8,9 +8,9 @@
8
8
  # Licensed under the Apache License, Version 2.0 (the "License");
9
9
  # you may not use this file except in compliance with the License.
10
10
  # You may obtain a copy of the License at
11
- #
11
+ #
12
12
  # http://www.apache.org/licenses/LICENSE-2.0
13
- #
13
+ #
14
14
  # Unless required by applicable law or agreed to in writing, software
15
15
  # distributed under the License is distributed on an "AS IS" BASIS,
16
16
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -21,67 +21,42 @@
21
21
  require "chef" / "mixin" / "checksum"
22
22
  require "chef" / "cookbook_loader"
23
23
 
24
- class ChefServerWebui::Application < Merb::Controller
24
+ class Application < Merb::Controller
25
25
 
26
26
  include Chef::Mixin::Checksum
27
27
 
28
- controller_for_slice
29
-
30
- # Generate the absolute url for a slice - takes the slice's :path_prefix into account.
31
- #
32
- # @param slice_name<Symbol>
33
- # The name of the slice - in identifier_sym format (underscored).
34
- # @param *args<Array[Symbol,Hash]>
35
- # There are several possibilities regarding arguments:
36
- # - when passing a Hash only, the :default route of the current
37
- # slice will be used
38
- # - when a Symbol is passed, it's used as the route name
39
- # - a Hash with additional params can optionally be passed
40
- #
41
- # @return <String> A uri based on the requested slice.
42
- #
43
- # @example absolute_slice_url(:awesome, :format => 'html')
44
- # @example absolute_slice_url(:forum, :posts, :format => 'xml')
45
- def absolute_slice_url(slice_name, *args)
46
- options = extract_options_from_args!(args) || {}
47
- protocol = options.delete(:protocol) || request.protocol
48
- host = options.delete(:host) || request.host
49
-
50
- protocol + "://" + host + slice_url(slice_name,*args)
51
- end
52
-
53
28
  # Check if the user is logged in and if the user still exists
54
29
  def login_required
55
30
  if session[:user]
56
31
  begin
57
32
  Chef::WebUIUser.load(session[:user]) rescue (raise NotFound, "Cannot find User #{session[:user]}, maybe it got deleted by an Administrator.")
58
- rescue
33
+ rescue
59
34
  logout_and_redirect_to_login
60
- else
35
+ else
61
36
  return session[:user]
62
- end
63
- else
37
+ end
38
+ else
64
39
  self.store_location
65
40
  throw(:halt, :access_denied)
66
41
  end
67
42
  end
68
-
43
+
69
44
  def cleanup_session
70
45
  [:user,:level].each { |n| session.delete(n) }
71
- end
72
-
46
+ end
47
+
73
48
  def logout_and_redirect_to_login
74
49
  cleanup_session
75
50
  @user = Chef::WebUIUser.new
76
- redirect(slice_url(:users_login), {:message => { :error => $! }, :permanent => true})
77
- end
78
-
79
-
51
+ redirect(url(:users_login), {:message => { :error => $! }, :permanent => true})
52
+ end
53
+
54
+
80
55
  def is_admin(name)
81
56
  user = Chef::WebUIUser.load(name)
82
57
  return user.admin
83
58
  end
84
-
59
+
85
60
  #return true if there is only one admin left, false otehrwise
86
61
  def is_last_admin
87
62
  count = 0
@@ -95,32 +70,12 @@ class ChefServerWebui::Application < Merb::Controller
95
70
  end
96
71
  true
97
72
  end
98
-
73
+
99
74
  #whether or not the user should be able to edit a user's admin status
100
75
  def edit_admin
101
76
  is_admin(params[:user_id]) ? (!is_last_admin) : true
102
- end
103
-
104
- def authorized_node
105
- # if session[:level] == :admin
106
- # Chef::Log.debug("Authorized as Administrator")
107
- # true
108
- # elsif session[:level] == :node
109
- # Chef::Log.debug("Authorized as node")
110
- # if session[:node_name] == params[:id].gsub(/\./, '_')
111
- # true
112
- # else
113
- # raise(
114
- # Unauthorized,
115
- # "You are not the correct node for this action: #{session[:node_name]} instead of #{params[:id]}"
116
- # )
117
- # end
118
- # else
119
- # Chef::Log.debug("Unauthorized")
120
- # raise Unauthorized, "You are not allowed to take this action."
121
- # end
122
77
  end
123
-
78
+
124
79
  def authorized_user
125
80
  if session[:level] == :admin
126
81
  Chef::Log.debug("Authorized as Administrator")
@@ -128,9 +83,9 @@ class ChefServerWebui::Application < Merb::Controller
128
83
  else
129
84
  Chef::Log.debug("Unauthorized")
130
85
  raise Unauthorized, "The current user is not an Administrator, you can only Show and Edit the user itself. To control other users, login as an Administrator."
131
- end
132
- end
133
-
86
+ end
87
+ end
88
+
134
89
  # Store the URI of the current request in the session.
135
90
  #
136
91
  # We can return to this location by calling #redirect_back_or_default.
@@ -145,18 +100,18 @@ class ChefServerWebui::Application < Merb::Controller
145
100
  session[:return_to] = nil
146
101
  redirect loc
147
102
  end
148
-
103
+
149
104
  def access_denied
150
105
  case content_type
151
106
  when :html
152
107
  store_location
153
- redirect slice_url(:users_login), :message => { :error => "You don't have access to that, please login."}
108
+ redirect url(:users_login), :message => { :error => "You don't have access to that, please login."}
154
109
  else
155
110
  raise Unauthorized, "You must authenticate first!"
156
111
  end
157
112
  end
158
-
159
- # Load a cookbook and return a hash with a list of all the files of a
113
+
114
+ # Load a cookbook and return a hash with a list of all the files of a
160
115
  # given segment (attributes, recipes, definitions, libraries)
161
116
  #
162
117
  # === Parameters
@@ -166,14 +121,14 @@ class ChefServerWebui::Application < Merb::Controller
166
121
  # === Returns
167
122
  # <Hash>:: A hash consisting of the short name of the file in :name, and the full path
168
123
  # to the file in :file.
169
- def load_cookbook_segment(cookbook_id, segment)
124
+ def load_cookbook_segment(cookbook_id, segment)
170
125
  r = Chef::REST.new(Chef::Config[:chef_server_url])
171
126
  cookbook = r.get_rest("cookbooks/#{cookbook_id}")
172
127
 
173
128
  raise NotFound unless cookbook
174
-
129
+
175
130
  files_list = segment_files(segment, cookbook)
176
-
131
+
177
132
  files = Hash.new
178
133
  files_list.each do |f|
179
134
  files[f['name']] = {
@@ -183,7 +138,7 @@ class ChefServerWebui::Application < Merb::Controller
183
138
  end
184
139
  files
185
140
  end
186
-
141
+
187
142
  def segment_files(segment, cookbook)
188
143
  files_list = nil
189
144
  case segment
@@ -201,59 +156,87 @@ class ChefServerWebui::Application < Merb::Controller
201
156
  files_list
202
157
  end
203
158
 
204
- #
205
- # The following should no longer be necessary for the re-factored cookbooks replated webui controllers (which talks to the API)
206
- # But I want to wait until further verified before removing the code. [nuo]
207
- #
208
- # def specific_cookbooks(node_name, cl)
209
- # valid_cookbooks = Hash.new
210
- # begin
211
- # node = Chef::Node.load(node_name)
212
- # recipes, default_attrs, override_attrs = node.run_list.expand
213
- # rescue Net::HTTPServerException
214
- # recipes = []
215
- # end
216
- # recipes.each do |recipe|
217
- # valid_cookbooks = expand_cookbook_deps(valid_cookbooks, cl, recipe)
218
- # end
219
- # valid_cookbooks
220
- # end
221
- #
222
- # def expand_cookbook_deps(valid_cookbooks, cl, recipe)
223
- # cookbook = recipe
224
- # if recipe =~ /^(.+)::/
225
- # cookbook = $1
226
- # end
227
- # Chef::Log.debug("Node requires #{cookbook}")
228
- # valid_cookbooks[cookbook] = true
229
- # cl.metadata[cookbook.to_sym].dependencies.each do |dep, versions|
230
- # expand_cookbook_deps(valid_cookbooks, cl, dep) unless valid_cookbooks[dep]
231
- # end
232
- # valid_cookbooks
233
- # end
234
- #
235
- # def load_all_files(segment, node_name=nil)
236
- # r = Chef::REST.new(Chef::Config[:chef_server_url])
237
- # cookbooks = r.get_rest("cookbooks")
238
- #
239
- # files = Array.new
240
- # valid_cookbooks = node_name ? specific_cookbooks(node_name, cookbooks) : {}
241
- # cl.each do |cookbook|
242
- # if node_name
243
- # next unless valid_cookbooks[cookbook.name.to_s]
244
- # end
245
- # segment_files(segment, cookbook).each do |sf|
246
- # mo = sf.match("cookbooks/#{cookbook.name}/#{segment}/(.+)")
247
- # file_name = mo[1]
248
- # files << {
249
- # :cookbook => cookbook.name,
250
- # :name => file_name,
251
- # :checksum => checksum(sf)
252
- # }
253
- # end
254
- # end
255
- # files
256
- # end
159
+ def build_tree(name, node)
160
+ html = "<table id='#{name}' class='tree table'>"
161
+ html << "<tr><th class='first'>Attribute</th><th class='last'>Value</th></tr>"
162
+ count = 0
163
+ parent = 0
164
+ append_tree(name, html, node, count, parent)
165
+ html << "</table>"
166
+ html
167
+ end
168
+
169
+ def append_tree(name, html, node, count, parent)
170
+ to_do = node
171
+ #to_do = node.kind_of?(Chef::Node) ? node.attribute : node
172
+ Chef::Log.error("I have #{to_do.inspect}")
173
+ to_do.sort{ |a,b| a[0] <=> b[0] }.each do |key, value|
174
+ Chef::Log.error("I am #{key.inspect} #{value.inspect}")
175
+ to_send = Array.new
176
+ count += 1
177
+ is_parent = false
178
+ local_html = ""
179
+ local_html << "<tr id='#{name}-#{count}' class='collapsed #{name}"
180
+ if parent != 0
181
+ local_html << " child-of-#{name}-#{parent}' style='display: none;'>"
182
+ else
183
+ local_html << "'>"
184
+ end
185
+ local_html << "<td class='table-key'><span toggle='#{name}-#{count}'/>#{key}</td>"
186
+ case value
187
+ when Hash
188
+ is_parent = true
189
+ local_html << "<td></td>"
190
+ p = count
191
+ to_send << Proc.new { append_tree(name, html, value, count, p) }
192
+ when Array
193
+ is_parent = true
194
+ local_html << "<td></td>"
195
+ as_hash = {}
196
+ value.each_index { |i| as_hash[i] = value[i] }
197
+ p = count
198
+ to_send << Proc.new { append_tree(name, html, as_hash, count, p) }
199
+ else
200
+ local_html << "<td><div class='json-attr'>#{value}</div></td>"
201
+ end
202
+ local_html << "</tr>"
203
+ local_html.sub!(/class='collapsed/, 'class=\'collapsed parent') if is_parent
204
+ local_html.sub!(/<span/, "<span class='expander'") if is_parent
205
+ html << local_html
206
+ to_send.each { |s| count = s.call }
207
+ count += to_send.length
208
+ end
209
+ count
210
+ end
211
+
212
+ def syntax_highlight(code)
213
+ tokens = File.exists?(code) ? CodeRay.scan_file(code, :ruby) : CodeRay.scan(code, :ruby)
214
+ CodeRay.encode_tokens(tokens, :span)
215
+ end
216
+
217
+ def get_file(uri)
218
+ r = Chef::REST.new(Chef::Config[:chef_server_url])
219
+ content = r.get_rest(uri)
220
+ a = Tempfile.new("cookbook_temp_file")
221
+ File.open(a.path, 'w'){|f| f.write(content)}
222
+ path = a.path
223
+ a.close
224
+ path
225
+ end
226
+
227
+ def str_to_bool(str)
228
+ str =~ /true/ ? true : false
229
+ end
230
+
231
+ #for showing search result
232
+ def determine_name(type, object)
233
+ case type
234
+ when :node, :role, :client
235
+ object.name
236
+ else
237
+ params[:id]
238
+ end
239
+ end
257
240
 
258
241
  def get_available_recipes
259
242
  r = Chef::REST.new(Chef::Config[:chef_server_url])
@@ -264,7 +247,7 @@ class ChefServerWebui::Application < Merb::Controller
264
247
  cb["recipes"].each do |recipe|
265
248
  recipe["name"] =~ /(.+)\.rb/
266
249
  r_name = $1;
267
- if r_name == "default"
250
+ if r_name == "default"
268
251
  result << key
269
252
  else
270
253
  result << "#{key}::#{r_name}"
@@ -273,7 +256,7 @@ class ChefServerWebui::Application < Merb::Controller
273
256
  end
274
257
  result
275
258
  end
276
-
259
+
277
260
  def convert_newline_to_br(string)
278
261
  string.to_s.gsub(/\n/, '<br />') unless string.nil?
279
262
  end
@@ -18,21 +18,21 @@
18
18
 
19
19
  require 'chef/api_client'
20
20
 
21
- class ChefServerWebui::Clients < ChefServerWebui::Application
21
+ class Clients < Application
22
22
  provides :json
23
23
  provides :html
24
24
  before :login_required
25
25
 
26
26
  # GET /clients
27
27
  def index
28
- @clients_list = begin
29
- Chef::ApiClient.list()
30
- rescue => e
31
- Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}")
32
- @_message = {:error => "Could not list clients"}
33
- {}
34
- end
35
- render
28
+ begin
29
+ @clients_list = Chef::ApiClient.list().keys.sort
30
+ rescue => e
31
+ Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}")
32
+ @_message = {:error => "Could not list clients"}
33
+ @clients_list = []
34
+ end
35
+ render
36
36
  end
37
37
 
38
38
  # GET /clients/:id
@@ -107,7 +107,7 @@ class ChefServerWebui::Clients < ChefServerWebui::Application
107
107
  begin
108
108
  @client = Chef::ApiClient.load(params[:id])
109
109
  @client.destroy
110
- redirect(absolute_slice_url(:clients), {:message => { :notice => "Client #{params[:id]} deleted successfully" }, :permanent => true})
110
+ redirect(absolute_url(:clients), {:message => { :notice => "Client #{params[:id]} deleted successfully" }, :permanent => true})
111
111
  rescue => e
112
112
  Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}")
113
113
  @_message = {:error => "Could not delete client #{params[:id]}" }
@@ -19,7 +19,7 @@
19
19
 
20
20
  require 'chef' / 'mixin' / 'checksum'
21
21
 
22
- class ChefServerWebui::CookbookAttributes < ChefServerWebui::Application
22
+ class CookbookAttributes < Application
23
23
 
24
24
  provides :html
25
25