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.
Files changed (207) hide show
  1. data/LICENSE +201 -0
  2. data/README.rdoc +135 -0
  3. data/Rakefile +62 -0
  4. data/app/controllers/application.rb +281 -0
  5. data/app/controllers/clients.rb +120 -0
  6. data/app/controllers/cookbook_attributes.rb +41 -0
  7. data/app/controllers/cookbook_definitions.rb +41 -0
  8. data/app/controllers/cookbook_files.rb +39 -0
  9. data/app/controllers/cookbook_libraries.rb +41 -0
  10. data/app/controllers/cookbook_recipes.rb +40 -0
  11. data/app/controllers/cookbook_templates.rb +57 -0
  12. data/app/controllers/cookbooks.rb +78 -0
  13. data/app/controllers/databag_items.rb +102 -0
  14. data/app/controllers/databags.rb +83 -0
  15. data/app/controllers/exceptions.rb +19 -0
  16. data/app/controllers/main.rb +7 -0
  17. data/app/controllers/nodes.rb +138 -0
  18. data/app/controllers/openid_consumer.rb +154 -0
  19. data/app/controllers/roles.rb +144 -0
  20. data/app/controllers/search.rb +62 -0
  21. data/app/controllers/search_entries.rb +64 -0
  22. data/app/controllers/status.rb +39 -0
  23. data/app/controllers/users.rb +186 -0
  24. data/app/helpers/application_helper.rb +171 -0
  25. data/app/helpers/cookbook_attributes_helper.rb +7 -0
  26. data/app/helpers/cookbook_definitions_helper.rb +8 -0
  27. data/app/helpers/cookbook_files_helper.rb +8 -0
  28. data/app/helpers/cookbook_libraries_helper.rb +7 -0
  29. data/app/helpers/cookbook_recipes_helper.rb +8 -0
  30. data/app/helpers/cookbook_templates_helper.rb +8 -0
  31. data/app/helpers/exceptions_helper.rb +6 -0
  32. data/app/helpers/global_helpers.rb +35 -0
  33. data/app/helpers/nodes_helper.rb +41 -0
  34. data/app/helpers/openid_consumer_helper.rb +8 -0
  35. data/app/helpers/openid_register_helper.rb +8 -0
  36. data/app/helpers/openid_server_helper.rb +6 -0
  37. data/app/helpers/openid_server_helpers.rb +29 -0
  38. data/app/helpers/roles_helper.rb +5 -0
  39. data/app/helpers/search_entries_helper.rb +8 -0
  40. data/app/helpers/search_helper.rb +38 -0
  41. data/app/helpers/status_helper.rb +26 -0
  42. data/app/views/clients/_form.html.haml +22 -0
  43. data/app/views/clients/_navigation.html.haml +9 -0
  44. data/app/views/clients/edit.html.haml +6 -0
  45. data/app/views/clients/index.html.haml +21 -0
  46. data/app/views/clients/new.html.haml +6 -0
  47. data/app/views/clients/show.html.haml +20 -0
  48. data/app/views/cookbooks/index.html.haml +10 -0
  49. data/app/views/cookbooks/show.html.haml +40 -0
  50. data/app/views/databag_items/_form.html.haml +14 -0
  51. data/app/views/databag_items/_navigation.html.haml +9 -0
  52. data/app/views/databag_items/edit.html.haml +6 -0
  53. data/app/views/databag_items/index.html.haml +0 -0
  54. data/app/views/databag_items/new.html.haml +6 -0
  55. data/app/views/databag_items/show.html.haml +9 -0
  56. data/app/views/databags/_form.html.haml +12 -0
  57. data/app/views/databags/_item_navigation.html.haml +8 -0
  58. data/app/views/databags/_navigation.html.haml +9 -0
  59. data/app/views/databags/edit.html.haml +6 -0
  60. data/app/views/databags/index.html.haml +19 -0
  61. data/app/views/databags/new.html.haml +6 -0
  62. data/app/views/databags/show.html.haml +19 -0
  63. data/app/views/exceptions/bad_request.json.erb +1 -0
  64. data/app/views/exceptions/internal_server_error.html.erb +216 -0
  65. data/app/views/exceptions/not_acceptable.html.erb +63 -0
  66. data/app/views/exceptions/not_found.html.erb +47 -0
  67. data/app/views/exceptions/standard_error.html.erb +217 -0
  68. data/app/views/layout/_jsonedit.html.haml +82 -0
  69. data/app/views/layout/chef_server_webui.html.haml +56 -0
  70. data/app/views/layout/login.html.haml +36 -0
  71. data/app/views/main/index.html.erb +1 -0
  72. data/app/views/nodes/_action.html.haml +13 -0
  73. data/app/views/nodes/_form.html.haml +53 -0
  74. data/app/views/nodes/_navigation.html.haml +9 -0
  75. data/app/views/nodes/_resource.html.haml +22 -0
  76. data/app/views/nodes/edit.html.haml +7 -0
  77. data/app/views/nodes/index.html.haml +25 -0
  78. data/app/views/nodes/new.html.haml +6 -0
  79. data/app/views/nodes/show.html.haml +60 -0
  80. data/app/views/openid_consumer/index.html.haml +28 -0
  81. data/app/views/openid_consumer/start.html.haml +4 -0
  82. data/app/views/openid_login/index.html.haml +5 -0
  83. data/app/views/openid_register/index.html.haml +19 -0
  84. data/app/views/openid_register/show.html.haml +7 -0
  85. data/app/views/roles/_form.html.haml +53 -0
  86. data/app/views/roles/_navigation.html.haml +9 -0
  87. data/app/views/roles/edit.html.haml +6 -0
  88. data/app/views/roles/index.html.haml +21 -0
  89. data/app/views/roles/new.html.haml +6 -0
  90. data/app/views/roles/show.html.haml +54 -0
  91. data/app/views/search/_search_form.html.haml +6 -0
  92. data/app/views/search/index.html.haml +8 -0
  93. data/app/views/search/show.html.haml +13 -0
  94. data/app/views/search_entries/index.html.haml +8 -0
  95. data/app/views/search_entries/show.html.haml +7 -0
  96. data/app/views/status/index.html.haml +90 -0
  97. data/app/views/users/_form.html.haml +39 -0
  98. data/app/views/users/_navigation.html.haml +9 -0
  99. data/app/views/users/edit.html.haml +6 -0
  100. data/app/views/users/index.html.haml +20 -0
  101. data/app/views/users/login.html.haml +16 -0
  102. data/app/views/users/new.html.haml +27 -0
  103. data/app/views/users/show.html.haml +13 -0
  104. data/app/views/users/start.html.haml +4 -0
  105. data/config.ru +84 -0
  106. data/config/init.rb +49 -0
  107. data/config/router.rb +6 -0
  108. data/lib/chef-server-webui.rb +155 -0
  109. data/lib/chef-server-webui/merbtasks.rb +103 -0
  110. data/lib/chef-server-webui/slicetasks.rb +20 -0
  111. data/lib/chef-server-webui/spectasks.rb +53 -0
  112. data/public/facebox/README.txt +4 -0
  113. data/public/facebox/b.png +0 -0
  114. data/public/facebox/bl.png +0 -0
  115. data/public/facebox/br.png +0 -0
  116. data/public/facebox/closelabel.gif +0 -0
  117. data/public/facebox/facebox.css +95 -0
  118. data/public/facebox/facebox.js +319 -0
  119. data/public/facebox/loading.gif +0 -0
  120. data/public/facebox/tl.png +0 -0
  121. data/public/facebox/tr.png +0 -0
  122. data/public/images/avatar.png +0 -0
  123. data/public/images/black_big.png +0 -0
  124. data/public/images/indicator.gif +0 -0
  125. data/public/images/jsonedit/add2.png +0 -0
  126. data/public/images/jsonedit/build-button.png +0 -0
  127. data/public/images/jsonedit/bullet.gif +0 -0
  128. data/public/images/jsonedit/bullet_orange.png +0 -0
  129. data/public/images/jsonedit/cross.png +0 -0
  130. data/public/images/jsonedit/delete.png +0 -0
  131. data/public/images/jsonedit/deleted.png +0 -0
  132. data/public/images/jsonedit/json.jpg +0 -0
  133. data/public/images/jsonedit/label.gif +0 -0
  134. data/public/images/jsonedit/minus.gif +0 -0
  135. data/public/images/jsonedit/pixel.gif +0 -0
  136. data/public/images/jsonedit/plus.gif +0 -0
  137. data/public/images/jsonedit/saved.png +0 -0
  138. data/public/images/jsonedit/table_refresh.png +0 -0
  139. data/public/images/jsonedit/value.gif +0 -0
  140. data/public/images/merb.jpg +0 -0
  141. data/public/images/toggle-collapse-dark.png +0 -0
  142. data/public/images/toggle-collapse-light.png +0 -0
  143. data/public/images/toggle-collapse.gif +0 -0
  144. data/public/images/toggle-expand-dark.png +0 -0
  145. data/public/images/toggle-expand-light.png +0 -0
  146. data/public/images/toggle-expand.gif +0 -0
  147. data/public/images/treeBuilderImages/Thumbs.db +0 -0
  148. data/public/images/treeBuilderImages/doc.gif +0 -0
  149. data/public/images/treeBuilderImages/docNode.gif +0 -0
  150. data/public/images/treeBuilderImages/docNodeLast.gif +0 -0
  151. data/public/images/treeBuilderImages/docNodeLastFirst.gif +0 -0
  152. data/public/images/treeBuilderImages/folder.gif +0 -0
  153. data/public/images/treeBuilderImages/folderNode.gif +0 -0
  154. data/public/images/treeBuilderImages/folderNodeFirst.gif +0 -0
  155. data/public/images/treeBuilderImages/folderNodeLast.gif +0 -0
  156. data/public/images/treeBuilderImages/folderNodeLastFirst.gif +0 -0
  157. data/public/images/treeBuilderImages/folderNodeOpen.gif +0 -0
  158. data/public/images/treeBuilderImages/folderNodeOpenFirst.gif +0 -0
  159. data/public/images/treeBuilderImages/folderNodeOpenLast.gif +0 -0
  160. data/public/images/treeBuilderImages/folderNodeOpenLastFirst.gif +0 -0
  161. data/public/images/treeBuilderImages/folderOpen.gif +0 -0
  162. data/public/images/treeBuilderImages/vertLine.gif +0 -0
  163. data/public/javascripts/chef.js +160 -0
  164. data/public/javascripts/jquery-1.3.2.min.js +19 -0
  165. data/public/javascripts/jquery-ui-1.7.1.custom.min.js +65 -0
  166. data/public/javascripts/jquery.editinline.js +108 -0
  167. data/public/javascripts/jquery.jeditable.mini.js +30 -0
  168. data/public/javascripts/jquery.livequery.js +250 -0
  169. data/public/javascripts/jquery.localscroll.js +104 -0
  170. data/public/javascripts/jquery.scrollTo.js +150 -0
  171. data/public/javascripts/jquery.tools.min.js +17 -0
  172. data/public/javascripts/jquery.treeTable.min.js +165 -0
  173. data/public/javascripts/json.js +153 -0
  174. data/public/javascripts/jsonedit_main.js +675 -0
  175. data/public/javascripts/yetii-min.js +1 -0
  176. data/public/stylesheets/base.css +336 -0
  177. data/public/stylesheets/chef.css +157 -0
  178. data/public/stylesheets/images/ui-bg_diagonals-small_0_aaaaaa_40x40.png +0 -0
  179. data/public/stylesheets/images/ui-bg_diagonals-thick_15_444444_40x40.png +0 -0
  180. data/public/stylesheets/images/ui-bg_glass_100_f0f0f0_1x400.png +0 -0
  181. data/public/stylesheets/images/ui-bg_glass_50_99c2ff_1x400.png +0 -0
  182. data/public/stylesheets/images/ui-bg_glass_55_fbf5d0_1x400.png +0 -0
  183. data/public/stylesheets/images/ui-bg_glass_80_e6e6e6_1x400.png +0 -0
  184. data/public/stylesheets/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  185. data/public/stylesheets/images/ui-bg_highlight-hard_100_f9f9f9_1x100.png +0 -0
  186. data/public/stylesheets/images/ui-bg_highlight-soft_100_e7eef3_1x100.png +0 -0
  187. data/public/stylesheets/images/ui-icons_222222_256x240.png +0 -0
  188. data/public/stylesheets/images/ui-icons_2694e8_256x240.png +0 -0
  189. data/public/stylesheets/images/ui-icons_2e83ff_256x240.png +0 -0
  190. data/public/stylesheets/images/ui-icons_72a7cf_256x240.png +0 -0
  191. data/public/stylesheets/images/ui-icons_888888_256x240.png +0 -0
  192. data/public/stylesheets/images/ui-icons_cd0a0a_256x240.png +0 -0
  193. data/public/stylesheets/images/ui-icons_ffffff_256x240.png +0 -0
  194. data/public/stylesheets/jquery-ui-1.7.1.custom.css +404 -0
  195. data/public/stylesheets/jquery.treeTable.css +43 -0
  196. data/public/stylesheets/jsonedit_main.css +280 -0
  197. data/public/stylesheets/themes/bec-green/style.css +290 -0
  198. data/public/stylesheets/themes/bec/style.css +301 -0
  199. data/public/stylesheets/themes/blue/style.css +280 -0
  200. data/public/stylesheets/themes/default/style.css +267 -0
  201. data/public/stylesheets/themes/djime-cerulean/style.css +298 -0
  202. data/public/stylesheets/themes/kathleene/style.css +272 -0
  203. data/public/stylesheets/themes/orange/style.css +263 -0
  204. data/public/stylesheets/themes/reidb-greenish/style.css +301 -0
  205. data/stubs/app/controllers/application.rb +2 -0
  206. data/stubs/app/controllers/main.rb +2 -0
  207. metadata +399 -0
