diff --git a/docs/requirements.txt b/docs/requirements.txt index cd7c3062a54c674c19c4d182d65b5a2882606fcf..cc674ad653b6692568a1cc20b2cc37d986df896a 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 f5dd3d43d2312c65969dc841ef4da5f05135107f..2d89320ea72464347ae633ad812dd074f43f4139 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 c8613779e927873760f0e19ee76546065d355b76..51eb61753b2bf5739cc6e4477a28910eca14db23 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 93cf1deaefec1eb0aaa179f111d4533fa3c8b8b7..21bf9712cd65c8471008b30a24736d51084f1e5a 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 99a57fb165ca22ac3f1f97e160667f09e890bbe4..9c731ef8b8531382726e2a33d5c323bcbfc0a97a 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 f51b631c1dceba424e4005a2e6182407dad464e2..45eb8700be5a259663a7bc3d702d9c8a4ee4095d 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 130294e54becd81e70c206c3dcbefd96f9303d0d..3ada6f6aef6e88eaa8a016779a8af43841e6136b 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``.