chef-server-webui 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
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