Merge "Create READDME file for DMaaP Mediator Producer"
authorHenrik Andersson <henrik.b.andersson@est.tech>
Wed, 27 Oct 2021 13:34:24 +0000 (13:34 +0000)
committerGerrit Code Review <gerrit@o-ran-sc.org>
Wed, 27 Oct 2021 13:34:24 +0000 (13:34 +0000)
23 files changed:
dmaap-adaptor-java/api/api.json [new file with mode: 0644]
dmaap-adaptor-java/api/api.yaml [new file with mode: 0644]
dmaap-adaptor-java/config/application.yaml
dmaap-adaptor-java/pom.xml
dmaap-adaptor-java/src/main/java/org/oran/dmaapadapter/SwaggerConfig.java [new file with mode: 0644]
dmaap-adaptor-java/src/main/java/org/oran/dmaapadapter/controllers/ProducerCallbacksController.java
dmaap-adaptor-java/src/main/java/org/oran/dmaapadapter/repository/Job.java
dmaap-adaptor-java/src/main/java/org/oran/dmaapadapter/tasks/ProducerRegstrationTask.java
dmaap-adaptor-java/src/test/java/org/oran/dmaapadapter/ApplicationTest.java
dmaap-adaptor-java/src/test/java/org/oran/dmaapadapter/ConsumerController.java
dmaap-adaptor-java/src/test/java/org/oran/dmaapadapter/DmaapSimulatorController.java
dmaap-adaptor-java/src/test/java/org/oran/dmaapadapter/EcsSimulatorController.java
docker-compose/data/prepareDmaapMsg.sh
docker-compose/data/prepareEcsData.sh
docker-compose/data/sendMsgToMediator.sh [new file with mode: 0755]
docker-compose/data/testdata/ECS/EiJob.json
docker-compose/data/testdata/ECS/EiProducer.json
docker-compose/data/testdata/dmaap-mediator-java/flow.puml [new file with mode: 0644]
docker-compose/data/testdata/dmaap-mediator-java/job.json [new file with mode: 0644]
docker-compose/dmaap-mediator-java/config/application.yaml [new file with mode: 0755]
docker-compose/dmaap-mediator-java/config/application_configuration.json [new file with mode: 0644]
docker-compose/dmaap-mediator-java/docker-compose.yaml
docker-compose/ecs/docker-compose.yaml

