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

Commit 7989dee

Browse files
committed
Fixes #8409 - Pull docker image asynchronously
1 parent e054355 commit 7989dee

20 files changed

Lines changed: 269 additions & 147 deletions

File tree

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
@@ -34,7 +34,7 @@ def use_hub?
3434
end
3535

3636
def hub_image_exists?(terms)
37-
@compute_resource.exist?(terms)
37+
::Docker::Image.exist?(terms)
3838
end
3939

4040
def hub_auto_complete_image_tags(terms)
@@ -61,10 +61,9 @@ def registry_auto_complete_image_tags(terms)
6161
end
6262

6363
def registry_search_image(terms)
64-
r = ::Service::RegistryApi.new(:url => @registry.url,
65-
:user => @registry.username,
66-
:password => @registry.password).search(terms)
67-
r['results']
64+
::Service::RegistryApi.new(:url => @registry.url,
65+
:user => @registry.username,
66+
:password => @registry.password).search(terms)['results']
6867
end
6968

7069
def action_permission

app/helpers/containers_helper.rb

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,28 @@ def container_link_hash(container, resource)
3333
end
3434
end
3535

36+
def container_title(container)
37+
title = container.name.titleize
38+
title += if container.uuid.present?
39+
"- #{container.in_fog.name}"
40+
else
41+
_(" - provisioning ") + image_tag('spinner.gif')
42+
end
43+
title(container.name.titleize, title.html_safe)
44+
end
45+
3646
def container_title_actions(container)
3747
@compute_resource = container.compute_resource
48+
container_title(container)
3849
title_actions(
39-
button_group(
40-
link_to(_('Commit'), '#commit-modal', :'data-toggle' => 'modal')
41-
),
42-
button_group(vm_power_action(container.in_fog)),
43-
button_group(
44-
display_delete_if_authorized(
45-
hash_for_container_path(:id => container.id)
46-
.merge(:auth_object => container,
47-
:auth_action => 'destroy',
48-
:authorizer => authorizer),
49-
:confirm => _("Delete %s?") % container.name)
50-
)
51-
)
50+
button_group(link_to(_('Commit'), '#commit-modal', :'data-toggle' => 'modal')),
51+
button_group(vm_power_action(container.in_fog)),
52+
button_group(display_delete_if_authorized(
53+
hash_for_container_path(:id => container.id).merge(:auth_object => container,
54+
:auth_action => 'destroy',
55+
:authorizer => authorizer),
56+
:confirm => _("Delete %s?") % container.name))
57+
) if container.uuid.present?
5258
end
5359

5460
def auto_complete_docker_search(name, val, options = {})
@@ -63,4 +69,20 @@ def hub_url(image)
6369
"https://registry.hub.docker.com/u/#{image['name']}"
6470
end
6571
end
72+
73+
def fog_property(container)
74+
return 'Not available' unless container.uuid.present?
75+
yield
76+
end
77+
78+
def pair_attributes_table(attributes)
79+
table = "<table id='environment_variables' class='table table-bordered'
80+
style='table-layout:fixed; word-wrap: break-word'>"
81+
attributes.each do |pair|
82+
pair = pair.split("=")
83+
table += "<tr><td><b> #{pair.first} </b></td><td><i> #{pair.second} </i></td></tr>"
84+
end
85+
table += '</table>'
86+
table.html_safe
87+
end
6688
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
@@ -35,4 +36,8 @@ def parametrize
3536
def in_fog
3637
@fog_container ||= compute_resource.vms.get(uuid)
3738
end
39+
40+
def to_hash
41+
parametrize
42+
end
3843
end

app/models/foreman_docker/docker.rb

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,12 @@ def tags_for_local_image(image)
4444
end
4545
end
4646

47-
def exist?(name)
48-
::Docker::Image.exist?(name)
49-
end
50-
5147
def image(id)
5248
client.image_get(id)
5349
end
5450

5551
def tags(image_name)
56-
if exist?(image_name)
52+
if ::Docker::Image.exist?(image_name)
5753
tags_for_local_image(local_images(image_name).first)
5854
else
5955
# If image is not found in the compute resource, get the tags from the Hub
@@ -73,23 +69,19 @@ def provider_friendly_name
7369
end
7470

7571
def create_container(args = {})
76-
options = vm_instance_defaults.merge(args)
72+
options = vm_instance_defaults.merge(args) { |_, default, new| new.empty? ? default : new }
7773
logger.debug("Creating container with the following options: #{options.inspect}")
78-
docker_command do
79-
::Docker::Container.create(options)
80-
end
74+
docker_command { ::Docker::Container.create(options) }
8175
end
8276

8377
def create_image(args = {})
78+
return true if ::Docker::Image.exist?(args[:fromImage])
8479
logger.debug("Creating docker image with the following options: #{args.inspect}")
85-
docker_command do
86-
::Docker::Image.create(args)
87-
end
80+
docker_command { ::Docker::Image.create(args) }
8881
end
8982

9083
def vm_instance_defaults
91-
ActiveSupport::HashWithIndifferentAccess.new('name' => "foreman_#{Time.now.to_i}",
92-
'Cmd' => ['/bin/bash'])
84+
{ 'name' => "foreman_#{Time.now.to_i}", 'Cmd' => ['/bin/bash'] }
9385
end
9486

9587
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: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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+
else
15+
suspend do |suspended_action|
16+
Thread.new do
17+
begin
18+
container = ::Container.find(input[:container])
19+
container.compute_resource
20+
.create_image(:fromImage => container.repository_pull_url)
21+
suspended_action << :done
22+
rescue => e
23+
action_logger.error(e.message)
24+
action_logger.debug(e.backtrace.join("\n "))
25+
error!(e)
26+
end
27+
end
28+
end
29+
end
30+
end
31+
32+
def humanized_name
33+
_('Pull')
34+
end
35+
36+
def finalize
37+
container = ::Container.find(input[:container])
38+
action_logger.info("[Docker] Finished pulling image #{container.repository_pull_url}")
39+
end
40+
end
41+
end
42+
end
43+
end
44+
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
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
module ForemanDocker
2+
module Service
3+
class Containers
4+
def errors
5+
@errors ||= []
6+
end
7+
8+
def start_container!(wizard_state)
9+
container = ActiveRecord::Base.transaction do
10+
container = Container.new(wizard_state.container_attributes) do |r|
11+
# eagerly load environment variables
12+
state = DockerContainerWizardState.includes(:environment => [:environment_variables])
13+
.find(wizard_state.id)
14+
state.environment_variables.each do |environment_variable|
15+
r.environment_variables.build :name => environment_variable.name,
16+
:value => environment_variable.value,
17+
:priority => environment_variable.priority
18+
end
19+
end
20+
Taxonomy.enabled_taxonomies.each do |taxonomy|
21+
container.send(:"#{taxonomy}=", wizard_state.preliminary.send(:"#{taxonomy}"))
22+
end
23+
container.save!
24+
container
25+
end
26+
27+
destroy_wizard_state(wizard_state)
28+
ForemanTasks.async_task(Service::Actions::Container::Provision, container)
29+
container
30+
end
31+
32+
def destroy_wizard_state(wizard_state)
33+
wizard_state.destroy
34+
DockerContainerWizardState.destroy_all(["updated_at < ?", (Time.now - 24.hours)])
35+
end
36+
end
37+
end
38+
end

0 commit comments

Comments
 (0)