mirror of https://github.com/docker/docker-py.git
				
				
				
			Merge pull request #1083 from docker/1042-ip-networking-config
Support ipv4_address and ipv6_address in create_endpoint_config
This commit is contained in:
		
						commit
						080b4711f2
					
				|  | @ -1,7 +1,7 @@ | ||||||
| import json | import json | ||||||
| 
 | 
 | ||||||
| from ..errors import InvalidVersion | from ..errors import InvalidVersion | ||||||
| from ..utils import check_resource, minimum_version, normalize_links | from ..utils import check_resource, minimum_version | ||||||
| from ..utils import version_lt | from ..utils import version_lt | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -63,26 +63,12 @@ class NetworkApiMixin(object): | ||||||
|                                      aliases=None, links=None): |                                      aliases=None, links=None): | ||||||
|         data = { |         data = { | ||||||
|             "Container": container, |             "Container": container, | ||||||
|             "EndpointConfig": { |             "EndpointConfig": self.create_endpoint_config( | ||||||
|                 "Aliases": aliases, |                 aliases=aliases, links=links, ipv4_address=ipv4_address, | ||||||
|                 "Links": normalize_links(links) if links else None, |                 ipv6_address=ipv6_address | ||||||
|             }, |             ), | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         # IPv4 or IPv6 or neither: |  | ||||||
|         if ipv4_address or ipv6_address: |  | ||||||
|             if version_lt(self._version, '1.22'): |  | ||||||
|                 raise InvalidVersion('IP address assignment is not ' |  | ||||||
|                                      'supported in API version < 1.22') |  | ||||||
| 
 |  | ||||||
|             data['EndpointConfig']['IPAMConfig'] = dict() |  | ||||||
|             if ipv4_address: |  | ||||||
|                 data['EndpointConfig']['IPAMConfig']['IPv4Address'] = \ |  | ||||||
|                     ipv4_address |  | ||||||
|             if ipv6_address: |  | ||||||
|                 data['EndpointConfig']['IPAMConfig']['IPv6Address'] = \ |  | ||||||
|                     ipv6_address |  | ||||||
| 
 |  | ||||||
|         url = self._url("/networks/{0}/connect", net_id) |         url = self._url("/networks/{0}/connect", net_id) | ||||||
|         res = self._post_json(url, data=data) |         res = self._post_json(url, data=data) | ||||||
|         self._raise_for_status(res) |         self._raise_for_status(res) | ||||||
|  |  | ||||||
|  | @ -813,19 +813,30 @@ def create_networking_config(endpoints_config=None): | ||||||
|     return networking_config |     return networking_config | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def create_endpoint_config(version, aliases=None, links=None): | def create_endpoint_config(version, aliases=None, links=None, | ||||||
|  |                            ipv4_address=None, ipv6_address=None): | ||||||
|  |     if version_lt(version, '1.22'): | ||||||
|  |         raise errors.InvalidVersion( | ||||||
|  |             'Endpoint config is not supported for API version < 1.22' | ||||||
|  |         ) | ||||||
|     endpoint_config = {} |     endpoint_config = {} | ||||||
| 
 | 
 | ||||||
|     if aliases: |     if aliases: | ||||||
|         if version_lt(version, '1.22'): |  | ||||||
|             raise host_config_version_error('endpoint_config.aliases', '1.22') |  | ||||||
|         endpoint_config["Aliases"] = aliases |         endpoint_config["Aliases"] = aliases | ||||||
| 
 | 
 | ||||||
|     if links: |     if links: | ||||||
|         if version_lt(version, '1.22'): |  | ||||||
|             raise host_config_version_error('endpoint_config.links', '1.22') |  | ||||||
|         endpoint_config["Links"] = normalize_links(links) |         endpoint_config["Links"] = normalize_links(links) | ||||||
| 
 | 
 | ||||||
|  |     ipam_config = {} | ||||||
|  |     if ipv4_address: | ||||||
|  |         ipam_config['IPv4Address'] = ipv4_address | ||||||
|  | 
 | ||||||
|  |     if ipv6_address: | ||||||
|  |         ipam_config['IPv6Address'] = ipv6_address | ||||||
|  | 
 | ||||||
|  |     if ipam_config: | ||||||
|  |         endpoint_config['IPAMConfig'] = ipam_config | ||||||
|  | 
 | ||||||
|     return endpoint_config |     return endpoint_config | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -242,6 +242,7 @@ from. Optionally a single string joining container id's with commas | ||||||
| * labels (dict or list): A dictionary of name-value labels (e.g. `{"label1": "value1", "label2": "value2"}`) or a list of names of labels to set with empty values (e.g. `["label1", "label2"]`) | * labels (dict or list): A dictionary of name-value labels (e.g. `{"label1": "value1", "label2": "value2"}`) or a list of names of labels to set with empty values (e.g. `["label1", "label2"]`) | ||||||
| * volume_driver (str): The name of a volume driver/plugin. | * volume_driver (str): The name of a volume driver/plugin. | ||||||
| * stop_signal (str): The stop signal to use to stop the container (e.g. `SIGINT`). | * stop_signal (str): The stop signal to use to stop the container (e.g. `SIGINT`). | ||||||
|  | * networking_config (dict): A [NetworkingConfig](networks.md) dictionary | ||||||
| 
 | 
 | ||||||
| **Returns** (dict): A dictionary with an image 'Id' key and a 'Warnings' key. | **Returns** (dict): A dictionary with an image 'Id' key and a 'Warnings' key. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										161
									
								
								docs/networks.md
								
								
								
								
							
							
						
						
									
										161
									
								
								docs/networks.md
								
								
								
								
							|  | @ -1,27 +1,176 @@ | ||||||
| # Using Networks | # Using Networks | ||||||
| 
 | 
 | ||||||
|  | ## Network creation | ||||||
|  | 
 | ||||||
| With the release of Docker 1.9 you can now manage custom networks. | With the release of Docker 1.9 you can now manage custom networks. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Here you can see how to create a network named ```network1``` using the ```bridge``` driver | Here you can see how to create a network named `network1` using | ||||||
|  | the `bridge` driver | ||||||
| 
 | 
 | ||||||
| ```python | ```python | ||||||
| docker_client.create_network("network1", driver="bridge") | docker_client.create_network("network1", driver="bridge") | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| You can also create more advanced networks with custom IPAM configurations. For example,  | You can also create more advanced networks with custom IPAM configurations. | ||||||
| setting the subnet to ```192.168.52.0/24``` and gateway to ```192.168.52.254``` | For example, setting the subnet to `192.168.52.0/24` and gateway address | ||||||
|  | to `192.168.52.254` | ||||||
| 
 | 
 | ||||||
| ```python | ```python | ||||||
| 
 | ipam_pool = docker.utils.create_ipam_pool( | ||||||
| ipam_config = docker.utils.create_ipam_config(subnet='192.168.52.0/24', gateway='192.168.52.254') |     subnet='192.168.52.0/24', | ||||||
|  |     gateway='192.168.52.254' | ||||||
|  | ) | ||||||
|  | ipam_config = docker.utils.create_ipam_config( | ||||||
|  |     pool_configs=[ipam_pool] | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| docker_client.create_network("network1", driver="bridge", ipam=ipam_config) | docker_client.create_network("network1", driver="bridge", ipam=ipam_config) | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| With Docker 1.10 you can now also create internal networks | By default, when you connect a container to an overlay network, Docker also | ||||||
|  | connects a bridge network to it to provide external connectivity. If you want | ||||||
|  | to create an externally isolated overlay network, with Docker 1.10 you can | ||||||
|  | create an internal network. | ||||||
| 
 | 
 | ||||||
| ```python | ```python | ||||||
| 
 | 
 | ||||||
| docker_client.create_network("network1", driver="bridge", internal=True) | docker_client.create_network("network1", driver="bridge", internal=True) | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
|  | ## Container network configuration | ||||||
|  | 
 | ||||||
|  | In order to specify which network a container will be connected to, and | ||||||
|  | additional configuration, use the `networking_config` parameter in | ||||||
|  | `Client.create_container`. Note that at the time of creation, you can | ||||||
|  | only connect a container to a single network. Later on, you may create more | ||||||
|  | connections using `Client.connect_container_to_network`. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ```python | ||||||
|  | networking_config = docker_client.create_networking_config({ | ||||||
|  |     'network1': docker_client.create_endpoint_config( | ||||||
|  |         ipv4_address='172.28.0.124', | ||||||
|  |         aliases=['foo', 'bar'], | ||||||
|  |         links=['container2'] | ||||||
|  |     ) | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | ctnr = docker_client.create_container( | ||||||
|  |     img, command, networking_config=networking_config | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## Network API documentation | ||||||
|  | 
 | ||||||
|  | ### Client.create_networking_config | ||||||
|  | 
 | ||||||
|  | Create a networking config dictionary to be used as the `networking_config` | ||||||
|  | parameter in `Client.create_container_config` | ||||||
|  | 
 | ||||||
|  | **Params**: | ||||||
|  | 
 | ||||||
|  | * endpoints_config (dict): A dictionary of `network_name -> endpoint_config` | ||||||
|  |   relationships. Values should be endpoint config dictionaries created by | ||||||
|  |   `Client.create_endpoint_config`. Defaults to `None` (default config). | ||||||
|  | 
 | ||||||
|  | **Returns** A networking config dictionary. | ||||||
|  | 
 | ||||||
|  | ```python | ||||||
|  | 
 | ||||||
|  | docker_client.create_network('network1') | ||||||
|  | 
 | ||||||
|  | networking_config = docker_client.create_networking_config({ | ||||||
|  |     'network1': docker_client.create_endpoint_config() | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | container = docker_client.create_container( | ||||||
|  |     img, command, networking_config=networking_config | ||||||
|  | ) | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ### Client.create_endpoint_config | ||||||
|  | 
 | ||||||
|  | Create an endpoint config dictionary to be used with | ||||||
|  | `Client.create_networking_config`. | ||||||
|  | 
 | ||||||
|  | **Params**: | ||||||
|  | 
 | ||||||
|  | * aliases (list): A list of aliases for this endpoint. Names in that list can | ||||||
|  |   be used within the network to reach the container. Defaults to `None`. | ||||||
|  | * links (list): A list of links for this endpoint. Containers declared in this | ||||||
|  |   list will be [linked](https://docs.docker.com/engine/userguide/networking/work-with-networks/#linking-containers-in-user-defined-networks) | ||||||
|  |   to this container. Defaults to `None`. | ||||||
|  | * ipv4_address (str): The IP address of this container on the network, | ||||||
|  |   using the IPv4 protocol. Defaults to `None`. | ||||||
|  | * ipv6_address (str): The IP address of this container on the network, | ||||||
|  |   using the IPv6 protocol. Defaults to `None`. | ||||||
|  | 
 | ||||||
|  | **Returns** An endpoint config dictionary. | ||||||
|  | 
 | ||||||
|  | ```python | ||||||
|  | endpoint_config = docker_client.create_endpoint_config( | ||||||
|  |     aliases=['web', 'app'], | ||||||
|  |     links=['app_db'], | ||||||
|  |     ipv4_address='132.65.0.123' | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | docker_client.create_network('network1') | ||||||
|  | networking_config = docker_client.create_networking_config({ | ||||||
|  |     'network1': endpoint_config | ||||||
|  | }) | ||||||
|  | container = docker_client.create_container( | ||||||
|  |     img, command, networking_config=networking_config | ||||||
|  | ) | ||||||
|  | ``` | ||||||
|  | ### docker.utils.create_ipam_config | ||||||
|  | 
 | ||||||
|  | Create an IPAM (IP Address Management) config dictionary to be used with | ||||||
|  | `Client.create_network`. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | **Params**: | ||||||
|  | 
 | ||||||
|  | * driver (str): The IPAM driver to use. Defaults to `'default'`. | ||||||
|  | * pool_configs (list): A list of pool configuration dictionaries as created | ||||||
|  |   by `docker.utils.create_ipam_pool`. Defaults to empty list. | ||||||
|  | 
 | ||||||
|  | **Returns** An IPAM config dictionary | ||||||
|  | 
 | ||||||
|  | ```python | ||||||
|  | ipam_config = docker.utils.create_ipam_config(driver='default') | ||||||
|  | network = docker_client.create_network('network1', ipam=ipam_config) | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ### docker.utils.create_ipam_pool | ||||||
|  | 
 | ||||||
|  | Create an IPAM pool config dictionary to be added to the `pool_configs` param | ||||||
|  | in `docker.utils.create_ipam_config`. | ||||||
|  | 
 | ||||||
|  | **Params**: | ||||||
|  | 
 | ||||||
|  | * subnet (str): Custom subnet for this IPAM pool using the CIDR notation. | ||||||
|  |   Defaults to `None`. | ||||||
|  | * iprange (str): Custom IP range for endpoints in this IPAM pool using the | ||||||
|  |   CIDR notation. Defaults to `None`. | ||||||
|  | * gateway (str): Custom IP address for the pool's gateway. | ||||||
|  | * aux_addresses (dict): A dictionary of `key -> ip_address` relationships | ||||||
|  |   specifying auxiliary addresses that need to be allocated by the | ||||||
|  |   IPAM driver. | ||||||
|  | 
 | ||||||
|  | **Returns** An IPAM pool config dictionary | ||||||
|  | 
 | ||||||
|  | ```python | ||||||
|  | ipam_pool = docker.utils.create_ipam_pool( | ||||||
|  |     subnet='124.42.0.0/16', | ||||||
|  |     iprange='124.42.0.0/24', | ||||||
|  |     gateway='124.42.0.254', | ||||||
|  |     aux_addresses={ | ||||||
|  |         'reserved1': '124.42.1.1' | ||||||
|  |     } | ||||||
|  | ) | ||||||
|  | ipam_config = docker.utils.create_ipam_config(pool_configs=[ipam_pool]) | ||||||
|  | network = docker_client.create_network('network1', ipam=ipam_config) | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | @ -185,7 +185,66 @@ class TestNetworks(helpers.BaseTestCase): | ||||||
|         container_data = self.client.inspect_container(container) |         container_data = self.client.inspect_container(container) | ||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             container_data['NetworkSettings']['Networks'][net_name]['Aliases'], |             container_data['NetworkSettings']['Networks'][net_name]['Aliases'], | ||||||
|             ['foo', 'bar']) |             ['foo', 'bar'] | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |     @requires_api_version('1.22') | ||||||
|  |     def test_create_with_ipv4_address(self): | ||||||
|  |         net_name, net_id = self.create_network( | ||||||
|  |             ipam=create_ipam_config( | ||||||
|  |                 driver='default', | ||||||
|  |                 pool_configs=[create_ipam_pool(subnet="132.124.0.0/16")], | ||||||
|  |             ), | ||||||
|  |         ) | ||||||
|  |         container = self.client.create_container( | ||||||
|  |             image='busybox', command='top', | ||||||
|  |             host_config=self.client.create_host_config(network_mode=net_name), | ||||||
|  |             networking_config=self.client.create_networking_config({ | ||||||
|  |                 net_name: self.client.create_endpoint_config( | ||||||
|  |                     ipv4_address='132.124.0.23' | ||||||
|  |                 ) | ||||||
|  |             }) | ||||||
|  |         ) | ||||||
|  |         self.tmp_containers.append(container) | ||||||
|  |         self.client.start(container) | ||||||
|  | 
 | ||||||
|  |         container_data = self.client.inspect_container(container) | ||||||
|  |         self.assertEqual( | ||||||
|  |             container_data[ | ||||||
|  |                 'NetworkSettings']['Networks'][net_name]['IPAMConfig'][ | ||||||
|  |                 'IPv4Address' | ||||||
|  |             ], | ||||||
|  |             '132.124.0.23' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |     @requires_api_version('1.22') | ||||||
|  |     def test_create_with_ipv6_address(self): | ||||||
|  |         net_name, net_id = self.create_network( | ||||||
|  |             ipam=create_ipam_config( | ||||||
|  |                 driver='default', | ||||||
|  |                 pool_configs=[create_ipam_pool(subnet="2001:389::1/64")], | ||||||
|  |             ), | ||||||
|  |         ) | ||||||
|  |         container = self.client.create_container( | ||||||
|  |             image='busybox', command='top', | ||||||
|  |             host_config=self.client.create_host_config(network_mode=net_name), | ||||||
|  |             networking_config=self.client.create_networking_config({ | ||||||
|  |                 net_name: self.client.create_endpoint_config( | ||||||
|  |                     ipv6_address='2001:389::f00d' | ||||||
|  |                 ) | ||||||
|  |             }) | ||||||
|  |         ) | ||||||
|  |         self.tmp_containers.append(container) | ||||||
|  |         self.client.start(container) | ||||||
|  | 
 | ||||||
|  |         container_data = self.client.inspect_container(container) | ||||||
|  |         self.assertEqual( | ||||||
|  |             container_data[ | ||||||
|  |                 'NetworkSettings']['Networks'][net_name]['IPAMConfig'][ | ||||||
|  |                 'IPv6Address' | ||||||
|  |             ], | ||||||
|  |             '2001:389::f00d' | ||||||
|  |         ) | ||||||
| 
 | 
 | ||||||
|     @requires_api_version('1.22') |     @requires_api_version('1.22') | ||||||
|     def test_create_with_links(self): |     def test_create_with_links(self): | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue