From 917646b0bbac1cbe227e4d4eb44a04fe23d652a6 Mon Sep 17 00:00:00 2001
From: Jean-Paul Calderone <exarkun@twistedmatrix.com>
Date: Tue, 25 Jan 2022 10:20:57 -0500
Subject: [PATCH] try using redoc and a validator

---
 docs/requirements.txt                           |  2 +-
 docs/source/conf.py                             | 14 ++++++++++++--
 docs/source/designs/backup-recovery.rst         |  2 +-
 requirements/test.in                            |  1 +
 setup.cfg                                       |  2 +-
 .../_zkapauthorizer}/backup-recovery.yaml       | 15 +++++++++++++++
 .../tests/test_client_resource.py               | 17 +++++++++++++++++
 7 files changed, 48 insertions(+), 5 deletions(-)
 rename {docs/source/designs => src/_zkapauthorizer}/backup-recovery.yaml (88%)

diff --git a/docs/requirements.txt b/docs/requirements.txt
index cd7c306..cc674ad 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,2 +1,2 @@
 sphinx
-sphinxcontrib-openapi
+sphinxcontrib-redoc
diff --git a/docs/source/conf.py b/docs/source/conf.py
index f5dd3d4..2d89320 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -39,7 +39,17 @@ release = '0.0'
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
 extensions = [
-    "sphinxcontrib.openapi",
+    "sphinxcontrib.redoc",
+]
+
+# Configure redoc
+redoc = [
+    {
+        'name': 'ZKAPAuthorizer Backup/Recovery API',
+        'page': 'designs/backup-recovery-openapi',
+        'spec': '../../src/_zkapauthorizer/backup-recovery.yaml',
+        'embed': True,
+    },
 ]
 
 # Add any paths that contain templates here, relative to this directory.
@@ -86,7 +96,7 @@ html_theme = 'alabaster'
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = []
 
 # Custom sidebar templates, must be a dictionary that maps document names
 # to template names.
diff --git a/docs/source/designs/backup-recovery.rst b/docs/source/designs/backup-recovery.rst
index c861377..51eb617 100644
--- a/docs/source/designs/backup-recovery.rst
+++ b/docs/source/designs/backup-recovery.rst
@@ -205,7 +205,7 @@ Backup operations resume as usual from this point using the existing on-grid sta
 External Interfaces
 ~~~~~~~~~~~~~~~~~~~
 
-.. openapi:: ./backup-recovery.yaml
+See the `OpenAPI specification <backup-recovery-openapi.html>`_.
 
 Data Integrity
 ~~~~~~~~~~~~~~
diff --git a/requirements/test.in b/requirements/test.in
index 93cf1de..21bf971 100644
--- a/requirements/test.in
+++ b/requirements/test.in
@@ -3,3 +3,4 @@ fixtures
 testtools
 hypothesis
 pyflakes
+openapi_spec_validator
diff --git a/setup.cfg b/setup.cfg
index 99a57fb..9c731ef 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -58,7 +58,7 @@ install_requires =
     colorama
 
 [options.extras_require]
-test = coverage; fixtures; testtools; hypothesis
+test = coverage; fixtures; testtools; hypothesis; openapi_spec_validator
 
 [flake8]
 # Enforce all pyflakes constraints, and also prohibit tabs for indentation.
diff --git a/docs/source/designs/backup-recovery.yaml b/src/_zkapauthorizer/backup-recovery.yaml
similarity index 88%
rename from docs/source/designs/backup-recovery.yaml
rename to src/_zkapauthorizer/backup-recovery.yaml
index f51b631..45eb870 100644
--- a/docs/source/designs/backup-recovery.yaml
+++ b/src/_zkapauthorizer/backup-recovery.yaml
@@ -51,6 +51,19 @@ paths:
                 properties: {}
 
   /storage-plugins/privatestorageio-zkapauthz-v1/backup:
+    get:
+      description: >-
+        Retrieve information about the backup configuration and state of this
+        node.
+      responses:
+        200:
+          description: >-
+            Information about backup configuration is available and included
+            in the response.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/BackupConfiguration"
     post:
       description: |
         Configure ZKAPAuthorizer to maintain an on-grid backup of its state or
@@ -96,6 +109,8 @@ components:
             is the capability which can be submitted in order to initiate a
             recovery from the backup.
 
+
+
   responses:
     ErrorResponse:
       description: >-
diff --git a/src/_zkapauthorizer/tests/test_client_resource.py b/src/_zkapauthorizer/tests/test_client_resource.py
index 130294e..3ada6f6 100644
--- a/src/_zkapauthorizer/tests/test_client_resource.py
+++ b/src/_zkapauthorizer/tests/test_client_resource.py
@@ -43,6 +43,8 @@ from hypothesis.strategies import (
     text,
     tuples,
 )
+from openapi_spec_validator import validate_spec
+from openapi_spec_validator.readers import read_from_filename
 from testtools import TestCase
 from testtools.content import text_content
 from testtools.matchers import (
@@ -66,6 +68,7 @@ from twisted.web.http import BAD_REQUEST, NOT_FOUND, NOT_IMPLEMENTED, OK, UNAUTH
 from twisted.web.http_headers import Headers
 from twisted.web.resource import IResource, getChildForRequest
 
+from .. import __file__ as package_init_file
 from .. import __version__ as zkapauthorizer_version
 from .._base64 import urlsafe_b64decode
 from .._json import dumps_utf8
@@ -285,6 +288,20 @@ def add_api_token_to_config(basedir, config, api_auth_token):
     config.write_private_config("api_auth_token", api_auth_token)
 
 
+class OpenAPITests(TestCase):
+    """
+    Tests for the OpenAPI specification for the HTTP API.
+    """
+    def test_backup_recovery_valid(self):
+        """
+        The specification document is valid OpenAPI 3.0.
+        """
+        spec_path = FilePath(package_init_file).sibling("backup-recovery.yaml")
+        spec_dict, spec_url = read_from_filename(spec_path.path)
+        # If no exception is raised then the spec is valid.
+        validate_spec(spec_dict)
+
+
 class FromConfigurationTests(TestCase):
     """
     Tests for ``from_configuration``.
-- 
GitLab