diff --git a/docker/api/swarm.py b/docker/api/swarm.py index 13e4fd5c..897f08e4 100644 --- a/docker/api/swarm.py +++ b/docker/api/swarm.py @@ -406,8 +406,10 @@ class SwarmApiMixin(object): return True @utils.minimum_version('1.24') - def update_swarm(self, version, swarm_spec=None, rotate_worker_token=False, - rotate_manager_token=False): + def update_swarm(self, version, swarm_spec=None, + rotate_worker_token=False, + rotate_manager_token=False, + rotate_manager_unlock_key=False): """ Update the Swarm's configuration @@ -421,6 +423,8 @@ class SwarmApiMixin(object): ``False``. rotate_manager_token (bool): Rotate the manager join token. Default: ``False``. + rotate_manager_unlock_key (bool): Rotate the manager unlock key. + Default: ``False``. Returns: ``True`` if the request went through. @@ -429,12 +433,20 @@ class SwarmApiMixin(object): :py:class:`docker.errors.APIError` If the server returns an error. """ - url = self._url('/swarm/update') - response = self._post_json(url, data=swarm_spec, params={ + params = { 'rotateWorkerToken': rotate_worker_token, 'rotateManagerToken': rotate_manager_token, 'version': version - }) + } + if rotate_manager_unlock_key: + if utils.version_lt(self._version, '1.25'): + raise errors.InvalidVersion( + 'Rotate manager unlock key ' + 'is only available for API version >= 1.25' + ) + params['rotateManagerUnlockKey'] = rotate_manager_unlock_key + + response = self._post_json(url, data=swarm_spec, params=params) self._raise_for_status(response) return True diff --git a/docker/models/swarm.py b/docker/models/swarm.py index f8c5fff6..755c17db 100644 --- a/docker/models/swarm.py +++ b/docker/models/swarm.py @@ -151,7 +151,7 @@ class Swarm(Model): unlock.__doc__ = APIClient.unlock_swarm.__doc__ def update(self, rotate_worker_token=False, rotate_manager_token=False, - **kwargs): + rotate_manager_unlock_key=False, **kwargs): """ Update the swarm's configuration. @@ -164,7 +164,8 @@ class Swarm(Model): ``False``. rotate_manager_token (bool): Rotate the manager join token. Default: ``False``. - + rotate_manager_unlock_key (bool): Rotate the manager unlock key. + Default: ``False``. Raises: :py:class:`docker.errors.APIError` If the server returns an error. @@ -178,5 +179,6 @@ class Swarm(Model): version=self.version, swarm_spec=self.client.api.create_swarm_spec(**kwargs), rotate_worker_token=rotate_worker_token, - rotate_manager_token=rotate_manager_token + rotate_manager_token=rotate_manager_token, + rotate_manager_unlock_key=rotate_manager_unlock_key ) diff --git a/tests/integration/api_swarm_test.py b/tests/integration/api_swarm_test.py index 5d4086a6..bf809bd0 100644 --- a/tests/integration/api_swarm_test.py +++ b/tests/integration/api_swarm_test.py @@ -236,6 +236,19 @@ class SwarmTest(BaseAPIIntegrationTest): assert e.value.response.status_code >= 400 + @requires_api_version('1.25') + def test_rotate_manager_unlock_key(self): + spec = self.client.create_swarm_spec(autolock_managers=True) + assert self.init_swarm(swarm_spec=spec) + swarm_info = self.client.inspect_swarm() + key_1 = self.client.get_unlock_key() + assert self.client.update_swarm( + version=swarm_info['Version']['Index'], + rotate_manager_unlock_key=True + ) + key_2 = self.client.get_unlock_key() + assert key_1['UnlockKey'] != key_2['UnlockKey'] + @requires_api_version('1.30') def test_init_swarm_data_path_addr(self): assert self.init_swarm(data_path_addr='eth0')