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

Commit

Permalink
Fixes #8409 - Pull docker image asynchronously
Browse files Browse the repository at this point in the history
  • Loading branch information
dLobatog committed Apr 6, 2015
1 parent a79b7ae commit efe3a69
Show file tree
Hide file tree
Showing 23 changed files with 375 additions and 173 deletions.
2 changes: 1 addition & 1 deletion app/controllers/api/v2/containers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def show
param_group :container, :as => :create

def create
@container = Service::Containers.new.start_container!(set_wizard_state)
@container = ForemanDocker::Service::Containers.new.start_container!(set_wizard_state)
set_container_taxonomies
process_response @container.save
rescue ActiveModel::MassAssignmentSecurity::Error => e
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/containers/steps_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def set_form

def create_container
@state.send(:"create_#{step}", params[:"docker_container_wizard_states_#{step}"])
container = (service = Service::Containers.new).start_container!(@state)
container = (service = ForemanDocker::Service::Containers.new).start_container!(@state)
if container.present?
process_success(:object => container, :success_redirect => container_path(container))
else
Expand Down
9 changes: 4 additions & 5 deletions app/controllers/image_search_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def use_hub?
end

def hub_image_exists?(terms)
@compute_resource.exist?(terms)
::Docker::Image.exist?(terms)
end

def hub_auto_complete_image_tags(terms)
Expand All @@ -79,10 +79,9 @@ def registry_auto_complete_image_tags(terms)
end

def registry_search_image(terms)
r = ::Service::RegistryApi.new(:url => @registry.url,
:user => @registry.username,
:password => @registry.password).search(terms)
r['results']
::Service::RegistryApi.new(:url => @registry.url,
:user => @registry.username,
:password => @registry.password).search(terms)['results']
end

def action_permission
Expand Down
48 changes: 35 additions & 13 deletions app/helpers/containers_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,28 @@ def container_link_hash(container, resource)
end
end

def container_title(container)
title = container.name.titleize
title += if container.uuid.present?
"- #{container.in_fog.name}"
else
_(" - provisioning ") + image_tag('spinner.gif')
end
title(container.name.titleize, title.html_safe)
end

def container_title_actions(container)
@compute_resource = container.compute_resource
container_title(container)
title_actions(
button_group(
link_to(_('Commit'), '#commit-modal', :'data-toggle' => 'modal')
),
button_group(container_power_action(container.in_fog)),
button_group(
display_delete_if_authorized(
hash_for_container_path(:id => container.id)
.merge(:auth_object => container,
:auth_action => 'destroy',
:authorizer => authorizer),
:confirm => _("Delete %s?") % container.name)
)
)
button_group(link_to(_('Commit'), '#commit-modal', :'data-toggle' => 'modal')),
button_group(container_power_action(container.in_fog)),
button_group(display_delete_if_authorized(
hash_for_container_path(:id => container.id).merge(:auth_object => container,
:auth_action => 'destroy',
:authorizer => authorizer),
:confirm => _("Delete %s?") % container.name))
) if container.uuid.present?
end

def container_power_action(vm, authorizer = nil)
Expand Down Expand Up @@ -99,4 +105,20 @@ def processes(container)
def logs(container, opts = {})
ForemanDocker::Docker.get_container(container).logs(opts)
end

def fog_property(container)
return 'Not available' unless container.uuid.present?
yield
end

def pair_attributes_table(attributes)
table = "<table id='environment_variables' class='table table-bordered'
style='table-layout:fixed; word-wrap: break-word'>"
attributes.each do |pair|
pair = pair.split("=")
table += "<tr><td><b> #{pair.first} </b></td><td><i> #{pair.second} </i></td></tr>"
end
table += '</table>'
table.html_safe
end
end
2 changes: 1 addition & 1 deletion app/models/concerns/fog_extensions/fogdocker/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def command
end

def poweroff
service.vm_action(:id => id, :action => :kill)
service.container_action(:id => id, :action => :kill)
end

def reset
Expand Down
6 changes: 6 additions & 0 deletions app/models/container.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class Container < ActiveRecord::Base
include Authorizable
include Taxonomix
include ForemanTasks::Concerns::ActionSubject

belongs_to :compute_resource
belongs_to :registry, :class_name => "DockerRegistry", :foreign_key => :registry_id
Expand Down Expand Up @@ -41,5 +42,10 @@ def in_fog

