]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr: api_docs.py: Update for use outside Calamari
authorTim Serong <tserong@suse.com>
Thu, 30 Jun 2016 06:38:11 +0000 (16:38 +1000)
committerJohn Spray <john.spray@redhat.com>
Thu, 29 Sep 2016 16:26:56 +0000 (17:26 +0100)
The ceph_state module is implemented in C++, and isn't available at
build time, which causes import failures when api_docs.py tries to
import calamari_rest in order to introspect it (MgrModule is eventually
imported, which in turn tries to import ceph_state, which fails unless
we stub it out).

Additional changes:

* Search calamari_rest.urls (not calamari_web)

calamari_web isn't available - it largely held static content in
Calamari, and in turn included calamari_rest.urls.  Here in ceph-mgr we
only have calamari_rest.

* note that --list-urls does nothing, apparently

* Pass actions to old as_view method

django-rest-framework 3.x raises TypeError if the actions argument isn't
passed to as_view().

* Use view().get_view_name() instead of metadata

Attempting to access view().metadata(None)['name'] results in
"AttributeError: 'super' object has no attribute 'metadata'".

* Use somewhat unfriendly field class names

django-rest-framework 3.x seems to have done away with type_label for
fields, so instead use the field's class name, which is somewhat
unfriendly, but arguably better than nothing.

* import global_instance to fix ImportError

This is necessary to avoid what seems to be weird import loops (if this
isn't present, we later get "ImportError: cannot import name
UserRequest" or similar).

* Make api_examples.json optional

This way we at least get bare docs with no examples, rather than no docs
at all.

* Explain how to generate API docs

Signed-off-by: Tim Serong <tserong@suse.com>
src/pybind/mgr/calamari_rest/management/commands/api_docs.py

index c9922ee73f2c7d7e83956e55ba821013f4e01694..bbaca1777598793dfd7b4b87fc378e0514c08a86 100644 (file)
@@ -1,3 +1,18 @@
+#
+# If Django is installed locally, run the following command from the top of
+# the ceph source tree:
+#
+#   PYTHONPATH=src/pybind/mgr \
+#   DJANGO_SETTINGS_MODULE=calamari_rest.settings \
+#   CALAMARI_CONFIG=src/pybind/mgr/calamari.conf \
+#       django-admin api_docs
+#
+# This will create resources.rst (the API docs), and rest.log (which will
+# probably just be empty).
+#
+# TODO: Add the above to a makefile, so the docs land somewhere sane.
+#
+
 from collections import defaultdict
 import json
 from optparse import make_option
@@ -12,8 +27,15 @@ from django.core.urlresolvers import RegexURLPattern, RegexURLResolver
 import sys
 import codecs
 
-from calamari_rest.serializers.v2 import ValidatingSerializer
+class ceph_state:
+    pass
+
+sys.modules["ceph_state"] = ceph_state
 
+# Needed to avoid weird import loops
+from rest import global_instance
+
+from calamari_rest.serializers.v2 import ValidatingSerializer
 
 GENERATED_PREFIX = "."
 
@@ -28,7 +50,7 @@ old_as_view = rest_framework.viewsets.ViewSetMixin.as_view
 
 @classmethod
 def as_view(cls, actions=None, **initkwargs):
-    view = old_as_view.__func__(cls)
+    view = old_as_view.__func__(cls, actions, **initkwargs)
     view._actions = actions
     return view
 
@@ -193,7 +215,7 @@ class ApiIntrospector(object):
                             continue
                         view_to_url_patterns[view_cls].append(url_pattern)
 
-        self.prefix = _find_prefix("calamari_web.urls", url_module)
+        self.prefix = _find_prefix("calamari_rest.urls", url_module)
         parse_urls(importlib.import_module(url_module).urlpatterns)
 
         self.view_to_url_patterns = sorted(view_to_url_patterns.items(), cmp=lambda x, y: cmp(x[0].__name__, y[0].__name__))
@@ -208,7 +230,7 @@ class ApiIntrospector(object):
         """
         Output RsT for one API view
         """
-        name = view().metadata(None)['name']
+        name = view().get_view_name()
 
         if view.__doc__:
             view_help_text = view.__doc__
@@ -261,7 +283,7 @@ class ApiIntrospector(object):
                     field_help_text = ""
                 field_table.append(
                     [field_name,
-                     field.type_label,
+                     field.__class__.__name__,
                      str(field.read_only),
                      create,
                      modify,
@@ -286,7 +308,7 @@ class ApiIntrospector(object):
 
                 row = [_pretty_url(self.prefix, url_pattern)]
 
-                view_name = view().metadata(None)['name']
+                view_name = view().get_view_name()
                 row.append(
                     u":ref:`{0} <{1}>`".format(view_name.replace(" ", unichr(0x00a0)), view.__name__)
                 )
@@ -368,14 +390,15 @@ class Command(NoArgsCommand):
     def handle_noargs(self, list_urls, **options):
         introspector = ApiIntrospector("calamari_rest.urls.v2")
         if list_urls:
+            # TODO: this just prints an empty array (not sure why)
             print json.dumps(introspector.get_url_list())
         else:
             try:
                 try:
                     examples = json.load(open(EXAMPLES_FILE, 'r'))
                 except IOError:
-                    print >>sys.stderr, "Examples data '%s' not found, have you run test_rest_api?" % EXAMPLES_FILE
-                    return
+                    examples = {}
+                    print >>sys.stderr, "Examples data '%s' not found, no examples will be generated" % EXAMPLES_FILE
 
                 introspector.write_docs(examples)
             except: