]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
pybind/mgr/hello: add typing annotation
authorKefu Chai <kchai@redhat.com>
Fri, 29 Jan 2021 16:48:36 +0000 (00:48 +0800)
committerKefu Chai <kchai@redhat.com>
Wed, 3 Feb 2021 09:17:24 +0000 (17:17 +0800)
also, use Option and CLIReadCommand to define options and cli
commands. this module serves as a "hello world" example for
developers of mgr modules. so it's important to use the more
convenient and safer way to implement the module

Signed-off-by: Kefu Chai <kchai@redhat.com>
src/mypy.ini
src/pybind/mgr/hello/module.py
src/pybind/mgr/tox.ini

index a10f9e4b3f26d1ec8bbe6d644911ddb8147763e8..afdb6d528e5be1fb692389b1d3aec3c21ab9fabb 100755 (executable)
@@ -30,6 +30,9 @@ disallow_untyped_defs = True
 [mypy-devicehealth.*]
 disallow_untyped_defs = True
 
+[mypy-hello.*]
+disallow_untyped_defs = True
+
 [mypy-iostat.*]
 disallow_untyped_defs = True
 
index b164dfb620d0f4c15b28f6051902f487f532996a..395a1bee1584a137b38d62675d085076bfff2352 100644 (file)
@@ -5,27 +5,13 @@ A hello world module
 See doc/mgr/hello.rst for more info.
 """
 
-from mgr_module import MgrModule, HandleCommandResult
+from mgr_module import CLIReadCommand, HandleCommandResult, MgrModule, Option
 from threading import Event
+from typing import cast, Any, Optional, TYPE_CHECKING
 import errno
 
-class Hello(MgrModule):
-    # these are CLI commands we implement
-    COMMANDS = [
-        {
-            "cmd": "hello "
-                   "name=person_name,type=CephString,req=false",
-            "desc": "Say hello",
-            "perm": "r"
-        },
-        {
-            "cmd": "count "
-                   "name=num,type=CephInt",
-            "desc": "Do some counting",
-            "perm": "r"
-        },
-    ]
 
+class Hello(MgrModule):
     # These are module options we understand.  These can be set with
     #
     #   ceph config set global mgr/hello/<name> <value>
@@ -35,26 +21,20 @@ class Hello(MgrModule):
     #   ceph config set global mgr/hello/place Earth
     #
     MODULE_OPTIONS = [
-        {
-            'name': 'place',
-            'default': 'world',
-            'desc': 'a place in the world',
-            'runtime': True,   # can be updated at runtime (no mgr restart)
-        },
-        {
-            'name': 'emphatic',
-            'type': 'bool',
-            'desc': 'whether to say it loudly',
-            'default': True,
-            'runtime': True,
-        },
-        {
-            'name': 'foo',
-            'type': 'enum',
-            'enum_allowed': [ 'a', 'b', 'c' ],
-            'default': 'a',
-            'runtime': True,
-        },
+        Option(name='place',
+               default='world',
+               desc='a place in the world',
+               runtime=True),   # can be updated at runtime (no mgr restart)
+        Option(name='emphatic',
+               type='bool',
+               desc='whether to say it loudly',
+               default=True,
+               runtime=True),
+        Option(name='foo',
+               type='str',
+               enum_allowed=['a', 'b', 'c'],
+               default='a',
+               runtime=True)
     ]
 
     # These are "native" Ceph options that this module cares about.
@@ -62,8 +42,8 @@ class Hello(MgrModule):
         'mgr_tick_period',
     ]
 
-    def __init__(self, *args, **kwargs):
-        super(Hello, self).__init__(*args, **kwargs)
+    def __init__(self, *args: Any, **kwargs: Any):
+        super().__init__(*args, **kwargs)
 
         # set up some members to enable the serve() method and shutdown()
         self.run = True
@@ -72,8 +52,11 @@ class Hello(MgrModule):
         # ensure config options members are initialized; see config_notify()
         self.config_notify()
 
+        # for mypy which does not run the code
+        if TYPE_CHECKING:
+            self.mgr_tick_period = 0
 
-    def config_notify(self):
+    def config_notify(self) -> None:
         """
         This method is called whenever one of our config options is changed.
         """
@@ -93,34 +76,43 @@ class Hello(MgrModule):
                     self.get_ceph_option(opt))
             self.log.debug(' native option %s = %s', opt, getattr(self, opt))
 
-    def handle_command(self, inbuf, cmd):
+    # there are CLI commands we implement
+    @CLIReadCommand('hello')
+    def hello(self, person_name: Optional[str] = None) -> HandleCommandResult:
+        """
+        Say hello
+        """
+        out = ''
+        if person_name is None:
+            out = 'Hello, ' + cast(str, self.get_module_option('place'))
+        else:
+            out = f'Hello, {person_name}'
+        if self.get_module_option('emphatic'):
+            out += '!'
+        return HandleCommandResult(stdout=out)
+
+    @CLIReadCommand('count')
+    def count(self, num: int) -> HandleCommandResult:
+        """
+        Do some counting
+        """
         ret = 0
         out = ''
         err = ''
-        if cmd['prefix'] == 'hello':
-            if 'person_name' in cmd:
-                out = "Hello, " + cmd['person_name']
-            else:
-                out = "Hello " + self.get_module_option('place')
-            if self.get_module_option('emphatic'):
-                out += '!'
-        elif cmd['prefix'] == 'count':
-            num = cmd.get('num', 0)
-            if num < 1:
-                err = 'That\'s too small a number'
-                ret = -errno.EINVAL
-            elif num > 10:
-                err = 'That\'s too big a number'
-                ret = -errno.EINVAL
-            else:
-                out = 'Hello, I am the count!\n'
-                out += ', '.join([str(x) for x in range(1, num + 1)]) + '!'
-        return HandleCommandResult(
-            retval=ret,   # exit code
-            stdout=out,   # stdout
-            stderr=err)
-
-    def serve(self):
+        if num < 1:
+            err = 'That\'s too small a number'
+            ret = -errno.EINVAL
+        elif num > 10:
+            err = 'That\'s too big a number'
+            ret = -errno.EINVAL
+        else:
+            out = 'Hello, I am the count!\n'
+            out += ', '.join([str(x) for x in range(1, num + 1)]) + '!'
+        return HandleCommandResult(retval=ret,
+                                   stdout=out,
+                                   stderr=err)
+
+    def serve(self) -> None:
         """
         This method is called by the mgr when the module starts and can be
         used for any background activity.
@@ -134,10 +126,10 @@ class Hello(MgrModule):
             # would presumably have some more appropriate frequency.
             sleep_interval = self.mgr_tick_period
             self.log.debug('Sleeping for %d seconds', sleep_interval)
-            ret = self.event.wait(sleep_interval)
+            self.event.wait(sleep_interval)
             self.event.clear()
 
-    def shutdown(self):
+    def shutdown(self) -> None:
         """
         This method is called by the mgr when the module needs to shut
         down (i.e., when the serve() function needs to exit).
index baa45111b7eae9f77b7d5ff2dce98f678c172582..b0916a2299e15592ff921d9e63ba35dd2a1887c8 100644 (file)
@@ -59,6 +59,7 @@ commands =
            -m cephadm \
            -m dashboard \
            -m devicehealth \
+           -m hello \
            -m iostat \
            -m mds_autoscaler \
            -m mgr_module \