From 781dc30ad425286ede981d639647cae6afd1a2e9 Mon Sep 17 00:00:00 2001 From: Barry Shapira Date: Fri, 14 Dec 2018 07:30:55 +0000 Subject: [PATCH] Check API version before setting swarm addr pool. Also corrected a documentation error: the default API version from constants is currently 1.35, not 1.30 as was sometimes listed. Signed-off-by: Barry Shapira Removed accidental whitespace. Signed-off-by: Barry Shapira --- docker/api/swarm.py | 27 ++++++++++++++++++++++++--- docker/constants.py | 3 +++ docker/models/swarm.py | 6 +++--- tests/integration/api_swarm_test.py | 23 ++++++++++++++--------- 4 files changed, 44 insertions(+), 15 deletions(-) diff --git a/docker/api/swarm.py b/docker/api/swarm.py index bec3efdf..4a39782a 100644 --- a/docker/api/swarm.py +++ b/docker/api/swarm.py @@ -1,5 +1,6 @@ import logging from six.moves import http_client +from ..constants import DEFAULT_SWARM_ADDR_POOL, DEFAULT_SWARM_SUBNET_SIZE from .. import errors from .. import types from .. import utils @@ -82,7 +83,7 @@ class SwarmApiMixin(object): @utils.minimum_version('1.24') def init_swarm(self, advertise_addr=None, listen_addr='0.0.0.0:2377', - default_addr_pool=[], subnet_size=24, + default_addr_pool=None, subnet_size=None, force_new_cluster=False, swarm_spec=None): """ Initialize a new Swarm using the current connected engine as the first @@ -106,9 +107,9 @@ class SwarmApiMixin(object): default_addr_pool (list of strings): Default Address Pool specifies default subnet pools for global scope networks. Each pool should be specified as a CIDR block, like '10.0.0.0/16'. - Default: [] + Default: None subnet_size (int): SubnetSize specifies the subnet size of the - networks created from the default subnet pool. Default: 24 + networks created from the default subnet pool. Default: None force_new_cluster (bool): Force creating a new Swarm, even if already part of one. Default: False swarm_spec (dict): Configuration settings of the new Swarm. Use @@ -124,8 +125,28 @@ class SwarmApiMixin(object): """ url = self._url('/swarm/init') + if swarm_spec is not None and not isinstance(swarm_spec, dict): raise TypeError('swarm_spec must be a dictionary') + + if default_addr_pool is not None: + if utils.version_lt(self._version, '1.39'): + raise errors.InvalidVersion( + 'Address pool is only available for API version >= 1.39' + ) + # subnet_size becomes 0 if not set with default_addr_pool + if subnet_size is None: + subnet_size = DEFAULT_SWARM_SUBNET_SIZE + + if subnet_size is not None: + if utils.version_lt(self._version, '1.39'): + raise errors.InvalidVersion( + 'Subnet size is only available for API version >= 1.39' + ) + # subnet_size is ignored if set without default_addr_pool + if default_addr_pool is None: + default_addr_pool = DEFAULT_SWARM_ADDR_POOL + data = { 'AdvertiseAddr': advertise_addr, 'ListenAddr': listen_addr, diff --git a/docker/constants.py b/docker/constants.py index dcba0de2..4b96e1ce 100644 --- a/docker/constants.py +++ b/docker/constants.py @@ -25,3 +25,6 @@ DEFAULT_NUM_POOLS = 25 DEFAULT_NUM_POOLS_SSH = 9 DEFAULT_DATA_CHUNK_SIZE = 1024 * 2048 + +DEFAULT_SWARM_ADDR_POOL = ['10.0.0.0/8'] +DEFAULT_SWARM_SUBNET_SIZE = 24 diff --git a/docker/models/swarm.py b/docker/models/swarm.py index e39e6f35..1106ce26 100644 --- a/docker/models/swarm.py +++ b/docker/models/swarm.py @@ -34,7 +34,7 @@ class Swarm(Model): get_unlock_key.__doc__ = APIClient.get_unlock_key.__doc__ def init(self, advertise_addr=None, listen_addr='0.0.0.0:2377', - default_addr_pool=[], subnet_size=24, + default_addr_pool=None, subnet_size=None, force_new_cluster=False, **kwargs): """ Initialize a new swarm on this Engine. @@ -58,9 +58,9 @@ class Swarm(Model): default_addr_pool (list of str): Default Address Pool specifies default subnet pools for global scope networks. Each pool should be specified as a CIDR block, like '10.0.0.0/16'. - Default: [] + Default: None subnet_size (int): SubnetSize specifies the subnet size of the - networks created from the default subnet pool. Default: 24 + networks created from the default subnet pool. Default: None force_new_cluster (bool): Force creating a new Swarm, even if already part of one. Default: False task_history_retention_limit (int): Maximum number of tasks diff --git a/tests/integration/api_swarm_test.py b/tests/integration/api_swarm_test.py index 5ef651d2..41fae578 100644 --- a/tests/integration/api_swarm_test.py +++ b/tests/integration/api_swarm_test.py @@ -37,26 +37,31 @@ class SwarmTest(BaseAPIIntegrationTest): @requires_api_version('1.39') def test_init_swarm_custom_addr_pool(self): + # test defaults assert self.init_swarm() results_1 = self.client.inspect_swarm() - assert results_1['DefaultAddrPool'] is None + assert set(results_1['DefaultAddrPool']) == {'10.0.0.0/8'} assert results_1['SubnetSize'] == 24 - + # test addr pool alone assert self.init_swarm(default_addr_pool=['2.0.0.0/16'], force_new_cluster=True) results_2 = self.client.inspect_swarm() - assert set(results_2['DefaultAddrPool']) == ( - {'2.0.0.0/16'} - ) + assert set(results_2['DefaultAddrPool']) == {'2.0.0.0/16'} assert results_2['SubnetSize'] == 24 - + # test subnet size alone + assert self.init_swarm(subnet_size=26, + force_new_cluster=True) + results_3 = self.client.inspect_swarm() + assert set(results_3['DefaultAddrPool']) == {'10.0.0.0/8'} + assert results_3['SubnetSize'] == 26 + # test both arguments together assert self.init_swarm(default_addr_pool=['2.0.0.0/16', '3.0.0.0/16'], subnet_size=28, force_new_cluster=True) - results_3 = self.client.inspect_swarm() - assert set(results_3['DefaultAddrPool']) == ( + results_4 = self.client.inspect_swarm() + assert set(results_4['DefaultAddrPool']) == ( {'2.0.0.0/16', '3.0.0.0/16'} ) - assert results_3['SubnetSize'] == 28 + assert results_4['SubnetSize'] == 28 @requires_api_version('1.24') def test_init_already_in_cluster(self):