diff --git a/dmaap-adaptor-java/api/api.json b/dmaap-adaptor-java/api/api.json
new file mode 100644 (file)
index 0000000..39056e9
--- /dev/null
@@ -0,0 +1,399 @@
+{
+    "components": {"schemas": {
+        "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"
+                }
+            }
+        },
+        "error_information": {
+            "description": "Problem as defined in https://tools.ietf.org/html/rfc7807",
+            "type": "object",
+            "properties": {
+                "detail": {
+                    "description": " A human-readable explanation specific to this occurrence of the problem.",
+                    "type": "string",
+                    "example": "Policy 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": 503
+                }
+            }
+        },
+        "void": {
+            "description": "Void/empty",
+            "type": "object"
+        },
+        "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"
+                }
+            }
+        },
+        "Link": {
+            "type": "object",
+            "properties": {
+                "templated": {"type": "boolean"},
+                "href": {"type": "string"}
+            }
+        },
+        "producer_info_type_info": {
+            "description": "Information for an Information Type",
+            "type": "object",
+            "required": [
+                "info_job_data_schema",
+                "info_type_information"
+            ],
+            "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"
+                }
+            }
+        }
+    }},
+    "openapi": "3.0.1",
+    "paths": {
+        "/dmaap_dataproducer/info_job": {
+            "post": {
+                "summary": "Callback for Information Job creation/modification",
+                "requestBody": {
+                    "content": {"application/json": {"schema": {"type": "string"}}},
+                    "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"}}}
+                    },
+                    "404": {
+                        "description": "Information type is not found",
+                        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/error_information"}}}
+                    }
+                },
+                "tags": ["Producer job control API"]
+            },
+            "get": {
+                "summary": "Get all jobs",
+                "description": "Returns all info jobs, can be used for trouble shooting",
+                "operationId": "getJobs",
+                "responses": {"200": {
+                    "description": "Information jobs",
+                    "content": {"application/json": {"schema": {
+                        "type": "array",
+                        "items": {"$ref": "#/components/schemas/producer_info_job_request"}
+                    }}}
+                }},
+                "tags": ["Producer job control API"]
+            }
+        },
+        "/dmaap_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": ["Producer job control API"]
+        }},
+        "/actuator/threaddump": {"get": {
+            "summary": "Actuator web endpoint 'threaddump'",
+            "operationId": "handle_2_1_3",
+            "responses": {"200": {
+                "description": "OK",
+                "content": {"*/*": {"schema": {"type": "object"}}}
+            }},
+            "tags": ["Actuator"]
+        }},
+        "/actuator/info": {"get": {
+            "summary": "Actuator web endpoint 'info'",
+            "operationId": "handle_9",
+            "responses": {"200": {
+                "description": "OK",
+                "content": {"*/*": {"schema": {"type": "object"}}}
+            }},
+            "tags": ["Actuator"]
+        }},
+        "/data-producer/v1/info-types/{infoTypeId}": {"put": {
+            "requestBody": {
+                "content": {"application/json": {"schema": {"$ref": "#/components/schemas/producer_info_type_info"}}},
+                "required": true
+            },
+            "operationId": "putInfoType",
+            "responses": {"200": {
+                "description": "OK",
+                "content": {"application/json": {"schema": {"type": "object"}}}
+            }},
+            "parameters": [{
+                "schema": {"type": "string"},
+                "in": "path",
+                "name": "infoTypeId",
+                "required": true
+            }],
+            "tags": ["Information Coordinator Service Simulator (exists only in test)"]
+        }},
+        "/actuator/loggers": {"get": {
+            "summary": "Actuator web endpoint 'loggers'",
+            "operationId": "handle_6",
+            "responses": {"200": {
+                "description": "OK",
+                "content": {"*/*": {"schema": {"type": "object"}}}
+            }},
+            "tags": ["Actuator"]
+        }},
+        "/actuator/health/**": {"get": {
+            "summary": "Actuator web endpoint 'health-path'",
+            "operationId": "handle_12",
+            "responses": {"200": {
+                "description": "OK",
+                "content": {"*/*": {"schema": {"type": "object"}}}
+            }},
+            "tags": ["Actuator"]
+        }},
+        "/data-producer/v1/info-producers/{infoProducerId}": {
+            "get": {
+                "operationId": "getInfoProducer",
+                "responses": {"200": {
+                    "description": "OK",
+                    "content": {"application/json": {"schema": {"type": "object"}}}
+                }},
+                "parameters": [{
+                    "schema": {"type": "string"},
+                    "in": "path",
+                    "name": "infoProducerId",
+                    "required": true
+                }],
+                "tags": ["Information Coordinator Service Simulator (exists only in test)"]
+            },
+            "put": {
+                "requestBody": {
+                    "content": {"application/json": {"schema": {"$ref": "#/components/schemas/producer_registration_info"}}},
+                    "required": true
+                },
+                "operationId": "putInfoProducer",
+                "responses": {"200": {
+                    "description": "OK",
+                    "content": {"application/json": {"schema": {"type": "object"}}}
+                }},
+                "parameters": [{
+                    "schema": {"type": "string"},
+                    "in": "path",
+                    "name": "infoProducerId",
+                    "required": true
+                }],
+                "tags": ["Information Coordinator Service Simulator (exists only in test)"]
+            }
+        },
+        "/actuator/metrics/{requiredMetricName}": {"get": {
+            "summary": "Actuator web endpoint 'metrics-requiredMetricName'",
+            "operationId": "handle_5",
+            "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_1",
+            "responses": {"200": {
+                "description": "OK",
+                "content": {"*/*": {"schema": {
+                    "additionalProperties": {
+                        "additionalProperties": {"$ref": "#/components/schemas/Link"},
+                        "type": "object"
+                    },
+                    "type": "object"
+                }}}
+            }},
+            "tags": ["Actuator"]
+        }},
+        "/actuator/logfile": {"get": {
+            "summary": "Actuator web endpoint 'logfile'",
+            "operationId": "handle_8",
+            "responses": {"200": {
+                "description": "OK",
+                "content": {"*/*": {"schema": {"type": "object"}}}
+            }},
+            "tags": ["Actuator"]
+        }},
+        "/actuator/loggers/{name}": {
+            "post": {
+                "summary": "Actuator web endpoint 'loggers-name'",
+                "operationId": "handle_0",
+                "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": "handle_7",
+                "responses": {"200": {
+                    "description": "OK",
+                    "content": {"*/*": {"schema": {"type": "object"}}}
+                }},
+                "parameters": [{
+                    "schema": {"type": "string"},
+                    "in": "path",
+                    "name": "name",
+                    "required": true
+                }],
+                "tags": ["Actuator"]
+            }
+        },
+        "/dmaap_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": ["Producer job control API"]
+        }},
+        "/actuator/health": {"get": {
+            "summary": "Actuator web endpoint 'health'",
+            "operationId": "handle_11",
+            "responses": {"200": {
+                "description": "OK",
+                "content": {"*/*": {"schema": {"type": "object"}}}
+            }},
+            "tags": ["Actuator"]
+        }},
+        "/consumer": {"post": {
+            "summary": "Consume data",
+            "requestBody": {
+                "content": {"application/json": {"schema": {"type": "string"}}},
+                "required": true
+            },
+            "description": "The call is invoked to push data to consumer",
+            "operationId": "postData",
+            "responses": {"200": {
+                "description": "OK",
+                "content": {"application/json": {"schema": {"$ref": "#/components/schemas/void"}}}
+            }},
+            "tags": ["Test Consumer Simulator (exists only in test)"]
+        }},
+        "/dmaap-topic-1": {"get": {
+            "summary": "GET from topic",
+            "description": "The call is invoked to activate or to modify a data subscription. The endpoint is provided by the Information Producer.",
+            "operationId": "getFromTopic",
+            "responses": {"200": {
+                "description": "OK",
+                "content": {"application/json": {"schema": {"$ref": "#/components/schemas/void"}}}
+            }},
+            "tags": ["DMAAP Simulator (exists only in test)"]
+        }},
+        "/actuator/metrics": {"get": {
+            "summary": "Actuator web endpoint 'metrics'",
+            "operationId": "handle_4",
+            "responses": {"200": {
+                "description": "OK",
+                "content": {"*/*": {"schema": {"type": "object"}}}
+            }},
+            "tags": ["Actuator"]
+        }},
+        "/actuator/heapdump": {"get": {
+            "summary": "Actuator web endpoint 'heapdump'",
+            "operationId": "handle_10",
+            "responses": {"200": {
+                "description": "OK",
+                "content": {"*/*": {"schema": {"type": "object"}}}
+            }},
+            "tags": ["Actuator"]
+        }}
+    },
+    "info": {
+        "license": {
+            "name": "Copyright (C) 2021 Nordix Foundation. Licensed under the Apache License.",
+            "url": "http://www.apache.org/licenses/LICENSE-2.0"
+        },
+        "description": "Reads data from DMAAP and sends it further to information consumers",
+        "title": "Generic Dmaap Information Producer",
+        "version": "1.0"
+    },
+    "tags": [{
+        "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/dmaap-adaptor-java/api/api.yaml b/dmaap-adaptor-java/api/api.yaml
new file mode 100644 (file)
index 0000000..3c9fb59
--- /dev/null
@@ -0,0 +1,471 @@
+openapi: 3.0.1
+info:
+  title: Generic Dmaap Information Producer
+  description: Reads data from DMAAP and sends it further to information consumers
+  license:
+    name: Copyright (C) 2021 Nordix Foundation. Licensed under the Apache License.
+    url: http://www.apache.org/licenses/LICENSE-2.0
+  version: "1.0"
+servers:
+- url: /
+tags:
+- 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:
+  /dmaap_dataproducer/info_job:
+    get:
+      tags:
+      - Producer job control API
+      summary: Get all jobs
+      description: Returns all info jobs, can be used for trouble shooting
+      operationId: getJobs
+      responses:
+        200:
+          description: Information jobs
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/producer_info_job_request'
+    post:
+      tags:
+      - Producer job control API
+      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:
+              type: string
+        required: true
+      responses:
+        200:
+          description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/void'
+        404:
+          description: Information type is not found
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/error_information'
+  /dmaap_dataproducer/health_check:
+    get:
+      tags:
+      - Producer job control API
+      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/threaddump:
+    get:
+      tags:
+      - Actuator
+      summary: Actuator web endpoint 'threaddump'
+      operationId: handle_2_1_3
+      responses:
+        200:
+          description: OK
+          content:
+            '*/*':
+              schema:
+                type: object
+  /actuator/info:
+    get:
+      tags:
+      - Actuator
+      summary: Actuator web endpoint 'info'
+      operationId: handle_9
+      responses:
+        200:
+          description: OK
+          content:
+            '*/*':
+              schema:
+                type: object
+  /data-producer/v1/info-types/{infoTypeId}:
+    put:
+      tags:
+      - Information Coordinator Service Simulator (exists only in test)
+      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: OK
+          content:
+            application/json:
+              schema:
+                type: object
+  /actuator/loggers:
+    get:
+      tags:
+      - Actuator
+      summary: Actuator web endpoint 'loggers'
+      operationId: handle_6
+      responses:
+        200:
+          description: OK
+          content:
+            '*/*':
+              schema:
+                type: object
+  /actuator/health/**:
+    get:
+      tags:
+      - Actuator
+      summary: Actuator web endpoint 'health-path'
+      operationId: handle_12
+      responses:
+        200:
+          description: OK
+          content:
+            '*/*':
+              schema:
+                type: object
+  /data-producer/v1/info-producers/{infoProducerId}:
+    get:
+      tags:
+      - Information Coordinator Service Simulator (exists only in test)
+      operationId: getInfoProducer
+      parameters:
+      - name: infoProducerId
+        in: path
+        required: true
+        style: simple
+        explode: false
+        schema:
+          type: string
+      responses:
+        200:
+          description: OK
+          content:
+            application/json:
+              schema:
+                type: object
+    put:
+      tags:
+      - Information Coordinator Service Simulator (exists only in test)
+      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: OK
+          content:
+            application/json:
+              schema:
+                type: object
+  /actuator/metrics/{requiredMetricName}:
+    get:
+      tags:
+      - Actuator
+      summary: Actuator web endpoint 'metrics-requiredMetricName'
+      operationId: handle_5
+      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_1
+      responses:
+        200:
+          description: OK
+          content:
+            '*/*':
+              schema:
+                type: object
+                additionalProperties:
+                  type: object
+                  additionalProperties:
+                    $ref: '#/components/schemas/Link'
+  /actuator/logfile:
+    get:
+      tags:
+      - Actuator
+      summary: Actuator web endpoint 'logfile'
+      operationId: handle_8
+      responses:
+        200:
+          description: OK
+          content:
+            '*/*':
+              schema:
+                type: object
+  /actuator/loggers/{name}:
+    get:
+      tags:
+      - Actuator
+      summary: Actuator web endpoint 'loggers-name'
+      operationId: handle_7
+      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: handle_0
+      parameters:
+      - name: name
+        in: path
+        required: true
+        style: simple
+        explode: false
+        schema:
+          type: string
+      responses:
+        200:
+          description: OK
+          content:
+            '*/*':
+              schema:
+                type: object
+  /dmaap_dataproducer/info_job/{infoJobId}:
+    delete:
+      tags:
+      - Producer job control API
+      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'
+  /actuator/health:
+    get:
+      tags:
+      - Actuator
+      summary: Actuator web endpoint 'health'
+      operationId: handle_11
+      responses:
+        200:
+          description: OK
+          content:
+            '*/*':
+              schema:
+                type: object
+  /consumer:
+    post:
+      tags:
+      - Test Consumer Simulator (exists only in test)
+      summary: Consume data
+      description: The call is invoked to push data to consumer
+      operationId: postData
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+        required: true
+      responses:
+        200:
+          description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/void'
+  /dmaap-topic-1:
+    get:
+      tags:
+      - DMAAP Simulator (exists only in test)
+      summary: GET from topic
+      description: The call is invoked to activate or to modify a data subscription.
+        The endpoint is provided by the Information Producer.
+      operationId: getFromTopic
+      responses:
+        200:
+          description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/void'
+  /actuator/metrics:
+    get:
+      tags:
+      - Actuator
+      summary: Actuator web endpoint 'metrics'
+      operationId: handle_4
+      responses:
+        200:
+          description: OK
+          content:
+            '*/*':
+              schema:
+                type: object
+  /actuator/heapdump:
+    get:
+      tags:
+      - Actuator
+      summary: Actuator web endpoint 'heapdump'
+      operationId: handle_10
+      responses:
+        200:
+          description: OK
+          content:
+            '*/*':
+              schema:
+                type: object
+components:
+  schemas:
+    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
+    error_information:
+      type: object
+      properties:
+        detail:
+          type: string
+          description: ' A human-readable explanation specific to this occurrence
+            of the problem.'
+          example: Policy 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: 503
+      description: Problem as defined in https://tools.ietf.org/html/rfc7807
+    void:
+      type: object
+      description: Void/empty
+    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
+    Link:
+      type: object
+      properties:
+        templated:
+          type: boolean
+        href:
+          type: string
+    producer_info_type_info:
+      required:
+      - info_job_data_schema
+      - info_type_information
+      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
index b327a0b..5733ea7 100644 (file)
@@ -11,7 +11,8 @@ management:
       exposure:
         # Enabling of springboot actuator features. See springboot documentation.
         include: "loggers,logfile,health,info,metrics,threaddump,heapdump"
-
+springdoc:
+  show-actuator: true 
 logging:
   # Configuration of logging
   level:
index 01f51e2..1fbd83c 100644 (file)
@@ -3,7 +3,7 @@
 * ========================LICENSE_START=================================
 * O-RAN-SC
 * %%
-* Copyright (C) 2019 Nordix Foundation
+* Copyright (C) 2021 Nordix Foundation
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
                             <language>openapi-yaml</language>
                             <output>${project.basedir}/api</output>
                             <configOptions>
-                                <outputFile>ecs-api.yaml</outputFile>
+                                <outputFile>api.yaml</outputFile>
                             </configOptions>
                         </configuration>
                     </execution>
diff --git a/dmaap-adaptor-java/src/main/java/org/oran/dmaapadapter/SwaggerConfig.java b/dmaap-adaptor-java/src/main/java/org/oran/dmaapadapter/SwaggerConfig.java
new file mode 100644 (file)
index 0000000..8f33377
--- /dev/null
@@ -0,0 +1,43 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2021 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.oran.dmaapadapter;
+
+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) 2021 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 = "Generic Dmaap Information Producer";
+    static final String DESCRIPTION = "Reads data from DMAAP and sends it further to information consumers";
+}
index d4fe95c..ca7c96c 100644 (file)
@@ -24,12 +24,16 @@ import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 
 import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
 import io.swagger.v3.oas.annotations.media.Content;
 import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.responses.ApiResponse;
 import io.swagger.v3.oas.annotations.responses.ApiResponses;
 import io.swagger.v3.oas.annotations.tags.Tag;
 
