Skip to content
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
35 changes: 29 additions & 6 deletions docker/api/swarm.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ def get_unlock_key(self):
@utils.minimum_version('1.24')
def init_swarm(self, advertise_addr=None, listen_addr='0.0.0.0:2377',
force_new_cluster=False, swarm_spec=None,
default_addr_pool=None, subnet_size=None):
default_addr_pool=None, subnet_size=None,
data_path_addr=None):
"""
Initialize a new Swarm using the current connected engine as the first
node.
Expand Down Expand Up @@ -115,6 +116,8 @@ def init_swarm(self, advertise_addr=None, listen_addr='0.0.0.0:2377',
Default: None
subnet_size (int): SubnetSize specifies the subnet size of the
networks created from the default subnet pool. Default: None
data_path_addr (string): Address or interface to use for data path
traffic. For example, 192.168.1.1, or an interface, like eth0.

Returns:
``True`` if successful.
Expand Down Expand Up @@ -154,6 +157,15 @@ def init_swarm(self, advertise_addr=None, listen_addr='0.0.0.0:2377',
'ForceNewCluster': force_new_cluster,
'Spec': swarm_spec,
}

if data_path_addr is not None:
if utils.version_lt(self._version, '1.30'):
raise errors.InvalidVersion(
'Data address path is only available for '
'API version >= 1.30'
)
data['DataPathAddr'] = data_path_addr

response = self._post_json(url, data=data)
self._raise_for_status(response)
return True
Expand Down Expand Up @@ -194,7 +206,7 @@ def inspect_node(self, node_id):

@utils.minimum_version('1.24')
def join_swarm(self, remote_addrs, join_token, listen_addr='0.0.0.0:2377',
advertise_addr=None):
advertise_addr=None, data_path_addr=None):
"""
Make this Engine join a swarm that has already been created.

Expand All @@ -213,6 +225,8 @@ def join_swarm(self, remote_addrs, join_token, listen_addr='0.0.0.0:2377',
the port number from the listen address is used. If
AdvertiseAddr is not specified, it will be automatically
detected when possible. Default: ``None``
data_path_addr (string): Address or interface to use for data path
traffic. For example, 192.168.1.1, or an interface, like eth0.

Returns:
``True`` if the request went through.
Expand All @@ -222,11 +236,20 @@ def join_swarm(self, remote_addrs, join_token, listen_addr='0.0.0.0:2377',
If the server returns an error.
"""
data = {
"RemoteAddrs": remote_addrs,
"ListenAddr": listen_addr,
"JoinToken": join_token,
"AdvertiseAddr": advertise_addr,
'RemoteAddrs': remote_addrs,
'ListenAddr': listen_addr,
'JoinToken': join_token,
'AdvertiseAddr': advertise_addr,
}

if data_path_addr is not None:
if utils.version_lt(self._version, '1.30'):
raise errors.InvalidVersion(
'Data address path is only available for '
'API version >= 1.30'
)
data['DataPathAddr'] = data_path_addr

url = self._url('/swarm/join')
response = self._post_json(url, data=data)
self._raise_for_status(response)
Expand Down
7 changes: 5 additions & 2 deletions docker/models/swarm.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def get_unlock_key(self):

def init(self, advertise_addr=None, listen_addr='0.0.0.0:2377',
force_new_cluster=False, default_addr_pool=None,
subnet_size=None, **kwargs):
subnet_size=None, data_path_addr=None, **kwargs):
"""
Initialize a new swarm on this Engine.

Expand Down Expand Up @@ -63,6 +63,8 @@ def init(self, advertise_addr=None, listen_addr='0.0.0.0:2377',
Default: None
subnet_size (int): SubnetSize specifies the subnet size of the
networks created from the default subnet pool. Default: None
data_path_addr (string): Address or interface to use for data path
traffic. For example, 192.168.1.1, or an interface, like eth0.
task_history_retention_limit (int): Maximum number of tasks
history stored.
snapshot_interval (int): Number of logs entries between snapshot.
Expand Down Expand Up @@ -117,7 +119,8 @@ def init(self, advertise_addr=None, listen_addr='0.0.0.0:2377',
'listen_addr': listen_addr,
'force_new_cluster': force_new_cluster,
'default_addr_pool': default_addr_pool,
'subnet_size': subnet_size
'subnet_size': subnet_size,
'data_path_addr': data_path_addr,
}
init_kwargs['swarm_spec'] = self.client.api.create_swarm_spec(**kwargs)
self.client.api.init_swarm(**init_kwargs)
Expand Down
4 changes: 4 additions & 0 deletions tests/integration/api_swarm_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,7 @@ def test_remove_main_node(self):
self.client.remove_node(node_id, True)

assert e.value.response.status_code >= 400

@requires_api_version('1.30')
def test_init_swarm_data_path_addr(self):
assert self.init_swarm(data_path_addr='eth0')
12 changes: 12 additions & 0 deletions tests/integration/models_swarm_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,15 @@ def test_init_update_leave(self):
cm.value.response.status_code == 406 or
cm.value.response.status_code == 503
)

def test_join_on_already_joined_swarm(self):
client = docker.from_env(version=TEST_API_VERSION)
client.swarm.init()
join_token = client.swarm.attrs['JoinTokens']['Manager']
with pytest.raises(docker.errors.APIError) as cm:
client.swarm.join(
remote_addrs=['127.0.0.1'],
join_token=join_token,
)
assert cm.value.response.status_code == 503
assert 'This node is already part of a swarm.' in cm.value.explanation