Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docker_container: pass networks to Daemon on container creation #933

Merged
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
12 changes: 12 additions & 0 deletions changelogs/fragments/933-docker_container-networks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
minor_changes:
- "docker_container - when creating a container, directly pass all networks to connect to to the Docker Daemon
for API version 1.44 and newer. This makes creation more efficient and works around a bug in Docker Daemon that
does not use the specified MAC address in at least some cases, though only for creation
(https://github.com/ansible-collections/community.docker/pull/933)."
bugfixes:
- "docker_container - restore behavior of the module from community.docker 2.x.y that passes the first network
to the Docker Deamon while creating the container (https://github.com/ansible-collections/community.docker/pull/933)."
known_issues:
- "docker_container - when specifying a MAC address for a container's network, and the network is attached
after container creation (for example, due to idempotency checks), the MAC address is at least in some
cases ignored by the Docker Daemon (https://github.com/ansible-collections/community.docker/pull/933)."
5 changes: 4 additions & 1 deletion plugins/module_utils/module_container/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,11 @@ def disconnect_container_from_network(self, client, container_id, network_id):
def connect_container_to_network(self, client, container_id, network_id, parameters=None):
pass

def create_container_supports_more_than_one_network(self, client):
return False

@abc.abstractmethod
def create_container(self, client, container_name, create_parameters):
def create_container(self, client, container_name, create_parameters, networks=None):
pass

@abc.abstractmethod
Expand Down
22 changes: 19 additions & 3 deletions plugins/module_utils/module_container/docker_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,8 @@ def unpause_container(self, client, container_id):
def disconnect_container_from_network(self, client, container_id, network_id):
client.post_json('/networks/{0}/disconnect', network_id, data={'Container': container_id})

def connect_container_to_network(self, client, container_id, network_id, parameters=None):
parameters = (parameters or {}).copy()
def _create_endpoint_config(self, parameters):
parameters = parameters.copy()
params = {}
for para, dest_para in {
'ipv4_address': 'IPv4Address',
Expand All @@ -268,16 +268,32 @@ def connect_container_to_network(self, client, container_id, network_id, paramet
ipam_config[param] = params.pop(param)
if ipam_config:
params['IPAMConfig'] = ipam_config
return params

def connect_container_to_network(self, client, container_id, network_id, parameters=None):
parameters = (parameters or {}).copy()
params = self._create_endpoint_config(parameters or {})
data = {
'Container': container_id,
'EndpointConfig': params,
}
client.post_json('/networks/{0}/connect', network_id, data=data)

def create_container(self, client, container_name, create_parameters):
def create_container_supports_more_than_one_network(self, client):
return client.docker_api_version >= LooseVersion('1.44')

def create_container(self, client, container_name, create_parameters, networks=None):
params = {'name': container_name}
if 'platform' in create_parameters:
params['platform'] = create_parameters.pop('platform')
if networks is not None:
create_parameters = create_parameters.copy()
create_parameters['NetworkingConfig'] = {
'EndpointsConfig': dict(
(network, self._create_endpoint_config(network_params))
for network, network_params in networks.items()
)
}
new_container = client.post_json_to_json('/containers/create', data=create_parameters, params=params)
client.report_warnings(new_container)
return new_container['Id']
Expand Down
14 changes: 12 additions & 2 deletions plugins/module_utils/module_container/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -766,12 +766,22 @@ def container_create(self, image):
self.log("create container")
self.log("image: %s parameters:" % image)
self.log(create_parameters, pretty_print=True)
self.results['actions'].append(dict(created="Created container", create_parameters=create_parameters))
networks = {}
if self.param_networks_cli_compatible and self.module.params['networks']:
network_list = self.module.params['networks']
if not self.engine_driver.create_container_supports_more_than_one_network(self.client):
network_list = network_list[:1]
for network in network_list:
networks[network['name']] = {
key: value for key, value in network.items()
if key not in ('name', 'id')
}
self.results['actions'].append(dict(created="Created container", create_parameters=create_parameters, networks=networks))
self.results['changed'] = True
new_container = None
if not self.check_mode:
try:
container_id = self.engine_driver.create_container(self.client, self.param_name, create_parameters)
container_id = self.engine_driver.create_container(self.client, self.param_name, create_parameters, networks=networks)
except Exception as exc:
self.fail("Error creating container: %s" % to_native(exc))
return self._get_container(container_id)
Expand Down
3 changes: 3 additions & 0 deletions plugins/modules/docker_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,9 @@
description:
- Endpoint MAC address (for example, V(92:d0:c6:0a:29:33)).
- This is only available for Docker API version 1.44 and later.
- Please note that when a container is attached to a network after creation,
this is currently ignored by the Docker Daemon at least in some cases.
When passed on creation, this seems to work better.
type: str
version_added: 3.6.0
networks_cli_compatible:
Expand Down
Loading