+import java.util.ArrayList;
+import java.util.Collection;
+
 import org.oran.dmaapadapter.r1.ProducerJobInfo;
 import org.oran.dmaapadapter.repository.InfoTypes;
 import org.oran.dmaapadapter.repository.Job;
@@ -52,7 +56,7 @@ import org.springframework.web.bind.annotation.RestController;
 public class ProducerCallbacksController {
     private static final Logger logger = LoggerFactory.getLogger(ProducerCallbacksController.class);
 
-    public static final String API_NAME = "Management of configuration";
+    public static final String API_NAME = "Producer job control API";
     public static final String API_DESCRIPTION = "";
     public static final String JOB_URL = "/dmaap_dataproducer/info_job";
     public static final String SUPERVISION_URL = "/dmaap_dataproducer/health_check";
@@ -70,7 +74,9 @@ public class ProducerCallbacksController {
             description = "The call is invoked to activate or to modify a data subscription. The endpoint is provided by the Information Producer.")
     @ApiResponses(value = { //
             @ApiResponse(responseCode = "200", description = "OK", //
-                    content = @Content(schema = @Schema(implementation = VoidResponse.class))) //
+                    content = @Content(schema = @Schema(implementation = VoidResponse.class))), //
+            @ApiResponse(responseCode = "404", description = "Information type is not found", //
+                    content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))), //
     })
     public ResponseEntity<Object> jobCreatedCallback( //
             @RequestBody String body) {
@@ -78,7 +84,8 @@ public class ProducerCallbacksController {
             ProducerJobInfo request = gson.fromJson(body, ProducerJobInfo.class);
 
             logger.info("Job started callback {}", request.id);
-            Job job = new Job(request.id, request.targetUri, types.getType(request.typeId));
+            Job job = new Job(request.id, request.targetUri, types.getType(request.typeId), request.owner,
+                    request.lastUpdated);
             this.jobs.put(job);
             return new ResponseEntity<>(HttpStatus.OK);
         } catch (Exception e) {
@@ -86,6 +93,21 @@ public class ProducerCallbacksController {
         }
     }
 
+    @GetMapping(path = JOB_URL, produces = MediaType.APPLICATION_JSON_VALUE)
+    @Operation(summary = "Get all jobs", description = "Returns all info jobs, can be used for trouble shooting")
+    @ApiResponse(responseCode = "200", //
+            description = "Information jobs", //
+            content = @Content(array = @ArraySchema(schema = @Schema(implementation = ProducerJobInfo.class)))) //
+    public ResponseEntity<Object> getJobs() {
+
+        Collection<ProducerJobInfo> producerJobs = new ArrayList<>();
+        for (Job j : this.jobs.getAll()) {
+            producerJobs.add(new ProducerJobInfo(null, j.getId(), j.getType().getId(), j.getCallbackUrl(), j.getOwner(),
+                    j.getLastUpdated()));
+        }
+        return new ResponseEntity<>(gson.toJson(producerJobs), HttpStatus.OK);
+    }
+
     @DeleteMapping(path = JOB_URL + "/{infoJobId}", produces = MediaType.APPLICATION_JSON_VALUE)
     @Operation(summary = "Callback for Information Job deletion",
             description = "The call is invoked to terminate a data subscription. The endpoint is provided by the Information Producer.")
@@ -109,7 +131,7 @@ public class ProducerCallbacksController {
                     content = @Content(schema = @Schema(implementation = String.class))) //
     })
     public ResponseEntity<Object> producerSupervision() {
-        logger.info("Producer supervision");
+        logger.debug("Producer supervision");
         return new ResponseEntity<>(HttpStatus.OK);
     }
 