def self.humanize_class_name(_name = nil)
_("Docker/Container")
parametrize
end

def to_hash
parametrize
end
end
8 changes: 4 additions & 4 deletions app/models/foreman_docker/docker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def image(id)
end

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

def create_container(args = {})
options = vm_instance_defaults.merge(args)
options = vm_instance_defaults.merge(args) { |_, default, new| new.empty? ? default : new }
logger.debug("Creating container with the following options: #{options.inspect}")
docker_command do
::Docker::Container.create(options, docker_connection)
end
end

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

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

def console(uuid)
Expand Down
26 changes: 26 additions & 0 deletions app/models/foreman_docker/service/actions/container/provision.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module ForemanDocker
module Service
module Actions
module Container
class Provision < ::Actions::EntryAction
def plan(container)
action_subject(container)

sequence do
plan_action(Container::Pull, container)
plan_action(Container::Start, container)
end
end

def humanized_name
_('Provision container')
end

def finalize
action_logger.info('Finished provisioning of Docker container')
end
end
end
end
end
end
50 changes: 50 additions & 0 deletions app/models/foreman_docker/service/actions/container/pull.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
module ForemanDocker
module Service
module Actions
module Container
class Pull < ::Actions::EntryAction
def plan(container)
action_subject(container)
plan_self(:container => container.id)
end

def run(event = nil)
case event
when :done # do nothing and move to next step
when StandardError
action_logger.error(event.message)
action_logger.debug(event.backtrace.join("\n "))
error!(event)
else
suspend do |suspended_action|
pull_docker_image(::Container.find(input[:container]), suspended_action)
end
end
end

def pull_docker_image(container, suspended_action)
Thread.new do
begin
container.compute_resource
.create_image(:fromImage => container.repository_pull_url)
suspended_action << :done
rescue => e
# encapsulate e as Foreman::Exception
suspended_action << e
end
end
end

def humanized_name
_('Pull')
end

def finalize
container = ::Container.find(input[:container])
action_logger.info("[Docker] Finished pulling image #{container.repository_pull_url}")
end
end
end
end
end
end
34 changes: 34 additions & 0 deletions app/models/foreman_docker/service/actions/container/start.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module ForemanDocker
module Service
module Actions
module Container
class Start < ::Actions::EntryAction
def plan(container)
action_subject(container)
plan_self(:container => container.id)
end

def run
container = ::Container.find(input[:container])
started = container.compute_resource.create_container(container.parametrize)
if started
container.update_attribute(:uuid, started.id)
started
else
[container.compute_resource.errors[:base]]
end
end

def humanized_name
_('Start')
end

def finalize
container = ::Container.find(input[:container])
action_logger.info("[Docker] container #{container.name} successfully started")
end
end
end
end
end
end
39 changes: 39 additions & 0 deletions app/models/foreman_docker/service/containers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module ForemanDocker
module Service
class Containers
def errors
@errors ||= []
end

def start_container!(wizard_state)
container = ActiveRecord::Base.transaction do
container = Container.new(wizard_state.container_attributes) do |r|
# eagerly load environment variables
state =
DockerContainerWizardState.includes(:environment => [:environment_variables])
.find(wizard_state.id)
state.environment_variables.each do |environment_variable|
r.environment_variables.build :name => environment_variable.name,
:value => environment_variable.value,
:priority => environment_variable.priority
end
end
Taxonomy.enabled_taxonomies.each do |taxonomy|
container.send(:"#{taxonomy}=", wizard_state.preliminary.send(:"#{taxonomy}"))
end
container.save!
container
end

destroy_wizard_state(wizard_state)
ForemanTasks.async_task(Service::Actions::Container::Provision, container)
container
end

def destroy_wizard_state(wizard_state)
wizard_state.destroy
DockerContainerWizardState.destroy_all(["updated_at < ?", (Time.now - 24.hours)])
end
end
end
end
50 changes: 0 additions & 50 deletions app/models/service/containers.rb

This file was deleted.

3 changes: 3 additions & 0 deletions app/views/api/v2/containers/create.json.rabl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object @container

extends "api/v2/containers/show"
Loading

0 comments on commit efe3a69

Please sign in to comment.