Implement 'healthcheck' option
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
This commit is contained in:
parent
466ebb6cc1
commit
716a6baa59
9 changed files with 172 additions and 9 deletions
|
|
@ -21,6 +21,7 @@ from .. import mock
|
|||
from compose.cli.command import get_project
|
||||
from compose.container import Container
|
||||
from compose.project import OneOffFilter
|
||||
from compose.utils import nanoseconds_from_time_seconds
|
||||
from tests.integration.testcases import DockerClientTestCase
|
||||
from tests.integration.testcases import get_links
|
||||
from tests.integration.testcases import pull_busybox
|
||||
|
|
@ -329,9 +330,9 @@ class CLITestCase(DockerClientTestCase):
|
|||
},
|
||||
|
||||
'healthcheck': {
|
||||
'command': 'cat /etc/passwd',
|
||||
'interval': '10s',
|
||||
'timeout': '1s',
|
||||
'test': 'cat /etc/passwd',
|
||||
'interval': 10000000000,
|
||||
'timeout': 1000000000,
|
||||
'retries': 5,
|
||||
},
|
||||
|
||||
|
|
@ -925,6 +926,49 @@ class CLITestCase(DockerClientTestCase):
|
|||
assert foo_container.get('HostConfig.NetworkMode') == \
|
||||
'container:{}'.format(bar_container.id)
|
||||
|
||||
def test_up_with_healthcheck(self):
|
||||
def wait_on_health_status(container, status):
|
||||
def condition():
|
||||
container.inspect()
|
||||
return container.get('State.Health.Status') == status
|
||||
|
||||
return wait_on_condition(condition, delay=0.5)
|
||||
|
||||
self.base_dir = 'tests/fixtures/healthcheck'
|
||||
self.dispatch(['up', '-d'], None)
|
||||
|
||||
passes = self.project.get_service('passes')
|
||||
passes_container = passes.containers()[0]
|
||||
|
||||
assert passes_container.get('Config.Healthcheck') == {
|
||||
"Test": ["CMD-SHELL", "/bin/true"],
|
||||
"Interval": nanoseconds_from_time_seconds(1),
|
||||
"Timeout": nanoseconds_from_time_seconds(30*60),
|
||||
"Retries": 1,
|
||||
}
|
||||
|
||||
wait_on_health_status(passes_container, 'healthy')
|
||||
|
||||
fails = self.project.get_service('fails')
|
||||
fails_container = fails.containers()[0]
|
||||
|
||||
assert fails_container.get('Config.Healthcheck') == {
|
||||
"Test": ["CMD", "/bin/false"],
|
||||
"Interval": nanoseconds_from_time_seconds(2.5),
|
||||
"Retries": 2,
|
||||
}
|
||||
|
||||
wait_on_health_status(fails_container, 'unhealthy')
|
||||
|
||||
disabled = self.project.get_service('disabled')
|
||||
disabled_container = disabled.containers()[0]
|
||||
|
||||
assert disabled_container.get('Config.Healthcheck') == {
|
||||
"Test": ["NONE"],
|
||||
}
|
||||
|
||||
assert 'Health' not in disabled_container.get('State')
|
||||
|
||||
def test_up_with_no_deps(self):
|
||||
self.base_dir = 'tests/fixtures/links-composefile'
|
||||
self.dispatch(['up', '-d', '--no-deps', 'web'], None)
|
||||
|
|
|
|||
24
tests/fixtures/healthcheck/docker-compose.yml
vendored
Normal file
24
tests/fixtures/healthcheck/docker-compose.yml
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
version: "3"
|
||||
services:
|
||||
passes:
|
||||
image: busybox
|
||||
command: top
|
||||
healthcheck:
|
||||
test: "/bin/true"
|
||||
interval: 1s
|
||||
timeout: 30m
|
||||
retries: 1
|
||||
|
||||
fails:
|
||||
image: busybox
|
||||
command: top
|
||||
healthcheck:
|
||||
test: ["CMD", "/bin/false"]
|
||||
interval: 2.5s
|
||||
retries: 2
|
||||
|
||||
disabled:
|
||||
image: busybox
|
||||
command: top
|
||||
healthcheck:
|
||||
disable: true
|
||||
2
tests/fixtures/v3-full/docker-compose.yml
vendored
2
tests/fixtures/v3-full/docker-compose.yml
vendored
|
|
@ -29,7 +29,7 @@ services:
|
|||
constraints: [node=foo]
|
||||
|
||||
healthcheck:
|
||||
command: cat /etc/passwd
|
||||
test: cat /etc/passwd
|
||||
interval: 10s
|
||||
timeout: 1s
|
||||
retries: 5
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ from compose.config.errors import ConfigurationError
|
|||
from compose.config.errors import VERSION_EXPLANATION
|
||||
from compose.config.types import VolumeSpec
|
||||
from compose.const import IS_WINDOWS_PLATFORM
|
||||
from compose.utils import nanoseconds_from_time_seconds
|
||||
from tests import mock
|
||||
from tests import unittest
|
||||
|
||||
|
|
@ -3171,6 +3172,54 @@ class BuildPathTest(unittest.TestCase):
|
|||
assert 'build path' in exc.exconly()
|
||||
|
||||
|
||||
class HealthcheckTest(unittest.TestCase):
|
||||
def test_healthcheck(self):
|
||||
service_dict = make_service_dict(
|
||||
'test',
|
||||
{'healthcheck': {
|
||||
'test': ['CMD', 'true'],
|
||||
'interval': '1s',
|
||||
'timeout': '1m',
|
||||
'retries': 3,
|
||||
}},
|
||||
'.',
|
||||
)
|
||||
|
||||
assert service_dict['healthcheck'] == {
|
||||
'test': ['CMD', 'true'],
|
||||
'interval': nanoseconds_from_time_seconds(1),
|
||||
'timeout': nanoseconds_from_time_seconds(60),
|
||||
'retries': 3,
|
||||
}
|
||||
|
||||
def test_disable(self):
|
||||
service_dict = make_service_dict(
|
||||
'test',
|
||||
{'healthcheck': {
|
||||
'disable': True,
|
||||
}},
|
||||
'.',
|
||||
)
|
||||
|
||||
assert service_dict['healthcheck'] == {
|
||||
'test': ['NONE'],
|
||||
}
|
||||
|
||||
def test_disable_with_other_config_is_invalid(self):
|
||||
with pytest.raises(ConfigurationError) as excinfo:
|
||||
make_service_dict(
|
||||
'invalid-healthcheck',
|
||||
{'healthcheck': {
|
||||
'disable': True,
|
||||
'interval': '1s',
|
||||
}},
|
||||
'.',
|
||||
)
|
||||
|
||||
assert 'invalid-healthcheck' in excinfo.exconly()
|
||||
assert 'disable' in excinfo.exconly()
|
||||
|
||||
|
||||
class GetDefaultConfigFilesTestCase(unittest.TestCase):
|
||||
|
||||
files = [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue