Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 5 additions & 133 deletions docker/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,134 +105,6 @@ def _result(self, response, json=False, binary=False):
return response.content
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):
# Go <1.1 can't unserialize null to a string
# so we do this disgusting thing here.
Expand Down Expand Up @@ -547,11 +419,11 @@ def create_container(self, image, command=None, hostname=None, user=None,
'host_config is not supported in API < 1.15'
)

config = self._container_config(
image, command, hostname, user, detach, stdin_open, tty, mem_limit,
ports, environment, dns, volumes, volumes_from, network_disabled,
entrypoint, cpu_shares, working_dir, domainname, memswap_limit,
cpuset, host_config, mac_address
config = utils.create_container_config(
self._version, image, command, hostname, user, detach, stdin_open,
tty, mem_limit, ports, environment, dns, volumes, volumes_from,
network_disabled, entrypoint, cpu_shares, working_dir, domainname,
memswap_limit, cpuset, host_config, mac_address
)
return self.create_container_from_config(config, name)

Expand Down
3 changes: 2 additions & 1 deletion docker/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .utils import (
compare_version, convert_port_bindings, convert_volume_binds,
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
140 changes: 140 additions & 0 deletions docker/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import os
import os.path
import json
import shlex
import tarfile
import tempfile
from distutils.version import StrictVersion
Expand All @@ -31,6 +32,12 @@

DEFAULT_HTTP_HOST = "127.0.0.1"
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):
Expand Down Expand Up @@ -304,6 +311,41 @@ def datetime_to_timestamp(dt=datetime.now()):
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(
binds=None, port_bindings=None, lxc_conf=None,
publish_all_ports=False, links=None, privileged=False,
Expand Down Expand Up @@ -392,3 +434,101 @@ def create_host_config(
host_config['LxcConf'] = lxc_conf

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
}