From 483ccbf2d8f0c71ebb15a4a47246a68a42e68f3e Mon Sep 17 00:00:00 2001 From: Bogumil Zebek Date: Wed, 25 Mar 2020 11:54:11 +0100 Subject: [PATCH] Documentation Issue-ID: AAF-1091 Signed-off-by: Zebek Bogumil Change-Id: I59df0545c4dd5adfde32c83988f89cd2d0c4676b --- certService/README.md | 4 +- docs/Makefile | 23 ++++ docs/README.md | 21 ++++ docs/conf.py | 3 + docs/index.rst | 21 +++- docs/requirements-docs.txt | 1 + docs/sections/architecture.rst | 18 +++ docs/sections/build.rst | 61 +++++++++++ docs/sections/configuration.rst | 28 +++++ docs/sections/img/certservice_high_level.jpg | Bin 0 -> 24640 bytes docs/sections/installation.rst | 21 ++++ docs/sections/logging.rst | 25 +++++ docs/sections/offeredapis.rst | 11 ++ docs/sections/openapi.yaml | 158 +++++++++++++++++++++++++++ docs/sections/release-notes.rst | 50 +++++++++ 15 files changed, 440 insertions(+), 5 deletions(-) create mode 100644 docs/Makefile create mode 100644 docs/README.md create mode 100644 docs/sections/architecture.rst create mode 100644 docs/sections/build.rst create mode 100644 docs/sections/configuration.rst create mode 100644 docs/sections/img/certservice_high_level.jpg create mode 100644 docs/sections/installation.rst create mode 100644 docs/sections/logging.rst create mode 100644 docs/sections/offeredapis.rst create mode 100644 docs/sections/openapi.yaml create mode 100644 docs/sections/release-notes.rst diff --git a/certService/README.md b/certService/README.md index 8e7fccc4..61506e79 100644 --- a/certService/README.md +++ b/certService/README.md @@ -88,11 +88,11 @@ path: cd /var/log/onap/aaf/certservice ``` You should see: -audit.log error.log trace.log +audit.log error.log debug.log ### RestAPI API is described by Swagger ( OpenAPI 3.0 ) on endpoint /docs ( endpoint is defined in properties as springdoc.swagger-ui.path ) ``` http://localchost:8080/docs -``` \ No newline at end of file +``` diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..65513dc3 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,23 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) +clean: + @echo "##### Clean build directory #####" + rm -rf $(BUILDDIR) + @echo "##### Done #####" + +.PHONY: help clean Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..15deadea --- /dev/null +++ b/docs/README.md @@ -0,0 +1,21 @@ +## AAF Certification Service documentation +###Requirements + Python 3.x + +To generate a documentation locally follow below steps. + +1. Open **docs** folder in terminal +2. Install all required dependencies + + ``` + python install -r requirements-docs.txt + ``` +3. Generate local documentation + ``` + make html + ``` + After command execution the documentation will be available in **_build/html** folder. +4. Before you commit documentation changes please execute + ``` + make clean + ``` diff --git a/docs/conf.py b/docs/conf.py index 8f40e8b8..b37b90cf 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -7,6 +7,9 @@ linkcheck_ignore = [ 'http://localhost', ] +extensions = [ + 'sphinxcontrib.openapi', +] intersphinx_mapping = {} html_last_updated_fmt = '%d-%b-%y %H:%M' diff --git a/docs/index.rst b/docs/index.rst index 87b61527..e84df935 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -2,7 +2,22 @@ .. http://creativecommons.org/licenses/by/4.0 .. Copyright 2020 NOKIA -AAF Cert Service ------------------------------------------------- +AAF Certification Service +========================================= + .. toctree:: - :maxdepth: 1 + :maxdepth: 2 + :caption: Contents: + + sections/architecture.rst + sections/build.rst + sections/offeredapis.rst + sections/logging.rst + sections/installation.rst + sections/configuration.rst + sections/release-notes.rst + +Indices and tables +================== + +* :ref:`search` diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index b3188ddd..98fc25ce 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -10,6 +10,7 @@ sphinxcontrib-needs>=0.2.3 sphinxcontrib-nwdiag sphinxcontrib-seqdiag sphinxcontrib-swaggerdoc +sphinxcontrib-openapi sphinxcontrib-plantuml sphinx_bootstrap_theme lfdocs-conf diff --git a/docs/sections/architecture.rst b/docs/sections/architecture.rst new file mode 100644 index 00000000..654208d1 --- /dev/null +++ b/docs/sections/architecture.rst @@ -0,0 +1,18 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright 2020 NOKIA + +Architecture +============ + +The micro-service called CertService is designed for requesting certificates +signed by external Certificate Authority (CA) using CMP over HTTP protocol. It uses CMPv2 client to send and receive CMPv2 messages. +CertService's client will be also provided so other ONAP components (aka end components) can easily get certificate from CertService. +End component is an ONAP component (e.g. DCAE collector or controller) which requires certificate from CMPv2 server +to protect external traffic and uses CertService's client to get it. +CertService's client communicates with CertService via REST API over HTTPS, while CertService with CMPv2 server via CMP over HTTP. + +.. image:: img/certservice_high_level.jpg + :width: 855px + :height: 178px + :alt: Interaction between components diff --git a/docs/sections/build.rst b/docs/sections/build.rst new file mode 100644 index 00000000..d533e330 --- /dev/null +++ b/docs/sections/build.rst @@ -0,0 +1,61 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright 2020 NOKIA + +Build +===== + +Jenkins +------- +#. JJB Master + + https://jenkins.onap.org/view/aaf/job/aaf-certservice-master-merge-java/ + +#. JJB Stage + + https://jenkins.onap.org/view/aaf/job/aaf-certservice-maven-docker-stage-master/ + +#. JJB Release + + https://jenkins.onap.org/view/aaf/job/aaf-certservice-maven-stage-master/ + https://jenkins.onap.org/view/aaf/job/aaf-certservice-release-merge/ + +#. JJB CSIT + + https://jenkins.onap.org/view/CSIT/job/aaf-master-csit-certservice/ + +Environment +----------- + +* Java 11 +* Apache Maven 3.6.0 +* Linux +* Docker 18.09.5 +* Python 2.7.x + +How to build images? +-------------------- + +#. Checkout the project from https://gerrit.onap.org/r/#/admin/projects/aaf/certservice +#. Read information's stored in README.md file +#. Use a Makefile to build images:: + + make build + +How to start service locally? +----------------------------------------------- +#. Start Cert Service with configured EJBCA:: + + make start-backend + +#. Run Cert Service Client:: + + make run-client + +#. Remove client container:: + + make stop-client + +#. Stop Cert Service and EJBCA:: + + make stop-backend diff --git a/docs/sections/configuration.rst b/docs/sections/configuration.rst new file mode 100644 index 00000000..47f2dd87 --- /dev/null +++ b/docs/sections/configuration.rst @@ -0,0 +1,28 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright 2020 NOKIA + +Configuration +============= + +.. note:: + * This section is used to describe the options a software component offers for configuration. + + * Configuration is typically: provided for platform-component and sdk projects; + and referenced in developer and user guides. + + * This note must be removed after content has been added. + + + +Example ... + +You can provide the following in ``basic.conf`` + +``host=ADDRESS`` + The address of the host + +``port=PORT`` + The port used for signaling + + Optional. Default: ``8080`` diff --git a/docs/sections/img/certservice_high_level.jpg b/docs/sections/img/certservice_high_level.jpg new file mode 100644 index 0000000000000000000000000000000000000000..11466983e1be1a5d8202190c2e5e936b70da6f3a GIT binary patch literal 24640 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