From 3f679933a6695f91d24d0ed02b52f9caab2d4e5d Mon Sep 17 00:00:00 2001 From: Ryan Walls Date: Fri, 22 May 2015 16:36:38 -0600 Subject: [PATCH 1/5] Add support for --log-driver option that docker released with Docker 1.6 --- cloud/docker/docker.py | 112 +++++++++++++++++++++++++++-------------- 1 file changed, 74 insertions(+), 38 deletions(-) diff --git a/cloud/docker/docker.py b/cloud/docker/docker.py index cb6d3dae075..e4c27797b71 100644 --- a/cloud/docker/docker.py +++ b/cloud/docker/docker.py @@ -92,6 +92,21 @@ options: - 'alias. Use docker CLI-style syntax: C(redis:myredis).' default: null version_added: "1.5" + log_driver: + description: + - You can specify a different logging driver for the container than for the daemon. + "json-file" Default logging driver for Docker. Writes JSON messages to file. + docker logs command is available only for this logging driver. + "none" disables any logging for the container. docker logs won't be available with this driver. + "syslog" Syslog logging driver for Docker. Writes log messages to syslog. + docker logs command is not available for this logging driver. + Requires docker >= 1.6.0. + required: false + default: json-file + choices: + - json-file + - none + - syslog memory_limit: description: - RAM allocated to the container as a number of bytes or as a human-readable @@ -506,6 +521,7 @@ class DockerManager(object): 'restart_policy': ((0, 5, 0), '1.14'), 'extra_hosts': ((0, 7, 0), '1.3.1'), 'pid': ((1, 0, 0), '1.17'), + 'log_driver': ((1, 2, 0), '1.18'), # Clientside only 'insecure_registry': ((0, 5, 0), '0.0') } @@ -1110,6 +1126,15 @@ class DockerManager(object): self.reload_reasons.append('volumes_from ({0} => {1})'.format(actual_volumes_from, expected_volumes_from)) differing.append(container) + # LOG_DRIVER + + expected_log_driver = set(self.module.params.get('log_driver') or []) + actual_log_driver = set(container['HostConfig']['LogConfig'] or []) + if actual_log_driver != expected_log_driver: + self.reload_reasons.append('log_driver ({0} => {1})'.format(actual_log_driver, expected_log_driver)) + differing.append(container) + continue + return differing def get_deployed_containers(self): @@ -1206,6 +1231,52 @@ class DockerManager(object): except Exception as e: self.module.fail_json(msg="Failed to pull the specified image: %s" % resource, error=repr(e)) + def create_host_config(self): + params = { + 'lxc_conf': self.lxc_conf, + 'binds': self.binds, + 'port_bindings': self.port_bindings, + 'publish_all_ports': self.module.params.get('publish_all_ports'), + 'privileged': self.module.params.get('privileged'), + 'links': self.links, + 'network_mode': self.module.params.get('net'), + } + + optionals = {} + for optional_param in ('dns', 'volumes_from', 'restart_policy', + 'restart_policy_retry', 'pid', 'extra_hosts', 'log_driver'): + optionals[optional_param] = self.module.params.get(optional_param) + + if optionals['dns'] is not None: + self.ensure_capability('dns') + params['dns'] = optionals['dns'] + + if optionals['volumes_from'] is not None: + self.ensure_capability('volumes_from') + params['volumes_from'] = optionals['volumes_from'] + + if optionals['restart_policy'] is not None: + self.ensure_capability('restart_policy') + params['restart_policy'] = { 'Name': optionals['restart_policy'] } + if params['restart_policy']['Name'] == 'on-failure': + params['restart_policy']['MaximumRetryCount'] = optionals['restart_policy_retry'] + + if optionals['pid'] is not None: + self.ensure_capability('pid') + params['pid_mode'] = optionals['pid'] + + if optionals['extra_hosts'] is not None: + self.ensure_capability('extra_hosts') + params['extra_hosts'] = optionals['extra_hosts'] + + if optionals['log_driver'] is not None: + self.ensure_capability('log_driver') + log_config = docker.utils.LogConfig(type=docker.utils.LogConfig.types.JSON) + log_config.type = optionals['log_driver'] + params['log_config'] = log_config + + return docker.utils.create_host_config(**params) + def create_containers(self, count=1): try: mem_limit = _human_to_bytes(self.module.params.get('memory_limit')) @@ -1224,6 +1295,7 @@ class DockerManager(object): 'name': self.module.params.get('name'), 'stdin_open': self.module.params.get('stdin_open'), 'tty': self.module.params.get('tty'), + 'host_config': self.create_host_config(), } def do_create(count, params): @@ -1244,45 +1316,8 @@ class DockerManager(object): return containers def start_containers(self, containers): - params = { - 'lxc_conf': self.lxc_conf, - 'binds': self.binds, - 'port_bindings': self.port_bindings, - 'publish_all_ports': self.module.params.get('publish_all_ports'), - 'privileged': self.module.params.get('privileged'), - 'links': self.links, - 'network_mode': self.module.params.get('net'), - } - - optionals = {} - for optional_param in ('dns', 'volumes_from', 'restart_policy', - 'restart_policy_retry', 'pid', 'extra_hosts'): - optionals[optional_param] = self.module.params.get(optional_param) - - if optionals['dns'] is not None: - self.ensure_capability('dns') - params['dns'] = optionals['dns'] - - if optionals['volumes_from'] is not None: - self.ensure_capability('volumes_from') - params['volumes_from'] = optionals['volumes_from'] - - if optionals['restart_policy'] is not None: - self.ensure_capability('restart_policy') - params['restart_policy'] = { 'Name': optionals['restart_policy'] } - if params['restart_policy']['Name'] == 'on-failure': - params['restart_policy']['MaximumRetryCount'] = optionals['restart_policy_retry'] - - if optionals['pid'] is not None: - self.ensure_capability('pid') - params['pid_mode'] = optionals['pid'] - - if optionals['extra_hosts'] is not None: - self.ensure_capability('extra_hosts') - params['extra_hosts'] = optionals['extra_hosts'] - for i in containers: - self.client.start(i['Id'], **params) + self.client.start(i) self.increment_counter('started') def stop_containers(self, containers): @@ -1475,6 +1510,7 @@ def main(): net = dict(default=None), pid = dict(default=None), insecure_registry = dict(default=False, type='bool'), + log_driver = dict(default='json-file', choices=['json-file', 'none', 'syslog']), ), required_together = ( ['tls_client_cert', 'tls_client_key'], From 5f1d88a8299ca11bc9d1cf64f22eaa03fd8e4565 Mon Sep 17 00:00:00 2001 From: Ryan Walls Date: Wed, 27 May 2015 12:33:11 -0600 Subject: [PATCH 2/5] Update docker module to look at log_driver variable when deciding if container configuration has changed. --- cloud/docker/docker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloud/docker/docker.py b/cloud/docker/docker.py index e4c27797b71..d765ce00c66 100644 --- a/cloud/docker/docker.py +++ b/cloud/docker/docker.py @@ -1129,7 +1129,7 @@ class DockerManager(object): # LOG_DRIVER expected_log_driver = set(self.module.params.get('log_driver') or []) - actual_log_driver = set(container['HostConfig']['LogConfig'] or []) + actual_log_driver = set(container['HostConfig']['LogConfig']['Type'] or []) if actual_log_driver != expected_log_driver: self.reload_reasons.append('log_driver ({0} => {1})'.format(actual_log_driver, expected_log_driver)) differing.append(container) From c95717afe582ae889f781e44e58683b77657d1e9 Mon Sep 17 00:00:00 2001 From: Ryan Walls Date: Thu, 28 May 2015 11:36:20 -0600 Subject: [PATCH 3/5] Set default "log_driver" option to None in docker module. --- cloud/docker/docker.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cloud/docker/docker.py b/cloud/docker/docker.py index d765ce00c66..e22f8ff3edd 100644 --- a/cloud/docker/docker.py +++ b/cloud/docker/docker.py @@ -100,6 +100,7 @@ options: "none" disables any logging for the container. docker logs won't be available with this driver. "syslog" Syslog logging driver for Docker. Writes log messages to syslog. docker logs command is not available for this logging driver. + If not defined explicitly, the Docker daemon's default ("json-file") will apply. Requires docker >= 1.6.0. required: false default: json-file @@ -1510,7 +1511,7 @@ def main(): net = dict(default=None), pid = dict(default=None), insecure_registry = dict(default=False, type='bool'), - log_driver = dict(default='json-file', choices=['json-file', 'none', 'syslog']), + log_driver = dict(default=None, choices=['json-file', 'none', 'syslog']), ), required_together = ( ['tls_client_cert', 'tls_client_key'], From 88eddb13c01ff6f18c86a7b391ca2478a7fa05c7 Mon Sep 17 00:00:00 2001 From: Ryan Walls Date: Mon, 1 Jun 2015 09:48:24 -0600 Subject: [PATCH 4/5] Update docker module to avoid false positives when containers are first created. Also have the module check for api compatibility before trying to set a "--log-driver" option. --- cloud/docker/docker.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/cloud/docker/docker.py b/cloud/docker/docker.py index e22f8ff3edd..977969da03f 100644 --- a/cloud/docker/docker.py +++ b/cloud/docker/docker.py @@ -1129,12 +1129,13 @@ class DockerManager(object): # LOG_DRIVER - expected_log_driver = set(self.module.params.get('log_driver') or []) - actual_log_driver = set(container['HostConfig']['LogConfig']['Type'] or []) - if actual_log_driver != expected_log_driver: - self.reload_reasons.append('log_driver ({0} => {1})'.format(actual_log_driver, expected_log_driver)) - differing.append(container) - continue + if self.ensure_capability('log_driver', false) : + expected_log_driver = self.module.params.get('log_driver') or 'json-file' + actual_log_driver = container['HostConfig']['LogConfig']['Type'] + if actual_log_driver != expected_log_driver: + self.reload_reasons.append('log_driver ({0} => {1})'.format(actual_log_driver, expected_log_driver)) + differing.append(container) + continue return differing From a2630d40fb2239bf80509dc3843df9787258908e Mon Sep 17 00:00:00 2001 From: Ryan Walls Date: Tue, 2 Jun 2015 00:09:01 -0600 Subject: [PATCH 5/5] Fix typo in Docker module. --- cloud/docker/docker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloud/docker/docker.py b/cloud/docker/docker.py index 977969da03f..c4f8e3e9f0b 100644 --- a/cloud/docker/docker.py +++ b/cloud/docker/docker.py @@ -1129,7 +1129,7 @@ class DockerManager(object): # LOG_DRIVER - if self.ensure_capability('log_driver', false) : + if self.ensure_capability('log_driver', False) : expected_log_driver = self.module.params.get('log_driver') or 'json-file' actual_log_driver = container['HostConfig']['LogConfig']['Type'] if actual_log_driver != expected_log_driver: