mirror of https://github.com/docker/docker-py.git
Update swarm methods to include newly added parameters
Rename swarm methods to be more explicit Utility methods / types to create swarm spec objects Integration tests Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
parent
9fdc8d476d
commit
07563cfe3f
|
@ -4,38 +4,49 @@ log = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class SwarmApiMixin(object):
|
||||
|
||||
def create_swarm_spec(self, *args, **kwargs):
|
||||
return utils.SwarmSpec(*args, **kwargs)
|
||||
|
||||
@utils.minimum_version('1.24')
|
||||
def swarm(self):
|
||||
def init_swarm(self, advertise_addr, listen_addr='0.0.0.0:2377',
|
||||
force_new_cluster=False, swarm_spec=None):
|
||||
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')
|
||||
data = {
|
||||
'AdvertiseAddr': advertise_addr,
|
||||
'ListenAddr': listen_addr,
|
||||
'ForceNewCluster': force_new_cluster,
|
||||
'Spec': swarm_spec,
|
||||
}
|
||||
response = self._post_json(url, data=data)
|
||||
self._raise_for_status(response)
|
||||
return True
|
||||
|
||||
@utils.minimum_version('1.24')
|
||||
def inspect_swarm(self):
|
||||
url = self._url('/swarm')
|
||||
return self._result(self._get(url), True)
|
||||
|
||||
@utils.minimum_version('1.24')
|
||||
def swarm_init(self, listen_addr, force_new_cluster=False,
|
||||
swarm_opts=None):
|
||||
url = self._url('/swarm/init')
|
||||
if swarm_opts is not None and not isinstance(swarm_opts, dict):
|
||||
raise TypeError('swarm_opts must be a dictionary')
|
||||
data = {
|
||||
'ListenAddr': listen_addr,
|
||||
'ForceNewCluster': force_new_cluster,
|
||||
'Spec': swarm_opts
|
||||
}
|
||||
return self._result(self._post_json(url, data=data), True)
|
||||
|
||||
@utils.minimum_version('1.24')
|
||||
def swarm_join(self, remote_address, listen_address=None,
|
||||
def join_swarm(self, remote_addresses, listen_address=None,
|
||||
secret=None, ca_cert_hash=None, manager=False):
|
||||
data = {
|
||||
"RemoteAddr": remote_address,
|
||||
"RemoteAddrs": remote_addresses,
|
||||
"ListenAddr": listen_address,
|
||||
"Secret": secret,
|
||||
"CACertHash": ca_cert_hash,
|
||||
"Manager": manager
|
||||
}
|
||||
url = self._url('/swarm/join', )
|
||||
return self._result(self._post_json(url, data=data), True)
|
||||
url = self._url('/swarm/join')
|
||||
response = self._post_json(url, data=data)
|
||||
self._raise_for_status(response)
|
||||
return True
|
||||
|
||||
@utils.minimum_version('1.24')
|
||||
def swarm_leave(self):
|
||||
def leave_swarm(self, force=False):
|
||||
url = self._url('/swarm/leave')
|
||||
return self._result(self._post(url))
|
||||
response = self._post(url, params={'force': force})
|
||||
self._raise_for_status(response)
|
||||
return True
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import sys
|
||||
from .version import version
|
||||
|
||||
DEFAULT_DOCKER_API_VERSION = '1.22'
|
||||
DEFAULT_DOCKER_API_VERSION = '1.24'
|
||||
DEFAULT_TIMEOUT_SECONDS = 60
|
||||
STREAM_HEADER_SIZE_BYTES = 8
|
||||
CONTAINER_LIMITS_KEYS = [
|
||||
|
|
|
@ -8,5 +8,8 @@ from .utils import (
|
|||
create_ipam_config, create_ipam_pool, parse_devices, normalize_links,
|
||||
)
|
||||
|
||||
from .types import Ulimit, LogConfig
|
||||
from .types import LogConfig, Ulimit
|
||||
from .types import (
|
||||
SwarmAcceptancePolicy, SwarmExternalCA, SwarmSpec,
|
||||
)
|
||||
from .decorators import check_resource, minimum_version, update_headers
|
||||
|
|
|
@ -94,3 +94,52 @@ class Ulimit(DictType):
|
|||
@hard.setter
|
||||
def hard(self, value):
|
||||
self['Hard'] = value
|
||||
|
||||
|
||||
class SwarmSpec(DictType):
|
||||
def __init__(self, policies=None, task_history_retention_limit=None,
|
||||
snapshot_interval=None, keep_old_snapshots=None,
|
||||
log_entries_for_slow_followers=None, heartbeat_tick=None,
|
||||
election_tick=None, dispatcher_heartbeat_period=None,
|
||||
node_cert_expiry=None, external_ca=None):
|
||||
if policies is not None:
|
||||
self['AcceptancePolicy'] = {'Policies': policies}
|
||||
if task_history_retention_limit is not None:
|
||||
self['Orchestration'] = {
|
||||
'TaskHistoryRetentionLimit': task_history_retention_limit
|
||||
}
|
||||
if any(snapshot_interval, keep_old_snapshots,
|
||||
log_entries_for_slow_followers, heartbeat_tick, election_tick):
|
||||
self['Raft'] = {
|
||||
'SnapshotInterval': snapshot_interval,
|
||||
'KeepOldSnapshots': keep_old_snapshots,
|
||||
'LogEntriesForSlowFollowers': log_entries_for_slow_followers,
|
||||
'HeartbeatTick': heartbeat_tick,
|
||||
'ElectionTick': election_tick
|
||||
}
|
||||
|
||||
if dispatcher_heartbeat_period:
|
||||
self['Dispatcher'] = {
|
||||
'HeartbeatPeriod': dispatcher_heartbeat_period
|
||||
}
|
||||
|
||||
if node_cert_expiry or external_ca:
|
||||
self['CAConfig'] = {
|
||||
'NodeCertExpiry': node_cert_expiry,
|
||||
'ExternalCA': external_ca
|
||||
}
|
||||
|
||||
|
||||
class SwarmAcceptancePolicy(DictType):
|
||||
def __init__(self, role, auto_accept=False, secret=None):
|
||||
self['Role'] = role.upper()
|
||||
self['Autoaccept'] = auto_accept
|
||||
if secret is not None:
|
||||
self['Secret'] = secret
|
||||
|
||||
|
||||
class SwarmExternalCA(DictType):
|
||||
def __init__(self, url, protocol=None, options=None):
|
||||
self['URL'] = url
|
||||
self['Protocol'] = protocol
|
||||
self['Options'] = options
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
import docker
|
||||
import pytest
|
||||
|
||||
from ..base import requires_api_version
|
||||
from .. import helpers
|
||||
|
||||
|
||||
BUSYBOX = helpers.BUSYBOX
|
||||
|
||||
|
||||
class SwarmTest(helpers.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(SwarmTest, self).setUp()
|
||||
try:
|
||||
self.client.leave_swarm(force=True)
|
||||
except docker.errors.APIError:
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
super(SwarmTest, self).tearDown()
|
||||
try:
|
||||
self.client.leave_swarm(force=True)
|
||||
except docker.errors.APIError:
|
||||
pass
|
||||
|
||||
@requires_api_version('1.24')
|
||||
def test_init_swarm_simple(self):
|
||||
assert self.client.init_swarm('eth0')
|
||||
|
||||
@requires_api_version('1.24')
|
||||
def test_init_swarm_force_new_cluster(self):
|
||||
pytest.skip('Test stalls the engine on 1.12')
|
||||
|
||||
assert self.client.init_swarm('eth0')
|
||||
version_1 = self.client.inspect_swarm()['Version']['Index']
|
||||
assert self.client.init_swarm('eth0', force_new_cluster=True)
|
||||
version_2 = self.client.inspect_swarm()['Version']['Index']
|
||||
assert version_2 != version_1
|
||||
|
||||
@requires_api_version('1.24')
|
||||
def test_init_already_in_cluster(self):
|
||||
assert self.client.init_swarm('eth0')
|
||||
with pytest.raises(docker.errors.APIError):
|
||||
self.client.init_swarm('eth0')
|
||||
|
||||
@requires_api_version('1.24')
|
||||
def test_leave_swarm(self):
|
||||
assert self.client.init_swarm('eth0')
|
||||
with pytest.raises(docker.errors.APIError) as exc_info:
|
||||
self.client.leave_swarm()
|
||||
exc_info.value.response.status_code == 500
|
||||
assert self.client.leave_swarm(force=True)
|
||||
with pytest.raises(docker.errors.APIError) as exc_info:
|
||||
self.client.inspect_swarm()
|
||||
exc_info.value.response.status_code == 406
|
Loading…
Reference in New Issue