Skip to content

Commit

Permalink
Merge branch 'master' into feature/plugin-system
Browse files Browse the repository at this point in the history
  • Loading branch information
GM-Alex authored Sep 16, 2016
2 parents 92b5a62 + 651283e commit 67a21f4
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 10 deletions.
7 changes: 4 additions & 3 deletions compose/bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ def __init__(self, image_name):


class NeedsPull(Exception):
def __init__(self, image_name):
def __init__(self, image_name, service_name):
self.image_name = image_name
self.service_name = service_name


class MissingDigests(Exception):
Expand All @@ -74,7 +75,7 @@ def get_image_digests(project, allow_push=False):
except NeedsPush as e:
needs_push.add(e.image_name)
except NeedsPull as e:
needs_pull.add(e.image_name)
needs_pull.add(e.service_name)

if needs_push or needs_pull:
raise MissingDigests(needs_push, needs_pull)
Expand Down Expand Up @@ -109,7 +110,7 @@ def get_image_digest(service, allow_push=False):
return image['RepoDigests'][0]

if 'build' not in service.options:
raise NeedsPull(service.image_name)
raise NeedsPull(service.image_name, service.name)

if not allow_push:
raise NeedsPush(service.image_name)
Expand Down
11 changes: 9 additions & 2 deletions compose/cli/log_printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from itertools import cycle
from threading import Thread

from docker.errors import APIError
from six.moves import _thread as thread
from six.moves.queue import Empty
from six.moves.queue import Queue
Expand Down Expand Up @@ -176,8 +177,14 @@ def build_log_generator(container, log_args):


def wait_on_exit(container):
exit_code = container.wait()
return "%s exited with code %s\n" % (container.name, exit_code)
try:
exit_code = container.wait()
return "%s exited with code %s\n" % (container.name, exit_code)
except APIError as e:
return "Unexpected API error for %s (HTTP code %s)\nResponse body:\n%s\n" % (
container.name, e.response.status_code,
e.response.text or '[empty]'
)


def start_producer_thread(thread_args):
Expand Down
2 changes: 1 addition & 1 deletion compose/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def log_driver(self):
@property
def has_api_logs(self):
log_type = self.log_driver
return not log_type or log_type != 'none'
return not log_type or log_type in ('json-file', 'journald')

def attach_log_stream(self):
"""A log stream can only be attached if the container uses a json-file
Expand Down
5 changes: 3 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
PyYAML==3.11
backports.ssl-match-hostname==3.5.0.1; python_version < '3'
cached-property==1.2.0
docker-py==1.9.0
docker-py==1.10.2
dockerpty==0.4.1
docopt==0.6.1
enum34==1.0.4; python_version < '3.4'
functools32==3.2.3.post2; python_version < '3.2'
ipaddress==1.0.16
jsonschema==2.5.1
pypiwin32==219; sys_platform == 'win32'
requests==2.7.0
six==1.7.3
six==1.10.0
texttable==0.8.4
websocket-client==0.32.0
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def find_version(*file_paths):
'requests >= 2.6.1, < 2.8',
'texttable >= 0.8.1, < 0.9',
'websocket-client >= 0.32.0, < 1.0',
'docker-py >= 1.9.0, < 2.0',
'docker-py >= 1.10.2, < 2.0',
'dockerpty >= 0.4.1, < 0.5',
'six >= 1.3.0, < 2',
'jsonschema >= 2.5.1, < 3',
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/cli/errors_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_generic_connection_error(self, mock_logging):
raise ConnectionError()

_, args, _ = mock_logging.error.mock_calls[0]
assert "Couldn't connect to Docker daemon at" in args[0]
assert "Couldn't connect to Docker daemon" in args[0]

def test_api_error_version_mismatch(self, mock_logging):
with pytest.raises(errors.ConnectionError):
Expand Down
22 changes: 22 additions & 0 deletions tests/unit/cli/log_printer_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import itertools

import pytest
import requests
import six
from docker.errors import APIError
from six.moves.queue import Queue

from compose.cli.log_printer import build_log_generator
Expand Down Expand Up @@ -56,6 +58,26 @@ def test_wait_on_exit():
assert expected == wait_on_exit(mock_container)


def test_wait_on_exit_raises():
status_code = 500

def mock_wait():
resp = requests.Response()
resp.status_code = status_code
raise APIError('Bad server', resp)

mock_container = mock.Mock(
spec=Container,
name='cname',
wait=mock_wait
)

expected = 'Unexpected API error for {} (HTTP code {})\n'.format(
mock_container.name, status_code,
)
assert expected in wait_on_exit(mock_container)


def test_build_no_log_generator(mock_container):
mock_container.has_api_logs = False
mock_container.log_driver = 'none'
Expand Down
28 changes: 28 additions & 0 deletions tests/unit/container_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,34 @@ def test_short_id(self):
container = Container(None, self.container_dict, has_been_inspected=True)
assert container.short_id == self.container_id[:12]

def test_has_api_logs(self):
container_dict = {
'HostConfig': {
'LogConfig': {
'Type': 'json-file'
}
}
}

container = Container(None, container_dict, has_been_inspected=True)
assert container.has_api_logs is True

container_dict['HostConfig']['LogConfig']['Type'] = 'none'
container = Container(None, container_dict, has_been_inspected=True)
assert container.has_api_logs is False

container_dict['HostConfig']['LogConfig']['Type'] = 'syslog'
container = Container(None, container_dict, has_been_inspected=True)
assert container.has_api_logs is False

container_dict['HostConfig']['LogConfig']['Type'] = 'journald'
container = Container(None, container_dict, has_been_inspected=True)
assert container.has_api_logs is True

container_dict['HostConfig']['LogConfig']['Type'] = 'foobar'
container = Container(None, container_dict, has_been_inspected=True)
assert container.has_api_logs is False


class GetContainerNameTestCase(unittest.TestCase):

Expand Down

0 comments on commit 67a21f4

Please sign in to comment.