Skip to content
This repository was archived by the owner on Mar 16, 2021. It is now read-only.

Commit 1c76df5

Browse files
committed
Fixes #8409 - Pull docker image asynchronously
1 parent b60918b commit 1c76df5

23 files changed

Lines changed: 374 additions & 173 deletions

File tree

app/controllers/api/v2/containers_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def show
6969
param_group :container, :as => :create
7070

7171
def create
72-
@container = Service::Containers.new.start_container!(set_wizard_state)
72+
@container = ForemanDocker::Service::Containers.new.start_container!(set_wizard_state)
7373
set_container_taxonomies
7474
process_response @container.save
7575
rescue ActiveModel::MassAssignmentSecurity::Error => e

app/controllers/containers/steps_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def set_form
4343

4444
def create_container
4545
@state.send(:"create_#{step}", params[:"docker_container_wizard_states_#{step}"])
46-
container = (service = Service::Containers.new).start_container!(@state)
46+
container = (service = ForemanDocker::Service::Containers.new).start_container!(@state)
4747
if container.present?
4848
process_success(:object => container, :success_redirect => container_path(container))
4949
else

app/controllers/image_search_controller.rb

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def use_hub?
5252
end
5353

5454
def hub_image_exists?(terms)
55-
@compute_resource.exist?(terms)
55+
::Docker::Image.exist?(terms)
5656
end
5757

5858
def hub_auto_complete_image_tags(terms)
@@ -79,10 +79,9 @@ def registry_auto_complete_image_tags(terms)
7979
end
8080

8181
def registry_search_image(terms)
82-
r = ::Service::RegistryApi.new(:url => @registry.url,
83-
:user => @registry.username,
84-
:password => @registry.password).search(terms)
85-
r['results']
82+
::Service::RegistryApi.new(:url => @registry.url,
83+
:user => @registry.username,
84+
:password => @registry.password).search(terms)['results']
8685
end
8786

8887
def action_permission

app/helpers/containers_helper.rb

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,28 @@ def container_link_hash(container, resource)
2727
end
2828
end
2929

30+
def container_title(container)
31+
title = container.name.titleize
32+
title += if container.uuid.present?
33+
"- #{container.in_fog.name}"
34+
else
35+
_(" - provisioning ") + image_tag('spinner.gif')
36+
end
37+
title(container.name.titleize, title.html_safe)
38+
end
39+
3040
def container_title_actions(container)
3141
@compute_resource = container.compute_resource
42+
container_title(container)
3243
title_actions(
33-
button_group(
34-
link_to(_('Commit'), '#commit-modal', :'data-toggle' => 'modal')
35-
),
36-
button_group(container_power_action(container.in_fog)),
37-
button_group(
38-
display_delete_if_authorized(
39-
hash_for_container_path(:id => container.id)
40-
.merge(:auth_object => container,
41-
:auth_action => 'destroy',
42-
:authorizer => authorizer),
43-
:confirm => _("Delete %s?") % container.name)
44-
)
45-
)
44+
button_group(link_to(_('Commit'), '#commit-modal', :'data-toggle' => 'modal')),
45+
button_group(container_power_action(container.in_fog)),
46+
button_group(display_delete_if_authorized(
47+
hash_for_container_path(:id => container.id).merge(:auth_object => container,
48+
:auth_action => 'destroy',
49+
:authorizer => authorizer),
50+
:confirm => _("Delete %s?") % container.name))
51+
) if container.uuid.present?
4652
end
4753

4854
def container_power_action(vm, authorizer = nil)
@@ -99,4 +105,20 @@ def processes(container)
99105
def logs(container, opts = {})
100106
ForemanDocker::Docker.get_container(container).logs(opts)
101107
end
108+
109+
def fog_property(container)
110+
return 'Not available' unless container.uuid.present?
111+
yield
112+
end
113+
114+
def pair_attributes_table(attributes)
115+
table = "<table id='environment_variables' class='table table-bordered'
116+
style='table-layout:fixed; word-wrap: break-word'>"
117+
attributes.each do |pair|
118+
pair = pair.split("=")
119+
table += "<tr><td><b> #{pair.first} </b></td><td><i> #{pair.second} </i></td></tr>"
120+
end
121+
table += '</table>'
122+
table.html_safe
123+
end
102124
end

app/models/concerns/fog_extensions/fogdocker/server.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def command
2727
end
2828

2929
def poweroff
30-
service.vm_action(:id => id, :action => :kill)
30+
service.container_action(:id => id, :action => :kill)
3131
end
3232

3333
def reset

app/models/container.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
class Container < ActiveRecord::Base
22
include Authorizable
33
include Taxonomix
4+
include ForemanTasks::Concerns::ActionSubject
45

