docs: update list of plugins 26/26126/5
authorPaul Vinciguerra <pvinci@vinciconsulting.com>
Tue, 24 Mar 2020 20:37:40 +0000 (16:37 -0400)
committerDave Wallace <dwallacelf@gmail.com>
Mon, 21 Dec 2020 23:23:13 +0000 (23:23 +0000)
The list of plugins is outdated.

This change introduces a dynamically
generated list of the plugins along with their descriptions,
extracted directly from the sources.

Type: docs

Change-Id: Icb7b65e6b45289e257d71a1c18d10f62ced59cbe
Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
.gitignore
docs/Makefile
docs/dynamic_includes/.gitkeep [new file with mode: 0644]
docs/gettingstarted/installing/packages.rst
docs/includes_renderer.py [new file with mode: 0644]

index ea33024..19378e8 100644 (file)
@@ -81,6 +81,7 @@ GTAGS
 /build-root/.doxygen-bootstrap.ok
 /build-root/.doxygen-siphon.dep
 /docs/_build
+/docs/dynamic_includes
 /sphinx_venv
 !/docs/Makefile
 
index 6c5960d..4993864 100644 (file)
@@ -27,6 +27,8 @@ help:
 # Catch-all target: route all unknown targets to Sphinx using the new
 # "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
 %: Makefile
+# Generate dynamic content
+       @python3 ./includes_renderer.py
        @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
 
 spell:
diff --git a/docs/dynamic_includes/.gitkeep b/docs/dynamic_includes/.gitkeep
new file mode 100644 (file)
index 0000000..e69de29
index 719fffb..6c4fae1 100644 (file)
@@ -35,19 +35,7 @@ vpp-plugins
 
 Vector Packet Processing plugin modules.
 
-* acl
-* dpdk
-* flowprobe
-* gtpu
-* ixge
-* kubeproxy
-* l2e
-* lb
-* memif
-* nat
-* pppoe
-* sixrd
-* stn
+.. include:: ../../dynamic_includes/plugin_list.inc
 
 vpp-dbg
 -------
diff --git a/docs/includes_renderer.py b/docs/includes_renderer.py
new file mode 100644 (file)
index 0000000..d36752d
--- /dev/null
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+#  Copyright (c) 2020. Vinci Consulting Corp. All Rights Reserved.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+import glob
+import inspect
+import os.path
+import re
+
+
+class ContentRenderer:
+    name = ""
+    curr_path = os.path.abspath(inspect.getsourcefile(lambda: 0))
+    vpp_root = curr_path.rsplit("/", 2)[0]
+    output_dir = f"{vpp_root}/docs/dynamic_includes/"
+
+    def render(self):
+        raise NotImplementedError
+
+
+class PluginRenderer(ContentRenderer):
+    name = "plugin_list.inc"
+
+    plugin_dir = f"{ContentRenderer.vpp_root}/src/plugins"
+
+    pattern = r'VLIB_PLUGIN_REGISTER\s?\(\)\s*=\s*{.*\.description\s?=\s?"([^"]*)".*};'  # noqa: 501
+    regex = re.compile(pattern, re.MULTILINE | re.DOTALL)
+
+    def render(self):
+        with open(f"{self.__class__.output_dir}{self.__class__.name}",
+                  "w") as output:
+            with os.scandir(self.__class__.plugin_dir) as pdir:
+                for entry in sorted(pdir, key=lambda entry: entry.name):
+                    if not entry.name.startswith('.') and entry.is_dir():
+                        description = "<no-description-found>"
+                        # we use glob because a plugin can (ioam for now)
+                        # define the plugin definition in
+                        # a further subdirectory.
+                        for f in glob.iglob(f'{self.__class__.plugin_dir}/'
+                                            f'{entry.name}/**',
+                                            recursive=True):
+                            if f.endswith('.c'):
+                                with open(f, "r", encoding="utf-8") \
+                                        as src:
+                                    for match in self.__class__.regex.finditer(
+                                            src.read()):
+                                        description = "%s" % (match.group(1))
+
+                        output.write(f"* {entry.name} - {description}\n")
+
+
+# if this list grows substantially, we can move the classes to
+# a folder and import them.
+renderers = [PluginRenderer,
+             ]
+
+
+def main():
+    print("rendering dynamic includes...")
+    for renderer in renderers:
+        renderer().render()
+    print("done.")
+
+
+if __name__ == "__main__":
+    main()