mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Do not pass any argument to docker.start
docker.create is responsible to manage all of them, since docker API 1.16
This commit is contained in:
parent
d8cca2a009
commit
65c8762e1f
3 changed files with 423 additions and 493 deletions
|
@ -289,7 +289,7 @@ __func_alias__ = {
|
|||
}
|
||||
|
||||
# Minimum supported versions
|
||||
MIN_DOCKER = (1, 0, 0)
|
||||
MIN_DOCKER = (1, 4, 0)
|
||||
MIN_DOCKER_PY = (1, 4, 0)
|
||||
|
||||
VERSION_RE = r'([\d.]+)'
|
||||
|
@ -420,9 +420,6 @@ VALID_CREATE_OPTS = {
|
|||
'labels': {
|
||||
'path': 'Config:Labels',
|
||||
},
|
||||
}
|
||||
|
||||
VALID_RUNTIME_OPTS = {
|
||||
'binds': {
|
||||
'path': 'HostConfig:Binds',
|
||||
},
|
||||
|
@ -1039,8 +1036,7 @@ def _error_detail(data, item):
|
|||
data.append(msg)
|
||||
|
||||
|
||||
def _validate_input(action,
|
||||
kwargs,
|
||||
def _validate_input(kwargs,
|
||||
validate_ip_addrs=True):
|
||||
'''
|
||||
Perform validation on kwargs. Checks each key in kwargs against the
|
||||
|
@ -1670,15 +1666,6 @@ def _validate_input(action,
|
|||
kwargs['labels'] = salt.utils.repack_dictlist(kwargs['labels'])
|
||||
|
||||
# And now, the actual logic to perform the validation
|
||||
if action == 'create':
|
||||
valid_opts = VALID_CREATE_OPTS
|
||||
elif action == 'runtime':
|
||||
valid_opts = VALID_RUNTIME_OPTS
|
||||
else:
|
||||
raise SaltInvocationError(
|
||||
'Invalid validation action \'{0}\''.format(action)
|
||||
)
|
||||
|
||||
if 'docker.docker_version' not in __context__:
|
||||
# Have to call this func using the __salt__ dunder (instead of just
|
||||
# version()) because this _validate_input() will be imported into the
|
||||
|
@ -1696,13 +1683,13 @@ def _validate_input(action,
|
|||
|
||||
_locals = locals()
|
||||
for kwarg in kwargs:
|
||||
if kwarg not in valid_opts:
|
||||
if kwarg not in VALID_CREATE_OPTS:
|
||||
raise SaltInvocationError('Invalid argument \'{0}\''.format(kwarg))
|
||||
|
||||
# Check for Docker/docker-py compatibility
|
||||
compat_errors = []
|
||||
if 'min_docker' in valid_opts[kwarg]:
|
||||
min_docker = valid_opts[kwarg]['min_docker']
|
||||
if 'min_docker' in VALID_CREATE_OPTS[kwarg]:
|
||||
min_docker = VALID_CREATE_OPTS[kwarg]['min_docker']
|
||||
if __context__['docker.docker_version'] is not None:
|
||||
if __context__['docker.docker_version'] < min_docker:
|
||||
compat_errors.append(
|
||||
|
@ -1713,10 +1700,10 @@ def _validate_input(action,
|
|||
'.'.join(__context__['docker.docker_version'])
|
||||
)
|
||||
)
|
||||
if 'min_docker_py' in valid_opts[kwarg]:
|
||||
if 'min_docker_py' in VALID_CREATE_OPTS[kwarg]:
|
||||
cur_docker_py = _get_docker_py_versioninfo()
|
||||
if cur_docker_py is not None:
|
||||
min_docker_py = valid_opts[kwarg]['min_docker_py']
|
||||
min_docker_py = VALID_CREATE_OPTS[kwarg]['min_docker_py']
|
||||
if cur_docker_py < min_docker_py:
|
||||
compat_errors.append(
|
||||
'The \'{0}\' parameter requires at least docker-py '
|
||||
|
@ -1729,7 +1716,7 @@ def _validate_input(action,
|
|||
if compat_errors:
|
||||
raise SaltInvocationError('; '.join(compat_errors))
|
||||
|
||||
default_val = valid_opts[kwarg].get('default')
|
||||
default_val = VALID_CREATE_OPTS[kwarg].get('default')
|
||||
if kwargs[kwarg] is None:
|
||||
if default_val is None:
|
||||
# Passed as None and None is the default. Skip validation. This
|
||||
|
@ -1740,7 +1727,7 @@ def _validate_input(action,
|
|||
# None, don't let them do this.
|
||||
raise SaltInvocationError(kwarg + ' cannot be None')
|
||||
|
||||
validator = valid_opts[kwarg].get('validator')
|
||||
validator = VALID_CREATE_OPTS[kwarg].get('validator')
|
||||
if validator is None:
|
||||
# Look for custom validation function
|
||||
validator = kwarg
|
||||
|
@ -2538,6 +2525,7 @@ def version():
|
|||
@_refresh_mine_cache
|
||||
def create(image,
|
||||
name=None,
|
||||
validate_ip_addrs=True,
|
||||
client_timeout=CLIENT_TIMEOUT,
|
||||
**kwargs):
|
||||
'''
|
||||
|
@ -2678,6 +2666,166 @@ def create(image,
|
|||
Example: ``labels=LABEL1,LABEL2``,
|
||||
``labels="{'LABEL1': 'value1', 'LABEL2': 'value2'}"``
|
||||
|
||||
validate_ip_addrs : True
|
||||
For parameters which accept IP addresses as input, IP address
|
||||
validation will be performed. To disable, set this to ``False``
|
||||
|
||||
binds
|
||||
Files/directories to bind mount. Each bind mount should be passed in
|
||||
the format ``<host_path>:<container_path>:<read_only>``, where
|
||||
``<read_only>`` is one of ``rw`` (for read-write access) or ``ro`` (for
|
||||
read-only access). Optionally, the read-only information can be left
|
||||
off the end and the bind mount will be assumed to be read-write.
|
||||
Examples 2 and 3 below are equivalent.
|
||||
|
||||
Example 1: ``binds=/srv/www:/var/www:ro``
|
||||
|
||||
Example 2: ``binds=/srv/www:/var/www:rw``
|
||||
|
||||
Example 3: ``binds=/srv/www:/var/www``
|
||||
|
||||
port_bindings
|
||||
Bind exposed ports which were exposed using the ``ports`` argument to
|
||||
:py:func:`dockerng.create <salt.modules.dockerng.create>`. These
|
||||
should be passed in the same way as the ``--publish`` argument to the
|
||||
``docker run`` CLI command:
|
||||
|
||||
- ``ip:hostPort:containerPort`` - Bind a specific IP and port on the
|
||||
host to a specific port within the container.
|
||||
- ``ip::containerPort`` - Bind a specific IP and an ephemeral port to a
|
||||
specific port within the container.
|
||||
- ``hostPort:containerPort`` - Bind a specific port on all of the
|
||||
host's interfaces to a specific port within the container.
|
||||
- ``containerPort`` - Bind an ephemeral port on all of the host's
|
||||
interfaces to a specific port within the container.
|
||||
|
||||
Multiple bindings can be separated by commas, or passed as a Python
|
||||
list. The below two examples are equivalent:
|
||||
|
||||
Example 1: ``port_bindings="5000:5000,2123:2123/udp,8080"``
|
||||
|
||||
Example 2: ``port_bindings="['5000:5000', '2123:2123/udp', '8080']"``
|
||||
|
||||
.. note::
|
||||
|
||||
When configuring bindings for UDP ports, the protocol must be
|
||||
passed in the ``containerPort`` value, as seen in the examples
|
||||
above.
|
||||
|
||||
lxc_conf
|
||||
Additional LXC configuration parameters to set before starting the
|
||||
container.
|
||||
|
||||
Example: ``lxc_conf="{lxc.utsname: docker}"``
|
||||
|
||||
.. note::
|
||||
|
||||
These LXC configuration parameters will only have the desired
|
||||
effect if the container is using the LXC execution driver, which
|
||||
has not been the default for some time.
|
||||
|
||||
publish_all_ports : False
|
||||
Allocates a random host port for each port exposed using the ``ports``
|
||||
argument to :py:func:`dockerng.create <salt.modules.dockerng.create>`.
|
||||
|
||||
Example: ``publish_all_ports=True``
|
||||
|
||||
links
|
||||
Link this container to another. Links should be specified in the format
|
||||
``<container_name_or_id>:<link_alias>``. Multiple links can be passed,
|
||||
ether as a comma separated list or a Python list.
|
||||
|
||||
Example 1: ``links=mycontainer:myalias``,
|
||||
``links=web1:link1,web2:link2``
|
||||
|
||||
Example 2: ``links="['mycontainer:myalias']"``
|
||||
``links="['web1:link1', 'web2:link2']"``
|
||||
|
||||
dns
|
||||
List of DNS nameservers. Can be passed as a comma-separated list or a
|
||||
Python list.
|
||||
|
||||
Example: ``dns=8.8.8.8,8.8.4.4`` or ``dns="[8.8.8.8, 8.8.4.4]"``
|
||||
|
||||
.. note::
|
||||
|
||||
To skip IP address validation, use ``validate_ip_addrs=False``
|
||||
|
||||
dns_search
|
||||
List of DNS search domains. Can be passed as a comma-separated list
|
||||
or a Python list.
|
||||
|
||||
Example: ``dns_search=foo1.domain.tld,foo2.domain.tld`` or
|
||||
``dns_search="[foo1.domain.tld, foo2.domain.tld]"``
|
||||
|
||||
volumes_from
|
||||
Container names or IDs from which the container will get volumes. Can
|
||||
be passed as a comma-separated list or a Python list.
|
||||
|
||||
Example: ``volumes_from=foo``, ``volumes_from=foo,bar``,
|
||||
``volumes_from="[foo, bar]"``
|
||||
|
||||
network_mode : bridge
|
||||
One of the following:
|
||||
|
||||
- ``bridge`` - Creates a new network stack for the container on the
|
||||
docker bridge
|
||||
- ``null`` - No networking (equivalent of the Docker CLI argument
|
||||
``--net=none``)
|
||||
- ``container:<name_or_id>`` - Reuses another container's network stack
|
||||
- ``host`` - Use the host's network stack inside the container
|
||||
|
||||
.. warning::
|
||||
|
||||
Using ``host`` mode gives the container full access to the
|
||||
hosts system's services (such as D-bus), and is therefore
|
||||
considered insecure.
|
||||
|
||||
Example: ``network_mode=null``, ``network_mode=container:web1``
|
||||
|
||||
restart_policy
|
||||
Set a restart policy for the container. Must be passed as a string in
|
||||
the format ``policy[:retry_count]`` where ``policy`` is one of
|
||||
``always`` or ``on-failure``, and ``retry_count`` is an optional limit
|
||||
to the number of retries. The retry count is ignored when using the
|
||||
``always`` restart policy.
|
||||
|
||||
Example 1: ``restart_policy=on-failure:5``
|
||||
|
||||
Example 2: ``restart_policy=always``
|
||||
|
||||
cap_add
|
||||
List of capabilities to add within the container. Can be passed as a
|
||||
comma-separated list or a Python list. Requires Docker 1.2.0 or
|
||||
newer.
|
||||
|
||||
Example: ``cap_add=SYS_ADMIN,MKNOD``, ``cap_add="[SYS_ADMIN, MKNOD]"``
|
||||
|
||||
cap_drop
|
||||
List of capabilities to drop within the container. Can be passed as a
|
||||
comma-separated string or a Python list. Requires Docker 1.2.0 or
|
||||
newer.
|
||||
|
||||
Example: ``cap_drop=SYS_ADMIN,MKNOD``,
|
||||
``cap_drop="[SYS_ADMIN, MKNOD]"``
|
||||
|
||||
extra_hosts
|
||||
Additional hosts to add to the container's /etc/hosts file. Can be
|
||||
passed as a comma-separated list or a Python list. Requires Docker
|
||||
1.3.0 or newer.
|
||||
|
||||
Example: ``extra_hosts=web1:10.9.8.7,web2:10.9.8.8``
|
||||
|
||||
.. note::
|
||||
|
||||
To skip IP address validation, use ``validate_ip_addrs=False``
|
||||
|
||||
pid_mode
|
||||
Set to ``host`` to use the host container's PID namespace within the
|
||||
container. Requires Docker 1.5.0 or newer.
|
||||
|
||||
Example: ``pid_mode=host``
|
||||
|
||||
**RETURN DATA**
|
||||
|
||||
A dictionary containing the following keys:
|
||||
|
@ -2716,7 +2864,7 @@ def create(image,
|
|||
create_kwargs['hostname'] = create_kwargs['name']
|
||||
|
||||
if create_kwargs.pop('validate_input', False):
|
||||
_validate_input('create', create_kwargs)
|
||||
_validate_input(create_kwargs, validate_ip_addrs=validate_ip_addrs)
|
||||
|
||||
# Rename the kwargs whose names differ from their counterparts in the
|
||||
# docker.client.Client class member functions. Can't use iterators here
|
||||
|
@ -4215,174 +4363,13 @@ def signal_(name, signal):
|
|||
|
||||
@_refresh_mine_cache
|
||||
@_ensure_exists
|
||||
def start(name, validate_ip_addrs=True, **kwargs):
|
||||
def start(name):
|
||||
'''
|
||||
Start a container
|
||||
|
||||
name
|
||||
Container name or ID
|
||||
|
||||
validate_ip_addrs : True
|
||||
For parameters which accept IP addresses as input, IP address
|
||||
validation will be performed. To disable, set this to ``False``
|
||||
|
||||
binds
|
||||
Files/directories to bind mount. Each bind mount should be passed in
|
||||
the format ``<host_path>:<container_path>:<read_only>``, where
|
||||
``<read_only>`` is one of ``rw`` (for read-write access) or ``ro`` (for
|
||||
read-only access). Optionally, the read-only information can be left
|
||||
off the end and the bind mount will be assumed to be read-write.
|
||||
Examples 2 and 3 below are equivalent.
|
||||
|
||||
Example 1: ``binds=/srv/www:/var/www:ro``
|
||||
|
||||
Example 2: ``binds=/srv/www:/var/www:rw``
|
||||
|
||||
Example 3: ``binds=/srv/www:/var/www``
|
||||
|
||||
port_bindings
|
||||
Bind exposed ports which were exposed using the ``ports`` argument to
|
||||
:py:func:`dockerng.create <salt.modules.dockerng.create>`. These
|
||||
should be passed in the same way as the ``--publish`` argument to the
|
||||
``docker run`` CLI command:
|
||||
|
||||
- ``ip:hostPort:containerPort`` - Bind a specific IP and port on the
|
||||
host to a specific port within the container.
|
||||
- ``ip::containerPort`` - Bind a specific IP and an ephemeral port to a
|
||||
specific port within the container.
|
||||
- ``hostPort:containerPort`` - Bind a specific port on all of the
|
||||
host's interfaces to a specific port within the container.
|
||||
- ``containerPort`` - Bind an ephemeral port on all of the host's
|
||||
interfaces to a specific port within the container.
|
||||
|
||||
Multiple bindings can be separated by commas, or passed as a Python
|
||||
list. The below two examples are equivalent:
|
||||
|
||||
Example 1: ``port_bindings="5000:5000,2123:2123/udp,8080"``
|
||||
|
||||
Example 2: ``port_bindings="['5000:5000', '2123:2123/udp', '8080']"``
|
||||
|
||||
.. note::
|
||||
|
||||
When configuring bindings for UDP ports, the protocol must be
|
||||
passed in the ``containerPort`` value, as seen in the examples
|
||||
above.
|
||||
|
||||
lxc_conf
|
||||
Additional LXC configuration parameters to set before starting the
|
||||
container.
|
||||
|
||||
Example: ``lxc_conf="{lxc.utsname: docker}"``
|
||||
|
||||
.. note::
|
||||
|
||||
These LXC configuration parameters will only have the desired
|
||||
effect if the container is using the LXC execution driver, which
|
||||
has not been the default for some time.
|
||||
|
||||
publish_all_ports : False
|
||||
Allocates a random host port for each port exposed using the ``ports``
|
||||
argument to :py:func:`dockerng.create <salt.modules.dockerng.create>`.
|
||||
|
||||
Example: ``publish_all_ports=True``
|
||||
|
||||
links
|
||||
Link this container to another. Links should be specified in the format
|
||||
``<container_name_or_id>:<link_alias>``. Multiple links can be passed,
|
||||
ether as a comma separated list or a Python list.
|
||||
|
||||
Example 1: ``links=mycontainer:myalias``,
|
||||
``links=web1:link1,web2:link2``
|
||||
|
||||
Example 2: ``links="['mycontainer:myalias']"``
|
||||
``links="['web1:link1', 'web2:link2']"``
|
||||
|
||||
dns
|
||||
List of DNS nameservers. Can be passed as a comma-separated list or a
|
||||
Python list.
|
||||
|
||||
Example: ``dns=8.8.8.8,8.8.4.4`` or ``dns="[8.8.8.8, 8.8.4.4]"``
|
||||
|
||||
.. note::
|
||||
|
||||
To skip IP address validation, use ``validate_ip_addrs=False``
|
||||
|
||||
dns_search
|
||||
List of DNS search domains. Can be passed as a comma-separated list
|
||||
or a Python list.
|
||||
|
||||
Example: ``dns_search=foo1.domain.tld,foo2.domain.tld`` or
|
||||
``dns_search="[foo1.domain.tld, foo2.domain.tld]"``
|
||||
|
||||
volumes_from
|
||||
Container names or IDs from which the container will get volumes. Can
|
||||
be passed as a comma-separated list or a Python list.
|
||||
|
||||
Example: ``volumes_from=foo``, ``volumes_from=foo,bar``,
|
||||
``volumes_from="[foo, bar]"``
|
||||
|
||||
network_mode : bridge
|
||||
One of the following:
|
||||
|
||||
- ``bridge`` - Creates a new network stack for the container on the
|
||||
docker bridge
|
||||
- ``null`` - No networking (equivalent of the Docker CLI argument
|
||||
``--net=none``)
|
||||
- ``container:<name_or_id>`` - Reuses another container's network stack
|
||||
- ``host`` - Use the host's network stack inside the container
|
||||
|
||||
.. warning::
|
||||
|
||||
Using ``host`` mode gives the container full access to the
|
||||
hosts system's services (such as D-bus), and is therefore
|
||||
considered insecure.
|
||||
|
||||
Example: ``network_mode=null``, ``network_mode=container:web1``
|
||||
|
||||
restart_policy
|
||||
Set a restart policy for the container. Must be passed as a string in
|
||||
the format ``policy[:retry_count]`` where ``policy`` is one of
|
||||
``always`` or ``on-failure``, and ``retry_count`` is an optional limit
|
||||
to the number of retries. The retry count is ignored when using the
|
||||
``always`` restart policy.
|
||||
|
||||
Example 1: ``restart_policy=on-failure:5``
|
||||
|
||||
Example 2: ``restart_policy=always``
|
||||
|
||||
cap_add
|
||||
List of capabilities to add within the container. Can be passed as a
|
||||
comma-separated list or a Python list. Requires Docker 1.2.0 or
|
||||
newer.
|
||||
|
||||
Example: ``cap_add=SYS_ADMIN,MKNOD``, ``cap_add="[SYS_ADMIN, MKNOD]"``
|
||||
|
||||
cap_drop
|
||||
List of capabilities to drop within the container. Can be passed as a
|
||||
comma-separated string or a Python list. Requires Docker 1.2.0 or
|
||||
newer.
|
||||
|
||||
Example: ``cap_drop=SYS_ADMIN,MKNOD``,
|
||||
``cap_drop="[SYS_ADMIN, MKNOD]"``
|
||||
|
||||
extra_hosts
|
||||
Additional hosts to add to the container's /etc/hosts file. Can be
|
||||
passed as a comma-separated list or a Python list. Requires Docker
|
||||
1.3.0 or newer.
|
||||
|
||||
Example: ``extra_hosts=web1:10.9.8.7,web2:10.9.8.8``
|
||||
|
||||
.. note::
|
||||
|
||||
To skip IP address validation, use ``validate_ip_addrs=False``
|
||||
|
||||
pid_mode
|
||||
Set to ``host`` to use the host container's PID namespace within the
|
||||
container. Requires Docker 1.5.0 or newer.
|
||||
|
||||
Example: ``pid_mode=host``
|
||||
|
||||
|
||||
**RETURN DATA**
|
||||
|
||||
A dictionary will be returned, containing the following keys:
|
||||
|
@ -4406,26 +4393,7 @@ def start(name, validate_ip_addrs=True, **kwargs):
|
|||
'comment': ('Container \'{0}\' is paused, cannot start'
|
||||
.format(name))}
|
||||
|
||||
runtime_kwargs = salt.utils.clean_kwargs(**copy.deepcopy(kwargs))
|
||||
if runtime_kwargs.pop('validate_input', False):
|
||||
_validate_input('runtime',
|
||||
runtime_kwargs,
|
||||
validate_ip_addrs=validate_ip_addrs)
|
||||
|
||||
# Rename the kwargs whose names differ from their counterparts in the
|
||||
# docker.client.Client class member functions. Can't use iterators here
|
||||
# because we're going to be modifying the dict.
|
||||
for key in list(six.iterkeys(VALID_RUNTIME_OPTS)):
|
||||
if key in runtime_kwargs:
|
||||
val = VALID_RUNTIME_OPTS[key]
|
||||
if 'api_name' in val:
|
||||
runtime_kwargs[val['api_name']] = runtime_kwargs.pop(key)
|
||||
|
||||
log.debug(
|
||||
'dockerng.start is using the following kwargs to start container '
|
||||
'\'{0}\': {1}'.format(name, runtime_kwargs)
|
||||
)
|
||||
return _change_state(name, 'start', 'running', **runtime_kwargs)
|
||||
return _change_state(name, 'start', 'running')
|
||||
|
||||
|
||||
@_refresh_mine_cache
|
||||
|
|
|
@ -49,7 +49,6 @@ from salt.modules.dockerng import (
|
|||
CLIENT_TIMEOUT,
|
||||
STOP_TIMEOUT,
|
||||
VALID_CREATE_OPTS,
|
||||
VALID_RUNTIME_OPTS,
|
||||
_validate_input,
|
||||
_get_repo_tag
|
||||
)
|
||||
|
@ -122,7 +121,7 @@ def _prep_input(kwargs):
|
|||
raise SaltInvocationError(err)
|
||||
|
||||
|
||||
def _compare(actual, create_kwargs, runtime_kwargs):
|
||||
def _compare(actual, create_kwargs):
|
||||
'''
|
||||
Compare the desired configuration against the actual configuration returned
|
||||
by dockerng.inspect_container
|
||||
|
@ -131,250 +130,247 @@ def _compare(actual, create_kwargs, runtime_kwargs):
|
|||
salt.utils.traverse_dict(actual, path, NOTSET, delimiter=':')
|
||||
)
|
||||
ret = {}
|
||||
for desired, valid_opts in ((create_kwargs, VALID_CREATE_OPTS),
|
||||
(runtime_kwargs, VALID_RUNTIME_OPTS)):
|
||||
for item, data, in six.iteritems(desired):
|
||||
if item not in valid_opts:
|
||||
log.error(
|
||||
'Trying to compare \'{0}\', but it is not a valid '
|
||||
'parameter. Skipping.'.format(item)
|
||||
)
|
||||
continue
|
||||
log.trace('dockerng.running: comparing ' + item)
|
||||
conf_path = valid_opts[item]['path']
|
||||
if isinstance(conf_path, tuple):
|
||||
actual_data = [_get(x) for x in conf_path]
|
||||
for val in actual_data:
|
||||
if val is NOTSET:
|
||||
_api_mismatch(item)
|
||||
else:
|
||||
actual_data = _get(conf_path)
|
||||
if actual_data is NOTSET:
|
||||
for item, data, in six.iteritems(create_kwargs):
|
||||
if item not in VALID_CREATE_OPTS:
|
||||
log.error(
|
||||
'Trying to compare \'{0}\', but it is not a valid '
|
||||
'parameter. Skipping.'.format(item)
|
||||
)
|
||||
continue
|
||||
log.trace('dockerng.running: comparing ' + item)
|
||||
conf_path = VALID_CREATE_OPTS[item]['path']
|
||||
if isinstance(conf_path, tuple):
|
||||
actual_data = [_get(x) for x in conf_path]
|
||||
for val in actual_data:
|
||||
if val is NOTSET:
|
||||
_api_mismatch(item)
|
||||
log.trace('dockerng.running ({0}): desired value: {1}'
|
||||
.format(item, data))
|
||||
log.trace('dockerng.running ({0}): actual value: {1}'
|
||||
.format(item, actual_data))
|
||||
else:
|
||||
actual_data = _get(conf_path)
|
||||
if actual_data is NOTSET:
|
||||
_api_mismatch(item)
|
||||
log.trace('dockerng.running ({0}): desired value: {1}'
|
||||
.format(item, data))
|
||||
log.trace('dockerng.running ({0}): actual value: {1}'
|
||||
.format(item, actual_data))
|
||||
|
||||
if actual_data is None and data is not None \
|
||||
or actual_data is not None and data is None:
|
||||
ret.update({item: {'old': actual_data, 'new': data}})
|
||||
continue
|
||||
if actual_data is None and data is not None \
|
||||
or actual_data is not None and data is None:
|
||||
ret.update({item: {'old': actual_data, 'new': data}})
|
||||
continue
|
||||
|
||||
# 'create' comparison params
|
||||
if item == 'detach':
|
||||
# Something unique here. Two fields to check, if both are False
|
||||
# then detach is True
|
||||
actual_detach = all(x is False for x in actual_data)
|
||||
log.trace('dockerng.running ({0}): munged actual value: {1}'
|
||||
.format(item, actual_detach))
|
||||
if actual_detach != data:
|
||||
ret.update({item: {'old': actual_detach, 'new': data}})
|
||||
continue
|
||||
# 'create' comparison params
|
||||
if item == 'detach':
|
||||
# Something unique here. Two fields to check, if both are False
|
||||
# then detach is True
|
||||
actual_detach = all(x is False for x in actual_data)
|
||||
log.trace('dockerng.running ({0}): munged actual value: {1}'
|
||||
.format(item, actual_detach))
|
||||
if actual_detach != data:
|
||||
ret.update({item: {'old': actual_detach, 'new': data}})
|
||||
continue
|
||||
|
||||
elif item == 'environment':
|
||||
actual_env = {}
|
||||
for env_var in actual_data:
|
||||
try:
|
||||
key, val = env_var.split('=', 1)
|
||||
except (AttributeError, ValueError):
|
||||
log.warning(
|
||||
'Unexpected environment variable in inspect '
|
||||
'output {0}'.format(env_var)
|
||||
)
|
||||
continue
|
||||
else:
|
||||
actual_env[key] = val
|
||||
log.trace('dockerng.running ({0}): munged actual value: {1}'
|
||||
.format(item, actual_env))
|
||||
env_diff = {}
|
||||
for key in data:
|
||||
actual_val = actual_env.get(key)
|
||||
if data[key] != actual_val:
|
||||
env_ptr = env_diff.setdefault(item, {})
|
||||
env_ptr.setdefault('old', {})[key] = actual_val
|
||||
env_ptr.setdefault('new', {})[key] = data[key]
|
||||
if env_diff:
|
||||
ret.update(env_diff)
|
||||
continue
|
||||
|
||||
elif item == 'ports':
|
||||
# Munge the desired configuration instead of the actual
|
||||
# configuration here, because the desired configuration is a
|
||||
# list of ints or tuples, and that won't look as good in the
|
||||
# nested outputter as a simple comparison of lists of
|
||||
# port/protocol pairs (as found in the "actual" dict).
|
||||
actual_ports = sorted(actual_data)
|
||||
desired_ports = []
|
||||
for port_def in data:
|
||||
if isinstance(port_def, tuple):
|
||||
desired_ports.append('{0}/{1}'.format(*port_def))
|
||||
else:
|
||||
desired_ports.append('{0}/tcp'.format(port_def))
|
||||
desired_ports.sort()
|
||||
log.trace('dockerng.running ({0}): munged actual value: {1}'
|
||||
.format(item, actual_ports))
|
||||
log.trace('dockerng.running ({0}): munged desired value: {1}'
|
||||
.format(item, desired_ports))
|
||||
if actual_ports != desired_ports:
|
||||
ret.update({item: {'old': actual_ports,
|
||||
'new': desired_ports}})
|
||||
continue
|
||||
|
||||
# 'runtime' comparison params
|
||||
elif item == 'binds':
|
||||
actual_binds = []
|
||||
for bind in actual_data:
|
||||
bind_parts = bind.split(':')
|
||||
if len(bind_parts) == 2:
|
||||
actual_binds.append(bind + ':rw')
|
||||
else:
|
||||
actual_binds.append(bind)
|
||||
desired_binds = []
|
||||
for host_path, bind_data in six.iteritems(data):
|
||||
desired_binds.append(
|
||||
'{0}:{1}:{2}'.format(
|
||||
host_path,
|
||||
bind_data['bind'],
|
||||
'ro' if bind_data['ro'] else 'rw'
|
||||
)
|
||||
elif item == 'environment':
|
||||
actual_env = {}
|
||||
for env_var in actual_data:
|
||||
try:
|
||||
key, val = env_var.split('=', 1)
|
||||
except (AttributeError, ValueError):
|
||||
log.warning(
|
||||
'Unexpected environment variable in inspect '
|
||||
'output {0}'.format(env_var)
|
||||
)
|
||||
actual_binds.sort()
|
||||
desired_binds.sort()
|
||||
if actual_binds != desired_binds:
|
||||
ret.update({item: {'old': actual_binds,
|
||||
'new': desired_binds}})
|
||||
continue
|
||||
else:
|
||||
actual_env[key] = val
|
||||
log.trace('dockerng.running ({0}): munged actual value: {1}'
|
||||
.format(item, actual_env))
|
||||
env_diff = {}
|
||||
for key in data:
|
||||
actual_val = actual_env.get(key)
|
||||
if data[key] != actual_val:
|
||||
env_ptr = env_diff.setdefault(item, {})
|
||||
env_ptr.setdefault('old', {})[key] = actual_val
|
||||
env_ptr.setdefault('new', {})[key] = data[key]
|
||||
if env_diff:
|
||||
ret.update(env_diff)
|
||||
continue
|
||||
|
||||
elif item == 'port_bindings':
|
||||
actual_binds = []
|
||||
for container_port, bind_list in six.iteritems(actual_data):
|
||||
elif item == 'ports':
|
||||
# Munge the desired configuration instead of the actual
|
||||
# configuration here, because the desired configuration is a
|
||||
# list of ints or tuples, and that won't look as good in the
|
||||
# nested outputter as a simple comparison of lists of
|
||||
# port/protocol pairs (as found in the "actual" dict).
|
||||
actual_ports = sorted(actual_data)
|
||||
desired_ports = []
|
||||
for port_def in data:
|
||||
if isinstance(port_def, tuple):
|
||||
desired_ports.append('{0}/{1}'.format(*port_def))
|
||||
else:
|
||||
desired_ports.append('{0}/tcp'.format(port_def))
|
||||
desired_ports.sort()
|
||||
log.trace('dockerng.running ({0}): munged actual value: {1}'
|
||||
.format(item, actual_ports))
|
||||
log.trace('dockerng.running ({0}): munged desired value: {1}'
|
||||
.format(item, desired_ports))
|
||||
if actual_ports != desired_ports:
|
||||
ret.update({item: {'old': actual_ports,
|
||||
'new': desired_ports}})
|
||||
continue
|
||||
|
||||
elif item == 'binds':
|
||||
actual_binds = []
|
||||
for bind in actual_data:
|
||||
bind_parts = bind.split(':')
|
||||
if len(bind_parts) == 2:
|
||||
actual_binds.append(bind + ':rw')
|
||||
else:
|
||||
actual_binds.append(bind)
|
||||
desired_binds = []
|
||||
for host_path, bind_data in six.iteritems(data):
|
||||
desired_binds.append(
|
||||
'{0}:{1}:{2}'.format(
|
||||
host_path,
|
||||
bind_data['bind'],
|
||||
'ro' if bind_data['ro'] else 'rw'
|
||||
)
|
||||
)
|
||||
actual_binds.sort()
|
||||
desired_binds.sort()
|
||||
if actual_binds != desired_binds:
|
||||
ret.update({item: {'old': actual_binds,
|
||||
'new': desired_binds}})
|
||||
continue
|
||||
|
||||
elif item == 'port_bindings':
|
||||
actual_binds = []
|
||||
for container_port, bind_list in six.iteritems(actual_data):
|
||||
if container_port.endswith('/tcp'):
|
||||
container_port = container_port[:-4]
|
||||
for bind_data in bind_list:
|
||||
# Port range will have to be updated for future Docker
|
||||
# versions (see
|
||||
# https://github.com/docker/docker/issues/10220). Note
|
||||
# that Docker 1.5.0 (released a few weeks after the fix
|
||||
# was merged) does not appear to have this fix in it,
|
||||
# so we're probably looking at 1.6.0 for this fix.
|
||||
if bind_data['HostPort'] == '' or \
|
||||
49153 <= int(bind_data['HostPort']) <= 65535:
|
||||
host_port = ''
|
||||
else:
|
||||
host_port = bind_data['HostPort']
|
||||
if bind_data['HostIp'] in ('0.0.0.0', ''):
|
||||
if host_port:
|
||||
bind_def = (host_port, container_port)
|
||||
else:
|
||||
bind_def = (container_port,)
|
||||
else:
|
||||
bind_def = (bind_data['HostIp'],
|
||||
host_port,
|
||||
container_port)
|
||||
actual_binds.append(':'.join(bind_def))
|
||||
|
||||
desired_binds = []
|
||||
for container_port, bind_list in six.iteritems(data):
|
||||
try:
|
||||
if container_port.endswith('/tcp'):
|
||||
container_port = container_port[:-4]
|
||||
for bind_data in bind_list:
|
||||
# Port range will have to be updated for future Docker
|
||||
# versions (see
|
||||
# https://github.com/docker/docker/issues/10220). Note
|
||||
# that Docker 1.5.0 (released a few weeks after the fix
|
||||
# was merged) does not appear to have this fix in it,
|
||||
# so we're probably looking at 1.6.0 for this fix.
|
||||
if bind_data['HostPort'] == '' or \
|
||||
49153 <= int(bind_data['HostPort']) <= 65535:
|
||||
except AttributeError:
|
||||
# The port's protocol was not specified, so it is
|
||||
# assumed to be TCP. Thus, according to docker-py usage
|
||||
# examples, the port was passed as an int. Convert it
|
||||
# to a string here.
|
||||
container_port = str(container_port)
|
||||
for bind_data in bind_list:
|
||||
if isinstance(bind_data, tuple):
|
||||
try:
|
||||
host_ip, host_port = bind_data
|
||||
host_port = str(host_port)
|
||||
except ValueError:
|
||||
host_ip = bind_data[0]
|
||||
host_port = ''
|
||||
else:
|
||||
host_port = bind_data['HostPort']
|
||||
if bind_data['HostIp'] in ('0.0.0.0', ''):
|
||||
if host_port:
|
||||
bind_def = (host_port, container_port)
|
||||
else:
|
||||
bind_def = (container_port,)
|
||||
else:
|
||||
bind_def = (bind_data['HostIp'],
|
||||
host_port,
|
||||
container_port)
|
||||
actual_binds.append(':'.join(bind_def))
|
||||
|
||||
desired_binds = []
|
||||
for container_port, bind_list in six.iteritems(data):
|
||||
try:
|
||||
if container_port.endswith('/tcp'):
|
||||
container_port = container_port[:-4]
|
||||
except AttributeError:
|
||||
# The port's protocol was not specified, so it is
|
||||
# assumed to be TCP. Thus, according to docker-py usage
|
||||
# examples, the port was passed as an int. Convert it
|
||||
# to a string here.
|
||||
container_port = str(container_port)
|
||||
for bind_data in bind_list:
|
||||
if isinstance(bind_data, tuple):
|
||||
try:
|
||||
host_ip, host_port = bind_data
|
||||
host_port = str(host_port)
|
||||
except ValueError:
|
||||
host_ip = bind_data[0]
|
||||
host_port = ''
|
||||
bind_def = '{0}:{1}:{2}'.format(
|
||||
host_ip, host_port, container_port
|
||||
bind_def = '{0}:{1}:{2}'.format(
|
||||
host_ip, host_port, container_port
|
||||
)
|
||||
else:
|
||||
if bind_data is not None:
|
||||
bind_def = '{0}:{1}'.format(
|
||||
bind_data, container_port
|
||||
)
|
||||
else:
|
||||
if bind_data is not None:
|
||||
bind_def = '{0}:{1}'.format(
|
||||
bind_data, container_port
|
||||
)
|
||||
else:
|
||||
bind_def = container_port
|
||||
desired_binds.append(bind_def)
|
||||
actual_binds.sort()
|
||||
desired_binds.sort()
|
||||
log.trace('dockerng.running ({0}): munged actual value: {1}'
|
||||
.format(item, actual_binds))
|
||||
log.trace('dockerng.running ({0}): munged desired value: {1}'
|
||||
.format(item, desired_binds))
|
||||
if actual_binds != desired_binds:
|
||||
ret.update({item: {'old': actual_binds,
|
||||
'new': desired_binds}})
|
||||
continue
|
||||
|
||||
elif item == 'links':
|
||||
actual_links = []
|
||||
for link in actual_data:
|
||||
try:
|
||||
link_name, alias_info = link.split(':')
|
||||
except ValueError:
|
||||
log.error(
|
||||
'Failed to compare link {0}, unrecognized format'
|
||||
.format(link)
|
||||
)
|
||||
continue
|
||||
container_name, _, link_alias = alias_info.rpartition('/')
|
||||
if not container_name:
|
||||
log.error(
|
||||
'Failed to interpret link alias from {0}, '
|
||||
'unrecognized format'.format(alias_info)
|
||||
)
|
||||
continue
|
||||
actual_links.append((link_name, link_alias))
|
||||
actual_links.sort()
|
||||
desired_links = sorted(data)
|
||||
if actual_links != desired_links:
|
||||
ret.update({item: {'old': actual_links,
|
||||
'new': desired_links}})
|
||||
continue
|
||||
|
||||
elif item == 'extra_hosts':
|
||||
actual_hosts = sorted(actual_data)
|
||||
desired_hosts = sorted(
|
||||
['{0}:{1}'.format(x, y) for x, y in six.iteritems(data)]
|
||||
)
|
||||
if actual_hosts != desired_hosts:
|
||||
ret.update({item: {'old': actual_hosts,
|
||||
'new': desired_hosts}})
|
||||
continue
|
||||
|
||||
elif isinstance(data, list):
|
||||
# Compare two sorted lists of items. Won't work for "command"
|
||||
# or "entrypoint" because those are both shell commands and the
|
||||
# original order matters. It will, however, work for "volumes"
|
||||
# because even though "volumes" is a sub-dict nested within the
|
||||
# "actual" dict sorted(somedict) still just gives you a sorted
|
||||
# list of the dictionary's keys. And we don't care about the
|
||||
# value for "volumes", just its keys.
|
||||
actual_data = sorted(actual_data)
|
||||
desired_data = sorted(data)
|
||||
log.trace('dockerng.running ({0}): munged actual value: {1}'
|
||||
.format(item, actual_data))
|
||||
log.trace('dockerng.running ({0}): munged desired value: {1}'
|
||||
.format(item, desired_data))
|
||||
if actual_data != desired_data:
|
||||
ret.update({item: {'old': actual_data,
|
||||
'new': desired_data}})
|
||||
bind_def = container_port
|
||||
desired_binds.append(bind_def)
|
||||
actual_binds.sort()
|
||||
desired_binds.sort()
|
||||
log.trace('dockerng.running ({0}): munged actual value: {1}'
|
||||
.format(item, actual_binds))
|
||||
log.trace('dockerng.running ({0}): munged desired value: {1}'
|
||||
.format(item, desired_binds))
|
||||
if actual_binds != desired_binds:
|
||||
ret.update({item: {'old': actual_binds,
|
||||
'new': desired_binds}})
|
||||
continue
|
||||
|
||||
else:
|
||||
# Generic comparison, works on strings, numeric types, and
|
||||
# booleans
|
||||
if actual_data != data:
|
||||
ret.update({item: {'old': actual_data, 'new': data}})
|
||||
elif item == 'links':
|
||||
actual_links = []
|
||||
for link in actual_data:
|
||||
try:
|
||||
link_name, alias_info = link.split(':')
|
||||
except ValueError:
|
||||
log.error(
|
||||
'Failed to compare link {0}, unrecognized format'
|
||||
.format(link)
|
||||
)
|
||||
continue
|
||||
container_name, _, link_alias = alias_info.rpartition('/')
|
||||
if not container_name:
|
||||
log.error(
|
||||
'Failed to interpret link alias from {0}, '
|
||||
'unrecognized format'.format(alias_info)
|
||||
)
|
||||
continue
|
||||
actual_links.append((link_name, link_alias))
|
||||
actual_links.sort()
|
||||
desired_links = sorted(data)
|
||||
if actual_links != desired_links:
|
||||
ret.update({item: {'old': actual_links,
|
||||
'new': desired_links}})
|
||||
continue
|
||||
|
||||
elif item == 'extra_hosts':
|
||||
actual_hosts = sorted(actual_data)
|
||||
desired_hosts = sorted(
|
||||
['{0}:{1}'.format(x, y) for x, y in six.iteritems(data)]
|
||||
)
|
||||
if actual_hosts != desired_hosts:
|
||||
ret.update({item: {'old': actual_hosts,
|
||||
'new': desired_hosts}})
|
||||
continue
|
||||
|
||||
elif isinstance(data, list):
|
||||
# Compare two sorted lists of items. Won't work for "command"
|
||||
# or "entrypoint" because those are both shell commands and the
|
||||
# original order matters. It will, however, work for "volumes"
|
||||
# because even though "volumes" is a sub-dict nested within the
|
||||
# "actual" dict sorted(somedict) still just gives you a sorted
|
||||
# list of the dictionary's keys. And we don't care about the
|
||||
# value for "volumes", just its keys.
|
||||
actual_data = sorted(actual_data)
|
||||
desired_data = sorted(data)
|
||||
log.trace('dockerng.running ({0}): munged actual value: {1}'
|
||||
.format(item, actual_data))
|
||||
log.trace('dockerng.running ({0}): munged desired value: {1}'
|
||||
.format(item, desired_data))
|
||||
if actual_data != desired_data:
|
||||
ret.update({item: {'old': actual_data,
|
||||
'new': desired_data}})
|
||||
continue
|
||||
|
||||
else:
|
||||
# Generic comparison, works on strings, numeric types, and
|
||||
# booleans
|
||||
if actual_data != data:
|
||||
ret.update({item: {'old': actual_data, 'new': data}})
|
||||
return ret
|
||||
|
||||
|
||||
|
@ -1450,19 +1446,10 @@ def running(name,
|
|||
|
||||
# Strip __pub kwargs and divide the remaining arguments into the ones for
|
||||
# container creation and the ones for starting containers.
|
||||
invalid_kwargs = []
|
||||
create_kwargs = {}
|
||||
runtime_kwargs = {}
|
||||
kwargs_copy = salt.utils.clean_kwargs(**copy.deepcopy(kwargs))
|
||||
send_signal = kwargs_copy.pop('send_signal', False)
|
||||
create_kwargs = salt.utils.clean_kwargs(**copy.deepcopy(kwargs))
|
||||
send_signal = create_kwargs.pop('send_signal', False)
|
||||
|
||||
for key, val in six.iteritems(kwargs_copy):
|
||||
if key in VALID_CREATE_OPTS:
|
||||
create_kwargs[key] = val
|
||||
elif key in VALID_RUNTIME_OPTS:
|
||||
runtime_kwargs[key] = val
|
||||
else:
|
||||
invalid_kwargs.append(key)
|
||||
invalid_kwargs = set(create_kwargs.keys()).difference(set(VALID_CREATE_OPTS.keys()))
|
||||
if invalid_kwargs:
|
||||
ret['comment'] = (
|
||||
'The following arguments are invalid: {0}'
|
||||
|
@ -1473,18 +1460,14 @@ def running(name,
|
|||
# Input validation
|
||||
try:
|
||||
# Repack any dictlists that need it
|
||||
_prep_input(runtime_kwargs)
|
||||
_prep_input(create_kwargs)
|
||||
# Perform data type validation and, where necessary, munge
|
||||
# the data further so it is in a format that can be passed
|
||||
# to dockerng.start.
|
||||
_validate_input('runtime',
|
||||
runtime_kwargs,
|
||||
# to dockerng.create.
|
||||
_validate_input(create_kwargs,
|
||||
validate_ip_addrs=validate_ip_addrs)
|
||||
|
||||
# Add any needed container creation arguments based on the validated
|
||||
# runtime arguments.
|
||||
if runtime_kwargs.get('binds') is not None:
|
||||
if create_kwargs.get('binds') is not None:
|
||||
if 'volumes' not in create_kwargs:
|
||||
# Check if there are preconfigured volumes in the image
|
||||
for step in __salt__['dockerng.history'](image, quiet=True):
|
||||
|
@ -1495,9 +1478,9 @@ def running(name,
|
|||
# the ones from the "binds" configuration.
|
||||
create_kwargs['volumes'] = [
|
||||
x['bind']
|
||||
for x in six.itervalues(runtime_kwargs['binds'])
|
||||
for x in six.itervalues(create_kwargs['binds'])
|
||||
]
|
||||
if runtime_kwargs.get('port_bindings') is not None:
|
||||
if create_kwargs.get('port_bindings') is not None:
|
||||
if 'ports' not in create_kwargs:
|
||||
# Check if there are preconfigured ports in the image
|
||||
for step in __salt__['dockerng.history'](image, quiet=True):
|
||||
|
@ -1507,14 +1490,8 @@ def running(name,
|
|||
# No preconfigured ports, we need to make our own. Use
|
||||
# the ones from the "port_bindings" configuration.
|
||||
create_kwargs['ports'] = list(
|
||||
runtime_kwargs['port_bindings'])
|
||||
create_kwargs['port_bindings'])
|
||||
|
||||
# Perform data type validation and, where necessary, munge
|
||||
# the data further so it is in a format that can be passed
|
||||
# to dockerng.create.
|
||||
_validate_input('create',
|
||||
create_kwargs,
|
||||
validate_ip_addrs=validate_ip_addrs)
|
||||
except SaltInvocationError as exc:
|
||||
ret['comment'] = '{0}'.format(exc)
|
||||
return ret
|
||||
|
@ -1540,9 +1517,7 @@ def running(name,
|
|||
# Container is the correct image, let's check the container
|
||||
# config and see if we need to replace the container
|
||||
try:
|
||||
changes_needed = _compare(pre_config,
|
||||
create_kwargs,
|
||||
runtime_kwargs)
|
||||
changes_needed = _compare(pre_config, create_kwargs)
|
||||
if changes_needed:
|
||||
log.debug(
|
||||
'dockerng.running: Analysis of container \'{0}\' '
|
||||
|
@ -1634,6 +1609,7 @@ def running(name,
|
|||
create_result = __salt__['dockerng.create'](
|
||||
image,
|
||||
name=name,
|
||||
validate_ip_addrs=False,
|
||||
# Already validated input
|
||||
validate_input=False,
|
||||
client_timeout=client_timeout,
|
||||
|
@ -1653,10 +1629,6 @@ def running(name,
|
|||
# Start container
|
||||
__salt__['dockerng.start'](
|
||||
name,
|
||||
# Already validated input earlier, no need to repeat it
|
||||
validate_ip_addrs=False,
|
||||
validate_input=False,
|
||||
**runtime_kwargs
|
||||
)
|
||||
except Exception as exc:
|
||||
comments.append(
|
||||
|
@ -1678,9 +1650,7 @@ def running(name,
|
|||
if changes_needed:
|
||||
try:
|
||||
post_config = __salt__['dockerng.inspect_container'](name)
|
||||
changes_still_needed = _compare(post_config,
|
||||
create_kwargs,
|
||||
runtime_kwargs)
|
||||
changes_still_needed = _compare(post_config, create_kwargs)
|
||||
if changes_still_needed:
|
||||
log.debug(
|
||||
'dockerng.running: Analysis of container \'{0}\' after '
|
||||
|
|
|
@ -66,13 +66,11 @@ class DockerngTestCase(TestCase):
|
|||
'image:latest',
|
||||
validate_input=False,
|
||||
name='cont',
|
||||
volumes=['/container-0'],
|
||||
client_timeout=60)
|
||||
dockerng_start.assert_called_with(
|
||||
'cont',
|
||||
binds={'/host-0': {'bind': '/container-0', 'ro': True}},
|
||||
volumes=['/container-0'],
|
||||
validate_ip_addrs=False,
|
||||
validate_input=False)
|
||||
client_timeout=60)
|
||||
dockerng_start.assert_called_with('cont')
|
||||
|
||||
def test_running_with_predifined_volume(self):
|
||||
'''
|
||||
|
@ -103,13 +101,11 @@ class DockerngTestCase(TestCase):
|
|||
dockerng_create.assert_called_with(
|
||||
'image:latest',
|
||||
validate_input=False,
|
||||
name='cont',
|
||||
client_timeout=60)
|
||||
dockerng_start.assert_called_with(
|
||||
'cont',
|
||||
binds={'/host-0': {'bind': '/container-0', 'ro': True}},
|
||||
validate_ip_addrs=False,
|
||||
validate_input=False)
|
||||
name='cont',
|
||||
client_timeout=60)
|
||||
dockerng_start.assert_called_with('cont')
|
||||
|
||||
def test_running_with_no_predifined_ports(self):
|
||||
'''
|
||||
|
@ -142,12 +138,10 @@ class DockerngTestCase(TestCase):
|
|||
validate_input=False,
|
||||
name='cont',
|
||||
ports=[9797],
|
||||
client_timeout=60)
|
||||
dockerng_start.assert_called_with(
|
||||
'cont',
|
||||
port_bindings={9797: [9090]},
|
||||
validate_ip_addrs=False,
|
||||
validate_input=False)
|
||||
client_timeout=60)
|
||||
dockerng_start.assert_called_with('cont')
|
||||
|
||||
def test_running_with_predifined_ports(self):
|
||||
'''
|
||||
|
@ -179,12 +173,10 @@ class DockerngTestCase(TestCase):
|
|||
'image:latest',
|
||||
validate_input=False,
|
||||
name='cont',
|
||||
client_timeout=60)
|
||||
dockerng_start.assert_called_with(
|
||||
'cont',
|
||||
port_bindings={9797: [9090]},
|
||||
validate_ip_addrs=False,
|
||||
validate_input=False)
|
||||
client_timeout=60)
|
||||
dockerng_start.assert_called_with('cont')
|
||||
|
||||
def test_running_compare_images_by_id(self):
|
||||
'''
|
||||
|
|
Loading…
Add table
Reference in a new issue