From: elinuxhenrik
Date: Mon, 4 Apr 2022 13:47:19 +0000 (+0200)
Subject: Seed code
X-Git-Tag: 1.3.0~5
X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F33%2F8033%2F1;p=nonrtric%2Fplt%2Finformationcoordinatorservice.git
Seed code
Issue-ID: NONRTRIC-716
Signed-off-by: elinuxhenrik
Change-Id: I3db047b6e46530987da171508b33e68c27e2763e
---
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..80763d8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,23 @@
+# Documentation
+.idea/
+.tox
+docs/_build/
+.DS_STORE
+.swagger*
+docs/offeredapis/swagger/README.md
+
+# Eclipse
+.checkstyle
+.classpath
+target/
+.sts4-cache
+.project
+.settings
+.pydevproject
+infer-out/
+/target/
+
+.vscode
+.factorypath
+
+coverage.*
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 0000000..095222a
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,16 @@
+---
+version: 2
+
+formats:
+ - htmlzip
+
+build:
+ image: latest
+
+python:
+ version: 3.7
+ install:
+ - requirements: docs/requirements-docs.txt
+
+sphinx:
+ configuration: docs/conf.py
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..cc8813e
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,51 @@
+#
+# ============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/information-coordinator-service
+RUN mkdir -p /var/log/information-coordinator-service
+RUN mkdir -p /opt/app/information-coordinator-service/etc/cert/
+RUN mkdir -p /var/information-coordinator-service
+
+EXPOSE 8083 8434
+
+ADD /config/application.yaml /opt/app/information-coordinator-service/config/application.yaml
+ADD target/${JAR} /opt/app/information-coordinator-service/information-coordinator-service.jar
+ADD /config/keystore.jks /opt/app/information-coordinator-service/etc/cert/keystore.jks
+ADD /config/truststore.jks /opt/app/information-coordinator-service/etc/cert/truststore.jks
+
+ARG user=nonrtric
+ARG group=nonrtric
+
+RUN groupadd $user && \
+ useradd -r -g $group $user
+RUN chown -R $user:$group /opt/app/information-coordinator-service
+RUN chown -R $user:$group /var/log/information-coordinator-service
+RUN chown -R $user:$group /var/information-coordinator-service
+
+USER ${user}
+
+CMD ["java", "-jar", "/opt/app/information-coordinator-service/information-coordinator-service.jar"]
+
+
+
+
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..96589bf
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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/api/ics-api.json b/api/ics-api.json
new file mode 100644
index 0000000..56bbcb5
--- /dev/null
+++ b/api/ics-api.json
@@ -0,0 +1,1289 @@
+{
+ "components": {"schemas": {
+ "consumer_information_type": {
+ "description": "Information for an Information type",
+ "type": "object",
+ "required": [
+ "job_data_schema",
+ "no_of_producers",
+ "type_status"
+ ],
+ "properties": {
+ "no_of_producers": {
+ "format": "int32",
+ "description": "The number of registered producers for the type",
+ "type": "integer"
+ },
+ "type_status": {
+ "description": "Allowed values: ENABLED: one or several producers for the information type are available DISABLED: no producers for the information type are available",
+ "type": "string",
+ "enum": [
+ "ENABLED",
+ "DISABLED"
+ ]
+ },
+ "job_data_schema": {
+ "description": "Json schema for the job data",
+ "type": "object"
+ }
+ }
+ },
+ "EiTypeObject": {
+ "description": "Information for an EI type",
+ "type": "object"
+ },
+ "service_status_info": {
+ "type": "object",
+ "required": [
+ "no_of_jobs",
+ "no_of_producers",
+ "no_of_types",
+ "status"
+ ],
+ "properties": {
+ "no_of_producers": {
+ "format": "int32",
+ "description": "Number of Information Producers",
+ "type": "integer"
+ },
+ "no_of_types": {
+ "format": "int32",
+ "description": "Number of Information Types",
+ "type": "integer"
+ },
+ "no_of_jobs": {
+ "format": "int32",
+ "description": "Number of Information Jobs",
+ "type": "integer"
+ },
+ "status": {
+ "description": "status text",
+ "type": "string"
+ }
+ }
+ },
+ "producer_registration_info": {
+ "description": "Information for an Information Producer",
+ "type": "object",
+ "required": [
+ "info_job_callback_url",
+ "info_producer_supervision_callback_url",
+ "supported_info_types"
+ ],
+ "properties": {
+ "info_producer_supervision_callback_url": {
+ "description": "callback for producer supervision",
+ "type": "string"
+ },
+ "supported_info_types": {
+ "description": "Supported Information Type IDs",
+ "type": "array",
+ "items": {
+ "description": "Supported Information Type IDs",
+ "type": "string"
+ }
+ },
+ "info_job_callback_url": {
+ "description": "callback for Information Job",
+ "type": "string"
+ }
+ }
+ },
+ "consumer_type_registration_info": {
+ "description": "Information for an Information type",
+ "type": "object",
+ "required": [
+ "info_type_id",
+ "job_data_schema",
+ "status"
+ ],
+ "properties": {
+ "info_type_id": {
+ "description": "Information type identifier",
+ "type": "string"
+ },
+ "job_data_schema": {
+ "description": "Json schema for the job data",
+ "type": "object"
+ },
+ "status": {
+ "description": "Allowed values: REGISTERED: the information type has been registered DEREGISTERED: the information type has been removed",
+ "type": "string",
+ "enum": [
+ "REGISTERED",
+ "DEREGISTERED"
+ ]
+ }
+ }
+ },
+ "ProblemDetails": {
+ "description": "A problem detail to carry details in a HTTP response according to RFC 7807",
+ "type": "object",
+ "properties": {
+ "detail": {
+ "description": "A human-readable explanation specific to this occurrence of the problem.",
+ "type": "string",
+ "example": "Information Job type 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
+ }
+ }
+ },
+ "EiJobStatusObject": {
+ "description": "Status for an EI job",
+ "type": "object",
+ "required": ["eiJobStatus"],
+ "properties": {"eiJobStatus": {
+ "description": "Allowed values for EI job status: ENABLED: the A1-EI producer is able to deliver EI result for the EI job DISABLED: the A1-EI producer is unable to deliver EI result for the EI job",
+ "type": "string",
+ "enum": [
+ "ENABLED",
+ "DISABLED"
+ ]
+ }}
+ },
+ "consumer_job_status": {
+ "description": "Status for an Information Job",
+ "type": "object",
+ "required": [
+ "info_job_status",
+ "producers"
+ ],
+ "properties": {
+ "info_job_status": {
+ "description": "Allowed values: ENABLED: the A1-Information producer is able to deliver result for the Information Job DISABLED: the A1-Information producer is unable to deliver result for the Information Job",
+ "type": "string",
+ "enum": [
+ "ENABLED",
+ "DISABLED"
+ ]
+ },
+ "producers": {
+ "description": "An array of all registered Information Producer Identifiers.",
+ "type": "array",
+ "items": {
+ "description": "An array of all registered Information Producer Identifiers.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "EiJobObject": {
+ "description": "Information for an Enrichment Information Job",
+ "type": "object",
+ "required": [
+ "eiTypeId",
+ "jobDefinition",
+ "jobOwner",
+ "jobResultUri"
+ ],
+ "properties": {
+ "eiTypeId": {
+ "description": "EI type Idenitifier of the EI job",
+ "type": "string"
+ },
+ "jobResultUri": {
+ "description": "The target URI of the EI data",
+ "type": "string"
+ },
+ "jobOwner": {
+ "description": "Identity of the owner of the job",
+ "type": "string"
+ },
+ "statusNotificationUri": {
+ "description": "The target of EI job status notifications",
+ "type": "string"
+ },
+ "jobDefinition": {
+ "description": "EI type specific job data",
+ "type": "object"
+ }
+ }
+ },
+ "producer_info_type_info": {
+ "description": "Information for an Information Type",
+ "type": "object",
+ "required": ["info_job_data_schema"],
+ "properties": {
+ "info_type_information": {
+ "description": "Type specific information for the information type",
+ "type": "object"
+ },
+ "info_job_data_schema": {
+ "description": "Json schema for the job data",
+ "type": "object"
+ }
+ }
+ },
+ "producer_info_job_request": {
+ "description": "The body of the Information Producer callbacks for Information Job creation and deletion",
+ "type": "object",
+ "required": ["info_job_identity"],
+ "properties": {
+ "owner": {
+ "description": "The owner of the job",
+ "type": "string"
+ },
+ "last_updated": {
+ "description": "The time when the job was last updated or created (ISO-8601)",
+ "type": "string"
+ },
+ "info_job_identity": {
+ "description": "Identity of the Information Job",
+ "type": "string"
+ },
+ "target_uri": {
+ "description": "URI for the target of the produced Information",
+ "type": "string"
+ },
+ "info_job_data": {
+ "description": "Json for the job data",
+ "type": "object"
+ },
+ "info_type_identity": {
+ "description": "Type identity for the job",
+ "type": "string"
+ }
+ }
+ },
+ "consumer_job": {
+ "description": "Information for an Information Job",
+ "type": "object",
+ "required": [
+ "info_type_id",
+ "job_definition",
+ "job_owner",
+ "job_result_uri"
+ ],
+ "properties": {
+ "info_type_id": {
+ "description": "Information type Idenitifier of the subscription job",
+ "type": "string"
+ },
+ "job_result_uri": {
+ "description": "The target URI of the subscribed information",
+ "type": "string"
+ },
+ "job_owner": {
+ "description": "Identity of the owner of the job",
+ "type": "string"
+ },
+ "job_definition": {
+ "description": "Information type specific job data",
+ "type": "object"
+ },
+ "status_notification_uri": {
+ "description": "The target of Information subscription job status notifications",
+ "type": "string"
+ }
+ }
+ },
+ "producer_status": {
+ "description": "Status for an Info Producer",
+ "type": "object",
+ "required": ["operational_state"],
+ "properties": {"operational_state": {
+ "description": "Represents the operational states",
+ "type": "string",
+ "enum": [
+ "ENABLED",
+ "DISABLED"
+ ]
+ }}
+ },
+ "Void": {
+ "description": "Void/empty ",
+ "type": "object"
+ },
+ "Link": {
+ "type": "object",
+ "properties": {
+ "templated": {"type": "boolean"},
+ "href": {"type": "string"}
+ }
+ },
+ "consumer_type_subscription_info": {
+ "description": "Information for an information type subscription",
+ "type": "object",
+ "required": [
+ "owner",
+ "status_result_uri"
+ ],
+ "properties": {
+ "owner": {
+ "description": "Identity of the owner of the subscription",
+ "type": "string"
+ },
+ "status_result_uri": {
+ "description": "The target URI of the subscribed information",
+ "type": "string"
+ }
+ }
+ }
+ }},
+ "openapi": "3.0.1",
+ "paths": {
+ "/data-producer/v1/info-types": {"get": {
+ "summary": "Info Type identifiers",
+ "operationId": "getInfoTypdentifiers",
+ "responses": {"200": {
+ "description": "Info Type identifiers",
+ "content": {"application/json": {"schema": {
+ "type": "array",
+ "items": {"type": "string"}
+ }}}
+ }},
+ "tags": ["Data producer (registration)"]
+ }},
+ "/actuator/threaddump": {"get": {
+ "summary": "Actuator web endpoint 'threaddump'",
+ "operationId": "threaddump_2",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"*/*": {"schema": {"type": "object"}}}
+ }},
+ "tags": ["Actuator"]
+ }},
+ "/A1-EI/v1/eitypes/{eiTypeId}": {"get": {
+ "summary": "Individual EI type",
+ "operationId": "getEiType",
+ "responses": {
+ "200": {
+ "description": "EI type",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EiTypeObject"}}}
+ },
+ "404": {
+ "description": "Enrichment Information type is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "eiTypeId",
+ "required": true
+ }],
+ "tags": ["A1-EI (registration)"]
+ }},
+ "/data-producer/v1/info-types/{infoTypeId}": {
+ "get": {
+ "summary": "Individual Information Type",
+ "operationId": "getInfoType",
+ "responses": {
+ "200": {
+ "description": "Info Type",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/producer_info_type_info"}}}
+ },
+ "404": {
+ "description": "Information type is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoTypeId",
+ "required": true
+ }],
+ "tags": ["Data producer (registration)"]
+ },
+ "delete": {
+ "summary": "Individual Information Type",
+ "operationId": "deleteInfoType",
+ "responses": {
+ "200": {
+ "description": "Not used",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "204": {
+ "description": "Producer deleted",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "404": {
+ "description": "Information type is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ },
+ "409": {
+ "description": "The Information type has one or several active producers",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoTypeId",
+ "required": true
+ }],
+ "tags": ["Data producer (registration)"]
+ },
+ "put": {
+ "summary": "Individual Information Type",
+ "requestBody": {
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/producer_info_type_info"}}},
+ "required": true
+ },
+ "operationId": "putInfoType",
+ "responses": {
+ "200": {
+ "description": "Type updated",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "201": {
+ "description": "Type created",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "400": {
+ "description": "Input validation failed",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoTypeId",
+ "required": true
+ }],
+ "tags": ["Data producer (registration)"]
+ }
+ },
+ "/data-consumer/v1/info-type-subscription/{subscriptionId}": {
+ "get": {
+ "summary": "Individual subscription for information types (registration/deregistration)",
+ "operationId": "getIndividualTypeSubscription",
+ "responses": {
+ "200": {
+ "description": "Type subscription",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/consumer_type_subscription_info"}}}
+ },
+ "404": {
+ "description": "Subscription is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "subscriptionId",
+ "required": true
+ }],
+ "tags": ["Data consumer"]
+ },
+ "delete": {
+ "summary": "Individual subscription for information types (registration/deregistration)",
+ "operationId": "deleteIndividualTypeSubscription",
+ "responses": {
+ "200": {
+ "description": "Not used",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "204": {
+ "description": "Subscription deleted",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "404": {
+ "description": "Subscription is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "subscriptionId",
+ "required": true
+ }],
+ "tags": ["Data consumer"]
+ },
+ "put": {
+ "summary": "Individual subscription for information types (registration/deregistration)",
+ "requestBody": {
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/consumer_type_subscription_info"}}},
+ "required": true
+ },
+ "description": "This service operation is used to subscribe to notifications for changes in the availability of data types.",
+ "operationId": "putIndividualTypeSubscription",
+ "responses": {
+ "200": {
+ "description": "Subscription updated",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "201": {
+ "description": "Subscription created",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "subscriptionId",
+ "required": true
+ }],
+ "tags": ["Data consumer"]
+ }
+ },
+ "/example-dataproducer/health-check": {"get": {
+ "summary": "Producer supervision",
+ "description": "The endpoint is provided by the Information Producer and is used for supervision of the producer.",
+ "operationId": "producerSupervision",
+ "responses": {"200": {
+ "description": "The producer is OK",
+ "content": {"application/json": {"schema": {"type": "string"}}}
+ }},
+ "tags": ["Data producer (callbacks)"]
+ }},
+ "/actuator/loggers": {"get": {
+ "summary": "Actuator web endpoint 'loggers'",
+ "operationId": "loggers",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"*/*": {"schema": {"type": "object"}}}
+ }},
+ "tags": ["Actuator"]
+ }},
+ "/actuator/health/**": {"get": {
+ "summary": "Actuator web endpoint 'health-path'",
+ "operationId": "health-path",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"*/*": {"schema": {"type": "object"}}}
+ }},
+ "tags": ["Actuator"]
+ }},
+ "/data-consumer/v1/info-types": {"get": {
+ "summary": "Information type identifiers",
+ "operationId": "getinfoTypeIdentifiers",
+ "responses": {"200": {
+ "description": "Information type identifiers",
+ "content": {"application/json": {"schema": {
+ "type": "array",
+ "items": {"type": "string"}
+ }}}
+ }},
+ "tags": ["Data consumer"]
+ }},
+ "/example-dataconsumer/info-type-status": {"post": {
+ "summary": "Callback for changed Information type registration status",
+ "requestBody": {
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/consumer_type_registration_info"}}},
+ "required": true
+ },
+ "description": "The primitive is implemented by the data consumer and is invoked when a Information type status has been changed. Subscription are managed by primitives in 'Data consumer'",
+ "operationId": "typeStatusCallback",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ }},
+ "tags": ["Data consumer (callbacks)"]
+ }},
+ "/actuator/metrics/{requiredMetricName}": {"get": {
+ "summary": "Actuator web endpoint 'metrics-requiredMetricName'",
+ "operationId": "metrics-requiredMetricName",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"*/*": {"schema": {"type": "object"}}}
+ }},
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "requiredMetricName",
+ "required": true
+ }],
+ "tags": ["Actuator"]
+ }},
+ "/actuator": {"get": {
+ "summary": "Actuator root web endpoint",
+ "operationId": "links",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"*/*": {"schema": {
+ "additionalProperties": {
+ "additionalProperties": {"$ref": "#/components/schemas/Link"},
+ "type": "object"
+ },
+ "type": "object"
+ }}}
+ }},
+ "tags": ["Actuator"]
+ }},
+ "/data-consumer/v1/info-jobs": {"get": {
+ "summary": "Information Job identifiers",
+ "description": "query for information job identifiers",
+ "operationId": "getJobIds",
+ "responses": {
+ "200": {
+ "description": "Information information job identifiers",
+ "content": {"application/json": {"schema": {
+ "type": "array",
+ "items": {"type": "string"}
+ }}}
+ },
+ "404": {
+ "description": "Information type is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [
+ {
+ "schema": {"type": "string"},
+ "in": "query",
+ "name": "infoTypeId",
+ "description": "selects subscription jobs of matching information type",
+ "required": false
+ },
+ {
+ "schema": {"type": "string"},
+ "in": "query",
+ "name": "owner",
+ "description": "selects result for one owner",
+ "required": false
+ }
+ ],
+ "tags": ["Data consumer"]
+ }},
+ "/actuator/loggers/{name}": {
+ "post": {
+ "summary": "Actuator web endpoint 'loggers-name'",
+ "operationId": "loggers-name",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"*/*": {"schema": {"type": "object"}}}
+ }},
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "name",
+ "required": true
+ }],
+ "tags": ["Actuator"]
+ },
+ "get": {
+ "summary": "Actuator web endpoint 'loggers-name'",
+ "operationId": "loggers-name_2",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"*/*": {"schema": {"type": "object"}}}
+ }},
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "name",
+ "required": true
+ }],
+ "tags": ["Actuator"]
+ }
+ },
+ "/example-dataproducer/info-job": {"post": {
+ "summary": "Callback for Information Job creation/modification",
+ "requestBody": {
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/producer_info_job_request"}}},
+ "required": true
+ },
+ "description": "The call is invoked to activate or to modify a data subscription. The endpoint is provided by the Information Producer.",
+ "operationId": "jobCreatedCallback",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ }},
+ "tags": ["Data producer (callbacks)"]
+ }},
+ "/example-dataproducer/info-job/{infoJobId}": {"delete": {
+ "summary": "Callback for Information Job deletion",
+ "description": "The call is invoked to terminate a data subscription. The endpoint is provided by the Information Producer.",
+ "operationId": "jobDeletedCallback",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ }},
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoJobId",
+ "required": true
+ }],
+ "tags": ["Data producer (callbacks)"]
+ }},
+ "/A1-EI/v1/eijobs/{eiJobId}/status": {"get": {
+ "summary": "EI job status",
+ "operationId": "getEiJobStatus_1",
+ "responses": {
+ "200": {
+ "description": "EI job status",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EiJobStatusObject"}}}
+ },
+ "404": {
+ "description": "Enrichment Information job is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "eiJobId",
+ "required": true
+ }],
+ "tags": ["A1-EI (registration)"]
+ }},
+ "/data-producer/v1/info-producers/{infoProducerId}/status": {"get": {
+ "summary": "Information producer status",
+ "operationId": "getInfoProducerStatus",
+ "responses": {
+ "200": {
+ "description": "Information producer status",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/producer_status"}}}
+ },
+ "404": {
+ "description": "Information producer is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoProducerId",
+ "required": true
+ }],
+ "tags": ["Data producer (registration)"]
+ }},
+ "/data-consumer/v1/info-jobs/{infoJobId}/status": {"get": {
+ "summary": "Job status",
+ "operationId": "getEiJobStatus",
+ "responses": {
+ "200": {
+ "description": "Information subscription job status",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/consumer_job_status"}}}
+ },
+ "404": {
+ "description": "Information subscription job is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoJobId",
+ "required": true
+ }],
+ "tags": ["Data consumer"]
+ }},
+ "/actuator/metrics": {"get": {
+ "summary": "Actuator web endpoint 'metrics'",
+ "operationId": "metrics",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"*/*": {"schema": {"type": "object"}}}
+ }},
+ "tags": ["Actuator"]
+ }},
+ "/example-dataconsumer/info-jobs/{infoJobId}/status": {"post": {
+ "summary": "Callback for changed Information Job status",
+ "requestBody": {
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EiJobStatusObject"}}},
+ "required": true
+ },
+ "description": "The primitive is implemented by the data consumer and is invoked when a Information Job status has been changed.",
+ "operationId": "jobStatusCallback",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ }},
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoJobId",
+ "required": true
+ }],
+ "tags": ["A1-EI (callbacks)"]
+ }},
+ "/actuator/info": {"get": {
+ "summary": "Actuator web endpoint 'info'",
+ "operationId": "info",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"*/*": {"schema": {"type": "object"}}}
+ }},
+ "tags": ["Actuator"]
+ }},
+ "/A1-EI/v1/eitypes": {"get": {
+ "summary": "EI type identifiers",
+ "operationId": "getEiTypeIdentifiers",
+ "responses": {"200": {
+ "description": "EI type identifiers",
+ "content": {"application/json": {"schema": {
+ "type": "array",
+ "items": {"type": "string"}
+ }}}
+ }},
+ "tags": ["A1-EI (registration)"]
+ }},
+ "/data-producer/v1/info-producers/{infoProducerId}": {
+ "get": {
+ "summary": "Individual Information Producer",
+ "operationId": "getInfoProducer",
+ "responses": {
+ "200": {
+ "description": "Information producer",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/producer_registration_info"}}}
+ },
+ "404": {
+ "description": "Information producer is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoProducerId",
+ "required": true
+ }],
+ "tags": ["Data producer (registration)"]
+ },
+ "delete": {
+ "summary": "Individual Information Producer",
+ "operationId": "deleteInfoProducer",
+ "responses": {
+ "200": {
+ "description": "Not used",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "204": {
+ "description": "Producer deleted",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "404": {
+ "description": "Producer is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoProducerId",
+ "required": true
+ }],
+ "tags": ["Data producer (registration)"]
+ },
+ "put": {
+ "summary": "Individual Information Producer",
+ "requestBody": {
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/producer_registration_info"}}},
+ "required": true
+ },
+ "operationId": "putInfoProducer",
+ "responses": {
+ "200": {
+ "description": "Producer updated",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "201": {
+ "description": "Producer created",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "400": {
+ "description": "Input validation failed",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ },
+ "404": {
+ "description": "Producer type not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoProducerId",
+ "required": true
+ }],
+ "tags": ["Data producer (registration)"]
+ }
+ },
+ "/status": {"get": {
+ "summary": "Returns status and statistics of this service",
+ "operationId": "getStatus",
+ "responses": {"200": {
+ "description": "Service is living",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/service_status_info"}}}
+ }},
+ "tags": ["Service status"]
+ }},
+ "/data-consumer/v1/info-type-subscription": {"get": {
+ "summary": "Information type subscription identifiers",
+ "description": "query for information type subscription identifiers",
+ "operationId": "getInfoTypeSubscriptions",
+ "responses": {"200": {
+ "description": "Information type subscription identifiers",
+ "content": {"application/json": {"schema": {
+ "type": "array",
+ "items": {"type": "string"}
+ }}}
+ }},
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "query",
+ "name": "owner",
+ "description": "selects result for one owner",
+ "required": false
+ }],
+ "tags": ["Data consumer"]
+ }},
+ "/A1-EI/v1/eijobs/{eiJobId}": {
+ "get": {
+ "summary": "Individual EI job",
+ "operationId": "getIndividualEiJob_1",
+ "responses": {
+ "200": {
+ "description": "EI job",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EiJobObject"}}}
+ },
+ "404": {
+ "description": "Enrichment Information job is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "eiJobId",
+ "required": true
+ }],
+ "tags": ["A1-EI (registration)"]
+ },
+ "delete": {
+ "summary": "Individual EI job",
+ "operationId": "deleteIndividualEiJob_1",
+ "responses": {
+ "200": {
+ "description": "Not used",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "204": {
+ "description": "Job deleted",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "404": {
+ "description": "Enrichment Information job is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "eiJobId",
+ "required": true
+ }],
+ "tags": ["A1-EI (registration)"]
+ },
+ "put": {
+ "summary": "Individual EI job",
+ "requestBody": {
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EiJobObject"}}},
+ "required": true
+ },
+ "operationId": "putIndividualEiJob",
+ "responses": {
+ "200": {
+ "description": "Job updated",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "201": {
+ "description": "Job created",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "400": {
+ "description": "Input validation failed",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ },
+ "404": {
+ "description": "Enrichment Information type is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ },
+ "409": {
+ "description": "Cannot modify job type",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "eiJobId",
+ "required": true
+ }],
+ "tags": ["A1-EI (registration)"]
+ }
+ },
+ "/actuator/logfile": {"get": {
+ "summary": "Actuator web endpoint 'logfile'",
+ "operationId": "logfile",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"*/*": {"schema": {"type": "object"}}}
+ }},
+ "tags": ["Actuator"]
+ }},
+ "/data-consumer/v1/info-jobs/{infoJobId}": {
+ "get": {
+ "summary": "Individual data subscription job",
+ "operationId": "getIndividualEiJob",
+ "responses": {
+ "200": {
+ "description": "Information subscription job",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/consumer_job"}}}
+ },
+ "404": {
+ "description": "Information subscription job is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoJobId",
+ "required": true
+ }],
+ "tags": ["Data consumer"]
+ },
+ "delete": {
+ "summary": "Individual data subscription job",
+ "operationId": "deleteIndividualEiJob",
+ "responses": {
+ "200": {
+ "description": "Not used",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "204": {
+ "description": "Job deleted",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "404": {
+ "description": "Information subscription job is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoJobId",
+ "required": true
+ }],
+ "tags": ["Data consumer"]
+ },
+ "put": {
+ "summary": "Individual data subscription job",
+ "requestBody": {
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/consumer_job"}}},
+ "required": true
+ },
+ "description": "The job will be enabled when a producer is available",
+ "operationId": "putIndividualInfoJob",
+ "responses": {
+ "200": {
+ "description": "Job updated",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "201": {
+ "description": "Job created",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
+ },
+ "400": {
+ "description": "Input validation failed",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ },
+ "404": {
+ "description": "Information type is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ },
+ "409": {
+ "description": "Cannot modify job type",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [
+ {
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoJobId",
+ "required": true
+ },
+ {
+ "schema": {
+ "default": false,
+ "type": "boolean"
+ },
+ "in": "query",
+ "name": "typeCheck",
+ "description": "when true, a validation of that the type exists and that the job matches the type schema.",
+ "required": false
+ }
+ ],
+ "tags": ["Data consumer"]
+ }
+ },
+ "/data-producer/v1/info-producers": {"get": {
+ "summary": "Information producer identifiers",
+ "operationId": "getInfoProducerIdentifiers",
+ "responses": {"200": {
+ "description": "Information producer identifiers",
+ "content": {"application/json": {"schema": {
+ "type": "array",
+ "items": {"type": "string"}
+ }}}
+ }},
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "query",
+ "name": "infoTypeId",
+ "description": "If given, only the producers for the EI Data type is returned.",
+ "required": false
+ }],
+ "tags": ["Data producer (registration)"]
+ }},
+ "/data-consumer/v1/info-types/{infoTypeId}": {"get": {
+ "summary": "Individual information type",
+ "operationId": "getInfoType_1",
+ "responses": {
+ "200": {
+ "description": "Information type",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/consumer_information_type"}}}
+ },
+ "404": {
+ "description": "Information type is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoTypeId",
+ "required": true
+ }],
+ "tags": ["Data consumer"]
+ }},
+ "/actuator/health": {"get": {
+ "summary": "Actuator web endpoint 'health'",
+ "operationId": "health",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"*/*": {"schema": {"type": "object"}}}
+ }},
+ "tags": ["Actuator"]
+ }},
+ "/A1-EI/v1/eijobs": {"get": {
+ "summary": "EI job identifiers",
+ "description": "query for EI job identifiers",
+ "operationId": "getEiJobIds",
+ "responses": {
+ "200": {
+ "description": "EI job identifiers",
+ "content": {"application/json": {"schema": {
+ "type": "array",
+ "items": {"type": "string"}
+ }}}
+ },
+ "404": {
+ "description": "Enrichment Information type is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [
+ {
+ "schema": {"type": "string"},
+ "in": "query",
+ "name": "eiTypeId",
+ "description": "selects EI jobs of matching EI type",
+ "required": false
+ },
+ {
+ "schema": {"type": "string"},
+ "in": "query",
+ "name": "owner",
+ "description": "selects EI jobs for one EI job owner",
+ "required": false
+ }
+ ],
+ "tags": ["A1-EI (registration)"]
+ }},
+ "/data-producer/v1/info-producers/{infoProducerId}/info-jobs": {"get": {
+ "summary": "Information Job definitions",
+ "description": "Information Job definitions for one Information Producer",
+ "operationId": "getInfoProducerJobs",
+ "responses": {
+ "200": {
+ "description": "Information producer",
+ "content": {"application/json": {"schema": {
+ "type": "array",
+ "items": {"$ref": "#/components/schemas/producer_info_job_request"}
+ }}}
+ },
+ "404": {
+ "description": "Information producer is not found",
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+ }
+ },
+ "parameters": [{
+ "schema": {"type": "string"},
+ "in": "path",
+ "name": "infoProducerId",
+ "required": true
+ }],
+ "tags": ["Data producer (registration)"]
+ }},
+ "/actuator/heapdump": {"get": {
+ "summary": "Actuator web endpoint 'heapdump'",
+ "operationId": "heapdump",
+ "responses": {"200": {
+ "description": "OK",
+ "content": {"*/*": {"schema": {"type": "object"}}}
+ }},
+ "tags": ["Actuator"]
+ }}
+ },
+ "info": {
+ "license": {
+ "name": "Copyright (C) 2020-2022 Nordix Foundation. Licensed under the Apache License.",
+ "url": "http://www.apache.org/licenses/LICENSE-2.0"
+ },
+ "description": "
API documentation<\/h1>
General<\/h2>
The service is mainly a broker between data producers and data consumers. A data producer has the ability to produce one or several types of data (Information Type). One type of data can be produced by zero to many producers.
A data consumer can have several active data subscriptions (Information Job). One Information Job consists of the type of data to produce and additional parameters for filtering of the data. These parameters are different for different data types.<\/p>
APIs provided by the service<\/h2>
A1-EI<\/h4>
This API is between Near-RT RIC and the Non-RT RIC. The Near-RT RIC is a data consumer, which creates Information Jobs to subscribe for data. In this context, the information is referred to as 'Enrichment Information', EI.<\/p>
Data producer API<\/h4>
This API is provided by the Non-RT RIC platform and is intended to be part of the O-RAN R1 interface. The API is for use by different kinds of data producers and provides support for:
Registry of supported information types and which parameters needed to setup a subscription.<\/li>
Registry of existing data producers.<\/li>
Callback API provided by producers to setup subscriptions.<\/li><\/ul><\/p>
Data consumer API<\/h4>
This API is provided by the Non-RT RIC platform and is intended to be part of the O-RAN R1 interface. The API is for use by different kinds of data consumers and provides support for:
Querying of available types of data to consume.<\/li>
Management of data subscription jobs<\/li>
Optional callback API provided by consumers to get notification on added and removed information types.<\/li><\/ul><\/p>
Service status<\/h4>
This API provides a means to monitor the health of this service.<\/p>",
+ "title": "Data management and exposure",
+ "version": "1.0"
+ },
+ "tags": [
+ {
+ "name": "A1-EI (registration)",
+ "description": "Data consumer EI job registration"
+ },
+ {
+ "name": "A1-EI (callbacks)",
+ "description": "Data consumer EI job status callbacks"
+ },
+ {
+ "name": "Data consumer (callbacks)",
+ "description": "API for data consumers"
+ },
+ {
+ "name": "Data producer (registration)",
+ "description": "API for data producers"
+ },
+ {
+ "name": "Data producer (callbacks)",
+ "description": "API implemented by data producers"
+ },
+ {
+ "name": "Data consumer",
+ "description": "API for data consumers"
+ },
+ {
+ "name": "Service status",
+ "description": "API for monitoring of the service"
+ },
+ {
+ "name": "Actuator",
+ "description": "Monitor and interact",
+ "externalDocs": {
+ "description": "Spring Boot Actuator Web API Documentation",
+ "url": "https://docs.spring.io/spring-boot/docs/current/actuator-api/html/"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/api/ics-api.yaml b/api/ics-api.yaml
new file mode 100644
index 0000000..be8fc94
--- /dev/null
+++ b/api/ics-api.yaml
@@ -0,0 +1,1486 @@
+openapi: 3.0.1
+info:
+ title: Data management and exposure
+ description:
API documentation
General
The service is mainly
+ a broker between data producers and data consumers. A data producer has the ability
+ to produce one or several types of data (Information Type). One type of data can
+ be produced by zero to many producers.
A data consumer can have several
+ active data subscriptions (Information Job). One Information Job consists of the
+ type of data to produce and additional parameters for filtering of the data. These
+ parameters are different for different data types.
APIs provided by the
+ service
A1-EI
This API is between Near-RT RIC and the Non-RT
+ RIC. The Near-RT RIC is a data consumer, which creates Information Jobs to subscribe
+ for data. In this context, the information is referred to as 'Enrichment Information',
+ EI.
Data producer API
This API is provided by the Non-RT RIC platform
+ and is intended to be part of the O-RAN R1 interface. The API is for use by different
+ kinds of data producers and provides support for:
Registry of supported
+ information types and which parameters needed to setup a subscription.
Registry
+ of existing data producers.
Callback API provided by producers to setup
+ subscriptions.
Data consumer API
This API is provided
+ by the Non-RT RIC platform and is intended to be part of the O-RAN R1 interface. The
+ API is for use by different kinds of data consumers and provides support for:
Querying
+ of available types of data to consume.
Management of data subscription
+ jobs
Optional callback API provided by consumers to get notification on
+ added and removed information types.
Service status
This
+ API provides a means to monitor the health of this service.
+ license:
+ name: Copyright (C) 2020-2022 Nordix Foundation. Licensed under the Apache License.
+ url: http://www.apache.org/licenses/LICENSE-2.0
+ version: "1.0"
+servers:
+- url: /
+tags:
+- name: A1-EI (registration)
+ description: Data consumer EI job registration
+- name: A1-EI (callbacks)
+ description: Data consumer EI job status callbacks
+- name: Data consumer (callbacks)
+ description: API for data consumers
+- name: Data producer (registration)
+ description: API for data producers
+- name: Data producer (callbacks)
+ description: API implemented by data producers
+- name: Data consumer
+ description: API for data consumers
+- name: Service status
+ description: API for monitoring of the service
+- name: Actuator
+ description: Monitor and interact
+ externalDocs:
+ description: Spring Boot Actuator Web API Documentation
+ url: https://docs.spring.io/spring-boot/docs/current/actuator-api/html/
+paths:
+ /data-producer/v1/info-types:
+ get:
+ tags:
+ - Data producer (registration)
+ summary: Info Type identifiers
+ operationId: getInfoTypdentifiers
+ responses:
+ 200:
+ description: Info Type identifiers
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: string
+ /actuator/threaddump:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'threaddump'
+ operationId: threaddump_2
+ responses:
+ 200:
+ description: OK
+ content:
+ '*/*':
+ schema:
+ type: object
+ /A1-EI/v1/eitypes/{eiTypeId}:
+ get:
+ tags:
+ - A1-EI (registration)
+ summary: Individual EI type
+ operationId: getEiType
+ parameters:
+ - name: eiTypeId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: EI type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EiTypeObject'
+ 404:
+ description: Enrichment Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /data-producer/v1/info-types/{infoTypeId}:
+ get:
+ tags:
+ - Data producer (registration)
+ summary: Individual Information Type
+ operationId: getInfoType
+ parameters:
+ - name: infoTypeId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Info Type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/producer_info_type_info'
+ 404:
+ description: Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ put:
+ tags:
+ - Data producer (registration)
+ summary: Individual Information Type
+ operationId: putInfoType
+ parameters:
+ - name: infoTypeId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/producer_info_type_info'
+ required: true
+ responses:
+ 200:
+ description: Type updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 201:
+ description: Type created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 400:
+ description: Input validation failed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ delete:
+ tags:
+ - Data producer (registration)
+ summary: Individual Information Type
+ operationId: deleteInfoType
+ parameters:
+ - name: infoTypeId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Not used
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 204:
+ description: Producer deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 404:
+ description: Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ 409:
+ description: The Information type has one or several active producers
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /data-consumer/v1/info-type-subscription/{subscriptionId}:
+ get:
+ tags:
+ - Data consumer
+ summary: Individual subscription for information types (registration/deregistration)
+ operationId: getIndividualTypeSubscription
+ parameters:
+ - name: subscriptionId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Type subscription
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/consumer_type_subscription_info'
+ 404:
+ description: Subscription is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ put:
+ tags:
+ - Data consumer
+ summary: Individual subscription for information types (registration/deregistration)
+ description: This service operation is used to subscribe to notifications for
+ changes in the availability of data types.
+ operationId: putIndividualTypeSubscription
+ parameters:
+ - name: subscriptionId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/consumer_type_subscription_info'
+ required: true
+ responses:
+ 200:
+ description: Subscription updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 201:
+ description: Subscription created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ delete:
+ tags:
+ - Data consumer
+ summary: Individual subscription for information types (registration/deregistration)
+ operationId: deleteIndividualTypeSubscription
+ parameters:
+ - name: subscriptionId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Not used
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 204:
+ description: Subscription deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 404:
+ description: Subscription is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /example-dataproducer/health-check:
+ get:
+ tags:
+ - Data producer (callbacks)
+ summary: Producer supervision
+ description: The endpoint is provided by the Information Producer and is used
+ for supervision of the producer.
+ operationId: producerSupervision
+ responses:
+ 200:
+ description: The producer is OK
+ content:
+ application/json:
+ schema:
+ type: string
+ /actuator/loggers:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'loggers'
+ operationId: loggers
+ responses:
+ 200:
+ description: OK
+ content:
+ '*/*':
+ schema:
+ type: object
+ /actuator/health/**:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'health-path'
+ operationId: health-path
+ responses:
+ 200:
+ description: OK
+ content:
+ '*/*':
+ schema:
+ type: object
+ /data-consumer/v1/info-types:
+ get:
+ tags:
+ - Data consumer
+ summary: Information type identifiers
+ operationId: getinfoTypeIdentifiers
+ responses:
+ 200:
+ description: Information type identifiers
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: string
+ /example-dataconsumer/info-type-status:
+ post:
+ tags:
+ - Data consumer (callbacks)
+ summary: Callback for changed Information type registration status
+ description: The primitive is implemented by the data consumer and is invoked
+ when a Information type status has been changed. Subscription are managed
+ by primitives in 'Data consumer'
+ operationId: typeStatusCallback
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/consumer_type_registration_info'
+ required: true
+ responses:
+ 200:
+ description: OK
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ /actuator/metrics/{requiredMetricName}:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'metrics-requiredMetricName'
+ operationId: metrics-requiredMetricName
+ parameters:
+ - name: requiredMetricName
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: OK
+ content:
+ '*/*':
+ schema:
+ type: object
+ /actuator:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator root web endpoint
+ operationId: links
+ responses:
+ 200:
+ description: OK
+ content:
+ '*/*':
+ schema:
+ type: object
+ additionalProperties:
+ type: object
+ additionalProperties:
+ $ref: '#/components/schemas/Link'
+ /data-consumer/v1/info-jobs:
+ get:
+ tags:
+ - Data consumer
+ summary: Information Job identifiers
+ description: query for information job identifiers
+ operationId: getJobIds
+ parameters:
+ - name: infoTypeId
+ in: query
+ description: selects subscription jobs of matching information type
+ required: false
+ style: form
+ explode: true
+ schema:
+ type: string
+ - name: owner
+ in: query
+ description: selects result for one owner
+ required: false
+ style: form
+ explode: true
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information information job identifiers
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: string
+ 404:
+ description: Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /actuator/loggers/{name}:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'loggers-name'
+ operationId: loggers-name_2
+ parameters:
+ - name: name
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: OK
+ content:
+ '*/*':
+ schema:
+ type: object
+ post:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'loggers-name'
+ operationId: loggers-name
+ parameters:
+ - name: name
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: OK
+ content:
+ '*/*':
+ schema:
+ type: object
+ /example-dataproducer/info-job:
+ post:
+ tags:
+ - Data producer (callbacks)
+ summary: Callback for Information Job creation/modification
+ description: The call is invoked to activate or to modify a data subscription.
+ The endpoint is provided by the Information Producer.
+ operationId: jobCreatedCallback
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/producer_info_job_request'
+ required: true
+ responses:
+ 200:
+ description: OK
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ /example-dataproducer/info-job/{infoJobId}:
+ delete:
+ tags:
+ - Data producer (callbacks)
+ summary: Callback for Information Job deletion
+ description: The call is invoked to terminate a data subscription. The endpoint
+ is provided by the Information Producer.
+ operationId: jobDeletedCallback
+ parameters:
+ - name: infoJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: OK
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ /A1-EI/v1/eijobs/{eiJobId}/status:
+ get:
+ tags:
+ - A1-EI (registration)
+ summary: EI job status
+ operationId: getEiJobStatus_1
+ parameters:
+ - name: eiJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: EI job status
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EiJobStatusObject'
+ 404:
+ description: Enrichment Information job is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /data-producer/v1/info-producers/{infoProducerId}/status:
+ get:
+ tags:
+ - Data producer (registration)
+ summary: Information producer status
+ operationId: getInfoProducerStatus
+ parameters:
+ - name: infoProducerId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information producer status
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/producer_status'
+ 404:
+ description: Information producer is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /data-consumer/v1/info-jobs/{infoJobId}/status:
+ get:
+ tags:
+ - Data consumer
+ summary: Job status
+ operationId: getEiJobStatus
+ parameters:
+ - name: infoJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information subscription job status
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/consumer_job_status'
+ 404:
+ description: Information subscription job is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /actuator/metrics:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'metrics'
+ operationId: metrics
+ responses:
+ 200:
+ description: OK
+ content:
+ '*/*':
+ schema:
+ type: object
+ /example-dataconsumer/info-jobs/{infoJobId}/status:
+ post:
+ tags:
+ - A1-EI (callbacks)
+ summary: Callback for changed Information Job status
+ description: The primitive is implemented by the data consumer and is invoked
+ when a Information Job status has been changed.
+ operationId: jobStatusCallback
+ parameters:
+ - name: infoJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EiJobStatusObject'
+ required: true
+ responses:
+ 200:
+ description: OK
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ /actuator/info:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'info'
+ operationId: info
+ responses:
+ 200:
+ description: OK
+ content:
+ '*/*':
+ schema:
+ type: object
+ /A1-EI/v1/eitypes:
+ get:
+ tags:
+ - A1-EI (registration)
+ summary: EI type identifiers
+ operationId: getEiTypeIdentifiers
+ responses:
+ 200:
+ description: EI type identifiers
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: string
+ /data-producer/v1/info-producers/{infoProducerId}:
+ get:
+ tags:
+ - Data producer (registration)
+ summary: Individual Information Producer
+ operationId: getInfoProducer
+ parameters:
+ - name: infoProducerId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information producer
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/producer_registration_info'
+ 404:
+ description: Information producer is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ put:
+ tags:
+ - Data producer (registration)
+ summary: Individual Information Producer
+ operationId: putInfoProducer
+ parameters:
+ - name: infoProducerId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/producer_registration_info'
+ required: true
+ responses:
+ 200:
+ description: Producer updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 201:
+ description: Producer created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 400:
+ description: Input validation failed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ 404:
+ description: Producer type not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ delete:
+ tags:
+ - Data producer (registration)
+ summary: Individual Information Producer
+ operationId: deleteInfoProducer
+ parameters:
+ - name: infoProducerId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Not used
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 204:
+ description: Producer deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 404:
+ description: Producer is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /status:
+ get:
+ tags:
+ - Service status
+ summary: Returns status and statistics of this service
+ operationId: getStatus
+ responses:
+ 200:
+ description: Service is living
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/service_status_info'
+ /data-consumer/v1/info-type-subscription:
+ get:
+ tags:
+ - Data consumer
+ summary: Information type subscription identifiers
+ description: query for information type subscription identifiers
+ operationId: getInfoTypeSubscriptions
+ parameters:
+ - name: owner
+ in: query
+ description: selects result for one owner
+ required: false
+ style: form
+ explode: true
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information type subscription identifiers
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: string
+ /A1-EI/v1/eijobs/{eiJobId}:
+ get:
+ tags:
+ - A1-EI (registration)
+ summary: Individual EI job
+ operationId: getIndividualEiJob_1
+ parameters:
+ - name: eiJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: EI job
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EiJobObject'
+ 404:
+ description: Enrichment Information job is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ put:
+ tags:
+ - A1-EI (registration)
+ summary: Individual EI job
+ operationId: putIndividualEiJob
+ parameters:
+ - name: eiJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EiJobObject'
+ required: true
+ responses:
+ 200:
+ description: Job updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 201:
+ description: Job created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 400:
+ description: Input validation failed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ 404:
+ description: Enrichment Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ 409:
+ description: Cannot modify job type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ delete:
+ tags:
+ - A1-EI (registration)
+ summary: Individual EI job
+ operationId: deleteIndividualEiJob_1
+ parameters:
+ - name: eiJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Not used
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 204:
+ description: Job deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 404:
+ description: Enrichment Information job is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /actuator/logfile:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'logfile'
+ operationId: logfile
+ responses:
+ 200:
+ description: OK
+ content:
+ '*/*':
+ schema:
+ type: object
+ /data-consumer/v1/info-jobs/{infoJobId}:
+ get:
+ tags:
+ - Data consumer
+ summary: Individual data subscription job
+ operationId: getIndividualEiJob
+ parameters:
+ - name: infoJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information subscription job
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/consumer_job'
+ 404:
+ description: Information subscription job is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ put:
+ tags:
+ - Data consumer
+ summary: Individual data subscription job
+ description: The job will be enabled when a producer is available
+ operationId: putIndividualInfoJob
+ parameters:
+ - name: infoJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ - name: typeCheck
+ in: query
+ description: when true, a validation of that the type exists and that the
+ job matches the type schema.
+ required: false
+ style: form
+ explode: true
+ schema:
+ type: boolean
+ default: false
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/consumer_job'
+ required: true
+ responses:
+ 200:
+ description: Job updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 201:
+ description: Job created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 400:
+ description: Input validation failed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ 404:
+ description: Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ 409:
+ description: Cannot modify job type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ delete:
+ tags:
+ - Data consumer
+ summary: Individual data subscription job
+ operationId: deleteIndividualEiJob
+ parameters:
+ - name: infoJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Not used
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 204:
+ description: Job deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 404:
+ description: Information subscription job is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /data-producer/v1/info-producers:
+ get:
+ tags:
+ - Data producer (registration)
+ summary: Information producer identifiers
+ operationId: getInfoProducerIdentifiers
+ parameters:
+ - name: infoTypeId
+ in: query
+ description: If given, only the producers for the EI Data type is returned.
+ required: false
+ style: form
+ explode: true
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information producer identifiers
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: string
+ /data-consumer/v1/info-types/{infoTypeId}:
+ get:
+ tags:
+ - Data consumer
+ summary: Individual information type
+ operationId: getInfoType_1
+ parameters:
+ - name: infoTypeId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/consumer_information_type'
+ 404:
+ description: Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /actuator/health:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'health'
+ operationId: health
+ responses:
+ 200:
+ description: OK
+ content:
+ '*/*':
+ schema:
+ type: object
+ /A1-EI/v1/eijobs:
+ get:
+ tags:
+ - A1-EI (registration)
+ summary: EI job identifiers
+ description: query for EI job identifiers
+ operationId: getEiJobIds
+ parameters:
+ - name: eiTypeId
+ in: query
+ description: selects EI jobs of matching EI type
+ required: false
+ style: form
+ explode: true
+ schema:
+ type: string
+ - name: owner
+ in: query
+ description: selects EI jobs for one EI job owner
+ required: false
+ style: form
+ explode: true
+ schema:
+ type: string
+ responses:
+ 200:
+ description: EI job identifiers
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: string
+ 404:
+ description: Enrichment Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /data-producer/v1/info-producers/{infoProducerId}/info-jobs:
+ get:
+ tags:
+ - Data producer (registration)
+ summary: Information Job definitions
+ description: Information Job definitions for one Information Producer
+ operationId: getInfoProducerJobs
+ parameters:
+ - name: infoProducerId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information producer
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/producer_info_job_request'
+ 404:
+ description: Information producer is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /actuator/heapdump:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'heapdump'
+ operationId: heapdump
+ responses:
+ 200:
+ description: OK
+ content:
+ '*/*':
+ schema:
+ type: object
+components:
+ schemas:
+ consumer_information_type:
+ required:
+ - job_data_schema
+ - no_of_producers
+ - type_status
+ type: object
+ properties:
+ no_of_producers:
+ type: integer
+ description: The number of registered producers for the type
+ format: int32
+ type_status:
+ type: string
+ description: 'Allowed values: ENABLED: one or several producers for
+ the information type are available DISABLED: no producers for the
+ information type are available'
+ enum:
+ - ENABLED
+ - DISABLED
+ job_data_schema:
+ type: object
+ description: Json schema for the job data
+ description: Information for an Information type
+ EiTypeObject:
+ type: object
+ description: Information for an EI type
+ service_status_info:
+ required:
+ - no_of_jobs
+ - no_of_producers
+ - no_of_types
+ - status
+ type: object
+ properties:
+ no_of_producers:
+ type: integer
+ description: Number of Information Producers
+ format: int32
+ no_of_types:
+ type: integer
+ description: Number of Information Types
+ format: int32
+ no_of_jobs:
+ type: integer
+ description: Number of Information Jobs
+ format: int32
+ status:
+ type: string
+ description: status text
+ producer_registration_info:
+ required:
+ - info_job_callback_url
+ - info_producer_supervision_callback_url
+ - supported_info_types
+ type: object
+ properties:
+ info_producer_supervision_callback_url:
+ type: string
+ description: callback for producer supervision
+ supported_info_types:
+ type: array
+ description: Supported Information Type IDs
+ items:
+ type: string
+ description: Supported Information Type IDs
+ info_job_callback_url:
+ type: string
+ description: callback for Information Job
+ description: Information for an Information Producer
+ consumer_type_registration_info:
+ required:
+ - info_type_id
+ - job_data_schema
+ - status
+ type: object
+ properties:
+ info_type_id:
+ type: string
+ description: Information type identifier
+ job_data_schema:
+ type: object
+ description: Json schema for the job data
+ status:
+ type: string
+ description: 'Allowed values: REGISTERED: the information type has
+ been registered DEREGISTERED: the information type has been removed'
+ enum:
+ - REGISTERED
+ - DEREGISTERED
+ description: Information for an Information type
+ ProblemDetails:
+ type: object
+ properties:
+ detail:
+ type: string
+ description: A human-readable explanation specific to this occurrence of
+ the problem.
+ example: Information Job type 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: A problem detail to carry details in a HTTP response according
+ to RFC 7807
+ EiJobStatusObject:
+ required:
+ - eiJobStatus
+ type: object
+ properties:
+ eiJobStatus:
+ type: string
+ description: 'Allowed values for EI job status: ENABLED: the A1-EI
+ producer is able to deliver EI result for the EI job DISABLED: the
+ A1-EI producer is unable to deliver EI result for the EI job'
+ enum:
+ - ENABLED
+ - DISABLED
+ description: Status for an EI job
+ consumer_job_status:
+ required:
+ - info_job_status
+ - producers
+ type: object
+ properties:
+ info_job_status:
+ type: string
+ description: 'Allowed values: ENABLED: the A1-Information producer
+ is able to deliver result for the Information Job DISABLED: the A1-Information
+ producer is unable to deliver result for the Information Job'
+ enum:
+ - ENABLED
+ - DISABLED
+ producers:
+ type: array
+ description: An array of all registered Information Producer Identifiers.
+ items:
+ type: string
+ description: An array of all registered Information Producer Identifiers.
+ description: Status for an Information Job
+ EiJobObject:
+ required:
+ - eiTypeId
+ - jobDefinition
+ - jobOwner
+ - jobResultUri
+ type: object
+ properties:
+ eiTypeId:
+ type: string
+ description: EI type Idenitifier of the EI job
+ jobResultUri:
+ type: string
+ description: The target URI of the EI data
+ jobOwner:
+ type: string
+ description: Identity of the owner of the job
+ statusNotificationUri:
+ type: string
+ description: The target of EI job status notifications
+ jobDefinition:
+ type: object
+ description: EI type specific job data
+ description: Information for an Enrichment Information Job
+ producer_info_type_info:
+ required:
+ - info_job_data_schema
+ type: object
+ properties:
+ info_type_information:
+ type: object
+ description: Type specific information for the information type
+ info_job_data_schema:
+ type: object
+ description: Json schema for the job data
+ description: Information for an Information Type
+ producer_info_job_request:
+ required:
+ - info_job_identity
+ type: object
+ properties:
+ owner:
+ type: string
+ description: The owner of the job
+ last_updated:
+ type: string
+ description: The time when the job was last updated or created (ISO-8601)
+ info_job_identity:
+ type: string
+ description: Identity of the Information Job
+ target_uri:
+ type: string
+ description: URI for the target of the produced Information
+ info_job_data:
+ type: object
+ description: Json for the job data
+ info_type_identity:
+ type: string
+ description: Type identity for the job
+ description: The body of the Information Producer callbacks for Information
+ Job creation and deletion
+ consumer_job:
+ required:
+ - info_type_id
+ - job_definition
+ - job_owner
+ - job_result_uri
+ type: object
+ properties:
+ info_type_id:
+ type: string
+ description: Information type Idenitifier of the subscription job
+ job_result_uri:
+ type: string
+ description: The target URI of the subscribed information
+ job_owner:
+ type: string
+ description: Identity of the owner of the job
+ job_definition:
+ type: object
+ description: Information type specific job data
+ status_notification_uri:
+ type: string
+ description: The target of Information subscription job status notifications
+ description: Information for an Information Job
+ producer_status:
+ required:
+ - operational_state
+ type: object
+ properties:
+ operational_state:
+ type: string
+ description: Represents the operational states
+ enum:
+ - ENABLED
+ - DISABLED
+ description: Status for an Info Producer
+ Void:
+ type: object
+ description: 'Void/empty '
+ Link:
+ type: object
+ properties:
+ templated:
+ type: boolean
+ href:
+ type: string
+ consumer_type_subscription_info:
+ required:
+ - owner
+ - status_result_uri
+ type: object
+ properties:
+ owner:
+ type: string
+ description: Identity of the owner of the subscription
+ status_result_uri:
+ type: string
+ description: The target URI of the subscribed information
+ description: Information for an information type subscription
diff --git a/config/README b/config/README
new file mode 100644
index 0000000..140927f
--- /dev/null
+++ b/config/README
@@ -0,0 +1,41 @@
+The keystore.jks and truststore.jks files are created by using the following commands (note that this is an example):
+
+1) Create a CA certificate and a private key:
+
+openssl genrsa -des3 -out CA-key.pem 2048
+openssl req -new -key CA-key.pem -x509 -days 1000 -out CA-cert.pem
+
+2) Create a keystore with a private key entry that is signed by the CA:
+
+keytool -genkeypair -alias policy_agent -keyalg RSA -keysize 2048 -keystore keystore.jks -validity 3650 -storepass policy_agent
+keytool -certreq -alias policy_agent -file request.csr -keystore keystore.jks -ext san=dns:your.domain.com -storepass policy_agent
+openssl x509 -req -days 365 -in request.csr -CA CA-cert.pem -CAkey CA-key.pem -CAcreateserial -out ca_signed-cert.pem
+keytool -importcert -alias ca_cert -file CA-cert.pem -keystore keystore.jks -trustcacerts -storepass policy_agent
+keytool -importcert -alias policy_agent -file ca_signed-cert.pem -keystore keystore.jks -trustcacerts -storepass policy_agent
+
+
+3) Create a trust store containing the CA cert (to trust all certs signed by the CA):
+
+keytool -genkeypair -alias not_used -keyalg RSA -keysize 2048 -keystore truststore.jks -validity 3650 -storepass policy_agent
+keytool -importcert -alias ca_cert -file CA-cert.pem -keystore truststore.jks -trustcacerts -storepass policy_agent
+
+
+4) Command for listing of the contents of jks files, examples:
+keytool -list -v -keystore keystore.jks -storepass policy_agent
+keytool -list -v -keystore truststore.jks -storepass policy_agent
+
+## 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/config/application.yaml b/config/application.yaml
new file mode 100644
index 0000000..372b61c
--- /dev/null
+++ b/config/application.yaml
@@ -0,0 +1,52 @@
+spring:
+ profiles:
+ active: prod
+ main:
+ allow-bean-definition-overriding: true
+ aop:
+ auto: false
+springdoc:
+ show-actuator: true
+management:
+ endpoints:
+ web:
+ exposure:
+ # Enabling of springboot actuator features. See springboot documentation.
+ include: "loggers,logfile,health,info,metrics,threaddump,heapdump"
+
+logging:
+ # Configuration of logging
+ level:
+ ROOT: ERROR
+ org.springframework: ERROR
+ org.springframework.data: ERROR
+ org.springframework.web.reactive.function.client.ExchangeFunctions: ERROR
+ org.oransc.ics: INFO
+ file:
+ name: /var/log/information-coordinator-service/application.log
+server:
+ # Configuration of the HTTP/REST server. The parameters are defined and handeled by the springboot framework.
+ # See springboot documentation.
+ port : 8434
+ http-port: 8083
+ ssl:
+ key-store-type: JKS
+ key-store-password: policy_agent
+ key-store: /opt/app/information-coordinator-service/etc/cert/keystore.jks
+ key-password: policy_agent
+ key-alias: policy_agent
+app:
+ webclient:
+ # Configuration of the trust store used for the HTTP client (outgoing requests)
+ # The file location and the password for the truststore is only relevant if trust-store-used == true
+ # Note that the same keystore as for the server is used.
+ trust-store-used: false
+ trust-store-password: policy_agent
+ trust-store: /opt/app/information-coordinator-service/etc/cert/truststore.jks
+ # Configuration of usage of HTTP Proxy for the southbound accesses.
+ # The HTTP proxy (if configured) will only be used for accessing NearRT RIC:s
+ http.proxy-host:
+ http.proxy-port: 0
+ vardata-directory: /var/information-coordinator-service
+ # If the file name is empty, no authorzation token is sent
+ auth-token-file:
\ No newline at end of file
diff --git a/config/keystore.jks b/config/keystore.jks
new file mode 100644
index 0000000..122997a
Binary files /dev/null and b/config/keystore.jks differ
diff --git a/config/truststore.jks b/config/truststore.jks
new file mode 100644
index 0000000..60d6288
Binary files /dev/null and b/config/truststore.jks differ
diff --git a/docs/_static/logo.png b/docs/_static/logo.png
new file mode 100644
index 0000000..c3b6ce5
Binary files /dev/null and b/docs/_static/logo.png differ
diff --git a/docs/api-docs.rst b/docs/api-docs.rst
new file mode 100644
index 0000000..fee0f20
--- /dev/null
+++ b/docs/api-docs.rst
@@ -0,0 +1,31 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. Copyright (C) 2021 Nordix
+
+.. _api_docs:
+
+.. |swagger-icon| image:: ./images/swagger.png
+ :width: 40px
+
+.. |yaml-icon| image:: ./images/yaml_logo.png
+ :width: 40px
+
+
+========
+API-Docs
+========
+
+Here we describe the APIs to access the Non-RT RIC Information Coordination Service.
+
+Information Coordinator Service
+===============================
+
+See `A1 Information Information Coordination Service API <./ics-api.html>`_ for full details of the API.
+
+The API is also described in Swagger-JSON and YAML:
+
+.. csv-table::
+ :header: "API name", "|swagger-icon|", "|yaml-icon|"
+ :widths: 10,5,5
+
+ "A1 Information Coordination Service API", ":download:`link <../api/ics-api.json>`", ":download:`link <../api/ics-api.yaml>`"
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..496a7a3
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,30 @@
+from docs_conf.conf import *
+
+#branch configuration
+
+branch = 'latest'
+
+linkcheck_ignore = [
+ 'http://localhost.*',
+ 'http://127.0.0.1.*',
+ 'https://gerrit.o-ran-sc.org.*',
+ './ics-api.html', #Generated file that doesn't exist at link check.
+]
+
+extensions = ['sphinxcontrib.redoc', 'sphinx.ext.intersphinx',]
+
+redoc = [
+ {
+ 'name': 'ICS API',
+ 'page': 'ics-api',
+ 'spec': '../api/ics-api.json',
+ 'embed': True,
+ }
+ ]
+
+redoc_uri = 'https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js'
+
+#intershpinx mapping with other projects
+intersphinx_mapping = {}
+
+intersphinx_mapping['nonrtric-controlpanel'] = ('https://docs.o-ran-sc.org/projects/o-ran-sc-portal-nonrtric-controlpanel/en/%s' % branch, None)
diff --git a/docs/conf.yaml b/docs/conf.yaml
new file mode 100644
index 0000000..0e8d0f9
--- /dev/null
+++ b/docs/conf.yaml
@@ -0,0 +1,3 @@
+---
+project_cfg: oran
+project: nonrtric-plt-informationcoordinatorservice
diff --git a/docs/developer-guide.rst b/docs/developer-guide.rst
new file mode 100644
index 0000000..d4f4cf2
--- /dev/null
+++ b/docs/developer-guide.rst
@@ -0,0 +1,65 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. SPDX-License-Identifier: CC-BY-4.0
+.. Copyright (C) 2021 Nordix
+
+Developer Guide
+===============
+
+This document provides a quickstart for developers of the Non-RT RIC Information Coordinator Service.
+
+Additional developer guides are available on the `O-RAN SC NONRTRIC Developer wiki `_.
+
+Information Coordinator Service
+-------------------------------
+The Information Coordinator Service is a Java 11 web application built using the Spring Framework. Using Spring Boot
+dependencies, it runs as a standalone application.
+
+Its main functionality is to act as a data subscription broker and to decouple data producer from data consumers.
+
+See the ./config/README file in the *information-coordinator-service* directory Gerrit repo on how to create and setup
+the certificates and private keys needed for HTTPS.
+
+Start standalone
+++++++++++++++++
+
+The project uses Maven. To start the Information Coordinator Service as a freestanding application, run the following
+command in the *information-coordinator-service* directory:
+
+ +-----------------------------+
+ | mvn spring-boot:run |
+ +-----------------------------+
+
+There are a few files that needs to be available to run. These are referred to from the application.yaml file.
+The following properties have to be modified:
+
+* server.ssl.key-store=./config/keystore.jks
+* app.webclient.trust-store=./config/truststore.jks
+* app.vardata-directory=./target
+
+Start in Docker
++++++++++++++++
+
+To build and deploy the Information Coordinator Service, go to the "information-coordinator-service" folder and run the
+following command:
+
+ +-----------------------------+
+ | mvn clean install |
+ +-----------------------------+
+
+Then start the container by running the following command:
+
+ +--------------------------------------------------------------------+
+ | docker run nonrtric-information-coordinator-service |
+ +--------------------------------------------------------------------+
+
+Kubernetes deployment
+---------------------
+
+Non-RT RIC can be also deployed in a Kubernetes cluster, `it/dep repository `_.
+hosts deployment and integration artifacts. Instructions and helm charts to deploy the Non-RT-RIC functions in the
+OSC NONRTRIC integrated test environment can be found in the *./nonrtric* directory.
+
+For more information on installation of NonRT-RIC in Kubernetes, see `Deploy NONRTRIC in Kubernetes `_.
+
+For more information see `Integration and Testing documentation on the O-RAN-SC wiki `_.
+
diff --git a/docs/favicon.ico b/docs/favicon.ico
new file mode 100644
index 0000000..00b0fd0
Binary files /dev/null and b/docs/favicon.ico differ
diff --git a/docs/images/swagger.png b/docs/images/swagger.png
new file mode 100644
index 0000000..f5a9e0c
Binary files /dev/null and b/docs/images/swagger.png differ
diff --git a/docs/images/yaml_logo.png b/docs/images/yaml_logo.png
new file mode 100644
index 0000000..0492eb4
Binary files /dev/null and b/docs/images/yaml_logo.png differ
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..0d33cd5
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,18 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. SPDX-License-Identifier: CC-BY-4.0
+.. Copyright (C) 2021 Nordix
+
+Non-RT RIC Information Coordination Service
+===========================================
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ ./overview.rst
+ ./developer-guide.rst
+ ./api-docs.rst
+ ./installation-guide.rst
+ ./release-notes.rst
+
+* :ref:`search`
diff --git a/docs/installation-guide.rst b/docs/installation-guide.rst
new file mode 100644
index 0000000..1837152
--- /dev/null
+++ b/docs/installation-guide.rst
@@ -0,0 +1,41 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. Copyright (C) 2021 Nordix
+
+Installation Guide
+==================
+
+Abstract
+--------
+
+This document describes how to install the Non-RT RIC components, their dependencies and required system resources.
+
+Software Installation and Deployment
+------------------------------------
+
+Install with Docker
++++++++++++++++++++
+
+Docker compose files are provided, in the "docker-compose" folder, to install the components. Run the following
+command to start the components:
+
+ .. code-block:: bash
+
+ docker-compose -f docker-compose.yaml
+ -f policy-service/docker-compose.yaml
+ -f ics/docker-compose.yaml
+
+The example above is just an example to start some of the components.
+For more information on running and configuring the functions can be found in the README file in the "`docker-compose `__" folder, and on the `wiki page `_
+
+Install with Helm
++++++++++++++++++
+
+Helm charts and an example recipe are provided in the `it/dep repo `_,
+under "nonrtric". By modifying the variables named "installXXX" in the beginning of the example recipe file, which
+components that will be installed can be controlled. Then the components can be installed and started by running the
+following command:
+
+ .. code-block:: bash
+
+ bin/deploy-nonrtric -f nonrtric/RECIPE_EXAMPLE/example_recipe.yaml
diff --git a/docs/overview.rst b/docs/overview.rst
new file mode 100644
index 0000000..a2c15b1
--- /dev/null
+++ b/docs/overview.rst
@@ -0,0 +1,26 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. SPDX-License-Identifier: CC-BY-4.0
+.. Copyright (C) 2021 Nordix
+
+Information Coordination Service
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Coordinate/Register Information Types, Producers, Consumers, and Jobs.
+
+Coordinate/Register A1-EI Types, Producers, Consumers, and Jobs (A1 Enrichment Information Job Coordination).
+
+* Maintains a registry of:
+
+ + Information Types / schemas
+ + Information Producers
+ + Information Consumers
+ + Information Jobs
+
+* Information Query API (e.g. per producer, per consumer, per types).
+* Query status of Information jobs.
+* After Information-type/Producer/Consumer/Job is successfully registered delivery/flow can happen directly between Information Producers and Information Consumers.
+* The Information Coordinator Service natively supports the O-RAN A1 Enrichment Information (A1-EI) interface, supporting coordination A1-EI Jobs where information (A1-EI)flow from the SMO/Non-RT-RIC/rApps to near-RT-RICs over the A1 interface.
+
+Implementation:
+
+* Implemented as a Java Spring Boot application.
diff --git a/docs/release-notes.rst b/docs/release-notes.rst
new file mode 100644
index 0000000..7d02112
--- /dev/null
+++ b/docs/release-notes.rst
@@ -0,0 +1,133 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. Copyright (C) 2021 Nordix
+
+=============
+Release-Notes
+=============
+
+
+This document provides the release notes for the release of the Non-RT RIC Information Coordination Service.
+
+
+Version history Information Coordinator Service
+===============================================
+
++------------+----------+------------------+--------------------+
+| **Date** | **Ver.** | **Author** | **Comment** |
+| | | | |
++------------+----------+------------------+--------------------+
+| 2020-12-03 | 1.0.0 | Henrik Andersson | Cherry Release |
+| | | | |
++------------+----------+------------------+--------------------+
+| 2021-06-23 | 1.1.0 | Henrik Andersson | D Release |
+| | | | |
++------------+----------+------------------+--------------------+
+| 2021-12-13 | 1.2.0 | Henrik Andersson | E Release |
+| | | | Renamed and minor |
+| | | | improvements |
++------------+----------+------------------+--------------------+
+| 2022-02-07 | 1.2.1 | Henrik Andersson | E Maintenance |
+| | | | Release |
+| | | | Non root user in |
+| | | | Docker |
++------------+----------+------------------+--------------------+
+
+
+Release Data
+============
+
+Cherry
+------
++-----------------------------+---------------------------------------------------+
+| **Project** | Non-RT RIC |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Repo/commit-ID** | nonrtric/90ce16238dd6970153e1c0fbddb15e32c68c504f |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Release designation** | Cherry |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Release date** | 2020-12-03 |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Purpose of the delivery** | Introduction of Enrichment Service Coordinator |
+| | |
++-----------------------------+---------------------------------------------------+
+
+D
+-
++-----------------------------+---------------------------------------------------+
+| **Project** | Non-RT RIC |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Repo/commit-ID** | nonrtric/dd3ebfd784e96919a00ddd745826f8a8e074c66f |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Release designation** | D |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Release date** | 2021-06-23 |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Purpose of the delivery** | Improvements |
+| | |
++-----------------------------+---------------------------------------------------+
+
+D Maintenance
+-------------
++-----------------------------+---------------------------------------------------+
+| **Project** | Non-RT RIC |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Repo/commit-ID** | nonrtric/973ae56894fb29a929fba9e344cae42e7607087b |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Release designation** | D |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Release date** | 2021-08-10 |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Purpose of the delivery** | Minor bug fixes |
++-----------------------------+---------------------------------------------------+
+
+E Release
+---------
++-----------------------------+---------------------------------------------------+
+| **Project** | Non-RT RIC |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Repo/commit-ID** | nonrtric/b472c167413a55a42fc7bfa08d2138f967a204fb |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Release designation** | E |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Release date** | 2021-12-13 |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Purpose of the delivery** | Improvements and renaming. |
+| | |
++-----------------------------+---------------------------------------------------+
+
+E Maintenance Release
+---------------------
++-----------------------------+---------------------------------------------------+
+| **Project** | Non-RT RIC |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Repo/commit-ID** | nonrtric/4df1f9ca4cd1ebc21e0c5ea57bcb0b7ef096d067 |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Release designation** | E |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Release date** | 2022-02-09 |
+| | |
++-----------------------------+---------------------------------------------------+
+| **Purpose of the delivery** | Improvements and bug fixes |
+| | |
++-----------------------------+---------------------------------------------------+
+
diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt
new file mode 100644
index 0000000..692a79f
--- /dev/null
+++ b/docs/requirements-docs.txt
@@ -0,0 +1,12 @@
+tox
+Sphinx
+doc8
+docutils
+setuptools
+six
+sphinx_rtd_theme
+sphinxcontrib-needs
+sphinxcontrib-swaggerdoc
+sphinx_bootstrap_theme
+sphinxcontrib-redoc
+lfdocs-conf
\ No newline at end of file
diff --git a/eclipse-formatter.xml b/eclipse-formatter.xml
new file mode 100644
index 0000000..c8cca2e
--- /dev/null
+++ b/eclipse-formatter.xml
@@ -0,0 +1,314 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..ce3abf3
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,354 @@
+
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.6
+
+
+ org.o-ran-sc.nonrtric
+ nonrtric-plt-informationcoordinatorservice
+ 1.3.0-SNAPSHOT
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+ onap-releases
+ onap-releases
+ https://nexus.onap.org/content/repositories/releases/
+
+
+
+ 11
+ 3.0.0
+ 2.8.2
+ 2.1.13
+ 20211205
+ 3.8.0
+ 2.12.2
+ 1.24.3
+ 3.0.11
+ 0.30.0
+ 3.7.0.1746
+ 0.8.5
+ true
+
+
+
+ org.springdoc
+ springdoc-openapi-ui
+ 1.6.6
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+ org.springframework
+ spring-webflux
+
+
+ io.swagger.core.v3
+ swagger-jaxrs2
+ ${swagger.version}
+
+
+ io.swagger.core.v3
+ swagger-jaxrs2-servlet-initializer
+ ${swagger.version}
+
+
+ org.immutables
+ value
+ ${immutable.version}
+ provided
+
+
+ org.immutables
+ gson
+ ${immutable.version}
+
+
+ org.json
+ json
+ ${json.version}
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ com.github.erosb
+ everit-json-schema
+ 1.12.1
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+ io.springfox
+ springfox-swagger2
+ ${springfox.version}
+
+
+ io.springfox
+ springfox-swagger-ui
+ ${springfox.version}
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.awaitility
+ awaitility
+ test
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ test
+
+
+ org.mockito
+ mockito-core
+ test
+
+
+ com.squareup.okhttp3
+ mockwebserver
+ test
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ net.revelc.code.formatter
+ formatter-maven-plugin
+ ${formatter-maven-plugin.version}
+
+ ${project.basedir}/eclipse-formatter.xml
+
+
+
+
+ com.diffplug.spotless
+ spotless-maven-plugin
+ ${spotless-maven-plugin.version}
+
+
+
+
+ com,java,org
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ false
+
+
+
+ maven-failsafe-plugin
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ add-source
+ generate-sources
+
+ add-source
+
+
+
+ ${project.build.directory}/generated-sources/annotations/
+
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco-maven-plugin.version}
+
+
+ default-prepare-agent
+
+ prepare-agent
+
+
+
+ default-report
+ prepare-package
+
+ report
+
+
+
+
+
+ io.swagger.codegen.v3
+ swagger-codegen-maven-plugin
+ ${swagger-codegen-maven-plugin.version}
+
+
+ test
+
+ generate
+
+
+ ${project.basedir}/api/ics-api.json
+ openapi-yaml
+
+
+ ics-api.yaml
+
+
+
+
+
+
+ io.fabric8
+ docker-maven-plugin
+ ${docker-maven-plugin}
+ false
+
+
+ generate-nonrtric-plt-informationcoordinatorservice-image
+ package
+
+ build
+
+
+ ${env.CONTAINER_PULL_REGISTRY}
+
+
+ o-ran-sc/nonrtric-plt-informationcoordinatorservice:${project.version}
+
+ try
+ ${basedir}
+ Dockerfile
+
+ ${project.build.finalName}.jar
+
+
+ ${project.version}
+
+
+
+
+
+
+
+ push-nonrtric-plt-informationcoordinatorservice-image
+
+ build
+ push
+
+
+ ${env.CONTAINER_PULL_REGISTRY}
+ ${env.CONTAINER_PUSH_REGISTRY}
+
+
+ o-ran-sc/nonrtric-plt-informationcoordinatorservice:${project.version}
+
+ ${basedir}
+ Dockerfile
+
+ ${project.build.finalName}.jar
+
+
+ ${project.version}
+ latest
+
+
+
+
+
+
+
+
+
+
+
+ JIRA
+ https://jira.o-ran-sc.org/
+
+
diff --git a/src/main/java/org/oransc/ics/Application.java b/src/main/java/org/oransc/ics/Application.java
new file mode 100644
index 0000000..46caac1
--- /dev/null
+++ b/src/main/java/org/oransc/ics/Application.java
@@ -0,0 +1,33 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2019 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.ics;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class);
+ }
+
+}
diff --git a/src/main/java/org/oransc/ics/BeanFactory.java b/src/main/java/org/oransc/ics/BeanFactory.java
new file mode 100644
index 0000000..3847cc3
--- /dev/null
+++ b/src/main/java/org/oransc/ics/BeanFactory.java
@@ -0,0 +1,115 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2019 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.ics;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.lang.invoke.MethodHandles;
+
+import org.apache.catalina.connector.Connector;
+import org.oransc.ics.clients.SecurityContext;
+import org.oransc.ics.configuration.ApplicationConfig;
+import org.oransc.ics.controllers.r1producer.ProducerCallbacks;
+import org.oransc.ics.repository.InfoJobs;
+import org.oransc.ics.repository.InfoTypes;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+class BeanFactory {
+
+ @Value("${server.http-port}")
+ private int httpPort = 0;
+
+ private final ApplicationConfig applicationConfig = new ApplicationConfig();
+ private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private ProducerCallbacks producerCallbacks;
+ private InfoTypes infoTypes;
+ private InfoJobs infoJobs;
+
+ @Bean
+ public ObjectMapper mapper() {
+ return new ObjectMapper();
+ }
+
+ @Bean
+ public ServletWebServerFactory servletContainer() {
+ TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
+ if (httpPort > 0) {
+ tomcat.addAdditionalTomcatConnectors(getHttpConnector(httpPort));
+ }
+ return tomcat;
+ }
+
+ @Bean
+ public InfoJobs infoJobs(SecurityContext securityContext) {
+ if (infoJobs == null) {
+ infoJobs = new InfoJobs(getApplicationConfig(), producerCallbacks(securityContext));
+ try {
+ infoJobs.restoreJobsFromDatabase();
+ } catch (Exception e) {
+ logger.error("Could not restore jobs from database: {}", e.getMessage());
+ }
+ }
+ return infoJobs;
+ }
+
+ @Bean
+ public InfoTypes infoTypes() {
+ if (this.infoTypes == null) {
+ infoTypes = new InfoTypes(getApplicationConfig());
+ try {
+ infoTypes.restoreTypesFromDatabase();
+ } catch (Exception e) {
+ logger.error("Could not restore Information Types from database: {}", e.getMessage());
+ }
+ }
+ return infoTypes;
+ }
+
+ @Bean
+ public ProducerCallbacks producerCallbacks(SecurityContext securityContext) {
+ if (this.producerCallbacks == null) {
+ producerCallbacks = new ProducerCallbacks(getApplicationConfig(), securityContext);
+ }
+ return this.producerCallbacks;
+ }
+
+ @Bean
+ public ApplicationConfig getApplicationConfig() {
+ return this.applicationConfig;
+ }
+
+ private static Connector getHttpConnector(int httpPort) {
+ Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
+ connector.setScheme("http");
+ connector.setPort(httpPort);
+ connector.setSecure(false);
+ return connector;
+ }
+
+}
diff --git a/src/main/java/org/oransc/ics/SwaggerConfig.java b/src/main/java/org/oransc/ics/SwaggerConfig.java
new file mode 100644
index 0000000..30c0d4a
--- /dev/null
+++ b/src/main/java/org/oransc/ics/SwaggerConfig.java
@@ -0,0 +1,84 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2019 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.ics;
+
+import io.swagger.v3.oas.annotations.OpenAPIDefinition;
+import io.swagger.v3.oas.annotations.info.Info;
+import io.swagger.v3.oas.annotations.info.License;
+
+/**
+ * Swagger configuration class that uses swagger documentation type and scans
+ * all the controllers. To access the swagger gui go to
+ * http://ip:port/swagger-ui.html
+ */
+
+@OpenAPIDefinition( //
+ info = @Info(
+ title = SwaggerConfig.API_TITLE, //
+ version = "1.0", //
+ description = SwaggerConfig.DESCRIPTION, //
+ license = @License(
+ name = "Copyright (C) 2020-2022 Nordix Foundation. Licensed under the Apache License.",
+ url = "http://www.apache.org/licenses/LICENSE-2.0")))
+public class SwaggerConfig {
+ private SwaggerConfig() {
+ }
+
+ static final String API_TITLE = "Data management and exposure";
+
+ static final String DESCRIPTION = "
API documentation
" //
+ + "
General
" //
+ + "
" //
+ + " The service is mainly a broker between data producers and data consumers. A data producer has the ability to produce one or several types of data (Information Type). One type of data can be produced by zero to many producers.
A data consumer can have several active data subscriptions (Information Job). One Information Job consists of the type of data to produce and additional parameters for filtering of the data. These parameters are different for different data types." //
+ + "
" //
+ + "
APIs provided by the service
" //
+ + "
A1-EI
" //
+ + "
" //
+ + " This API is between Near-RT RIC and the Non-RT RIC." //
+ + " The Near-RT RIC is a data consumer, which creates Information Jobs to subscribe for data." //
+ + " In this context, the information is referred to as 'Enrichment Information', EI." //
+ + "
" //
+ + "
Data producer API
" //
+ + "
" //
+ + " This API is provided by the Non-RT RIC platform and is intended to be part of the O-RAN R1 interface." //
+ + " The API is for use by different kinds of data producers and provides support for:" //
+ + "
" //
+ + "
Registry of supported information types and which parameters needed to setup a subscription.
" //
+ + "
Registry of existing data producers.
" //
+ + "
Callback API provided by producers to setup subscriptions.
" //
+ + "
" //
+ + "" //
+ + "
Data consumer API
" //
+ + "
" //
+ + " This API is provided by the Non-RT RIC platform and is intended to be part of the O-RAN R1 interface." //
+ + " The API is for use by different kinds of data consumers and provides support for:" //
+ + "
" //
+ + "
Querying of available types of data to consume.
" //
+ + "
Management of data subscription jobs
" //
+ + "
Optional callback API provided by consumers to get notification on added and removed information types.
" //
+ + "
" //
+ + "" //
+ + "
Service status
" //
+ + "
" //
+ + " This API provides a means to monitor the health of this service." //
+ + "
";
+
+}
diff --git a/src/main/java/org/oransc/ics/clients/AsyncRestClient.java b/src/main/java/org/oransc/ics/clients/AsyncRestClient.java
new file mode 100644
index 0000000..2879092
--- /dev/null
+++ b/src/main/java/org/oransc/ics/clients/AsyncRestClient.java
@@ -0,0 +1,213 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.ics.clients;
+
+import io.netty.channel.ChannelOption;
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.timeout.ReadTimeoutHandler;
+import io.netty.handler.timeout.WriteTimeoutHandler;
+
+import java.lang.invoke.MethodHandles;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.oransc.ics.configuration.WebClientConfig.HttpProxyConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.lang.Nullable;
+import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
+import org.springframework.web.reactive.function.client.ExchangeStrategies;
+import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec;
+
+import reactor.core.publisher.Mono;
+import reactor.netty.http.client.HttpClient;
+import reactor.netty.transport.ProxyProvider;
+
+/**
+ * Generic reactive REST client.
+ */
+public class AsyncRestClient {
+
+ private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ private WebClient webClient = null;
+ private final String baseUrl;
+ private static final AtomicInteger sequenceNumber = new AtomicInteger();
+ private final SslContext sslContext;
+ private final HttpProxyConfig httpProxyConfig;
+ private final SecurityContext securityContext;
+
+ public AsyncRestClient(String baseUrl, @Nullable SslContext sslContext, @Nullable HttpProxyConfig httpProxyConfig,
+ SecurityContext securityContext) {
+ this.baseUrl = baseUrl;
+ this.sslContext = sslContext;
+ this.httpProxyConfig = httpProxyConfig;
+ this.securityContext = securityContext;
+ }
+
+ public Mono> postForEntity(String uri, @Nullable String body) {
+ Mono bodyProducer = body != null ? Mono.just(body) : Mono.empty();
+
+ RequestHeadersSpec> request = getWebClient() //
+ .post() //
+ .uri(uri) //
+ .contentType(MediaType.APPLICATION_JSON) //
+ .body(bodyProducer, String.class);
+ return retrieve(request);
+ }
+
+ public Mono post(String uri, @Nullable String body) {
+ return postForEntity(uri, body) //
+ .map(this::toBody);
+ }
+
+ public Mono postWithAuthHeader(String uri, String body, String username, String password) {
+ RequestHeadersSpec> request = getWebClient() //
+ .post() //
+ .uri(uri) //
+ .headers(headers -> headers.setBasicAuth(username, password)) //
+ .contentType(MediaType.APPLICATION_JSON) //
+ .bodyValue(body);
+ return retrieve(request) //
+ .map(this::toBody);
+ }
+
+ public Mono> putForEntity(String uri, String body) {
+ RequestHeadersSpec> request = getWebClient() //
+ .put() //
+ .uri(uri) //
+ .contentType(MediaType.APPLICATION_JSON) //
+ .bodyValue(body);
+ return retrieve(request);
+ }
+
+ public Mono> putForEntity(String uri) {
+ RequestHeadersSpec> request = getWebClient() //
+ .put() //
+ .uri(uri);
+ return retrieve(request);
+ }
+
+ public Mono put(String uri, String body) {
+ return putForEntity(uri, body) //
+ .map(this::toBody);
+ }
+
+ public Mono> getForEntity(String uri) {
+ RequestHeadersSpec> request = getWebClient().get().uri(uri);
+ return retrieve(request);
+ }
+
+ public Mono get(String uri) {
+ return getForEntity(uri) //
+ .map(this::toBody);
+ }
+
+ public Mono> deleteForEntity(String uri) {
+ RequestHeadersSpec> request = getWebClient().delete().uri(uri);
+ return retrieve(request);
+ }
+
+ public Mono delete(String uri) {
+ return deleteForEntity(uri) //
+ .map(this::toBody);
+ }
+
+ private Mono> retrieve(RequestHeadersSpec> request) {
+ if (securityContext.isConfigured()) {
+ request.headers(h -> h.setBearerAuth(securityContext.getBearerAuthToken()));
+ }
+ return request.retrieve() //
+ .toEntity(String.class);
+ }
+
+ private static Object createTraceTag() {
+ return sequenceNumber.incrementAndGet();
+ }
+
+ private String toBody(ResponseEntity entity) {
+ if (entity.getBody() == null) {
+ return "";
+ } else {
+ return entity.getBody();
+ }
+ }
+
+ private boolean isHttpProxyConfigured() {
+ return httpProxyConfig != null && httpProxyConfig.httpProxyPort() > 0
+ && !httpProxyConfig.httpProxyHost().isEmpty();
+ }
+
+ private HttpClient buildHttpClient() {
+ HttpClient httpClient = HttpClient.create() //
+ .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) //
+ .doOnConnected(connection -> {
+ connection.addHandlerLast(new ReadTimeoutHandler(30));
+ connection.addHandlerLast(new WriteTimeoutHandler(30));
+ });
+
+ if (this.sslContext != null) {
+ httpClient = httpClient.secure(ssl -> ssl.sslContext(sslContext));
+ }
+
+ if (isHttpProxyConfigured()) {
+ httpClient = httpClient.proxy(proxy -> proxy.type(ProxyProvider.Proxy.HTTP)
+ .host(httpProxyConfig.httpProxyHost()).port(httpProxyConfig.httpProxyPort()));
+ }
+ return httpClient;
+ }
+
+ public WebClient buildWebClient(String baseUrl) {
+ Object traceTag = createTraceTag();
+
+ final HttpClient httpClient = buildHttpClient();
+ ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder() //
+ .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)) //
+ .build();
+
+ ExchangeFilterFunction reqLogger = ExchangeFilterFunction.ofRequestProcessor(req -> {
+ logger.debug("{} {} uri = '{}''", traceTag, req.method(), req.url());
+ return Mono.just(req);
+ });
+
+ ExchangeFilterFunction respLogger = ExchangeFilterFunction.ofResponseProcessor(resp -> {
+ logger.debug("{} resp: {}", traceTag, resp.statusCode());
+ return Mono.just(resp);
+ });
+
+ return WebClient.builder() //
+ .clientConnector(new ReactorClientHttpConnector(httpClient)) //
+ .baseUrl(baseUrl) //
+ .exchangeStrategies(exchangeStrategies) //
+ .filter(reqLogger) //
+ .filter(respLogger) //
+ .build();
+ }
+
+ private WebClient getWebClient() {
+ if (this.webClient == null) {
+ this.webClient = buildWebClient(baseUrl);
+ }
+ return this.webClient;
+ }
+}
diff --git a/src/main/java/org/oransc/ics/clients/AsyncRestClientFactory.java b/src/main/java/org/oransc/ics/clients/AsyncRestClientFactory.java
new file mode 100644
index 0000000..9a6c4f7
--- /dev/null
+++ b/src/main/java/org/oransc/ics/clients/AsyncRestClientFactory.java
@@ -0,0 +1,193 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.ics.clients;
+
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.invoke.MethodHandles;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.net.ssl.KeyManagerFactory;
+
+import org.oransc.ics.configuration.WebClientConfig;
+import org.oransc.ics.configuration.WebClientConfig.HttpProxyConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.ResourceUtils;
+
+/**
+ * Factory for a generic reactive REST client.
+ */
+public class AsyncRestClientFactory {
+ private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private final SslContextFactory sslContextFactory;
+ private final HttpProxyConfig httpProxyConfig;
+ private final SecurityContext securityContext;
+
+ public AsyncRestClientFactory(WebClientConfig clientConfig, SecurityContext securityContext) {
+ if (clientConfig != null) {
+ this.sslContextFactory = new CachingSslContextFactory(clientConfig);
+ this.httpProxyConfig = clientConfig.httpProxyConfig();
+ } else {
+ logger.warn("No configuration for web client defined, HTTPS will not work");
+ this.sslContextFactory = null;
+ this.httpProxyConfig = null;
+ }
+ this.securityContext = securityContext;
+ }
+
+ public AsyncRestClient createRestClientNoHttpProxy(String baseUrl) {
+ return createRestClient(baseUrl, false);
+ }
+
+ public AsyncRestClient createRestClientUseHttpProxy(String baseUrl) {
+ return createRestClient(baseUrl, true);
+ }
+
+ private AsyncRestClient createRestClient(String baseUrl, boolean useHttpProxy) {
+ if (this.sslContextFactory != null) {
+ try {
+ return new AsyncRestClient(baseUrl, this.sslContextFactory.createSslContext(),
+ useHttpProxy ? httpProxyConfig : null, this.securityContext);
+ } catch (Exception e) {
+ String exceptionString = e.toString();
+ logger.error("Could not init SSL context, reason: {}", exceptionString);
+ }
+ }
+ return new AsyncRestClient(baseUrl, null, httpProxyConfig, this.securityContext);
+ }
+
+ private class SslContextFactory {
+ private final WebClientConfig clientConfig;
+
+ public SslContextFactory(WebClientConfig clientConfig) {
+ this.clientConfig = clientConfig;
+ }
+
+ public SslContext createSslContext() throws UnrecoverableKeyException, NoSuchAlgorithmException,
+ CertificateException, KeyStoreException, IOException {
+ return this.createSslContext(createKeyManager());
+ }
+
+ private SslContext createSslContext(KeyManagerFactory keyManager)
+ throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException {
+ if (this.clientConfig.isTrustStoreUsed()) {
+ return createSslContextRejectingUntrustedPeers(this.clientConfig.trustStore(),
+ this.clientConfig.trustStorePassword(), keyManager);
+ } else {
+ // Trust anyone
+ return SslContextBuilder.forClient() //
+ .keyManager(keyManager) //
+ .trustManager(InsecureTrustManagerFactory.INSTANCE) //
+ .build();
+ }
+ }
+
+ private SslContext createSslContextRejectingUntrustedPeers(String trustStorePath, String trustStorePass,
+ KeyManagerFactory keyManager)
+ throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException {
+
+ final KeyStore trustStore = getTrustStore(trustStorePath, trustStorePass);
+ List certificateList = Collections.list(trustStore.aliases()).stream() //
+ .filter(alias -> isCertificateEntry(trustStore, alias)) //
+ .map(alias -> getCertificate(trustStore, alias)) //
+ .collect(Collectors.toList());
+ final X509Certificate[] certificates = certificateList.toArray(new X509Certificate[certificateList.size()]);
+
+ return SslContextBuilder.forClient() //
+ .keyManager(keyManager) //
+ .trustManager(certificates) //
+ .build();
+ }
+
+ private boolean isCertificateEntry(KeyStore trustStore, String alias) {
+ try {
+ return trustStore.isCertificateEntry(alias);
+ } catch (KeyStoreException e) {
+ logger.error("Error reading truststore {}", e.getMessage());
+ return false;
+ }
+ }
+
+ private Certificate getCertificate(KeyStore trustStore, String alias) {
+ try {
+ return trustStore.getCertificate(alias);
+ } catch (KeyStoreException e) {
+ logger.error("Error reading truststore {}", e.getMessage());
+ return null;
+ }
+ }
+
+ private KeyManagerFactory createKeyManager() throws NoSuchAlgorithmException, CertificateException, IOException,
+ UnrecoverableKeyException, KeyStoreException {
+ final KeyManagerFactory keyManager = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ final KeyStore keyStore = KeyStore.getInstance(this.clientConfig.keyStoreType());
+ final String keyStoreFile = this.clientConfig.keyStore();
+ final String keyStorePassword = this.clientConfig.keyStorePassword();
+ final String keyPassword = this.clientConfig.keyPassword();
+ try (final InputStream inputStream = new FileInputStream(keyStoreFile)) {
+ keyStore.load(inputStream, keyStorePassword.toCharArray());
+ }
+ keyManager.init(keyStore, keyPassword.toCharArray());
+ return keyManager;
+ }
+
+ private synchronized KeyStore getTrustStore(String trustStorePath, String trustStorePass)
+ throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException {
+
+ KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
+ store.load(new FileInputStream(ResourceUtils.getFile(trustStorePath)), trustStorePass.toCharArray());
+ return store;
+ }
+ }
+
+ public class CachingSslContextFactory extends SslContextFactory {
+ private SslContext cachedContext = null;
+
+ public CachingSslContextFactory(WebClientConfig clientConfig) {
+ super(clientConfig);
+ }
+
+ @Override
+ public SslContext createSslContext() throws UnrecoverableKeyException, NoSuchAlgorithmException,
+ CertificateException, KeyStoreException, IOException {
+ if (this.cachedContext == null) {
+ this.cachedContext = super.createSslContext();
+ }
+ return this.cachedContext;
+
+ }
+ }
+}
diff --git a/src/main/java/org/oransc/ics/clients/SecurityContext.java b/src/main/java/org/oransc/ics/clients/SecurityContext.java
new file mode 100644
index 0000000..aadc1bf
--- /dev/null
+++ b/src/main/java/org/oransc/ics/clients/SecurityContext.java
@@ -0,0 +1,76 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2022 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.ics.clients;
+
+import java.lang.invoke.MethodHandles;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import lombok.Setter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@EnableConfigurationProperties
+@ConfigurationProperties()
+@Component
+public class SecurityContext {
+
+ private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private long tokenTimestamp = 0;
+
+ private String authToken = "";
+
+ @Setter
+ private Path authTokenFilePath;
+
+ public SecurityContext(@Value("${app.auth-token-file:\"\"}") String authTokenFilename) {
+ if (!authTokenFilename.isEmpty()) {
+ this.authTokenFilePath = Path.of(authTokenFilename);
+ }
+ }
+
+ public boolean isConfigured() {
+ return authTokenFilePath != null;
+ }
+
+ public synchronized String getBearerAuthToken() {
+ if (!isConfigured()) {
+ return "";
+ }
+ try {
+ long lastModified = authTokenFilePath.toFile().lastModified();
+ if (lastModified != this.tokenTimestamp) {
+ this.authToken = Files.readString(authTokenFilePath);
+ this.tokenTimestamp = lastModified;
+ }
+ } catch (Exception e) {
+ logger.warn("Could not read auth token file: {}, reason: {}", authTokenFilePath, e.getMessage());
+ }
+ return this.authToken;
+ }
+
+}
diff --git a/src/main/java/org/oransc/ics/configuration/ApplicationConfig.java b/src/main/java/org/oransc/ics/configuration/ApplicationConfig.java
new file mode 100644
index 0000000..0a63d42
--- /dev/null
+++ b/src/main/java/org/oransc/ics/configuration/ApplicationConfig.java
@@ -0,0 +1,96 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.ics.configuration;
+
+import lombok.Getter;
+
+import org.oransc.ics.configuration.WebClientConfig.HttpProxyConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+
+@EnableConfigurationProperties
+@ConfigurationProperties()
+public class ApplicationConfig {
+
+ private static final Logger logger = LoggerFactory.getLogger(ApplicationConfig.class);
+
+ @Getter
+ @Value("${app.vardata-directory}")
+ private String vardataDirectory;
+
+ @Value("${server.ssl.key-store-type}")
+ private String sslKeyStoreType = "";
+
+ @Value("${server.ssl.key-store-password}")
+ private String sslKeyStorePassword = "";
+
+ @Value("${server.ssl.key-store}")
+ private String sslKeyStore = "";
+
+ @Value("${server.ssl.key-password}")
+ private String sslKeyPassword = "";
+
+ @Value("${app.webclient.trust-store-used}")
+ private boolean sslTrustStoreUsed = false;
+
+ @Value("${app.webclient.trust-store-password}")
+ private String sslTrustStorePassword = "";
+
+ @Value("${app.webclient.trust-store}")
+ private String sslTrustStore = "";
+
+ @Value("${app.webclient.http.proxy-host:\"\"}")
+ private String httpProxyHost = "";
+
+ @Value("${app.webclient.http.proxy-port:0}")
+ private int httpProxyPort = 0;
+
+ private WebClientConfig webClientConfig = null;
+
+ public WebClientConfig getWebClientConfig() {
+ if (this.webClientConfig == null) {
+ if (this.httpProxyPort == 0) {
+ logger.info("Http proxy is not used");
+ } else {
+ logger.info("Http proxy is used for RAN access {}:{}", httpProxyHost, httpProxyPort);
+ }
+ HttpProxyConfig httpProxyConfig = ImmutableHttpProxyConfig.builder() //
+ .httpProxyHost(this.httpProxyHost) //
+ .httpProxyPort(this.httpProxyPort) //
+ .build();
+ this.webClientConfig = ImmutableWebClientConfig.builder() //
+ .keyStoreType(this.sslKeyStoreType) //
+ .keyStorePassword(this.sslKeyStorePassword) //
+ .keyStore(this.sslKeyStore) //
+ .keyPassword(this.sslKeyPassword) //
+ .isTrustStoreUsed(this.sslTrustStoreUsed) //
+ .trustStore(this.sslTrustStore) //
+ .trustStorePassword(this.sslTrustStorePassword) //
+ .httpProxyConfig(httpProxyConfig) //
+ .build();
+ }
+ return this.webClientConfig;
+ }
+
+}
diff --git a/src/main/java/org/oransc/ics/configuration/WebClientConfig.java b/src/main/java/org/oransc/ics/configuration/WebClientConfig.java
new file mode 100644
index 0000000..12e9cfd
--- /dev/null
+++ b/src/main/java/org/oransc/ics/configuration/WebClientConfig.java
@@ -0,0 +1,54 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.ics.configuration;
+
+import org.immutables.value.Value;
+
+@Value.Immutable
+@Value.Style(redactedMask = "####")
+public interface WebClientConfig {
+ public String keyStoreType();
+
+ @Value.Redacted
+ public String keyStorePassword();
+
+ public String keyStore();
+
+ @Value.Redacted
+ public String keyPassword();
+
+ public boolean isTrustStoreUsed();
+
+ @Value.Redacted
+ public String trustStorePassword();
+
+ public String trustStore();
+
+ @Value.Immutable
+ public interface HttpProxyConfig {
+ public String httpProxyHost();
+
+ public int httpProxyPort();
+ }
+
+ public HttpProxyConfig httpProxyConfig();
+
+}
diff --git a/src/main/java/org/oransc/ics/controllers/ErrorResponse.java b/src/main/java/org/oransc/ics/controllers/ErrorResponse.java
new file mode 100644
index 0000000..25b0c16
--- /dev/null
+++ b/src/main/java/org/oransc/ics/controllers/ErrorResponse.java
@@ -0,0 +1,110 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.ics.controllers;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.annotations.SerializedName;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+import org.oransc.ics.exceptions.ServiceException;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import reactor.core.publisher.Mono;
+
+public class ErrorResponse {
+ private static Gson gson = new GsonBuilder().create();
+
+ // Returned as body for all failed REST calls
+ @Schema(
+ name = "ProblemDetails",
+ description = "A problem detail to carry details in a HTTP response according to RFC 7807")
+ public static class ErrorInfo {
+ @SerializedName("type")
+ private String type = "about:blank";
+
+ @SerializedName("title")
+ private String title = null;
+
+ @SerializedName("status")
+ private final Integer status;
+
+ @SerializedName("detail")
+ private String detail = null;
+
+ @SerializedName("instance")
+ private String instance = null;
+
+ public ErrorInfo(String detail, Integer status) {
+ this.detail = detail;
+ this.status = status;
+ }
+
+ @Schema(
+ example = "404",
+ description = "The HTTP status code generated by the origin server for this occurrence of the problem.")
+ public Integer getStatus() {
+ return status;
+ }
+
+ @Schema(
+ example = "Information Job type not found",
+ description = "A human-readable explanation specific to this occurrence of the problem.")
+ public String getDetail() {
+ return this.detail;
+ }
+ }
+
+ @Schema(name = "message")
+ public final String message;
+
+ ErrorResponse(String message) {
+ this.message = message;
+ }
+
+ public static Mono> createMono(Throwable e, HttpStatus code) {
+ return Mono.just(create(e, code));
+ }
+
+ public static ResponseEntity