From 5ada515a9b796bdcb0a78c7fd4eb3512bd21c031 Mon Sep 17 00:00:00 2001 From: elinuxhenrik Date: Mon, 19 Oct 2020 10:39:59 +0200 Subject: [PATCH] Introduce rAPP Catalogue API Change-Id: I0128c5b6405d2efd4de49d4ced200cd9fed6cf96 Issue-ID: NONRTRIC-287 Signed-off-by: elinuxhenrik --- .gitignore | 4 +- docs/.project | 11 - docs/api-docs.rst | 23 +- docs/conf.py | 16 +- docs/images/swagger.png | Bin 0 -> 3590 bytes docs/images/yaml_logo.png | Bin 0 -> 3477 bytes docs/requirements-docs.txt | 17 +- pom.xml | 1 + r-app-catalogue/.gitignore | 3 + r-app-catalogue/Dockerfile | 39 ++++ r-app-catalogue/README.md | 27 +++ r-app-catalogue/api/rac-api.json | 246 ++++++++++++++++++++ r-app-catalogue/api/rac-api.yaml | 175 +++++++++++++++ r-app-catalogue/config/application.yaml | 4 + r-app-catalogue/pom.xml | 250 +++++++++++++++++++++ .../rappcatalogue/api/ServicesApiDelegateImpl.java | 34 +++ .../api/ServicesApiDelegateImplTest.java | 33 +++ tox.ini | 15 +- 18 files changed, 867 insertions(+), 31 deletions(-) delete mode 100644 docs/.project create mode 100644 docs/images/swagger.png create mode 100644 docs/images/yaml_logo.png create mode 100644 r-app-catalogue/.gitignore create mode 100644 r-app-catalogue/Dockerfile create mode 100644 r-app-catalogue/README.md create mode 100644 r-app-catalogue/api/rac-api.json create mode 100644 r-app-catalogue/api/rac-api.yaml create mode 100644 r-app-catalogue/config/application.yaml create mode 100644 r-app-catalogue/pom.xml create mode 100644 r-app-catalogue/src/main/java/org/oransc/rappcatalogue/api/ServicesApiDelegateImpl.java create mode 100644 r-app-catalogue/src/test/java/org/oransc/rappcatalogue/api/ServicesApiDelegateImplTest.java diff --git a/.gitignore b/.gitignore index e5a2f721..26c6731d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,10 +6,12 @@ docs/_build/ # Eclipse .checkstyle +.classpath +target/ .sts4-cache .project .settings .pydevproject infer-out/ -.vscode \ No newline at end of file +.vscode diff --git a/docs/.project b/docs/.project deleted file mode 100644 index e248a4fa..00000000 --- a/docs/.project +++ /dev/null @@ -1,11 +0,0 @@ - - - docs - - - - - - - - diff --git a/docs/api-docs.rst b/docs/api-docs.rst index 12ff5167..9b0608a6 100644 --- a/docs/api-docs.rst +++ b/docs/api-docs.rst @@ -15,9 +15,10 @@ This is the API-docs of Non-RT RIC. :depth: 3 :local: -The Non-RT RIC consists of two parts, described in the sections below: +The Non-RT RIC consists of three parts, described in the sections below: * The Policy Agent * The SDNC A1 Controller + * The rAPP Catalogue Policy Agent @@ -44,6 +45,26 @@ See :ref:`sdnc-a1-controller-api` for how to use the API. See the README.md file in the nonrtric/sdnc-a1-controller repo for info about how to use it. +rAPP Catalogue +============== + +The Non RT-RIC Service Catalogue provides a way for services to register themselves for other services to discover. + +See `RAC API <./rac-api.html>`_ for how to use the API. + +.. |swagger-icon| image:: ./images/swagger.png + :width: 40px + +.. |yaml-icon| image:: ./images/yaml_logo.png + :width: 40px + + +.. csv-table:: + :header: "API name", "|swagger-icon|", "|yaml-icon|" + :widths: 10,5, 5 + + "RAC API", ":download:`link <../r-app-catalogue/api/rac-api.json>`", ":download:`link <../r-app-catalogue/api/rac-api.yaml>`" + Complementary tools =================== diff --git a/docs/conf.py b/docs/conf.py index d6202898..a6ae7f96 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -7,9 +7,23 @@ branch = 'latest' linkcheck_ignore = [ 'http://localhost.*', 'http://127.0.0.1.*', - 'https://gerrit.o-ran-sc.org.*' + 'https://gerrit.o-ran-sc.org.*', + './rac-api.html' #Generated file that doesn't exist at link check. ] +extensions = ['sphinxcontrib.redoc', 'sphinx.ext.intersphinx',] + +redoc = [ + { + 'name': 'RAC API', + 'page': 'rac-api', + 'spec': '../r-app-catalogue/api/rac-api.json', + 'embed': True, + } + ] + +redoc_uri = 'https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js' + #intershpinx mapping with other projects intersphinx_mapping = {} diff --git a/docs/images/swagger.png b/docs/images/swagger.png new file mode 100644 index 0000000000000000000000000000000000000000..f5a9e0c0c47ce2969affb08af684094da1850a58 GIT binary patch literal 3590 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 literal 0 HcmV?d00001 diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index 09a0c1cb..78db6850 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,5 +1,12 @@ -sphinx -sphinx-rtd-theme -sphinxcontrib-httpdomain -recommonmark -lfdocs-conf +tox +Sphinx>=2,<4 +doc8 +docutils +setuptools +six +sphinx_rtd_theme>=0.4.3 +sphinxcontrib-needs>=0.2.3 +sphinxcontrib-swaggerdoc +sphinx_bootstrap_theme +sphinxcontrib-redoc +lfdocs-conf \ No newline at end of file diff --git a/pom.xml b/pom.xml index cb8302ef..f21502fe 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,7 @@ policy-agent sdnc-a1-controller enrichment-coordinator-service + r-app-catalogue diff --git a/r-app-catalogue/.gitignore b/r-app-catalogue/.gitignore new file mode 100644 index 00000000..ad56f2de --- /dev/null +++ b/r-app-catalogue/.gitignore @@ -0,0 +1,3 @@ +.swagger-codegen-ignore +.swagger-codegen/ +api/README.md diff --git a/r-app-catalogue/Dockerfile b/r-app-catalogue/Dockerfile new file mode 100644 index 00000000..a85f57d6 --- /dev/null +++ b/r-app-catalogue/Dockerfile @@ -0,0 +1,39 @@ +# +# ============LICENSE_START======================================================= +# Copyright (C) 2020 Nordix Foundation. +# ================================================================================ +# 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. +# +# SPDX-License-Identifier: Apache-2.0 +# ============LICENSE_END========================================================= +# +FROM openjdk:11-jre-slim + +ARG JAR + +WORKDIR /opt/app/r-app-catalogue +RUN mkdir -p /var/log/r-app-catalogue + +EXPOSE 8081 8433 + +ADD /config/application.yaml /opt/app/r-app-catalogue/config/application.yaml +ADD target/${JAR} /opt/app/r-app-catalogue/r-app-catalogue.jar + + +RUN chmod -R 777 /opt/app/r-app-catalogue/config/ + +CMD ["java", "-jar", "/opt/app/r-app-catalogue/r-app-catalogue.jar"] + + + + diff --git a/r-app-catalogue/README.md b/r-app-catalogue/README.md new file mode 100644 index 00000000..863713db --- /dev/null +++ b/r-app-catalogue/README.md @@ -0,0 +1,27 @@ +# O-RAN-SC Non-RT RIC rAPP Catalogue + +The O-RAN Non-RT RIC rApp Catalogue provides an OpenApi 3.0 REST API for services to register themselves and discover +other services. + +**NOTE!** The definition of the REST API is done in the `api/rac-api.json` file. The yaml version of the file is +generated during compilation. + +The application is a SpringBoot application generated using the openapitools openapi-generator-maven-plugin. + +To start the application run: +`mvn spring-boot:run` + +## License + +Copyright (C) 2020 Nordix Foundation. 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. diff --git a/r-app-catalogue/api/rac-api.json b/r-app-catalogue/api/rac-api.json new file mode 100644 index 00000000..3741bdd1 --- /dev/null +++ b/r-app-catalogue/api/rac-api.json @@ -0,0 +1,246 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "rAPP Catalogue API", + "description": "The Non RT-RIC Service Catalogue provides a way for services to register themselves for other services to discover.", + "version": "1.0.0" + }, + "paths": { + "/services": { + "get": { + "summary": "Service names", + "deprecated": false, + "operationId": "getServiceNamesUsingGET", + "responses": { + "200": { + "description": "Service names", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "example": [ + "DroneIdentifier", + "Collector" + ] + } + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not used" + } + }, + "tags": [ + "rAPP Catalogue API" + ] + } + }, + "/services/{serviceName}": { + "get": { + "summary": "Individual Service", + "deprecated": false, + "operationId": "getIndividualServiceUsingGET", + "responses": { + "200": { + "description": "EI Job", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/service" + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Service is not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error_information" + } + } + } + } + }, + "parameters": [ + { + "in": "path", + "name": "serviceName", + "description": "serviceName", + "schema": { + "type": "string" + }, + "required": true, + "example": "DroneIdentifier" + } + ], + "tags": [ + "rAPP Catalogue API" + ] + }, + "put": { + "summary": "Create or update a Service", + "deprecated": false, + "operationId": "putIndividualServiceUsingPUT", + "responses": { + "200": { + "description": "Service updated" + }, + "201": { + "description": "Service created" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Provided service is not correct", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error_information" + }, + "example": { + "detail": "Service is missing required property version", + "status": 404 + } + } + } + } + }, + "parameters": [ + { + "name": "serviceName", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "example": "DroneIdentifier" + } + ], + "requestBody": { + "description": "Service to create/update", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/service" + } + } + } + }, + "tags": [ + "rAPP Catalogue API" + ] + }, + "delete": { + "summary": "Remove a Service from the catalogue", + "deprecated": false, + "operationId": "deleteIndividualServiceUsingDELETE", + "responses": { + "200": { + "description": "Not used" + }, + "204": { + "description": "Job deleted" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Service is not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error_information" + } + } + } + } + }, + "parameters": [ + { + "name": "serviceName", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "example": "DroneIdentifier" + } + ], + "tags": [ + "rAPP Catalogue API" + ] + } + } + }, + "components": { + "schemas": { + "service": { + "description": "A Service", + "type": "object", + "title": "service", + "required": [ + "version" + ], + "properties": { + "version": { + "description": "Version of the Service", + "type": "string", + "example": "1.0.0" + }, + "display_name": { + "description": "Display name for the Service", + "type": "string", + "example": "Drone Identifier" + }, + "description": { + "description": "Description of the Service", + "type": "string", + "example": "Detects if a UE is a drone" + } + } + }, + "error_information": { + "description": "Problem as defined in https://tools.ietf.org/html/rfc7807", + "type": "object", + "title": "error_information", + "properties": { + "detail": { + "description": "A human-readable explanation specific to this occurrence of the problem.", + "type": "string", + "example": "Service not found" + }, + "status": { + "format": "int32", + "description": "The HTTP status code generated by the origin server for this occurrence of the problem.", + "type": "integer", + "example": 404 + } + } + } + } + } +} \ No newline at end of file diff --git a/r-app-catalogue/api/rac-api.yaml b/r-app-catalogue/api/rac-api.yaml new file mode 100644 index 00000000..87e2eb97 --- /dev/null +++ b/r-app-catalogue/api/rac-api.yaml @@ -0,0 +1,175 @@ +openapi: 3.0.0 +info: + title: rAPP Catalogue API + description: The Non RT-RIC Service Catalogue provides a way for services to register + themselves for other services to discover. + version: 1.0.0 +servers: +- url: / +paths: + /services: + get: + tags: + - rAPP Catalogue API + summary: Service names + operationId: getServiceNamesUsingGET + responses: + 200: + description: Service names + content: + application/json: + schema: + type: array + items: + type: string + example: + - DroneIdentifier + - Collector + 401: + description: Unauthorized + 403: + description: Forbidden + 404: + description: Not used + deprecated: false + /services/{serviceName}: + get: + tags: + - rAPP Catalogue API + summary: Individual Service + operationId: getIndividualServiceUsingGET + parameters: + - name: serviceName + in: path + description: serviceName + required: true + style: simple + explode: false + schema: + type: string + example: DroneIdentifier + responses: + 200: + description: EI Job + content: + application/json: + schema: + $ref: '#/components/schemas/service' + 401: + description: Unauthorized + 403: + description: Forbidden + 404: + description: Service is not found + content: + application/json: + schema: + $ref: '#/components/schemas/error_information' + deprecated: false + put: + tags: + - rAPP Catalogue API + summary: Create or update a Service + operationId: putIndividualServiceUsingPUT + parameters: + - name: serviceName + in: path + required: true + style: simple + explode: false + schema: + type: string + example: DroneIdentifier + requestBody: + description: Service to create/update + content: + application/json: + schema: + $ref: '#/components/schemas/service' + required: true + responses: + 200: + description: Service updated + 201: + description: Service created + 401: + description: Unauthorized + 403: + description: Forbidden + 404: + description: Provided service is not correct + content: + application/json: + schema: + $ref: '#/components/schemas/error_information' + example: + detail: Service is missing required property version + status: 404 + deprecated: false + delete: + tags: + - rAPP Catalogue API + summary: Remove a Service from the catalogue + operationId: deleteIndividualServiceUsingDELETE + parameters: + - name: serviceName + in: path + required: true + style: simple + explode: false + schema: + type: string + example: DroneIdentifier + responses: + 200: + description: Not used + 204: + description: Job deleted + 401: + description: Unauthorized + 403: + description: Forbidden + 404: + description: Service is not found + content: + application/json: + schema: + $ref: '#/components/schemas/error_information' + deprecated: false +components: + schemas: + service: + title: service + required: + - version + type: object + properties: + version: + type: string + description: Version of the Service + example: 1.0.0 + display_name: + type: string + description: Display name for the Service + example: Drone Identifier + description: + type: string + description: Description of the Service + example: Detects if a UE is a drone + description: A Service + error_information: + title: error_information + type: object + properties: + detail: + type: string + description: A human-readable explanation specific to this occurrence of + the problem. + example: Service not found + status: + type: integer + description: The HTTP status code generated by the origin server for this + occurrence of the problem. + format: int32 + example: 404 + description: Problem as defined in https://tools.ietf.org/html/rfc7807 diff --git a/r-app-catalogue/config/application.yaml b/r-app-catalogue/config/application.yaml new file mode 100644 index 00000000..fadf7d24 --- /dev/null +++ b/r-app-catalogue/config/application.yaml @@ -0,0 +1,4 @@ +spring: + profiles: + active: prod + diff --git a/r-app-catalogue/pom.xml b/r-app-catalogue/pom.xml new file mode 100644 index 00000000..3ac85627 --- /dev/null +++ b/r-app-catalogue/pom.xml @@ -0,0 +1,250 @@ + + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 2.3.4.RELEASE + + + org.o-ran-sc.nonrtric + r-app-catalogue + 1.0.0-SNAPSHOT + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + 11 + 1.5.22 + 2.9.2 + 0.2.1 + 4.3.1 + 3.0.11 + 0.30.0 + + + + + io.swagger + swagger-annotations + ${swagger-annotations.version} + + + com.fasterxml.jackson.core + jackson-annotations + + + org.springframework + spring-beans + + + org.springframework.boot + spring-boot-autoconfigure + + + org.springframework + spring-web + + + org.springframework.boot + spring-boot + + + org.springframework + spring-webmvc + + + org.springframework + spring-context + + + io.springfox + springfox-swagger2 + ${springfox.version} + + + io.springfox + springfox-core + ${springfox.version} + + + io.springfox + springfox-spring-web + ${springfox.version} + + + io.springfox + springfox-spi + ${springfox.version} + + + org.assertj + assertj-core + + + org.apache.tomcat.embed + tomcat-embed-core + + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable.version} + + + javax.validation + validation-api + + + com.fasterxml.jackson.core + jackson-databind + + + org.yaml + snakeyaml + runtime + + + + org.springframework + spring-test + test + + + org.junit.jupiter + junit-jupiter-api + test + + + + + + + org.openapitools + openapi-generator-maven-plugin + ${openapi-generator-maven-plugin.version} + + + + generate + + + ${project.basedir}/api/rac-api.json + spring + org.oransc.rappcatalogue.api + org.oransc.rappcatalogue.model + + true + + + + + + + io.swagger.codegen.v3 + swagger-codegen-maven-plugin + ${swagger-codegen-maven-plugin.version} + + + + generate + + + ${project.basedir}/api/rac-api.json + openapi-yaml + ${project.basedir}/api/ + + rac-api.yaml + + + + + + + io.fabric8 + docker-maven-plugin + ${docker-maven-plugin.version} + false + + + generate-r-app-catalogue-image + package + + build + + + ${env.CONTAINER_PULL_REGISTRY} + + + o-ran-sc/nonrtric-r-app-catalogue:${project.version} + + try + ${basedir} + Dockerfile + + ${project.build.finalName}.jar + + + ${project.version} + + + + + + + + push-r-app-catalogue-image + + build + push + + + ${env.CONTAINER_PULL_REGISTRY} + ${env.CONTAINER_PUSH_REGISTRY} + + + o-ran-sc/nonrtric-r-app-catalogue:${project.version} + + ${basedir} + Dockerfile + + ${project.build.finalName}.jar + + + ${project.version} + latest + + + + + + + + + + + \ No newline at end of file diff --git a/r-app-catalogue/src/main/java/org/oransc/rappcatalogue/api/ServicesApiDelegateImpl.java b/r-app-catalogue/src/main/java/org/oransc/rappcatalogue/api/ServicesApiDelegateImpl.java new file mode 100644 index 00000000..701f1d8b --- /dev/null +++ b/r-app-catalogue/src/main/java/org/oransc/rappcatalogue/api/ServicesApiDelegateImpl.java @@ -0,0 +1,34 @@ +package org.oransc.rappcatalogue.api; + +import java.util.Arrays; +import java.util.List; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +@org.springframework.stereotype.Service +public class ServicesApiDelegateImpl implements ServicesApiDelegate { + + @Override + public ResponseEntity deleteIndividualServiceUsingDELETE(String serviceName) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } + + // @Override + // public ResponseEntity getIndividualServiceUsingGET(String serviceName) { + // return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + // } + + @Override + public ResponseEntity> getServiceNamesUsingGET() { + List services = Arrays.asList("a", "b"); + return ResponseEntity.ok(services); + } + + // @Override + // public ResponseEntity putIndividualServiceUsingPUT(String serviceName, Service service) { + // return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + // } +} diff --git a/r-app-catalogue/src/test/java/org/oransc/rappcatalogue/api/ServicesApiDelegateImplTest.java b/r-app-catalogue/src/test/java/org/oransc/rappcatalogue/api/ServicesApiDelegateImplTest.java new file mode 100644 index 00000000..53dfc1a5 --- /dev/null +++ b/r-app-catalogue/src/test/java/org/oransc/rappcatalogue/api/ServicesApiDelegateImplTest.java @@ -0,0 +1,33 @@ +package org.oransc.rappcatalogue.api; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +class ServicesApiDelegateImplTest { + + @Test + void putValidService_shouldBeOk() { + ServicesApiDelegateImpl delegateUnderTest = new ServicesApiDelegateImpl(); + + ResponseEntity> response = delegateUnderTest.getServiceNamesUsingGET(); + } + + @Test + void getServices_shouldProvideArrayOfServices() throws Exception { + ServicesApiDelegateImpl delegateUnderTest = new ServicesApiDelegateImpl(); + + ResponseEntity> response = delegateUnderTest.getServiceNamesUsingGET(); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).isEqualTo(Arrays.asList("a", "b")); + } +} diff --git a/tox.ini b/tox.ini index 4491722a..2705e16e 100644 --- a/tox.ini +++ b/tox.ini @@ -24,23 +24,14 @@ skipsdist = true [testenv:docs] basepython = python3 -deps = - sphinx - sphinx-rtd-theme - sphinxcontrib-httpdomain - recommonmark - lfdocs-conf +deps = -r{toxinidir}/docs/requirements-docs.txt commands = - sphinx-build -W -b html -n -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/html + sphinx-build -W -b html -n -d {envtmpdir}/docs/doctrees ./docs/ {toxinidir}/docs/_build/html echo "Generated docs available in {toxinidir}/docs/_build/html" whitelist_externals = echo [testenv:docs-linkcheck] basepython = python3 -deps = sphinx - sphinx-rtd-theme - sphinxcontrib-httpdomain - recommonmark - lfdocs-conf +deps = -r{toxinidir}/docs/requirements-docs.txt commands = sphinx-build -W -b linkcheck -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/linkcheck -- 2.16.6