@@ -0,0 +1,6 @@
1
+ %form{ :method => "get", :action => slice_url(:search, { :id => index_name }) }
2
+ Q:
3
+ %input{ :type => "text", :name => "q" }
4
+ A:
5
+ %input{ :type => "text", :name => "a" }
6
+ %input{ :type => "submit", :value => "Search #{index_name}" }
@@ -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,8 @@
1
+ - @entries.each do |result|
2
+ .search_result
3
+ %h3= "#{h result[:index_name]} (#{h result[:id]})"
4
+ %table
5
+ - result.each do |k, v|
6
+ %tr.attr_group
7
+ %td.attr_name= k
8
+ %td.attr_value= v.kind_of?(Array) ? v.join(",") : v
@@ -0,0 +1,7 @@
1
+ .search_result
2
+ %h3= "#{h @entry[:index_name]} (#{h @entry[:id]})"
3
+ %table
4
+ - @entry.each do |k, v|
5
+ %tr.attr_group
6
+ %td.attr_name= k
7
+ %td.attr_value= v.kind_of?(Array) ? v.join(",") : v
@@ -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 = "&gt; #{hours/24} days ago"
49
+ - elsif hours > 0
50
+ - status_msg = "&gt; #{hours_text} ago"
51
+ - elsif minutes < 1
52
+ - status_msg = "&lt; 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 &nbsp;
12
+ %th.last &nbsp;
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."
@@ -0,0 +1,4 @@
1
+ <%= @form_text %>
2
+ <script type="text/javascript">
3
+ document.getElementById('users_form').submit();
4
+ </script>
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,6 @@
1
+ # This file is here so slice can be testing as a stand alone application.
2
+
3
+ #Merb::Router.prepare do
4
+ # resources :roles
5
+ # ...
6
+ #end
@@ -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