mirror of https://github.com/docker/docker-py.git
Merge pull request #563 from docker/logconfig-support
Logconfig support
This commit is contained in:
commit
185fceda7b
|
@ -5,4 +5,4 @@ from .utils import (
|
||||||
create_container_config, parse_bytes, ping_registry
|
create_container_config, parse_bytes, ping_registry
|
||||||
) # flake8: noqa
|
) # flake8: noqa
|
||||||
|
|
||||||
from .types import Ulimit # flake8: noqa
|
from .types import Ulimit, LogConfig # flake8: noqa
|
|
@ -1,12 +1,63 @@
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
|
||||||
|
class LogConfigTypesEnum(object):
|
||||||
|
_values = (
|
||||||
|
'json-file',
|
||||||
|
'syslog',
|
||||||
|
'none'
|
||||||
|
)
|
||||||
|
JSON, SYSLOG, NONE = _values
|
||||||
|
|
||||||
|
|
||||||
class DictType(dict):
|
class DictType(dict):
|
||||||
def __init__(self, init):
|
def __init__(self, init):
|
||||||
for k, v in six.iteritems(init):
|
for k, v in six.iteritems(init):
|
||||||
self[k] = v
|
self[k] = v
|
||||||
|
|
||||||
|
|
||||||
|
class LogConfig(DictType):
|
||||||
|
types = LogConfigTypesEnum
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
type_ = kwargs.get('type', kwargs.get('Type'))
|
||||||
|
config = kwargs.get('config', kwargs.get('Config'))
|
||||||
|
if type_ not in self.types._values:
|
||||||
|
raise ValueError("LogConfig.type must be one of ({0})".format(
|
||||||
|
', '.join(self.types._values)
|
||||||
|
))
|
||||||
|
if config and not isinstance(config, dict):
|
||||||
|
raise ValueError("LogConfig.config must be a dictionary")
|
||||||
|
|
||||||
|
super(LogConfig, self).__init__({
|
||||||
|
'Type': type_,
|
||||||
|
'Config': config or {}
|
||||||
|
})
|
||||||
|
|
||||||
|
@property
|
||||||
|
def type(self):
|
||||||
|
return self['Type']
|
||||||
|
|
||||||
|
@type.setter
|
||||||
|
def type(self, value):
|
||||||
|
if value not in self.types._values:
|
||||||
|
raise ValueError("LogConfig.type must be one of {0}".format(
|
||||||
|
', '.join(self.types._values)
|
||||||
|
))
|
||||||
|
self['Type'] = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def config(self):
|
||||||
|
return self['Config']
|
||||||
|
|
||||||
|
def set_config_value(self, key, value):
|
||||||
|
self.config[key] = value
|
||||||
|
|
||||||
|
def unset_config(self, key):
|
||||||
|
if key in self.config:
|
||||||
|
del self.config[key]
|
||||||
|
|
||||||
|
|
||||||
class Ulimit(DictType):
|
class Ulimit(DictType):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
name = kwargs.get('name', kwargs.get('Name'))
|
name = kwargs.get('name', kwargs.get('Name'))
|
||||||
|
|
|
@ -28,7 +28,7 @@ import six
|
||||||
|
|
||||||
from .. import errors
|
from .. import errors
|
||||||
from .. import tls
|
from .. import tls
|
||||||
from .types import Ulimit
|
from .types import Ulimit, LogConfig
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_HTTP_HOST = "127.0.0.1"
|
DEFAULT_HTTP_HOST = "127.0.0.1"
|
||||||
|
@ -359,7 +359,7 @@ def create_host_config(
|
||||||
dns=None, dns_search=None, volumes_from=None, network_mode=None,
|
dns=None, dns_search=None, volumes_from=None, network_mode=None,
|
||||||
restart_policy=None, cap_add=None, cap_drop=None, devices=None,
|
restart_policy=None, cap_add=None, cap_drop=None, devices=None,
|
||||||
extra_hosts=None, read_only=None, pid_mode=None, ipc_mode=None,
|
extra_hosts=None, read_only=None, pid_mode=None, ipc_mode=None,
|
||||||
security_opt=None, ulimits=None
|
security_opt=None, ulimits=None, log_config=None
|
||||||
):
|
):
|
||||||
host_config = {}
|
host_config = {}
|
||||||
|
|
||||||
|
@ -456,13 +456,24 @@ def create_host_config(
|
||||||
if not isinstance(ulimits, list):
|
if not isinstance(ulimits, list):
|
||||||
raise errors.DockerException(
|
raise errors.DockerException(
|
||||||
'Invalid type for ulimits param: expected list but found'
|
'Invalid type for ulimits param: expected list but found'
|
||||||
' {0}'.format(type(ulimits)))
|
' {0}'.format(type(ulimits))
|
||||||
|
)
|
||||||
host_config['Ulimits'] = []
|
host_config['Ulimits'] = []
|
||||||
for l in ulimits:
|
for l in ulimits:
|
||||||
if not isinstance(l, Ulimit):
|
if not isinstance(l, Ulimit):
|
||||||
l = Ulimit(**l)
|
l = Ulimit(**l)
|
||||||
host_config['Ulimits'].append(l)
|
host_config['Ulimits'].append(l)
|
||||||
|
|
||||||
|
if log_config is not None:
|
||||||
|
if not isinstance(log_config, LogConfig):
|
||||||
|
if not isinstance(log_config, dict):
|
||||||
|
raise errors.DockerException(
|
||||||
|
'Invalid type for log_config param: expected LogConfig but'
|
||||||
|
' found {0}'.format(type(log_config))
|
||||||
|
)
|
||||||
|
log_config = LogConfig(**log_config)
|
||||||
|
host_config['LogConfig'] = log_config
|
||||||
|
|
||||||
return host_config
|
return host_config
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -85,8 +85,11 @@ for example:
|
||||||
* read_only (bool): mount the container's root filesystem as read only
|
* read_only (bool): mount the container's root filesystem as read only
|
||||||
* pid_mode (str): if set to "host", use the host PID namespace inside the
|
* pid_mode (str): if set to "host", use the host PID namespace inside the
|
||||||
container
|
container
|
||||||
* security_opt (list): A list of string values to customize labels for MLS systems, such as SELinux.
|
* security_opt (list): A list of string values to customize labels for MLS
|
||||||
* ulimits (list): A list of dicts or `docker.utils.Ulimit` objects.
|
systems, such as SELinux.
|
||||||
|
* ulimits (list): A list of dicts or `docker.utils.Ulimit` objects. A list
|
||||||
|
of ulimits to be set in the container.
|
||||||
|
* log_config (`docker.utils.LogConfig` or dict): Logging configuration to container
|
||||||
|
|
||||||
**Returns** (dict) HostConfig dictionary
|
**Returns** (dict) HostConfig dictionary
|
||||||
|
|
||||||
|
|
|
@ -348,6 +348,31 @@ class TestStartContainerWithFileBind(BaseTestCase):
|
||||||
os.unlink(mount_origin)
|
os.unlink(mount_origin)
|
||||||
|
|
||||||
|
|
||||||
|
class TestCreateContainerWithLogConfig(BaseTestCase):
|
||||||
|
def runTest(self):
|
||||||
|
config = docker.utils.LogConfig(
|
||||||
|
type=docker.utils.LogConfig.types.SYSLOG,
|
||||||
|
config={'key1': 'val1'}
|
||||||
|
)
|
||||||
|
ctnr = self.client.create_container(
|
||||||
|
'busybox', ['true'],
|
||||||
|
host_config=create_host_config(log_config=config)
|
||||||
|
)
|
||||||
|
self.assertIn('Id', ctnr)
|
||||||
|
self.tmp_containers.append(ctnr['Id'])
|
||||||
|
self.client.start(ctnr)
|
||||||
|
info = self.client.inspect_container(ctnr)
|
||||||
|
self.assertIn('HostConfig', info)
|
||||||
|
host_config = info['HostConfig']
|
||||||
|
self.assertIn('LogConfig', host_config)
|
||||||
|
log_config = host_config['LogConfig']
|
||||||
|
self.assertIn('Type', log_config)
|
||||||
|
self.assertEqual(log_config['Type'], config.type)
|
||||||
|
self.assertIn('Config', log_config)
|
||||||
|
self.assertEqual(type(log_config['Config']), dict)
|
||||||
|
self.assertEqual(log_config['Config'], config.config)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(not EXEC_DRIVER_IS_NATIVE, 'Exec driver not native')
|
@unittest.skipIf(not EXEC_DRIVER_IS_NATIVE, 'Exec driver not native')
|
||||||
class TestCreateContainerReadOnlyFs(BaseTestCase):
|
class TestCreateContainerReadOnlyFs(BaseTestCase):
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
|
@ -958,7 +983,7 @@ class TestStartContainerWithVolumesFrom(BaseTestCase):
|
||||||
|
|
||||||
class TestStartContainerWithUlimits(BaseTestCase):
|
class TestStartContainerWithUlimits(BaseTestCase):
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
ulimit = docker.utils.Ulimit('nofile', 4096, 4096)
|
ulimit = docker.utils.Ulimit(name='nofile', soft=4096, hard=4096)
|
||||||
|
|
||||||
res0 = self.client.create_container('busybox', 'true')
|
res0 = self.client.create_container('busybox', 'true')
|
||||||
container1_id = res0['Id']
|
container1_id = res0['Id']
|
||||||
|
|
|
@ -6,7 +6,7 @@ from docker.client import Client
|
||||||
from docker.errors import DockerException
|
from docker.errors import DockerException
|
||||||
from docker.utils import (
|
from docker.utils import (
|
||||||
parse_repository_tag, parse_host, convert_filters, kwargs_from_env,
|
parse_repository_tag, parse_host, convert_filters, kwargs_from_env,
|
||||||
create_host_config, Ulimit
|
create_host_config, Ulimit, LogConfig
|
||||||
)
|
)
|
||||||
from docker.utils.ports import build_port_bindings, split_port
|
from docker.utils.ports import build_port_bindings, split_port
|
||||||
from docker.auth import resolve_authconfig
|
from docker.auth import resolve_authconfig
|
||||||
|
@ -141,6 +141,26 @@ class UtilsTest(base.BaseTestCase):
|
||||||
self.assertRaises(ValueError, lambda: Ulimit(name='hello', soft='123'))
|
self.assertRaises(ValueError, lambda: Ulimit(name='hello', soft='123'))
|
||||||
self.assertRaises(ValueError, lambda: Ulimit(name='hello', hard='456'))
|
self.assertRaises(ValueError, lambda: Ulimit(name='hello', hard='456'))
|
||||||
|
|
||||||
|
def test_create_host_config_dict_logconfig(self):
|
||||||
|
dct = {'type': LogConfig.types.SYSLOG, 'config': {'key1': 'val1'}}
|
||||||
|
config = create_host_config(log_config=dct)
|
||||||
|
self.assertIn('LogConfig', config)
|
||||||
|
self.assertTrue(isinstance(config['LogConfig'], LogConfig))
|
||||||
|
self.assertEqual(dct['type'], config['LogConfig'].type)
|
||||||
|
|
||||||
|
def test_create_host_config_obj_logconfig(self):
|
||||||
|
obj = LogConfig(type=LogConfig.types.SYSLOG, config={'key1': 'val1'})
|
||||||
|
config = create_host_config(log_config=obj)
|
||||||
|
self.assertIn('LogConfig', config)
|
||||||
|
self.assertTrue(isinstance(config['LogConfig'], LogConfig))
|
||||||
|
self.assertEqual(obj, config['LogConfig'])
|
||||||
|
|
||||||
|
def test_logconfig_invalid_type(self):
|
||||||
|
self.assertRaises(ValueError, lambda: LogConfig(type='xxx', config={}))
|
||||||
|
self.assertRaises(ValueError, lambda: LogConfig(
|
||||||
|
type=LogConfig.types.JSON, config='helloworld'
|
||||||
|
))
|
||||||
|
|
||||||
def test_resolve_authconfig(self):
|
def test_resolve_authconfig(self):
|
||||||
auth_config = {
|
auth_config = {
|
||||||
'https://index.docker.io/v1/': {'auth': 'indexuser'},
|
'https://index.docker.io/v1/': {'auth': 'indexuser'},
|
||||||
|
|
Loading…
Reference in New Issue