* Moved _container_config to utils.create_container_config

* memswap_limit can now be provided as a string, similar to mem_limit
This commit is contained in:
Joffrey F 2015-02-11 14:02:21 -08:00
parent c5f4c7e7d2
commit e2233fcee1
3 changed files with 147 additions and 134 deletions

View File

@ -105,134 +105,6 @@ class Client(requests.Session):
return response.content return response.content
return response.text return response.text
def _container_config(self, image, command, hostname=None, user=None,
detach=False, stdin_open=False, tty=False,
mem_limit=0, ports=None, environment=None, dns=None,
volumes=None, volumes_from=None,
network_disabled=False, entrypoint=None,
cpu_shares=None, working_dir=None,
domainname=None, memswap_limit=0, cpuset=None,
host_config=None, mac_address=None):
if isinstance(command, six.string_types):
command = shlex.split(str(command))
if isinstance(environment, dict):
environment = [
six.text_type('{0}={1}').format(k, v)
for k, v in six.iteritems(environment)
]
if isinstance(mem_limit, six.string_types):
if len(mem_limit) == 0:
mem_limit = 0
else:
units = {'b': 1,
'k': 1024,
'm': 1024 * 1024,
'g': 1024 * 1024 * 1024}
suffix = mem_limit[-1].lower()
# Check if the variable is a string representation of an int
# without a units part. Assuming that the units are bytes.
if suffix.isdigit():
digits_part = mem_limit
suffix = 'b'
else:
digits_part = mem_limit[:-1]
if suffix in units.keys() or suffix.isdigit():
try:
digits = int(digits_part)
except ValueError:
message = ('Failed converting the string value for'
' mem_limit ({0}) to a number.')
formatted_message = message.format(digits_part)
raise errors.DockerException(formatted_message)
mem_limit = digits * units[suffix]
else:
message = ('The specified value for mem_limit parameter'
' ({0}) should specify the units. The postfix'
' should be one of the `b` `k` `m` `g`'
' characters')
raise errors.DockerException(message.format(mem_limit))
if isinstance(ports, list):
exposed_ports = {}
for port_definition in ports:
port = port_definition
proto = 'tcp'
if isinstance(port_definition, tuple):
if len(port_definition) == 2:
proto = port_definition[1]
port = port_definition[0]
exposed_ports['{0}/{1}'.format(port, proto)] = {}
ports = exposed_ports
if isinstance(volumes, six.string_types):
volumes = [volumes, ]
if isinstance(volumes, list):
volumes_dict = {}
for vol in volumes:
volumes_dict[vol] = {}
volumes = volumes_dict
if volumes_from:
if not isinstance(volumes_from, six.string_types):
volumes_from = ','.join(volumes_from)
else:
# Force None, an empty list or dict causes client.start to fail
volumes_from = None
attach_stdin = False
attach_stdout = False
attach_stderr = False
stdin_once = False
if not detach:
attach_stdout = True
attach_stderr = True
if stdin_open:
attach_stdin = True
stdin_once = True
if utils.compare_version('1.10', self._version) >= 0:
message = ('{0!r} parameter has no effect on create_container().'
' It has been moved to start()')
if dns is not None:
raise errors.DockerException(message.format('dns'))
if volumes_from is not None:
raise errors.DockerException(message.format('volumes_from'))
return {
'Hostname': hostname,
'Domainname': domainname,
'ExposedPorts': ports,
'User': user,
'Tty': tty,
'OpenStdin': stdin_open,
'StdinOnce': stdin_once,
'Memory': mem_limit,
'AttachStdin': attach_stdin,
'AttachStdout': attach_stdout,
'AttachStderr': attach_stderr,
'Env': environment,
'Cmd': command,
'Dns': dns,
'Image': image,
'Volumes': volumes,
'VolumesFrom': volumes_from,
'NetworkDisabled': network_disabled,
'Entrypoint': entrypoint,
'CpuShares': cpu_shares,
'Cpuset': cpuset,
'WorkingDir': working_dir,
'MemorySwap': memswap_limit,
'HostConfig': host_config,
'MacAddress': mac_address
}
def _post_json(self, url, data, **kwargs): def _post_json(self, url, data, **kwargs):
# Go <1.1 can't unserialize null to a string # Go <1.1 can't unserialize null to a string
# so we do this disgusting thing here. # so we do this disgusting thing here.
@ -547,11 +419,11 @@ class Client(requests.Session):
'host_config is not supported in API < 1.15' 'host_config is not supported in API < 1.15'
) )
config = self._container_config( config = utils.create_container_config(
image, command, hostname, user, detach, stdin_open, tty, mem_limit, self._version, image, command, hostname, user, detach, stdin_open,
ports, environment, dns, volumes, volumes_from, network_disabled, tty, mem_limit, ports, environment, dns, volumes, volumes_from,
entrypoint, cpu_shares, working_dir, domainname, memswap_limit, network_disabled, entrypoint, cpu_shares, working_dir, domainname,
cpuset, host_config, mac_address memswap_limit, cpuset, host_config, mac_address
) )
return self.create_container_from_config(config, name) return self.create_container_from_config(config, name)

View File

@ -1,5 +1,6 @@
from .utils import ( from .utils import (
compare_version, convert_port_bindings, convert_volume_binds, compare_version, convert_port_bindings, convert_volume_binds,
mkbuildcontext, ping, tar, parse_repository_tag, parse_host, mkbuildcontext, ping, tar, parse_repository_tag, parse_host,
kwargs_from_env, convert_filters, create_host_config kwargs_from_env, convert_filters, create_host_config,
create_container_config, parse_bytes
) # flake8: noqa ) # flake8: noqa

View File

@ -16,6 +16,7 @@ import io
import os import os
import os.path import os.path
import json import json
import shlex
import tarfile import tarfile
import tempfile import tempfile
from distutils.version import StrictVersion from distutils.version import StrictVersion
@ -31,6 +32,12 @@ from .. import tls
DEFAULT_HTTP_HOST = "127.0.0.1" DEFAULT_HTTP_HOST = "127.0.0.1"
DEFAULT_UNIX_SOCKET = "http+unix://var/run/docker.sock" DEFAULT_UNIX_SOCKET = "http+unix://var/run/docker.sock"
BYTE_UNITS = {
'b': 1,
'k': 1024,
'm': 1024 * 1024,
'g': 1024 * 1024 * 1024
}
def mkbuildcontext(dockerfile): def mkbuildcontext(dockerfile):
@ -304,6 +311,41 @@ def datetime_to_timestamp(dt=datetime.now()):
return delta.seconds + delta.days * 24 * 3600 return delta.seconds + delta.days * 24 * 3600
def parse_bytes(s):
if len(s) == 0:
s = 0
else:
units = BYTE_UNITS
suffix = s[-1].lower()
# Check if the variable is a string representation of an int
# without a units part. Assuming that the units are bytes.
if suffix.isdigit():
digits_part = s
suffix = 'b'
else:
digits_part = s[:-1]
if suffix in units.keys() or suffix.isdigit():
try:
digits = int(digits_part)
except ValueError:
message = ('Failed converting the string value for'
'memory ({0}) to a number.')
formatted_message = message.format(digits_part)
raise errors.DockerException(formatted_message)
s = digits * units[suffix]
else:
message = ('The specified value for memory'
' ({0}) should specify the units. The postfix'
' should be one of the `b` `k` `m` `g`'
' characters')
raise errors.DockerException(message.format(s))
return s
def create_host_config( def create_host_config(
binds=None, port_bindings=None, lxc_conf=None, binds=None, port_bindings=None, lxc_conf=None,
publish_all_ports=False, links=None, privileged=False, publish_all_ports=False, links=None, privileged=False,
@ -392,3 +434,101 @@ def create_host_config(
host_config['LxcConf'] = lxc_conf host_config['LxcConf'] = lxc_conf
return host_config return host_config
def create_container_config(
version, image, command, hostname=None, user=None, detach=False,
stdin_open=False, tty=False, mem_limit=0, ports=None, environment=None,
dns=None, volumes=None, volumes_from=None, network_disabled=False,
entrypoint=None, cpu_shares=None, working_dir=None, domainname=None,
memswap_limit=0, cpuset=None, host_config=None, mac_address=None
):
if isinstance(command, six.string_types):
command = shlex.split(str(command))
if isinstance(environment, dict):
environment = [
six.text_type('{0}={1}').format(k, v)
for k, v in six.iteritems(environment)
]
if isinstance(mem_limit, six.string_types):
mem_limit = parse_bytes(mem_limit)
if isinstance(memswap_limit, six.string_types):
memswap_limit = parse_bytes(memswap_limit)
if isinstance(ports, list):
exposed_ports = {}
for port_definition in ports:
port = port_definition
proto = 'tcp'
if isinstance(port_definition, tuple):
if len(port_definition) == 2:
proto = port_definition[1]
port = port_definition[0]
exposed_ports['{0}/{1}'.format(port, proto)] = {}
ports = exposed_ports
if isinstance(volumes, six.string_types):
volumes = [volumes, ]
if isinstance(volumes, list):
volumes_dict = {}
for vol in volumes:
volumes_dict[vol] = {}
volumes = volumes_dict
if volumes_from:
if not isinstance(volumes_from, six.string_types):
volumes_from = ','.join(volumes_from)
else:
# Force None, an empty list or dict causes client.start to fail
volumes_from = None
attach_stdin = False
attach_stdout = False
attach_stderr = False
stdin_once = False
if not detach:
attach_stdout = True
attach_stderr = True
if stdin_open:
attach_stdin = True
stdin_once = True
if compare_version('1.10', version) >= 0:
message = ('{0!r} parameter has no effect on create_container().'
' It has been moved to start()')
if dns is not None:
raise errors.DockerException(message.format('dns'))
if volumes_from is not None:
raise errors.DockerException(message.format('volumes_from'))
return {
'Hostname': hostname,
'Domainname': domainname,
'ExposedPorts': ports,
'User': user,
'Tty': tty,
'OpenStdin': stdin_open,
'StdinOnce': stdin_once,
'Memory': mem_limit,
'AttachStdin': attach_stdin,
'AttachStdout': attach_stdout,
'AttachStderr': attach_stderr,
'Env': environment,
'Cmd': command,
'Dns': dns,
'Image': image,
'Volumes': volumes,
'VolumesFrom': volumes_from,
'NetworkDisabled': network_disabled,
'Entrypoint': entrypoint,
'CpuShares': cpu_shares,
'Cpuset': cpuset,
'WorkingDir': working_dir,
'MemorySwap': memswap_limit,
'HostConfig': host_config,
'MacAddress': mac_address
}