foreman_docker 0.2.0 → 1.0.0
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.
- checksums.yaml +4 -4
- data/README.md +10 -3
- data/app/assets/javascripts/foreman_docker/image_step.js +44 -5
- data/app/controllers/concerns/foreman_docker/find_container.rb +19 -0
- data/app/controllers/containers/steps_controller.rb +25 -39
- data/app/controllers/containers_controller.rb +10 -43
- data/app/controllers/image_search_controller.rb +88 -0
- data/app/controllers/registries_controller.rb +47 -0
- data/app/helpers/container_steps_helper.rb +21 -4
- data/app/helpers/containers_helper.rb +19 -7
- data/app/models/concerns/foreman_docker/parameter_validators.rb +11 -0
- data/app/models/container.rb +20 -7
- data/app/models/docker_container_wizard_state.rb +30 -0
- data/app/models/docker_container_wizard_states/configuration.rb +7 -0
- data/app/models/docker_container_wizard_states/environment.rb +21 -0
- data/app/models/docker_container_wizard_states/environment_variable.rb +7 -0
- data/app/models/docker_container_wizard_states/image.rb +11 -0
- data/app/models/docker_container_wizard_states/preliminary.rb +11 -0
- data/app/models/docker_registry.rb +28 -0
- data/app/models/environment_variable.rb +5 -0
- data/app/models/foreman_docker/docker.rb +22 -3
- data/app/models/service/containers.rb +38 -0
- data/app/models/service/registry_api.rb +26 -0
- data/app/views/containers/_list.html.erb +19 -18
- data/app/views/containers/index.html.erb +11 -6
- data/app/views/containers/show.html.erb +26 -7
- data/app/views/containers/steps/_form_buttons.html.erb +1 -1
- data/app/views/containers/steps/configuration.html.erb +2 -2
- data/app/views/containers/steps/environment.html.erb +19 -6
- data/app/views/containers/steps/image.html.erb +58 -39
- data/app/views/containers/steps/preliminary.html.erb +21 -4
- data/app/views/foreman_docker/common_parameters/_environment_variable.html.erb +18 -0
- data/app/views/image_search/_repository_search_results.html.erb +12 -0
- data/app/views/registries/_form.html.erb +26 -0
- data/app/views/registries/edit.html.erb +3 -0
- data/app/views/registries/index.html.erb +28 -0
- data/app/views/registries/new.html.erb +3 -0
- data/config/routes.rb +11 -2
- data/db/migrate/20141024163003_create_docker_registries.rb +22 -0
- data/db/migrate/20141120123003_add_user_credentials_to_docker_registries.rb +6 -0
- data/db/migrate/20141209182008_remove_docker_tables.rb +72 -0
- data/db/migrate/20141222113313_create_wizard_states.rb +42 -0
- data/lib/foreman_docker/engine.rb +25 -5
- data/lib/foreman_docker/version.rb +1 -1
- data/test/factories/containers.rb +2 -0
- data/test/factories/docker_registry.rb +16 -0
- data/test/functionals/containers_steps_controller_test.rb +7 -40
- data/test/integration/container_steps_test.rb +24 -0
- data/test/integration/container_test.rb +18 -0
- data/test/units/container_test.rb +0 -7
- data/test/units/containers_service_test.rb +21 -0
- data/test/units/docker_registry_test.rb +24 -0
- metadata +45 -22
- data/app/models/docker_image.rb +0 -9
- data/app/models/docker_tag.rb +0 -8
- data/test/factories/docker_image.rb +0 -5
- data/test/factories/docker_tag.rb +0 -6
- data/test/units/docker_image_test.rb +0 -23
- data/test/units/docker_tag_test.rb +0 -35
@@ -2,10 +2,27 @@ module ContainerStepsHelper
|
|
2
2
|
def container_wizard(step)
|
3
3
|
wizard_header(
|
4
4
|
step,
|
5
|
-
|
6
|
-
_('Image'),
|
7
|
-
_('Configuration'),
|
8
|
-
_('Environment')
|
5
|
+
*wizard_steps.map { |s| s.to_s.humanize }
|
9
6
|
)
|
10
7
|
end
|
8
|
+
|
9
|
+
def select_registry(f)
|
10
|
+
registries = DockerRegistry.with_taxonomy_scope_override(@location, @organization)
|
11
|
+
.authorized(:view_registries)
|
12
|
+
field(f, 'docker_container_wizard_states_image[registry_id]', :label => _("Registry")) do
|
13
|
+
collection_select :wizard_states_image, :registry_id,
|
14
|
+
registries,
|
15
|
+
:id, :name,
|
16
|
+
{ :prompt => _("Select a registry") },
|
17
|
+
:class => "form-control", :disabled => registries.size == 0
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def last_step?
|
22
|
+
step == wizard_steps.last
|
23
|
+
end
|
24
|
+
|
25
|
+
def taxonomy_icon(taxonomy)
|
26
|
+
taxonomy == 'locations' ? 'globe' : 'briefcase'
|
27
|
+
end
|
11
28
|
end
|
@@ -1,10 +1,6 @@
|
|
1
1
|
module ContainersHelper
|
2
2
|
def managed_icon(container, resource)
|
3
|
-
|
4
|
-
'<span class="glyphicon glyphicon-check"></span>'.html_safe
|
5
|
-
else
|
6
|
-
'<span class="glyphicon glyphicon-unchecked"></span>'.html_safe
|
7
|
-
end
|
3
|
+
icon_text(managed?(container, resource) ? 'check' : 'unchecked')
|
8
4
|
end
|
9
5
|
|
10
6
|
def managed?(container, resource)
|
@@ -12,7 +8,9 @@ module ContainersHelper
|
|
12
8
|
end
|
13
9
|
|
14
10
|
def uuids_in_resource(resource)
|
15
|
-
|
11
|
+
@uuids_in_resource ||= {}
|
12
|
+
@uuids_in_resource[resource.id] ||= Container.where(:compute_resource_id => resource.id)
|
13
|
+
.pluck(:uuid)
|
16
14
|
end
|
17
15
|
|
18
16
|
def link_to_container(container, resource)
|
@@ -20,6 +18,12 @@ module ContainersHelper
|
|
20
18
|
container_link_hash(container, resource)
|
21
19
|
end
|
22
20
|
|
21
|
+
def link_to_taxonomies(taxonomies)
|
22
|
+
taxonomies.map do |taxonomy|
|
23
|
+
link_to(taxonomy)
|
24
|
+
end.join(' ')
|
25
|
+
end
|
26
|
+
|
23
27
|
def container_link_hash(container, resource)
|
24
28
|
if managed?(container, resource)
|
25
29
|
hash_for_container_path(:id => Container.find_by_uuid(container.identity).id)
|
@@ -47,8 +51,16 @@ module ContainersHelper
|
|
47
51
|
)
|
48
52
|
end
|
49
53
|
|
50
|
-
def
|
54
|
+
def auto_complete_docker_search(name, val, options = {})
|
51
55
|
addClass options, 'form-control'
|
52
56
|
text_field_tag(name, val, options)
|
53
57
|
end
|
58
|
+
|
59
|
+
def hub_url(image)
|
60
|
+
if image['is_official']
|
61
|
+
"https://registry.hub.docker.com/_/#{image['name']}"
|
62
|
+
else
|
63
|
+
"https://registry.hub.docker.com/u/#{image['name']}"
|
64
|
+
end
|
65
|
+
end
|
54
66
|
end
|
data/app/models/container.rb
CHANGED
@@ -1,22 +1,35 @@
|
|
1
1
|
class Container < ActiveRecord::Base
|
2
2
|
include Authorizable
|
3
|
+
include Taxonomix
|
3
4
|
|
4
5
|
belongs_to :compute_resource
|
5
|
-
belongs_to :
|
6
|
-
|
6
|
+
belongs_to :registry, :class_name => "DockerRegistry", :foreign_key => :registry_id
|
7
|
+
has_many :environment_variables, :dependent => :destroy, :foreign_key => :reference_id,
|
8
|
+
:inverse_of => :container,
|
9
|
+
:class_name => 'EnvironmentVariable',
|
10
|
+
:validate => false
|
11
|
+
accepts_nested_attributes_for :environment_variables, :allow_destroy => true
|
12
|
+
include ForemanDocker::ParameterValidators
|
7
13
|
|
8
|
-
attr_accessible :command, :
|
9
|
-
:cpu_set, :cpu_shares, :memory, :tty, :attach_stdin,
|
10
|
-
:attach_stdout, :attach_stderr, :tag, :uuid
|
14
|
+
attr_accessible :command, :repository_name, :name, :compute_resource_id, :entrypoint,
|
15
|
+
:cpu_set, :cpu_shares, :memory, :tty, :attach_stdin, :registry_id,
|
16
|
+
:attach_stdout, :attach_stderr, :tag, :uuid, :environment_variables_attributes
|
17
|
+
|
18
|
+
def repository_pull_url
|
19
|
+
repo = tag.blank? ? repository_name : "#{repository_name}:#{tag}"
|
20
|
+
repo = registry.prefixed_url(repo) if registry
|
21
|
+
repo
|
22
|
+
end
|
11
23
|
|
12
24
|
def parametrize
|
13
25
|
{ 'name' => name, # key has to be lower case to be picked up by the Docker API
|
14
|
-
'Image' =>
|
26
|
+
'Image' => repository_pull_url,
|
15
27
|
'Tty' => tty, 'Memory' => memory,
|
16
28
|
'Entrypoint' => entrypoint.try(:split), 'Cmd' => command.try(:split),
|
17
29
|
'AttachStdout' => attach_stdout, 'AttachStdin' => attach_stdin,
|
18
30
|
'AttachStderr' => attach_stderr, 'CpuShares' => cpu_shares,
|
19
|
-
'Cpuset' => cpu_set
|
31
|
+
'Cpuset' => cpu_set,
|
32
|
+
'Env' => environment_variables.map { |env| "#{env.name}=#{env.value}" } }
|
20
33
|
end
|
21
34
|
|
22
35
|
def in_fog
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class DockerContainerWizardState < ActiveRecord::Base
|
2
|
+
has_one :preliminary, :class_name => DockerContainerWizardStates::Preliminary,
|
3
|
+
:dependent => :destroy, :validate => true, :autosave => true
|
4
|
+
has_one :image, :class_name => DockerContainerWizardStates::Image,
|
5
|
+
:dependent => :destroy, :validate => true, :autosave => true
|
6
|
+
has_one :configuration, :class_name => DockerContainerWizardStates::Configuration,
|
7
|
+
:dependent => :destroy, :validate => true, :autosave => true
|
8
|
+
has_one :environment, :class_name => DockerContainerWizardStates::Environment,
|
9
|
+
:dependent => :destroy, :validate => true, :autosave => true
|
10
|
+
|
11
|
+
delegate :compute_resource_id, :to => :preliminary
|
12
|
+
delegate :environment_variables, :to => :environment
|
13
|
+
|
14
|
+
def container_attributes
|
15
|
+
{ :repository_name => image.repository_name,
|
16
|
+
:tag => image.tag,
|
17
|
+
:registry_id => image.registry_id,
|
18
|
+
:name => configuration.name,
|
19
|
+
:compute_resource_id => preliminary.compute_resource_id,
|
20
|
+
:tty => environment.tty,
|
21
|
+
:memory => configuration.memory,
|
22
|
+
:entrypoint => configuration.entrypoint,
|
23
|
+
:command => configuration.command,
|
24
|
+
:attach_stdout => environment.attach_stdout,
|
25
|
+
:attach_stdin => environment.attach_stdin,
|
26
|
+
:attach_stderr => environment.attach_stderr,
|
27
|
+
:cpu_shares => configuration.cpu_shares,
|
28
|
+
:cpu_set => configuration.cpu_set }
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
module DockerContainerWizardStates
|
2
|
+
class Configuration < ActiveRecord::Base
|
3
|
+
self.table_name_prefix = 'docker_container_wizard_states_'
|
4
|
+
belongs_to :wizard_state, :class_name => DockerContainerWizardState,
|
5
|
+
:foreign_key => :docker_container_wizard_state_id
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module DockerContainerWizardStates
|
2
|
+
class Environment < ActiveRecord::Base
|
3
|
+
self.table_name_prefix = 'docker_container_wizard_states_'
|
4
|
+
belongs_to :wizard_state, :class_name => DockerContainerWizardState
|
5
|
+
# Fix me:
|
6
|
+
# Validations are off on this association as there's a bug in ::Parameter
|
7
|
+
# that forces validation of reference_id. This will fail on new records as
|
8
|
+
# validations are executed before parent and children records have been persisted.
|
9
|
+
has_many :environment_variables, :dependent => :destroy, :foreign_key => :reference_id,
|
10
|
+
:inverse_of => :environment,
|
11
|
+
:class_name => 'DockerContainerWizardStates::EnvironmentVariable',
|
12
|
+
:validate => false
|
13
|
+
include ::ParameterValidators
|
14
|
+
|
15
|
+
accepts_nested_attributes_for :environment_variables, :allow_destroy => true
|
16
|
+
|
17
|
+
def parameters_symbol
|
18
|
+
:environment_variables
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
module DockerContainerWizardStates
|
2
|
+
class EnvironmentVariable < Parameter
|
3
|
+
belongs_to :environment, :foreign_key => :reference_id, :inverse_of => :environment_variables,
|
4
|
+
:class_name => 'DockerContainerWizardStates::Environment'
|
5
|
+
validates :name, :uniqueness => { :scope => :reference_id }
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module DockerContainerWizardStates
|
2
|
+
class Image < ActiveRecord::Base
|
3
|
+
self.table_name_prefix = 'docker_container_wizard_states_'
|
4
|
+
belongs_to :wizard_state, :class_name => DockerContainerWizardState,
|
5
|
+
:foreign_key => :docker_container_wizard_state_id
|
6
|
+
delegate :compute_resource_id, :to => :wizard_state
|
7
|
+
|
8
|
+
validates :tag, :presence => true
|
9
|
+
validates :repository_name, :presence => true
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module DockerContainerWizardStates
|
2
|
+
class Preliminary < ActiveRecord::Base
|
3
|
+
include Taxonomix
|
4
|
+
|
5
|
+
self.table_name_prefix = 'docker_container_wizard_states_'
|
6
|
+
belongs_to :wizard_state, :class_name => DockerContainerWizardState,
|
7
|
+
:foreign_key => :docker_container_wizard_state_id
|
8
|
+
|
9
|
+
validates :compute_resource_id, :presence => true
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class DockerRegistry < ActiveRecord::Base
|
2
|
+
include Authorizable
|
3
|
+
include Taxonomix
|
4
|
+
include Encryptable
|
5
|
+
|
6
|
+
has_many :containers, :foreign_key => "registry_id", :dependent => :destroy
|
7
|
+
encrypts :password
|
8
|
+
|
9
|
+
scoped_search :on => :name, :complete_value => true
|
10
|
+
scoped_search :on => :url
|
11
|
+
|
12
|
+
def used_location_ids
|
13
|
+
Location.joins(:taxable_taxonomies).where(
|
14
|
+
'taxable_taxonomies.taxable_type' => 'DockerRegistry',
|
15
|
+
'taxable_taxonomies.taxable_id' => id).pluck(:id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def used_organization_ids
|
19
|
+
Organization.joins(:taxable_taxonomies).where(
|
20
|
+
'taxable_taxonomies.taxable_type' => 'DockerRegistry',
|
21
|
+
'taxable_taxonomies.taxable_id' => id).pluck(:id)
|
22
|
+
end
|
23
|
+
|
24
|
+
def prefixed_url(image_name)
|
25
|
+
uri = URI(url)
|
26
|
+
"#{uri.hostname}:#{uri.port}/#{image_name}"
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
class EnvironmentVariable < Parameter
|
2
|
+
belongs_to :container, :foreign_key => :reference_id, :inverse_of => :environment_variables
|
3
|
+
audited :except => [:priority], :associated_with => :container, :allow_mass_assignment => true
|
4
|
+
validates :name, :uniqueness => { :scope => :reference_id }
|
5
|
+
end
|
@@ -28,12 +28,18 @@ module ForemanDocker
|
|
28
28
|
client.images.all
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
31
|
+
def local_images(filter = '')
|
32
32
|
client # initialize Docker-Api
|
33
|
-
# we are using an older version of docker-api, which differs from the current
|
34
33
|
::Docker::Image.all('filter' => filter)
|
35
34
|
end
|
36
35
|
|
36
|
+
def tags_for_local_image(image)
|
37
|
+
image.info['RepoTags'].map do |image_tag|
|
38
|
+
_, tag = image_tag.split(':')
|
39
|
+
tag
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
37
43
|
def exist?(name)
|
38
44
|
::Docker::Image.exist?(name)
|
39
45
|
end
|
@@ -42,6 +48,18 @@ module ForemanDocker
|
|
42
48
|
client.image_get(id)
|
43
49
|
end
|
44
50
|
|
51
|
+
def tags(image_name)
|
52
|
+
if exist?(image_name)
|
53
|
+
tags_for_local_image(local_images(image_name).first)
|
54
|
+
else
|
55
|
+
# If image is not found in the compute resource, get the tags from the Hub
|
56
|
+
hub_api_url = "https://index.docker.io/v1/repositories/#{image_name}/tags"
|
57
|
+
JSON.parse(URI.parse(hub_api_url).read).map do |tag|
|
58
|
+
tag['name']
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
45
63
|
def search(term = '')
|
46
64
|
client.images.image_search(:term => term)
|
47
65
|
end
|
@@ -77,10 +95,11 @@ module ForemanDocker
|
|
77
95
|
|
78
96
|
def test_connection(options = {})
|
79
97
|
super
|
80
|
-
client
|
98
|
+
client.present?
|
81
99
|
# This should only rescue Fog::Errors, but Fog returns all kinds of errors...
|
82
100
|
rescue => e
|
83
101
|
errors[:base] << e.message
|
102
|
+
false
|
84
103
|
end
|
85
104
|
|
86
105
|
protected
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Service
|
2
|
+
class Containers
|
3
|
+
def self.start_container!(wizard_state)
|
4
|
+
ActiveRecord::Base.transaction do
|
5
|
+
container = Container.new(wizard_state.container_attributes) do |r|
|
6
|
+
# eagerly load environment variables
|
7
|
+
state = DockerContainerWizardState.includes(:environment => [:environment_variables])
|
8
|
+
.find(wizard_state.id)
|
9
|
+
state.environment_variables.each do |environment_variable|
|
10
|
+
r.environment_variables.build :name => environment_variable.name,
|
11
|
+
:value => environment_variable.value,
|
12
|
+
:priority => environment_variable.priority
|
13
|
+
end
|
14
|
+
end
|
15
|
+
Taxonomy.enabled_taxonomies.each do |taxonomy|
|
16
|
+
container.send(:"#{taxonomy}=", wizard_state.preliminary.send(:"#{taxonomy}"))
|
17
|
+
end
|
18
|
+
|
19
|
+
fail ActiveRecord::Rollback unless start_container(container)
|
20
|
+
|
21
|
+
container.save!
|
22
|
+
destroy_wizard_state(wizard_state)
|
23
|
+
container
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.start_container(container)
|
28
|
+
started = container.compute_resource.create_container(container.parametrize)
|
29
|
+
container.uuid = started.id if started
|
30
|
+
started
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.destroy_wizard_state(wizard_state)
|
34
|
+
wizard_state.destroy
|
35
|
+
DockerContainerWizardState.destroy_all(["updated_at < ?", (Time.now - 24.hours)])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Service
|
2
|
+
class RegistryApi
|
3
|
+
DEFAULTS = { :url => 'http://localhost:5000' }
|
4
|
+
attr_reader :config
|
5
|
+
|
6
|
+
def initialize(params = {})
|
7
|
+
config = DEFAULTS.merge(params)
|
8
|
+
uri = URI(config.delete(:url))
|
9
|
+
uri.user = config.delete(:user)
|
10
|
+
uri.password = config.delete(:password)
|
11
|
+
@config = config.merge(:url => uri.to_s)
|
12
|
+
end
|
13
|
+
|
14
|
+
def search(aquery)
|
15
|
+
response = RestClient.get(config[:url] + '/v1/search',
|
16
|
+
:params => { :q => aquery }, :accept => :json)
|
17
|
+
JSON.parse(response.body)
|
18
|
+
end
|
19
|
+
|
20
|
+
def list_repository_tags(arepository)
|
21
|
+
response = RestClient.get(config[:url] + "/v1/repositories/#{arepository}/tags",
|
22
|
+
:accept => :json)
|
23
|
+
JSON.parse(response.body)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,25 +1,29 @@
|
|
1
1
|
<table class="table table-bordered table-striped table-condensed" data-table="inline">
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
2
|
+
<thead>
|
3
|
+
<tr>
|
4
|
+
<th class="text-center"><%= _("Name") %></th>
|
5
|
+
<th class="hidden-tablet hidden-xs text-center"><%= _("Status") %></th>
|
6
|
+
<th class="hidden-tablet hidden-xs text-center"><%= _("Image") %></th>
|
7
|
+
<th class="hidden-tablet hidden-xs text-center"><%= _("Command") %></th>
|
8
|
+
<th class="hidden-tablet hidden-xs text-center"><%= _("Uptime") %></th>
|
9
|
+
<th class="hidden-tablet hidden-xs text-center"><%= _("Running on") %></th>
|
10
|
+
<th class="hidden-tablet hidden-xs text-center"><%= _("Managed") %></th>
|
11
|
+
<th></th>
|
12
|
+
</tr>
|
13
13
|
</thead>
|
14
14
|
|
15
|
+
<tbody>
|
15
16
|
<% containers.each do |container| %>
|
16
17
|
<tr>
|
17
18
|
<td class="ellipsis text-center"><%= link_to_container(container, resource) %></td>
|
18
|
-
<td class="hidden-tablet hidden-xs text-center"
|
19
|
+
<td class="hidden-tablet hidden-xs text-center">
|
20
|
+
<span <%= vm_power_class(container.ready?) %>><%= vm_state(container) %></span></td>
|
19
21
|
<td class="hidden-tablet hidden-xs text-center"><%= trunc(container.image_friendly_name) %></td>
|
20
22
|
<td class="hidden-tablet hidden-xs text-center"><%= trunc(container.command) %></td>
|
21
|
-
<td class="hidden-tablet hidden-xs text-center"
|
22
|
-
|
23
|
+
<td class="hidden-tablet hidden-xs text-center">
|
24
|
+
<span class="glyphicon glyphicon-time"></span> <%= container.ready? ? time_ago_in_words(container.started_at) : "N/A" %>
|
25
|
+
</td>
|
26
|
+
<td class="hidden-tablet hidden-xs text-center"><%= link_to resource, compute_resource_path(resource) %> </td>
|
23
27
|
<td class="hidden-tablet hidden-xs text-center"><%= managed_icon(container, resource) %></td>
|
24
28
|
<% @compute_resource = resource %>
|
25
29
|
<td><%= action_buttons(vm_power_action(container),
|
@@ -30,8 +34,5 @@
|
|
30
34
|
:confirm => _("Delete %s?") % container.name)) %></td>
|
31
35
|
</tr>
|
32
36
|
<% end %>
|
37
|
+
</tbody>
|
33
38
|
</table>
|
34
|
-
|
35
|
-
<!-- To be replaced by will_paginate_with_info after 1.6 support is deprecated -->
|
36
|
-
<%= page_entries_info containers %>
|
37
|
-
<%= will_paginate containers %>
|