From 6c468636c3790e3420da97dab19057892988fa11 Mon Sep 17 00:00:00 2001 From: PatrikBuhr Date: Tue, 23 Feb 2021 13:26:23 +0100 Subject: [PATCH] Added Information consumer API Change-Id: I116a6a00156b106550558720e99312ba699d7160 Signed-off-by: PatrikBuhr Issue-ID: NONRTRIC-415 --- enrichment-coordinator-service/api/ecs-api.json | 276 ++++++++++- enrichment-coordinator-service/api/ecs-api.yaml | 319 ++++++++++-- .../java/org/oransc/enrichment/BeanFactory.java | 2 +- .../java/org/oransc/enrichment/SwaggerConfig.java | 47 +- .../enrichment/controllers/StatusController.java | 2 +- .../A1eCallbacks.java} | 11 +- .../ConsumerConsts.java => a1e/A1eConsts.java} | 6 +- .../A1eController.java} | 56 ++- .../A1eEiJobInfo.java} | 9 +- .../A1eEiJobStatus.java} | 8 +- .../A1eEiTypeInfo.java} | 4 +- .../controllers/r1consumer/ConsumerConsts.java | 41 ++ .../controllers/r1consumer/ConsumerController.java | 352 ++++++++++++++ .../r1consumer/ConsumerInfoTypeInfo.java | 46 ++ .../controllers/r1consumer/ConsumerJobInfo.java | 73 +++ .../controllers/r1consumer/ConsumerJobStatus.java | 56 +++ .../ProducerCallbacks.java | 4 +- .../{producer => r1producer}/ProducerConsts.java | 5 +- .../ProducerController.java | 12 +- .../ProducerEiTypeInfo.java | 2 +- .../{producer => r1producer}/ProducerJobInfo.java | 2 +- .../ProducerRegistrationInfo.java | 2 +- .../ProducerStatusInfo.java | 2 +- .../org/oransc/enrichment/repository/EiJobs.java | 4 +- .../oransc/enrichment/repository/EiProducers.java | 6 +- .../org/oransc/enrichment/repository/EiTypes.java | 4 +- .../enrichment/tasks/ProducerSupervision.java | 8 +- .../org/oransc/enrichment/ApplicationTest.java | 535 ++++++++++++++------- .../controller/ConsumerSimulatorController.java | 10 +- .../controller/ProducerSimulatorController.java | 4 +- 30 files changed, 1579 insertions(+), 329 deletions(-) rename enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/{consumer/ConsumerCallbacks.java => a1e/A1eCallbacks.java} (88%) rename enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/{consumer/ConsumerConsts.java => a1e/A1eConsts.java} (93%) rename enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/{consumer/ConsumerController.java => a1e/A1eController.java} (88%) rename enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/{consumer/ConsumerEiJobInfo.java => a1e/A1eEiJobInfo.java} (90%) rename enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/{consumer/ConsumerEiJobStatus.java => a1e/A1eEiJobStatus.java} (90%) rename enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/{consumer/ConsumerEiTypeInfo.java => a1e/A1eEiTypeInfo.java} (91%) create mode 100644 enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerConsts.java create mode 100644 enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerController.java create mode 100644 enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerInfoTypeInfo.java create mode 100644 enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerJobInfo.java create mode 100644 enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerJobStatus.java rename enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/{producer => r1producer}/ProducerCallbacks.java (97%) rename enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/{producer => r1producer}/ProducerConsts.java (95%) rename enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/{producer => r1producer}/ProducerController.java (97%) rename enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/{producer => r1producer}/ProducerEiTypeInfo.java (96%) rename enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/{producer => r1producer}/ProducerJobInfo.java (98%) rename enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/{producer => r1producer}/ProducerRegistrationInfo.java (97%) rename enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/{producer => r1producer}/ProducerStatusInfo.java (97%) diff --git a/enrichment-coordinator-service/api/ecs-api.json b/enrichment-coordinator-service/api/ecs-api.json index 237c3c4c..06f6ac14 100644 --- a/enrichment-coordinator-service/api/ecs-api.json +++ b/enrichment-coordinator-service/api/ecs-api.json @@ -101,19 +101,6 @@ } } }, - "producer_status": { - "description": "Status for an EI Producer", - "type": "object", - "required": ["operational_state"], - "properties": {"operational_state": { - "description": "Represents the operational states", - "type": "string", - "enum": [ - "ENABLED", - "DISABLED" - ] - }} - }, "ProblemDetails": { "description": "A problem detail to carry details in a HTTP response according to RFC 7807", "type": "object", @@ -131,10 +118,6 @@ } } }, - "Void": { - "description": "Void/empty ", - "type": "object" - }, "EiJobStatusObject": { "description": "Status for an EI job", "type": "object", @@ -179,6 +162,77 @@ "type": "object" } } + }, + "JobStatus": { + "description": "Status for an EI job", + "type": "object", + "required": ["eiJobStatus"], + "properties": {"eiJobStatus": { + "description": "Allowed values for EI job status", + "type": "string", + "enum": [ + "ENABLED", + "DISABLED" + ] + }} + }, + "producer_status": { + "description": "Status for an EI 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" + }, + "Job": { + "description": "Information for an Enrichment Information Job", + "type": "object", + "required": [ + "infoTypeId", + "jobDefinition", + "jobOwner", + "jobResultUri" + ], + "properties": { + "jobResultUri": { + "description": "The target URI of the subscribed information", + "type": "string" + }, + "infoTypeId": { + "description": "Information type Idenitifier of the subscription job", + "type": "string" + }, + "jobOwner": { + "description": "Identity of the owner of the job", + "type": "string" + }, + "statusNotificationUri": { + "description": "The target of Information subscription job status notifications", + "type": "string" + }, + "jobDefinition": { + "description": "Information type specific job data", + "type": "object" + } + } + }, + "InformationType": { + "description": "Information for an Information type", + "type": "object", + "required": ["consumer_job_data_schema"], + "properties": {"consumer_job_data_schema": { + "description": "Json schema for the job data", + "type": "object" + }} } }}, "openapi": "3.0.1", @@ -242,6 +296,18 @@ }}, "tags": ["A1-EI (registration)"] }}, + "/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"] + }}, "/ei-producer/v1/eiproducers/{eiProducerId}/status": {"get": { "summary": "EI producer status", "operationId": "getEiProducerStatus", @@ -367,7 +433,7 @@ "description": "Service is living", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/status_info"}}} }}, - "tags": ["EI Service status"] + "tags": ["Service status"] }}, "/ei-producer/v1/eiproducers": {"get": { "summary": "EI producer identifiers", @@ -391,7 +457,7 @@ "/A1-EI/v1/eijobs/{eiJobId}": { "get": { "summary": "Individual EI job", - "operationId": "getIndividualEiJob", + "operationId": "getIndividualEiJob_1", "responses": { "200": { "description": "EI job", @@ -412,7 +478,7 @@ }, "delete": { "summary": "Individual EI job", - "operationId": "deleteIndividualEiJob", + "operationId": "deleteIndividualEiJob_1", "responses": { "200": { "description": "Not used", @@ -527,6 +593,10 @@ "201": { "description": "Producer created", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}} + }, + "404": { + "description": "Producer not found", + "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}} } }, "parameters": [{ @@ -548,6 +618,118 @@ }}, "tags": ["Data producer (callbacks)"] }}, + "/data-consumer/v1/info-jobs": {"get": { + "summary": "EI 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 subscription jobs for one job owner", + "required": false + } + ], + "tags": ["Data consumer"] + }}, + "/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/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/Job"}}}, + "required": true + }, + "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"}}} + }, + "404": { + "description": "Enrichment Information type is not found", + "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}} + } + }, + "parameters": [{ + "schema": {"type": "string"}, + "in": "path", + "name": "infoJobId", + "required": true + }], + "tags": ["Data consumer"] + } + }, "/ei-producer/v1/eiproducers/{eiProducerId}/eijobs": {"get": { "summary": "EI job definitions", "description": "EI job definitions for one EI producer", @@ -573,6 +755,27 @@ }], "tags": ["Data producer (registration)"] }}, + "/data-consumer/v1/info-types/{infoTypeId}": {"get": { + "summary": "Individual information type", + "operationId": "getInfoType", + "responses": { + "200": { + "description": "Information type", + "content": {"application/json": {"schema": {"$ref": "#/components/schemas/InformationType"}}} + }, + "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"] + }}, "/A1-EI/v1/eijobs": {"get": { "summary": "EI job identifiers", "description": "query for EI job identifiers", @@ -610,7 +813,7 @@ }}, "/A1-EI/v1/eijobs/{eiJobId}/status": {"get": { "summary": "EI job status", - "operationId": "getEiJobStatus", + "operationId": "getEiJobStatus_1", "responses": { "200": { "description": "EI job status", @@ -648,6 +851,27 @@ "required": true }], "tags": ["A1-EI (callbacks)"] + }}, + "/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/JobStatus"}}} + }, + "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"] }} }, "info": { @@ -655,8 +879,8 @@ "name": "Copyright (C) 2020 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 producer one or several type of data (EI type). One type of data can be produced by zero to many producers.

A data consumer can have several active data subscriptions (EI job). One EI 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, which is a data consumer, and the Non-RT RIC. <\/p>

Data producer API<\/h4>

This API is between data producers and this service. It is divivided into two parts, where one is provided by this service (registration) and one part is provided by the data producer.<\/p>

EI Service status<\/h4>

This API provides a means to monitor the service.<\/p>", - "title": "Enrichment Information Service", + "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 (EI type). One type of data can be produced by zero to many producers.

A data consumer can have several active data subscriptions (EI job). One EI 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 Enrichment Information Jobs to subscribe for data.<\/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><\/ul><\/p>

      EI Service status<\/h4>

      This API provides a means to monitor the service.<\/p>", + "title": "Data management and exposure", "version": "1.0" }, "tags": [ @@ -677,8 +901,12 @@ "description": "API for data producers" }, { - "name": "EI Service status", + "name": "Service status", "description": "API for monitoring of the service" + }, + { + "name": "Data consumer", + "description": "API for data consumers" } ] } \ No newline at end of file diff --git a/enrichment-coordinator-service/api/ecs-api.yaml b/enrichment-coordinator-service/api/ecs-api.yaml index beb5512d..f94743e2 100644 --- a/enrichment-coordinator-service/api/ecs-api.yaml +++ b/enrichment-coordinator-service/api/ecs-api.yaml @@ -1,18 +1,25 @@ openapi: 3.0.1 info: - title: Enrichment Information Service + 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 producer one or several type of data (EI type). One type of data can be produced + to produce one or several types of data (EI type). One type of data can be produced by zero to many producers.

      A data consumer can have several active data subscriptions (EI job). One EI 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, which is a data consumer, and the Non-RT RIC.

      Data - producer API

      This API is between data producers and this service. It - is divivided into two parts, where one is provided by this service (registration) - and one part is provided by the data producer.

      EI Service status

      This - API provides a means to monitor the service.

      + API is between Near-RT RIC and the Non-RT RIC. The Near-RT RIC is a data consumer, + which creates Enrichment Information Jobs to subscribe for data.

      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

      EI + Service status

      This API provides a means to monitor the service.

      license: name: Copyright (C) 2020 Nordix Foundation. Licensed under the Apache License. url: http://www.apache.org/licenses/LICENSE-2.0 @@ -28,8 +35,10 @@ tags: description: API implemented by data producers - name: Data producer (registration) description: API for data producers -- name: EI Service status +- name: Service status description: API for monitoring of the service +- name: Data consumer + description: API for data consumers paths: /producer_simulator/ei_job: post: @@ -109,6 +118,21 @@ paths: type: array items: type: string + /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 /ei-producer/v1/eiproducers/{eiProducerId}/status: get: tags: @@ -265,7 +289,7 @@ paths: /status: get: tags: - - EI Service status + - Service status summary: Returns status and statistics of this service operationId: getStatus responses: @@ -304,7 +328,7 @@ paths: tags: - A1-EI (registration) summary: Individual EI job - operationId: getIndividualEiJob + operationId: getIndividualEiJob_1 parameters: - name: eiJobId in: path @@ -368,7 +392,7 @@ paths: tags: - A1-EI (registration) summary: Individual EI job - operationId: deleteIndividualEiJob + operationId: deleteIndividualEiJob_1 parameters: - name: eiJobId in: path @@ -455,6 +479,12 @@ paths: application/json: schema: $ref: '#/components/schemas/Void' + 404: + description: Producer not found + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemDetails' delete: tags: - Data producer (registration) @@ -502,6 +532,142 @@ paths: application/json: schema: type: string + /data-consumer/v1/info-jobs: + get: + tags: + - Data consumer + summary: EI 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 subscription jobs for one job 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' + /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/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 + operationId: putIndividualInfoJob + parameters: + - name: infoJobId + in: path + required: true + style: simple + explode: false + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/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' + 404: + description: Enrichment Information type is not found + 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' /ei-producer/v1/eiproducers/{eiProducerId}/eijobs: get: tags: @@ -532,6 +698,33 @@ paths: application/json: schema: $ref: '#/components/schemas/ProblemDetails' + /data-consumer/v1/info-types/{infoTypeId}: + get: + tags: + - Data consumer + summary: Individual information type + operationId: getInfoType + 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/InformationType' + 404: + description: Information type is not found + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemDetails' /A1-EI/v1/eijobs: get: tags: @@ -576,7 +769,7 @@ paths: tags: - A1-EI (registration) summary: EI job status - operationId: getEiJobStatus + operationId: getEiJobStatus_1 parameters: - name: eiJobId in: path @@ -627,6 +820,33 @@ paths: application/json: schema: $ref: '#/components/schemas/Void' + /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/JobStatus' + 404: + description: Information subscription job is not found + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemDetails' components: schemas: producer_ei_job_request: @@ -708,18 +928,6 @@ components: type: string description: callback for EI job description: Information for an EI producer - producer_status: - required: - - operational_state - type: object - properties: - operational_state: - type: string - description: Represents the operational states - enum: - - ENABLED - - DISABLED - description: Status for an EI Producer ProblemDetails: type: object properties: @@ -736,9 +944,6 @@ components: example: 404 description: A problem detail to carry details in a HTTP response according to RFC 7807 - Void: - type: object - description: 'Void/empty ' EiJobStatusObject: required: - eiJobStatus @@ -775,3 +980,63 @@ components: type: object description: EI type specific job data description: Information for an Enrichment Information Job + JobStatus: + required: + - eiJobStatus + type: object + properties: + eiJobStatus: + type: string + description: Allowed values for EI job status + enum: + - ENABLED + - DISABLED + description: Status for an EI 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 EI Producer + Void: + type: object + description: 'Void/empty ' + Job: + required: + - infoTypeId + - jobDefinition + - jobOwner + - jobResultUri + type: object + properties: + jobResultUri: + type: string + description: The target URI of the subscribed information + infoTypeId: + type: string + description: Information type Idenitifier of the subscription job + jobOwner: + type: string + description: Identity of the owner of the job + statusNotificationUri: + type: string + description: The target of Information subscription job status notifications + jobDefinition: + type: object + description: Information type specific job data + description: Information for an Enrichment Information Job + InformationType: + required: + - consumer_job_data_schema + type: object + properties: + consumer_job_data_schema: + type: object + description: Json schema for the job data + description: Information for an Information type diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/BeanFactory.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/BeanFactory.java index f5aca7e6..e636e50f 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/BeanFactory.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/BeanFactory.java @@ -26,7 +26,7 @@ import java.lang.invoke.MethodHandles; import org.apache.catalina.connector.Connector; import org.oransc.enrichment.configuration.ApplicationConfig; -import org.oransc.enrichment.controllers.producer.ProducerCallbacks; +import org.oransc.enrichment.controllers.r1producer.ProducerCallbacks; import org.oransc.enrichment.repository.EiJobs; import org.oransc.enrichment.repository.EiTypes; import org.slf4j.Logger; diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/SwaggerConfig.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/SwaggerConfig.java index fdfc0c9e..58f69de8 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/SwaggerConfig.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/SwaggerConfig.java @@ -26,8 +26,9 @@ import io.swagger.v3.oas.annotations.info.License; import io.swagger.v3.oas.annotations.tags.Tag; import org.oransc.enrichment.controllers.StatusController; -import org.oransc.enrichment.controllers.consumer.ConsumerConsts; -import org.oransc.enrichment.controllers.producer.ProducerConsts; +import org.oransc.enrichment.controllers.a1e.A1eConsts; +import org.oransc.enrichment.controllers.r1consumer.ConsumerConsts; +import org.oransc.enrichment.controllers.r1producer.ProducerConsts; /** * Swagger configuration class that uses swagger documentation type and scans @@ -36,17 +37,18 @@ import org.oransc.enrichment.controllers.producer.ProducerConsts; */ @OpenAPIDefinition( // - tags = {@Tag(name = ConsumerConsts.CONSUMER_API_NAME, description = ConsumerConsts.CONSUMER_API_DESCRIPTION), - @Tag( - name = ConsumerConsts.CONSUMER_API_CALLBACKS_NAME, - description = ConsumerConsts.CONSUMER_API_CALLBACKS_DESCRIPTION), + tags = { // + @Tag(name = A1eConsts.CONSUMER_API_NAME, description = A1eConsts.CONSUMER_API_DESCRIPTION), + @Tag(name = A1eConsts.CONSUMER_API_CALLBACKS_NAME, description = A1eConsts.CONSUMER_API_CALLBACKS_DESCRIPTION), @Tag( name = ProducerConsts.PRODUCER_API_CALLBACKS_NAME, description = ProducerConsts.PRODUCER_API_CALLBACKS_DESCRIPTION), @Tag(name = ProducerConsts.PRODUCER_API_NAME, description = ProducerConsts.PRODUCER_API_DESCRIPTION), // - @Tag(name = StatusController.API_NAME, description = StatusController.API_DESCRIPTION)}, // + @Tag(name = StatusController.API_NAME, description = StatusController.API_DESCRIPTION), // + @Tag(name = ConsumerConsts.CONSUMER_API_NAME, description = ConsumerConsts.CONSUMER_API_DESCRIPTION), // + }, // info = @Info( - title = "Enrichment Information Service", // + title = SwaggerConfig.API_TITLE, // version = "1.0", // description = SwaggerConfig.DESCRIPTION, // license = @License( @@ -56,20 +58,37 @@ public class SwaggerConfig { private SwaggerConfig() { } - static final String API_TITLE = "Enrichment Data service"; + 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 producer one or several type of data (EI type). One type of data can be produced by zero to many producers.

      A data consumer can have several active data subscriptions (EI job). One EI 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." // + + " 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 (EI type). One type of data can be produced by zero to many producers.

      A data consumer can have several active data subscriptions (EI job). One EI 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, which is a data consumer, and the Non-RT RIC. " // - + "

      " + "

      Data producer API

      " // - + "

      " - + " This API is between data producers and this service. It is divivided into two parts, where one is provided by this service (registration) and one part is provided by the data producer." + + " This API is between Near-RT RIC and the Non-RT RIC." // + + " The Near-RT RIC is a data consumer, which creates Enrichment Information Jobs to subscribe for data." // + + "

      " // + + "

      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
      • " // + + "
      " // + "

      " // + "

      EI Service status

      " // + "

      " // diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/StatusController.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/StatusController.java index e823a939..b23d606d 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/StatusController.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/StatusController.java @@ -46,7 +46,7 @@ import reactor.core.publisher.Mono; @Tag(name = StatusController.API_NAME) public class StatusController { - public static final String API_NAME = "EI Service status"; + public static final String API_NAME = "Service status"; public static final String API_DESCRIPTION = "API for monitoring of the service"; @Autowired diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerCallbacks.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eCallbacks.java similarity index 88% rename from enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerCallbacks.java rename to enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eCallbacks.java index 7ccf61d0..fc17ee2e 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerCallbacks.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eCallbacks.java @@ -18,7 +18,7 @@ * ========================LICENSE_END=================================== */ -package org.oransc.enrichment.controllers.consumer; +package org.oransc.enrichment.controllers.a1e; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -46,7 +46,7 @@ import reactor.core.publisher.Mono; */ @Component @SuppressWarnings("java:S3457") // No need to call "toString()" method as formatting and string .. -public class ConsumerCallbacks { +public class A1eCallbacks { private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private static Gson gson = new GsonBuilder().create(); @@ -56,7 +56,7 @@ public class ConsumerCallbacks { private final EiProducers eiProducers; @Autowired - public ConsumerCallbacks(ApplicationConfig config, EiJobs eiJobs, EiProducers eiProducers) { + public A1eCallbacks(ApplicationConfig config, EiJobs eiJobs, EiProducers eiProducers) { AsyncRestClientFactory restClientFactory = new AsyncRestClientFactory(config.getWebClientConfig()); this.restClient = restClientFactory.createRestClientUseHttpProxy(""); this.eiJobs = eiJobs; @@ -73,9 +73,8 @@ public class ConsumerCallbacks { private Mono noifyStatusToJobOwner(EiJob job) { boolean isJobEnabled = this.eiProducers.isJobEnabled(job); - ConsumerEiJobStatus status = - isJobEnabled ? new ConsumerEiJobStatus(ConsumerEiJobStatus.EiJobStatusValues.ENABLED) - : new ConsumerEiJobStatus(ConsumerEiJobStatus.EiJobStatusValues.DISABLED); + A1eEiJobStatus status = isJobEnabled ? new A1eEiJobStatus(A1eEiJobStatus.EiJobStatusValues.ENABLED) + : new A1eEiJobStatus(A1eEiJobStatus.EiJobStatusValues.DISABLED); String body = gson.toJson(status); return this.restClient.post(job.getJobStatusUrl(), body) // .doOnNext(response -> logger.debug("Consumer notified OK {}", job.getId())) // diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerConsts.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eConsts.java similarity index 93% rename from enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerConsts.java rename to enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eConsts.java index 48aad131..4c1509f8 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerConsts.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eConsts.java @@ -18,9 +18,9 @@ * ========================LICENSE_END=================================== */ -package org.oransc.enrichment.controllers.consumer; +package org.oransc.enrichment.controllers.a1e; -public class ConsumerConsts { +public class A1eConsts { public static final String CONSUMER_API_NAME = "A1-EI (registration)"; public static final String CONSUMER_API_DESCRIPTION = "Data consumer EI job registration"; @@ -35,6 +35,6 @@ public class ConsumerConsts { public static final String EI_TYPE_ID_PARAM = "eiTypeId"; public static final String EI_TYPE_ID_PARAM_DESCRIPTION = "selects EI jobs of matching EI type"; - private ConsumerConsts() { + private A1eConsts() { } } diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerController.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eController.java similarity index 88% rename from enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerController.java rename to enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eController.java index ec83f65c..34d9725e 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerController.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eController.java @@ -18,7 +18,7 @@ * ========================LICENSE_END=================================== */ -package org.oransc.enrichment.controllers.consumer; +package org.oransc.enrichment.controllers.a1e; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; @@ -41,7 +41,7 @@ import org.json.JSONObject; import org.oransc.enrichment.configuration.ApplicationConfig; import org.oransc.enrichment.controllers.ErrorResponse; import org.oransc.enrichment.controllers.VoidResponse; -import org.oransc.enrichment.controllers.producer.ProducerCallbacks; +import org.oransc.enrichment.controllers.r1producer.ProducerCallbacks; import org.oransc.enrichment.exceptions.ServiceException; import org.oransc.enrichment.repository.EiJob; import org.oransc.enrichment.repository.EiJobs; @@ -66,9 +66,9 @@ import reactor.core.publisher.Mono; @SuppressWarnings("java:S3457") // No need to call "toString()" method as formatting and string .. @RestController("A1-EI") -@Tag(name = ConsumerConsts.CONSUMER_API_NAME) -@RequestMapping(path = ConsumerConsts.API_ROOT, produces = MediaType.APPLICATION_JSON_VALUE) -public class ConsumerController { +@Tag(name = A1eConsts.CONSUMER_API_NAME) +@RequestMapping(path = A1eConsts.API_ROOT, produces = MediaType.APPLICATION_JSON_VALUE) +public class A1eController { private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); @@ -101,7 +101,7 @@ public class ConsumerController { public ResponseEntity getEiTypeIdentifiers( // ) { List result = new ArrayList<>(); - for (EiType eiType : this.eiTypes.getAllEiTypes()) { + for (EiType eiType : this.eiTypes.getAllInfoTypes()) { result.add(eiType.getId()); } @@ -115,7 +115,7 @@ public class ConsumerController { @ApiResponse( responseCode = "200", description = "EI type", // - content = @Content(schema = @Schema(implementation = ConsumerEiTypeInfo.class))), // + content = @Content(schema = @Schema(implementation = A1eEiTypeInfo.class))), // @ApiResponse( responseCode = "404", description = "Enrichment Information type is not found", // @@ -125,7 +125,7 @@ public class ConsumerController { @PathVariable("eiTypeId") String eiTypeId) { try { this.eiTypes.getType(eiTypeId); // Make sure that the type exists - ConsumerEiTypeInfo info = toEiTypeInfo(); + A1eEiTypeInfo info = toEiTypeInfo(); return new ResponseEntity<>(gson.toJson(info), HttpStatus.OK); } catch (Exception e) { return ErrorResponse.create(e, HttpStatus.NOT_FOUND); @@ -147,15 +147,15 @@ public class ConsumerController { }) public ResponseEntity getEiJobIds( // @Parameter( - name = ConsumerConsts.EI_TYPE_ID_PARAM, + name = A1eConsts.EI_TYPE_ID_PARAM, required = false, // - description = ConsumerConsts.EI_TYPE_ID_PARAM_DESCRIPTION) // - @RequestParam(name = ConsumerConsts.EI_TYPE_ID_PARAM, required = false) String eiTypeId, + description = A1eConsts.EI_TYPE_ID_PARAM_DESCRIPTION) // + @RequestParam(name = A1eConsts.EI_TYPE_ID_PARAM, required = false) String eiTypeId, @Parameter( - name = ConsumerConsts.OWNER_PARAM, + name = A1eConsts.OWNER_PARAM, required = false, // - description = ConsumerConsts.OWNER_PARAM_DESCRIPTION) // - @RequestParam(name = ConsumerConsts.OWNER_PARAM, required = false) String owner) { + description = A1eConsts.OWNER_PARAM_DESCRIPTION) // + @RequestParam(name = A1eConsts.OWNER_PARAM, required = false) String owner) { try { List result = new ArrayList<>(); if (owner != null) { @@ -184,7 +184,7 @@ public class ConsumerController { @ApiResponse( responseCode = "200", description = "EI job", // - content = @Content(schema = @Schema(implementation = ConsumerEiJobInfo.class))), // + content = @Content(schema = @Schema(implementation = A1eEiJobInfo.class))), // @ApiResponse( responseCode = "404", description = "Enrichment Information job is not found", // @@ -207,7 +207,7 @@ public class ConsumerController { @ApiResponse( responseCode = "200", description = "EI job status", // - content = @Content(schema = @Schema(implementation = ConsumerEiJobStatus.class))), // + content = @Content(schema = @Schema(implementation = A1eEiJobStatus.class))), // @ApiResponse( responseCode = "404", description = "Enrichment Information job is not found", // @@ -223,10 +223,9 @@ public class ConsumerController { } } - private ConsumerEiJobStatus toEiJobStatus(EiJob job) { - return this.eiProducers.isJobEnabled(job) - ? new ConsumerEiJobStatus(ConsumerEiJobStatus.EiJobStatusValues.ENABLED) - : new ConsumerEiJobStatus(ConsumerEiJobStatus.EiJobStatusValues.DISABLED); + private A1eEiJobStatus toEiJobStatus(EiJob job) { + return this.eiProducers.isJobEnabled(job) ? new A1eEiJobStatus(A1eEiJobStatus.EiJobStatusValues.ENABLED) + : new A1eEiJobStatus(A1eEiJobStatus.EiJobStatusValues.DISABLED); } @@ -280,7 +279,7 @@ public class ConsumerController { }) public Mono> putIndividualEiJob( // @PathVariable("eiJobId") String eiJobId, // - @RequestBody ConsumerEiJobInfo eiJobObject) { + @RequestBody A1eEiJobInfo eiJobObject) { final boolean isNewJob = this.eiJobs.get(eiJobId) == null; @@ -292,13 +291,13 @@ public class ConsumerController { } private Mono startEiJob(EiJob newEiJob) { - return this.producerCallbacks.startEiJob(newEiJob, eiProducers) // + return this.producerCallbacks.startInfoSubscriptionJob(newEiJob, eiProducers) // .doOnNext(noOfAcceptingProducers -> this.logger.debug( "Started EI job {}, number of activated producers: {}", newEiJob.getId(), noOfAcceptingProducers)) // .flatMap(noOfAcceptingProducers -> Mono.just(newEiJob)); } - private Mono validatePutEiJob(String eiJobId, ConsumerEiJobInfo eiJobInfo) { + private Mono validatePutEiJob(String eiJobId, A1eEiJobInfo eiJobInfo) { try { EiType eiType = this.eiTypes.getType(eiJobInfo.eiTypeId); validateJsonObjectAgainstSchema(eiType.getJobDataSchema(), eiJobInfo.jobDefinition); @@ -331,7 +330,7 @@ public class ConsumerController { } } - private EiJob toEiJob(ConsumerEiJobInfo info, String id, EiType type) { + private EiJob toEiJob(A1eEiJobInfo info, String id, EiType type) { return EiJob.builder() // .id(id) // .typeId(type.getId()) // @@ -342,12 +341,11 @@ public class ConsumerController { .build(); } - private ConsumerEiTypeInfo toEiTypeInfo() { - return new ConsumerEiTypeInfo(); + private A1eEiTypeInfo toEiTypeInfo() { + return new A1eEiTypeInfo(); } - private ConsumerEiJobInfo toEiJobInfo(EiJob s) { - return new ConsumerEiJobInfo(s.getTypeId(), s.getJobData(), s.getOwner(), s.getTargetUrl(), - s.getJobStatusUrl()); + private A1eEiJobInfo toEiJobInfo(EiJob s) { + return new A1eEiJobInfo(s.getTypeId(), s.getJobData(), s.getOwner(), s.getTargetUrl(), s.getJobStatusUrl()); } } diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerEiJobInfo.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eEiJobInfo.java similarity index 90% rename from enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerEiJobInfo.java rename to enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eEiJobInfo.java index 0b750f5c..05506d21 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerEiJobInfo.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eEiJobInfo.java @@ -18,7 +18,7 @@ * ========================LICENSE_END=================================== */ -package org.oransc.enrichment.controllers.consumer; +package org.oransc.enrichment.controllers.a1e; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.annotations.SerializedName; @@ -29,7 +29,7 @@ import org.immutables.gson.Gson; @Gson.TypeAdapters @Schema(name = "EiJobObject", description = "Information for an Enrichment Information Job") -public class ConsumerEiJobInfo { +public class A1eEiJobInfo { @Schema(name = "eiTypeId", description = "EI type Idenitifier of the EI job", required = true) @SerializedName("eiTypeId") @@ -56,11 +56,10 @@ public class ConsumerEiJobInfo { @JsonProperty(value = "jobStatusNotificationUri", required = false) public String statusNotificationUri; - public ConsumerEiJobInfo() { + public A1eEiJobInfo() { } - public ConsumerEiJobInfo(String eiTypeId, Object jobData, String owner, String targetUri, - String statusNotificationUri) { + public A1eEiJobInfo(String eiTypeId, Object jobData, String owner, String targetUri, String statusNotificationUri) { this.eiTypeId = eiTypeId; this.jobDefinition = jobData; this.owner = owner; diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerEiJobStatus.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eEiJobStatus.java similarity index 90% rename from enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerEiJobStatus.java rename to enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eEiJobStatus.java index 87a69bb4..cc558658 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerEiJobStatus.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eEiJobStatus.java @@ -18,7 +18,7 @@ * ========================LICENSE_END=================================== */ -package org.oransc.enrichment.controllers.consumer; +package org.oransc.enrichment.controllers.a1e; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.annotations.SerializedName; @@ -29,7 +29,7 @@ import org.immutables.gson.Gson; @Gson.TypeAdapters @Schema(name = "EiJobStatusObject", description = "Status for an EI job") -public class ConsumerEiJobStatus { +public class A1eEiJobStatus { @Gson.TypeAdapters @Schema(name = "EiJobStatusValues", description = "Allowed values for EI job status") @@ -46,10 +46,10 @@ public class ConsumerEiJobStatus { @JsonProperty(value = "eiJobStatus", required = true) public EiJobStatusValues state; - public ConsumerEiJobStatus() { + public A1eEiJobStatus() { } - public ConsumerEiJobStatus(EiJobStatusValues state) { + public A1eEiJobStatus(EiJobStatusValues state) { this.state = state; } diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerEiTypeInfo.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eEiTypeInfo.java similarity index 91% rename from enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerEiTypeInfo.java rename to enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eEiTypeInfo.java index c63d6f74..6202d24b 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerEiTypeInfo.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eEiTypeInfo.java @@ -18,7 +18,7 @@ * ========================LICENSE_END=================================== */ -package org.oransc.enrichment.controllers.consumer; +package org.oransc.enrichment.controllers.a1e; import io.swagger.v3.oas.annotations.media.Schema; @@ -26,6 +26,6 @@ import org.immutables.gson.Gson; @Gson.TypeAdapters @Schema(name = "EiTypeObject", description = "Information for an EI type") -public class ConsumerEiTypeInfo { +public class A1eEiTypeInfo { } diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerConsts.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerConsts.java new file mode 100644 index 00000000..656808f9 --- /dev/null +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerConsts.java @@ -0,0 +1,41 @@ +/*- + * ========================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.enrichment.controllers.r1consumer; + +public class ConsumerConsts { + + public static final String API_ROOT = "/data-consumer/v1"; + + public static final String CONSUMER_API_NAME = "Data consumer"; + public static final String CONSUMER_API_DESCRIPTION = "API for data consumers"; + + public static final String OWNER_PARAM = "owner"; + public static final String OWNER_PARAM_DESCRIPTION = "selects subscription jobs for one job owner"; + + public static final String INDIVIDUAL_JOB = "Individual data subscription job"; + + public static final String INFO_TYPE_ID_PARAM = "infoTypeId"; + public static final String INFO_TYPE_ID_PARAM_DESCRIPTION = + "selects subscription jobs of matching information type"; + + private ConsumerConsts() { + } +} diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerController.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerController.java new file mode 100644 index 00000000..7a1bf184 --- /dev/null +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerController.java @@ -0,0 +1,352 @@ +/*- + * ========================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.enrichment.controllers.r1consumer; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +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.lang.invoke.MethodHandles; +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONObject; +import org.oransc.enrichment.configuration.ApplicationConfig; +import org.oransc.enrichment.controllers.ErrorResponse; +import org.oransc.enrichment.controllers.VoidResponse; +import org.oransc.enrichment.controllers.r1producer.ProducerCallbacks; +import org.oransc.enrichment.exceptions.ServiceException; +import org.oransc.enrichment.repository.EiJob; +import org.oransc.enrichment.repository.EiJobs; +import org.oransc.enrichment.repository.EiProducers; +import org.oransc.enrichment.repository.EiType; +import org.oransc.enrichment.repository.EiTypes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +@SuppressWarnings("java:S3457") // No need to call "toString()" method as formatting and string .. +@RestController("Consumer registry") +@Tag(name = ConsumerConsts.CONSUMER_API_NAME) +@RequestMapping(path = ConsumerConsts.API_ROOT, produces = MediaType.APPLICATION_JSON_VALUE) +public class ConsumerController { + + private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + @Autowired + ApplicationConfig applicationConfig; + + @Autowired + private EiJobs jobs; + + @Autowired + private EiTypes infoTypes; + + @Autowired + private EiProducers infoProducers; + + @Autowired + ProducerCallbacks producerCallbacks; + + private static Gson gson = new GsonBuilder().create(); + + @GetMapping(path = "/info-types", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Information type identifiers", description = "") + @ApiResponses( + value = { // + @ApiResponse( + responseCode = "200", + description = "Information type identifiers", // + content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))), // + }) + public ResponseEntity getinfoTypeIdentifiers( // + ) { + List result = new ArrayList<>(); + for (EiType infoType : this.infoTypes.getAllInfoTypes()) { + result.add(infoType.getId()); + } + + return new ResponseEntity<>(gson.toJson(result), HttpStatus.OK); + } + + @GetMapping(path = "/info-types/{infoTypeId}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Individual information type", description = "") + @ApiResponses( + value = { // + @ApiResponse( + responseCode = "200", + description = "Information type", // + content = @Content(schema = @Schema(implementation = ConsumerInfoTypeInfo.class))), // + @ApiResponse( + responseCode = "404", + description = "Information type is not found", // + content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // + }) + public ResponseEntity getInfoType( // + @PathVariable("infoTypeId") String infoTypeId) { + try { + EiType type = this.infoTypes.getType(infoTypeId); + ConsumerInfoTypeInfo info = toInfoTypeInfo(type); + return new ResponseEntity<>(gson.toJson(info), HttpStatus.OK); + } catch (Exception e) { + return ErrorResponse.create(e, HttpStatus.NOT_FOUND); + } + } + + @GetMapping(path = "/info-jobs", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "EI job identifiers", description = "query for information job identifiers") + @ApiResponses( + value = { // + @ApiResponse( + responseCode = "200", + description = "Information information job identifiers", // + content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))), + @ApiResponse( + responseCode = "404", + description = "Information type is not found", // + content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // + }) + public ResponseEntity getJobIds( // + @Parameter( + name = ConsumerConsts.INFO_TYPE_ID_PARAM, + required = false, // + description = ConsumerConsts.INFO_TYPE_ID_PARAM_DESCRIPTION) // + @RequestParam(name = ConsumerConsts.INFO_TYPE_ID_PARAM, required = false) String infoTypeId, + @Parameter( + name = ConsumerConsts.OWNER_PARAM, + required = false, // + description = ConsumerConsts.OWNER_PARAM_DESCRIPTION) // + @RequestParam(name = ConsumerConsts.OWNER_PARAM, required = false) String owner) { + try { + List result = new ArrayList<>(); + if (owner != null) { + for (EiJob job : this.jobs.getJobsForOwner(owner)) { + if (infoTypeId == null || job.getTypeId().equals(infoTypeId)) { + result.add(job.getId()); + } + } + } else if (infoTypeId != null) { + this.jobs.getJobsForType(infoTypeId).forEach(job -> result.add(job.getId())); + } else { + this.jobs.getJobs().forEach(job -> result.add(job.getId())); + } + return new ResponseEntity<>(gson.toJson(result), HttpStatus.OK); + } catch ( + + Exception e) { + return ErrorResponse.create(e, HttpStatus.NOT_FOUND); + } + } + + @GetMapping(path = "/info-jobs/{infoJobId}", produces = MediaType.APPLICATION_JSON_VALUE) // + @Operation(summary = ConsumerConsts.INDIVIDUAL_JOB, description = "") // + @ApiResponses( + value = { // + @ApiResponse( + responseCode = "200", + description = "Information subscription job", // + content = @Content(schema = @Schema(implementation = ConsumerJobInfo.class))), // + @ApiResponse( + responseCode = "404", + description = "Information subscription job is not found", // + content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // + }) + public ResponseEntity getIndividualEiJob( // + @PathVariable("infoJobId") String infoJobId) { + try { + EiJob job = this.jobs.getJob(infoJobId); + return new ResponseEntity<>(gson.toJson(toInfoJobInfo(job)), HttpStatus.OK); + } catch (Exception e) { + return ErrorResponse.create(e, HttpStatus.NOT_FOUND); + } + } + + @GetMapping(path = "/info-jobs/{infoJobId}/status", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Job status", description = "") + @ApiResponses( + value = { // + @ApiResponse( + responseCode = "200", + description = "Information subscription job status", // + content = @Content(schema = @Schema(implementation = ConsumerJobStatus.class))), // + @ApiResponse( + responseCode = "404", + description = "Information subscription job is not found", // + content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // + }) + public ResponseEntity getEiJobStatus( // + @PathVariable("infoJobId") String jobId) { + try { + EiJob job = this.jobs.getJob(jobId); + return new ResponseEntity<>(gson.toJson(toInfoJobStatus(job)), HttpStatus.OK); + } catch (Exception e) { + return ErrorResponse.create(e, HttpStatus.NOT_FOUND); + } + } + + private ConsumerJobStatus toInfoJobStatus(EiJob job) { + return this.infoProducers.isJobEnabled(job) + ? new ConsumerJobStatus(ConsumerJobStatus.InfoJobStatusValues.ENABLED) + : new ConsumerJobStatus(ConsumerJobStatus.InfoJobStatusValues.DISABLED); + + } + + @DeleteMapping(path = "/info-jobs/{infoJobId}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = ConsumerConsts.INDIVIDUAL_JOB, description = "") + @ApiResponses( + value = { // + @ApiResponse( + responseCode = "200", + description = "Not used", // + content = @Content(schema = @Schema(implementation = VoidResponse.class))), + @ApiResponse( + responseCode = "204", + description = "Job deleted", // + content = @Content(schema = @Schema(implementation = VoidResponse.class))), // "Individual EI job" + @ApiResponse( + responseCode = "404", + description = "Information subscription job is not found", // + content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // + }) + public ResponseEntity deleteIndividualEiJob( // + @PathVariable("infoJobId") String jobId) { + try { + EiJob job = this.jobs.getJob(jobId); + this.jobs.remove(job, this.infoProducers); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } catch (Exception e) { + return ErrorResponse.create(e, HttpStatus.NOT_FOUND); + } + } + + @PutMapping( + path = "/info-jobs/{infoJobId}", // + produces = MediaType.APPLICATION_JSON_VALUE, // + consumes = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = ConsumerConsts.INDIVIDUAL_JOB) + @ApiResponses( + value = { // + @ApiResponse( + responseCode = "201", + description = "Job created", // + content = @Content(schema = @Schema(implementation = VoidResponse.class))), // + @ApiResponse( + responseCode = "200", + description = "Job updated", // + content = @Content(schema = @Schema(implementation = VoidResponse.class))), // + @ApiResponse( + responseCode = "404", + description = "Enrichment Information type is not found", // + content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // + }) + public Mono> putIndividualInfoJob( // + @PathVariable("infoJobId") String jobId, // + @RequestBody ConsumerJobInfo informationJobObject) { + + final boolean isNewJob = this.jobs.get(jobId) == null; + + return validatePutInfoJob(jobId, informationJobObject) // + .flatMap(this::startInfoSubscriptionJob) // + .doOnNext(newEiJob -> this.jobs.put(newEiJob)) // + .flatMap(newEiJob -> Mono.just(new ResponseEntity<>(isNewJob ? HttpStatus.CREATED : HttpStatus.OK))) + .onErrorResume(throwable -> Mono.just(ErrorResponse.create(throwable, HttpStatus.NOT_FOUND))); + } + + private Mono startInfoSubscriptionJob(EiJob newInfoJob) { + return this.producerCallbacks.startInfoSubscriptionJob(newInfoJob, infoProducers) // + .doOnNext(noOfAcceptingProducers -> this.logger.debug("Started job {}, number of activated producers: {}", + newInfoJob.getId(), noOfAcceptingProducers)) // + .flatMap(noOfAcceptingProducers -> Mono.just(newInfoJob)); + } + + private Mono validatePutInfoJob(String jobId, ConsumerJobInfo jobInfo) { + try { + EiType infoType = this.infoTypes.getType(jobInfo.infoTypeId); + validateJsonObjectAgainstSchema(infoType.getJobDataSchema(), jobInfo.jobDefinition); + EiJob existingEiJob = this.jobs.get(jobId); + + if (existingEiJob != null && !existingEiJob.getTypeId().equals(jobInfo.infoTypeId)) { + throw new ServiceException("Not allowed to change type for existing job", HttpStatus.CONFLICT); + } + return Mono.just(toEiJob(jobInfo, jobId, infoType)); + } catch (Exception e) { + return Mono.error(e); + } + } + + private void validateJsonObjectAgainstSchema(Object schemaObj, Object object) throws ServiceException { + if (schemaObj != null) { // schema is optional for now + try { + ObjectMapper mapper = new ObjectMapper(); + + String schemaAsString = mapper.writeValueAsString(schemaObj); + JSONObject schemaJSON = new JSONObject(schemaAsString); + org.everit.json.schema.Schema schema = org.everit.json.schema.loader.SchemaLoader.load(schemaJSON); + + String objectAsString = mapper.writeValueAsString(object); + JSONObject json = new JSONObject(objectAsString); + schema.validate(json); + } catch (Exception e) { + throw new ServiceException("Json validation failure " + e.toString(), HttpStatus.CONFLICT); + } + } + } + + private EiJob toEiJob(ConsumerJobInfo info, String id, EiType type) { + return EiJob.builder() // + .id(id) // + .typeId(type.getId()) // + .owner(info.owner) // + .jobData(info.jobDefinition) // + .targetUrl(info.jobResultUri) // + .jobStatusUrl(info.statusNotificationUri == null ? "" : info.statusNotificationUri) // + .build(); + } + + private ConsumerInfoTypeInfo toInfoTypeInfo(EiType type) { + return new ConsumerInfoTypeInfo(type.getJobDataSchema()); + } + + private ConsumerJobInfo toInfoJobInfo(EiJob s) { + return new ConsumerJobInfo(s.getTypeId(), s.getJobData(), s.getOwner(), s.getTargetUrl(), s.getJobStatusUrl()); + } +} diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerInfoTypeInfo.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerInfoTypeInfo.java new file mode 100644 index 00000000..b3ef96af --- /dev/null +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerInfoTypeInfo.java @@ -0,0 +1,46 @@ +/*- + * ========================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.enrichment.controllers.r1consumer; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.gson.annotations.SerializedName; + +import io.swagger.v3.oas.annotations.media.Schema; + +import org.immutables.gson.Gson; + +@Gson.TypeAdapters +@Schema(name = "InformationType", description = "Information for an Information type") +public class ConsumerInfoTypeInfo { + + @Schema(name = "consumer_job_data_schema", description = "Json schema for the job data", required = true) + @SerializedName("consumer__job_data_schema") + @JsonProperty(value = "consumer_job_data_schema", required = true) + public Object jobDataSchema; + + public ConsumerInfoTypeInfo(Object jobDataSchema) { + this.jobDataSchema = jobDataSchema; + } + + public ConsumerInfoTypeInfo() { + } + +} diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerJobInfo.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerJobInfo.java new file mode 100644 index 00000000..09a78fa9 --- /dev/null +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerJobInfo.java @@ -0,0 +1,73 @@ +/*- + * ========================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.enrichment.controllers.r1consumer; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.gson.annotations.SerializedName; + +import io.swagger.v3.oas.annotations.media.Schema; + +import org.immutables.gson.Gson; + +@Gson.TypeAdapters +@Schema(name = "Job", description = "Information for an Enrichment Information Job") +public class ConsumerJobInfo { + + @Schema(name = "infoTypeId", description = "Information type Idenitifier of the subscription job", required = true) + @SerializedName("infoTypeId") + @JsonProperty(value = "infoTypeId", required = true) + public String infoTypeId; + + @Schema(name = "jobOwner", description = "Identity of the owner of the job", required = true) + @SerializedName("jobOwner") + @JsonProperty(value = "jobOwner", required = true) + public String owner; + + @Schema(name = "jobDefinition", description = "Information type specific job data", required = true) + @SerializedName("jobDefinition") + @JsonProperty(value = "jobDefinition", required = true) + public Object jobDefinition; + + @Schema(name = "jobResultUri", description = "The target URI of the subscribed information", required = true) + @SerializedName("jobResultUri") + @JsonProperty(value = "jobResultUri", required = true) + public String jobResultUri; + + @Schema( + name = "statusNotificationUri", + description = "The target of Information subscription job status notifications", + required = false) + @SerializedName("jobStatusNotificationUri") + @JsonProperty(value = "jobStatusNotificationUri", required = false) + public String statusNotificationUri; + + public ConsumerJobInfo() { + } + + public ConsumerJobInfo(String eiTypeId, Object jobData, String owner, String targetUri, + String statusNotificationUri) { + this.infoTypeId = eiTypeId; + this.jobDefinition = jobData; + this.owner = owner; + this.jobResultUri = targetUri; + this.statusNotificationUri = statusNotificationUri; + } +} diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerJobStatus.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerJobStatus.java new file mode 100644 index 00000000..034fc33d --- /dev/null +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerJobStatus.java @@ -0,0 +1,56 @@ +/*- + * ========================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.enrichment.controllers.r1consumer; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.gson.annotations.SerializedName; + +import io.swagger.v3.oas.annotations.media.Schema; + +import org.immutables.gson.Gson; + +@Gson.TypeAdapters +@Schema(name = "JobStatus", description = "Status for an EI job") +public class ConsumerJobStatus { + + @Gson.TypeAdapters + @Schema(name = "JobStatusValues", description = "Allowed values for EI job status") + public enum InfoJobStatusValues { + ENABLED, DISABLED + } + + private static final String OPERATIONAL_STATE_DESCRIPTION = "values:\n" // + + "ENABLED: the A1-EI producer is able to deliver EI result for the EI job\n" // + + "DISABLED: the A1-EI producer is unable to deliver EI result for the EI job"; + + @Schema(name = "eiJobStatus", description = OPERATIONAL_STATE_DESCRIPTION, required = true) + @SerializedName("eiJobStatus") + @JsonProperty(value = "eiJobStatus", required = true) + public InfoJobStatusValues state; + + public ConsumerJobStatus() { + } + + public ConsumerJobStatus(InfoJobStatusValues state) { + this.state = state; + } + +} diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerCallbacks.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerCallbacks.java similarity index 97% rename from enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerCallbacks.java rename to enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerCallbacks.java index 9b489cdf..26dd1a1b 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerCallbacks.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerCallbacks.java @@ -18,7 +18,7 @@ * ========================LICENSE_END=================================== */ -package org.oransc.enrichment.controllers.producer; +package org.oransc.enrichment.controllers.r1producer; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -79,7 +79,7 @@ public class ProducerCallbacks { * @param eiJob an EI job * @return the number of producers that returned OK */ - public Mono startEiJob(EiJob eiJob, EiProducers eiProducers) { + public Mono startInfoSubscriptionJob(EiJob eiJob, EiProducers eiProducers) { Retry retrySpec = Retry.fixedDelay(1, Duration.ofSeconds(1)); return Flux.fromIterable(getProducersForJob(eiJob, eiProducers)) // .flatMap(eiProducer -> startEiJob(eiProducer, eiJob, retrySpec)) // diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerConsts.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerConsts.java similarity index 95% rename from enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerConsts.java rename to enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerConsts.java index 3d37267b..46161303 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerConsts.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerConsts.java @@ -18,12 +18,11 @@ * ========================LICENSE_END=================================== */ -package org.oransc.enrichment.controllers.producer; +package org.oransc.enrichment.controllers.r1producer; public class ProducerConsts { - - public static final String API_ROOT = "/ei-producer/v1"; public static final String PRODUCER_API_NAME = "Data producer (registration)"; + public static final String API_ROOT = "/ei-producer/v1"; public static final String PRODUCER_API_DESCRIPTION = "API for data producers"; public static final String PRODUCER_API_CALLBACKS_NAME = "Data producer (callbacks)"; diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerController.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerController.java similarity index 97% rename from enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerController.java rename to enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerController.java index fb2253db..b63e8342 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerController.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerController.java @@ -18,7 +18,7 @@ * ========================LICENSE_END=================================== */ -package org.oransc.enrichment.controllers.producer; +package org.oransc.enrichment.controllers.r1producer; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -86,7 +86,7 @@ public class ProducerController { public ResponseEntity getEiTypeIdentifiers( // ) { List result = new ArrayList<>(); - for (EiType eiType : this.eiTypes.getAllEiTypes()) { + for (EiType eiType : this.eiTypes.getAllInfoTypes()) { result.add(eiType.getId()); } @@ -170,7 +170,7 @@ public class ProducerController { EiType type = this.eiTypes.get(eiTypeId); if (type == null) { - return ErrorResponse.create("EI type not found", HttpStatus.NOT_FOUND); + return ErrorResponse.create("Information type not found", HttpStatus.NOT_FOUND); } if (!this.eiProducers.getProducersForType(type).isEmpty()) { String firstProducerId = this.eiProducers.getProducersForType(type).iterator().next().getId(); @@ -309,7 +309,11 @@ public class ProducerController { @ApiResponse( responseCode = "200", description = "Producer updated", // - content = @Content(schema = @Schema(implementation = VoidResponse.class))) // + content = @Content(schema = @Schema(implementation = VoidResponse.class))), // + @ApiResponse( + responseCode = "404", + description = "Producer not found", // + content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // }) public ResponseEntity putEiProducer( // @PathVariable("eiProducerId") String eiProducerId, // diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerEiTypeInfo.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerEiTypeInfo.java similarity index 96% rename from enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerEiTypeInfo.java rename to enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerEiTypeInfo.java index e587ce36..c4e495f3 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerEiTypeInfo.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerEiTypeInfo.java @@ -18,7 +18,7 @@ * ========================LICENSE_END=================================== */ -package org.oransc.enrichment.controllers.producer; +package org.oransc.enrichment.controllers.r1producer; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.annotations.SerializedName; diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerJobInfo.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerJobInfo.java similarity index 98% rename from enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerJobInfo.java rename to enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerJobInfo.java index d7dd7174..fcc7b7df 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerJobInfo.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerJobInfo.java @@ -18,7 +18,7 @@ * ========================LICENSE_END=================================== */ -package org.oransc.enrichment.controllers.producer; +package org.oransc.enrichment.controllers.r1producer; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.annotations.SerializedName; diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerRegistrationInfo.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerRegistrationInfo.java similarity index 97% rename from enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerRegistrationInfo.java rename to enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerRegistrationInfo.java index b270c853..f73819fb 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerRegistrationInfo.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerRegistrationInfo.java @@ -18,7 +18,7 @@ * ========================LICENSE_END=================================== */ -package org.oransc.enrichment.controllers.producer; +package org.oransc.enrichment.controllers.r1producer; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.annotations.SerializedName; diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerStatusInfo.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerStatusInfo.java similarity index 97% rename from enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerStatusInfo.java rename to enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerStatusInfo.java index fc19bcae..14d4555f 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerStatusInfo.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerStatusInfo.java @@ -18,7 +18,7 @@ * ========================LICENSE_END=================================== */ -package org.oransc.enrichment.controllers.producer; +package org.oransc.enrichment.controllers.r1producer; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.annotations.SerializedName; diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/EiJobs.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/EiJobs.java index 2f36115f..0380a716 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/EiJobs.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/EiJobs.java @@ -39,7 +39,7 @@ import java.util.ServiceLoader; import java.util.Vector; import org.oransc.enrichment.configuration.ApplicationConfig; -import org.oransc.enrichment.controllers.producer.ProducerCallbacks; +import org.oransc.enrichment.controllers.r1producer.ProducerCallbacks; import org.oransc.enrichment.exceptions.ServiceException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -91,7 +91,7 @@ public class EiJobs { public synchronized EiJob getJob(String id) throws ServiceException { EiJob ric = allEiJobs.get(id); if (ric == null) { - throw new ServiceException("Could not find EI job: " + id); + throw new ServiceException("Could not find Information job: " + id); } return ric; } diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/EiProducers.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/EiProducers.java index f0fc49ff..1fdb9864 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/EiProducers.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/EiProducers.java @@ -28,8 +28,8 @@ import java.util.Map; import java.util.Vector; import org.immutables.value.Value.Immutable; -import org.oransc.enrichment.controllers.consumer.ConsumerCallbacks; -import org.oransc.enrichment.controllers.producer.ProducerCallbacks; +import org.oransc.enrichment.controllers.a1e.A1eCallbacks; +import org.oransc.enrichment.controllers.r1producer.ProducerCallbacks; import org.oransc.enrichment.exceptions.ServiceException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,7 +50,7 @@ public class EiProducers { private ProducerCallbacks producerCallbacks; @Autowired - private ConsumerCallbacks consumerCallbacks; + private A1eCallbacks consumerCallbacks; @Autowired private EiJobs eiJobs; diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/EiTypes.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/EiTypes.java index 363a65e2..7f04099b 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/EiTypes.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/EiTypes.java @@ -77,14 +77,14 @@ public class EiTypes { storeInFile(type); } - public synchronized Collection getAllEiTypes() { + public synchronized Collection getAllInfoTypes() { return new Vector<>(allEiTypes.values()); } public synchronized EiType getType(String id) throws ServiceException { EiType type = allEiTypes.get(id); if (type == null) { - throw new ServiceException("EI type not found: " + id); + throw new ServiceException("Information type not found: " + id); } return type; } diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/tasks/ProducerSupervision.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/tasks/ProducerSupervision.java index d73127f2..7852bef6 100644 --- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/tasks/ProducerSupervision.java +++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/tasks/ProducerSupervision.java @@ -21,8 +21,8 @@ package org.oransc.enrichment.tasks; import org.oransc.enrichment.configuration.ApplicationConfig; -import org.oransc.enrichment.controllers.consumer.ConsumerCallbacks; -import org.oransc.enrichment.controllers.producer.ProducerCallbacks; +import org.oransc.enrichment.controllers.a1e.A1eCallbacks; +import org.oransc.enrichment.controllers.r1producer.ProducerCallbacks; import org.oransc.enrichment.repository.EiJob; import org.oransc.enrichment.repository.EiJobs; import org.oransc.enrichment.repository.EiProducer; @@ -50,11 +50,11 @@ public class ProducerSupervision { private final EiProducers eiProducers; private final EiJobs eiJobs; private final ProducerCallbacks producerCallbacks; - private final ConsumerCallbacks consumerCallbacks; + private final A1eCallbacks consumerCallbacks; @Autowired public ProducerSupervision(ApplicationConfig applicationConfig, EiProducers eiProducers, EiJobs eiJobs, - ProducerCallbacks producerCallbacks, ConsumerCallbacks consumerCallbacks) { + ProducerCallbacks producerCallbacks, A1eCallbacks consumerCallbacks) { this.eiProducers = eiProducers; this.eiJobs = eiJobs; this.producerCallbacks = producerCallbacks; diff --git a/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/ApplicationTest.java b/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/ApplicationTest.java index 29e9aadf..45961416 100644 --- a/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/ApplicationTest.java +++ b/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/ApplicationTest.java @@ -50,16 +50,19 @@ import org.oransc.enrichment.configuration.WebClientConfig; import org.oransc.enrichment.configuration.WebClientConfig.HttpProxyConfig; import org.oransc.enrichment.controller.ConsumerSimulatorController; import org.oransc.enrichment.controller.ProducerSimulatorController; -import org.oransc.enrichment.controllers.consumer.ConsumerConsts; -import org.oransc.enrichment.controllers.consumer.ConsumerEiJobInfo; -import org.oransc.enrichment.controllers.consumer.ConsumerEiJobStatus; -import org.oransc.enrichment.controllers.consumer.ConsumerEiTypeInfo; -import org.oransc.enrichment.controllers.producer.ProducerCallbacks; -import org.oransc.enrichment.controllers.producer.ProducerConsts; -import org.oransc.enrichment.controllers.producer.ProducerEiTypeInfo; -import org.oransc.enrichment.controllers.producer.ProducerJobInfo; -import org.oransc.enrichment.controllers.producer.ProducerRegistrationInfo; -import org.oransc.enrichment.controllers.producer.ProducerStatusInfo; +import org.oransc.enrichment.controllers.a1e.A1eConsts; +import org.oransc.enrichment.controllers.a1e.A1eEiJobInfo; +import org.oransc.enrichment.controllers.a1e.A1eEiJobStatus; +import org.oransc.enrichment.controllers.a1e.A1eEiTypeInfo; +import org.oransc.enrichment.controllers.r1consumer.ConsumerConsts; +import org.oransc.enrichment.controllers.r1consumer.ConsumerInfoTypeInfo; +import org.oransc.enrichment.controllers.r1consumer.ConsumerJobInfo; +import org.oransc.enrichment.controllers.r1producer.ProducerCallbacks; +import org.oransc.enrichment.controllers.r1producer.ProducerConsts; +import org.oransc.enrichment.controllers.r1producer.ProducerEiTypeInfo; +import org.oransc.enrichment.controllers.r1producer.ProducerJobInfo; +import org.oransc.enrichment.controllers.r1producer.ProducerRegistrationInfo; +import org.oransc.enrichment.controllers.r1producer.ProducerStatusInfo; import org.oransc.enrichment.exceptions.ServiceException; import org.oransc.enrichment.repository.EiJob; import org.oransc.enrichment.repository.EiJobs; @@ -99,8 +102,8 @@ import reactor.test.StepVerifier; class ApplicationTest { private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private final String EI_TYPE_ID = "typeId"; - private final String EI_PRODUCER_ID = "producerId"; + private final String TYPE_ID = "typeId"; + private final String PRODUCER_ID = "producerId"; private final String EI_JOB_PROPERTY = "\"property1\""; private final String EI_JOB_ID = "jobId"; @@ -177,129 +180,200 @@ class ApplicationTest { } @Test - void testGetEiTypes() throws Exception { - putEiProducerWithOneType(EI_PRODUCER_ID, "test"); - String url = ConsumerConsts.API_ROOT + "/eitypes"; + void a1eGetEiTypes() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, "test"); + String url = A1eConsts.API_ROOT + "/eitypes"; String rsp = restClient().get(url).block(); assertThat(rsp).isEqualTo("[\"test\"]"); } @Test - void testGetEiTypesEmpty() throws Exception { - String url = ConsumerConsts.API_ROOT + "/eitypes"; + void consumerGetEiTypes() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, "test"); + String url = ConsumerConsts.API_ROOT + "/info-types"; String rsp = restClient().get(url).block(); - assertThat(rsp).isEqualTo("[]"); + assertThat(rsp).isEqualTo("[\"test\"]"); } @Test - void testPutEiType() throws JsonMappingException, JsonProcessingException, ServiceException { - assertThat(putEiType(EI_TYPE_ID)).isEqualTo(HttpStatus.CREATED); - assertThat(putEiType(EI_TYPE_ID)).isEqualTo(HttpStatus.OK); + void a1eGetEiTypesEmpty() throws Exception { + String url = A1eConsts.API_ROOT + "/eitypes"; + String rsp = restClient().get(url).block(); + assertThat(rsp).isEqualTo("[]"); } @Test - void testPutEiType_noSchema() { - String url = ProducerConsts.API_ROOT + "/eitypes/" + EI_TYPE_ID; - String body = "{}"; - testErrorCode(restClient().put(url, body), HttpStatus.BAD_REQUEST, "No schema provided"); + void consumerGetEiTypesEmpty() throws Exception { + String url = ConsumerConsts.API_ROOT + "/info-types"; + String rsp = restClient().get(url).block(); + assertThat(rsp).isEqualTo("[]"); } @Test - void testGetEiType() throws Exception { - putEiProducerWithOneType(EI_PRODUCER_ID, "test"); - String url = ConsumerConsts.API_ROOT + "/eitypes/test"; + void a1eGetEiType() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, "test"); + String url = A1eConsts.API_ROOT + "/eitypes/test"; String rsp = restClient().get(url).block(); - ConsumerEiTypeInfo info = gson.fromJson(rsp, ConsumerEiTypeInfo.class); + A1eEiTypeInfo info = gson.fromJson(rsp, A1eEiTypeInfo.class); assertThat(info).isNotNull(); } @Test - void testDeleteEiType() throws Exception { - putEiType(EI_TYPE_ID); - String url = ProducerConsts.API_ROOT + "/eitypes/" + EI_TYPE_ID; - restClient().delete(url).block(); - assertThat(this.eiTypes.size()).isEqualTo(0); + void consumerGetEiType() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, "test"); + String url = ConsumerConsts.API_ROOT + "/info-types/test"; + String rsp = restClient().get(url).block(); + ConsumerInfoTypeInfo info = gson.fromJson(rsp, ConsumerInfoTypeInfo.class); + assertThat(info).isNotNull(); + assertThat(info.jobDataSchema).isNotNull(); + } - testErrorCode(restClient().delete(url), HttpStatus.NOT_FOUND, "EI type not found"); + @Test + void a1eGetEiTypeNotFound() throws Exception { + String url = A1eConsts.API_ROOT + "/eitypes/junk"; + testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Information type not found: junk"); } @Test - void testDeleteEiTypeExistingProducer() throws Exception { - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - String url = ProducerConsts.API_ROOT + "/eitypes/" + EI_TYPE_ID; - testErrorCode(restClient().delete(url), HttpStatus.NOT_ACCEPTABLE, - "The type has active producers: " + EI_PRODUCER_ID); - assertThat(this.eiTypes.size()).isEqualTo(1); + void consumerGetEiTypeNotFound() throws Exception { + String url = ConsumerConsts.API_ROOT + "/info-types/junk"; + testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Information type not found: junk"); } @Test - void testGetEiTypeNotFound() throws Exception { - String url = ConsumerConsts.API_ROOT + "/eitypes/junk"; - testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "EI type not found: junk"); + void a1eGetEiJobsIds() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiJob(TYPE_ID, "jobId"); + final String JOB_ID_JSON = "[\"jobId\"]"; + String url = A1eConsts.API_ROOT + "/eijobs?eiTypeId=typeId"; + String rsp = restClient().get(url).block(); + assertThat(rsp).isEqualTo(JOB_ID_JSON); + + url = A1eConsts.API_ROOT + "/eijobs?owner=owner"; + rsp = restClient().get(url).block(); + assertThat(rsp).isEqualTo(JOB_ID_JSON); + + url = A1eConsts.API_ROOT + "/eijobs?owner=JUNK"; + rsp = restClient().get(url).block(); + assertThat(rsp).isEqualTo("[]"); + + url = A1eConsts.API_ROOT + "/eijobs"; + rsp = restClient().get(url).block(); + assertThat(rsp).isEqualTo(JOB_ID_JSON); + + url = A1eConsts.API_ROOT + "/eijobs?eiTypeId=typeId&&owner=owner"; + rsp = restClient().get(url).block(); + assertThat(rsp).isEqualTo(JOB_ID_JSON); + + url = A1eConsts.API_ROOT + "/eijobs?eiTypeId=JUNK"; + rsp = restClient().get(url).block(); + assertThat(rsp).isEqualTo("[]"); } @Test - void testGetEiJobsIds() throws Exception { - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - putEiJob(EI_TYPE_ID, "jobId"); + void consumerGetInformationJobsIds() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiJob(TYPE_ID, "jobId"); final String JOB_ID_JSON = "[\"jobId\"]"; - String url = ConsumerConsts.API_ROOT + "/eijobs?eiTypeId=typeId"; + String url = ConsumerConsts.API_ROOT + "/info-jobs?infoTypeId=typeId"; String rsp = restClient().get(url).block(); assertThat(rsp).isEqualTo(JOB_ID_JSON); - url = ConsumerConsts.API_ROOT + "/eijobs?owner=owner"; + url = ConsumerConsts.API_ROOT + "/info-jobs?owner=owner"; rsp = restClient().get(url).block(); assertThat(rsp).isEqualTo(JOB_ID_JSON); - url = ConsumerConsts.API_ROOT + "/eijobs?owner=JUNK"; + url = ConsumerConsts.API_ROOT + "/info-jobs?owner=JUNK"; rsp = restClient().get(url).block(); assertThat(rsp).isEqualTo("[]"); - url = ConsumerConsts.API_ROOT + "/eijobs"; + url = ConsumerConsts.API_ROOT + "/info-jobs"; rsp = restClient().get(url).block(); assertThat(rsp).isEqualTo(JOB_ID_JSON); - url = ConsumerConsts.API_ROOT + "/eijobs?eiTypeId=typeId&&owner=owner"; + url = ConsumerConsts.API_ROOT + "/info-jobs?infoTypeId=typeId&&owner=owner"; rsp = restClient().get(url).block(); assertThat(rsp).isEqualTo(JOB_ID_JSON); - url = ConsumerConsts.API_ROOT + "/eijobs?eiTypeId=JUNK"; + url = ConsumerConsts.API_ROOT + "/info-jobs?infoTypeId=JUNK"; rsp = restClient().get(url).block(); assertThat(rsp).isEqualTo("[]"); } @Test - void testGetEiJob() throws Exception { - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - putEiJob(EI_TYPE_ID, "jobId"); - String url = ConsumerConsts.API_ROOT + "/eijobs/jobId"; + void a1eGetEiJob() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiJob(TYPE_ID, "jobId"); + String url = A1eConsts.API_ROOT + "/eijobs/jobId"; String rsp = restClient().get(url).block(); - ConsumerEiJobInfo info = gson.fromJson(rsp, ConsumerEiJobInfo.class); + A1eEiJobInfo info = gson.fromJson(rsp, A1eEiJobInfo.class); assertThat(info.owner).isEqualTo("owner"); - assertThat(info.eiTypeId).isEqualTo(EI_TYPE_ID); + assertThat(info.eiTypeId).isEqualTo(TYPE_ID); } @Test - void testGetEiJobNotFound() throws Exception { - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - String url = ConsumerConsts.API_ROOT + "/eijobs/junk"; - testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find EI job: junk"); + void consumerGetEiJob() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiJob(TYPE_ID, "jobId"); + String url = ConsumerConsts.API_ROOT + "/info-jobs/jobId"; + String rsp = restClient().get(url).block(); + ConsumerJobInfo info = gson.fromJson(rsp, ConsumerJobInfo.class); + assertThat(info.owner).isEqualTo("owner"); + assertThat(info.infoTypeId).isEqualTo(TYPE_ID); } @Test - void testGetEiJobStatus() throws Exception { - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - putEiJob(EI_TYPE_ID, "jobId"); + void a1eGetEiJobNotFound() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + String url = A1eConsts.API_ROOT + "/eijobs/junk"; + testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find Information job: junk"); + } + + @Test + void consumerGetInfoJobNotFound() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + String url = ConsumerConsts.API_ROOT + "/info-jobs/junk"; + testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find Information job: junk"); + } + + @Test + void a1eGetEiJobStatus() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiJob(TYPE_ID, "jobId"); verifyJobStatus("jobId", "ENABLED"); } @Test - void testDeleteEiJob() throws Exception { - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - putEiJob(EI_TYPE_ID, "jobId"); + void consumerGetEiJobStatus() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiJob(TYPE_ID, "jobId"); + + String url = ConsumerConsts.API_ROOT + "/info-jobs/jobId/status"; + String rsp = restClient().get(url).block(); + assertThat(rsp).contains("ENABLED"); + } + + @Test + void a1eDeleteEiJob() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiJob(TYPE_ID, "jobId"); + assertThat(this.eiJobs.size()).isEqualTo(1); + String url = A1eConsts.API_ROOT + "/eijobs/jobId"; + restClient().delete(url).block(); + assertThat(this.eiJobs.size()).isZero(); + + ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults(); + await().untilAsserted(() -> assertThat(simulatorResults.jobsStopped.size()).isEqualTo(1)); + assertThat(simulatorResults.jobsStopped.get(0)).isEqualTo("jobId"); + } + + @Test + void consumerDeleteEiJob() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiJob(TYPE_ID, "jobId"); assertThat(this.eiJobs.size()).isEqualTo(1); - String url = ConsumerConsts.API_ROOT + "/eijobs/jobId"; + String url = ConsumerConsts.API_ROOT + "/info-jobs/jobId"; restClient().delete(url).block(); assertThat(this.eiJobs.size()).isZero(); @@ -309,19 +383,26 @@ class ApplicationTest { } @Test - void testDeleteEiJobNotFound() throws Exception { - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - String url = ConsumerConsts.API_ROOT + "/eijobs/junk"; - testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find EI job: junk"); + void a1eDeleteEiJobNotFound() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + String url = A1eConsts.API_ROOT + "/eijobs/junk"; + testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find Information job: junk"); } @Test - void testPutEiJob() throws Exception { + void consumerDeleteEiJobNotFound() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + String url = ConsumerConsts.API_ROOT + "/info-jobs/junk"; + testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find Information job: junk"); + } + + @Test + void a1ePutEiJob() throws Exception { // Test that one producer accepting a job is enough - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - putEiProducerWithOneTypeRejecting("simulateProducerError", EI_TYPE_ID); + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiProducerWithOneTypeRejecting("simulateProducerError", TYPE_ID); - String url = ConsumerConsts.API_ROOT + "/eijobs/jobId"; + String url = A1eConsts.API_ROOT + "/eijobs/jobId"; String body = gson.toJson(eiJobInfo()); ResponseEntity resp = restClient().putForEntity(url, body).block(); assertThat(this.eiJobs.size()).isEqualTo(1); @@ -345,28 +426,36 @@ class ApplicationTest { } @Test - void putEiProducerWithOneType_rejecting() throws JsonMappingException, JsonProcessingException, ServiceException { - putEiProducerWithOneTypeRejecting("simulateProducerError", EI_TYPE_ID); - String url = ConsumerConsts.API_ROOT + "/eijobs/" + EI_JOB_ID; - String body = gson.toJson(eiJobInfo()); - restClient().put(url, body).block(); + void consumerPutInformationJob() throws Exception { + // Test that one producer accepting a job is enough + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + + String url = ConsumerConsts.API_ROOT + "/info-jobs/jobId"; + String body = gson.toJson(consumerJobInfo()); + ResponseEntity resp = restClient().putForEntity(url, body).block(); + assertThat(this.eiJobs.size()).isEqualTo(1); + assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.CREATED); ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults(); - // There is one retry -> 2 calls - await().untilAsserted(() -> assertThat(simulatorResults.noOfRejectedCreate).isEqualTo(2)); - assertThat(simulatorResults.noOfRejectedCreate).isEqualTo(2); + await().untilAsserted(() -> assertThat(simulatorResults.jobsStarted.size()).isEqualTo(1)); + ProducerJobInfo request = simulatorResults.jobsStarted.get(0); + assertThat(request.id).isEqualTo("jobId"); - verifyJobStatus(EI_JOB_ID, "DISABLED"); + resp = restClient().putForEntity(url, body).block(); + assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); + EiJob job = this.eiJobs.getJob("jobId"); + assertThat(job.getOwner()).isEqualTo("owner"); + verifyJobStatus(EI_JOB_ID, "ENABLED"); } @Test - void testPutEiJob_jsonSchemavalidationError() throws Exception { - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); + void a1ePutEiJob_jsonSchemavalidationError() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); - String url = ConsumerConsts.API_ROOT + "/eijobs/jobId"; + String url = A1eConsts.API_ROOT + "/eijobs/jobId"; // The element with name "property1" is mandatory in the schema - ConsumerEiJobInfo jobInfo = new ConsumerEiJobInfo("typeId", jsonObject("{ \"XXstring\" : \"value\" }"), "owner", + A1eEiJobInfo jobInfo = new A1eEiJobInfo("typeId", jsonObject("{ \"XXstring\" : \"value\" }"), "owner", "targetUri", "jobStatusUrl"); String body = gson.toJson(jobInfo); @@ -374,45 +463,117 @@ class ApplicationTest { } @Test - void testGetEiProducerTypes() throws Exception { - final String EI_TYPE_ID_2 = EI_TYPE_ID + "_2"; - putEiProducerWithOneType("producer1", EI_TYPE_ID); - putEiJob(EI_TYPE_ID, "jobId"); - putEiProducerWithOneType("producer2", EI_TYPE_ID_2); - putEiJob(EI_TYPE_ID_2, "jobId2"); - String url = ProducerConsts.API_ROOT + "/eitypes"; + void consumerPutJob_jsonSchemavalidationError() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); - ResponseEntity resp = restClient().getForEntity(url).block(); - assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(resp.getBody()).contains(EI_TYPE_ID); - assertThat(resp.getBody()).contains(EI_TYPE_ID_2); + String url = ConsumerConsts.API_ROOT + "/info-jobs/jobId"; + // The element with name "property1" is mandatory in the schema + ConsumerJobInfo jobInfo = new ConsumerJobInfo("typeId", jsonObject("{ \"XXstring\" : \"value\" }"), "owner", + "targetUri", "jobStatusUrl"); + String body = gson.toJson(jobInfo); + + testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT, "Json validation failure"); } @Test - void testChangingEiTypeGetRejected() throws Exception { + void a1eChangingEiTypeGetRejected() throws Exception { putEiProducerWithOneType("producer1", "typeId1"); putEiProducerWithOneType("producer2", "typeId2"); putEiJob("typeId1", "jobId"); - String url = ConsumerConsts.API_ROOT + "/eijobs/jobId"; + String url = A1eConsts.API_ROOT + "/eijobs/jobId"; String body = gson.toJson(eiJobInfo("typeId2", "jobId")); testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT, "Not allowed to change type for existing EI job"); } @Test - void testPutEiProducer() throws Exception { - this.putEiType(EI_TYPE_ID); + void consumerChangingInfoTypeGetRejected() throws Exception { + putEiProducerWithOneType("producer1", "typeId1"); + putEiProducerWithOneType("producer2", "typeId2"); + putEiJob("typeId1", "jobId"); + + String url = ConsumerConsts.API_ROOT + "/info-jobs/jobId"; + String body = gson.toJson(consumerJobInfo("typeId2", "jobId")); + testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT, "Not allowed to change type for existing job"); + } + + @Test + void producerPutEiType() throws JsonMappingException, JsonProcessingException, ServiceException { + assertThat(putEiType(TYPE_ID)).isEqualTo(HttpStatus.CREATED); + assertThat(putEiType(TYPE_ID)).isEqualTo(HttpStatus.OK); + } + + @Test + void producerPutEiType_noSchema() { + String url = ProducerConsts.API_ROOT + "/eitypes/" + TYPE_ID; + String body = "{}"; + testErrorCode(restClient().put(url, body), HttpStatus.BAD_REQUEST, "No schema provided"); + } + + @Test + void producerDeleteEiType() throws Exception { + putEiType(TYPE_ID); + String url = ProducerConsts.API_ROOT + "/eitypes/" + TYPE_ID; + restClient().delete(url).block(); + assertThat(this.eiTypes.size()).isEqualTo(0); + + testErrorCode(restClient().delete(url), HttpStatus.NOT_FOUND, "Information type not found"); + } + + @Test + void producerDeleteEiTypeExistingProducer() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + String url = ProducerConsts.API_ROOT + "/eitypes/" + TYPE_ID; + testErrorCode(restClient().delete(url), HttpStatus.NOT_ACCEPTABLE, + "The type has active producers: " + PRODUCER_ID); + assertThat(this.eiTypes.size()).isEqualTo(1); + } + + @Test + void producerPutProducerWithOneType_rejecting() + throws JsonMappingException, JsonProcessingException, ServiceException { + putEiProducerWithOneTypeRejecting("simulateProducerError", TYPE_ID); + String url = A1eConsts.API_ROOT + "/eijobs/" + EI_JOB_ID; + String body = gson.toJson(eiJobInfo()); + restClient().put(url, body).block(); + + ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults(); + // There is one retry -> 2 calls + await().untilAsserted(() -> assertThat(simulatorResults.noOfRejectedCreate).isEqualTo(2)); + assertThat(simulatorResults.noOfRejectedCreate).isEqualTo(2); + + verifyJobStatus(EI_JOB_ID, "DISABLED"); + } + + @Test + void producerGetEiProducerTypes() throws Exception { + final String EI_TYPE_ID_2 = TYPE_ID + "_2"; + putEiProducerWithOneType("producer1", TYPE_ID); + putEiJob(TYPE_ID, "jobId"); + putEiProducerWithOneType("producer2", EI_TYPE_ID_2); + putEiJob(EI_TYPE_ID_2, "jobId2"); + String url = ProducerConsts.API_ROOT + "/eitypes"; + + ResponseEntity resp = restClient().getForEntity(url).block(); + assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(resp.getBody()).contains(TYPE_ID); + assertThat(resp.getBody()).contains(EI_TYPE_ID_2); + } + + @Test + void producerPutEiProducer() throws Exception { + this.putEiType(TYPE_ID); String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId"; - String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID)); + String body = gson.toJson(producerEiRegistratioInfo(TYPE_ID)); ResponseEntity resp = restClient().putForEntity(url, body).block(); assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.CREATED); assertThat(this.eiTypes.size()).isEqualTo(1); - assertThat(this.eiProducers.getProducersForType(EI_TYPE_ID).size()).isEqualTo(1); + assertThat(this.eiProducers.getProducersForType(TYPE_ID).size()).isEqualTo(1); assertThat(this.eiProducers.size()).isEqualTo(1); - assertThat(this.eiProducers.get("eiProducerId").getEiTypes().iterator().next().getId()).isEqualTo(EI_TYPE_ID); + assertThat(this.eiProducers.get("eiProducerId").getEiTypes().iterator().next().getId()).isEqualTo(TYPE_ID); resp = restClient().putForEntity(url, body).block(); assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); @@ -423,11 +584,11 @@ class ApplicationTest { } @Test - void testPutEiProducerExistingJob() throws Exception { - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - putEiJob(EI_TYPE_ID, "jobId"); + void producerPutEiProducerExistingJob() throws Exception { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiJob(TYPE_ID, "jobId"); String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId"; - String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID)); + String body = gson.toJson(producerEiRegistratioInfo(TYPE_ID)); restClient().putForEntity(url, body).block(); ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults(); @@ -439,20 +600,20 @@ class ApplicationTest { @Test void testPutEiProducer_noType() throws Exception { String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId"; - String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID)); - testErrorCode(restClient().put(url, body), HttpStatus.NOT_FOUND, "EI type not found"); + String body = gson.toJson(producerEiRegistratioInfo(TYPE_ID)); + testErrorCode(restClient().put(url, body), HttpStatus.NOT_FOUND, "Information type not found"); } @Test - void testPutProducerAndEiJob() throws Exception { - this.putEiType(EI_TYPE_ID); + void producerPutProducerAndEiJob() throws Exception { + this.putEiType(TYPE_ID); String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId"; - String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID)); + String body = gson.toJson(producerEiRegistratioInfo(TYPE_ID)); restClient().putForEntity(url, body).block(); assertThat(this.eiTypes.size()).isEqualTo(1); - this.eiTypes.getType(EI_TYPE_ID); + this.eiTypes.getType(TYPE_ID); - url = ConsumerConsts.API_ROOT + "/eijobs/jobId"; + url = A1eConsts.API_ROOT + "/eijobs/jobId"; body = gson.toJson(eiJobInfo()); restClient().putForEntity(url, body).block(); @@ -463,14 +624,14 @@ class ApplicationTest { } @Test - void testGetEiJobsForProducer() throws JsonMappingException, JsonProcessingException, ServiceException { - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - putEiJob(EI_TYPE_ID, "jobId1"); - putEiJob(EI_TYPE_ID, "jobId2"); + void producerGetEiJobsForProducer() throws JsonMappingException, JsonProcessingException, ServiceException { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiJob(TYPE_ID, "jobId1"); + putEiJob(TYPE_ID, "jobId2"); - // PUT a consumer + // PUT a consumerRestApiTestBase.java String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId"; - String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID)); + String body = gson.toJson(producerEiRegistratioInfo(TYPE_ID)); restClient().putForEntity(url, body).block(); url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId/eijobs"; @@ -478,25 +639,25 @@ class ApplicationTest { assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); ProducerJobInfo[] parsedResp = gson.fromJson(resp.getBody(), ProducerJobInfo[].class); - assertThat(parsedResp[0].typeId).isEqualTo(EI_TYPE_ID); - assertThat(parsedResp[1].typeId).isEqualTo(EI_TYPE_ID); + assertThat(parsedResp[0].typeId).isEqualTo(TYPE_ID); + assertThat(parsedResp[1].typeId).isEqualTo(TYPE_ID); } @Test - void testDeleteEiProducer() throws Exception { - putEiProducerWithOneType("eiProducerId", EI_TYPE_ID); - putEiProducerWithOneType("eiProducerId2", EI_TYPE_ID); + void producerDeleteEiProducer() throws Exception { + putEiProducerWithOneType("eiProducerId", TYPE_ID); + putEiProducerWithOneType("eiProducerId2", TYPE_ID); assertThat(this.eiProducers.size()).isEqualTo(2); - EiType type = this.eiTypes.getType(EI_TYPE_ID); + EiType type = this.eiTypes.getType(TYPE_ID); assertThat(this.eiProducers.getProducerIdsForType(type.getId())).contains("eiProducerId"); assertThat(this.eiProducers.getProducerIdsForType(type.getId())).contains("eiProducerId2"); - putEiJob(EI_TYPE_ID, "jobId"); + putEiJob(TYPE_ID, "jobId"); assertThat(this.eiJobs.size()).isEqualTo(1); deleteEiProducer("eiProducerId"); assertThat(this.eiProducers.size()).isEqualTo(1); - assertThat(this.eiProducers.getProducerIdsForType(EI_TYPE_ID)).doesNotContain("eiProducerId"); + assertThat(this.eiProducers.getProducerIdsForType(TYPE_ID)).doesNotContain("eiProducerId"); verifyJobStatus("jobId", "ENABLED"); deleteEiProducer("eiProducerId2"); @@ -506,13 +667,13 @@ class ApplicationTest { } @Test - void testJobStatusNotifications() throws JsonMappingException, JsonProcessingException, ServiceException { + void a1eJobStatusNotifications() throws JsonMappingException, JsonProcessingException, ServiceException { ConsumerSimulatorController.TestResults consumerCalls = this.consumerSimulator.getTestResults(); ProducerSimulatorController.TestResults producerCalls = this.producerSimulator.getTestResults(); - putEiProducerWithOneType("eiProducerId", EI_TYPE_ID); - putEiJob(EI_TYPE_ID, "jobId"); - putEiProducerWithOneType("eiProducerId2", EI_TYPE_ID); + putEiProducerWithOneType("eiProducerId", TYPE_ID); + putEiJob(TYPE_ID, "jobId"); + putEiProducerWithOneType("eiProducerId2", TYPE_ID); await().untilAsserted(() -> assertThat(producerCalls.jobsStarted.size()).isEqualTo(2)); deleteEiProducer("eiProducerId2"); @@ -521,53 +682,53 @@ class ApplicationTest { assertThat(this.eiTypes.size()).isEqualTo(1); // The type remains assertThat(this.eiJobs.size()).isEqualTo(1); // The job remains await().untilAsserted(() -> assertThat(consumerCalls.status.size()).isEqualTo(1)); - assertThat(consumerCalls.status.get(0).state).isEqualTo(ConsumerEiJobStatus.EiJobStatusValues.DISABLED); + assertThat(consumerCalls.status.get(0).state).isEqualTo(A1eEiJobStatus.EiJobStatusValues.DISABLED); - putEiProducerWithOneType("eiProducerId", EI_TYPE_ID); + putEiProducerWithOneType("eiProducerId", TYPE_ID); await().untilAsserted(() -> assertThat(consumerCalls.status.size()).isEqualTo(2)); - assertThat(consumerCalls.status.get(1).state).isEqualTo(ConsumerEiJobStatus.EiJobStatusValues.ENABLED); + assertThat(consumerCalls.status.get(1).state).isEqualTo(A1eEiJobStatus.EiJobStatusValues.ENABLED); } @Test - void testJobStatusNotifications2() throws JsonMappingException, JsonProcessingException, ServiceException { + void a1eJobStatusNotifications2() throws JsonMappingException, JsonProcessingException, ServiceException { // Test replacing a producer with new and removed types // Create a job - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - putEiJob(EI_TYPE_ID, EI_JOB_ID); + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiJob(TYPE_ID, EI_JOB_ID); // change the type for the producer, the job shall be disabled - putEiProducerWithOneType(EI_PRODUCER_ID, "junk"); + putEiProducerWithOneType(PRODUCER_ID, "junk"); verifyJobStatus(EI_JOB_ID, "DISABLED"); ConsumerSimulatorController.TestResults consumerCalls = this.consumerSimulator.getTestResults(); await().untilAsserted(() -> assertThat(consumerCalls.status.size()).isEqualTo(1)); - assertThat(consumerCalls.status.get(0).state).isEqualTo(ConsumerEiJobStatus.EiJobStatusValues.DISABLED); + assertThat(consumerCalls.status.get(0).state).isEqualTo(A1eEiJobStatus.EiJobStatusValues.DISABLED); - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); verifyJobStatus(EI_JOB_ID, "ENABLED"); await().untilAsserted(() -> assertThat(consumerCalls.status.size()).isEqualTo(2)); - assertThat(consumerCalls.status.get(1).state).isEqualTo(ConsumerEiJobStatus.EiJobStatusValues.ENABLED); + assertThat(consumerCalls.status.get(1).state).isEqualTo(A1eEiJobStatus.EiJobStatusValues.ENABLED); } @Test - void testGetProducerEiType() throws JsonMappingException, JsonProcessingException, ServiceException { - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - String url = ProducerConsts.API_ROOT + "/eitypes/" + EI_TYPE_ID; + void producerGetProducerEiType() throws JsonMappingException, JsonProcessingException, ServiceException { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + String url = ProducerConsts.API_ROOT + "/eitypes/" + TYPE_ID; ResponseEntity resp = restClient().getForEntity(url).block(); ProducerEiTypeInfo info = gson.fromJson(resp.getBody(), ProducerEiTypeInfo.class); assertThat(info.jobDataSchema).isNotNull(); } @Test - void testGetProducerIdentifiers() throws JsonMappingException, JsonProcessingException, ServiceException { - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); + void producerGetProducerIdentifiers() throws JsonMappingException, JsonProcessingException, ServiceException { + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); String url = ProducerConsts.API_ROOT + "/eiproducers"; ResponseEntity resp = restClient().getForEntity(url).block(); - assertThat(resp.getBody()).contains(EI_PRODUCER_ID); + assertThat(resp.getBody()).contains(PRODUCER_ID); - url = ProducerConsts.API_ROOT + "/eiproducers?ei_type_id=" + EI_TYPE_ID; + url = ProducerConsts.API_ROOT + "/eiproducers?ei_type_id=" + TYPE_ID; resp = restClient().getForEntity(url).block(); - assertThat(resp.getBody()).contains(EI_PRODUCER_ID); + assertThat(resp.getBody()).contains(PRODUCER_ID); url = ProducerConsts.API_ROOT + "/eiproducers?ei_type_id=junk"; resp = restClient().getForEntity(url).block(); @@ -575,20 +736,20 @@ class ApplicationTest { } @Test - void testProducerSupervision() throws JsonMappingException, JsonProcessingException, ServiceException { + void producerSupervision() throws JsonMappingException, JsonProcessingException, ServiceException { ConsumerSimulatorController.TestResults consumerResults = this.consumerSimulator.getTestResults(); - putEiProducerWithOneTypeRejecting("simulateProducerError", EI_TYPE_ID); + putEiProducerWithOneTypeRejecting("simulateProducerError", TYPE_ID); { // Create a job - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - putEiJob(EI_TYPE_ID, EI_JOB_ID); + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiJob(TYPE_ID, EI_JOB_ID); verifyJobStatus(EI_JOB_ID, "ENABLED"); - deleteEiProducer(EI_PRODUCER_ID); + deleteEiProducer(PRODUCER_ID); // A Job disabled status notification shall now be received await().untilAsserted(() -> assertThat(consumerResults.status.size()).isEqualTo(1)); - assertThat(consumerResults.status.get(0).state).isEqualTo(ConsumerEiJobStatus.EiJobStatusValues.DISABLED); + assertThat(consumerResults.status.get(0).state).isEqualTo(A1eEiJobStatus.EiJobStatusValues.DISABLED); verifyJobStatus(EI_JOB_ID, "DISABLED"); } @@ -610,21 +771,21 @@ class ApplicationTest { // Now we have one disabled job, and no producer. // PUT a producer, then a Job ENABLED status notification shall be received - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); await().untilAsserted(() -> assertThat(consumerResults.status.size()).isEqualTo(2)); - assertThat(consumerResults.status.get(1).state).isEqualTo(ConsumerEiJobStatus.EiJobStatusValues.ENABLED); + assertThat(consumerResults.status.get(1).state).isEqualTo(A1eEiJobStatus.EiJobStatusValues.ENABLED); verifyJobStatus(EI_JOB_ID, "ENABLED"); } @Test - void testProducerSupervision2() throws JsonMappingException, JsonProcessingException, ServiceException { + void producerSupervision2() throws JsonMappingException, JsonProcessingException, ServiceException { // Test that supervision enables not enabled jobs and sends a notification when // suceeded - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - putEiJob(EI_TYPE_ID, EI_JOB_ID); + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiJob(TYPE_ID, EI_JOB_ID); - EiProducer producer = this.eiProducers.getProducer(EI_PRODUCER_ID); + EiProducer producer = this.eiProducers.getProducer(PRODUCER_ID); EiJob job = this.eiJobs.getJob(EI_JOB_ID); // Pretend that the producer did reject the job and the a DISABLED notification // is sent for the job @@ -636,14 +797,14 @@ class ApplicationTest { this.producerSupervision.createTask().blockLast(); ConsumerSimulatorController.TestResults consumerResults = this.consumerSimulator.getTestResults(); await().untilAsserted(() -> assertThat(consumerResults.status.size()).isEqualTo(1)); - assertThat(consumerResults.status.get(0).state).isEqualTo(ConsumerEiJobStatus.EiJobStatusValues.ENABLED); + assertThat(consumerResults.status.get(0).state).isEqualTo(A1eEiJobStatus.EiJobStatusValues.ENABLED); verifyJobStatus(EI_JOB_ID, "ENABLED"); } @Test void testGetStatus() throws JsonMappingException, JsonProcessingException, ServiceException { - putEiProducerWithOneTypeRejecting("simulateProducerError", EI_TYPE_ID); - putEiProducerWithOneTypeRejecting("simulateProducerError2", EI_TYPE_ID); + putEiProducerWithOneTypeRejecting("simulateProducerError", TYPE_ID); + putEiProducerWithOneTypeRejecting("simulateProducerError2", TYPE_ID); String url = "/status"; ResponseEntity resp = restClient().getForEntity(url).block(); @@ -652,9 +813,9 @@ class ApplicationTest { @Test void testEiJobDatabase() throws Exception { - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); - putEiJob(EI_TYPE_ID, "jobId1"); - putEiJob(EI_TYPE_ID, "jobId2"); + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); + putEiJob(TYPE_ID, "jobId1"); + putEiJob(TYPE_ID, "jobId2"); assertThat(this.eiJobs.size()).isEqualTo(2); @@ -687,7 +848,7 @@ class ApplicationTest { @Test void testEiTypesDatabase() throws Exception { - putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID); + putEiProducerWithOneType(PRODUCER_ID, TYPE_ID); assertThat(this.eiTypes.size()).isEqualTo(1); @@ -706,7 +867,7 @@ class ApplicationTest { assertThat(types.size()).isEqualTo(0); } logger.warn("Test removing a job when the db file is gone"); - this.eiTypes.remove(this.eiTypes.getType(EI_TYPE_ID)); + this.eiTypes.remove(this.eiTypes.getType(TYPE_ID)); assertThat(this.eiJobs.size()).isEqualTo(0); } @@ -716,7 +877,7 @@ class ApplicationTest { } private void verifyJobStatus(String jobId, String expStatus) { - String url = ConsumerConsts.API_ROOT + "/eijobs/" + jobId + "/status"; + String url = A1eConsts.API_ROOT + "/eijobs/" + jobId + "/status"; String rsp = restClient().get(url).block(); assertThat(rsp).contains(expStatus); } @@ -747,12 +908,22 @@ class ApplicationTest { baseUrl() + ProducerSimulatorController.JOB_URL, baseUrl() + ProducerSimulatorController.SUPERVISION_URL); } - private ConsumerEiJobInfo eiJobInfo() throws JsonMappingException, JsonProcessingException { - return eiJobInfo(EI_TYPE_ID, EI_JOB_ID); + private ConsumerJobInfo consumerJobInfo() throws JsonMappingException, JsonProcessingException { + return consumerJobInfo(TYPE_ID, EI_JOB_ID); + } + + ConsumerJobInfo consumerJobInfo(String typeId, String eiJobId) + throws JsonMappingException, JsonProcessingException { + return new ConsumerJobInfo(typeId, jsonObject(), "owner", "targetUri", + baseUrl() + ConsumerSimulatorController.getJobStatusUrl(eiJobId)); + } + + private A1eEiJobInfo eiJobInfo() throws JsonMappingException, JsonProcessingException { + return eiJobInfo(TYPE_ID, EI_JOB_ID); } - ConsumerEiJobInfo eiJobInfo(String typeId, String eiJobId) throws JsonMappingException, JsonProcessingException { - return new ConsumerEiJobInfo(typeId, jsonObject(), "owner", "targetUri", + A1eEiJobInfo eiJobInfo(String typeId, String eiJobId) throws JsonMappingException, JsonProcessingException { + return new A1eEiJobInfo(typeId, jsonObject(), "owner", "targetUri", baseUrl() + ConsumerSimulatorController.getJobStatusUrl(eiJobId)); } @@ -788,7 +959,7 @@ class ApplicationTest { private EiJob putEiJob(String eiTypeId, String jobId) throws JsonMappingException, JsonProcessingException, ServiceException { - String url = ConsumerConsts.API_ROOT + "/eijobs/" + jobId; + String url = A1eConsts.API_ROOT + "/eijobs/" + jobId; String body = gson.toJson(eiJobInfo(eiTypeId, jobId)); restClient().putForEntity(url, body).block(); diff --git a/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/controller/ConsumerSimulatorController.java b/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/controller/ConsumerSimulatorController.java index 660277f7..a9fae154 100644 --- a/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/controller/ConsumerSimulatorController.java +++ b/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/controller/ConsumerSimulatorController.java @@ -35,8 +35,8 @@ import java.util.List; import lombok.Getter; import org.oransc.enrichment.controllers.VoidResponse; -import org.oransc.enrichment.controllers.consumer.ConsumerConsts; -import org.oransc.enrichment.controllers.consumer.ConsumerEiJobStatus; +import org.oransc.enrichment.controllers.a1e.A1eConsts; +import org.oransc.enrichment.controllers.a1e.A1eEiJobStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; @@ -48,14 +48,14 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController("ConsumerSimulatorController") -@Tag(name = ConsumerConsts.CONSUMER_API_CALLBACKS_NAME) +@Tag(name = A1eConsts.CONSUMER_API_CALLBACKS_NAME) public class ConsumerSimulatorController { private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); public static class TestResults { - public List status = Collections.synchronizedList(new ArrayList()); + public List status = Collections.synchronizedList(new ArrayList()); public void reset() { status.clear(); @@ -82,7 +82,7 @@ public class ConsumerSimulatorController { }) public ResponseEntity jobStatusCallback( // @PathVariable("eiJobId") String eiJobId, // - @RequestBody ConsumerEiJobStatus status) { + @RequestBody A1eEiJobStatus status) { logger.info("Job status callback status: {} eiJobId: {}", status.state, eiJobId); this.testResults.status.add(status); return new ResponseEntity<>(HttpStatus.OK); diff --git a/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/controller/ProducerSimulatorController.java b/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/controller/ProducerSimulatorController.java index 8f99e501..f9828ff1 100644 --- a/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/controller/ProducerSimulatorController.java +++ b/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/controller/ProducerSimulatorController.java @@ -36,8 +36,8 @@ import lombok.Getter; import org.oransc.enrichment.controllers.ErrorResponse; import org.oransc.enrichment.controllers.VoidResponse; -import org.oransc.enrichment.controllers.producer.ProducerConsts; -import org.oransc.enrichment.controllers.producer.ProducerJobInfo; +import org.oransc.enrichment.controllers.r1producer.ProducerConsts; +import org.oransc.enrichment.controllers.r1producer.ProducerJobInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; -- 2.16.6