foreman_content 0.1

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 (81) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +113 -0
  3. data/Rakefile +111 -0
  4. data/app/assets/javascripts/content/content.js +12 -0
  5. data/app/assets/stylesheets/content/application.css +13 -0
  6. data/app/controllers/content/api/repositories_controller.rb +27 -0
  7. data/app/controllers/content/gpg_keys_controller.rb +42 -0
  8. data/app/controllers/content/products_controller.rb +51 -0
  9. data/app/controllers/content/repositories_controller.rb +57 -0
  10. data/app/helpers/content/application_helper.rb +5 -0
  11. data/app/helpers/content/repositories_helper.rb +56 -0
  12. data/app/models/content/custom_repository_paths.rb +27 -0
  13. data/app/models/content/environment_product.rb +19 -0
  14. data/app/models/content/gpg_key.rb +32 -0
  15. data/app/models/content/host_product.rb +20 -0
  16. data/app/models/content/hostgroup_product.rb +19 -0
  17. data/app/models/content/operatingsystem_repository.rb +19 -0
  18. data/app/models/content/orchestration/pulp.rb +93 -0
  19. data/app/models/content/product.rb +28 -0
  20. data/app/models/content/product_operatingsystem.rb +19 -0
  21. data/app/models/content/remote/pulp/repository.rb +46 -0
  22. data/app/models/content/repository.rb +70 -0
  23. data/app/models/content/validators/content_validator.rb +25 -0
  24. data/app/models/content/validators/description_format.rb +24 -0
  25. data/app/models/content/validators/name_format.rb +40 -0
  26. data/app/models/content/validators/no_trailing_space.rb +27 -0
  27. data/app/models/setting/content.rb +42 -0
  28. data/app/overrides/add_host_conent_tab.rb +9 -0
  29. data/app/overrides/add_hostgroup_conent_tab.rb +9 -0
  30. data/app/overrides/add_os_conent_tab.rb +9 -0
  31. data/app/services/content/pulp_event_handler.rb +25 -0
  32. data/app/views/content/gpg_keys/_form.html.erb +8 -0
  33. data/app/views/content/gpg_keys/edit.html.erb +3 -0
  34. data/app/views/content/gpg_keys/index.html.erb +20 -0
  35. data/app/views/content/gpg_keys/new.html.erb +3 -0
  36. data/app/views/content/products/_form.html.erb +26 -0
  37. data/app/views/content/products/_form_tab.html.erb +3 -0
  38. data/app/views/content/products/_host_tab_pane.html.erb +5 -0
  39. data/app/views/content/products/_hostgroup_tab_pane.html.erb +5 -0
  40. data/app/views/content/products/_operatingsystem_tab_pane.html.erb +5 -0
  41. data/app/views/content/products/edit.html.erb +3 -0
  42. data/app/views/content/products/index.html.erb +27 -0
  43. data/app/views/content/products/new.html.erb +3 -0
  44. data/app/views/content/products/welcome.html.erb +8 -0
  45. data/app/views/content/repositories/_form.html.erb +30 -0
  46. data/app/views/content/repositories/edit.html.erb +3 -0
  47. data/app/views/content/repositories/index.html.erb +32 -0
  48. data/app/views/content/repositories/new.html.erb +3 -0
  49. data/app/views/content/repositories/show.html.erb +98 -0
  50. data/app/views/content/repositories/welcome.html.erb +8 -0
  51. data/config/routes.rb +36 -0
  52. data/db/migrate/20130702140034_create_content_repositories.rb +19 -0
  53. data/db/migrate/20130702162629_create_content_products.rb +10 -0
  54. data/db/migrate/20130709001120_create_content_gpg_keys.rb +10 -0
  55. data/db/migrate/20130717032320_create_content_environments_products.rb +9 -0
  56. data/db/migrate/20130722084911_create_content_operatingsystem_repositories.rb +9 -0
  57. data/db/migrate/20130723084911_create_content_hostgroup_products.rb +9 -0
  58. data/db/migrate/20130723124911_create_content_host_products.rb +9 -0
  59. data/db/migrate/20130729032320_create_content_product_operatingsystems.rb +9 -0
  60. data/lib/content/engine.rb +59 -0
  61. data/lib/content/version.rb +3 -0
  62. data/lib/content_environment.rb +13 -0
  63. data/lib/content_home_helper_patch.rb +23 -0
  64. data/lib/content_host.rb +55 -0
  65. data/lib/content_hostgroup.rb +22 -0
  66. data/lib/content_operatingsystem.rb +17 -0
  67. data/lib/content_redhat.rb +36 -0
  68. data/lib/content_taxonomy.rb +18 -0
  69. data/lib/foreman_content.rb +4 -0
  70. data/lib/pulp_configuration.rb +23 -0
  71. data/lib/tasks/content_tasks.rake +4 -0
  72. data/test/content_test.rb +7 -0
  73. data/test/fixtures/content/products.yml +11 -0
  74. data/test/fixtures/content/repositories.yml +11 -0
  75. data/test/integration/navigation_test.rb +10 -0
  76. data/test/test_helper.rb +23 -0
  77. data/test/unit/content/description_format_validator_test.rb +20 -0
  78. data/test/unit/content/name_format_validator_test.rb +28 -0
  79. data/test/unit/content/product_validation_test.rb +18 -0
  80. data/test/unit/content/repositories_test.rb +7 -0
  81. metadata +194 -0
@@ -0,0 +1,25 @@
1
+ #
2
+ # Copyright 2013 Red Hat, Inc.
3
+ #
4
+ # This software is licensed to you under the GNU General Public
5
+ # License as published by the Free Software Foundation; either version
6
+ # 2 of the License (GPLv2) or (at your option) any later version.
7
+ # There is NO WARRANTY for this software, express or implied,
8
+ # including the implied warranties of MERCHANTABILITY,
9
+ # NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
10
+ # have received a copy of GPLv2 along with this software; if not, see
11
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
12
+
13
+ module Content
14
+ module Validators
15
+ class ContentValidator < ActiveModel::EachValidator
16
+ def validate_each(record, attribute, value)
17
+ begin
18
+ value.encode("UTF-8", 'binary') if !value.blank? && value.respond_to?(:encode)
19
+ rescue
20
+ record.errors[attribute] << (options[:message] || _("cannot be a binary file."))
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ #
2
+ # Copyright 2013 Red Hat, Inc.
3
+ #
4
+ # This software is licensed to you under the GNU General Public
5
+ # License as published by the Free Software Foundation; either version
6
+ # 2 of the License (GPLv2) or (at your option) any later version.
7
+ # There is NO WARRANTY for this software, express or implied,
8
+ # including the implied warranties of MERCHANTABILITY,
9
+ # NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
10
+ # have received a copy of GPLv2 along with this software; if not, see
11
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
12
+
13
+ module Content
14
+ module Validators
15
+ class DescriptionFormat < ActiveModel::EachValidator
16
+ MAX_LENGTH = 1000
17
+ def validate_each(record, attribute, value)
18
+ if value
19
+ record.errors[attribute] << N_("cannot contain more than %s characters") % MAX_LENGTH unless value.length <= MAX_LENGTH
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright 2013 Red Hat, Inc.
4
+ #
5
+ # This software is licensed to you under the GNU General Public
6
+ # License as published by the Free Software Foundation; either version
7
+ # 2 of the License (GPLv2) or (at your option) any later version.
8
+ # There is NO WARRANTY for this software, express or implied,
9
+ # including the implied warranties of MERCHANTABILITY,
10
+ # NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
11
+ # have received a copy of GPLv2 along with this software; if not, see
12
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13
+
14
+ module Content
15
+ module Validators
16
+ class NameFormat < ActiveModel::EachValidator
17
+ MIN_LENGTH = 1
18
+ MAX_LENGTH = 128
19
+
20
+ def validate_each(record, attribute, value)
21
+ if value
22
+ unless value =~ /\A[[:alnum:] _-]*\z/
23
+ record.errors[attribute] << N_("cannot contain characters other than alpha numerals, space, '_', '-'")
24
+ end
25
+ NoTrailingSpace.validate_trailing_space(record, attribute, value)
26
+ NameFormat.validate_length(record, attribute, value)
27
+ else
28
+ record.errors[attribute] << N_("cannot be blank")
29
+ end
30
+ end
31
+
32
+ def self.validate_length(record, attribute, value, max_length = MAX_LENGTH, min_length = MIN_LENGTH)
33
+ if value
34
+ record.errors[attribute] << _("cannot contain more than %s characters") % max_length unless value.length <= max_length
35
+ record.errors[attribute] << _("must contain at least %s character") % min_length unless value.length >= min_length
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,27 @@
1
+ #
2
+ # Copyright 2013 Red Hat, Inc.
3
+ #
4
+ # This software is licensed to you under the GNU General Public
5
+ # License as published by the Free Software Foundation; either version
6
+ # 2 of the License (GPLv2) or (at your option) any later version.
7
+ # There is NO WARRANTY for this software, express or implied,
8
+ # including the implied warranties of MERCHANTABILITY,
9
+ # NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
10
+ # have received a copy of GPLv2 along with this software; if not, see
11
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
12
+
13
+ module Content
14
+ module Validators
15
+ class NoTrailingSpace < ActiveModel::EachValidator
16
+ def validate_each(record, attribute, value)
17
+ NoTrailingSpaceValidator.validate_trailing_space(record, attribute, value)
18
+ end
19
+
20
+ def self.validate_trailing_space(record, attribute, value)
21
+ if value
22
+ record.errors[attribute] << _("must not contain leading or trailing white spaces.") unless value.strip == value
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,42 @@
1
+ class Setting::Content< ::Setting
2
+ BLANK_ATTRS << "use_pulp"
3
+ BLANK_ATTRS << "pulp_url"
4
+ BLANK_ATTRS << "pulp_oauth_secret"
5
+ BLANK_ATTRS << "pulp_oauth_key"
6
+
7
+ def self.load_defaults
8
+ return unless ActiveRecord::Base.connection.table_exists?('settings')
9
+ return unless super
10
+
11
+ Setting.transaction do
12
+ [
13
+ self.set('use_pulp', "Use Pulp to manage content", true),
14
+ self.set('pulp_url', "Pulp URL", "https://127.0.0.1/pulp/api/v2/"),
15
+ self.set('pulp_oauth_secret', "Pulp OAuth Secret", ""),
16
+ self.set('pulp_oauth_key', "Pulp OAuth Key", ""),
17
+ ].compact.each { |s| self.create s.update(:category => "Setting::Content") }
18
+ end
19
+
20
+ true
21
+
22
+ end
23
+
24
+ def self.ensure_sync_notification
25
+ include Rails.application.routes.url_helpers
26
+
27
+ resource = Runcible::Resources::EventNotifier
28
+ url = events_repositories_url(:only_path => false, :host => Setting[:foreman_url])
29
+ type = '*' #resource::EventTypes::REPO_SYNC_COMPLETE
30
+ notifs = resource.list
31
+
32
+ #delete any similar tasks with the wrong url (in case it changed)
33
+ notifs.select { |n| n['event_types'] == [type] && n['notifier_config']['url'] != url }.each do |e|
34
+ resource.delete(e['id'])
35
+ end
36
+
37
+ #only create a notifier if one doesn't exist with the correct url
38
+ exists = notifs.select { |n| n['event_types'] == [type] && n['notifier_config']['url'] == url }
39
+ resource.create(resource::NotifierTypes::REST_API, { :url => url }, [type]) if exists.empty?
40
+ end
41
+
42
+ end
@@ -0,0 +1,9 @@
1
+ Deface::Override.new(:virtual_path => "hosts/_form",
2
+ :name => "add_content_tab",
3
+ :insert_after => 'ul.nav > li a#params-tab',
4
+ :partial => 'content/products/form_tab')
5
+
6
+ Deface::Override.new(:virtual_path => "hosts/_form",
7
+ :name => "add_content_tab_pane",
8
+ :insert_after => 'div.tab-pane#params',
9
+ :partial => 'content/products/host_tab_pane')
@@ -0,0 +1,9 @@
1
+ Deface::Override.new(:virtual_path => "hostgroups/_form",
2
+ :name => "add_content_tab",
3
+ :insert_after => 'ul.nav > li a#params-tab',
4
+ :partial => 'content/products/form_tab')
5
+
6
+ Deface::Override.new(:virtual_path => "hostgroups/_form",
7
+ :name => "add_content_tab_pane",
8
+ :insert_after => 'div.tab-pane#params',
9
+ :partial => 'content/products/hostgroup_tab_pane')
@@ -0,0 +1,9 @@
1
+ Deface::Override.new(:virtual_path => "operatingsystems/_form",
2
+ :name => "add_content_tab",
3
+ :insert_after => 'ul.nav > li a#params-tab',
4
+ :partial => 'content/products/form_tab')
5
+
6
+ Deface::Override.new(:virtual_path => "operatingsystems/_form",
7
+ :name => "add_content_tab_pane",
8
+ :insert_after => 'div.tab-pane#params',
9
+ :partial => 'content/products/operatingsystem_tab_pane')
@@ -0,0 +1,25 @@
1
+ class Content::PulpEventHandler
2
+ attr_reader :type, :status
3
+ delegate :name, :to => :repo
4
+ delegate :logger, :to => :Rails
5
+
6
+ def initialize(pulp_id, params)
7
+ @repo = Content::Repository.where(:pulp_id => pulp_id).first
8
+ @params = params
9
+ @type, @status = parse_type
10
+ log
11
+ end
12
+
13
+ private
14
+ attr_reader :repo, :params
15
+
16
+ def log
17
+ logger.info "Repository #{name} #{type} #{status}"
18
+ end
19
+
20
+ def parse_type
21
+ # converts repo.sync.start to ['sync','start']
22
+ params['event_type'].gsub(/^repo\./, '').split('.')
23
+ end
24
+
25
+ end
@@ -0,0 +1,8 @@
1
+ <%= javascript 'content/application.js' %>
2
+ <%= form_for @gpg_key, :url => (@gpg_key.new_record? ? gpg_keys_path : gpg_key_path(:id => @gpg_key.id)) do |f| %>
3
+ <%= base_errors_for @gpg_key %>
4
+ <%= text_f f, :name %>
5
+ <%= textarea_f f, :content, :rows => 16, :class=>"span7" %>
6
+
7
+ <%= submit_or_cancel f %>
8
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <% title _("Edit Gpg key") %>
2
+
3
+ <%= render :partial => 'form' %>
@@ -0,0 +1,20 @@
1
+
2
+ <% title _("Gpg keys") %>
3
+ <% title_actions display_link_if_authorized(_("New Gpg key"), hash_for_new_gpg_key_path), help_path %>
4
+
5
+ <table class="table table-bordered table-striped">
6
+ <tr>
7
+ <th><%= sort :name, :as => s_("Name") %></th>
8
+ <th></th>
9
+ </tr>
10
+ <% for gpg_key in @gpg_keys %>
11
+ <tr>
12
+ <td><%= link_to_if_authorized(h(gpg_key.name), hash_for_edit_gpg_key_path(:id => gpg_key.name)) %></td>
13
+ <td align="right">
14
+ <%= display_delete_if_authorized hash_for_gpg_key_path(:id => gpg_key.name), :confirm => "Delete #{gpg_key.name}?" %>
15
+ </td>
16
+ </tr>
17
+ <% end %>
18
+ </table>
19
+ <%= page_entries_info @gpg_keys %>
20
+ <%= will_paginate @gpg_keys %>
@@ -0,0 +1,3 @@
1
+ <% title _("New Gpg key") %>
2
+
3
+ <%= render :partial => 'form' %>
@@ -0,0 +1,26 @@
1
+ <%= javascript 'content/content.js' %>
2
+ <%= form_for @product, :url => (@product.new_record? ? products_path : product_path(@product)) do |f| %>
3
+ <%= base_errors_for @product %>
4
+ <ul class="nav nav-tabs" data-tabs="tabs">
5
+ <li class="active"><a href="#primary" data-toggle="tab"><%= _("Product") %></a></li>
6
+ <li><a href="#environments" data-toggle="tab"><%= _("Environments") %></a></li>
7
+ <li><a href="#operatingsystems" data-toggle="tab"><%= _("Operating systems") %></a></li>
8
+ </ul>
9
+ <div class="tab-content">
10
+ <div class="tab-pane active" id="primary">
11
+ <%= text_f f, :name %>
12
+ <%= text_f f, :description %>
13
+ </div>
14
+ <div class="tab-pane" id="environments">
15
+ <%= alert :class => 'controls alert-success', :header => 'Product environments list',
16
+ :text => _('Repositories of this product will be restricted only for hosts in the selected environments.') %>
17
+ <%= multiple_selects(f, :environments, Environment, f.object.environment_ids) %>
18
+ </div>
19
+ <div class="tab-pane" id="operatingsystems">
20
+ <%= alert :class => 'controls alert-success', :header => 'Default Products for operating system',
21
+ :text => _('Repositories of this product will be added to every host that runs the selected operating system, pending environment restriction') %>
22
+ <%= multiple_selects(f, :operatingsystems, Redhat, f.object.operatingsystem_ids,{:label=>"Operating system default products"}) %>
23
+ </div>
24
+ </div>
25
+ <%= submit_or_cancel f %>
26
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <li id="products_tab">
2
+ <a href="#products" data-toggle="tab">Products</a>
3
+ </li>
@@ -0,0 +1,5 @@
1
+ <div class="tab-pane" id="products">
2
+ <%= fields_for @host do |f| %>
3
+ <%= multiple_selects f, :products, Content::Product, @host.all_product_ids , {:disabled => @host.inherited_product_ids}, {} %>
4
+ <% end -%>
5
+ </div>
@@ -0,0 +1,5 @@
1
+ <div class="tab-pane" id="products">
2
+ <%= fields_for @hostgroup do |f| %>
3
+ <%= multiple_selects f, :products, Content::Product, @hostgroup.all_product_ids , {:disabled => @hostgroup.inherited_product_ids}, {} %>
4
+ <% end -%>
5
+ </div>
@@ -0,0 +1,5 @@
1
+ <div class="tab-pane" id="products">
2
+ <%= fields_for @operatingsystem do |f| %>
3
+ <%= multiple_selects f, :products, Content::Product, @operatingsystem.product_ids , {}, {} %>
4
+ <% end -%>
5
+ </div>
@@ -0,0 +1,3 @@
1
+ <% title _("Edit Product") %>
2
+
3
+ <%= render :partial => 'form' %>
@@ -0,0 +1,27 @@
1
+
2
+ <% title _("Products") %>
3
+ <% title_actions display_link_if_authorized(_("New Product"), hash_for_new_product_path), help_path %>
4
+
5
+ <table class="table table-bordered table-striped">
6
+ <tr>
7
+ <th><%= sort :name, :as => s_("Name") %></th>
8
+ <th><%= _("Description") %></th>
9
+ <th><%= _("Repositories") %></th>
10
+ <th></th>
11
+ </tr>
12
+ <% @products.each do |product| %>
13
+ <tr>
14
+ <td><%= link_to_if_authorized(h(product.name), hash_for_edit_product_path(:id => product.name)) %></td>
15
+ <td><%= product.description %></td>
16
+ <td><%= link_to @counter[product.id] || '0', repositories_path(:search => "product=#{product.name}") %></td>
17
+ <td align="right">
18
+ <%= action_buttons(
19
+ display_link_if_authorized(_("Synchronize"), hash_for_sync_product_path(product), :method => :put),
20
+ display_delete_if_authorized(hash_for_product_path(product), :confirm => "Delete #{product.name}?")
21
+ )%>
22
+ </td>
23
+ </tr>
24
+ <% end %>
25
+ </table>
26
+ <%= page_entries_info @products %>
27
+ <%= will_paginate @products %>
@@ -0,0 +1,3 @@
1
+ <% title _("New Product") %>
2
+
3
+ <%= render :partial => 'form' %>
@@ -0,0 +1,8 @@
1
+ <% title_actions link_to(_("New product"), new_product_path) %>
2
+ <% title _("Product configuration") %>
3
+ <div id="welcome">
4
+ <p>
5
+ <%= _("Here come some fancy explanation about products and content in general, bla bla.") %>
6
+ </p>
7
+
8
+ </div>
@@ -0,0 +1,30 @@
1
+ <%= javascript 'content/content.js' %>
2
+ <%= form_for @repository, :url => (@repository.new_record? ? repositories_path : repository_path(:id => @repository.id)) do |f| %>
3
+ <%= base_errors_for @repository %>
4
+ <ul class="nav nav-tabs" data-tabs="tabs">
5
+ <li class="active"><a href="#primary" data-toggle="tab"><%= _("Repository") %></a></li>
6
+ <li><a href="#operatingsystems" data-toggle="tab"><%= _("Operating systems") %></a></li>
7
+ </ul>
8
+ <div class="tab-content">
9
+ <div class="tab-pane active" id="primary">
10
+ <%= select_f f, :product_id, Content::Product.all, :id, :name, {}, {:label => _("Product")} %>
11
+ <%= text_f f, :name %>
12
+ <%= text_f f, :feed, :class => 'span6' %>
13
+ <%= selectable_f f, :content_type, Content::Repository::TYPES %>
14
+ <%= select_f f, :architecture_id, ::Architecture.all, :id, :name, { :include_blank => N_("noarch")} %>
15
+ <%= checkbox_f f, :enabled %>
16
+
17
+ <%= select_f f, :gpg_key_id, Content::GpgKey.all, :id, :name, {:include_blank => true}, {:label => _("GPG Key")} %>
18
+
19
+ <% unless @repository.new_record? %>
20
+ <%= text_f f, :full_path, :disabled => true, :class => 'span6' %>
21
+ <% end %>
22
+ </div>
23
+ <div class="tab-pane" id="operatingsystems">
24
+ <%= alert :class => 'controls alert-success', :header => 'Repository for operating systems',
25
+ :text => _('This Repository will be restricted only to hosts that runs the selected operating system') %>
26
+ <%= multiple_selects(f, :operatingsystems, ::Redhat, f.object.operatingsystem_ids) %>
27
+ </div>
28
+ </div>
29
+ <%= submit_or_cancel f %>
30
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <% title _("Edit Repository") %>
2
+
3
+ <%= render :partial => 'form' %>
@@ -0,0 +1,32 @@
1
+ <% title _("Repositories") %>
2
+ <% title_actions display_link_if_authorized(_("New Repository"), hash_for_new_repository_path), help_path %>
3
+
4
+ <table class="table table-bordered table-striped">
5
+ <tr>
6
+ <th><%= sort :name, :as => s_("Name") %></th>
7
+ <th><%= _("Product") %></th>
8
+ <th><%= _("Operating system") %></th>
9
+ <th><%= _("Last sync status") %></th>
10
+ <th><%= _("Content type") %></th>
11
+ <th></th>
12
+ </tr>
13
+ <% @repositories.each do |repository| %>
14
+ <tr>
15
+ <td><%= link_to_if_authorized(h(repository.name), hash_for_repository_path(repository)) %></td>
16
+ <td><%= repository.product %></td>
17
+ <td><%= repository.operatingsystems.map(&:to_label).to_sentence %></td>
18
+ <td><%= sync_status repository %></td>
19
+ <td><%= repository.content_type %></td>
20
+ <td align="right">
21
+ <%= action_buttons(
22
+ display_link_if_authorized(_("Edit"), hash_for_edit_repository_path(repository)),
23
+ display_link_if_authorized(_("Synchronize"), hash_for_sync_repository_path(repository), :method => :put),
24
+ display_delete_if_authorized(hash_for_repository_path(repository), :confirm => "Delete #{repository.name}?")
25
+ )%>
26
+
27
+ </td>
28
+ </tr>
29
+ <% end %>
30
+ </table>
31
+ <%= page_entries_info @repositories %>
32
+ <%= will_paginate @repositories %>