From bb16d9e951afbd62a9f22d02b2eb613c1ac3ef4c Mon Sep 17 00:00:00 2001 From: Sorawis Nilparuk Date: Sat, 3 Feb 2018 13:14:27 -0800 Subject: [PATCH] Add health string generator to match `docker ps` output --- compose/container.py | 14 +++++++- tests/unit/container_test.py | 67 ++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/compose/container.py b/compose/container.py index 9323b1192..0c2ca9902 100644 --- a/compose/container.py +++ b/compose/container.py @@ -129,7 +129,7 @@ class Container(object): if self.is_restarting: return 'Restarting' if self.is_running: - return 'Ghost' if self.get('State.Ghost') else 'Up' + return 'Ghost' if self.get('State.Ghost') else self.human_readable_health_status else: return 'Exit %s' % self.get('State.ExitCode') @@ -172,6 +172,18 @@ class Container(object): log_type = self.log_driver return not log_type or log_type in ('json-file', 'journald') + @property + def human_readable_health_status(self): + """ Generate UP status string with up time and health + """ + status_string = 'Up' + container_status = self.get('State.Health.Status') + if container_status == 'starting': + status_string += ' (health: starting)' + elif container_status is not None: + status_string += ' (%s)' % container_status + return status_string + def attach_log_stream(self): """A log stream can only be attached if the container uses a json-file log driver. diff --git a/tests/unit/container_test.py b/tests/unit/container_test.py index 0fcf23fa6..d64263c1f 100644 --- a/tests/unit/container_test.py +++ b/tests/unit/container_test.py @@ -129,6 +129,73 @@ class ContainerTest(unittest.TestCase): assert container.get_local_port(45454, protocol='tcp') == '0.0.0.0:49197' + def test_human_readable_states_no_health(self): + container = Container(None, { + "State": { + "Status": "running", + "Running": True, + "Paused": False, + "Restarting": False, + "OOMKilled": False, + "Dead": False, + "Pid": 7623, + "ExitCode": 0, + "Error": "", + "StartedAt": "2018-01-29T00:34:25.2052414Z", + "FinishedAt": "0001-01-01T00:00:00Z" + }, + }, has_been_inspected=True) + expected = "Up" + assert container.human_readable_state == expected + + def test_human_readable_states_starting(self): + container = Container(None, { + "State": { + "Status": "running", + "Running": True, + "Paused": False, + "Restarting": False, + "OOMKilled": False, + "Dead": False, + "Pid": 11744, + "ExitCode": 0, + "Error": "", + "StartedAt": "2018-02-03T07:56:20.3591233Z", + "FinishedAt": "2018-01-31T08:56:11.0505228Z", + "Health": { + "Status": "starting", + "FailingStreak": 0, + "Log": [] + } + } + }, has_been_inspected=True) + expected = "Up (health: starting)" + assert container.human_readable_state == expected + + def test_human_readable_states_healthy(self): + container = Container(None, { + "State": { + "Status": "running", + "Running": True, + "Paused": False, + "Restarting": False, + "OOMKilled": False, + "Dead": False, + "Pid": 5674, + "ExitCode": 0, + "Error": "", + "StartedAt": "2018-02-03T08:32:05.3281831Z", + "FinishedAt": "2018-02-03T08:11:35.7872706Z", + "Health": { + "Status": "healthy", + "FailingStreak": 0, + "Log": [] + } + } + }, has_been_inspected=True) + expected = "Up (healthy)" + assert container.human_readable_state == expected + def test_get(self): container = Container(None, { "Status": "Up 8 seconds",