]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
python-common: make ServiceSpec and ServiceDescription compatible
authorSebastian Wagner <sebastian.wagner@suse.com>
Thu, 19 Mar 2020 14:17:16 +0000 (15:17 +0100)
committerSebastian Wagner <sebastian.wagner@suse.com>
Thu, 26 Mar 2020 11:02:56 +0000 (12:02 +0100)
`ServiceSpec.from_json(ServiceDescription().to_json())` now works

as does

`ceph orch ls  --format yaml | ceph orch apply -i -`

Signed-off-by: Sebastian Wagner <sebastian.wagner@suse.com>
src/python-common/ceph/deployment/service_spec.py

index 5f1251d5a2e11f4e718da0696474b66c9e7c56f3..b94be2549d84d00c2c45b15406aa98f2bdb0332e 100644 (file)
@@ -1,6 +1,7 @@
 import fnmatch
 import re
 from collections import namedtuple
+from functools import wraps
 from typing import Optional, Dict, Any, List, Union
 
 import six
@@ -28,6 +29,17 @@ def assert_valid_host(name):
         raise ServiceSpecValidationError(e)
 
 
+def handle_type_error(method):
+    @wraps(method)
+    def inner(cls, *args, **kwargs):
+        try:
+            return method(cls, *args, **kwargs)
+        except (TypeError, AttributeError) as e:
+            error_msg = '{}: {}'.format(cls.__name__, e)
+        raise ServiceSpecValidationError(error_msg)
+    return inner
+
+
 class HostPlacementSpec(namedtuple('HostPlacementSpec', ['hostname', 'network', 'name'])):
     def __str__(self):
         res = ''
@@ -39,6 +51,7 @@ class HostPlacementSpec(namedtuple('HostPlacementSpec', ['hostname', 'network',
         return res
 
     @classmethod
+    @handle_type_error
     def from_json(cls, data):
         return cls(**data)
 
@@ -189,6 +202,7 @@ class PlacementSpec(object):
         return "PlacementSpec(%s)" % ', '.join(kv)
 
     @classmethod
+    @handle_type_error
     def from_json(cls, data):
         c = data.copy()
         hosts = c.get('hosts', [])
@@ -370,6 +384,7 @@ class ServiceSpec(object):
         self.unmanaged = unmanaged
 
     @classmethod
+    @handle_type_error
     def from_json(cls, json_spec):
         # type: (dict) -> Any
         # Python 3:
@@ -383,7 +398,11 @@ class ServiceSpec(object):
         service_type = json_spec.get('service_type', '')
         _cls = cls._cls(service_type)
 
-        return _cls._from_json_impl(json_spec)  # type: ignore
+        c = json_spec.copy()
+        if 'status' in c:
+            del c['status']  # kludge to make us compatible to `ServiceDescription.to_json()`
+
+        return _cls._from_json_impl(c)  # type: ignore
 
     @classmethod
     def _from_json_impl(cls, json_spec):