index 690e465..0da94a6 100644 (file)
@@ -33,10 +33,18 @@ public class Job {
     @Getter
     private final InfoType type;
 
-    public Job(String id, String callbackUrl, InfoType type) {
+    @Getter
+    private final String owner;
+
+    @Getter
+    private final String lastUpdated;
+
+    public Job(String id, String callbackUrl, InfoType type, String owner, String lastUpdated) {
         this.id = id;
         this.callbackUrl = callbackUrl;
         this.type = type;
+        this.owner = owner;
+        this.lastUpdated = lastUpdated;
     }
 
 }
index b9a50b3..837ca32 100644 (file)
@@ -22,11 +22,12 @@ package org.oran.dmaapadapter.tasks;
 
 import com.google.gson.JsonParser;
 
+import lombok.Getter;
+
 import org.oran.dmaapadapter.clients.AsyncRestClient;
 import org.oran.dmaapadapter.clients.AsyncRestClientFactory;
 import org.oran.dmaapadapter.configuration.ApplicationConfig;
 import org.oran.dmaapadapter.controllers.ProducerCallbacksController;
-import org.oran.dmaapadapter.exceptions.ServiceException;
 import org.oran.dmaapadapter.r1.ProducerInfoTypeInfo;
 import org.oran.dmaapadapter.r1.ProducerRegistrationInfo;
 import org.oran.dmaapadapter.repository.InfoType;
@@ -56,6 +57,7 @@ public class ProducerRegstrationTask {
     private static com.google.gson.Gson gson = new com.google.gson.GsonBuilder().create();
 
     private static final String PRODUCER_ID = "DmaapGenericInfoProducer";
+    @Getter
     private boolean isRegisteredInEcs = false;
     private static final int REGISTRATION_SUPERVISION_INTERVAL_MS = 1000 * 5;
 
@@ -68,47 +70,58 @@ public class ProducerRegstrationTask {
 
     @Scheduled(fixedRate = REGISTRATION_SUPERVISION_INTERVAL_MS)
     public void supervisionTask() {
-        logger.debug("Checking producers starting");
-        createTask().subscribe(null, null, () -> logger.debug("Producer registration completed"));
+        checkRegistration() //
+                .filter(isRegisterred -> !isRegisterred) //
+                .flatMap(isRegisterred -> registerTypesAndProducer()) //
+                .subscribe( //
+                        null, //
+                        this::handleRegistrationFailure, //
+                        this::handleRegistrationCompleted);
     }
 
-    public Mono<Object> createTask() {
-        return checkProducerRegistration() //
-                .doOnError(t -> isRegisteredInEcs = false) //
-                .onErrorResume(t -> registerTypesAndProducer());
+    private void handleRegistrationCompleted() {
+        logger.debug("Registering types and producer succeeded");
+        isRegisteredInEcs = true;
     }
 
-    public boolean isRegisteredInEcs() {
-        return this.isRegisteredInEcs;
+    private void handleRegistrationFailure(Throwable t) {
+        logger.warn("Registration failed {}", t.getMessage());
+        isRegisteredInEcs = false;
     }
 
-    private Mono<Object> checkProducerRegistration() {
+    private Mono<Boolean> checkRegistration() {
         final String url = applicationConfig.getEcsBaseUrl() + "/data-producer/v1/info-producers/" + PRODUCER_ID;
         return restClient.get(url) //
-                .flatMap(this::checkRegistrationInfo) //
-        ;
+                .flatMap(this::isRegisterredInfoCorrect) //
+                .onErrorResume(t -> Mono.just(Boolean.FALSE));
+    }
+
+    private Mono<Boolean> isRegisterredInfoCorrect(String registerredInfoStr) {
+        ProducerRegistrationInfo registerredInfo = gson.fromJson(registerredInfoStr, ProducerRegistrationInfo.class);
+        if (isEqual(producerRegistrationInfo(), registerredInfo)) {
+            logger.trace("Already registered");
+            return Mono.just(Boolean.TRUE);
+        } else {
+            return Mono.just(Boolean.FALSE);
+        }
     }
 
     private String registerTypeUrl(InfoType type) {
-        String url = applicationConfig.getEcsBaseUrl() + "/data-producer/v1/info-types/" + type.getId();
-        return url;
+        return applicationConfig.getEcsBaseUrl() + "/data-producer/v1/info-types/" + type.getId();
     }
 
     private Mono<String> registerTypesAndProducer() {
+        final int CONCURRENCY = 20;
         final String producerUrl =
                 applicationConfig.getEcsBaseUrl() + "/data-producer/v1/info-producers/" + PRODUCER_ID;
 
         return Flux.fromIterable(this.types.getAll()) //
                 .doOnNext(type -> logger.info("Registering type {}", type.getId())) //
-                .flatMap(type -> restClient.put(registerTypeUrl(type), gson.toJson(typeRegistrationInfo()))) //
+                .flatMap(type -> restClient.put(registerTypeUrl(type), gson.toJson(typeRegistrationInfo())),
+                        CONCURRENCY) //
                 .collectList() //
-                .flatMap(resp -> restClient.put(producerUrl, gson.toJson(producerRegistrationInfo()))) //
-                .onErrorResume(t -> {
-                    logger.warn("Registration failed {}", t.getMessage());
-                    isRegisteredInEcs = false;
-                    return Mono.empty();
-                }) //
-                .doOnNext(x -> logger.debug("Registering types and producer completed"));
+                .doOnNext(type -> logger.info("Registering producer")) //
+                .flatMap(resp -> restClient.put(producerUrl, gson.toJson(producerRegistrationInfo())));
     }
 
     private Object typeSpecifcInfoObject() {
@@ -138,17 +151,6 @@ public class ProducerRegstrationTask {
         }
     }
 
-    private Mono<String> checkRegistrationInfo(String resp) {
-        ProducerRegistrationInfo info = gson.fromJson(resp, ProducerRegistrationInfo.class);
-        if (isEqual(producerRegistrationInfo(), info)) {
-            logger.debug("Already registered");
-            this.isRegisteredInEcs = true;
-            return Mono.empty();
-        } else {
-            return Mono.error(new ServiceException("Producer registration will be started"));
-        }
-    }
-
     private boolean isEqual(ProducerRegistrationInfo a, ProducerRegistrationInfo b) {
         return a.jobCallbackUrl.equals(b.jobCallbackUrl) //
                 && a.producerSupervisionCallbackUrl.equals(b.producerSupervisionCallbackUrl) //
@@ -160,7 +162,7 @@ public class ProducerRegstrationTask {
         return ProducerRegistrationInfo.builder() //
                 .jobCallbackUrl(baseUrl() + ProducerCallbacksController.JOB_URL) //
                 .producerSupervisionCallbackUrl(baseUrl() + ProducerCallbacksController.SUPERVISION_URL) //
-                .supportedTypeIds(types.typeIds()) //
+                .supportedTypeIds(this.types.typeIds()) //
                 .build();
     }
 
index cbaa59f..b1c1780 100644 (file)
@@ -147,7 +147,6 @@ class ApplicationTest {
         this.consumerController.testResults.reset();
         this.ecsSimulatorController.testResults.reset();
         this.jobs.clear();
-        this.types.clear();
     }
 
     private AsyncRestClient restClient(boolean useTrustValidation) {
@@ -240,7 +239,8 @@ class ApplicationTest {
         final String JOB_ID = "ID";
 
         // Register producer, Register types
-        await().untilAsserted(() -> assertThat(producerRegstrationTask.isRegisteredInEcs()).isTrue());
+        await().untilAsserted(() -> assertThat(ecsSimulatorController.testResults.registrationInfo).isNotNull());
+        assertThat(ecsSimulatorController.testResults.registrationInfo.supportedTypeIds).hasSize(1);
 
         // Create a job
         this.ecsSimulatorController.addJob(consumerJobInfo(), JOB_ID, restClient());
@@ -254,9 +254,32 @@ class ApplicationTest {
         await().untilAsserted(() -> assertThat(consumer.receivedBodies.size()).isEqualTo(2));
         assertThat(consumer.receivedBodies.get(0)).isEqualTo("DmaapResponse1");
 
+        String jobUrl = baseUrl() + ProducerCallbacksController.JOB_URL;
+        String jobs = restClient().get(jobUrl).block();
+        assertThat(jobs).contains("ExampleInformationType");
+
         // Delete the job
         this.ecsSimulatorController.deleteJob(JOB_ID, restClient());
         await().untilAsserted(() -> assertThat(this.jobs.size()).isZero());
+
+    }
+
+    @Test
+    void testReRegister() throws Exception {
+        // Wait foir register types and producer
+        await().untilAsserted(() -> assertThat(ecsSimulatorController.testResults.registrationInfo).isNotNull());
+        assertThat(ecsSimulatorController.testResults.registrationInfo.supportedTypeIds).hasSize(1);
+
+        // Clear the registration, should trigger a re-register
+        ecsSimulatorController.testResults.reset();
+        await().untilAsserted(() -> assertThat(ecsSimulatorController.testResults.registrationInfo).isNotNull());
+        assertThat(ecsSimulatorController.testResults.registrationInfo.supportedTypeIds).hasSize(1);
+
+        // Just clear the registerred types, should trigger a re-register
+        ecsSimulatorController.testResults.types.clear();
+        await().untilAsserted(
+                () -> assertThat(ecsSimulatorController.testResults.registrationInfo.supportedTypeIds).hasSize(1));
+
     }
 
     private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains) {
index 1dbe83f..4b6d901 100644 (file)
@@ -43,7 +43,7 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 
 @RestController("ConsumerSimulatorController")
-@Tag(name = "Consts.PRODUCER_API_CALLBACKS_NAME")
+@Tag(name = "Test Consumer Simulator (exists only in test)")
 public class ConsumerController {
 
     private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@@ -64,7 +64,7 @@ public class ConsumerController {
     final TestResults testResults = new TestResults();
 
     @PostMapping(path = CONSUMER_TARGET_URL, produces = MediaType.APPLICATION_JSON_VALUE)
-    @Operation(summary = "GET from topic", description = "The call is invoked to push data to consumer")
+    @Operation(summary = "Consume data", description = "The call is invoked to push data to consumer")
     @ApiResponses(value = { //
             @ApiResponse(responseCode = "200", description = "OK", //
                     content = @Content(schema = @Schema(implementation = VoidResponse.class))) //
index fbb600f..5259ee1 100644 (file)
@@ -42,8 +42,8 @@ import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-@RestController("ProducerSimulatorController")
-@Tag(name = "ProducerConsts.PRODUCER_API_CALLBACKS_NAME")
+@RestController("DmaapSimulatorController")
+@Tag(name = "DMAAP Simulator (exists only in test)")
 public class DmaapSimulatorController {
 
     private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
index 7542e0b..828b027 100644 (file)
@@ -45,8 +45,8 @@ import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 
-@RestController("EcsSimulatorController")
-@Tag(name = "EcsSimulator")
+@RestController("IcsSimulatorController")
+@Tag(name = "Information Coordinator Service Simulator (exists only in test)")
 public class EcsSimulatorController {
 
     private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@@ -54,14 +54,16 @@ public class EcsSimulatorController {
 
     public static class TestResults {
 
-        ProducerRegistrationInfo registrationInfo;
+        ProducerRegistrationInfo registrationInfo = null;
         Map<String, ProducerInfoTypeInfo> types = new HashMap<>();
+        String infoProducerId = null;
 
         public TestResults() {}
 
         public void reset() {
             registrationInfo = null;
             types.clear();
+            infoProducerId = null;
         }
     }
 
@@ -86,6 +88,7 @@ public class EcsSimulatorController {
             @PathVariable("infoProducerId") String infoProducerId, //
             @RequestBody ProducerRegistrationInfo registrationInfo) {
         testResults.registrationInfo = registrationInfo;
+        testResults.infoProducerId = infoProducerId;
         return new ResponseEntity<>(HttpStatus.OK);
     }
 
index 73b07bc..4de374a 100755 (executable)
@@ -32,6 +32,7 @@ a1_sim_OSC_port=${2:-30001}
 a1_sim_STD_port=${3:-30003}
 a1_sim_STD_v1_port=${4:-30005}
 httpx=${5:-"http"}
+SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
 
 echo "using dmaap-mr port: "$dmaa_mr_port
 echo "using a1-sim-OSC port: "$a1_sim_OSC_port
@@ -65,11 +66,11 @@ curl -skw %{http_code} $httpx://localhost:$a1_sim_STD_port/counter/interface
 echo -e "\n"
 
 echo "create policy type 1 to ric1:"
-curl -X PUT -skw %{http_code} $httpx://localhost:$a1_sim_OSC_port/policytype?id=1 -H Content-Type:application/json --data-binary @testdata/OSC/policy_type.json
+curl -X PUT -skw %{http_code} $httpx://localhost:$a1_sim_OSC_port/policytype?id=1 -H Content-Type:application/json --data-binary @${SHELL_FOLDER}/testdata/OSC/policy_type.json
 echo -e "\n"
 
 echo "create policy type 2 to ric3:"
-curl -skw %{http_code} $httpx://localhost:$a1_sim_STD_v1_port/policytype?id=2 -X PUT -H Accept:application/json -H Content-Type:application/json -H X-Requested-With:XMLHttpRequest --data-binary @testdata/v2/policy_type.json
+curl -skw %{http_code} $httpx://localhost:$a1_sim_STD_v1_port/policytype?id=2 -X PUT -H Accept:application/json -H Content-Type:application/json -H X-Requested-With:XMLHttpRequest --data-binary @${SHELL_FOLDER}/testdata/v2/policy_type.json
 echo -e "\n"
 
 for i in {1..12}; do
@@ -88,7 +89,7 @@ done
 
 ## Using PMS v1 interface
 echo "create service 1 to policy agent via dmaap_mr:"
-curl -k -X POST -sw %{http_code} -H accept:application/json -H Content-Type:application/json "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-READ/" --data-binary @testdata/dmaap/v1/dmaap-msg-service-create.json
+curl -k -X POST -sw %{http_code} -H accept:application/json -H Content-Type:application/json "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-READ/" --data-binary @${SHELL_FOLDER}/testdata/dmaap/v1/dmaap-msg-service-create.json
 echo -e "\n"
 
 echo "get result from mr of previous request:"
@@ -96,7 +97,7 @@ curl -X GET "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-WRITE/users
 echo -e "\n"
 
 echo "create policies to ric1 & ric2 & ric3 with type1 and service1 via dmaa_mr:"
-curl -k -X POST -sw %{http_code} -H accept:application/json -H Content-Type:application/json "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-READ/" --data-binary @testdata/dmaap/v1/dmaap-msg-policy-create.json
+curl -k -X POST -sw %{http_code} -H accept:application/json -H Content-Type:application/json "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-READ/" --data-binary @${SHELL_FOLDER}/testdata/dmaap/v1/dmaap-msg-policy-create.json
 echo -e "\n"
 
 echo "get result from mr of previous request:"
@@ -104,7 +105,7 @@ curl -X GET "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-WRITE/users
 echo -e "\n"
 
 echo "get policy from policy agent via dmaap_mr:"
-curl -k -X POST -sw %{http_code} -H accept:application/json -H Content-Type:application/json "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-READ/" --data-binary @testdata/dmaap/v1/dmaap-msg-policy-get.json
+curl -k -X POST -sw %{http_code} -H accept:application/json -H Content-Type:application/json "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-READ/" --data-binary @${SHELL_FOLDER}/testdata/dmaap/v1/dmaap-msg-policy-get.json
 echo -e "\n"
 
 echo "get result from mr of previous request:"
@@ -113,7 +114,7 @@ echo -e "\n"
 
 ## Using PMS v2 interface
 echo "create service 2 to policy agent via dmaap_mr:"
-curl -k -X POST -sw %{http_code} -H accept:application/json -H Content-Type:application/json "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-READ/" --data-binary @testdata/dmaap/v2/dmaap-msg-service-create.json
+curl -k -X POST -sw %{http_code} -H accept:application/json -H Content-Type:application/json "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-READ/" --data-binary @${SHELL_FOLDER}/testdata/dmaap/v2/dmaap-msg-service-create.json
 echo -e "\n"
 
 echo "get result from mr of previous request:"
@@ -121,7 +122,7 @@ curl -X GET "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-WRITE/users
 echo -e "\n"
 
 echo "create policies to ric1 & ric2 & ric3 with type1 and service1 via dmaa_mr:"
-curl -k -X POST -sw %{http_code} -H accept:application/json -H Content-Type:application/json "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-READ/" --data-binary @testdata/dmaap/v2/dmaap-msg-policy-create.json
+curl -k -X POST -sw %{http_code} -H accept:application/json -H Content-Type:application/json "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-READ/" --data-binary @${SHELL_FOLDER}/testdata/dmaap/v2/dmaap-msg-policy-create.json
 echo -e "\n"
 
 echo "get result from mr of previous request:"
@@ -129,7 +130,7 @@ curl -X GET "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-WRITE/users
 echo -e "\n"
 
 echo "get policy from policy agent via dmaap_mr:"
-curl -k -X POST -sw %{http_code} -H accept:application/json -H Content-Type:application/json "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-READ/" --data-binary @testdata/dmaap/v2/dmaap-msg-policy-get.json
+curl -k -X POST -sw %{http_code} -H accept:application/json -H Content-Type:application/json "$httpx://localhost:$dmaa_mr_port/events/A1-POLICY-AGENT-READ/" --data-binary @${SHELL_FOLDER}/testdata/dmaap/v2/dmaap-msg-policy-get.json
 echo -e "\n"
 
 echo "get result from mr of previous request:"
index 11b0dc8..21cc35b 100755 (executable)
@@ -28,6 +28,7 @@
 
 ecs_port=${1:-8083}
 httpx=${4:-"http"}
+SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
 
 echo "using ecs port: "$ecs_port
 echo "using protocol: "$httpx
@@ -39,7 +40,7 @@ echo -e "\n"
 
 # Create EiType
 echo "Create EiType:"
-curl -X PUT -skw %{http_code} $httpx://localhost:$ecs_port/data-producer/v1/info-types/type1 -H accept:application/json -H Content-Type:application/json --data-binary @testdata/ECS/EiType.json
+curl -X PUT -skw %{http_code} $httpx://localhost:$ecs_port/data-producer/v1/info-types/type1 -H accept:application/json -H Content-Type:application/json --data-binary @${SHELL_FOLDER}/testdata/ECS/EiType.json
 echo -e "\n"
 
 # Get EiTypes
@@ -54,7 +55,7 @@ echo -e "\n"
 
 # Create EiProducer
 echo "Create EiProducer:"
-curl -X PUT -skw %{http_code} $httpx://localhost:$ecs_port/data-producer/v1/info-producers/1 -H Content-Type:application/json --data-binary @testdata/ECS/EiProducer.json
+curl -X PUT -skw %{http_code} $httpx://localhost:$ecs_port/data-producer/v1/info-producers/1 -H Content-Type:application/json --data-binary @${SHELL_FOLDER}/testdata/ECS/EiProducer.json
 echo -e "\n"
 
 # Get EiProducers
@@ -74,7 +75,7 @@ echo -e "\n"
 
 # Create EiJob
 echo "Create EiJob Of A Certain Type type1:"
-curl -X PUT -skw %{http_code} $httpx://localhost:$ecs_port/A1-EI/v1/eijobs/job1 -H Content-Type:application/json --data-binary @testdata/ECS/EiJob.json
+curl -X PUT -skw %{http_code} $httpx://localhost:$ecs_port/A1-EI/v1/eijobs/job1 -H Content-Type:application/json --data-binary @${SHELL_FOLDER}/testdata/ECS/EiJob.json
 echo -e "\n"
 
 # Get EiJobs
diff --git a/docker-compose/data/sendMsgToMediator.sh b/docker-compose/data/sendMsgToMediator.sh
new file mode 100755 (executable)
index 0000000..a2f3db3
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2021 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.
+#  ============LICENSE_END=================================================
+#
+
+# The scripts in data/ will generate some dummy data in the running system.
+# It will send a dmaap msg of job to mediator:
+
+# Run command:
+# ./sendMsgToMediator.sh [dmaap-mr port] [http/https]
+
+SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
+bash ${SHELL_FOLDER}/prepareEcsData.sh
+
+dmaa_mr_port=${1:-3904}
+httpx=${2:-"http"}
+
+echo "using dmaap-mr port: "$dmaa_mr_port
+echo "using protocol: "$httpx
+echo -e "\n"
+
+echo "dmaap-mr topics:"
+curl -skw %{http_code} $httpx://localhost:$dmaa_mr_port/topics/listAll
+echo -e "\n"
+
+echo "dmaap-mr create topic unauthenticated.VES_NOTIFICATION_OUTPUT:"
+curl -skw %{http_code} -X POST "$httpx://localhost:$dmaa_mr_port/topics/create" -H  "accept: application/json" -H  "Content-Type: application/json" -d "{  \"topicName\": \"unauthenticated.VES_NOTIFICATION_OUTPUT\",  \"topicDescription\": \"test topic\",  \"partitionCount\": 1,  \"replicationCount\": 1,  \"transactionEnabled\": \"false\"}"
+echo -e "\n"
+
+echo "dmaap-mr topics:"
+curl -skw %{http_code} $httpx://localhost:$dmaa_mr_port/topics/listAll
+echo -e "\n"
+
+echo "send job msg to dmaap-mr:"
+curl -k -X POST -sw %{http_code} -H accept:application/json -H Content-Type:application/json "$httpx://localhost:$dmaa_mr_port/events/unauthenticated.VES_NOTIFICATION_OUTPUT/" --data-binary @${SHELL_FOLDER}/testdata/dmaap-mediator-java/job.json
+echo -e "\n"
\ No newline at end of file
index 003c70f..3788f21 100644 (file)
@@ -1,8 +1,8 @@
 {
     "eiTypeId": "type1",
-    "jobResultUri": "https://ricsim_g3_1:8185/datadelivery",
+    "jobResultUri": "http://consumer:80/",
     "jobOwner": "ricsim_g3_1",
-    "jobStatusNotificationUri": "http://producer:80/",
+    "jobStatusNotificationUri": "http://consumer:80/",
     "jobDefinition": {
         "jobparam1": "value1_job1",
         "jobparam2": "value2_job1",
index 85d3e6d..34632b0 100644 (file)
@@ -1,5 +1,5 @@
 {
     "supported_info_types": ["type1"],
-    "info_job_callback_url": "https://producer-stub:8093/callbacks/job/prod-a",
-    "info_producer_supervision_callback_url": "https://producer-stub:8093/callbacks/supervision/prod-a"
+    "info_job_callback_url": "http://consumer:80/",
+    "info_producer_supervision_callback_url": "http://consumer:80/"
 }
\ No newline at end of file
diff --git a/docker-compose/data/testdata/dmaap-mediator-java/flow.puml b/docker-compose/data/testdata/dmaap-mediator-java/flow.puml
new file mode 100644 (file)
index 0000000..5295fa6
--- /dev/null
@@ -0,0 +1,5 @@
+@startuml
+dmaap_mr <- dmaap_mediator: dmaap_mediator reads msg from dmaap_mr
+dmaap_mediator -> ecs: dmaap_mediator gets jobs from ecs
+dmaap_mediator -> consumer: callbackUrl, send msg to consumer
+@enduml
\ No newline at end of file
diff --git a/docker-compose/data/testdata/dmaap-mediator-java/job.json b/docker-compose/data/testdata/dmaap-mediator-java/job.json
new file mode 100644 (file)
index 0000000..51a68c5
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "testdata":"testdata"
+}
\ No newline at end of file
diff --git a/docker-compose/dmaap-mediator-java/config/application.yaml b/docker-compose/dmaap-mediator-java/config/application.yaml
new file mode 100755 (executable)
index 0000000..57fd8ce
--- /dev/null
@@ -0,0 +1,56 @@
+spring:
+  profiles:
+    active: prod
+  main:
+    allow-bean-definition-overriding: true
+  aop:
+    auto: false
+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.oran.dmaapadapter: TRACE
+  file:
+    name: /var/log/dmaap-adaptor-service/application.log
+server:
+   # Configuration of the HTTP/REST server. The parameters are defined and handeled by the springboot framework.
+   # See springboot documentation.
+   port : 8435
+   http-port: 8084
+   ssl:
+      key-store-type: JKS
+      key-store-password: policy_agent
+      key-store: /opt/app/dmaap-adaptor-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/dmaap-adaptor-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/dmaap-adaptor-service
+  ecs-base-url: http://ecs:8083
+  # Location of the component configuration file. The file will only be used if the Consul database is not used;
+  # configuration from the Consul will override the file.
+  configuration-filepath: /opt/app/dmaap-adaptor-service/data/application_configuration.json
+  dmaap-base-url: http://dmaap-mr:3904
+  # The url used to adress this component. This is used as a callback url sent to other components.
+  dmaap-adapter-base-url: https://dmaap-mediator-java:8435
+
diff --git a/docker-compose/dmaap-mediator-java/config/application_configuration.json b/docker-compose/dmaap-mediator-java/config/application_configuration.json
new file mode 100644 (file)
index 0000000..f15d628
--- /dev/null
@@ -0,0 +1,8 @@
+{
+   "types": [
+      {
+         "id": "type1",
+         "dmaapTopicUrl": "/events/unauthenticated.VES_NOTIFICATION_OUTPUT/OpenDcae-c12/C12"
+      }
+   ]
+}
index a2f1f5e..1d53de4 100644 (file)
@@ -28,4 +28,7 @@ services:
       - default
     ports:
       - 8084:8084
-      - 8435:8435
\ No newline at end of file
+      - 8435:8435
+    volumes:
+      - ./dmaap-mediator-java/config/application.yaml:/opt/app/dmaap-adaptor-service/config/application.yaml:ro
+      - ./dmaap-mediator-java/config/application_configuration.json:/opt/app/dmaap-adaptor-service/data/application_configuration.json:ro
\ No newline at end of file
index 354b3bc..376f734 100644 (file)
@@ -22,7 +22,7 @@ networks:
 
 services:
   ecs:
-    image: nexus3.o-ran-sc.org:10004/o-ran-sc/nonrtric-enrichment-coordinator-service:1.2.0
+    image: nexus3.o-ran-sc.org:10003/o-ran-sc/nonrtric-enrichment-coordinator-service:1.2.0-SNAPSHOT
     container_name: ecs
     networks:
       default:
@@ -31,9 +31,9 @@ services:
     ports:
       - 8083:8083
       - 8434:8434
-  producer:
+  consumer:
     image: eexit/mirror-http-server
-    container_name: producer
+    container_name: consumer
     networks:
       - default
     ports: