chef-server-webui 0.8.2
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/LICENSE +201 -0
- data/README.rdoc +135 -0
- data/Rakefile +62 -0
- data/app/controllers/application.rb +281 -0
- data/app/controllers/clients.rb +120 -0
- data/app/controllers/cookbook_attributes.rb +41 -0
- data/app/controllers/cookbook_definitions.rb +41 -0
- data/app/controllers/cookbook_files.rb +39 -0
- data/app/controllers/cookbook_libraries.rb +41 -0
- data/app/controllers/cookbook_recipes.rb +40 -0
- data/app/controllers/cookbook_templates.rb +57 -0
- data/app/controllers/cookbooks.rb +78 -0
- data/app/controllers/databag_items.rb +102 -0
- data/app/controllers/databags.rb +83 -0
- data/app/controllers/exceptions.rb +19 -0
- data/app/controllers/main.rb +7 -0
- data/app/controllers/nodes.rb +138 -0
- data/app/controllers/openid_consumer.rb +154 -0
- data/app/controllers/roles.rb +144 -0
- data/app/controllers/search.rb +62 -0
- data/app/controllers/search_entries.rb +64 -0
- data/app/controllers/status.rb +39 -0
- data/app/controllers/users.rb +186 -0
- data/app/helpers/application_helper.rb +171 -0
- data/app/helpers/cookbook_attributes_helper.rb +7 -0
- data/app/helpers/cookbook_definitions_helper.rb +8 -0
- data/app/helpers/cookbook_files_helper.rb +8 -0
- data/app/helpers/cookbook_libraries_helper.rb +7 -0
- data/app/helpers/cookbook_recipes_helper.rb +8 -0
- data/app/helpers/cookbook_templates_helper.rb +8 -0
- data/app/helpers/exceptions_helper.rb +6 -0
- data/app/helpers/global_helpers.rb +35 -0
- data/app/helpers/nodes_helper.rb +41 -0
- data/app/helpers/openid_consumer_helper.rb +8 -0
- data/app/helpers/openid_register_helper.rb +8 -0
- data/app/helpers/openid_server_helper.rb +6 -0
- data/app/helpers/openid_server_helpers.rb +29 -0
- data/app/helpers/roles_helper.rb +5 -0
- data/app/helpers/search_entries_helper.rb +8 -0
- data/app/helpers/search_helper.rb +38 -0
- data/app/helpers/status_helper.rb +26 -0
- data/app/views/clients/_form.html.haml +22 -0
- data/app/views/clients/_navigation.html.haml +9 -0
- data/app/views/clients/edit.html.haml +6 -0
- data/app/views/clients/index.html.haml +21 -0
- data/app/views/clients/new.html.haml +6 -0
- data/app/views/clients/show.html.haml +20 -0
- data/app/views/cookbooks/index.html.haml +10 -0
- data/app/views/cookbooks/show.html.haml +40 -0
- data/app/views/databag_items/_form.html.haml +14 -0
- data/app/views/databag_items/_navigation.html.haml +9 -0
- data/app/views/databag_items/edit.html.haml +6 -0
- data/app/views/databag_items/index.html.haml +0 -0
- data/app/views/databag_items/new.html.haml +6 -0
- data/app/views/databag_items/show.html.haml +9 -0
- data/app/views/databags/_form.html.haml +12 -0
- data/app/views/databags/_item_navigation.html.haml +8 -0
- data/app/views/databags/_navigation.html.haml +9 -0
- data/app/views/databags/edit.html.haml +6 -0
- data/app/views/databags/index.html.haml +19 -0
- data/app/views/databags/new.html.haml +6 -0
- data/app/views/databags/show.html.haml +19 -0
- data/app/views/exceptions/bad_request.json.erb +1 -0
- data/app/views/exceptions/internal_server_error.html.erb +216 -0
- data/app/views/exceptions/not_acceptable.html.erb +63 -0
- data/app/views/exceptions/not_found.html.erb +47 -0
- data/app/views/exceptions/standard_error.html.erb +217 -0
- data/app/views/layout/_jsonedit.html.haml +82 -0
- data/app/views/layout/chef_server_webui.html.haml +56 -0
- data/app/views/layout/login.html.haml +36 -0
- data/app/views/main/index.html.erb +1 -0
- data/app/views/nodes/_action.html.haml +13 -0
- data/app/views/nodes/_form.html.haml +53 -0
- data/app/views/nodes/_navigation.html.haml +9 -0
- data/app/views/nodes/_resource.html.haml +22 -0
- data/app/views/nodes/edit.html.haml +7 -0
- data/app/views/nodes/index.html.haml +25 -0
- data/app/views/nodes/new.html.haml +6 -0
- data/app/views/nodes/show.html.haml +60 -0
- data/app/views/openid_consumer/index.html.haml +28 -0
- data/app/views/openid_consumer/start.html.haml +4 -0
- data/app/views/openid_login/index.html.haml +5 -0
- data/app/views/openid_register/index.html.haml +19 -0
- data/app/views/openid_register/show.html.haml +7 -0
- data/app/views/roles/_form.html.haml +53 -0
- data/app/views/roles/_navigation.html.haml +9 -0
- data/app/views/roles/edit.html.haml +6 -0
- data/app/views/roles/index.html.haml +21 -0
- data/app/views/roles/new.html.haml +6 -0
- data/app/views/roles/show.html.haml +54 -0
- data/app/views/search/_search_form.html.haml +6 -0
- data/app/views/search/index.html.haml +8 -0
- data/app/views/search/show.html.haml +13 -0
- data/app/views/search_entries/index.html.haml +8 -0
- data/app/views/search_entries/show.html.haml +7 -0
- data/app/views/status/index.html.haml +90 -0
- data/app/views/users/_form.html.haml +39 -0
- data/app/views/users/_navigation.html.haml +9 -0
- data/app/views/users/edit.html.haml +6 -0
- data/app/views/users/index.html.haml +20 -0
- data/app/views/users/login.html.haml +16 -0
- data/app/views/users/new.html.haml +27 -0
- data/app/views/users/show.html.haml +13 -0
- data/app/views/users/start.html.haml +4 -0
- data/config.ru +84 -0
- data/config/init.rb +49 -0
- data/config/router.rb +6 -0
- data/lib/chef-server-webui.rb +155 -0
- data/lib/chef-server-webui/merbtasks.rb +103 -0
- data/lib/chef-server-webui/slicetasks.rb +20 -0
- data/lib/chef-server-webui/spectasks.rb +53 -0
- data/public/facebox/README.txt +4 -0
- data/public/facebox/b.png +0 -0
- data/public/facebox/bl.png +0 -0
- data/public/facebox/br.png +0 -0
- data/public/facebox/closelabel.gif +0 -0
- data/public/facebox/facebox.css +95 -0
- data/public/facebox/facebox.js +319 -0
- data/public/facebox/loading.gif +0 -0
- data/public/facebox/tl.png +0 -0
- data/public/facebox/tr.png +0 -0
- data/public/images/avatar.png +0 -0
- data/public/images/black_big.png +0 -0
- data/public/images/indicator.gif +0 -0
- data/public/images/jsonedit/add2.png +0 -0
- data/public/images/jsonedit/build-button.png +0 -0
- data/public/images/jsonedit/bullet.gif +0 -0
- data/public/images/jsonedit/bullet_orange.png +0 -0
- data/public/images/jsonedit/cross.png +0 -0
- data/public/images/jsonedit/delete.png +0 -0
- data/public/images/jsonedit/deleted.png +0 -0
- data/public/images/jsonedit/json.jpg +0 -0
- data/public/images/jsonedit/label.gif +0 -0
- data/public/images/jsonedit/minus.gif +0 -0
- data/public/images/jsonedit/pixel.gif +0 -0
- data/public/images/jsonedit/plus.gif +0 -0
- data/public/images/jsonedit/saved.png +0 -0
- data/public/images/jsonedit/table_refresh.png +0 -0
- data/public/images/jsonedit/value.gif +0 -0
- data/public/images/merb.jpg +0 -0
- data/public/images/toggle-collapse-dark.png +0 -0
- data/public/images/toggle-collapse-light.png +0 -0
- data/public/images/toggle-collapse.gif +0 -0
- data/public/images/toggle-expand-dark.png +0 -0
- data/public/images/toggle-expand-light.png +0 -0
- data/public/images/toggle-expand.gif +0 -0
- data/public/images/treeBuilderImages/Thumbs.db +0 -0
- data/public/images/treeBuilderImages/doc.gif +0 -0
- data/public/images/treeBuilderImages/docNode.gif +0 -0
- data/public/images/treeBuilderImages/docNodeLast.gif +0 -0
- data/public/images/treeBuilderImages/docNodeLastFirst.gif +0 -0
- data/public/images/treeBuilderImages/folder.gif +0 -0
- data/public/images/treeBuilderImages/folderNode.gif +0 -0
- data/public/images/treeBuilderImages/folderNodeFirst.gif +0 -0
- data/public/images/treeBuilderImages/folderNodeLast.gif +0 -0
- data/public/images/treeBuilderImages/folderNodeLastFirst.gif +0 -0
- data/public/images/treeBuilderImages/folderNodeOpen.gif +0 -0
- data/public/images/treeBuilderImages/folderNodeOpenFirst.gif +0 -0
- data/public/images/treeBuilderImages/folderNodeOpenLast.gif +0 -0
- data/public/images/treeBuilderImages/folderNodeOpenLastFirst.gif +0 -0
- data/public/images/treeBuilderImages/folderOpen.gif +0 -0
- data/public/images/treeBuilderImages/vertLine.gif +0 -0
- data/public/javascripts/chef.js +160 -0
- data/public/javascripts/jquery-1.3.2.min.js +19 -0
- data/public/javascripts/jquery-ui-1.7.1.custom.min.js +65 -0
- data/public/javascripts/jquery.editinline.js +108 -0
- data/public/javascripts/jquery.jeditable.mini.js +30 -0
- data/public/javascripts/jquery.livequery.js +250 -0
- data/public/javascripts/jquery.localscroll.js +104 -0
- data/public/javascripts/jquery.scrollTo.js +150 -0
- data/public/javascripts/jquery.tools.min.js +17 -0
- data/public/javascripts/jquery.treeTable.min.js +165 -0
- data/public/javascripts/json.js +153 -0
- data/public/javascripts/jsonedit_main.js +675 -0
- data/public/javascripts/yetii-min.js +1 -0
- data/public/stylesheets/base.css +336 -0
- data/public/stylesheets/chef.css +157 -0
- data/public/stylesheets/images/ui-bg_diagonals-small_0_aaaaaa_40x40.png +0 -0
- data/public/stylesheets/images/ui-bg_diagonals-thick_15_444444_40x40.png +0 -0
- data/public/stylesheets/images/ui-bg_glass_100_f0f0f0_1x400.png +0 -0
- data/public/stylesheets/images/ui-bg_glass_50_99c2ff_1x400.png +0 -0
- data/public/stylesheets/images/ui-bg_glass_55_fbf5d0_1x400.png +0 -0
- data/public/stylesheets/images/ui-bg_glass_80_e6e6e6_1x400.png +0 -0
- data/public/stylesheets/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/public/stylesheets/images/ui-bg_highlight-hard_100_f9f9f9_1x100.png +0 -0
- data/public/stylesheets/images/ui-bg_highlight-soft_100_e7eef3_1x100.png +0 -0
- data/public/stylesheets/images/ui-icons_222222_256x240.png +0 -0
- data/public/stylesheets/images/ui-icons_2694e8_256x240.png +0 -0
- data/public/stylesheets/images/ui-icons_2e83ff_256x240.png +0 -0
- data/public/stylesheets/images/ui-icons_72a7cf_256x240.png +0 -0
- data/public/stylesheets/images/ui-icons_888888_256x240.png +0 -0
- data/public/stylesheets/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/public/stylesheets/images/ui-icons_ffffff_256x240.png +0 -0
- data/public/stylesheets/jquery-ui-1.7.1.custom.css +404 -0
- data/public/stylesheets/jquery.treeTable.css +43 -0
- data/public/stylesheets/jsonedit_main.css +280 -0
- data/public/stylesheets/themes/bec-green/style.css +290 -0
- data/public/stylesheets/themes/bec/style.css +301 -0
- data/public/stylesheets/themes/blue/style.css +280 -0
- data/public/stylesheets/themes/default/style.css +267 -0
- data/public/stylesheets/themes/djime-cerulean/style.css +298 -0
- data/public/stylesheets/themes/kathleene/style.css +272 -0
- data/public/stylesheets/themes/orange/style.css +263 -0
- data/public/stylesheets/themes/reidb-greenish/style.css +301 -0
- data/stubs/app/controllers/application.rb +2 -0
- data/stubs/app/controllers/main.rb +2 -0
- metadata +399 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
.block#block-forms
|
|
2
|
+
.content
|
|
3
|
+
%h2.title Search Indexes
|
|
4
|
+
.inner
|
|
5
|
+
- @search_indexes.sort{ |a,b| a.to_s <=> b.to_s}.each do |index|
|
|
6
|
+
%form.form{ :method => "get", "accept-charset" => "UTF-8", :action => slice_url(:search, { :id => index[0]})}
|
|
7
|
+
.group.label= text_field :name => "q", :label => "Query (i.e. attribute:value, leave empty to search all) "
|
|
8
|
+
.group= submit "Search #{index[0]}"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
.block#block-tables
|
|
2
|
+
.content
|
|
3
|
+
%h2.title Search Results
|
|
4
|
+
.inner
|
|
5
|
+
- @results.each do |result|
|
|
6
|
+
%table.table.search{:width => '400px'}
|
|
7
|
+
%tr
|
|
8
|
+
%th.first Name
|
|
9
|
+
%th.last
|
|
10
|
+
- @results.each do |result|
|
|
11
|
+
- result.each do |o|
|
|
12
|
+
%tr
|
|
13
|
+
%td= link_to(o.name, slice_url(@type.to_sym, determine_name(@type.to_sym, o)))
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
.block#block-tables
|
|
2
|
+
.content
|
|
3
|
+
%h2.title Status
|
|
4
|
+
.inner
|
|
5
|
+
%table.table
|
|
6
|
+
%tr
|
|
7
|
+
%th.first Node Name
|
|
8
|
+
%th Platform
|
|
9
|
+
%th FQDN
|
|
10
|
+
%th IP Address
|
|
11
|
+
%th Uptime
|
|
12
|
+
%th Last Check-in
|
|
13
|
+
%th.last Run List
|
|
14
|
+
- if @status.empty?
|
|
15
|
+
%tr
|
|
16
|
+
%td{:colspan => 7}= "You appear to have no nodes - try connecting one, or creating or editing a #{link_to('client', slice_url(:clients))}"
|
|
17
|
+
- else
|
|
18
|
+
- @status.sort.each_with_index do |node, index|
|
|
19
|
+
%tr{:class => "#{index % 2 == 1 ? 'odd' : 'even'}"}
|
|
20
|
+
%td= link_to(node[1].name, slice_url(:node, node[1].name))
|
|
21
|
+
%td= "#{node[1]["platform"]} #{node[1]["platform_version"]}"
|
|
22
|
+
%td= node[1]["fqdn"]
|
|
23
|
+
%td= node[1]["ipaddress"]
|
|
24
|
+
%td
|
|
25
|
+
.accordion
|
|
26
|
+
-unless node[1]["uptime"].nil?
|
|
27
|
+
= link_to(node[1]["uptime"].split(" ")[0..1].join(" ") , "#", :class => 'tooltip')
|
|
28
|
+
.tooltip
|
|
29
|
+
%table.table.tooltip
|
|
30
|
+
%tr
|
|
31
|
+
%td= node[1]["uptime"]
|
|
32
|
+
|
|
33
|
+
- unless node[1]["ohai_time"].nil?
|
|
34
|
+
- current_time = DateTime.now
|
|
35
|
+
- date = DateTime.parse(Time.at(node[1]["ohai_time"]).to_s)
|
|
36
|
+
- hours, minutes, seconds, frac = DateTime.day_fraction_to_time(current_time - date)
|
|
37
|
+
- hours_text = "#{hours} hour#{hours == 1 ? '' : 's'}"
|
|
38
|
+
- minutes_text = "#{minutes} minute#{minutes == 1 ? '' : 's'}"
|
|
39
|
+
%td.flash
|
|
40
|
+
- status_class = ""
|
|
41
|
+
- if hours > 24
|
|
42
|
+
- status_class = "message error"
|
|
43
|
+
- elsif hours > 1
|
|
44
|
+
- status_class = "message warning"
|
|
45
|
+
%div{ :class => status_class }
|
|
46
|
+
.accordion
|
|
47
|
+
- if hours > 48
|
|
48
|
+
- status_msg = "> #{hours/24} days ago"
|
|
49
|
+
- elsif hours > 0
|
|
50
|
+
- status_msg = "> #{hours_text} ago"
|
|
51
|
+
- elsif minutes < 1
|
|
52
|
+
- status_msg = "< 1 minute ago"
|
|
53
|
+
- else
|
|
54
|
+
- status_msg = "#{minutes_text} ago"
|
|
55
|
+
= link_to(status_msg, "#", :class=> 'tooltip')
|
|
56
|
+
.tooltip
|
|
57
|
+
%table.table.tooltip
|
|
58
|
+
%tr
|
|
59
|
+
%td
|
|
60
|
+
= date
|
|
61
|
+
%br
|
|
62
|
+
- if hours == 0
|
|
63
|
+
= "#{minutes_text} ago"
|
|
64
|
+
- else
|
|
65
|
+
= "#{hours_text}, #{minutes_text} ago"
|
|
66
|
+
- else
|
|
67
|
+
%td Not Checked In
|
|
68
|
+
- unless node[1].run_list.nil?
|
|
69
|
+
%td
|
|
70
|
+
.accordion
|
|
71
|
+
= link_to("Run List", "#", :class => 'tooltip')
|
|
72
|
+
.tooltip
|
|
73
|
+
%table.table.tooltip
|
|
74
|
+
%tr
|
|
75
|
+
%th.first Position
|
|
76
|
+
%th Name
|
|
77
|
+
%th.last Type
|
|
78
|
+
- if node[1].run_list.empty?
|
|
79
|
+
%tr
|
|
80
|
+
%td{:colspan => 2} This node has no roles or recipes applied.
|
|
81
|
+
- else
|
|
82
|
+
- rl = Chef::RunList.new
|
|
83
|
+
- rl.reset!(node[1].run_list)
|
|
84
|
+
-rl.each_index do |i|
|
|
85
|
+
- type, name, fname = rl.parse_entry(rl[i])
|
|
86
|
+
%tr
|
|
87
|
+
%td.position= i
|
|
88
|
+
%td= name
|
|
89
|
+
%td= type
|
|
90
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
.content
|
|
2
|
+
.inner
|
|
3
|
+
-if form_for == "login"
|
|
4
|
+
%div.group
|
|
5
|
+
.text_field= text_field :id => "user_name", :name => "name", :label => "Username: ", :class => "text_field", :value => params.has_key?(:name) ? h(params[:name]) : @user.name
|
|
6
|
+
%br
|
|
7
|
+
|
|
8
|
+
%div.group
|
|
9
|
+
.text_field= password_field :id=> "password", :name => "password", :label=>"Password: ", :class => "password_field"
|
|
10
|
+
%br
|
|
11
|
+
=link_to("Or, log in with OpenID if you have one associated with an existing user account.", slice_url(:openid_consumer))
|
|
12
|
+
%br
|
|
13
|
+
|
|
14
|
+
- if form_for == "edit"
|
|
15
|
+
%div.group.form
|
|
16
|
+
%label.label New Password
|
|
17
|
+
= password_field :id=>"user_new_password", :name => "new_password", :class =>"password_field"
|
|
18
|
+
%span.description New password for the User. Keep blank if you do not want to change password.
|
|
19
|
+
|
|
20
|
+
%div.group.form
|
|
21
|
+
%label.label Confirm New Password
|
|
22
|
+
= password_field :id=>"user_confirm_new_password", :name => "confirm_new_password", :class =>"password_field"
|
|
23
|
+
%span.description Confirm new password for the User. Keep blank if you do not want to change password.
|
|
24
|
+
|
|
25
|
+
- if session[:level] == :admin && edit_admin
|
|
26
|
+
%div.group.form
|
|
27
|
+
%label.label Admin
|
|
28
|
+
= text_field :id => "user_admin", :name => "admin", :class => "text_field", :value => @user.admin
|
|
29
|
+
%span.description Whether or not the User is an admin.
|
|
30
|
+
|
|
31
|
+
%div.group.form
|
|
32
|
+
%label.label OpenID Association
|
|
33
|
+
= text_field :id => "openid", :name => "openid", :class => "text_field", :value => @user.openid
|
|
34
|
+
%span.description Associate an OpenID with the user account, leave blank if you do not want to associate one.
|
|
35
|
+
|
|
36
|
+
= form(:action => form_url, :method => :post, :id => form_id, :class => 'form') do
|
|
37
|
+
%div.group
|
|
38
|
+
.actions-bar
|
|
39
|
+
.actions= submit submit_name, :id => submit_id, :class => 'button'
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
.secondary-navigation
|
|
2
|
+
%ul
|
|
3
|
+
%li{ :class => "first #{active == 'index' ? "active" : ''}"}= link_to('List', slice_url(:users))
|
|
4
|
+
%li{ :class => (active == 'create' ? "active" : '')}= link_to('Create', slice_url(:users_new))
|
|
5
|
+
- if active != 'create' && active != 'index'
|
|
6
|
+
%li{ :class => (active == 'show' ? "active" : '')}= link_to('Show', slice_url(:users_show))
|
|
7
|
+
%li{ :class => (active == 'edit' ? "active" : '')}= link_to('Edit', slice_url(:users_edit, :user_id => params[:user_id]))
|
|
8
|
+
%li= link_to('Delete', slice_url(:users_delete, :user_id => params[:user_id]), :method => "delete", :confirm => "Really delete user #{params[:user_id]}? There is no undo.")
|
|
9
|
+
.clear
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
.block#block-tables
|
|
2
|
+
.content
|
|
3
|
+
%h2.title= "User: #{h @user.name}"
|
|
4
|
+
.inner
|
|
5
|
+
= partial('navigation', :active => 'edit')
|
|
6
|
+
= partial('form', :header => "Edit User #{@user.name}", :form_id => 'edit_user', :submit_name => "Save User", :submit_id => "edit_user_button", :form_for => 'edit', :form_url => slice_url(:users_update, @user.name) )
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.block#block-tables
|
|
2
|
+
.content
|
|
3
|
+
%h2.title Users
|
|
4
|
+
.inner
|
|
5
|
+
= partial('navigation', :active => 'index')
|
|
6
|
+
.content
|
|
7
|
+
.inner
|
|
8
|
+
%table.table
|
|
9
|
+
%tr
|
|
10
|
+
%th.first{:colspan => 2} Username
|
|
11
|
+
%th
|
|
12
|
+
%th.last
|
|
13
|
+
- even = false
|
|
14
|
+
- @users.sort.each do |user, user_url|
|
|
15
|
+
%tr{:class => even ? "even": "odd" }
|
|
16
|
+
%td{:colspan => 2}= link_to user, slice_url(:users_show, :user_id => user)
|
|
17
|
+
%td
|
|
18
|
+
= link_to('Edit', slice_url(:users_edit, :user_id => user))
|
|
19
|
+
|
|
|
20
|
+
= link_to('Delete', slice_url(:users_delete, :user_id => user), :method => "delete", :confirm => "Really delete User #{user}? There is no undo.")
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
- throw_content(:sidebar_block_notice) do
|
|
2
|
+
%h4 Where do I get a Login?
|
|
3
|
+
%p Any existing Admin level user can create new users.
|
|
4
|
+
%p To create the first user, please login with the default admin credential, which by default is:
|
|
5
|
+
%p username: admin, password: p@ssw0rd1 (May be different if you've set it in Chef::Config)
|
|
6
|
+
%b Please change the default password immediately after logging in!
|
|
7
|
+
%p Once you have an User, you can associate an OpenID with the User and login using the OpenID as the User.
|
|
8
|
+
%p Administrators can associate OpenID to any User.
|
|
9
|
+
|
|
10
|
+
.block#block-forms
|
|
11
|
+
.content
|
|
12
|
+
%h2.title Login
|
|
13
|
+
.inner
|
|
14
|
+
= partial('form', :header => "Login", :form_id => 'login', :submit_name => "login", :submit_id => "login_button", :form_for => 'login', :form_url => slice_url(:users_login_exec) )
|
|
15
|
+
|
|
16
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
.block#block-forms
|
|
2
|
+
.content
|
|
3
|
+
%h2.title Create New User
|
|
4
|
+
.inner
|
|
5
|
+
= partial('navigation', :active => 'create')
|
|
6
|
+
.content
|
|
7
|
+
.inner
|
|
8
|
+
%form.form{ :method => "get", "accept-charset" => "UTF-8", :action => slice_url(:users_create) }
|
|
9
|
+
%table.table
|
|
10
|
+
%tr
|
|
11
|
+
%td= "Username"
|
|
12
|
+
%td= text_field :name
|
|
13
|
+
%tr
|
|
14
|
+
%td= "Password"
|
|
15
|
+
%td= password_field :password
|
|
16
|
+
%tr
|
|
17
|
+
%td= "Confirm Password"
|
|
18
|
+
%td= password_field :password2
|
|
19
|
+
%tr
|
|
20
|
+
%td= "Admin"
|
|
21
|
+
%td= check_box :name => "admin", :value => "1"
|
|
22
|
+
%tr
|
|
23
|
+
%td= "OpenID (optional)"
|
|
24
|
+
%td= text_field :openid
|
|
25
|
+
|
|
26
|
+
.group.navform
|
|
27
|
+
.button= submit "Create"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
.block#block-tables
|
|
2
|
+
.content
|
|
3
|
+
%h2.title= "User: #{h @user.name}"
|
|
4
|
+
.inner
|
|
5
|
+
= partial("navigation", :active => "show")
|
|
6
|
+
.content
|
|
7
|
+
.inner
|
|
8
|
+
.left
|
|
9
|
+
%h3 Admin
|
|
10
|
+
= @user.admin
|
|
11
|
+
.left
|
|
12
|
+
%h3 OpenID
|
|
13
|
+
= @user.openid || "No OpenID associated to this user account."
|
data/config.ru
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'merb-core'
|
|
3
|
+
|
|
4
|
+
Dir.chdir(::File.dirname(__FILE__))
|
|
5
|
+
|
|
6
|
+
Merb::Config.setup(:merb_root => ::File.expand_path(::File.dirname(__FILE__)),
|
|
7
|
+
:environment => ENV['RACK_ENV'] || "development",
|
|
8
|
+
:fork_for_class_load => false,
|
|
9
|
+
:init_file => ::File.dirname(__FILE__) / "config/init.rb")
|
|
10
|
+
Merb.environment = Merb::Config[:environment]
|
|
11
|
+
Merb.root = Merb::Config[:merb_root]
|
|
12
|
+
|
|
13
|
+
# Uncomment if your app is mounted at a suburi
|
|
14
|
+
#if prefix = ::Merb::Config[:path_prefix]
|
|
15
|
+
# use Merb::Rack::PathPrefix, prefix
|
|
16
|
+
#end
|
|
17
|
+
|
|
18
|
+
# comment this out if you are running merb behind a load balancer
|
|
19
|
+
# that serves static files
|
|
20
|
+
# use Merb::Rack::Static, Merb.dir_for(:public)
|
|
21
|
+
use Merb::Rack::Static, Merb.root+"/public"
|
|
22
|
+
|
|
23
|
+
require 'merb-slices'
|
|
24
|
+
slice_name = "chef-server-webui"
|
|
25
|
+
|
|
26
|
+
if ::File.exists?(slice_file = ::File.join(Merb.root, 'lib', "#{slice_name}.rb"))
|
|
27
|
+
Merb::BootLoader.before_app_loads do
|
|
28
|
+
$SLICE_MODULE = Merb::Slices.filename2module(slice_file)
|
|
29
|
+
require slice_file
|
|
30
|
+
end
|
|
31
|
+
Merb::BootLoader.after_app_loads do
|
|
32
|
+
# See Merb::Slices::ModuleMixin - $SLICE_MODULE is used as a flag
|
|
33
|
+
Merb::Router.prepare do
|
|
34
|
+
slice($SLICE_MODULE)
|
|
35
|
+
slice_id = slice_name.gsub('-', '_').to_sym
|
|
36
|
+
slice_routes = Merb::Slices.named_routes[slice_id] || {}
|
|
37
|
+
|
|
38
|
+
# Setup a / root path matching route - try several defaults
|
|
39
|
+
route = slice_routes[:home] || slice_routes[:index]
|
|
40
|
+
if route
|
|
41
|
+
params = route.params.inject({}) do |hsh,(k,v)|
|
|
42
|
+
hsh[k] = v.gsub("\"", '') if k == :controller || k == :action
|
|
43
|
+
hsh
|
|
44
|
+
end
|
|
45
|
+
match('/').to(params)
|
|
46
|
+
else
|
|
47
|
+
match('/').to(:controller => 'merb_slices', :action => 'index')
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
else
|
|
52
|
+
puts "No slice found (expected: #{slice_name})"
|
|
53
|
+
exit
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class ::MerbSlices < Merb::Controller
|
|
57
|
+
|
|
58
|
+
def index
|
|
59
|
+
html = "<h1>#{slice.name}</h1><p>#{slice.description}</p>"
|
|
60
|
+
html << "<h2>Routes</h2><ul>"
|
|
61
|
+
sorted_names = slice.named_routes.keys.map { |k| [k.to_s, k] }.sort_by { |pair| pair.first }
|
|
62
|
+
sorted_names.each do |_, name|
|
|
63
|
+
if name != :default && (route = slice.named_routes[name])
|
|
64
|
+
if name == :index
|
|
65
|
+
html << %Q[<li><a href="#{url(route.name)}" title="visit #{name}">#{name}: #{route.inspect}</a></li>]
|
|
66
|
+
else
|
|
67
|
+
html << %Q[<li>#{name}: #{route.inspect}</li>]
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
html << "</ul>"
|
|
72
|
+
html
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def slice
|
|
78
|
+
@slice ||= Merb::Slices.slices.first
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
Merb::BootLoader.run
|
|
84
|
+
run Merb::Rack::Application.new
|
data/config/init.rb
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#
|
|
2
|
+
# ==== Standalone Chefserver configuration
|
|
3
|
+
#
|
|
4
|
+
# This configuration/environment file is only loaded by bin/slice, which can be
|
|
5
|
+
# used during development of the slice. It has no effect on this slice being
|
|
6
|
+
# loaded in a host application. To run your slice in standalone mode, just
|
|
7
|
+
# run 'slice' from its directory. The 'slice' command is very similar to
|
|
8
|
+
# the 'merb' command, and takes all the same options, including -i to drop
|
|
9
|
+
# into an irb session for example.
|
|
10
|
+
#
|
|
11
|
+
# The usual Merb configuration directives and init.rb setup methods apply,
|
|
12
|
+
# including use_orm and before_app_loads/after_app_loads.
|
|
13
|
+
#
|
|
14
|
+
# If you need need different configurations for different environments you can
|
|
15
|
+
# even create the specific environment file in config/environments/ just like
|
|
16
|
+
# in a regular Merb application.
|
|
17
|
+
#
|
|
18
|
+
# In fact, a slice is no different from a normal # Merb application - it only
|
|
19
|
+
# differs by the fact that seamlessly integrates into a so called 'host'
|
|
20
|
+
# application, which in turn can override or finetune the slice implementation
|
|
21
|
+
# code and views.
|
|
22
|
+
#
|
|
23
|
+
|
|
24
|
+
$: << File.join(File.dirname(__FILE__), "..", "..", "chef", "lib")
|
|
25
|
+
require 'chef'
|
|
26
|
+
|
|
27
|
+
merb_gems_version = " > 1.0"
|
|
28
|
+
dependency "merb-haml", merb_gems_version
|
|
29
|
+
dependency "merb-assets", merb_gems_version
|
|
30
|
+
dependency "merb-helpers", merb_gems_version
|
|
31
|
+
dependency "chef", :immediate=>true unless defined?(Chef)
|
|
32
|
+
|
|
33
|
+
use_template_engine :haml
|
|
34
|
+
|
|
35
|
+
Merb::Config.use do |c|
|
|
36
|
+
# BUGBUG [cb] For some reason, this next line
|
|
37
|
+
# causes a merb slice to vomit around openid
|
|
38
|
+
#c[:fork_for_class_load] = false
|
|
39
|
+
c[:session_id_key] = '_chef_server_session_id'
|
|
40
|
+
c[:session_secret_key] = Chef::Config.manage_secret_key
|
|
41
|
+
c[:session_store] = 'cookie'
|
|
42
|
+
c[:exception_details] = true
|
|
43
|
+
c[:reload_classes] = true
|
|
44
|
+
c[:log_level] = Chef::Config[:log_level]
|
|
45
|
+
if Chef::Config[:log_location].kind_of?(String)
|
|
46
|
+
c[:log_file] = Chef::Config[:log_location]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
data/config/router.rb
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
if defined?(Merb::Plugins)
|
|
2
|
+
$:.unshift File.dirname(__FILE__)
|
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "..", "chef", "lib")
|
|
4
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "..", "chef-solr", "lib")
|
|
5
|
+
|
|
6
|
+
dependency 'merb-slices', :immediate => true
|
|
7
|
+
dependency 'chef', :immediate=>true unless defined?(Chef)
|
|
8
|
+
require 'chef/role'
|
|
9
|
+
require 'chef/webui_user'
|
|
10
|
+
|
|
11
|
+
require 'coderay'
|
|
12
|
+
|
|
13
|
+
Merb::Plugins.add_rakefiles "chef-server-webui/merbtasks", "chef-server-webui/slicetasks", "chef-server-webui/spectasks"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# Register the Slice for the current host application
|
|
17
|
+
Merb::Slices::register(__FILE__)
|
|
18
|
+
|
|
19
|
+
Merb.disable :json
|
|
20
|
+
|
|
21
|
+
# Slice configuration - set this in a before_app_loads callback.
|
|
22
|
+
# By default a Slice uses its own layout, so you can switch to
|
|
23
|
+
# the main application layout or no layout at all if needed.
|
|
24
|
+
#
|
|
25
|
+
# Configuration options:
|
|
26
|
+
# :layout - the layout to use; defaults to :chefserverslice
|
|
27
|
+
# :mirror - which path component types to use on copy operations; defaults to all
|
|
28
|
+
Merb::Slices::config[:chef_server_webui][:layout] ||= :chef_server_webui
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# All Slice code is expected to be namespaced inside a module
|
|
32
|
+
module ChefServerWebui
|
|
33
|
+
# Slice metadata
|
|
34
|
+
self.description = "ChefServerWebui.. serving up some piping hot infrastructure!"
|
|
35
|
+
self.version = Chef::VERSION
|
|
36
|
+
self.author = "Opscode"
|
|
37
|
+
|
|
38
|
+
# Stub classes loaded hook - runs before LoadClasses BootLoader
|
|
39
|
+
# right after a slice's classes have been loaded internally.
|
|
40
|
+
def self.loaded
|
|
41
|
+
Chef::Config[:node_name] = Chef::Config[:web_ui_client_name]
|
|
42
|
+
Chef::Config[:client_key] = Chef::Config[:web_ui_key]
|
|
43
|
+
# Create the default admin user "admin" if no admin user exists
|
|
44
|
+
unless Chef::WebUIUser.admin_exist
|
|
45
|
+
user = Chef::WebUIUser.new
|
|
46
|
+
user.name = Chef::Config[:web_ui_admin_user_name]
|
|
47
|
+
user.set_password(Chef::Config[:web_ui_admin_default_password])
|
|
48
|
+
user.admin = true
|
|
49
|
+
user.save
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Initialization hook - runs before AfterAppLoads BootLoader
|
|
54
|
+
def self.init
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Activation hook - runs after AfterAppLoads BootLoader
|
|
58
|
+
def self.activate
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Deactivation hook - triggered by Merb::Slices.deactivate(Chefserver)
|
|
62
|
+
def self.deactivate
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Setup routes inside the host application
|
|
66
|
+
#
|
|
67
|
+
# @param scope<Merb::Router::Behaviour>
|
|
68
|
+
# Routes will be added within this scope (namespace). In fact, any
|
|
69
|
+
# router behaviour is a valid namespace, so you can attach
|
|
70
|
+
# routes at any level of your router setup.
|
|
71
|
+
#
|
|
72
|
+
# @note prefix your named routes with :chefserverslice_
|
|
73
|
+
# to avoid potential conflicts with global named routes.
|
|
74
|
+
def self.setup_router(scope)
|
|
75
|
+
|
|
76
|
+
scope.resources :nodes, :id => /[^\/]+/
|
|
77
|
+
scope.resources :clients, :id => /[^\/]+/
|
|
78
|
+
scope.resources :roles
|
|
79
|
+
|
|
80
|
+
scope.match("/status").to(:controller => "status", :action => "index").name(:status)
|
|
81
|
+
|
|
82
|
+
scope.resources :searches, :path => "search", :controller => "search"
|
|
83
|
+
scope.match("/search/:search_id/entries", :method => 'get').to(:controller => "search_entries", :action => "index")
|
|
84
|
+
scope.match("/search/:search_id/entries", :method => 'post').to(:controller => "search_entries", :action => "create")
|
|
85
|
+
scope.match("/search/:search_id/entries/:id", :method => 'get').to(:controller => "search_entries", :action => "show")
|
|
86
|
+
scope.match("/search/:search_id/entries/:id", :method => 'put').to(:controller => "search_entries", :action => "create")
|
|
87
|
+
scope.match("/search/:search_id/entries/:id", :method => 'post').to(:controller => "search_entries", :action => "update")
|
|
88
|
+
scope.match("/search/:search_id/entries/:id", :method => 'delete').to(:controller => "search_entries", :action => "destroy")
|
|
89
|
+
|
|
90
|
+
scope.match("/cookbooks/_attribute_files").to(:controller => "cookbooks", :action => "attribute_files")
|
|
91
|
+
scope.match("/cookbooks/_recipe_files").to(:controller => "cookbooks", :action => "recipe_files")
|
|
92
|
+
scope.match("/cookbooks/_definition_files").to(:controller => "cookbooks", :action => "definition_files")
|
|
93
|
+
scope.match("/cookbooks/_library_files").to(:controller => "cookbooks", :action => "library_files")
|
|
94
|
+
|
|
95
|
+
scope.match("/cookbooks/:cookbook_id/templates", :cookbook_id => /[\w\.]+/).to(:controller => "cookbook_templates", :action => "index")
|
|
96
|
+
scope.match("/cookbooks/:cookbook_id/libraries", :cookbook_id => /[\w\.]+/).to(:controller => "cookbook_libraries", :action => "index")
|
|
97
|
+
scope.match("/cookbooks/:cookbook_id/definitions", :cookbook_id => /[\w\.]+/).to(:controller => "cookbook_definitions", :action => "index")
|
|
98
|
+
scope.match("/cookbooks/:cookbook_id/recipes", :cookbook_id => /[\w\.]+/).to(:controller => "cookbook_recipes", :action => "index")
|
|
99
|
+
scope.match("/cookbooks/:cookbook_id/attributes", :cookbook_id => /[\w\.]+/).to(:controller => "cookbook_attributes", :action => "index")
|
|
100
|
+
scope.match("/cookbooks/:cookbook_id/files", :cookbook_id => /[\w\.]+/).to(:controller => "cookbook_files", :action => "index")
|
|
101
|
+
|
|
102
|
+
scope.resources :cookbooks
|
|
103
|
+
scope.resources :clients
|
|
104
|
+
|
|
105
|
+
scope.match("/databags/:databag_id/databag_items", :method => 'get').to(:controller => "databags", :action => "show", :id=>":databag_id")
|
|
106
|
+
|
|
107
|
+
scope.resources :databags do |s|
|
|
108
|
+
s.resources :databag_items
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
scope.match('/openid/consumer').to(:controller => 'openid_consumer', :action => 'index').name(:openid_consumer)
|
|
112
|
+
scope.match('/openid/consumer/start').to(:controller => 'openid_consumer', :action => 'start').name(:openid_consumer_start)
|
|
113
|
+
scope.match('/openid/consumer/login').to(:controller => 'openid_consumer', :action => 'login').name(:openid_consumer_login)
|
|
114
|
+
scope.match('/openid/consumer/complete').to(:controller => 'openid_consumer', :action => 'complete').name(:openid_consumer_complete)
|
|
115
|
+
scope.match('/openid/consumer/logout').to(:controller => 'openid_consumer', :action => 'logout').name(:openid_consumer_logout)
|
|
116
|
+
|
|
117
|
+
scope.match('/login').to(:controller=>'users', :action=>'login').name(:users_login)
|
|
118
|
+
scope.match('/logout').to(:controller => 'users', :action => 'logout').name(:users_logout)
|
|
119
|
+
|
|
120
|
+
scope.match('/users').to(:controller => 'users', :action => 'index').name(:users)
|
|
121
|
+
scope.match('/users/create').to(:controller => 'users', :action => 'create').name(:users_create)
|
|
122
|
+
scope.match('/users/start').to(:controller => 'users', :action => 'start').name(:users_start)
|
|
123
|
+
|
|
124
|
+
scope.match('/users/login').to(:controller => 'users', :action => 'login').name(:users_login)
|
|
125
|
+
scope.match('/users/login_exec').to(:controller => 'users', :action => 'login_exec').name(:users_login_exec)
|
|
126
|
+
scope.match('/users/complete').to(:controller => 'users', :action => 'complete').name(:users_complete)
|
|
127
|
+
scope.match('/users/logout').to(:controller => 'users', :action => 'logout').name(:users_logout)
|
|
128
|
+
scope.match('/users/new').to(:controller => 'users', :action => 'new').name(:users_new)
|
|
129
|
+
scope.match('/users/:user_id/edit').to(:controller => 'users', :action => 'edit').name(:users_edit)
|
|
130
|
+
scope.match('/users/:user_id').to(:controller => 'users', :action => 'show').name(:users_show)
|
|
131
|
+
scope.match('/users/:user_id/delete', :method => 'delete').to(:controller => 'users', :action => 'destroy').name(:users_delete)
|
|
132
|
+
scope.match('/users/:user_id/update', :method => 'put').to(:controller => 'users', :action => 'update').name(:users_update)
|
|
133
|
+
|
|
134
|
+
scope.match('/').to(:controller => 'nodes', :action =>'index').name(:top)
|
|
135
|
+
|
|
136
|
+
# enable slice-level default routes by default
|
|
137
|
+
# scope.default_routes
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Setup the slice layout for ChefServerWebui
|
|
143
|
+
#
|
|
144
|
+
# Use ChefServerWebui.push_path and ChefServerWebui.push_app_path
|
|
145
|
+
# to set paths to chefserver-level and app-level paths. Example:
|
|
146
|
+
#
|
|
147
|
+
# ChefServerWebui.push_path(:application, ChefServerWebui.root)
|
|
148
|
+
# ChefServerWebui.push_app_path(:application, Merb.root / 'slices' / 'chefserverslice')
|
|
149
|
+
# ...
|
|
150
|
+
#
|
|
151
|
+
# Any component path that hasn't been set will default to ChefServerWebui.root
|
|
152
|
+
#
|
|
153
|
+
# Or just call setup_default_structure! to setup a basic Merb MVC structure.
|
|
154
|
+
ChefServerWebui.setup_default_structure!
|
|
155
|
+
end
|