]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/cephadm: SNMP: use of python3 enums
authorSebastian Wagner <sewagner@redhat.com>
Thu, 16 Dec 2021 16:43:47 +0000 (17:43 +0100)
committerSebastian Wagner <sewagner@redhat.com>
Wed, 5 Jan 2022 09:23:01 +0000 (10:23 +0100)
Little reason to duplicate things ourselves

Signed-off-by: Sebastian Wagner <sewagner@redhat.com>
src/pybind/mgr/cephadm/tests/test_spec.py
src/pybind/mgr/orchestrator/module.py
src/python-common/ceph/deployment/service_spec.py
src/python-common/ceph/tests/test_service_spec.py

index 8697d19533f5293670a706f2b03de2ee4a9b761f..155641855ce478d5d247111a045e6970a7474187 100644 (file)
@@ -707,7 +707,7 @@ auth_protocol: SHA
 privacy_protocol: weewah
 snmp_destination: 192.168.1.42:162
 snmp_version: V3
-"""), 'privacy_protocol unsupported. Must be one of AES, DES'),
+"""), 'privacy_protocol unsupported. Must be one of DES, AES'),
         (YAMLdoc("""
 ---
 service_type: snmp-gateway
index febe13b8b63ca1d39bce49a8412259517d061205..9c252a35887cdc31d7762c9d20f12f5b185f7f7a 100644 (file)
@@ -11,7 +11,7 @@ from prettytable import PrettyTable
 from ceph.deployment.inventory import Device
 from ceph.deployment.drive_group import DriveGroupSpec, DeviceSelection, OSDMethod
 from ceph.deployment.service_spec import PlacementSpec, ServiceSpec, service_spec_allow_invalid_from_json, \
-    SNMPGatewaySpec, SNMPVersion, SNMPAuthType, SNMPPrivacyType
+    SNMPGatewaySpec
 from ceph.deployment.hostspec import SpecValidationError
 from ceph.utils import datetime_now
 
@@ -1151,12 +1151,12 @@ Usage:
 
     @_cli_write_command('orch apply snmp-gateway')
     def _apply_snmp_gateway(self,
-                            snmp_version: SNMPVersion,
+                            snmp_version: SNMPGatewaySpec.SNMPVersion,
                             destination: str,
                             port: int = 9464,
                             engine_id: Optional[str] = None,
-                            auth_protocol: Optional[SNMPAuthType] = None,
-                            privacy_protocol: Optional[SNMPPrivacyType] = None,
+                            auth_protocol: Optional[SNMPGatewaySpec.SNMPAuthType] = None,
+                            privacy_protocol: Optional[SNMPGatewaySpec.SNMPPrivacyType] = None,
                             placement: Optional[str] = None,
                             unmanaged: bool = False,
                             dry_run: bool = False,
@@ -1175,17 +1175,14 @@ Usage:
         except (OSError, yaml.YAMLError):
             raise OrchestratorValidationError('credentials file must be valid YAML')
 
-        auth = None if not auth_protocol else auth_protocol.value
-        priv = None if not privacy_protocol else privacy_protocol.value
-
         spec = SNMPGatewaySpec(
-            snmp_version=snmp_version.value,
+            snmp_version=snmp_version,
             port=port,
             credentials=credentials,
             snmp_destination=destination,
             engine_id=engine_id,
-            auth_protocol=auth,
-            privacy_protocol=priv,
+            auth_protocol=auth_protocol,
+            privacy_protocol=privacy_protocol,
             placement=PlacementSpec.from_string(placement),
             unmanaged=unmanaged,
             preview_only=dry_run
index f3bd4619ed03fd52f76e73dd808f47dcc8f15d1e..d45a460c904954f93f5681235025567eec338e8b 100644 (file)
@@ -18,21 +18,6 @@ ServiceSpecT = TypeVar('ServiceSpecT', bound='ServiceSpec')
 FuncT = TypeVar('FuncT', bound=Callable)
 
 
-class SNMPVersion(enum.Enum):
-    V2c = 'V2c'
-    V3 = 'V3'
-
-
-class SNMPAuthType(enum.Enum):
-    MD5 = 'MD5'
-    SHA = 'SHA'
-
-
-class SNMPPrivacyType(enum.Enum):
-    DES = 'DES'
-    AES = 'AES'
-
-
 def handle_type_error(method: FuncT) -> FuncT:
     @wraps(method)
     def inner(cls: Any, *args: Any, **kwargs: Any) -> Any:
@@ -1164,6 +1149,27 @@ yaml.add_representer(GrafanaSpec, ServiceSpec.yaml_representer)
 
 
 class SNMPGatewaySpec(ServiceSpec):
+    class SNMPVersion(str, enum.Enum):
+        V2c = 'V2c'
+        V3 = 'V3'
+
+        def to_json(self) -> str:
+            return self.value
+
+    class SNMPAuthType(str, enum.Enum):
+        MD5 = 'MD5'
+        SHA = 'SHA'
+
+        def to_json(self) -> str:
+            return self.value
+
+    class SNMPPrivacyType(str, enum.Enum):
+        DES = 'DES'
+        AES = 'AES'
+
+        def to_json(self) -> str:
+            return self.value
+
     valid_destination_types = [
         'Name:Port',
         'IPv4:Port'
@@ -1171,12 +1177,12 @@ class SNMPGatewaySpec(ServiceSpec):
 
     def __init__(self,
                  service_type: str = 'snmp-gateway',
-                 snmp_version: Optional[str] = None,
+                 snmp_version: Optional[SNMPVersion] = None,
                  snmp_destination: str = '',
                  credentials: Dict[str, str] = {},
                  engine_id: Optional[str] = None,
-                 auth_protocol: Optional[str] = None,
-                 privacy_protocol: Optional[str] = None,
+                 auth_protocol: Optional[SNMPAuthType] = None,
+                 privacy_protocol: Optional[SNMPPrivacyType] = None,
                  placement: Optional[PlacementSpec] = None,
                  unmanaged: bool = False,
                  preview_only: bool = False,
@@ -1199,6 +1205,25 @@ class SNMPGatewaySpec(ServiceSpec):
         self.auth_protocol = auth_protocol
         self.privacy_protocol = privacy_protocol
 
+    @classmethod
+    def _from_json_impl(cls, json_spec: dict) -> 'SNMPGatewaySpec':
+
+        cpy = json_spec.copy()
+        types = [
+            ('snmp_version', SNMPGatewaySpec.SNMPVersion),
+            ('auth_protocol', SNMPGatewaySpec.SNMPAuthType),
+            ('privacy_protocol', SNMPGatewaySpec.SNMPPrivacyType),
+        ]
+        for d in cpy, cpy.get('spec', {}):
+            for key, enum_cls in types:
+                try:
+                    if key in d:
+                        d[key] = enum_cls(d[key])
+                except ValueError:
+                    raise SpecValidationError(f'{key} unsupported. Must be one of '
+                                              f'{", ".join(enum_cls)}')
+        return super(SNMPGatewaySpec, cls)._from_json_impl(cpy)
+
     @property
     def ports(self) -> List[int]:
         return [self.port]
@@ -1209,14 +1234,6 @@ class SNMPGatewaySpec(ServiceSpec):
     def validate(self) -> None:
         super(SNMPGatewaySpec, self).validate()
 
-        def _check_type(name: str, value: Optional[str], options: List[str]) -> None:
-            if not value:
-                return
-            if value not in options:
-                raise SpecValidationError(
-                    f'{name} unsupported. Must be one of {", ".join(sorted(options))}'
-                )
-
         if not self.credentials:
             raise SpecValidationError(
                 'Missing authentication information (credentials). '
@@ -1227,16 +1244,6 @@ class SNMPGatewaySpec(ServiceSpec):
                 'Missing SNMP version (snmp_version)'
             )
 
-        _check_type('snmp_version',
-                    self.snmp_version,
-                    list(set(opt.value for opt in SNMPVersion)))
-        _check_type('auth_protocol',
-                    self.auth_protocol,
-                    list(set(opt.value for opt in SNMPAuthType)))
-        _check_type('privacy_protocol',
-                    self.privacy_protocol,
-                    list(set(opt.value for opt in SNMPPrivacyType)))
-
         creds_requirement = {
             'V2c': ['snmp_community'],
             'V3': ['snmp_v3_auth_username', 'snmp_v3_auth_password']
index 631b262be743b558a1a2632f3ab3fb0c06f33374..555ba9b894115e32c2a62669f36caecddf92fdeb 100644 (file)
@@ -572,6 +572,23 @@ service_id: foo
 placement:
   count_per_host: 0
 """, "count-per-host must be >= 1",),
+    ("""
+service_type: snmp-gateway
+service_name: snmp-gateway
+placement:
+  count: 1
+spec:
+  credentials:
+    snmp_v3_auth_password: mypassword
+    snmp_v3_auth_username: myuser
+    snmp_v3_priv_password: mysecret
+  port: 9464
+  engine_id: 8000c53f0000000000
+  privacy_protocol: WEIRD
+  snmp_destination: 192.168.122.1:162
+  auth_protocol: BIZARRE
+  snmp_version: V3
+""", "auth_protocol unsupported. Must be one of MD5, SHA"),
     ])
 def test_service_spec_validation_error(y, error_match):
     data = yaml.safe_load(y)