From 4dece7fcb20f4cae3a77291d20d1c83e34cbc4c3 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Mon, 23 Apr 2018 16:41:10 -0700 Subject: Retrieve objects using legacy (< 1.21) project names Signed-off-by: Joffrey F --- compose/network.py | 66 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 17 deletions(-) (limited to 'compose/network.py') diff --git a/compose/network.py b/compose/network.py index 1a080c40..e0fdb3e2 100644 --- a/compose/network.py +++ b/compose/network.py @@ -2,6 +2,7 @@ from __future__ import absolute_import from __future__ import unicode_literals import logging +import re from collections import OrderedDict from docker.errors import NotFound @@ -10,9 +11,11 @@ from docker.types import IPAMPool from docker.utils import version_gte from docker.utils import version_lt +from . import __version__ from .config import ConfigurationError from .const import LABEL_NETWORK from .const import LABEL_PROJECT +from .const import LABEL_VERSION log = logging.getLogger(__name__) @@ -39,6 +42,7 @@ class Network(object): self.enable_ipv6 = enable_ipv6 self.labels = labels self.custom_name = custom_name + self.legacy = False def ensure(self): if self.external: @@ -68,6 +72,14 @@ class Network(object): data = self.inspect() check_remote_network_config(data, self) except NotFound: + try: + data = self.inspect(legacy=True) + self.legacy = True + check_remote_network_config(data, self) + return + except NotFound: + pass + driver_name = 'the default driver' if self.driver: driver_name = 'driver "{}"'.format(self.driver) @@ -94,18 +106,37 @@ class Network(object): log.info("Network %s is external, skipping", self.full_name) return - log.info("Removing network {}".format(self.full_name)) - self.client.remove_network(self.full_name) + log.info("Removing network {}".format(self.true_name)) + try: + self.client.remove_network(self.full_name) + except NotFound: + self.client.remove_network(self.legacy_full_name) - def inspect(self): + def inspect(self, legacy=False): + if legacy: + return self.client.inspect_network(self.legacy_full_name) return self.client.inspect_network(self.full_name) + @property + def legacy_full_name(self): + if self.custom_name: + return self.name + return '{0}_{1}'.format( + re.sub(r'[_-]', '', self.project), self.name + ) + @property def full_name(self): if self.custom_name: return self.name return '{0}_{1}'.format(self.project, self.name) + @property + def true_name(self): + if self.legacy: + return self.legacy_full_name + return self.full_name + @property def _labels(self): if version_lt(self.client._version, '1.23'): @@ -114,6 +145,7 @@ class Network(object): labels.update({ LABEL_PROJECT: self.project, LABEL_NETWORK: self.name, + LABEL_VERSION: __version__, }) return labels @@ -150,49 +182,49 @@ def check_remote_ipam_config(remote, local): remote_ipam = remote.get('IPAM') ipam_dict = create_ipam_config_from_dict(local.ipam) if local.ipam.get('driver') and local.ipam.get('driver') != remote_ipam.get('Driver'): - raise NetworkConfigChangedError(local.full_name, 'IPAM driver') + raise NetworkConfigChangedError(local.true_name, 'IPAM driver') if len(ipam_dict['Config']) != 0: if len(ipam_dict['Config']) != len(remote_ipam['Config']): - raise NetworkConfigChangedError(local.full_name, 'IPAM configs') + raise NetworkConfigChangedError(local.true_name, 'IPAM configs') remote_configs = sorted(remote_ipam['Config'], key='Subnet') local_configs = sorted(ipam_dict['Config'], key='Subnet') while local_configs: lc = local_configs.pop() rc = remote_configs.pop() if lc.get('Subnet') != rc.get('Subnet'): - raise NetworkConfigChangedError(local.full_name, 'IPAM config subnet') + raise NetworkConfigChangedError(local.true_name, 'IPAM config subnet') if lc.get('Gateway') is not None and lc.get('Gateway') != rc.get('Gateway'): - raise NetworkConfigChangedError(local.full_name, 'IPAM config gateway') + raise NetworkConfigChangedError(local.true_name, 'IPAM config gateway') if lc.get('IPRange') != rc.get('IPRange'): - raise NetworkConfigChangedError(local.full_name, 'IPAM config ip_range') + raise NetworkConfigChangedError(local.true_name, 'IPAM config ip_range') if sorted(lc.get('AuxiliaryAddresses')) != sorted(rc.get('AuxiliaryAddresses')): - raise NetworkConfigChangedError(local.full_name, 'IPAM config aux_addresses') + raise NetworkConfigChangedError(local.true_name, 'IPAM config aux_addresses') remote_opts = remote_ipam.get('Options') or {} local_opts = local.ipam.get('options') or {} for k in set.union(set(remote_opts.keys()), set(local_opts.keys())): if remote_opts.get(k) != local_opts.get(k): - raise NetworkConfigChangedError(local.full_name, 'IPAM option "{}"'.format(k)) + raise NetworkConfigChangedError(local.true_name, 'IPAM option "{}"'.format(k)) def check_remote_network_config(remote, local): if local.driver and remote.get('Driver') != local.driver: - raise NetworkConfigChangedError(local.full_name, 'driver') + raise NetworkConfigChangedError(local.true_name, 'driver') local_opts = local.driver_opts or {} remote_opts = remote.get('Options') or {} for k in set.union(set(remote_opts.keys()), set(local_opts.keys())): if k in OPTS_EXCEPTIONS: continue if remote_opts.get(k) != local_opts.get(k): - raise NetworkConfigChangedError(local.full_name, 'option "{}"'.format(k)) + raise NetworkConfigChangedError(local.true_name, 'option "{}"'.format(k)) if local.ipam is not None: check_remote_ipam_config(remote, local) if local.internal is not None and local.internal != remote.get('Internal', False): - raise NetworkConfigChangedError(local.full_name, 'internal') + raise NetworkConfigChangedError(local.true_name, 'internal') if local.enable_ipv6 is not None and local.enable_ipv6 != remote.get('EnableIPv6', False): - raise NetworkConfigChangedError(local.full_name, 'enable_ipv6') + raise NetworkConfigChangedError(local.true_name, 'enable_ipv6') local_labels = local.labels or {} remote_labels = remote.get('Labels', {}) @@ -202,7 +234,7 @@ def check_remote_network_config(remote, local): if remote_labels.get(k) != local_labels.get(k): log.warn( 'Network {}: label "{}" has changed. It may need to be' - ' recreated.'.format(local.full_name, k) + ' recreated.'.format(local.true_name, k) ) @@ -257,7 +289,7 @@ class ProjectNetworks(object): try: network.remove() except NotFound: - log.warn("Network %s not found.", network.full_name) + log.warn("Network %s not found.", network.true_name) def initialize(self): if not self.use_networking: @@ -286,7 +318,7 @@ def get_networks(service_dict, network_definitions): for name, netdef in get_network_defs_for_service(service_dict).items(): network = network_definitions.get(name) if network: - networks[network.full_name] = netdef + networks[network.true_name] = netdef else: raise ConfigurationError( 'Service "{}" uses an undefined network "{}"' -- cgit v1.2.3 From 299ce6ad009fa9f56564c51a4cd86eafa6e7ccee Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Mon, 23 Apr 2018 18:16:58 -0700 Subject: Incorrect key name for IPAM options check Signed-off-by: Joffrey F --- compose/network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'compose/network.py') diff --git a/compose/network.py b/compose/network.py index 1a080c40..7803db97 100644 --- a/compose/network.py +++ b/compose/network.py @@ -169,7 +169,7 @@ def check_remote_ipam_config(remote, local): raise NetworkConfigChangedError(local.full_name, 'IPAM config aux_addresses') remote_opts = remote_ipam.get('Options') or {} - local_opts = local.ipam.get('options') or {} + local_opts = local.ipam.get('Options') or {} for k in set.union(set(remote_opts.keys()), set(local_opts.keys())): if remote_opts.get(k) != local_opts.get(k): raise NetworkConfigChangedError(local.full_name, 'IPAM option "{}"'.format(k)) -- cgit v1.2.3 From c1657dc46aab2edafbd175b27756e367839129d5 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Tue, 24 Apr 2018 15:48:02 -0700 Subject: Improve legacy network and volume detection Signed-off-by: Joffrey F --- compose/network.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'compose/network.py') diff --git a/compose/network.py b/compose/network.py index e0fdb3e2..b00e2ae9 100644 --- a/compose/network.py +++ b/compose/network.py @@ -42,7 +42,7 @@ class Network(object): self.enable_ipv6 = enable_ipv6 self.labels = labels self.custom_name = custom_name - self.legacy = False + self.legacy = None def ensure(self): if self.external: @@ -68,25 +68,17 @@ class Network(object): ) return + self._set_legacy_flag() try: - data = self.inspect() + data = self.inspect(legacy=self.legacy) check_remote_network_config(data, self) except NotFound: - try: - data = self.inspect(legacy=True) - self.legacy = True - check_remote_network_config(data, self) - return - except NotFound: - pass - driver_name = 'the default driver' if self.driver: driver_name = 'driver "{}"'.format(self.driver) log.info( - 'Creating network "{}" with {}' - .format(self.full_name, driver_name) + 'Creating network "{}" with {}'.format(self.full_name, driver_name) ) self.client.create_network( @@ -133,6 +125,7 @@ class Network(object): @property def true_name(self): + self._set_legacy_flag() if self.legacy: return self.legacy_full_name return self.full_name @@ -149,6 +142,15 @@ class Network(object): }) return labels + def _set_legacy_flag(self): + if self.legacy is not None: + return + try: + data = self.inspect(legacy=True) + self.legacy = data is not None + except NotFound: + self.legacy = False + def create_ipam_config_from_dict(ipam_dict): if not ipam_dict: -- cgit v1.2.3 From 3b2ce82fa1c2131a542d3af7768c6b4c56094a18 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Tue, 24 Apr 2018 16:10:59 -0700 Subject: Use true_name for remove operation Signed-off-by: Joffrey F --- compose/network.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'compose/network.py') diff --git a/compose/network.py b/compose/network.py index b00e2ae9..4ac3a0ea 100644 --- a/compose/network.py +++ b/compose/network.py @@ -95,14 +95,11 @@ class Network(object): def remove(self): if self.external: - log.info("Network %s is external, skipping", self.full_name) + log.info("Network %s is external, skipping", self.true_name) return log.info("Removing network {}".format(self.true_name)) - try: - self.client.remove_network(self.full_name) - except NotFound: - self.client.remove_network(self.legacy_full_name) + self.client.remove_network(self.true_name) def inspect(self, legacy=False): if legacy: -- cgit v1.2.3 From 707e21183f5117f4f2b5005615a7c483958b5b3d Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Tue, 7 Aug 2018 16:45:34 -0700 Subject: Fix config hash consistency with unprioritized networks Signed-off-by: Joffrey F --- compose/network.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'compose/network.py') diff --git a/compose/network.py b/compose/network.py index 9751f203..2491a598 100644 --- a/compose/network.py +++ b/compose/network.py @@ -323,7 +323,12 @@ def get_networks(service_dict, network_definitions): 'Service "{}" uses an undefined network "{}"' .format(service_dict['name'], name)) - return OrderedDict(sorted( - networks.items(), - key=lambda t: t[1].get('priority') or 0, reverse=True - )) + if any([v.get('priority') for v in networks.values()]): + return OrderedDict(sorted( + networks.items(), + key=lambda t: t[1].get('priority') or 0, reverse=True + )) + else: + # Ensure Compose will pick a consistent primary network if no + # priority is set + return OrderedDict(sorted(networks.items(), key=lambda t: t[0])) -- cgit v1.2.3 From 99e67d0c061fa3d9b9793391f3b7c8bdf8e841fc Mon Sep 17 00:00:00 2001 From: Inconnu08 Date: Wed, 15 May 2019 23:45:40 +0600 Subject: fix warning method is deprecated with tests Signed-off-by: Taufiq Rahman --- compose/network.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'compose/network.py') diff --git a/compose/network.py b/compose/network.py index 2491a598..e0d711ff 100644 --- a/compose/network.py +++ b/compose/network.py @@ -231,7 +231,7 @@ def check_remote_network_config(remote, local): if k.startswith('com.docker.'): # We are only interested in user-specified labels continue if remote_labels.get(k) != local_labels.get(k): - log.warn( + log.warning( 'Network {}: label "{}" has changed. It may need to be' ' recreated.'.format(local.true_name, k) ) @@ -276,7 +276,7 @@ class ProjectNetworks(object): } unused = set(networks) - set(service_networks) - {'default'} if unused: - log.warn( + log.warning( "Some networks were defined but are not used by any service: " "{}".format(", ".join(unused))) return cls(service_networks, use_networking) @@ -288,7 +288,7 @@ class ProjectNetworks(object): try: network.remove() except NotFound: - log.warn("Network %s not found.", network.true_name) + log.warning("Network %s not found.", network.true_name) def initialize(self): if not self.use_networking: -- cgit v1.2.3 From a5fbf91b72f1f32fe61b2d7b3e0cd5d53fbf2aac Mon Sep 17 00:00:00 2001 From: Danil Kister Date: Wed, 21 Aug 2019 18:51:44 +0200 Subject: Prevent KeyError when remote network labels are None. Signed-off-by: Danil Kister --- compose/network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'compose/network.py') diff --git a/compose/network.py b/compose/network.py index e0d711ff..84531ecc 100644 --- a/compose/network.py +++ b/compose/network.py @@ -226,7 +226,7 @@ def check_remote_network_config(remote, local): raise NetworkConfigChangedError(local.true_name, 'enable_ipv6') local_labels = local.labels or {} - remote_labels = remote.get('Labels', {}) + remote_labels = remote.get('Labels') or {} for k in set.union(set(remote_labels.keys()), set(local_labels.keys())): if k.startswith('com.docker.'): # We are only interested in user-specified labels continue -- cgit v1.2.3