mirror of https://github.com/docker/docker-py.git
Update SwarmSpec to include new parameters
Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
parent
1ce93ac6e7
commit
11a260225c
|
@ -9,8 +9,8 @@ class SwarmApiMixin(object):
|
||||||
|
|
||||||
def create_swarm_spec(self, *args, **kwargs):
|
def create_swarm_spec(self, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Create a ``docker.types.SwarmSpec`` instance that can be used as the
|
Create a :py:class:`docker.types.SwarmSpec` instance that can be used
|
||||||
``swarm_spec`` argument in
|
as the ``swarm_spec`` argument in
|
||||||
:py:meth:`~docker.api.swarm.SwarmApiMixin.init_swarm`.
|
:py:meth:`~docker.api.swarm.SwarmApiMixin.init_swarm`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -29,13 +29,25 @@ class SwarmApiMixin(object):
|
||||||
dispatcher_heartbeat_period (int): The delay for an agent to send
|
dispatcher_heartbeat_period (int): The delay for an agent to send
|
||||||
a heartbeat to the dispatcher.
|
a heartbeat to the dispatcher.
|
||||||
node_cert_expiry (int): Automatic expiry for nodes certificates.
|
node_cert_expiry (int): Automatic expiry for nodes certificates.
|
||||||
external_ca (dict): Configuration for forwarding signing requests
|
external_cas (:py:class:`list`): Configuration for forwarding
|
||||||
to an external certificate authority. Use
|
signing requests to an external certificate authority. Use
|
||||||
``docker.types.SwarmExternalCA``.
|
a list of :py:class:`docker.types.SwarmExternalCA`.
|
||||||
name (string): Swarm's name
|
name (string): Swarm's name
|
||||||
|
labels (dict): User-defined key/value metadata.
|
||||||
|
signing_ca_cert (str): The desired signing CA certificate for all
|
||||||
|
swarm node TLS leaf certificates, in PEM format.
|
||||||
|
signing_ca_key (str): The desired signing CA key for all swarm
|
||||||
|
node TLS leaf certificates, in PEM format.
|
||||||
|
ca_force_rotate (int): An integer whose purpose is to force swarm
|
||||||
|
to generate a new signing CA certificate and key, if none have
|
||||||
|
been specified.
|
||||||
|
autolock_managers (boolean): If set, generate a key and use it to
|
||||||
|
lock data stored on the managers.
|
||||||
|
log_driver (DriverConfig): The default log driver to use for tasks
|
||||||
|
created in the orchestrator.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
``docker.types.SwarmSpec`` instance.
|
:py:class:`docker.types.SwarmSpec`
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:py:class:`docker.errors.APIError`
|
:py:class:`docker.errors.APIError`
|
||||||
|
@ -51,7 +63,10 @@ class SwarmApiMixin(object):
|
||||||
force_new_cluster=False, swarm_spec=spec
|
force_new_cluster=False, swarm_spec=spec
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
return types.SwarmSpec(*args, **kwargs)
|
ext_ca = kwargs.pop('external_ca', None)
|
||||||
|
if ext_ca:
|
||||||
|
kwargs['external_cas'] = [ext_ca]
|
||||||
|
return types.SwarmSpec(self._version, *args, **kwargs)
|
||||||
|
|
||||||
@utils.minimum_version('1.24')
|
@utils.minimum_version('1.24')
|
||||||
def init_swarm(self, advertise_addr=None, listen_addr='0.0.0.0:2377',
|
def init_swarm(self, advertise_addr=None, listen_addr='0.0.0.0:2377',
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
from docker.api import APIClient
|
from docker.api import APIClient
|
||||||
from docker.errors import APIError
|
from docker.errors import APIError
|
||||||
from docker.types import SwarmSpec
|
|
||||||
from .resource import Model
|
from .resource import Model
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,6 +71,18 @@ class Swarm(Model):
|
||||||
to an external certificate authority. Use
|
to an external certificate authority. Use
|
||||||
``docker.types.SwarmExternalCA``.
|
``docker.types.SwarmExternalCA``.
|
||||||
name (string): Swarm's name
|
name (string): Swarm's name
|
||||||
|
labels (dict): User-defined key/value metadata.
|
||||||
|
signing_ca_cert (str): The desired signing CA certificate for all
|
||||||
|
swarm node TLS leaf certificates, in PEM format.
|
||||||
|
signing_ca_key (str): The desired signing CA key for all swarm
|
||||||
|
node TLS leaf certificates, in PEM format.
|
||||||
|
ca_force_rotate (int): An integer whose purpose is to force swarm
|
||||||
|
to generate a new signing CA certificate and key, if none have
|
||||||
|
been specified.
|
||||||
|
autolock_managers (boolean): If set, generate a key and use it to
|
||||||
|
lock data stored on the managers.
|
||||||
|
log_driver (DriverConfig): The default log driver to use for tasks
|
||||||
|
created in the orchestrator.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
``True`` if the request went through.
|
``True`` if the request went through.
|
||||||
|
@ -94,7 +105,7 @@ class Swarm(Model):
|
||||||
'listen_addr': listen_addr,
|
'listen_addr': listen_addr,
|
||||||
'force_new_cluster': force_new_cluster
|
'force_new_cluster': force_new_cluster
|
||||||
}
|
}
|
||||||
init_kwargs['swarm_spec'] = SwarmSpec(**kwargs)
|
init_kwargs['swarm_spec'] = self.client.api.create_swarm_spec(**kwargs)
|
||||||
self.client.api.init_swarm(**init_kwargs)
|
self.client.api.init_swarm(**init_kwargs)
|
||||||
self.reload()
|
self.reload()
|
||||||
|
|
||||||
|
@ -143,7 +154,7 @@ class Swarm(Model):
|
||||||
|
|
||||||
return self.client.api.update_swarm(
|
return self.client.api.update_swarm(
|
||||||
version=self.version,
|
version=self.version,
|
||||||
swarm_spec=SwarmSpec(**kwargs),
|
swarm_spec=self.client.api.create_swarm_spec(**kwargs),
|
||||||
rotate_worker_token=rotate_worker_token,
|
rotate_worker_token=rotate_worker_token,
|
||||||
rotate_manager_token=rotate_manager_token
|
rotate_manager_token=rotate_manager_token
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,9 +1,21 @@
|
||||||
|
from ..errors import InvalidVersion
|
||||||
|
from ..utils import version_lt
|
||||||
|
|
||||||
|
|
||||||
class SwarmSpec(dict):
|
class SwarmSpec(dict):
|
||||||
def __init__(self, task_history_retention_limit=None,
|
"""
|
||||||
|
Describe a Swarm's configuration and options. Use
|
||||||
|
:py:meth:`~docker.api.swarm.SwarmApiMixin.create_swarm_spec`
|
||||||
|
to instantiate.
|
||||||
|
"""
|
||||||
|
def __init__(self, version, task_history_retention_limit=None,
|
||||||
snapshot_interval=None, keep_old_snapshots=None,
|
snapshot_interval=None, keep_old_snapshots=None,
|
||||||
log_entries_for_slow_followers=None, heartbeat_tick=None,
|
log_entries_for_slow_followers=None, heartbeat_tick=None,
|
||||||
election_tick=None, dispatcher_heartbeat_period=None,
|
election_tick=None, dispatcher_heartbeat_period=None,
|
||||||
node_cert_expiry=None, external_ca=None, name=None):
|
node_cert_expiry=None, external_cas=None, name=None,
|
||||||
|
labels=None, signing_ca_cert=None, signing_ca_key=None,
|
||||||
|
ca_force_rotate=None, autolock_managers=None,
|
||||||
|
log_driver=None):
|
||||||
if task_history_retention_limit is not None:
|
if task_history_retention_limit is not None:
|
||||||
self['Orchestration'] = {
|
self['Orchestration'] = {
|
||||||
'TaskHistoryRetentionLimit': task_history_retention_limit
|
'TaskHistoryRetentionLimit': task_history_retention_limit
|
||||||
|
@ -26,18 +38,82 @@ class SwarmSpec(dict):
|
||||||
'HeartbeatPeriod': dispatcher_heartbeat_period
|
'HeartbeatPeriod': dispatcher_heartbeat_period
|
||||||
}
|
}
|
||||||
|
|
||||||
if node_cert_expiry or external_ca:
|
ca_config = {}
|
||||||
self['CAConfig'] = {
|
if node_cert_expiry is not None:
|
||||||
'NodeCertExpiry': node_cert_expiry,
|
ca_config['NodeCertExpiry'] = node_cert_expiry
|
||||||
'ExternalCA': external_ca
|
if external_cas:
|
||||||
}
|
if version_lt(version, '1.25'):
|
||||||
|
if len(external_cas) > 1:
|
||||||
|
raise InvalidVersion(
|
||||||
|
'Support for multiple external CAs is not available '
|
||||||
|
'for API version < 1.25'
|
||||||
|
)
|
||||||
|
ca_config['ExternalCA'] = external_cas[0]
|
||||||
|
else:
|
||||||
|
ca_config['ExternalCAs'] = external_cas
|
||||||
|
if signing_ca_key:
|
||||||
|
if version_lt(version, '1.30'):
|
||||||
|
raise InvalidVersion(
|
||||||
|
'signing_ca_key is not supported in API version < 1.30'
|
||||||
|
)
|
||||||
|
ca_config['SigningCAKey'] = signing_ca_key
|
||||||
|
if signing_ca_cert:
|
||||||
|
if version_lt(version, '1.30'):
|
||||||
|
raise InvalidVersion(
|
||||||
|
'signing_ca_cert is not supported in API version < 1.30'
|
||||||
|
)
|
||||||
|
ca_config['SigningCACert'] = signing_ca_cert
|
||||||
|
if ca_force_rotate is not None:
|
||||||
|
if version_lt(version, '1.30'):
|
||||||
|
raise InvalidVersion(
|
||||||
|
'force_rotate is not supported in API version < 1.30'
|
||||||
|
)
|
||||||
|
ca_config['ForceRotate'] = ca_force_rotate
|
||||||
|
if ca_config:
|
||||||
|
self['CAConfig'] = ca_config
|
||||||
|
|
||||||
|
if autolock_managers is not None:
|
||||||
|
if version_lt(version, '1.25'):
|
||||||
|
raise InvalidVersion(
|
||||||
|
'autolock_managers is not supported in API version < 1.25'
|
||||||
|
)
|
||||||
|
|
||||||
|
self['EncryptionConfig'] = {'AutoLockManagers': autolock_managers}
|
||||||
|
|
||||||
|
if log_driver is not None:
|
||||||
|
if version_lt(version, '1.25'):
|
||||||
|
raise InvalidVersion(
|
||||||
|
'log_driver is not supported in API version < 1.25'
|
||||||
|
)
|
||||||
|
|
||||||
|
self['TaskDefaults'] = {'LogDriver': log_driver}
|
||||||
|
|
||||||
if name is not None:
|
if name is not None:
|
||||||
self['Name'] = name
|
self['Name'] = name
|
||||||
|
if labels is not None:
|
||||||
|
self['Labels'] = labels
|
||||||
|
|
||||||
|
|
||||||
class SwarmExternalCA(dict):
|
class SwarmExternalCA(dict):
|
||||||
def __init__(self, url, protocol=None, options=None):
|
"""
|
||||||
|
Configuration for forwarding signing requests to an external
|
||||||
|
certificate authority.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
url (string): URL where certificate signing requests should be
|
||||||
|
sent.
|
||||||
|
protocol (string): Protocol for communication with the external CA.
|
||||||
|
options (dict): An object with key/value pairs that are interpreted
|
||||||
|
as protocol-specific options for the external CA driver.
|
||||||
|
ca_cert (string): The root CA certificate (in PEM format) this
|
||||||
|
external CA uses to issue TLS certificates (assumed to be to
|
||||||
|
the current swarm root CA certificate if not provided).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
def __init__(self, url, protocol=None, options=None, ca_cert=None):
|
||||||
self['URL'] = url
|
self['URL'] = url
|
||||||
self['Protocol'] = protocol
|
self['Protocol'] = protocol
|
||||||
self['Options'] = options
|
self['Options'] = options
|
||||||
|
self['CACert'] = ca_cert
|
||||||
|
|
|
@ -147,5 +147,7 @@ Configuration types
|
||||||
.. autoclass:: RestartPolicy
|
.. autoclass:: RestartPolicy
|
||||||
.. autoclass:: SecretReference
|
.. autoclass:: SecretReference
|
||||||
.. autoclass:: ServiceMode
|
.. autoclass:: ServiceMode
|
||||||
|
.. autoclass:: SwarmExternalCA
|
||||||
|
.. autoclass:: SwarmSpec(*args, **kwargs)
|
||||||
.. autoclass:: TaskTemplate
|
.. autoclass:: TaskTemplate
|
||||||
.. autoclass:: UpdateConfig
|
.. autoclass:: UpdateConfig
|
||||||
|
|
|
@ -45,6 +45,44 @@ class SwarmTest(BaseAPIIntegrationTest):
|
||||||
assert swarm_info['Spec']['Raft']['SnapshotInterval'] == 5000
|
assert swarm_info['Spec']['Raft']['SnapshotInterval'] == 5000
|
||||||
assert swarm_info['Spec']['Raft']['LogEntriesForSlowFollowers'] == 1200
|
assert swarm_info['Spec']['Raft']['LogEntriesForSlowFollowers'] == 1200
|
||||||
|
|
||||||
|
@requires_api_version('1.30')
|
||||||
|
def test_init_swarm_with_ca_config(self):
|
||||||
|
spec = self.client.create_swarm_spec(
|
||||||
|
node_cert_expiry=7776000000000000, ca_force_rotate=6000000000000
|
||||||
|
)
|
||||||
|
|
||||||
|
assert self.init_swarm(swarm_spec=spec)
|
||||||
|
swarm_info = self.client.inspect_swarm()
|
||||||
|
assert swarm_info['Spec']['CAConfig']['NodeCertExpiry'] == (
|
||||||
|
spec['CAConfig']['NodeCertExpiry']
|
||||||
|
)
|
||||||
|
assert swarm_info['Spec']['CAConfig']['ForceRotate'] == (
|
||||||
|
spec['CAConfig']['ForceRotate']
|
||||||
|
)
|
||||||
|
|
||||||
|
@requires_api_version('1.25')
|
||||||
|
def test_init_swarm_with_autolock_managers(self):
|
||||||
|
spec = self.client.create_swarm_spec(autolock_managers=True)
|
||||||
|
assert self.init_swarm(swarm_spec=spec)
|
||||||
|
swarm_info = self.client.inspect_swarm()
|
||||||
|
|
||||||
|
assert (
|
||||||
|
swarm_info['Spec']['EncryptionConfig']['AutoLockManagers'] is True
|
||||||
|
)
|
||||||
|
|
||||||
|
@requires_api_version('1.25')
|
||||||
|
@pytest.mark.xfail(
|
||||||
|
reason="This doesn't seem to be taken into account by the engine"
|
||||||
|
)
|
||||||
|
def test_init_swarm_with_log_driver(self):
|
||||||
|
spec = {'TaskDefaults': {'LogDriver': {'Name': 'syslog'}}}
|
||||||
|
assert self.init_swarm(swarm_spec=spec)
|
||||||
|
swarm_info = self.client.inspect_swarm()
|
||||||
|
|
||||||
|
assert swarm_info['Spec']['TaskDefaults']['LogDriver']['Name'] == (
|
||||||
|
'syslog'
|
||||||
|
)
|
||||||
|
|
||||||
@requires_api_version('1.24')
|
@requires_api_version('1.24')
|
||||||
def test_leave_swarm(self):
|
def test_leave_swarm(self):
|
||||||
assert self.init_swarm()
|
assert self.init_swarm()
|
||||||
|
|
Loading…
Reference in New Issue