56
belongs_to :compute_resource
67
belongs_to :registry, :class_name => "DockerRegistry", :foreign_key => :registry_id
@@ -38,4 +39,8 @@ def parametrize
3839
def in_fog
3940
@fog_container ||= compute_resource.vms.get(uuid)
4041
end
42+
43+
def to_hash
44+
parametrize
45+
end
4146
end

app/models/foreman_docker/docker.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def image(id)
5757
end
5858

5959
def tags(image_name)
60-
if exist?(image_name)
60+
if ::Docker::Image.exist?(image_name)
6161
tags_for_local_image(local_images(image_name).first)
6262
else
6363
# If image is not found in the compute resource, get the tags from the Hub
@@ -77,23 +77,23 @@ def provider_friendly_name
7777
end
7878

7979
def create_container(args = {})
80-
options = vm_instance_defaults.merge(args)
80+
options = vm_instance_defaults.merge(args) { |_, default, new| new.empty? ? default : new }
8181
logger.debug("Creating container with the following options: #{options.inspect}")
8282
docker_command do
8383
::Docker::Container.create(options, docker_connection)
8484
end
8585
end
8686

8787
def create_image(args = {})
88+
return true if ::Docker::Image.exist?(args[:fromImage])
8889
logger.debug("Creating docker image with the following options: #{args.inspect}")
8990
docker_command do
9091
::Docker::Image.create(args, credentials, docker_connection)
9192
end
9293
end
9394

9495
def vm_instance_defaults
95-
ActiveSupport::HashWithIndifferentAccess.new('name' => "foreman_#{Time.now.to_i}",
96-
'Cmd' => ['/bin/bash'])
96+
{ 'name' => "foreman_#{Time.now.to_i}", 'Cmd' => ['/bin/bash'] }
9797
end
9898

9999
def console(uuid)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
module ForemanDocker
2+
module Service
3+
module Actions
4+
module Container
5+
class Provision < ::Actions::EntryAction
6+
def plan(container)
7+
action_subject(container)
8+
9+
sequence do
10+
plan_action(Container::Pull, container)
11+
plan_action(Container::Start, container)
12+
end
13+
end
14+
15+
def humanized_name
16+
_('Provision container')
17+
end
18+
19+
def finalize
20+
action_logger.info('Finished provisioning of Docker container')
21+
end
22+
end
23+
end
24+
end
25+
end
26+
end
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
module ForemanDocker
2+
module Service
3+
module Actions
4+
module Container
5+
class Pull < ::Actions::EntryAction
6+
def plan(container)
7+
action_subject(container)
8+
plan_self(:container => container.id)
9+
end
10+
11+
def run(event = nil)
12+
case event
13+
when :done # do nothing and move to next step
14+
when StandardError
15+
action_logger.error(event.message)
16+
action_logger.debug(event.backtrace.join("\n "))
17+
error!(event)
18+
else
19+
suspend do |suspended_action|
20+
pull_docker_image(::Container.find(input[:container]), suspended_action)
21+
end
22+
end
23+
end
24+
25+
def pull_docker_image(container, suspended_action)
26+
Thread.new do
27+
begin
28+
container.compute_resource
29+
.create_image(:fromImage => container.repository_pull_url)
30+
suspended_action << :done
31+
rescue => e
32+
# encapsulate e as Foreman::Exception
33+
suspended_action << e
34+
end
35+
end
36+
end
37+
38+
def humanized_name
39+
_('Pull')
40+
end
41+
42+
def finalize
43+
container = ::Container.find(input[:container])
44+
action_logger.info("[Docker] Finished pulling image #{container.repository_pull_url}")
45+
end
46+
end
47+
end
48+
end
49+
end
50+
end
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module ForemanDocker
2+
module Service
3+
module Actions
4+
module Container
5+
class Start < ::Actions::EntryAction
6+
def plan(container)
7+
action_subject(container)
8+
plan_self(:container => container.id)
9+
end
10+
11+
def run
12+
container = ::Container.find(input[:container])
13+
started = container.compute_resource.create_container(container.parametrize)
14+
if started
15+
container.update_attribute(:uuid, started.id)
16+
else
17+
errors << container.compute_resource.errors[:base]
18+
end
19+
started
20+
end
21+
22+
def humanized_name
23+
_('Start')
24+
end
25+
26+
def finalize
27+
container = ::Container.find(input[:container])
28+
action_logger.info("[Docker] container #{container.name} successfully started")
29+
end
30+
end
31+
end
32+
end
33+
end
34+
end

0 commit comments

Comments
 (0)