Skip to content

Commit

Permalink
Merge pull request #62 from jcrobak/return-code-validation2
Browse files Browse the repository at this point in the history
Return code validation
  • Loading branch information
bflad committed Feb 8, 2014
2 parents 46a61ea + 5e416e6 commit 9c587b7
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 51 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ install_dir | Installation directory for docker binary | String | auto-detected
install_type | Installation type for docker ("binary", "package" or "source") | String | "package"
options | Additional options to pass to docker. These could be flags like "-api-enable-cors". | String | nil
registry_cmd_timeout | registry LWRP default cmd_timeout seconds | Fixnum | 60
docker_daemon_timeout | Timeout to wait for the docker daemon to start in seconds | Fixnum | 10
storage_type | Storage driver for docker (nil, "aufs", or "devmapper") | String | auto-detected (see attributes/default.rb)
version | Version of docker | String | nil
virtualization_type | Virtualization driver for docker (nil or "lxc") | String | auto-detected (see attributes/default.rb)
Expand Down
1 change: 1 addition & 0 deletions attributes/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
default['docker']['http_proxy'] = nil
default['docker']['image_cmd_timeout'] = 300
default['docker']['registry_cmd_timeout'] = 60
default['docker']['docker_daemon_timeout'] = 10

default['docker']['init_type'] = value_for_platform(
%w{ centos debian oracle redhat } => {
Expand Down
90 changes: 90 additions & 0 deletions libraries/helpers.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
require 'chef/mixin/shell_out'
include Chef::Mixin::ShellOut

# Helpers module
module Helpers
# Helpers::Docker module
module Docker
# Exception to signify that the Docker daemon is not yet ready to handle
# docker commands.
class DockerNotReady < StandardError
def initialize(timeout)
super <<-EOH
The Docker daemon did not become ready within #{timeout} seconds.
This most likely means that Docker failed to start.
Docker can fail to start if:
- a configuration file is invalid
- permissions are incorrect for the root directory of the docker runtime.
If this problem persists, check your service log files.
EOH
end
end

def cli_args(spec)
cli_line = ''
spec.each_pair do |arg, value|
Expand All @@ -28,5 +48,75 @@ def docker_inspect_id(id)
inspect = docker_inspect(id)
inspect['id'] if inspect
end

def timeout
node['docker']['docker_daemon_timeout']
end

# This is based upon wait_until_ready! from the opscode jenkins cookbook.
#
# Since the docker service returns immediately and the actual docker
# process is started as a daemon, we block the Chef Client run until the
# daemon is actually ready.
#
# This method will effectively "block" the current thread until the docker
# daemon is ready
#
# @raise [DockerNotReady]
# if the Docker master does not respond within (+timeout+) seconds
#
def wait_until_ready!
Timeout.timeout(timeout) do
loop do
result = shell_out('docker info')
break if Array(result.valid_exit_codes).include?(result.exitstatus)
Chef::Log.debug("Docker daemon is not running - #{result.stdout}\n#{result.stderr}")
sleep(0.5)
end
end
rescue Timeout::Error
raise DockerNotReady.new(timeout), 'docker timeout exceeded'
end

# the Error message to display if a command times out. Subclasses
# may want to override this to provide more details on the timeout.
def command_timeout_error_message
<<-EOM
Command timed out:
#{cmd}
EOM
end

# Runs a docker command. Does not raise exception on non-zero exit code.
def docker_cmd(cmd, timeout = new_resource.cmd_timeout)
execute_cmd('docker ' + cmd, timeout)
end

# Executes the given command with the specified timeout. Does not raise an
# exception on a non-zero exit code.
def execute_cmd(cmd, timeout = new_resource.cmd_timeout)
Chef::Log.debug('Executing: ' + cmd)
begin
shell_out(cmd, :timeout => timeout)
rescue Mixlib::ShellOut::CommandTimeout
raise CommandTimeout, command_timeout_error_message
end
end

# Executes the given docker command with the specified timeout. Raises an
# exception if the command returns a non-zero exit code.
def docker_cmd!(cmd, timeout = new_resource.cmd_timeout)
execute_cmd!('docker ' + cmd, timeout)
end

# Executes teh given command with the specified timeout. Raises an
# exception if the command returns a non-zero exit code.
def execute_cmd!(cmd, timeout = new_resource.cmd_timeout)
cmd = execute_cmd(cmd, timeout)
cmd.error!
cmd
end
end
end
32 changes: 14 additions & 18 deletions providers/container.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ class CommandTimeout < RuntimeError; end

def load_current_resource
@current_resource = Chef::Resource::DockerContainer.new(new_resource)
dps = docker_cmd('ps -a -notrunc')
wait_until_ready!
dps = docker_cmd!('ps -a -notrunc')
dps.stdout.each_line do |dps_line|
ps = dps(dps_line)
unless container_id_matches?(ps['id'])
Expand Down Expand Up @@ -121,7 +122,7 @@ def commit
commit_end_args = new_resource.repository
commit_end_args += ":#{new_resource.tag}" if new_resource.tag
end
docker_cmd("commit #{commit_args} #{current_resource.id} #{commit_end_args}")
docker_cmd!("commit #{commit_args} #{current_resource.id} #{commit_end_args}")
end

def container_command_matches_if_exists?(command)
Expand Down Expand Up @@ -151,7 +152,7 @@ def container_name
end

def cp
docker_cmd("cp #{current_resource.id}:#{new_resource.source} #{new_resource.destination}")
docker_cmd!("cp #{current_resource.id}:#{new_resource.source} #{new_resource.destination}")
end

def docker_cmd(cmd, timeout = new_resource.cmd_timeout)
Expand All @@ -175,34 +176,29 @@ def dps(dps_line)
ps
end

def execute_cmd(cmd, timeout = new_resource.cmd_timeout)
Chef::Log.debug('Executing: ' + cmd)
begin
shell_out(cmd, :timeout => timeout)
rescue Mixlib::ShellOut::CommandTimeout
raise CommandTimeout, <<-EOM
def command_timeout_error_message
<<-EOM
Command timed out:
#{cmd}
Please adjust node container_cmd_timeout attribute or this docker_container cmd_timeout attribute if necessary.
EOM
end
end

def exists?
@current_resource.id
end

def export
docker_cmd("export #{current_resource.id} > #{new_resource.destination}")
docker_cmd!("export #{current_resource.id} > #{new_resource.destination}")
end

def kill
if service?
service_stop
else
docker_cmd("kill #{current_resource.id}")
docker_cmd!("kill #{current_resource.id}")
end
end

Expand All @@ -221,15 +217,15 @@ def remove
rm_args = cli_args(
'link' => new_resource.link
)
docker_cmd("rm #{rm_args} #{current_resource.id}")
docker_cmd!("rm #{rm_args} #{current_resource.id}")
service_remove if service?
end

def restart
if service?
service_restart
else
docker_cmd("restart #{current_resource.id}")
docker_cmd!("restart #{current_resource.id}")
end
end

Expand Down Expand Up @@ -258,7 +254,7 @@ def run
'volumes-from' => new_resource.volumes_from,
'w' => new_resource.working_directory
)
dr = docker_cmd("run #{run_args} #{new_resource.image} #{new_resource.command}")
dr = docker_cmd!("run #{run_args} #{new_resource.image} #{new_resource.command}")
dr.error!
new_resource.id(dr.stdout.chomp)
service_create if service?
Expand Down Expand Up @@ -442,7 +438,7 @@ def start
if service?
service_create
else
docker_cmd("start #{start_args} #{current_resource.id}")
docker_cmd!("start #{start_args} #{current_resource.id}")
end
end

Expand All @@ -453,10 +449,10 @@ def stop
if service?
service_stop
else
docker_cmd("stop #{stop_args} #{current_resource.id}", (new_resource.cmd_timeout + 15))
docker_cmd!("stop #{stop_args} #{current_resource.id}", (new_resource.cmd_timeout + 15))
end
end

def wait
docker_cmd("wait #{current_resource.id}")
docker_cmd!("wait #{current_resource.id}")
end
34 changes: 14 additions & 20 deletions providers/image.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
class CommandTimeout < RuntimeError; end

def load_current_resource
wait_until_ready!
@current_resource = Chef::Resource::DockerImage.new(new_resource)
dimages = docker_cmd('images -a -notrunc')
if dimages.stdout.include?(new_resource.image_name)
Expand Down Expand Up @@ -122,7 +123,7 @@ def build
command = new_resource.source
end

docker_cmd("build #{build_args} #{command}")
docker_cmd!("build #{build_args} #{command}")
end

def di(di_line)
Expand All @@ -136,23 +137,14 @@ def di(di_line)
image
end

def docker_cmd(cmd, timeout = new_resource.cmd_timeout)
execute_cmd('docker ' + cmd, timeout)
end

def execute_cmd(cmd, timeout = new_resource.cmd_timeout)
Chef::Log.debug('Executing: ' + cmd)
begin
shell_out(cmd, :timeout => timeout)
rescue Mixlib::ShellOut::CommandTimeout
raise CommandTimeout, <<-EOM
def command_timeout_error_message
<<-EOM
Command timed out:
#{cmd}
Please adjust node image_cmd_timeout attribute or this docker_image cmd_timeout attribute if necessary.
EOM
end
end

def image_id_matches?(id)
Expand Down Expand Up @@ -183,36 +175,38 @@ def import
import_args += new_resource.source
import_args += " #{new_resource.image_name}"
end
docker_cmd("import #{import_args} #{repository_and_tag_args}")
docker_cmd!("import #{import_args} #{repository_and_tag_args}")
end
end

def insert
docker_cmd("insert #{new_resource.image_name} #{new_resource.source} #{new_resource.destination}")
docker_cmd!("insert #{new_resource.image_name} #{new_resource.source} #{new_resource.destination}")
end

def installed?
@current_resource.id
end

def load
docker_cmd("load < #{new_resource.source}")
docker_cmd!("load < #{new_resource.source}")
end

def pull
pull_args = cli_args(
'registry' => new_resource.registry,
't' => new_resource.tag
)
docker_cmd("pull #{new_resource.image_name} #{pull_args}")
docker_cmd!("pull #{new_resource.image_name} #{pull_args}")
end

def push
docker_cmd("push #{new_resource.image_name}")
docker_cmd!("push #{new_resource.image_name}")
end

def remove
docker_cmd("rmi #{new_resource.image_name}")
image_name = new_resource.image_name
image_name = "#{image_name}:#{new_resource.tag}" if new_resource.tag
docker_cmd!("rmi #{image_name}")
end

def repository_and_tag_args
Expand All @@ -225,12 +219,12 @@ def repository_and_tag_args
end

def save
docker_cmd("save #{new_resource.image_name} > #{new_resource.destination}")
docker_cmd!("save #{new_resource.image_name} > #{new_resource.destination}")
end

def tag
tag_args = cli_args(
'f' => new_resource.force
)
docker_cmd("tag #{tag_args} #{new_resource.image_name} #{repository_and_tag_args}")
docker_cmd!("tag #{tag_args} #{new_resource.image_name} #{repository_and_tag_args}")
end
16 changes: 4 additions & 12 deletions providers/registry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class CommandTimeout < RuntimeError; end

def load_current_resource
@current_resource = Chef::Resource::DockerRegistry.new(new_resource)
wait_until_ready!
# TODO: load current resource?
@current_resource
end
Expand All @@ -17,23 +18,14 @@ def load_current_resource
end
end

def docker_cmd(cmd, timeout = new_resource.cmd_timeout)
execute_cmd('docker ' + cmd, timeout)
end

def execute_cmd(cmd, timeout = new_resource.cmd_timeout)
Chef::Log.debug('Executing: ' + cmd)
begin
shell_out(cmd, :timeout => timeout)
rescue Mixlib::ShellOut::CommandTimeout
raise CommandTimeout, <<-EOM
def command_timeout_error_message
<<-EOM
Command timed out:
#{cmd}
Please adjust node registry_cmd_timeout attribute or this docker_registry cmd_timeout attribute if necessary.
EOM
end
end

def logged_in?
Expand All @@ -46,5 +38,5 @@ def login
'p' => new_resource.password,
'u' => new_resource.username
)
docker_cmd("login #{new_resource.server} #{login_args}")
docker_cmd!("login #{new_resource.server} #{login_args}")
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

describe_recipe "docker_test::image_lwrp_test" do
include Helpers::DockerTest

it "has base image not installed" do
refute image_exists?("base")
end
Expand All @@ -14,4 +14,8 @@
it "has bflad/testcontainerd image installed" do
assert image_exists?("bflad/testcontainerd")
end

it "has myImage image not installed" do
refute image_exists?("myImage")
end
end
Loading

0 comments on commit 9c587b7

Please sign in to comment.