From 14d016e5551fdc203770dd8f4eac4724152e4848 Mon Sep 17 00:00:00 2001 From: "Lott, Christopher (cl778h)" Date: Mon, 27 Apr 2020 10:45:47 -0400 Subject: [PATCH] Extend exception handler to report details On failed requests, log and return details in the HTTP error response. Extend documentation to pull in the OpenAPI specification document. On store, overwrite ID in body with ID from path to ensure consistency. Signed-off-by: Lott, Christopher (cl778h) Change-Id: I630360bcf90c80b84392c6afb1e59347fccd13ef --- .gitignore | 5 +++++ a1/controller.py | 28 ++++++++++++++++++---------- a1/data.py | 2 ++ docs/api-spec.rst | 16 ++++++++++++++++ docs/developer-guide.rst | 20 ++++++++++++-------- docs/index.rst | 10 ++++------ docs/installation-guide.rst | 4 ++-- docs/overview.rst | 15 ++++++++------- docs/release-notes.rst | 5 ++++- tox.ini | 7 +++++-- 10 files changed, 76 insertions(+), 36 deletions(-) create mode 100644 docs/api-spec.rst diff --git a/.gitignore b/.gitignore index 92ce839..77c5294 100644 --- a/.gitignore +++ b/.gitignore @@ -111,3 +111,8 @@ ENV/ # Test report xunit-reports coverage-reports + +# Eclipse +.project +.pydevproject +.settings/ diff --git a/a1/controller.py b/a1/controller.py index 2de69b8..5daa8a5 100644 --- a/a1/controller.py +++ b/a1/controller.py @@ -30,23 +30,31 @@ mdc_logger = Logger(name=__name__) def _try_func_return(func): """ - generic caller that returns the apporp http response if exceptions are raised + helper method that runs the function and returns a detailed http response if an exception is raised. """ try: return func() - except (ValidationError, exceptions.PolicyTypeAlreadyExists, exceptions.CantDeleteNonEmptyType): - return "", 400 - except (exceptions.PolicyTypeNotFound, exceptions.PolicyInstanceNotFound): - return "", 404 - except (RejectedByBackend, NotConnected, BackendError): + except (ValidationError, exceptions.PolicyTypeAlreadyExists, exceptions.CantDeleteNonEmptyType) as exc: + msg = repr(exc) + mdc_logger.warning("Request failed, returning 400: {0}".format(msg)) + return msg, 400 + except (exceptions.PolicyTypeNotFound, exceptions.PolicyInstanceNotFound) as exc: + msg = repr(exc) + mdc_logger.warning("Request failed, returning 404: {0}".format(msg)) + return msg, 404 + except (RejectedByBackend, NotConnected, BackendError) as exc: """ - These are SDL errors. At the time of development here, we do not have a good understanding which of these errors are "try again later it may work" - and which are "never going to work". There is some discussion that RejectedByBackend is in the latter category, suggesting it should map to 400, - but until we understand the root cause of these errors, it's confusing to clients to give them a 400 (a "your fault" code) because they won't know how to fix + These are SDL errors. At the time of development here, we do not have a good understanding + which of these errors are "try again later it may work" and which are "never going to work". + There is some discussion that RejectedByBackend is in the latter category, suggesting it + should map to 400, but until we understand the root cause of these errors, it's confusing + to clients to give them a 400 (a "your fault" code) because they won't know how to fix. For now, we log, and 503, and investigate the logs later to improve the handling/reporting. """ # mdc_logger.exception(exc) # waiting for https://jira.o-ran-sc.org/browse/RIC-39 - return "", 503 + msg = repr(exc) + mdc_logger.warning("Request failed, returning 503: {0}".format(msg)) + return msg, 503 # let other types of unexpected exceptions blow up and log diff --git a/a1/data.py b/a1/data.py index 45fe5de..dfe9dd2 100644 --- a/a1/data.py +++ b/a1/data.py @@ -166,6 +166,8 @@ def store_policy_type(policy_type_id, body): key = _generate_type_key(policy_type_id) if SDL.get(A1NS, key) is not None: raise PolicyTypeAlreadyExists() + # overwrite ID in body to enforce consistency + body['policy_type_id'] = policy_type_id SDL.set(A1NS, key, body) diff --git a/docs/api-spec.rst b/docs/api-spec.rst new file mode 100644 index 0000000..2191c4d --- /dev/null +++ b/docs/api-spec.rst @@ -0,0 +1,16 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 + +A1 Mediator API +=============== + +This page shows the Open API specification for the A1 Mediator. +Alternately, if you have checked out the code and are running the server, +you can see a formatted version at this URL: ``http://localhost:10000/ui/``. + +OpenAPI Specification +--------------------- + +.. literalinclude:: ../a1/openapi.yaml + :language: yaml + :linenos: diff --git a/docs/developer-guide.rst b/docs/developer-guide.rst index 63ddde3..5e18ca5 100644 --- a/docs/developer-guide.rst +++ b/docs/developer-guide.rst @@ -1,8 +1,8 @@ .. This work is licensed under a Creative Commons Attribution 4.0 International License. .. http://creativecommons.org/licenses/by/4.0 -Developer-Guide -=============== +A1 Developer Guide +================== .. contents:: :depth: 3 @@ -14,10 +14,10 @@ Tech Stack - OpenAPI3 - Connexion - Flask with Gevent serving -- Python3.7 +- Python3.8 -Version bumping ---------------- +Version bumping A1 +------------------ This project follows semver. When changes are made, the versions are in: @@ -34,16 +34,18 @@ This project follows semver. When changes are made, the versions are in: 6) in the ric-plt repo that contains a1 helm chart, ``values.yaml``, ``Chart.yml`` -Version bumping rmr +Version bumping RMR ------------------- + As of 2020/02/13, A1 (Dockerfile), Dockerfile-Unit-Test, and all three integration test receivers use a base image from o-ran-sc. The rmr version is in that base image. When version changes are made in that image, rebuilding those 5 containers in the A1 repo will pick it up (or just A1 itself for prod usage). However, there are two items in this repo that must be kept in sync: ``rmr-version.yaml``, which controls what rmr gets installed for unit testing in Jenkins, and ``integration_tests/install_rmr.sh`` which is a useful script for a variety of local testing. -Version bumping python itself ------------------------------ +Version bumping Python +---------------------- + If you want to update the version of python itself (ie just done from 37 to 38): 1) ``Dockerfile`` @@ -54,6 +56,7 @@ If you want to update the version of python itself (ie just done from 37 to 38): Unit Testing ------------ + Note, before this will work, for the first time on the machine running the tests, run ``./install_deps.sh``. This is only needed once on the machine. Also, this requires the python packages ``tox`` and ``pytest``. @@ -70,6 +73,7 @@ Alternatively, you can run the unit tests in Docker (this is somewhat less nice Integration testing ------------------- + This tests A1’s external API with three test receivers. This depends on helm+k8s. Build all the containers: diff --git a/docs/index.rst b/docs/index.rst index 5513baa..40e4463 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,20 +1,18 @@ .. This work is licensed under a Creative Commons Attribution 4.0 International License. .. SPDX-License-Identifier: CC-BY-4.0 -Welcome to O-RAN SC A1 Documentation -===================================== +RIC Platform A1 Mediator +======================== .. toctree:: :maxdepth: 2 :caption: Contents: overview.rst - developer-guide.rst installation-guide.rst + api-spec.rst + developer-guide.rst release-notes.rst -.. - user-guide.rst - api-docs.rst * :ref:`genindex` * :ref:`modindex` diff --git a/docs/installation-guide.rst b/docs/installation-guide.rst index babd4fb..d59cb87 100644 --- a/docs/installation-guide.rst +++ b/docs/installation-guide.rst @@ -2,8 +2,8 @@ .. http://creativecommons.org/licenses/by/4.0 .. Copyright (C) 2019 AT&T Intellectual Property -Installation Guide -================== +A1 Installation Guide +===================== .. contents:: :depth: 3 diff --git a/docs/overview.rst b/docs/overview.rst index 73f8ed9..ac751e7 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -1,19 +1,20 @@ .. This work is licensed under a Creative Commons Attribution 4.0 International License. .. SPDX-License-Identifier: CC-BY-4.0 -A1 Mediator +A1 Overview =========== +The RAN Intelligent Controller (RIC) Platform's A1 Mediator component listens for policy +type and policy instance requests sent via HTTP (the "northbound" interface), +and publishes those requests to running xApps via RMR messages (the "southbound" interface). + Code ---- -https://gerrit.o-ran-sc.org/r/admin/repos/ric-plt/a1 -API ---- +Code is managed in this Gerrit repository: + +https://gerrit.o-ran-sc.org/r/admin/repos/ric-plt/a1 -You can see the API (OpenAPI3 spec) at ``a1/openapi.yml``. You can also -see the “pretty” version if you run the container at -``http://localhost:10000/ui/``. Policy Overview ---------------- diff --git a/docs/release-notes.rst b/docs/release-notes.rst index 660f781..3ced56e 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -14,11 +14,14 @@ and this project adheres to `Semantic Versioning `__. :depth: 3 :local: -[2.1.7] - 2020-04-22 +[2.1.7] - 2020-04-27 -------------------- * Upgrade to rmr 3.8.0 * Upgrade integration tests to xapp-frame-go version 0.4.8 which drops NNG +* Extend exception handler to return error details in HTTP response +* Ensure that policy type ID on path matches ID in object +* Add OpenAPI spec to RST documentation [2.1.6] - 4/7/2020 ------------------- diff --git a/tox.ini b/tox.ini index 4d0a6a7..77613b8 100644 --- a/tox.ini +++ b/tox.ini @@ -18,10 +18,13 @@ # Code [tox] -envlist = py38,flake8,docs,docs-linkcheck +envlist = code,flake8,docs,docs-linkcheck minversion = 2.0 -[testenv] +[pytest] +testpaths = tests + +[testenv:code] basepython = python3.8 deps= pytest -- 2.16.6