import string
from typing import List, Dict, Optional, Callable, Tuple, TypeVar, \
- Any, Set, TYPE_CHECKING, cast, Iterator, NamedTuple
+ Any, Set, TYPE_CHECKING, cast, Iterator, NamedTuple, Sequence
import datetime
import os
}
@trivial_completion
- def plan(self, specs: List[GenericSpec]) -> List:
+ def plan(self, specs: Sequence[GenericSpec]) -> List:
results = [{'warning': 'WARNING! Dry-Runs are snapshots of a certain point in time and are bound \n'
'to the current inventory setup. If any on these conditions changes, the \n'
'preview will be invalid. Please make sure to have a minimal \n'
return "Scheduled %s update..." % spec.service_name()
@trivial_completion
- def apply(self, specs: List[GenericSpec]) -> List[str]:
+ def apply(self, specs: Sequence[GenericSpec]) -> List[str]:
results = []
for spec in specs:
results.append(self._apply(spec))
"""
raise NotImplementedError()
- def apply(self, specs: List["GenericSpec"]) -> Completion[List[str]]:
+ def apply(self, specs: Sequence["GenericSpec"]) -> Completion[List[str]]:
"""
Applies any spec
"""
completion = completion.then(next)
return completion
- def plan(self, spec: List["GenericSpec"]) -> Completion[List]:
+ def plan(self, spec: Sequence["GenericSpec"]) -> Completion[List]:
"""
Plan (Dry-run, Preview) a List of Specs.
"""
raise OrchestratorValidationError(usage)
spec = ServiceSpec.from_json(yaml.safe_load(inbuf))
else:
- spec = PlacementSpec.from_string(placement)
- assert daemon_type
- spec = ServiceSpec(daemon_type.value, placement=spec)
+ if not placement or not daemon_type:
+ raise OrchestratorValidationError(usage)
+ placement_spec = PlacementSpec.from_string(placement)
+ spec = ServiceSpec(daemon_type.value, placement=placement_spec)
if daemon_type == ServiceType.mon:
completion = self.add_mon(spec)
elif daemon_type == ServiceType.mds:
completion = self.add_mds(spec)
elif daemon_type == ServiceType.rgw:
- completion = self.add_rgw(spec)
+ completion = self.add_rgw(cast(RGWSpec, spec))
elif daemon_type == ServiceType.nfs:
- completion = self.add_nfs(spec)
+ completion = self.add_nfs(cast(NFSServiceSpec, spec))
elif daemon_type == ServiceType.iscsi:
- completion = self.add_iscsi(spec)
+ completion = self.add_iscsi(cast(IscsiServiceSpec, spec))
elif daemon_type == ServiceType.cephadm_exporter:
completion = self.add_cephadm_exporter(spec)
else:
import re
from collections import namedtuple, OrderedDict
from functools import wraps
-from typing import Optional, Dict, Any, List, Union, Callable, Iterable
+from typing import Optional, Dict, Any, List, Union, Callable, Iterable, Type, TypeVar, cast
import yaml
from ceph.deployment.hostspec import HostSpec
from ceph.deployment.utils import unwrap_ipv6
+ServiceSpecT = TypeVar('ServiceSpecT', bound='ServiceSpec')
+FuncT = TypeVar('FuncT', bound=Callable)
+
class ServiceSpecValidationError(Exception):
"""
raise ServiceSpecValidationError(e)
-def handle_type_error(method):
+def handle_type_error(method: FuncT) -> FuncT:
@wraps(method)
def inner(cls, *args, **kwargs):
try:
except (TypeError, AttributeError) as e:
error_msg = '{}: {}'.format(cls.__name__, e)
raise ServiceSpecValidationError(error_msg)
- return inner
+ return cast(FuncT, inner)
class HostPlacementSpec(namedtuple('HostPlacementSpec', ['hostname', 'network', 'name'])):
@classmethod
@handle_type_error
- def from_json(cls, json_spec):
- # type: (dict) -> Any
- # Python 3:
- # >>> ServiceSpecs = TypeVar('Base', bound=ServiceSpec)
- # then, the real type is: (dict) -> ServiceSpecs
+ def from_json(cls: Type[ServiceSpecT], json_spec: Dict) -> ServiceSpecT:
"""
Initialize 'ServiceSpec' object data from a json structure