Skip to content

Commit

Permalink
Merge branch 'main' into py3.12-compat
Browse files Browse the repository at this point in the history
  • Loading branch information
milas authored Nov 20, 2023
2 parents f04e77a + 4a88112 commit 1b735ef
Show file tree
Hide file tree
Showing 3 changed files with 374 additions and 130 deletions.
39 changes: 25 additions & 14 deletions docker/models/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
import ntpath
from collections import namedtuple

from .images import Image
from .resource import Collection, Model
from ..api import APIClient
from ..constants import DEFAULT_DATA_CHUNK_SIZE
from ..errors import (
ContainerError, DockerException, ImageNotFound,
NotFound, create_unexpected_kwargs_error
)
from ..types import HostConfig
from ..types import HostConfig, NetworkingConfig
from ..utils import version_gte
from .images import Image
from .resource import Collection, Model


class Container(Model):
Expand All @@ -21,6 +21,7 @@ class Container(Model):
query the Docker daemon for the current properties, causing
:py:attr:`attrs` to be refreshed.
"""

@property
def name(self):
"""
Expand Down Expand Up @@ -681,10 +682,14 @@ def run(self, image, command=None, stdout=True, stderr=False,
This mode is incompatible with ``ports``.
Incompatible with ``network``.
network_driver_opt (dict): A dictionary of options to provide
to the network driver. Defaults to ``None``. Used in
conjuction with ``network``. Incompatible
with ``network_mode``.
networking_config (Dict[str, EndpointConfig]):
Dictionary of EndpointConfig objects for each container network.
The key is the name of the network.
Defaults to ``None``.
Used in conjuction with ``network``.
Incompatible with ``network_mode``.
oom_kill_disable (bool): Whether to disable OOM killer.
oom_score_adj (int): An integer value containing the score given
to the container in order to tune OOM killer preferences.
Expand Down Expand Up @@ -849,9 +854,9 @@ def run(self, image, command=None, stdout=True, stderr=False,
'together.'
)

if kwargs.get('network_driver_opt') and not kwargs.get('network'):
if kwargs.get('networking_config') and not kwargs.get('network'):
raise RuntimeError(
'The options "network_driver_opt" can not be used '
'The option "networking_config" can not be used '
'without "network".'
)

Expand Down Expand Up @@ -1007,6 +1012,7 @@ def list(self, all=False, before=None, filters=None, limit=-1, since=None,

def prune(self, filters=None):
return self.client.api.prune_containers(filters=filters)

prune.__doc__ = APIClient.prune_containers.__doc__


Expand Down Expand Up @@ -1125,12 +1131,17 @@ def _create_container_args(kwargs):
host_config_kwargs['binds'] = volumes

network = kwargs.pop('network', None)
network_driver_opt = kwargs.pop('network_driver_opt', None)
networking_config = kwargs.pop('networking_config', None)
if network:
network_configuration = {'driver_opt': network_driver_opt} \
if network_driver_opt else None

create_kwargs['networking_config'] = {network: network_configuration}
if networking_config:
# Sanity check: check if the network is defined in the
# networking config dict, otherwise switch to None
if network not in networking_config:
networking_config = None

create_kwargs['networking_config'] = NetworkingConfig(
networking_config
) if networking_config else {network: None}
host_config_kwargs['network_mode'] = network

# All kwargs should have been consumed by this point, so raise
Expand Down
96 changes: 93 additions & 3 deletions tests/integration/models_containers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import pytest

import docker
from ..helpers import random_name
from ..helpers import requires_api_version
from .base import BaseIntegrationTest
from .base import TEST_API_VERSION
from ..helpers import random_name
from ..helpers import requires_api_version


class ContainerCollectionTest(BaseIntegrationTest):
Expand Down Expand Up @@ -104,6 +104,96 @@ def test_run_with_network(self):
assert 'Networks' in attrs['NetworkSettings']
assert list(attrs['NetworkSettings']['Networks'].keys()) == [net_name]

def test_run_with_networking_config(self):
net_name = random_name()
client = docker.from_env(version=TEST_API_VERSION)
client.networks.create(net_name)
self.tmp_networks.append(net_name)

test_aliases = ['hello']
test_driver_opt = {'key1': 'a'}

networking_config = {
net_name: client.api.create_endpoint_config(
aliases=test_aliases,
driver_opt=test_driver_opt
)
}

container = client.containers.run(
'alpine', 'echo hello world', network=net_name,
networking_config=networking_config,
detach=True
)
self.tmp_containers.append(container.id)

attrs = container.attrs

assert 'NetworkSettings' in attrs
assert 'Networks' in attrs['NetworkSettings']
assert list(attrs['NetworkSettings']['Networks'].keys()) == [net_name]
assert attrs['NetworkSettings']['Networks'][net_name]['Aliases'] == \
test_aliases
assert attrs['NetworkSettings']['Networks'][net_name]['DriverOpts'] \
== test_driver_opt

def test_run_with_networking_config_with_undeclared_network(self):
net_name = random_name()
client = docker.from_env(version=TEST_API_VERSION)
client.networks.create(net_name)
self.tmp_networks.append(net_name)

test_aliases = ['hello']
test_driver_opt = {'key1': 'a'}

networking_config = {
net_name: client.api.create_endpoint_config(
aliases=test_aliases,
driver_opt=test_driver_opt
),
'bar': client.api.create_endpoint_config(
aliases=['test'],
driver_opt={'key2': 'b'}
),
}

with pytest.raises(docker.errors.APIError) as e:
container = client.containers.run(
'alpine', 'echo hello world', network=net_name,
networking_config=networking_config,
detach=True
)
self.tmp_containers.append(container.id)

def test_run_with_networking_config_only_undeclared_network(self):
net_name = random_name()
client = docker.from_env(version=TEST_API_VERSION)
client.networks.create(net_name)
self.tmp_networks.append(net_name)

networking_config = {
'bar': client.api.create_endpoint_config(
aliases=['hello'],
driver_opt={'key1': 'a'}
),
}

container = client.containers.run(
'alpine', 'echo hello world', network=net_name,
networking_config=networking_config,
detach=True
)
self.tmp_containers.append(container.id)

attrs = container.attrs

assert 'NetworkSettings' in attrs
assert 'Networks' in attrs['NetworkSettings']
assert list(attrs['NetworkSettings']['Networks'].keys()) == [net_name]
assert attrs['NetworkSettings']['Networks'][net_name]['Aliases'] is None
assert (attrs['NetworkSettings']['Networks'][net_name]['DriverOpts']
is None)

def test_run_with_none_driver(self):
client = docker.from_env(version=TEST_API_VERSION)

Expand Down Expand Up @@ -187,7 +277,7 @@ def test_get(self):
container = client.containers.run("alpine", "sleep 300", detach=True)
self.tmp_containers.append(container.id)
assert client.containers.get(container.id).attrs[
'Config']['Image'] == "alpine"
'Config']['Image'] == "alpine"

def test_list(self):
client = docker.from_env(version=TEST_API_VERSION)
Expand Down
Loading

0 comments on commit 1b735ef

Please sign in to comment.