Commit bf968b7f authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

Add simple unittest for remote API docs


Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarLuca Bigliardi <shammash@google.com>
parent f72542cc
......@@ -31,6 +31,9 @@ from ganeti import http
from ganeti.rapi import baserlib
from ganeti.rapi import rlib2
_NAME_PATTERN = r"[\w\._-]+"
# the connection map is created at the end of this file
CONNECTOR = {}
......@@ -144,44 +147,62 @@ class R_2(baserlib.R_Generic):
return baserlib.BuildUriList(_getResources("2"), "/2/%s")
CONNECTOR.update({
"/": R_root,
def GetHandlers(node_name_pattern, instance_name_pattern, job_id_pattern):
"""Returns all supported resources and their handlers.
"""
return {
"/": R_root,
"/version": rlib2.R_version,
"/version": rlib2.R_version,
"/2": R_2,
"/2": R_2,
"/2/jobs": rlib2.R_2_jobs,
"/2/nodes": rlib2.R_2_nodes,
re.compile(r'^/2/nodes/([\w\._-]+)$'): rlib2.R_2_nodes_name,
re.compile(r'^/2/nodes/([\w\._-]+)/tags$'): rlib2.R_2_nodes_name_tags,
re.compile(r'^/2/nodes/([\w\._-]+)/role$'): rlib2.R_2_nodes_name_role,
re.compile(r'^/2/nodes/([\w\._-]+)/evacuate$'):
"/2/nodes": rlib2.R_2_nodes,
re.compile(r'^/2/nodes/(%s)$' % node_name_pattern):
rlib2.R_2_nodes_name,
re.compile(r'^/2/nodes/(%s)/tags$' % node_name_pattern):
rlib2.R_2_nodes_name_tags,
re.compile(r'^/2/nodes/(%s)/role$' % node_name_pattern):
rlib2.R_2_nodes_name_role,
re.compile(r'^/2/nodes/(%s)/evacuate$' % node_name_pattern):
rlib2.R_2_nodes_name_evacuate,
re.compile(r'^/2/nodes/([\w\._-]+)/migrate$'):
re.compile(r'^/2/nodes/(%s)/migrate$' % node_name_pattern):
rlib2.R_2_nodes_name_migrate,
re.compile(r'^/2/nodes/([\w\._-]+)/storage$'):
re.compile(r'^/2/nodes/(%s)/storage$' % node_name_pattern):
rlib2.R_2_nodes_name_storage,
re.compile(r'^/2/nodes/([\w\._-]+)/storage/modify$'):
re.compile(r'^/2/nodes/(%s)/storage/modify$' % node_name_pattern):
rlib2.R_2_nodes_name_storage_modify,
re.compile(r'^/2/nodes/([\w\._-]+)/storage/repair$'):
re.compile(r'^/2/nodes/(%s)/storage/repair$' % node_name_pattern):
rlib2.R_2_nodes_name_storage_repair,
"/2/instances": rlib2.R_2_instances,
re.compile(r'^/2/instances/([\w\._-]+)$'): rlib2.R_2_instances_name,
re.compile(r'^/2/instances/([\w\._-]+)/info$'):
"/2/instances": rlib2.R_2_instances,
re.compile(r'^/2/instances/(%s)$' % instance_name_pattern):
rlib2.R_2_instances_name,
re.compile(r'^/2/instances/(%s)/info$' % instance_name_pattern):
rlib2.R_2_instances_name_info,
re.compile(r'^/2/instances/([\w\._-]+)/tags$'): rlib2.R_2_instances_name_tags,
re.compile(r'^/2/instances/([\w\._-]+)/reboot$'):
re.compile(r'^/2/instances/(%s)/tags$' % instance_name_pattern):
rlib2.R_2_instances_name_tags,
re.compile(r'^/2/instances/(%s)/reboot$' % instance_name_pattern):
rlib2.R_2_instances_name_reboot,
re.compile(r'^/2/instances/([\w\._-]+)/reinstall$'):
re.compile(r'^/2/instances/(%s)/reinstall$' % instance_name_pattern):
rlib2.R_2_instances_name_reinstall,
re.compile(r'^/2/instances/([\w\._-]+)/replace-disks$'):
re.compile(r'^/2/instances/(%s)/replace-disks$' % instance_name_pattern):
rlib2.R_2_instances_name_replace_disks,
re.compile(r'^/2/instances/([\w\._-]+)/shutdown$'):
re.compile(r'^/2/instances/(%s)/shutdown$' % instance_name_pattern):
rlib2.R_2_instances_name_shutdown,
re.compile(r'^/2/instances/([\w\._-]+)/startup$'):
re.compile(r'^/2/instances/(%s)/startup$' % instance_name_pattern):
rlib2.R_2_instances_name_startup,
re.compile(r'/2/jobs/(%s)$' % constants.JOB_ID_TEMPLATE): rlib2.R_2_jobs_id,
"/2/tags": rlib2.R_2_tags,
"/2/info": rlib2.R_2_info,
"/2/os": rlib2.R_2_os,
})
"/2/jobs": rlib2.R_2_jobs,
re.compile(r'/2/jobs/(%s)$' % job_id_pattern):
rlib2.R_2_jobs_id,
"/2/tags": rlib2.R_2_tags,
"/2/info": rlib2.R_2_info,
"/2/os": rlib2.R_2_os,
}
CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN,
constants.JOB_ID_TEMPLATE))
......@@ -26,6 +26,7 @@ import re
from ganeti import utils
from ganeti import cmdlib
from ganeti.rapi import connector
import testutils
......@@ -66,5 +67,53 @@ class TestDocs(unittest.TestCase):
(lucls.HTYPE, lucls.HPATH)))
def testRapiDocs(self):
"""Check whether all RAPI resources are documented.
"""
rapidoc = self._ReadDocFile("rapi.rst")
node_name = "[node_name]"
instance_name = "[instance_name]"
job_id = "[job_id]"
resources = connector.GetHandlers(re.escape(node_name),
re.escape(instance_name),
re.escape(job_id))
titles = []
prevline = None
for line in rapidoc.splitlines():
if re.match(r"^\++$", line):
titles.append(prevline)
prevline = line
undocumented = []
for key, handler in resources.iteritems():
# Regex objects
if hasattr(key, "match"):
found = False
for title in titles:
if (title.startswith("``") and
title.endswith("``") and
key.match(title[2:-2])):
found = True
break
if not found:
# TODO: Find better way of identifying resource
undocumented.append(str(handler))
elif ("``%s``" % key) not in titles:
undocumented.append(key)
self.failIf(undocumented,
msg=("Missing RAPI resource documentation for %s" %
utils.CommaJoin(undocumented)))
if __name__ == "__main__":
unittest.main()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment