diff --git a/docker/models/containers.py b/docker/models/containers.py index 61d048c4f..c718bbeac 100644 --- a/docker/models/containers.py +++ b/docker/models/containers.py @@ -679,6 +679,10 @@ 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``. 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. @@ -843,6 +847,12 @@ def run(self, image, command=None, stdout=True, stderr=False, 'together.' ) + if kwargs.get('network_driver_opt') and not kwargs.get('network'): + raise RuntimeError( + 'The options "network_driver_opt" can not be used ' + 'without "network".' + ) + try: container = self.create(image=image, command=command, detach=detach, **kwargs) @@ -1113,8 +1123,12 @@ def _create_container_args(kwargs): host_config_kwargs['binds'] = volumes network = kwargs.pop('network', None) + network_driver_opt = kwargs.pop('network_driver_opt', None) if network: - create_kwargs['networking_config'] = {network: None} + network_configuration = {'driver_opt': network_driver_opt} \ + if network_driver_opt else None + + create_kwargs['networking_config'] = {network: network_configuration} host_config_kwargs['network_mode'] = network # All kwargs should have been consumed by this point, so raise diff --git a/tests/unit/models_containers_test.py b/tests/unit/models_containers_test.py index 51f001802..0592af5e0 100644 --- a/tests/unit/models_containers_test.py +++ b/tests/unit/models_containers_test.py @@ -74,6 +74,7 @@ def test_create_container_args(self): name='somename', network_disabled=False, network='foo', + network_driver_opt={'key1': 'a'}, oom_kill_disable=True, oom_score_adj=5, pid_mode='host', @@ -188,7 +189,7 @@ def test_create_container_args(self): mac_address='abc123', name='somename', network_disabled=False, - networking_config={'foo': None}, + networking_config={'foo': {'driver_opt': {'key1': 'a'}}}, platform='linux', ports=[('1111', 'tcp'), ('2222', 'tcp')], stdin_open=True, @@ -345,6 +346,42 @@ def test_run_platform(self): host_config={'NetworkMode': 'default'}, ) + def test_run_network_driver_opts_without_network(self): + client = make_fake_client() + + with pytest.raises(RuntimeError): + client.containers.run( + image='alpine', + network_driver_opt={'key1': 'a'} + ) + + def test_run_network_driver_opts_with_network_mode(self): + client = make_fake_client() + + with pytest.raises(RuntimeError): + client.containers.run( + image='alpine', + network_mode='none', + network_driver_opt={'key1': 'a'} + ) + + def test_run_network_driver_opts(self): + client = make_fake_client() + + client.containers.run( + image='alpine', + network='foo', + network_driver_opt={'key1': 'a'} + ) + + client.api.create_container.assert_called_with( + detach=False, + image='alpine', + command=None, + networking_config={'foo': {'driver_opt': {'key1': 'a'}}}, + host_config={'NetworkMode': 'foo'} + ) + def test_create(self): client = make_fake_client() container = client.containers.create( @@ -372,6 +409,51 @@ def test_create_with_image_object(self): host_config={'NetworkMode': 'default'} ) + def test_create_network_driver_opts_without_network(self): + client = make_fake_client() + + client.containers.create( + image='alpine', + network_driver_opt={'key1': 'a'} + ) + + client.api.create_container.assert_called_with( + image='alpine', + command=None, + host_config={'NetworkMode': 'default'} + ) + + def test_create_network_driver_opts_with_network_mode(self): + client = make_fake_client() + + client.containers.create( + image='alpine', + network_mode='none', + network_driver_opt={'key1': 'a'} + ) + + client.api.create_container.assert_called_with( + image='alpine', + command=None, + host_config={'NetworkMode': 'none'} + ) + + def test_create_network_driver_opts(self): + client = make_fake_client() + + client.containers.create( + image='alpine', + network='foo', + network_driver_opt={'key1': 'a'} + ) + + client.api.create_container.assert_called_with( + image='alpine', + command=None, + networking_config={'foo': {'driver_opt': {'key1': 'a'}}}, + host_config={'NetworkMode': 'foo'} + ) + def test_get(self): client = make_fake_client() container = client.containers.get(FAKE_CONTAINER_ID)