diff options
29 files changed, 1063 insertions, 1735 deletions
@@ -43,5 +43,8 @@ out/ _build/ .swagger* docs/offeredapis/swagger/README.md +a1-policy-management/api/README.md a1-policy-management/api/.openapi-generator* +a1-policy-management/api/pms-api/.openapi-generator* + diff --git a/a1-policy-management/Dockerfile b/a1-policy-management/Dockerfile index 44108979..54676d39 100644 --- a/a1-policy-management/Dockerfile +++ b/a1-policy-management/Dockerfile @@ -39,6 +39,7 @@ RUN mkdir -p /var/policy-management-service RUN chmod -R 777 /var/policy-management-service + RUN groupadd -r onap && useradd -ms /bin/bash a1pms -g onap RUN chown -R a1pms:onap /var/log/policy-agent diff --git a/a1-policy-management/api/pms-api.yaml b/a1-policy-management/api/pms-api.yaml index 44dc2ba4..3633bcac 100644 --- a/a1-policy-management/api/pms-api.yaml +++ b/a1-policy-management/api/pms-api.yaml @@ -1,4 +1,24 @@ -openapi: 3.0.1 +# ============LICENSE_START======================================================= +# Copyright (C) 2020-2023 Nordix Foundation +# Modifications Copyright (C) 2021 Pantheon.tech +# Modifications Copyright (C) 2021 Bell Canada +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# ============LICENSE_END========================================================= + +openapi: 3.0.3 info: description: "<h2>General</h2><p>The O-RAN Non-RT RIC Policy Management Service\ \ provides a REST API for management of A1 policies. <br/>The main tasks of the\ @@ -32,17 +52,17 @@ info: title: A1 Policy Management Service version: 1.2.0 servers: -- url: / + - url: / tags: -- description: "API used for authorization of information A1 policy access (this is\ - \ provided by an authorization producer such as OPA).\nNote that this API is called\ - \ by PMS, it is not provided.\n" - name: Authorization API -- description: Monitor and interact - externalDocs: - description: Spring Boot Actuator Web API Documentation - url: https://docs.spring.io/spring-boot/docs/current/actuator-api/html/ - name: Actuator + - description: "API used for authorization of information A1 policy access (this is + provided by an authorization producer such as OPA). <br> Note that this API is called + by PMS, it is not provided." + name: Authorization API + - description: Monitor and interact + externalDocs: + description: Spring Boot Actuator Web API Documentation + url: https://docs.spring.io/spring-boot/docs/current/actuator-api/html/ + name: Actuator paths: /a1-policy/v2/policy-instances: get: @@ -51,45 +71,48 @@ paths: \ are returned." operationId: getPolicyInstances parameters: - - description: Select policies with a given type identity. - explode: true - in: query - name: policytype_id - required: false - schema: - type: string - style: form - - description: Select policies for a given Near-RT RIC identity. - explode: true - in: query - name: ric_id - required: false - schema: - type: string - style: form - - description: Select policies owned by a given service. - explode: true - in: query - name: service_id - required: false - schema: - type: string - style: form - - description: Select policies of a given type name (type identity has the format - <typename_version>) - explode: true - in: query - name: type_name - required: false - schema: - type: string - style: form + - description: Select policies with a given type identity. + explode: true + in: query + name: policytype_id + required: false + schema: + type: string + style: form + - description: Select policies for a given Near-RT RIC identity. + explode: true + in: query + name: ric_id + required: false + schema: + type: string + style: form + - description: Select policies owned by a given service. + explode: true + in: query + name: service_id + required: false + schema: + type: string + style: form + - description: Select policies of a given type name (type identity has the format + <typename_version>) + explode: true + in: query + name: type_name + required: false + schema: + type: string + style: form responses: "200": content: application/json: + examples: + policy_info_list: + $ref: '#/components/examples/policy_info_list' schema: - $ref: '#/components/schemas/policy_info_list_v2' + type: object description: Policies "404": content: @@ -99,7 +122,7 @@ paths: description: "Near-RT RIC, policy type or service not found" summary: Query for A1 policy instances tags: - - A1 Policy Management + - A1 Policy Management /example-authz-check: post: description: The authorization function decides if access is granted. @@ -119,7 +142,7 @@ paths: description: OK summary: Request for access authorization. tags: - - Authorization API + - Authorization API /actuator/threaddump: get: operationId: threaddump @@ -141,7 +164,7 @@ paths: description: OK summary: Actuator web endpoint 'threaddump' tags: - - Actuator + - Actuator /a1-policy/v2/status: get: operationId: getStatus @@ -150,11 +173,14 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/status_info_v2' + type: object + examples: + status_info: + $ref: '#/components/examples/status_info' description: Service is living summary: Returns status and statistics of this service tags: - - Health Check + - Health Check /actuator/loggers: get: operationId: loggers @@ -173,7 +199,7 @@ paths: description: OK summary: Actuator web endpoint 'loggers' tags: - - Actuator + - Actuator /actuator/health/**: get: operationId: health-path @@ -192,7 +218,7 @@ paths: description: OK summary: Actuator web endpoint 'health-path' tags: - - Actuator + - Actuator /a1-policy/v2/rics/ric: get: description: Either a Near-RT RIC identity or a Managed Element identity can @@ -200,29 +226,32 @@ paths: in O1 for accessing the traffical element (such as the ID of CU). operationId: getRic parameters: - - description: "The identity of a Managed Element. If given, the Near-RT RIC\ + - description: "The identity of a Managed Element. If given, the Near-RT RIC\ \ managing the ME is returned." - explode: true - in: query - name: managed_element_id - required: false - schema: - type: string - style: form - - description: The identity of a Near-RT RIC to get information for. - explode: true - in: query - name: ric_id - required: false - schema: - type: string - style: form + explode: true + in: query + name: managed_element_id + required: false + schema: + type: string + style: form + - description: The identity of a Near-RT RIC to get information for. + explode: true + in: query + name: ric_id + required: false + schema: + type: string + style: form responses: "200": content: application/json: schema: - $ref: '#/components/schemas/ric_info_v2' + type: object + examples: + ric_info: + $ref: '#/components/examples/ric_info' description: Near-RT RIC is found "404": content: @@ -232,7 +261,7 @@ paths: description: Near-RT RIC is not found summary: Returns info for one Near-RT RIC tags: - - NearRT-RIC Repository + - NearRT-RIC Repository /actuator/shutdown: post: operationId: shutdown @@ -251,45 +280,48 @@ paths: description: OK summary: Actuator web endpoint 'shutdown' tags: - - Actuator + - Actuator /a1-policy/v2/policy-types: get: operationId: getPolicyTypes parameters: - - description: Select types for the given Near-RT RIC identity. - explode: true - in: query - name: ric_id - required: false - schema: - type: string - style: form - - description: Select types with the given type name (type identity has the - format <typename_version>) - explode: true - in: query - name: type_name - required: false - schema: - type: string - style: form - - description: Select types that are compatible with the given version. This - parameter is only applicable in conjunction with type_name. As an example - version 1.9.1 is compatible with 1.0.0 but not the other way around. Matching - types will be returned sorted in ascending order. - explode: true - in: query - name: compatible_with_version - required: false - schema: - type: string - style: form + - description: Select types for the given Near-RT RIC identity. + explode: true + in: query + name: ric_id + required: false + schema: + type: string + style: form + - description: Select types with the given type name (type identity has the + format <typename_version>) + explode: true + in: query + name: type_name + required: false + schema: + type: string + style: form + - description: Select types that are compatible with the given version. This + parameter is only applicable in conjunction with type_name. As an example + version 1.9.1 is compatible with 1.0.0 but not the other way around. Matching + types will be returned sorted in ascending order. + explode: true + in: query + name: compatible_with_version + required: false + schema: + type: string + style: form responses: "200": content: application/json: + examples: + policy_type_id_list: + $ref: '#/components/examples/policy_type_id_list' schema: - $ref: '#/components/schemas/policytype_id_list_v2' + type: object description: Policy type IDs "404": content: @@ -299,18 +331,18 @@ paths: description: Near-RT RIC is not found summary: Query policy type identities tags: - - A1 Policy Management + - A1 Policy Management /a1-policy/v2/policies/{policy_id}: delete: operationId: deletePolicy parameters: - - explode: false - in: path - name: policy_id - required: true - schema: - type: string - style: simple + - explode: false + in: path + name: policy_id + required: true + schema: + type: string + style: simple responses: "200": content: @@ -338,23 +370,26 @@ paths: description: Policy is not found summary: Delete a policy tags: - - A1 Policy Management + - A1 Policy Management get: operationId: getPolicy parameters: - - explode: false - in: path - name: policy_id - required: true - schema: - type: string - style: simple + - explode: false + in: path + name: policy_id + required: true + schema: + type: string + style: simple responses: "200": content: application/json: schema: - $ref: '#/components/schemas/policy_info_v2' + type: object + examples: + policy_info: + $ref: '#/components/examples/policy_info' description: Policy found "404": content: @@ -364,18 +399,18 @@ paths: description: Policy is not found summary: Returns a policy tags: - - A1 Policy Management + - A1 Policy Management /actuator/metrics/{requiredMetricName}: get: operationId: metrics-requiredMetricName parameters: - - explode: false - in: path - name: requiredMetricName - required: true - schema: - type: string - style: simple + - explode: false + in: path + name: requiredMetricName + required: true + schema: + type: string + style: simple responses: "200": content: @@ -391,7 +426,7 @@ paths: description: OK summary: Actuator web endpoint 'metrics-requiredMetricName' tags: - - Actuator + - Actuator /a1-policy/v2/configuration: get: operationId: getConfiguration @@ -410,7 +445,7 @@ paths: description: File is not found or readable summary: Returns the contents of the application configuration file tags: - - Management of configuration + - configuration put: operationId: putConfiguration requestBody: @@ -441,7 +476,7 @@ paths: again. summary: Replace the current configuration file with the given configuration tags: - - Management of configuration + - configuration /actuator: get: operationId: links @@ -472,18 +507,18 @@ paths: description: OK summary: Actuator root web endpoint tags: - - Actuator + - Actuator /actuator/loggers/{name}: get: operationId: loggers-name parameters: - - explode: false - in: path - name: name - required: true - schema: - type: string - style: simple + - explode: false + in: path + name: name + required: true + schema: + type: string + style: simple responses: "200": content: @@ -499,29 +534,29 @@ paths: description: OK summary: Actuator web endpoint 'loggers-name' tags: - - Actuator + - Actuator post: operationId: loggers-name_2 parameters: - - explode: false - in: path - name: name - required: true - schema: - type: string - style: simple + - explode: false + in: path + name: name + required: true + schema: + type: string + style: simple requestBody: content: application/json: schema: enum: - - TRACE - - DEBUG - - INFO - - WARN - - ERROR - - FATAL - - "OFF" + - TRACE + - DEBUG + - INFO + - WARN + - ERROR + - FATAL + - "OFF" type: string responses: "200": @@ -532,7 +567,7 @@ paths: description: OK summary: Actuator web endpoint 'loggers-name' tags: - - Actuator + - Actuator /a1-policy/v2/services/{service_id}/keepalive: put: description: A registered service should invoke this operation regularly to @@ -542,13 +577,13 @@ paths: when each service is initially registered) operationId: keepAliveService parameters: - - explode: false - in: path - name: service_id - required: true - schema: - type: string - style: simple + - explode: false + in: path + name: service_id + required: true + schema: + type: string + style: simple responses: "200": content: @@ -564,7 +599,7 @@ paths: description: "The service is not found, needs re-registration" summary: Heartbeat indicates that the service is running tags: - - Service Registry and Supervision + - Service Registry and Supervision /actuator/metrics: get: operationId: metrics @@ -583,28 +618,31 @@ paths: description: OK summary: Actuator web endpoint 'metrics' tags: - - Actuator + - Actuator /a1-policy/v2/rics: get: description: The call returns all Near-RT RICs that supports a given policy type identity operationId: getRics parameters: - - description: "The identity of a policy type. If given, all Near-RT RICs supporting\ + - description: "The identity of a policy type. If given, all Near-RT RICs supporting\ \ the policy type are returned" - explode: true - in: query - name: policytype_id - required: false - schema: - type: string - style: form + explode: true + in: query + name: policytype_id + required: false + schema: + type: string + style: form responses: "200": content: application/json: schema: - $ref: '#/components/schemas/ric_info_list_v2' + type: object + examples: + ric_info_list: + $ref: '#/components/examples/ric_info_list' description: OK "404": content: @@ -614,27 +652,30 @@ paths: description: Policy type is not found summary: Query Near-RT RIC information tags: - - NearRT-RIC Repository + - NearRT-RIC Repository /a1-policy/v2/services: get: description: Either information about a registered service with given identity or all registered services are returned. operationId: getServices parameters: - - description: The identity of the service - explode: true - in: query - name: service_id - required: false - schema: - type: string - style: form + - description: The identity of the service + explode: true + in: query + name: service_id + required: false + schema: + type: string + style: form responses: "200": content: application/json: schema: - $ref: '#/components/schemas/service_list_v2' + type: object + examples: + service_status_list: + $ref: '#/components/examples/service_status_list' description: OK "404": content: @@ -644,7 +685,7 @@ paths: description: Service is not found summary: Returns service information tags: - - Service Registry and Supervision + - Service Registry and Supervision put: description: "Registering a service is needed to:<ul><li>Get callbacks about\ \ available NearRT RICs.</li><li>Activate supervision of the service. If a\ @@ -656,7 +697,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/service_registration_info_v2' + $ref: '#/components/schemas/service_registration_info' required: true responses: "200": @@ -679,7 +720,7 @@ paths: description: The ServiceRegistrationInfo is not accepted summary: Register a service tags: - - Service Registry and Supervision + - Service Registry and Supervision /actuator/info: get: operationId: info @@ -698,7 +739,7 @@ paths: description: OK summary: Actuator web endpoint 'info' tags: - - Actuator + - Actuator /status: get: operationId: getStatusV1 @@ -711,34 +752,37 @@ paths: description: Service is living summary: Returns status and statistics of this service tags: - - Health Check + - Health Check /a1-policy/v2/policy-types/{policytype_id}: get: - operationId: getPolicyType + operationId: getPolicyTypeDefinition parameters: - - explode: false - in: path - name: policytype_id - required: true - schema: - type: string - style: simple + - explode: false + in: path + name: policytype_id + required: true + schema: + type: string + style: simple responses: "200": content: - '*/*': + application/json: schema: - $ref: '#/components/schemas/policytype_v2' - description: Policy type + type: object + examples: + policy_type_definition: + $ref: '#/components/examples/policy_type_definition' + description: schema of the given policy type "404": content: - '*/*': + application/json: schema: $ref: '#/components/schemas/error_information' description: Policy type is not found summary: Returns a policy type definition tags: - - A1 Policy Management + - A1 Policy Management /actuator/logfile: get: operationId: logfile @@ -751,7 +795,7 @@ paths: description: OK summary: Actuator web endpoint 'logfile' tags: - - Actuator + - Actuator /actuator/health: get: operationId: health @@ -770,7 +814,7 @@ paths: description: OK summary: Actuator web endpoint 'health' tags: - - Actuator + - Actuator /a1-policy/v2/policies: get: description: "Returns a list of A1 policies matching given search criteria.\ @@ -778,45 +822,48 @@ paths: \ are returned." operationId: getPolicyIds parameters: - - description: Select policies of a given policy type identity. - explode: true - in: query - name: policytype_id - required: false - schema: - type: string - style: form - - description: Select policies of a given Near-RT RIC identity. - explode: true - in: query - name: ric_id - required: false - schema: - type: string - style: form - - description: Select policies owned by a given service. - explode: true - in: query - name: service_id - required: false - schema: - type: string - style: form - - description: Select policies of types with the given type name (type identity - has the format <typename_version>) - explode: true - in: query - name: type_name - required: false - schema: - type: string - style: form + - description: Select policies of a given policy type identity. + explode: true + in: query + name: policytype_id + required: false + schema: + type: string + style: form + - description: Select policies of a given Near-RT RIC identity. + explode: true + in: query + name: ric_id + required: false + schema: + type: string + style: form + - description: Select policies owned by a given service. + explode: true + in: query + name: service_id + required: false + schema: + type: string + style: form + - description: Select policies of types with the given type name (type identity + has the format <typename_version>) + explode: true + in: query + name: type_name + required: false + schema: + type: string + style: form responses: "200": content: application/json: + examples: + policy_id_list: + $ref: '#/components/examples/policy_id_list' schema: - $ref: '#/components/schemas/policy_id_list_v2' + type: object description: Policy identities "404": content: @@ -826,14 +873,14 @@ paths: description: Near-RT RIC or type not found summary: Query policy identities tags: - - A1 Policy Management + - A1 Policy Management put: operationId: putPolicy requestBody: content: application/json: schema: - $ref: '#/components/schemas/policy_info_v2' + $ref: '#/components/schemas/policy_info' required: true responses: "200": @@ -862,7 +909,7 @@ paths: description: Near-RT RIC or policy type is not found summary: Create or update a policy tags: - - A1 Policy Management + - A1 Policy Management /r-app/near-rt-ric-status: post: description: The URL to this call is registered at Service registration. @@ -882,18 +929,18 @@ paths: description: OK summary: Callback for Near-RT RIC status tags: - - Service callbacks + - Service callbacks /a1-policy/v2/services/{service_id}: delete: operationId: deleteService parameters: - - explode: false - in: path - name: service_id - required: true - schema: - type: string - style: simple + - explode: false + in: path + name: service_id + required: true + schema: + type: string + style: simple responses: "200": content: @@ -915,7 +962,7 @@ paths: description: Service not found summary: Unregister a service tags: - - Service Registry and Supervision + - Service Registry and Supervision /actuator/heapdump: get: operationId: heapdump @@ -928,24 +975,27 @@ paths: description: OK summary: Actuator web endpoint 'heapdump' tags: - - Actuator + - Actuator /a1-policy/v2/policies/{policy_id}/status: get: operationId: getPolicyStatus parameters: - - explode: false - in: path - name: policy_id - required: true - schema: - type: string - style: simple + - explode: false + in: path + name: policy_id + required: true + schema: + type: string + style: simple responses: "200": content: application/json: + examples: + policy_status_info: + $ref: '#/components/examples/policy_status_info' schema: - $ref: '#/components/schemas/policy_status_info_v2' + type: object description: Policy status "404": content: @@ -955,9 +1005,118 @@ paths: description: Policy is not found summary: Returns a policy status tags: - - A1 Policy Management + - A1 Policy Management components: + examples: + service_status: + description: List of service information + value: + callback_url: callback_url + service_id: service_id + keep_alive_interval_seconds: 0 + time_since_last_activity_seconds: 6 + service_status_list: + description: List of service information + value: + service_list: + - callback_url: callback_url + service_id: service_id + keep_alive_interval_seconds: 0 + time_since_last_activity_seconds: 6 + - callback_url: callback_url + service_id: service_id + keep_alive_interval_seconds: 0 + time_since_last_activity_seconds: 6 + policy_type_definition: + description: Schema of the given Policy type + value: + policy_schema: "{}" + policy_type_id_list: + description: Array of policy type id's + value: + policy_type_id_list: + - policytype_id + - policytype_id + policy_info: + description: Policy information of one A1-P policy + value: + ric_id: ric_id + policy_id: policy_id + transient: false + service_id: service_id + policy_data: "{}" + status_notification_uri: status_notification_uri + policytype_id: policytype_id + policy_info_list: + description: List of policy information + value: + policies: + - ric_id: ric_id + policy_id: policy_id + transient: false + service_id: service_id + policy_data: "{}" + status_notification_uri: status_notification_uri + policytype_id: policytype_id + - ric_id: ric_id + policy_id: policy_id + transient: false + service_id: service_id + policy_data: "{}" + status_notification_uri: status_notification_uri + policytype_id: policytype_id + policy_id_list: + description: A list of policy identities + value: + policy_ids: + - policy_ids + - policy_ids + policy_status_info: + description: Status for one A1-P Policy + value: + last_modified: last_modified + status: "{}" + status_info: + value: + status: status + ric_info: + value: + ric_id: ric_id + managed_element_ids: + - managed_element_ids + - managed_element_ids + state: UNAVAILABLE + policytype_ids: + - policytype_ids + - policytype_ids + ric_info_list: + value: + rics: + - ric_id: ric_id + managed_element_ids: + - managed_element_ids + - managed_element_ids + state: UNAVAILABLE + policytype_ids: + - policytype_ids + - policytype_ids + - ric_id: ric_id + managed_element_ids: + - managed_element_ids + - managed_element_ids + state: UNAVAILABLE + policytype_ids: + - policytype_ids + - policytype_ids schemas: + policy_type_definition: + description: Contains policy type schema definition + type: object + properties: + policy_schema: + description: Policy type json schema. The schema is a json object following + http://json-schema.org/draft-07/schema + type: object error_information: description: Problem as defined in https://tools.ietf.org/html/rfc7807 properties: @@ -976,9 +1135,7 @@ components: void: description: Void/empty type: object - status_info_v2: - example: - status: status + status_info: properties: status: description: status text @@ -993,19 +1150,10 @@ components: description: "If true, the access is granted" type: boolean required: - - result + - result type: object - ric_info_v2: + ric_info: description: Information for a Near-RT RIC - example: - ric_id: ric_id - managed_element_ids: - - managed_element_ids - - managed_element_ids - state: UNAVAILABLE - policytype_ids: - - policytype_ids - - policytype_ids properties: ric_id: description: identity of the Near-RT RIC @@ -1019,10 +1167,10 @@ components: state: description: Represents the states for a Near-RT RIC enum: - - UNAVAILABLE - - AVAILABLE - - SYNCHRONIZING - - CONSISTENCY_CHECK + - UNAVAILABLE + - AVAILABLE + - SYNCHRONIZING + - CONSISTENCY_CHECK type: string policytype_ids: description: supported policy types @@ -1031,7 +1179,7 @@ components: type: string type: array type: object - service_registration_info_v2: + service_registration_info: description: Information for one service properties: callback_url: @@ -1051,38 +1199,19 @@ components: format: int64 type: integer required: - - service_id + - service_id type: object - policy_info_list_v2: + policy_info_list: description: List of policy information - example: - policies: - - ric_id: ric_id - policy_id: policy_id - transient: false - service_id: service_id - policy_data: "{}" - status_notification_uri: status_notification_uri - policytype_id: policytype_id - - ric_id: ric_id - policy_id: policy_id - transient: false - service_id: service_id - policy_data: "{}" - status_notification_uri: status_notification_uri - policytype_id: policytype_id properties: policies: description: List of policy information items: - $ref: '#/components/schemas/policy_info_v2' + $ref: '#/components/schemas/policy_info' type: array type: object - policy_status_info_v2: + policy_status_info: description: Status for one A1-P Policy - example: - last_modified: last_modified - status: "{}" properties: last_modified: description: "timestamp, last modification time" @@ -1091,13 +1220,7 @@ components: description: the Policy status type: object type: object - service_status_v2: - description: List of service information - example: - callback_url: callback_url - service_id: service_id - keep_alive_interval_seconds: 0 - time_since_last_activity_seconds: 6 + service_status: properties: callback_url: description: callback for notifying of RIC synchronization @@ -1114,52 +1237,24 @@ components: format: int64 type: integer type: object - ric_info_list_v2: + ric_info_list: description: List of Near-RT RIC information - example: - rics: - - ric_id: ric_id - managed_element_ids: - - managed_element_ids - - managed_element_ids - state: UNAVAILABLE - policytype_ids: - - policytype_ids - - policytype_ids - - ric_id: ric_id - managed_element_ids: - - managed_element_ids - - managed_element_ids - state: UNAVAILABLE - policytype_ids: - - policytype_ids - - policytype_ids properties: rics: description: List of Near-RT RIC information items: - $ref: '#/components/schemas/ric_info_v2' + $ref: '#/components/schemas/ric_info' type: array type: object - policytype_v2: - description: Policy type - example: - policy_schema: "{}" - properties: - policy_schema: - description: Policy type json schema. The schema is a json object following - http://json-schema.org/draft-07/schema - type: object - type: object input: description: input properties: access_type: description: Access type enum: - - READ - - WRITE - - DELETE + - READ + - WRITE + - DELETE type: string auth_token: description: Authorization token @@ -1168,9 +1263,9 @@ components: description: Policy type identifier type: string required: - - access_type - - auth_token - - policy_type_id + - access_type + - auth_token + - policy_type_id type: object policy_authorization: description: Authorization request for A1 policy requests @@ -1178,14 +1273,10 @@ components: input: $ref: '#/components/schemas/input' required: - - input + - input type: object - policytype_id_list_v2: + policy_type_id_list: description: Information about policy types - example: - policytype_ids: - - policytype_ids - - policytype_ids properties: policytype_ids: description: Policy type identities @@ -1194,16 +1285,8 @@ components: type: string type: array type: object - policy_info_v2: + policy_info: description: Information for one A1-P Policy - example: - ric_id: ric_id - policy_id: policy_id - transient: false - service_id: service_id - policy_data: "{}" - status_notification_uri: status_notification_uri - policytype_id: policytype_id properties: ric_id: description: identity of the target Near-RT RIC @@ -1217,6 +1300,7 @@ components: \ value is maintained by this service until explicitly deleted. Default\ \ false." example: false + nullable: false type: boolean service_id: description: the identity of the service owning the policy. This can be @@ -1233,17 +1317,18 @@ components: description: identity of the policy type type: string required: - - policy_data - - policy_id - - policytype_id - - ric_id + - ric_id + - policy_id + - service_id + - policy_data + - policytype_id type: object - policy_id_list_v2: + policy_id_list: description: A list of policy identities example: policy_ids: - - policy_ids - - policy_ids + - policy_ids + - policy_ids properties: policy_ids: description: Policy identities @@ -1252,23 +1337,12 @@ components: type: string type: array type: object - service_list_v2: - description: List of service information - example: - service_list: - - callback_url: callback_url - service_id: service_id - keep_alive_interval_seconds: 0 - time_since_last_activity_seconds: 6 - - callback_url: callback_url - service_id: service_id - keep_alive_interval_seconds: 0 - time_since_last_activity_seconds: 6 + service_status_list: properties: service_list: description: List of service information items: - $ref: '#/components/schemas/service_status_v2' + $ref: '#/components/schemas/service_status' type: array type: object service_callback_info_v2: @@ -1281,11 +1355,11 @@ components: description: "values:\nAVAILABLE: the Near-RT RIC has become available\ \ for A1 Policy management" enum: - - AVAILABLE + - AVAILABLE type: string required: - - event_type - - ric_id + - event_type + - ric_id type: object Link: properties: diff --git a/a1-policy-management/pom.xml b/a1-policy-management/pom.xml index 6b797526..2a24dbca 100644 --- a/a1-policy-management/pom.xml +++ b/a1-policy-management/pom.xml @@ -51,6 +51,26 @@ </properties> <dependencies> <dependency> + <groupId>javax.validation</groupId> + <artifactId>validation-api</artifactId> + <version>2.0.1.Final</version> + </dependency> + <dependency> + <groupId>javax.annotation</groupId> + <artifactId>javax.annotation-api</artifactId> + <version>1.3.2</version> + </dependency> + <dependency> + <groupId>io.swagger.core.v3</groupId> + <artifactId>swagger-annotations</artifactId> + <version>2.2.15</version> + </dependency> + <dependency> + <groupId>org.openapitools</groupId> + <artifactId>jackson-databind-nullable</artifactId> + <version>0.2.4</version> + </dependency> + <dependency> <!-- Temporary until version 2 is included by the parent spring-boot-starter-parent --> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> @@ -62,10 +82,6 @@ </dependency> <dependency> <groupId>org.springframework</groupId> - <artifactId>spring-beans</artifactId> - </dependency> - <dependency> - <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <dependency> @@ -73,22 +89,10 @@ <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-web</artifactId> - </dependency> - <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-webmvc</artifactId> - </dependency> - <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-webflux</artifactId> - </dependency> - <dependency> <!-- May be possible to remove this later when ccsdk parent bom stabilizes --> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> @@ -154,17 +158,6 @@ <optional>true</optional> <scope>runtime</scope> </dependency> - <!-- TEST --> - <dependency> - <groupId>org.springdoc</groupId> - <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> - <version>${springdoc.version}</version> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-test</artifactId> - <scope>test</scope> - </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> @@ -217,6 +210,7 @@ <plugin> <groupId>org.codehaus.gmaven</groupId> <artifactId>groovy-maven-plugin</artifactId> + <version>2.1.1</version> <executions> <execution> <phase>validate</phase> @@ -284,9 +278,6 @@ </configuration> </plugin> <plugin> - <artifactId>maven-failsafe-plugin</artifactId> - </plugin> - <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <executions> @@ -325,9 +316,31 @@ </executions> </plugin> <plugin> + <groupId>io.swagger.codegen.v3</groupId> + <artifactId>swagger-codegen-maven-plugin</artifactId> + <version>3.0.46</version> + <executions> + <execution> + <id>generate-openapi-json</id> + <phase>prepare-package</phase> + <goals> + <goal>generate</goal> + </goals> + <configuration> + <inputSpec>${project.basedir}/api/pms-api.yaml</inputSpec> + <language>openapi</language> + <output>${project.basedir}/api</output> + <configOptions> + <outputFile>pms-api.json</outputFile> + </configOptions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> <groupId>org.openapitools</groupId> <artifactId>openapi-generator-maven-plugin</artifactId> - <version>6.0.0</version> + <version>6.6.0</version> <executions> <execution> <id>generate-openapi-html</id> @@ -353,18 +366,32 @@ </configuration> </execution> <execution> - <id>generate-openapi-yaml</id> - <phase>prepare-package</phase> + <id>generate-policy-api</id> + <phase>generate-sources </phase> <goals> <goal>generate</goal> </goals> <configuration> - <inputSpec>${project.basedir}/api/pms-api.json</inputSpec> - <generatorName>openapi-yaml</generatorName> - <verbose>false</verbose> - <output>${project.basedir}/api</output> + <inputSpec>${project.basedir}/api/pms-api.yaml</inputSpec> + <invokerPackage>${project.groupId}.a1policymanagementservice.controllers.v2</invokerPackage> + <apiPackage>${project.groupId}.a1policymanagementservice.controllers.api.v2</apiPackage> + <modelPackage>${project.groupId}.a1policymanagementservice.models.v2</modelPackage> + <generateApiTests>false</generateApiTests> + <generateModelTests>false</generateModelTests> + <generatorName>spring</generatorName> + <generateSupportingFiles>false</generateSupportingFiles> + <skipValidateSpec>false</skipValidateSpec> + <library>spring-boot</library> <configOptions> - <outputFile>pms-api.yaml</outputFile> + <sourceFolder>src/gen/java</sourceFolder> + <interfaceOnly>true</interfaceOnly> + <useTags>true</useTags> + <reactive>true</reactive> + <dateLibrary>java8</dateLibrary> + <java8>true</java8> + <unhandledException>true</unhandledException> + <openApiNullable>false</openApiNullable> + <skipDefaultInterface>true</skipDefaultInterface> </configOptions> </configuration> </execution> diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java index 0d93eae2..71eae06f 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java @@ -31,8 +31,9 @@ import org.onap.ccsdk.oran.a1policymanagementservice.repository.Rics; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Services; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -78,8 +79,8 @@ public class BeanFactory { } @Bean - public ServletWebServerFactory servletContainer() { - TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); + public ReactiveWebServerFactory servletContainer() { + TomcatReactiveWebServerFactory tomcat = new TomcatReactiveWebServerFactory(); if (httpPort > 0) { tomcat.addAdditionalTomcatConnectors(getHttpConnector(httpPort)); } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConfigurationController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConfigurationController.java index 0d0919d8..6bf6fbaf 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConfigurationController.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConfigurationController.java @@ -22,38 +22,28 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import com.google.gson.JsonParser; - -import io.swagger.v3.oas.annotations.Operation; -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.io.IOException; -import java.util.Optional; - import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig; import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfigParser; import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ConfigurationFile; -import org.onap.ccsdk.oran.a1policymanagementservice.controllers.VoidResponse; +import org.onap.ccsdk.oran.a1policymanagementservice.controllers.api.v2.ConfigurationApi; 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.GetMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; +import java.io.IOException; +import java.util.Optional; @RestController("ConfigurationControllerV2") @Tag( // name = ConfigurationController.API_NAME, // description = ConfigurationController.API_DESCRIPTION // ) -public class ConfigurationController { +public class ConfigurationController implements ConfigurationApi { private static final Logger logger = LoggerFactory.getLogger(ConfigurationController.class); public static final String API_NAME = "Management of configuration"; @@ -71,58 +61,43 @@ public class ConfigurationController { private static Gson gson = new GsonBuilder() // .create(); // - @PutMapping(path = Consts.V2_API_ROOT + "/configuration", consumes = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Replace the current configuration file with the given configuration") - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", // - description = "Configuration updated", // - content = @Content(schema = @Schema(implementation = VoidResponse.class))), // - @ApiResponse(responseCode = "400", // - description = "Invalid configuration provided", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))), // - @ApiResponse(responseCode = "500", // - description = "Something went wrong when replacing the configuration. Try again.", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // - }) - public ResponseEntity<Object> putConfiguration(@RequestBody Object configuration) { - try { - String configAsString = gson.toJson(configuration); - JsonObject configJson = JsonParser.parseString(configAsString).getAsJsonObject(); - ApplicationConfigParser configParser = new ApplicationConfigParser(applicationConfig); - configParser.parse(configJson); - configurationFile.writeFile(configJson); - logger.info("Configuration changed through REST call."); - return new ResponseEntity<>(HttpStatus.OK); - } catch (IOException ioe) { - logger.warn("Configuration file not written, {}.", ioe.getMessage()); - return ErrorResponse.create("Internal error when writing the configuration.", - HttpStatus.INTERNAL_SERVER_ERROR); - } catch (Exception e) { - return ErrorResponse.create(e, HttpStatus.BAD_REQUEST); - } + @Override + public Mono<ResponseEntity<Object>> putConfiguration(final Mono<Object> configuration, + final ServerWebExchange exchange) { + return configuration + .flatMap(configObject -> { + try { + String configAsString = gson.toJson(configObject); + JsonObject configJson = JsonParser.parseString(configAsString).getAsJsonObject(); + ApplicationConfigParser configParser = new ApplicationConfigParser(applicationConfig); + configParser.parse(configJson); + configurationFile.writeFile(configJson); + logger.info("Configuration changed through REST call."); + return Mono.just(new ResponseEntity<>(HttpStatus.OK)); + } catch (IOException ioe) { + logger.warn("Configuration file not written, {}.", ioe.getMessage()); + return ErrorResponse.createMono("Internal error when writing the configuration.", + HttpStatus.INTERNAL_SERVER_ERROR); + } catch (Exception e) { + return ErrorResponse.createMono(e, HttpStatus.BAD_REQUEST); + } + }) + .onErrorResume(error -> { + return ErrorResponse.createMono(error.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + }); } - @GetMapping(path = Consts.V2_API_ROOT + "/configuration", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Returns the contents of the application configuration file") // - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", // - description = "Configuration", // - content = @Content(schema = @Schema(implementation = Object.class))), // - @ApiResponse(responseCode = "404", // - description = "File is not found or readable", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) - - }) - public ResponseEntity<Object> getConfiguration() { + @Override + public Mono<ResponseEntity<Object>> getConfiguration(final ServerWebExchange exchange) { try { Optional<JsonObject> rootObject = configurationFile.readFile(); if (rootObject.isPresent()) { - return new ResponseEntity<>(rootObject.get().toString(), HttpStatus.OK); + return Mono.just(new ResponseEntity<>(rootObject.get().toString(), HttpStatus.OK)); } else { - return ErrorResponse.create("File does not exist", HttpStatus.NOT_FOUND); + return ErrorResponse.createMono("File does not exist", HttpStatus.NOT_FOUND); } } catch (Exception e) { - return ErrorResponse.create(e, HttpStatus.INTERNAL_SERVER_ERROR); + return ErrorResponse.createMono(e, HttpStatus.INTERNAL_SERVER_ERROR); } } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java index 64905f44..23dcba71 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java @@ -2,7 +2,7 @@ * ========================LICENSE_START================================= * ONAP : ccsdk oran * ====================================================================== - * Copyright (C) 2019-2020 Nordix Foundation. All rights reserved. + * Copyright (C) 2019-2023 Nordix Foundation. All rights reserved. * ====================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,15 +20,12 @@ package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +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.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; @@ -41,38 +38,28 @@ import java.util.Map; import lombok.Getter; import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1ClientFactory; -import org.onap.ccsdk.oran.a1policymanagementservice.controllers.VoidResponse; +import org.onap.ccsdk.oran.a1policymanagementservice.controllers.api.v2.A1PolicyManagementApi; import org.onap.ccsdk.oran.a1policymanagementservice.controllers.authorization.AuthorizationCheck; import org.onap.ccsdk.oran.a1policymanagementservice.controllers.authorization.PolicyAuthorizationRequest.Input.AccessType; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.EntityNotFoundException; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.Lock; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.Lock.LockType; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policies; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policy; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyType; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyTypes; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.Ric; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.Rics; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.Service; -import org.onap.ccsdk.oran.a1policymanagementservice.repository.Services; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyTypeDefinition; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyInfo; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyTypeIdList; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyInfoList; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyIdList; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyStatusInfo; +import org.onap.ccsdk.oran.a1policymanagementservice.repository.*; 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.RequestHeader; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.reactive.function.client.WebClientException; import org.springframework.web.reactive.function.client.WebClientResponseException; +import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -81,7 +68,7 @@ import reactor.core.publisher.Mono; name = PolicyController.API_NAME, // description = PolicyController.API_DESCRIPTION // ) -public class PolicyController { +public class PolicyController implements A1PolicyManagementApi { public static final String API_NAME = "A1 Policy Management"; public static final String API_DESCRIPTION = ""; @@ -108,7 +95,8 @@ public class PolicyController { private A1ClientFactory a1ClientFactory; @Autowired private Services services; - + @Autowired + private ObjectMapper objectMapper; @Autowired private AuthorizationCheck authorization; @@ -116,51 +104,17 @@ public class PolicyController { private static Gson gson = new GsonBuilder() // .create(); // - @GetMapping(path = Consts.V2_API_ROOT + "/policy-types/{policytype_id:.+}") // - @Operation(summary = "Returns a policy type definition") // - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", // - description = "Policy type", // - content = @Content(schema = @Schema(implementation = PolicyTypeInfo.class))), // - @ApiResponse(responseCode = "404", // - description = "Policy type is not found", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class)))// - }) - public ResponseEntity<Object> getPolicyType( // - @PathVariable("policytype_id") String policyTypeId) throws EntityNotFoundException { + @Override + public Mono<ResponseEntity<Object>> getPolicyTypeDefinition(String policyTypeId, ServerWebExchange exchange) + throws EntityNotFoundException, JsonProcessingException { PolicyType type = policyTypes.getType(policyTypeId); - PolicyTypeInfo info = new PolicyTypeInfo(type.getSchema()); - return new ResponseEntity<>(gson.toJson(info), HttpStatus.OK); + JsonNode node = objectMapper.readTree(type.getSchema()); + PolicyTypeDefinition policyTypeDefinition = new PolicyTypeDefinition().policySchema(node); + return Mono.just(new ResponseEntity<>(policyTypeDefinition, HttpStatus.OK)); } - @GetMapping(path = Consts.V2_API_ROOT + "/policy-types", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Query policy type identities") - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", // - description = "Policy type IDs", // - content = @Content(schema = @Schema(implementation = PolicyTypeIdList.class))), // - @ApiResponse(responseCode = "404", // - description = "Near-RT RIC is not found", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // - }) - public ResponseEntity<Object> getPolicyTypes( // - @Parameter(name = Consts.RIC_ID_PARAM, required = false, // - description = "Select types for the given Near-RT RIC identity.") // - @RequestParam(name = Consts.RIC_ID_PARAM, required = false) String ricId, - - @Parameter(name = Consts.TYPE_NAME_PARAM, required = false, // - description = "Select types with the given type name (type identity has the format <typename_version>)") // - @RequestParam(name = Consts.TYPE_NAME_PARAM, required = false) String typeName, - - @Parameter(name = Consts.COMPATIBLE_WITH_VERSION_PARAM, required = false, // - description = "Select types that are compatible with the given version. This parameter is only applicable in conjunction with " - + Consts.TYPE_NAME_PARAM - + ". As an example version 1.9.1 is compatible with 1.0.0 but not the other way around." - + " Matching types will be returned sorted in ascending order.") // - @RequestParam(name = Consts.COMPATIBLE_WITH_VERSION_PARAM, required = false) String compatibleWithVersion - - ) throws ServiceException { - + @Override + public Mono<ResponseEntity<Object>> getPolicyTypes(String ricId, String typeName, String compatibleWithVersion, ServerWebExchange exchange) throws Exception { if (compatibleWithVersion != null && typeName == null) { throw new ServiceException("Parameter " + Consts.COMPATIBLE_WITH_VERSION_PARAM + " can only be used when " + Consts.TYPE_NAME_PARAM + " is given", HttpStatus.BAD_REQUEST); @@ -170,117 +124,82 @@ public class PolicyController { ricId != null ? rics.getRic(ricId).getSupportedPolicyTypes() : this.policyTypes.getAll(); types = PolicyTypes.filterTypes(types, typeName, compatibleWithVersion); - return new ResponseEntity<>(toPolicyTypeIdsJson(types), HttpStatus.OK); + return Mono.just(new ResponseEntity<>(toPolicyTypeIdsJson(types), HttpStatus.OK)); } - @GetMapping(path = Consts.V2_API_ROOT + "/policies/{policy_id:.+}", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Returns a policy") // - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", // - description = "Policy found", // - content = @Content(schema = @Schema(implementation = PolicyInfo.class))), // - @ApiResponse(responseCode = "404", // - description = "Policy is not found", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // - }) - public Mono<ResponseEntity<Object>> getPolicy( // - @PathVariable(name = Consts.POLICY_ID_PARAM, required = true) String id, - @RequestHeader Map<String, String> headers) throws EntityNotFoundException { - Policy policy = policies.getPolicy(id); - return authorization.doAccessControl(headers, policy, AccessType.READ) // - .map(x -> new ResponseEntity<>((Object) gson.toJson(toPolicyInfo(policy)), HttpStatus.OK)) // + + @Override + public Mono<ResponseEntity<Object>> getPolicy(String policyId, final ServerWebExchange exchange) + throws EntityNotFoundException { + Policy policy = policies.getPolicy(policyId); + return authorization.doAccessControl(exchange.getRequest().getHeaders().toSingleValueMap(), policy, AccessType.READ) // + .map(x -> new ResponseEntity<>((Object) toPolicyInfo(policy), HttpStatus.OK)) // .onErrorResume(this::handleException); } - @DeleteMapping(Consts.V2_API_ROOT + "/policies/{policy_id:.+}") - @Operation(summary = "Delete a policy") - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", // - description = "Not used", // - content = @Content(schema = @Schema(implementation = VoidResponse.class))), // - @ApiResponse(responseCode = "204", // - description = "Policy deleted", // - content = @Content(schema = @Schema(implementation = VoidResponse.class))), // - @ApiResponse(responseCode = "404", // - description = "Policy is not found", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))), // - @ApiResponse(responseCode = "423", // - description = "Near-RT RIC is not operational", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // - }) - public Mono<ResponseEntity<Object>> deletePolicy( // - @PathVariable(Consts.POLICY_ID_PARAM) String policyId, @RequestHeader Map<String, String> headers) - throws EntityNotFoundException { + @Override + public Mono<ResponseEntity<Object>> deletePolicy(String policyId, ServerWebExchange exchange) throws Exception { + Policy policy = policies.getPolicy(policyId); keepServiceAlive(policy.getOwnerServiceId()); - return authorization.doAccessControl(headers, policy, AccessType.WRITE) - .flatMap(x -> policy.getRic().getLock().lock(LockType.SHARED, "deletePolicy")) // - .flatMap(grant -> deletePolicy(grant, policy)) // + return authorization.doAccessControl(exchange.getRequest().getHeaders().toSingleValueMap(), policy, AccessType.WRITE) + .flatMap(x -> policy.getRic().getLock().lock(Lock.LockType.SHARED, "deletePolicy")) + .flatMap(grant -> deletePolicy(grant, policy)) .onErrorResume(this::handleException); } Mono<ResponseEntity<Object>> deletePolicy(Lock.Grant grant, Policy policy) { - return assertRicStateIdle(policy.getRic()) // - .flatMap(notUsed -> a1ClientFactory.createA1Client(policy.getRic())) // - .doOnNext(notUsed -> policies.remove(policy)) // - .doFinally(x -> grant.unlockBlocking()) // - .flatMap(client -> client.deletePolicy(policy)) // - .map(notUsed -> new ResponseEntity<>(HttpStatus.NO_CONTENT)) // + return checkRicStateIdle(policy.getRic()) // + .flatMap(notUsed -> a1ClientFactory.createA1Client(policy.getRic())) + .doOnNext(notUsed -> policies.remove(policy)) + .doFinally(x -> grant.unlockBlocking()) + .flatMap(client -> client.deletePolicy(policy)) + .map(notUsed -> new ResponseEntity<>(HttpStatus.NO_CONTENT)) .onErrorResume(this::handleException); } - @PutMapping(path = Consts.V2_API_ROOT + "/policies", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Create or update a policy") - @ApiResponses(value = { // - @ApiResponse(responseCode = "201", // - description = "Policy created", // - content = @Content(schema = @Schema(implementation = VoidResponse.class))), // - @ApiResponse(responseCode = "200", // - description = "Policy updated", // - content = @Content(schema = @Schema(implementation = VoidResponse.class))), // - @ApiResponse(responseCode = "423", // - description = "Near-RT RIC is not operational", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))), // - @ApiResponse(responseCode = "404", // - description = "Near-RT RIC or policy type is not found", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // - }) - public Mono<ResponseEntity<Object>> putPolicy(@RequestBody PolicyInfo policyInfo, - @RequestHeader Map<String, String> headers) throws EntityNotFoundException { - - if (!policyInfo.validate()) { - return ErrorResponse.createMono("Missing required parameter in body", HttpStatus.BAD_REQUEST); - } - String jsonString = gson.toJson(policyInfo.policyData); - Ric ric = rics.get(policyInfo.ricId); - PolicyType type = policyTypes.get(policyInfo.policyTypeId); - keepServiceAlive(policyInfo.serviceId); - if (ric == null || type == null) { - throw new EntityNotFoundException("Near-RT RIC or policy type not found"); - } - Policy policy = Policy.builder() // - .id(policyInfo.policyId) // - .json(jsonString) // - .type(type) // - .ric(ric) // - .ownerServiceId(policyInfo.serviceId) // - .lastModified(Instant.now()) // - .isTransient(policyInfo.isTransient) // - .statusNotificationUri(policyInfo.statusNotificationUri == null ? "" : policyInfo.statusNotificationUri) // - .build(); - - return authorization.doAccessControl(headers, policy, AccessType.WRITE) // - .flatMap(x -> ric.getLock().lock(LockType.SHARED, "putPolicy")) // - .flatMap(grant -> putPolicy(grant, policy)) // - .onErrorResume(this::handleException); + @Override + public Mono<ResponseEntity<Object>> putPolicy(final Mono<PolicyInfo> policyInfo, final ServerWebExchange exchange) { + + return policyInfo.flatMap(policyInfoValue -> { + String jsonString = gson.toJson(policyInfoValue.getPolicyData()); + return Mono.zip( + Mono.justOrEmpty(rics.get(policyInfoValue.getRicId())) + .switchIfEmpty(Mono.error(new EntityNotFoundException("Near-RT RIC not found"))), + Mono.justOrEmpty(policyTypes.get(policyInfoValue.getPolicytypeId())) + .switchIfEmpty(Mono.error(new EntityNotFoundException("policy type not found"))) + ) + .flatMap(tuple -> { + Ric ric = tuple.getT1(); + PolicyType type = tuple.getT2(); + + Policy policy = Policy.builder() + .id(policyInfoValue.getPolicyId()) + .json(jsonString) + .type(type) + .ric(ric) + .ownerServiceId(policyInfoValue.getServiceId()) + .lastModified(Instant.now()) + .isTransient(policyInfoValue.getTransient()) + .statusNotificationUri(policyInfoValue.getStatusNotificationUri() == null ? "" : policyInfoValue.getStatusNotificationUri()) + .build(); + + return authorization.doAccessControl(exchange.getRequest().getHeaders().toSingleValueMap(), policy, AccessType.WRITE) + .flatMap(x -> ric.getLock().lock(Lock.LockType.SHARED, "putPolicy")) + .flatMap(grant -> putPolicy(grant, policy)); + }) + .onErrorResume(this::handleException); + }); } + + private Mono<ResponseEntity<Object>> putPolicy(Lock.Grant grant, Policy policy) { final boolean isCreate = this.policies.get(policy.getId()) == null; final Ric ric = policy.getRic(); - return assertRicStateIdle(ric) // + return checkRicStateIdle(ric) // .flatMap(notUsed -> checkSupportedType(ric, policy.getType())) // .flatMap(notUsed -> validateModifiedPolicy(policy)) // .flatMap(notUsed -> a1ClientFactory.createA1Client(ric)) // @@ -333,7 +252,7 @@ public class PolicyController { return Mono.just("{}"); } - private Mono<Object> assertRicStateIdle(Ric ric) { + private Mono<Object> checkRicStateIdle(Ric ric) { if (ric.getState() == Ric.RicState.AVAILABLE) { return Mono.just("{}"); } else { @@ -345,77 +264,27 @@ public class PolicyController { } } - static final String GET_POLICIES_QUERY_DETAILS = - "Returns a list of A1 policies matching given search criteria. <br>" // - + "If several query parameters are defined, the policies matching all conditions are returned."; - - @GetMapping(path = Consts.V2_API_ROOT + "/policy-instances", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Query for A1 policy instances", description = GET_POLICIES_QUERY_DETAILS) - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", // - description = "Policies", // - content = @Content(schema = @Schema(implementation = PolicyInfoList.class))), // - @ApiResponse(responseCode = "404", // - description = "Near-RT RIC, policy type or service not found", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // - }) - public Mono<ResponseEntity<Object>> getPolicyInstances( // - @Parameter(name = Consts.POLICY_TYPE_ID_PARAM, required = false, - description = "Select policies with a given type identity.") // - @RequestParam(name = Consts.POLICY_TYPE_ID_PARAM, required = false) String typeId, // - @Parameter(name = Consts.RIC_ID_PARAM, required = false, - description = "Select policies for a given Near-RT RIC identity.") // - @RequestParam(name = Consts.RIC_ID_PARAM, required = false) String ric, // - @Parameter(name = Consts.SERVICE_ID_PARAM, required = false, - description = "Select policies owned by a given service.") // - @RequestParam(name = Consts.SERVICE_ID_PARAM, required = false) String service, - @Parameter(name = Consts.TYPE_NAME_PARAM, required = false, // - description = "Select policies of a given type name (type identity has the format <typename_version>)") // - @RequestParam(name = Consts.TYPE_NAME_PARAM, required = false) String typeName, - @RequestHeader Map<String, String> headers) throws EntityNotFoundException // - { - if ((typeId != null && this.policyTypes.get(typeId) == null)) { + @Override + public Mono<ResponseEntity<Object>> getPolicyInstances(String policyTypeId, String ricId, String serviceId, String typeName, ServerWebExchange exchange) throws Exception { + if ((policyTypeId != null && this.policyTypes.get(policyTypeId) == null)) { throw new EntityNotFoundException("Policy type identity not found"); } - if ((ric != null && this.rics.get(ric) == null)) { + if ((ricId != null && this.rics.get(ricId) == null)) { throw new EntityNotFoundException("Near-RT RIC not found"); } - Collection<Policy> filtered = policies.filterPolicies(typeId, ric, service, typeName); + Collection<Policy> filtered = policies.filterPolicies(policyTypeId, ricId, serviceId, typeName); return Flux.fromIterable(filtered) // - .flatMap(policy -> authorization.doAccessControl(headers, policy, AccessType.READ)) // - .doOnError(e -> logger.debug("Unauthorized to read policy: {}", e.getMessage())) // - .onErrorResume(e -> Mono.empty()) // - .collectList() // - .map(authPolicies -> policiesToJson(authPolicies)) // - .map(str -> new ResponseEntity<>(str, HttpStatus.OK)); + .flatMap(policy -> authorization.doAccessControl(exchange.getRequest().getHeaders().toSingleValueMap(), policy, AccessType.READ)) + .doOnError(e -> logger.debug("Unauthorized to read policy: {}", e.getMessage())) + .onErrorResume(e -> Mono.empty()) + .collectList() + .map(authPolicies -> new ResponseEntity<>((Object) policiesToJson(authPolicies), HttpStatus.OK)) + .onErrorResume(this::handleException); } - @GetMapping(path = Consts.V2_API_ROOT + "/policies", produces = MediaType.APPLICATION_JSON_VALUE) // - @Operation(summary = "Query policy identities", description = GET_POLICIES_QUERY_DETAILS) // - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", // - description = "Policy identities", // - content = @Content(schema = @Schema(implementation = PolicyIdList.class))), // - @ApiResponse(responseCode = "404", // - description = "Near-RT RIC or type not found", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // - }) - public Mono<ResponseEntity<Object>> getPolicyIds( // - @Parameter(name = Consts.POLICY_TYPE_ID_PARAM, required = false, // - description = "Select policies of a given policy type identity.") // - @RequestParam(name = Consts.POLICY_TYPE_ID_PARAM, required = false) String policyTypeId, // - @Parameter(name = Consts.RIC_ID_PARAM, required = false, // - description = "Select policies of a given Near-RT RIC identity.") // - @RequestParam(name = Consts.RIC_ID_PARAM, required = false) String ricId, // - @Parameter(name = Consts.SERVICE_ID_PARAM, required = false, // - description = "Select policies owned by a given service.") // - @RequestParam(name = Consts.SERVICE_ID_PARAM, required = false) String serviceId, - @Parameter(name = Consts.TYPE_NAME_PARAM, required = false, // - description = "Select policies of types with the given type name (type identity has the format <typename_version>)") // - @RequestParam(name = Consts.TYPE_NAME_PARAM, required = false) String typeName, - @RequestHeader Map<String, String> headers) throws EntityNotFoundException // - { + @Override + public Mono<ResponseEntity<Object>> getPolicyIds(String policyTypeId, String ricId, String serviceId, String typeName, ServerWebExchange exchange) throws Exception { if ((policyTypeId != null && this.policyTypes.get(policyTypeId) == null)) { throw new EntityNotFoundException("Policy type not found"); } @@ -424,42 +293,37 @@ public class PolicyController { } Collection<Policy> filtered = policies.filterPolicies(policyTypeId, ricId, serviceId, typeName); - return Flux.fromIterable(filtered) // - .flatMap(policy -> authorization.doAccessControl(headers, policy, AccessType.READ)) // - .doOnError(e -> logger.debug("Unauthorized to read policy: {}", e.getMessage())) // - .onErrorResume(e -> Mono.empty()) // - .collectList() // - .map(authPolicies -> toPolicyIdsJson(authPolicies)) // - .map(policyIdsJson -> new ResponseEntity<>(policyIdsJson, HttpStatus.OK)); + return Flux.fromIterable(filtered) + .flatMap(policy -> authorization.doAccessControl(exchange.getRequest().getHeaders().toSingleValueMap(), policy, AccessType.READ)) + .doOnError(e -> logger.debug("Unauthorized to read policy: {}", e.getMessage())) + .onErrorResume(e -> Mono.empty()) + .collectList() + .map(authPolicies -> new ResponseEntity<>((Object)toPolicyIdsJson(authPolicies), HttpStatus.OK)) + .onErrorResume(this::handleException); } - @GetMapping(path = Consts.V2_API_ROOT + "/policies/{policy_id}/status", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Returns a policy status") // - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", // - description = "Policy status", // - content = @Content(schema = @Schema(implementation = PolicyStatusInfo.class))), // - @ApiResponse(responseCode = "404", // - description = "Policy is not found", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // - }) - public Mono<ResponseEntity<Object>> getPolicyStatus( // - @PathVariable(Consts.POLICY_ID_PARAM) String policyId, @RequestHeader Map<String, String> headers) - throws EntityNotFoundException { + @Override + public Mono<ResponseEntity<Object>> getPolicyStatus(String policyId, ServerWebExchange exchange) throws Exception { Policy policy = policies.getPolicy(policyId); - return authorization.doAccessControl(headers, policy, AccessType.READ) // + return authorization.doAccessControl(exchange.getRequest().getHeaders().toSingleValueMap(), policy, AccessType.READ) // .flatMap(notUsed -> a1ClientFactory.createA1Client(policy.getRic())) // .flatMap(client -> client.getPolicyStatus(policy).onErrorResume(e -> Mono.just("{}"))) // - .flatMap(status -> createPolicyStatus(policy, status)) // + .flatMap(status -> createPolicyStatus(policy, status)) .onErrorResume(this::handleException); - } private Mono<ResponseEntity<Object>> createPolicyStatus(Policy policy, String statusFromNearRic) { - PolicyStatusInfo info = new PolicyStatusInfo(policy.getLastModified(), fromJson(statusFromNearRic)); - String str = gson.toJson(info); - return Mono.just(new ResponseEntity<>(str, HttpStatus.OK)); + + try { + PolicyStatusInfo policyStatusInfo = new PolicyStatusInfo(); + policyStatusInfo.setLastModified(policy.getLastModified().toString()); + policyStatusInfo.setStatus(fromJson(statusFromNearRic)); + String policyStatusInfoAsString = objectMapper.writeValueAsString(policyStatusInfo); + return Mono.just(new ResponseEntity<>(policyStatusInfoAsString, HttpStatus.OK)); + } catch (JsonProcessingException ex) { + throw new RuntimeException(ex); + } } private void keepServiceAlive(String name) { @@ -469,52 +333,70 @@ public class PolicyController { } } - private PolicyInfo toPolicyInfo(Policy p) { - PolicyInfo policyInfo = new PolicyInfo(); - policyInfo.policyId = p.getId(); - policyInfo.policyData = fromJson(p.getJson()); - policyInfo.ricId = p.getRic().id(); - policyInfo.policyTypeId = p.getType().getId(); - policyInfo.serviceId = p.getOwnerServiceId(); - policyInfo.isTransient = p.isTransient(); - if (!p.getStatusNotificationUri().isEmpty()) { - policyInfo.statusNotificationUri = p.getStatusNotificationUri(); - } - if (!policyInfo.validate()) { - logger.error("BUG, all mandatory fields must be set"); + private PolicyInfo toPolicyInfo(Policy policy) { + PolicyInfo policyInfo = new PolicyInfo() + .policyId(policy.getId()) + .policyData(gson.fromJson(policy.getJson(), Map.class)) + .ricId(policy.getRic().id()) + .policytypeId(policy.getType().getId()) + .serviceId(policy.getOwnerServiceId()) + ._transient(policy.isTransient()); + if (!policy.getStatusNotificationUri().isEmpty()) { + policyInfo.setStatusNotificationUri(policy.getStatusNotificationUri()); } - return policyInfo; } - private String policiesToJson(Collection<Policy> policies) { - List<PolicyInfo> v = new ArrayList<>(policies.size()); - for (Policy p : policies) { - v.add(toPolicyInfo(p)); + private String toPolicyInfoString(Policy policy) { + + try { + return objectMapper.writeValueAsString(toPolicyInfo(policy)); + } catch (JsonProcessingException ex) { + throw new RuntimeException(ex); } - PolicyInfoList list = new PolicyInfoList(v); - return gson.toJson(list); + } + + private String policiesToJson(Collection<Policy> policies) { + + try { + List<PolicyInfo> policiesList = new ArrayList<>(policies.size()); + PolicyInfoList policyInfoList = new PolicyInfoList(); + for (Policy policy : policies) { + policiesList.add(toPolicyInfo(policy)); + } + policyInfoList.setPolicies(policiesList); + return objectMapper.writeValueAsString(policyInfoList); + } catch(JsonProcessingException ex) { + throw new RuntimeException(ex); + } } private Object fromJson(String jsonStr) { return gson.fromJson(jsonStr, Object.class); } - private String toPolicyTypeIdsJson(Collection<PolicyType> types) { - List<String> v = new ArrayList<>(types.size()); - for (PolicyType t : types) { - v.add(t.getId()); + private String toPolicyTypeIdsJson(Collection<PolicyType> policyTypes) throws JsonProcessingException { + + PolicyTypeIdList idList = new PolicyTypeIdList(); + for (PolicyType policyType : policyTypes) { + idList.addPolicytypeIdsItem(policyType.getId()); } - PolicyTypeIdList ids = new PolicyTypeIdList(v); - return gson.toJson(ids); + + return objectMapper.writeValueAsString(idList); } private String toPolicyIdsJson(Collection<Policy> policies) { - List<String> v = new ArrayList<>(policies.size()); - for (Policy p : policies) { - v.add(p.getId()); + + try { + List<String> policyIds = new ArrayList<>(policies.size()); + PolicyIdList idList = new PolicyIdList(); + for (Policy policy : policies) { + policyIds.add(policy.getId()); + } + idList.setPolicyIds(policyIds); + return objectMapper.writeValueAsString(idList); + } catch (JsonProcessingException ex) { + throw new RuntimeException(ex); } - return gson.toJson(new PolicyIdList(v)); } - } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyIdList.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyIdList.java deleted file mode 100644 index 35c1c947..00000000 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyIdList.java +++ /dev/null @@ -1,41 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ONAP : ccsdk oran - * ====================================================================== - * Copyright (C) 2020-2023 Nordix Foundation. All rights reserved. - * ====================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================LICENSE_END=================================== - */ - -package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.gson.annotations.SerializedName; - -import io.swagger.v3.oas.annotations.media.Schema; - -import java.util.Collection; - -@Schema(name = "policy_id_list_v2", description = "A list of policy identities") -public class PolicyIdList { - - @Schema(description = "Policy identities") - @SerializedName("policy_ids") - @JsonProperty("policy_ids") - public final Collection<String> policyIds; - - public PolicyIdList(Collection<String> ids) { - this.policyIds = ids; - } -} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyInfo.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyInfo.java deleted file mode 100644 index 537f98c2..00000000 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyInfo.java +++ /dev/null @@ -1,81 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ONAP : ccsdk oran - * ====================================================================== - * Copyright (C) 2019-2020 Nordix Foundation. All rights reserved. - * ====================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================LICENSE_END=================================== - */ - -package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.gson.annotations.SerializedName; - -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.media.Schema.RequiredMode; - -@Schema(name = "policy_info_v2", description = "Information for one A1-P Policy") -public class PolicyInfo { - - @Schema(name = "policy_id", description = "identity of the policy", requiredMode = RequiredMode.REQUIRED) - @JsonProperty(value = "policy_id", required = true) - @SerializedName("policy_id") - public String policyId; - - @Schema(name = "policytype_id", description = "identity of the policy type", requiredMode = RequiredMode.REQUIRED) - @JsonProperty(value = "policytype_id", required = true) - @SerializedName("policytype_id") - public String policyTypeId; - - @Schema(name = "ric_id", description = "identity of the target Near-RT RIC", requiredMode = RequiredMode.REQUIRED) - @JsonProperty(value = "ric_id", required = true) - @SerializedName("ric_id") - public String ricId; - - @Schema(name = "policy_data", description = "the configuration of the policy", requiredMode = RequiredMode.REQUIRED) - @JsonProperty(value = "policy_data", required = true) - @SerializedName("policy_data") - public Object policyData; - - private static final String SERVICE_ID_DESCRIPTION = "the identity of the service owning the policy." - + " This can be used to group the policies (it is possible to get all policies associated to a service)." - + " Note that the service does not need to be registered."; - - @Schema(name = "service_id", description = SERVICE_ID_DESCRIPTION, requiredMode = RequiredMode.NOT_REQUIRED, - defaultValue = "") - @JsonProperty(value = "service_id", required = false) - @SerializedName("service_id") - public String serviceId = ""; - - @Schema(name = "transient", - description = "if true, the policy is deleted at RIC restart. If false, its value is maintained by this service until explicitly deleted. Default false.", - requiredMode = RequiredMode.NOT_REQUIRED, defaultValue = "false", example = "false") - @JsonProperty(value = "transient", required = false, defaultValue = "false") - @SerializedName("transient") - public boolean isTransient = false; - - @Schema(name = "status_notification_uri", description = "Callback URI for policy status updates", - requiredMode = RequiredMode.NOT_REQUIRED, defaultValue = "") - @JsonProperty(value = "status_notification_uri", required = false) - @SerializedName("status_notification_uri") - public String statusNotificationUri = ""; - - PolicyInfo() {} - - public boolean validate() { - return policyId != null && policyTypeId != null && ricId != null && policyData != null && serviceId != null; - } - -} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyInfoList.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyInfoList.java deleted file mode 100644 index ae1aed95..00000000 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyInfoList.java +++ /dev/null @@ -1,42 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ONAP : ccsdk oran - * ====================================================================== - * Copyright (C) 2020-2023 Nordix Foundation. All rights reserved. - * ====================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================LICENSE_END=================================== - */ - -package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.gson.annotations.SerializedName; - -import io.swagger.v3.oas.annotations.media.Schema; - -import java.util.Collection; - -@Schema(name = "policy_info_list_v2", description = "List of policy information") -public class PolicyInfoList { - - @Schema(description = "List of policy information") - @SerializedName("policies") - @JsonProperty("policies") - public final Collection<PolicyInfo> policies; - - public PolicyInfoList(Collection<PolicyInfo> policies) { - this.policies = policies; - } - -} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyStatusInfo.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyStatusInfo.java deleted file mode 100644 index c19c4a0d..00000000 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyStatusInfo.java +++ /dev/null @@ -1,54 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ONAP : ccsdk oran - * ====================================================================== - * Copyright (C) 2019-2020 Nordix Foundation. All rights reserved. - * ====================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================LICENSE_END=================================== - */ - -package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.gson.annotations.SerializedName; - -import io.swagger.v3.oas.annotations.media.Schema; - -import java.time.Instant; - -@Schema(name = "policy_status_info_v2", description = "Status for one A1-P Policy") -public class PolicyStatusInfo { - - @Schema(description = "timestamp, last modification time") - @SerializedName("last_modified") - @JsonProperty("last_modified") - public String lastModified; - - @Schema(description = "the Policy status") - @SerializedName("status") - @JsonProperty("status") - public Object status; - - public PolicyStatusInfo() {} - - public PolicyStatusInfo(Instant lastModified, Object statusFromNearRTRic) { - this.lastModified = lastModified.toString(); - this.status = statusFromNearRTRic; - } - - public boolean validate() { - return lastModified != null; - } - -} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyTypeIdList.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyTypeIdList.java deleted file mode 100644 index 0da2e654..00000000 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyTypeIdList.java +++ /dev/null @@ -1,41 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ONAP : ccsdk oran - * ====================================================================== - * Copyright (C) 2020-2023 Nordix Foundation. All rights reserved. - * ====================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================LICENSE_END=================================== - */ - -package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.gson.annotations.SerializedName; - -import io.swagger.v3.oas.annotations.media.Schema; - -import java.util.Collection; - -@Schema(name = "policytype_id_list_v2", description = "Information about policy types") -public class PolicyTypeIdList { - - @Schema(description = "Policy type identities") - @SerializedName("policytype_ids") - @JsonProperty("policytype_ids") - public final Collection<String> policyTypesIds; - - public PolicyTypeIdList(Collection<String> ids) { - this.policyTypesIds = ids; - } -} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyTypeInfo.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyTypeInfo.java deleted file mode 100644 index 1f0e4476..00000000 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyTypeInfo.java +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ONAP : ccsdk oran - * ====================================================================== - * Copyright (C) 2020-2023 Nordix Foundation. All rights reserved. - * ====================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================LICENSE_END=================================== - */ - -package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.annotations.SerializedName; - -import io.swagger.v3.oas.annotations.media.Schema; - -@Schema(name = "policytype_v2", description = "Policy type") -public class PolicyTypeInfo { - - @Schema(description = "Policy type json schema. The schema is a json object following http://json-schema.org/draft-07/schema") - @SerializedName("policy_schema") - @JsonProperty("policy_schema") - public final Object schema; - - public PolicyTypeInfo(String schemaAsString) { - JsonObject jsonObj = JsonParser.parseString(schemaAsString).getAsJsonObject(); - this.schema = jsonObj; - } - -} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/RicInfo.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/RicInfo.java deleted file mode 100644 index 81fc56cb..00000000 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/RicInfo.java +++ /dev/null @@ -1,72 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ONAP : ccsdk oran - * ====================================================================== - * Copyright (C) 2020-2023 Nordix Foundation. All rights reserved. - * ====================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================LICENSE_END=================================== - */ - -package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.gson.annotations.SerializedName; - -import io.swagger.v3.oas.annotations.media.Schema; - -import java.util.Collection; - -@Schema(name = "ric_info_v2", description = "Information for a Near-RT RIC") -public class RicInfo { - - @Schema(name = "ric_state_v2", description = "Represents the states for a Near-RT RIC") - public enum RicState { - UNAVAILABLE, AVAILABLE, SYNCHRONIZING, CONSISTENCY_CHECK - } - - private static final String STATE_DESCRIPTION = - """ - State for the Near-RT RIC, values: - UNAVAILABLE: The Near-RT RIC is not available, information may be inconsistent - AVAILABLE: The normal state. Policies can be configured. - SYNCHRONIZING: The Policy Management Service is synchronizing the view of the Near-RT RIC. Policies cannot be configured. - CONSISTENCY_CHECK: A consistency check between the Policy Management Service and the Near-RT RIC. Policies cannot be configured."""; - - @Schema(description = "identity of the Near-RT RIC") - @SerializedName("ric_id") - @JsonProperty("ric_id") - public final String ricId; - - @Schema(description = "O1 identities for managed entities") - @SerializedName("managed_element_ids") - @JsonProperty("managed_element_ids") - public final Collection<String> managedElementIds; - - @Schema(description = "supported policy types") - @SerializedName("policytype_ids") - @JsonProperty("policytype_ids") - public final Collection<String> policyTypeIds; - - @Schema(description = STATE_DESCRIPTION, name = "state") - @SerializedName("state") - @JsonProperty("state") - public final RicState state; - - RicInfo(String ricId, Collection<String> managedElementIds, Collection<String> policyTypes, RicState state) { - this.ricId = ricId; - this.managedElementIds = managedElementIds; - this.policyTypeIds = policyTypes; - this.state = state; - } -} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/RicInfoList.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/RicInfoList.java deleted file mode 100644 index 715c15b4..00000000 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/RicInfoList.java +++ /dev/null @@ -1,42 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ONAP : ccsdk oran - * ====================================================================== - * Copyright (C) 2020-2023 Nordix Foundation. All rights reserved. - * ====================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================LICENSE_END=================================== - */ - -package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.gson.annotations.SerializedName; - -import io.swagger.v3.oas.annotations.media.Schema; - -import java.util.Collection; - -@Schema(name = "ric_info_list_v2", description = "List of Near-RT RIC information") -public class RicInfoList { - - @Schema(description = "List of Near-RT RIC information") - @SerializedName("rics") - @JsonProperty("rics") - public final Collection<RicInfo> rics; - - public RicInfoList(Collection<RicInfo> rics) { - this.rics = rics; - } - -} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/RicRepositoryController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/RicRepositoryController.java index 9e2644ad..63b0560c 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/RicRepositoryController.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/RicRepositoryController.java @@ -20,39 +20,34 @@ package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; +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.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; - -import java.util.ArrayList; -import java.util.List; - +import org.onap.ccsdk.oran.a1policymanagementservice.controllers.api.v2.NearRtRicRepositoryApi; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.EntityNotFoundException; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.InvalidRequestException; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.RicInfo; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.RicInfoList; import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyTypes; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Ric; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Rics; 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.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.util.ArrayList; +import java.util.List; @RestController("RicRepositoryControllerV2") @Tag( // name = RicRepositoryController.API_NAME, // description = RicRepositoryController.API_DESCRIPTION // ) -public class RicRepositoryController { +public class RicRepositoryController implements NearRtRicRepositoryApi { public static final String API_NAME = "NearRT-RIC Repository"; public static final String API_DESCRIPTION = ""; @@ -63,6 +58,9 @@ public class RicRepositoryController { @Autowired PolicyTypes types; + @Autowired + ObjectMapper objectMapper; + private static Gson gson = new GsonBuilder() // .create(); // @@ -70,38 +68,18 @@ public class RicRepositoryController { private static final String GET_RIC_DETAILS = "Either a Near-RT RIC identity or a Managed Element identity can be specified.<br>" // + "The intention with Managed Element identity is the ID used in O1 for accessing the traffical element (such as the ID of CU)."; - - /** - * Example: http://localhost:8081/v2/rics/ric?managed_element_id=kista_1 - * - * @throws EntityNotFoundException - */ - @GetMapping(path = Consts.V2_API_ROOT + "/rics/ric", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = GET_RIC_BRIEF, description = GET_RIC_DETAILS) - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", // - description = "Near-RT RIC is found", // - content = @Content(schema = @Schema(implementation = RicInfo.class))), // - @ApiResponse(responseCode = "404", // - description = "Near-RT RIC is not found", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // - }) - public ResponseEntity<Object> getRic( // - @Parameter(name = Consts.MANAGED_ELEMENT_ID_PARAM, required = false, - description = "The identity of a Managed Element. If given, the Near-RT RIC managing the ME is returned.") // - @RequestParam(name = Consts.MANAGED_ELEMENT_ID_PARAM, required = false) String managedElementId, - @Parameter(name = Consts.RIC_ID_PARAM, required = false, - description = "The identity of a Near-RT RIC to get information for.") // - @RequestParam(name = Consts.RIC_ID_PARAM, required = false) String ricId) - throws EntityNotFoundException, InvalidRequestException { + @Override + public Mono<ResponseEntity<Object>> getRic( + final String managedElementId, final String ricId, final ServerWebExchange exchange) + throws Exception { if (managedElementId != null && ricId != null) { throw new InvalidRequestException("Give one query parameter"); } else if (managedElementId != null) { Ric ric = this.rics.lookupRicForManagedElement(managedElementId); - return new ResponseEntity<>(gson.toJson(toRicInfo(ric)), HttpStatus.OK); + return Mono.just(new ResponseEntity<>(objectMapper.writeValueAsString(toRicInfo(ric)), HttpStatus.OK)); } else if (ricId != null) { RicInfo info = toRicInfo(this.rics.getRic(ricId)); - return new ResponseEntity<>(gson.toJson(info), HttpStatus.OK); + return Mono.just(new ResponseEntity<>(objectMapper.writeValueAsString(info), HttpStatus.OK)); } else { throw new InvalidRequestException("Give one query parameter"); } @@ -110,25 +88,9 @@ public class RicRepositoryController { static final String QUERY_RIC_INFO_DETAILS = "The call returns all Near-RT RICs that supports a given policy type identity"; - /** - * @return a Json array of all RIC data Example: http://localhost:8081/v2/ric - * @throws EntityNotFoundException - */ - @GetMapping(path = Consts.V2_API_ROOT + "/rics", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Query Near-RT RIC information", description = QUERY_RIC_INFO_DETAILS) - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", // - description = "OK", // - content = @Content(schema = @Schema(implementation = RicInfoList.class))), // - @ApiResponse(responseCode = "404", // - description = "Policy type is not found", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) // - }) - public ResponseEntity<Object> getRics( // - @Parameter(name = Consts.POLICY_TYPE_ID_PARAM, required = false, - description = "The identity of a policy type. If given, all Near-RT RICs supporting the policy type are returned") // - @RequestParam(name = Consts.POLICY_TYPE_ID_PARAM, required = false) String supportingPolicyType) - throws EntityNotFoundException { + @Override + public Mono<ResponseEntity<Object>> getRics(final String supportingPolicyType, final ServerWebExchange exchange) + throws Exception { if ((supportingPolicyType != null) && (this.types.get(supportingPolicyType) == null)) { throw new EntityNotFoundException("Policy type not found"); } @@ -140,26 +102,28 @@ public class RicRepositoryController { } } - return new ResponseEntity<>(gson.toJson(new RicInfoList(result)), HttpStatus.OK); + return Mono.just(new ResponseEntity<>(objectMapper.writeValueAsString(new RicInfoList().rics(result)), HttpStatus.OK)); } - private RicInfo.RicState toRicState(Ric.RicState state) { + private RicInfo.StateEnum toRicState(Ric.RicState state) { switch (state) { case AVAILABLE: - return RicInfo.RicState.AVAILABLE; + return RicInfo.StateEnum.AVAILABLE; case CONSISTENCY_CHECK: - return RicInfo.RicState.CONSISTENCY_CHECK; + return RicInfo.StateEnum.CONSISTENCY_CHECK; case SYNCHRONIZING: - return RicInfo.RicState.SYNCHRONIZING; + return RicInfo.StateEnum.SYNCHRONIZING; case UNAVAILABLE: - return RicInfo.RicState.UNAVAILABLE; + return RicInfo.StateEnum.UNAVAILABLE; default: - return RicInfo.RicState.UNAVAILABLE; + return RicInfo.StateEnum.UNAVAILABLE; } } private RicInfo toRicInfo(Ric ric) { - return new RicInfo(ric.id(), ric.getManagedElementIds(), ric.getSupportedPolicyTypeNames(), - toRicState(ric.getState())); + return new RicInfo().ricId(ric.id()) + .managedElementIds((List<String>) ric.getManagedElementIds()) + .policytypeIds((List<String>) ric.getSupportedPolicyTypeNames()) + .state(toRicState(ric.getState())); } } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceController.java index ed97820f..07b9440c 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceController.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceController.java @@ -2,7 +2,7 @@ * ========================LICENSE_START================================= * ONAP : ccsdk oran * ====================================================================== - * Copyright (C) 2019-2020 Nordix Foundation. All rights reserved. + * Copyright (C) 2019-2023 Nordix Foundation. All rights reserved. * ====================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,39 +20,33 @@ package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; +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.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.net.MalformedURLException; -import java.net.URL; -import java.time.Duration; -import java.util.ArrayList; -import java.util.Collection; - -import org.onap.ccsdk.oran.a1policymanagementservice.controllers.VoidResponse; +import org.onap.ccsdk.oran.a1policymanagementservice.controllers.api.v2.ServiceRegistryAndSupervisionApi; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.ServiceRegistrationInfo; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.ServiceStatus; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.ServiceStatusList; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policies; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policy; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Service; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Services; +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.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.net.MalformedURLException; +import java.net.URL; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; @RestController("ServiceControllerV2") @Tag( // @@ -60,7 +54,7 @@ import org.springframework.web.bind.annotation.RestController; description = ServiceController.API_DESCRIPTION // ) -public class ServiceController { +public class ServiceController implements ServiceRegistryAndSupervisionApi { public static final String API_NAME = "Service Registry and Supervision"; public static final String API_DESCRIPTION = ""; @@ -68,6 +62,9 @@ public class ServiceController { private final Services services; private final Policies policies; + @Autowired + private ObjectMapper objectMapper; + private static Gson gson = new GsonBuilder().create(); ServiceController(Services services, Policies policies) { @@ -78,49 +75,40 @@ public class ServiceController { private static final String GET_SERVICE_DETAILS = "Either information about a registered service with given identity or all registered services are returned."; - @GetMapping(path = Consts.V2_API_ROOT + "/services", produces = MediaType.APPLICATION_JSON_VALUE) // - @Operation(summary = "Returns service information", description = GET_SERVICE_DETAILS) // - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", // - description = "OK", // - content = @Content(schema = @Schema(implementation = ServiceStatusList.class))), // - @ApiResponse(responseCode = "404", // - description = "Service is not found", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class)))// - }) - public ResponseEntity<Object> getServices(// - @Parameter(name = Consts.SERVICE_ID_PARAM, required = false, description = "The identity of the service") // - @RequestParam(name = Consts.SERVICE_ID_PARAM, required = false) String name) { + @Override + public Mono<ResponseEntity<Object>> getServices(final String name, final ServerWebExchange exchange) throws Exception { if (name != null && this.services.get(name) == null) { - return ErrorResponse.create("Service not found", HttpStatus.NOT_FOUND); + return ErrorResponse.createMono("Service not found", HttpStatus.NOT_FOUND); } - Collection<ServiceStatus> servicesStatus = new ArrayList<>(); + List<ServiceStatus> servicesStatus = new ArrayList<>(); for (Service s : this.services.getAll()) { if (name == null || name.equals(s.getName())) { servicesStatus.add(toServiceStatus(s)); } } - - String res = gson.toJson(new ServiceStatusList(servicesStatus)); - return new ResponseEntity<>(res, HttpStatus.OK); + String res = objectMapper.writeValueAsString(new ServiceStatusList().serviceList(servicesStatus)); + return Mono.just(new ResponseEntity<>(res, HttpStatus.OK)); } private ServiceStatus toServiceStatus(Service s) { - return new ServiceStatus(s.getName(), s.getKeepAliveInterval().toSeconds(), s.timeSinceLastPing().toSeconds(), - s.getCallbackUrl()); + return new ServiceStatus() + .serviceId(s.getName()) + .keepAliveIntervalSeconds(s.getKeepAliveInterval().toSeconds()) + .timeSinceLastActivitySeconds(s.timeSinceLastPing().toSeconds()) + .callbackUrl(s.getCallbackUrl()); } private void validateRegistrationInfo(ServiceRegistrationInfo registrationInfo) throws ServiceException, MalformedURLException { - if (registrationInfo.serviceId.isEmpty()) { + if (registrationInfo.getServiceId().isEmpty()) { throw new ServiceException("Missing mandatory parameter 'service-id'"); } - if (registrationInfo.keepAliveIntervalSeconds < 0) { - throw new ServiceException("Keepalive interval shoul be greater or equal to 0"); + if (registrationInfo.getKeepAliveIntervalSeconds() < 0) { + throw new ServiceException("Keep alive interval should be greater or equal to 0"); } - if (!registrationInfo.callbackUrl.isEmpty()) { - new URL(registrationInfo.callbackUrl); + if (!registrationInfo.getCallbackUrl().isEmpty()) { + new URL(registrationInfo.getCallbackUrl()); } } @@ -131,67 +119,42 @@ public class ServiceController { + "</ul>" // + "Policies can be created even if the service is not registerred. This is a feature which it is optional to use."; - @PutMapping(Consts.V2_API_ROOT + "/services") - @Operation(summary = "Register a service", description = REGISTER_SERVICE_DETAILS) - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", description = "Service updated"), - @ApiResponse(responseCode = "201", description = "Service created"), // - @ApiResponse(responseCode = "400", // - description = "The ServiceRegistrationInfo is not accepted", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class)))}) - - public ResponseEntity<Object> putService(// - @RequestBody ServiceRegistrationInfo registrationInfo) { - try { - validateRegistrationInfo(registrationInfo); - final boolean isCreate = this.services.get(registrationInfo.serviceId) == null; - this.services.put(toService(registrationInfo)); - return new ResponseEntity<>(isCreate ? HttpStatus.CREATED : HttpStatus.OK); - } catch (Exception e) { - return ErrorResponse.create(e, HttpStatus.BAD_REQUEST); - } + @Override + public Mono<ResponseEntity<Object>> putService( + final Mono<ServiceRegistrationInfo> registrationInfo, final ServerWebExchange exchange) { + return registrationInfo.flatMap(info -> { + try { + validateRegistrationInfo(info); + } catch(Exception e) { + return ErrorResponse.createMono(e, HttpStatus.BAD_REQUEST); + } + final boolean isCreate = this.services.get(info.getServiceId()) == null; + this.services.put(toService(info)); + return Mono.just(new ResponseEntity<>(isCreate ? HttpStatus.CREATED : HttpStatus.OK)); + }).onErrorResume(Exception.class, e -> ErrorResponse.createMono(e, HttpStatus.BAD_REQUEST)); } - @DeleteMapping(Consts.V2_API_ROOT + "/services/{service_id:.+}") - @Operation(summary = "Unregister a service") - @ApiResponses(value = { // - @ApiResponse(responseCode = "204", description = "Service unregistered"), - @ApiResponse(responseCode = "200", description = "Not used", // - content = @Content(schema = @Schema(implementation = VoidResponse.class))), - @ApiResponse(responseCode = "404", description = "Service not found", // - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) - - }) - public ResponseEntity<Object> deleteService(// - @PathVariable("service_id") String serviceId) { + @Override + public Mono<ResponseEntity<Object>> deleteService(final String serviceId, final ServerWebExchange exchange) { try { Service service = removeService(serviceId); // Remove the policies from the repo and let the consistency monitoring // do the rest. removePolicies(service); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); + return Mono.just(new ResponseEntity<>(HttpStatus.NO_CONTENT)); } catch (ServiceException e) { - return ErrorResponse.create(e, HttpStatus.NOT_FOUND); + return ErrorResponse.createMono(e, HttpStatus.NOT_FOUND); } } - @Operation(summary = "Heartbeat indicates that the service is running", - description = "A registered service should invoke this operation regularly to indicate that it is still alive. If a registered service fails to invoke this operation before the end of a timeout period the service will be deregistered and all its A1 policies wil be removed. (This timeout can be set or disabled when each service is initially registered)") - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", description = "Service supervision timer refreshed, OK"), // - @ApiResponse(responseCode = "404", description = "The service is not found, needs re-registration", - content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) - - }) - + @Override @PutMapping(Consts.V2_API_ROOT + "/services/{service_id}/keepalive") - public ResponseEntity<Object> keepAliveService(// - @PathVariable(Consts.SERVICE_ID_PARAM) String serviceId) { + public Mono<ResponseEntity<Object>> keepAliveService(final String serviceId, final ServerWebExchange exchange) { try { services.getService(serviceId).keepAlive(); - return new ResponseEntity<>(HttpStatus.OK); + return Mono.just(new ResponseEntity<>(HttpStatus.OK)); } catch (ServiceException e) { - return ErrorResponse.create(e, HttpStatus.NOT_FOUND); + return ErrorResponse.createMono(e, HttpStatus.NOT_FOUND); } } @@ -209,7 +172,7 @@ public class ServiceController { } private Service toService(ServiceRegistrationInfo s) { - return new Service(s.serviceId, Duration.ofSeconds(s.keepAliveIntervalSeconds), s.callbackUrl); + return new Service(s.getServiceId(), Duration.ofSeconds(s.getKeepAliveIntervalSeconds()), s.getCallbackUrl()); } } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceRegistrationInfo.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceRegistrationInfo.java deleted file mode 100644 index 1bbac871..00000000 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceRegistrationInfo.java +++ /dev/null @@ -1,61 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ONAP : ccsdk oran - * ====================================================================== - * Copyright (C) 2019-2020 Nordix Foundation. All rights reserved. - * ====================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================LICENSE_END=================================== - */ - -package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.gson.annotations.SerializedName; - -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.media.Schema.RequiredMode; - - -@Schema(name = "service_registration_info_v2", description = "Information for one service") -public class ServiceRegistrationInfo { - - @Schema(description = "identity of the service", requiredMode = RequiredMode.REQUIRED) - @SerializedName("service_id") - @JsonProperty("service_id") - public String serviceId = ""; - - @Schema(description = "keep alive interval for the service. This is used to enable optional heartbeat supervision of the service. " - + "If set (> 0) the registered service should regularly invoke a 'keepalive' REST call. " - + "When a service fails to invoke this 'keepalive' call within the configured time, the service is considered unavailable. " - + "An unavailable service will be automatically deregistered and its policies will be deleted. " - + "Value 0 means timeout supervision is disabled.") - @SerializedName("keep_alive_interval_seconds") - @JsonProperty("keep_alive_interval_seconds") - public long keepAliveIntervalSeconds = 0; - - @Schema(description = "callback for notifying of Near-RT RIC state changes", - requiredMode = RequiredMode.NOT_REQUIRED, defaultValue = "") - @SerializedName("callback_url") - @JsonProperty("callback_url") - public String callbackUrl = ""; - - public ServiceRegistrationInfo() {} - - public ServiceRegistrationInfo(String id, long keepAliveIntervalSeconds, String callbackUrl) { - this.serviceId = id; - this.keepAliveIntervalSeconds = keepAliveIntervalSeconds; - this.callbackUrl = callbackUrl; - } - -} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceStatus.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceStatus.java deleted file mode 100644 index f25aff0e..00000000 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceStatus.java +++ /dev/null @@ -1,58 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ONAP : ccsdk oran - * ====================================================================== - * Copyright (C) 2019-2020 Nordix Foundation. All rights reserved. - * ====================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================LICENSE_END=================================== - */ - -package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.gson.annotations.SerializedName; - -import io.swagger.v3.oas.annotations.media.Schema; - -@Schema(name = "service_status_v2") -public class ServiceStatus { - - @Schema(description = "identity of the service") - @SerializedName("service_id") - @JsonProperty("service_id") - public final String serviceId; - - @Schema(description = "policy keep alive timeout") - @SerializedName("keep_alive_interval_seconds") - @JsonProperty("keep_alive_interval_seconds") - public final long keepAliveIntervalSeconds; - - @Schema(description = "time since last invocation by the service") - @SerializedName("time_since_last_activity_seconds") - @JsonProperty("time_since_last_activity_seconds") - public final long timeSinceLastActivitySeconds; - - @Schema(description = "callback for notifying of RIC synchronization") - @SerializedName("callback_url") - @JsonProperty("callback_url") - public String callbackUrl; - - ServiceStatus(String id, long keepAliveIntervalSeconds, long timeSincePingSeconds, String callbackUrl) { - this.serviceId = id; - this.keepAliveIntervalSeconds = keepAliveIntervalSeconds; - this.timeSinceLastActivitySeconds = timeSincePingSeconds; - this.callbackUrl = callbackUrl; - } - -} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceStatusList.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceStatusList.java deleted file mode 100644 index 55593894..00000000 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceStatusList.java +++ /dev/null @@ -1,42 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ONAP : ccsdk oran - * ====================================================================== - * Copyright (C) 2020-2023 Nordix Foundation. All rights reserved. - * ====================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================LICENSE_END=================================== - */ - -package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.gson.annotations.SerializedName; - -import io.swagger.v3.oas.annotations.media.Schema; - -import java.util.Collection; - -@Schema(name = "service_list_v2", description = "List of service information") -public class ServiceStatusList { - - @Schema(description = "List of service information") - @SerializedName("service_list") - @JsonProperty("service_list") - public final Collection<ServiceStatus> statusList; - - public ServiceStatusList(Collection<ServiceStatus> statuses) { - this.statusList = statuses; - } - -} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/StatusController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/StatusController.java index 57731793..22200da6 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/StatusController.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/StatusController.java @@ -2,7 +2,7 @@ * ========================LICENSE_START================================= * ONAP : ccsdk oran * ====================================================================== - * Copyright (C) 2019-2020 Nordix Foundation. All rights reserved. + * Copyright (C) 2019-2023 Nordix Foundation. All rights reserved. * ====================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,27 +20,20 @@ package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; -import io.swagger.v3.oas.annotations.Operation; -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 org.onap.ccsdk.oran.a1policymanagementservice.controllers.api.v2.HealthCheckApi; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; - +import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @RestController("StatusControllerV2") -@Tag( // - name = StatusController.API_NAME, // - description = StatusController.API_DESCRIPTION // +@Tag( name = StatusController.API_NAME, + description = StatusController.API_DESCRIPTION ) -public class StatusController { +public class StatusController implements HealthCheckApi{ public static final String API_NAME = "Health Check"; public static final String API_DESCRIPTION = ""; @@ -55,28 +48,15 @@ public class StatusController { } } - @GetMapping(path = Consts.V2_API_ROOT + "/status", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Returns status and statistics of this service") - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", // - description = "Service is living", // - content = @Content(schema = @Schema(implementation = StatusInfo.class))), // - }) - - public Mono<ResponseEntity<Object>> getStatus() { + @Override + public Mono<ResponseEntity<Object>> getStatus(final ServerWebExchange exchange) { StatusInfo info = new StatusInfo("success"); return Mono.just(new ResponseEntity<>(info, HttpStatus.OK)); } - @GetMapping("/status") - @Operation(summary = "Returns status and statistics of this service") - @ApiResponses(value = { // - @ApiResponse(responseCode = "200", description = "Service is living", - content = @Content(schema = @Schema(implementation = String.class))) // - }) - - public Mono<ResponseEntity<String>> getStatusV1() { + @Override + public Mono<ResponseEntity<String>> getStatusV1(final ServerWebExchange exchange) { return Mono.just(new ResponseEntity<>("success", HttpStatus.OK)); } -} +}
\ No newline at end of file diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/datastore/FileStore.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/datastore/FileStore.java index 565120e1..7152614d 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/datastore/FileStore.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/datastore/FileStore.java @@ -83,7 +83,7 @@ class FileStore implements DataStore { private String externalName(Path path) { String fullName = path.toString(); String externalName = fullName.substring(path().toString().length()); - if (externalName.startsWith("/")) { + if (externalName.startsWith(File.separator)) { externalName = externalName.substring(1); } return externalName; @@ -127,7 +127,7 @@ class FileStore implements DataStore { } private Path path() { - return Path.of(applicationConfig.getVardataDirectory(), "database", this.location); + return Path.of(applicationConfig.getVardataDirectory(), "database", this.location, File.separator); } @Override diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/GlobalExceptionHandler.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/GlobalExceptionHandler.java index 76ce6f97..be2f5b7b 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/GlobalExceptionHandler.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/exceptions/GlobalExceptionHandler.java @@ -30,7 +30,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +import org.springframework.web.reactive.result.method.annotation.ResponseEntityExceptionHandler; @ControllerAdvice(annotations = RestController.class) public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policies.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policies.java index 7eddeae1..ba3dd279 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policies.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policies.java @@ -197,7 +197,7 @@ public class Policies { byte[] bytes = gson.toJson(toStorageObject(policy)).getBytes(); this.dataStore.writeObject(this.getPath(policy), bytes) // - .doOnError(t -> logger.error("Could not store policy in S3, reason: {}", t.getMessage())) // + .doOnError(t -> logger.error("Could not store policy in S3, reason: {}", t.getMessage())) .subscribe(); } @@ -232,29 +232,29 @@ public class Policies { } private PersistentPolicyInfo toStorageObject(Policy p) { - return PersistentPolicyInfo.builder() // - .id(p.getId()) // - .json(p.getJson()) // - .ownerServiceId(p.getOwnerServiceId()) // - .ricId(p.getRic().id()) // - .statusNotificationUri(p.getStatusNotificationUri()) // - .typeId(p.getType().getId()) // - .isTransient(p.isTransient()) // - .lastModified(p.getLastModified().toString()) // + return PersistentPolicyInfo.builder() + .id(p.getId()) + .json(p.getJson()) + .ownerServiceId(p.getOwnerServiceId()) + .ricId(p.getRic().id()) + .statusNotificationUri(p.getStatusNotificationUri()) + .typeId(p.getType().getId()) + .isTransient(p.isTransient()) + .lastModified(p.getLastModified().toString()) .build(); } private Policy toPolicy(PersistentPolicyInfo p, Ric ric, PolicyTypes types) { try { - return Policy.builder() // - .id(p.getId()) // - .isTransient(p.isTransient()) // - .json(p.getJson()) // - .lastModified(Instant.parse(p.lastModified)) // - .ownerServiceId(p.getOwnerServiceId()) // - .ric(ric) // - .statusNotificationUri(p.getStatusNotificationUri()) // - .type(types.getType(p.getTypeId())) // + return Policy.builder() + .id(p.getId()) + .isTransient(p.isTransient()) + .json(p.getJson()) + .lastModified(Instant.parse(p.lastModified)) + .ownerServiceId(p.getOwnerServiceId()) + .ric(ric) + .statusNotificationUri(p.getStatusNotificationUri()) + .type(types.getType(p.getTypeId())) .build(); } catch (EntityNotFoundException e) { logger.warn("Not found: {}", e.getMessage()); diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java index a42bd65e..9afa42f6 100644 --- a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java +++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java @@ -2,7 +2,7 @@ * ========================LICENSE_START================================= * ONAP : ccsdk oran * ====================================================================== - * Copyright (C) 2019-2022 Nordix Foundation. All rights reserved. + * Copyright (C) 2019-2023 Nordix Foundation. All rights reserved. * ====================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,23 +27,23 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import java.io.FileOutputStream; -import java.io.PrintStream; import java.lang.invoke.MethodHandles; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.HashMap; -import org.json.JSONObject; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -64,6 +64,16 @@ import org.onap.ccsdk.oran.a1policymanagementservice.controllers.ServiceCallback import org.onap.ccsdk.oran.a1policymanagementservice.controllers.authorization.PolicyAuthorizationRequest; import org.onap.ccsdk.oran.a1policymanagementservice.controllers.authorization.PolicyAuthorizationRequest.Input.AccessType; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.RicInfo; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyTypeDefinition; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyTypeIdList; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyInfo; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyInfoList; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyIdList; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyStatusInfo; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.ServiceStatusList; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.ServiceStatus; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.ServiceRegistrationInfo; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Lock; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Lock.LockType; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policies; @@ -132,6 +142,9 @@ class ApplicationTest { MockA1ClientFactory a1ClientFactory; @Autowired + private ObjectMapper objectMapper; + + @Autowired RicSupervision supervision; @Autowired @@ -247,23 +260,6 @@ class ApplicationTest { } @Test - @DisplayName("test generate Api Doc") - void generateApiDoc() throws Exception { - String url = "https://localhost:" + this.port + "/v3/api-docs"; - ResponseEntity<String> resp = restClient("", false).getForEntity(url).block(); - assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK); - JSONObject jsonObj = new JSONObject(resp.getBody()); - assertThat(jsonObj.remove("servers")).isNotNull(); - - String indented = (jsonObj).toString(4); - String docDir = "api/"; - Files.createDirectories(Paths.get(docDir)); - try (PrintStream out = new PrintStream(new FileOutputStream(docDir + "pms-api.json"))) { - out.print(indented); - } - } - - @Test @DisplayName("test Persistency Policies") void testPersistencyPolicies() throws Exception { Ric ric = this.addRic("ric1"); @@ -405,7 +401,8 @@ class ApplicationTest { this.addPolicyType("type1", "ric1"); String url = "/rics?policytype_id=type1"; String rsp = restClient().get(url).block(); - assertThat(rsp).contains("ric1"); + String expectedResponse = "{\"rics\":[{\"managed_element_ids\":[],\"ric_id\":\"ric1\", \"state\":\"AVAILABLE\",\"policytype_ids\":[\"type1\"]}]}"; + assertEquals(objectMapper.readTree(expectedResponse), objectMapper.readTree(rsp)); // nameless type for ORAN A1 1.1 addRic("ric2"); @@ -473,13 +470,13 @@ class ApplicationTest { String url = "/rics/ric?managed_element_id=" + managedElementId; String rsp = restClient().get(url).block(); - RicInfo ricInfo = gson.fromJson(rsp, RicInfo.class); - assertThat(ricInfo.ricId).isEqualTo(ricId); + RicInfo ricInfo = objectMapper.readValue(rsp, RicInfo.class); + assertThat(ricInfo.getRicId()).isEqualTo(ricId); url = "/rics/ric?ric_id=" + ricId; rsp = restClient().get(url).block(); - ricInfo = gson.fromJson(rsp, RicInfo.class); - assertThat(ricInfo.ricId).isEqualTo(ricId); + ricInfo = objectMapper.readValue(rsp, RicInfo.class); + assertThat(ricInfo.getRicId()).isEqualTo(ricId); // test GET RIC for ManagedElement that does not exist url = "/rics/ric?managed_element_id=" + "junk"; @@ -490,22 +487,32 @@ class ApplicationTest { } private String putPolicyBody(String serviceName, String ricId, String policyTypeName, String policyInstanceId, - boolean isTransient, String statusNotificationUri) { - PolicyInfo info = new PolicyInfo(); - info.policyId = policyInstanceId; - info.policyTypeId = policyTypeName; - info.ricId = ricId; - info.serviceId = serviceName; - info.policyData = gson.fromJson(jsonString(), Object.class); - - if (isTransient) { - info.isTransient = isTransient; - } - info.statusNotificationUri = statusNotificationUri; - return gson.toJson(info); - } - - private String putPolicyBody(String serviceName, String ricId, String policyTypeName, String policyInstanceId) { + boolean isTransient, String statusNotificationUri) throws JsonProcessingException { + PolicyInfo policyInfo = new PolicyInfo(); + policyInfo.setPolicyId(policyInstanceId); + policyInfo.setPolicytypeId(policyTypeName); + policyInfo.setRicId(ricId); + policyInfo.setServiceId(serviceName); + policyInfo.setPolicyData(jsonString()); + policyInfo.setTransient(isTransient); + policyInfo.setStatusNotificationUri(statusNotificationUri); + return objectMapper.writeValueAsString(policyInfo); + } + + private String putPolicyBod(String serviceName, String ricId, String policyTypeName, String policyInstanceId, + boolean isTransient, String statusNotificationUri) throws JsonProcessingException { + PolicyInfo policyInfo = new PolicyInfo(); + policyInfo.setPolicyId(policyInstanceId); + policyInfo.setPolicytypeId(policyTypeName); + policyInfo.setRicId(ricId); + policyInfo.setServiceId(serviceName); + policyInfo.setPolicyData(jsonString()); + policyInfo.setTransient(isTransient); + policyInfo.setStatusNotificationUri(statusNotificationUri); + return objectMapper.writeValueAsString(policyInfo); + } + + private String putPolicyBody(String serviceName, String ricId, String policyTypeName, String policyInstanceId) throws JsonProcessingException { return putPolicyBody(serviceName, ricId, policyTypeName, policyInstanceId, false, "statusUri"); } @@ -555,6 +562,7 @@ class ApplicationTest { url = "/policies/" + policyInstanceId; rsp = restClient().get(url).block(); + assertThat(rsp).contains(policyBody); // Test of error codes @@ -582,7 +590,6 @@ class ApplicationTest { this.applicationConfig .setAuthProviderUrl(baseUrl() + OpenPolicyAgentSimulatorController.ACCESS_CONTROL_URL_REJECT); - String url = "/policy-instances"; String rsp = restClient().get(url).block(); assertThat(rsp).as("Response contains no policy instance ID.").contains("[]"); @@ -622,7 +629,6 @@ class ApplicationTest { rsp = restClient().get(url).block(); assertThat(rsp).as("Response contains no policy instance ID.").contains("[]"); } - @Test @DisplayName("test Put Policy No Service No Status Uri") void testPutPolicy_NoServiceNoStatusUri() throws Exception { @@ -653,7 +659,7 @@ class ApplicationTest { * @throws ServiceException */ @DisplayName("test Error From Ric") - void testErrorFromRic() throws ServiceException { + void testErrorFromRic() throws ServiceException, JsonProcessingException { putService("service1"); addPolicyType("type1", "ric1"); @@ -687,31 +693,33 @@ class ApplicationTest { restClient().put("/policies", body).block(); String rsp = restClient().get("/policy-instances").block(); - PolicyInfoList info = gson.fromJson(rsp, PolicyInfoList.class); - assertThat(info.policies).hasSize(1); - PolicyInfo policyInfo = info.policies.iterator().next(); - assertThat(policyInfo.policyId).isEqualTo("id1"); - assertThat(policyInfo.policyTypeId).isEmpty(); + PolicyInfoList info = objectMapper.readValue(rsp, PolicyInfoList.class); + assertThat(info.getPolicies()).hasSize(1); + PolicyInfo policyInfo = info.getPolicies().iterator().next(); + assertThat(policyInfo.getPolicyId()).isEqualTo("id1"); + assertThat(policyInfo.getPolicytypeId()).isEmpty(); } @Test @DisplayName("test Update Service") void testUpdateService() throws Exception { this.addRic("ric1"); - this.addPolicy("p", "type1", "", "ric1"); + this.addPolicy("policyId", "type1", "", "ric1"); String url = "/policies?service_id="; String resp = restClient().get(url).block(); - assertThat(resp).contains("[\"p\"]"); + String expectedResponse = "{\"policy_ids\":[\"policyId\"]}"; + assertEquals(expectedResponse, resp); - this.addPolicy("p", "type1", "service", "ric1"); + this.addPolicy("policyId", "type1", "service", "ric1"); url = "/policies?service_id="; resp = restClient().get(url).block(); - assertThat(resp).contains("[]"); + expectedResponse = "{\"policy_ids\":[]}"; + assertEquals(expectedResponse, resp); url = "/policies?service_id=service"; resp = restClient().get(url).block(); - assertThat(resp).contains("[\"p\"]"); + assertThat(resp).contains("[\"policyId\"]"); } @Test @@ -735,10 +743,10 @@ class ApplicationTest { String url = "/policies/id"; Policy policy = addPolicy("id", "typeName", "service1", "ric1"); { - String rsp = restClient().get(url).block(); - PolicyInfo info = gson.fromJson(rsp, PolicyInfo.class); - String policyStr = gson.toJson(info.policyData); - assertThat(policyStr).isEqualTo(policy.getJson()); + String response = restClient().get(url).block(); + PolicyInfo policyInfo = objectMapper.readValue(response, PolicyInfo.class); + String policyData = gson.toJson(policyInfo.getPolicyData()); + assertThat(policyData).isEqualTo(policy.getJson()); } { policies.remove(policy); @@ -763,6 +771,7 @@ class ApplicationTest { testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND); } + @Test @DisplayName("test Get Policy Type") void testGetPolicyType() throws Exception { @@ -773,21 +782,21 @@ class ApplicationTest { String url = "/policy-types/" + typeId; - String rsp = this.restClient().get(url).block(); + String response = this.restClient().get(url).block(); - PolicyTypeInfo info = gson.fromJson(rsp, PolicyTypeInfo.class); - assertThat(info.schema).isNotNull(); + assertEquals("{\"policy_schema\":{\"title\":\"AC.D\"}}", response); // Get non existing schema url = "/policy-types/JUNK"; testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND); } - String createPolicyTypesJson(String... types) { + String createPolicyTypesJson(String... types) throws JsonProcessingException { List<String> list = new ArrayList<>(); Collections.addAll(list, types); - PolicyTypeIdList ids = new PolicyTypeIdList(list); - return gson.toJson(ids); + PolicyTypeIdList ids = new PolicyTypeIdList(); + ids.setPolicytypeIds(list); + return objectMapper.writeValueAsString(ids); } @Test @@ -845,15 +854,14 @@ class ApplicationTest { addPolicy("id1", "type1", "service1"); String url = "/policy-instances"; - String rsp = restClient().get(url).block(); - logger.info(rsp); - PolicyInfoList info = gson.fromJson(rsp, PolicyInfoList.class); - assertThat(info.policies).hasSize(1); - PolicyInfo policyInfo = info.policies.iterator().next(); - assert (policyInfo.validate()); - assertThat(policyInfo.policyId).isEqualTo("id1"); - assertThat(policyInfo.policyTypeId).isEqualTo("type1"); - assertThat(policyInfo.serviceId).isEqualTo("service1"); + String response = restClient().get(url).block(); + logger.info(response); + PolicyInfoList policyInfoList = objectMapper.readValue(response, PolicyInfoList.class); + assertThat(policyInfoList.getPolicies()).hasSize(1); + PolicyInfo policyInfo = policyInfoList.getPolicies().iterator().next(); + assertThat(policyInfo.getPolicyId()).isEqualTo("id1"); + assertThat(policyInfo.getPolicytypeId()).isEqualTo("type1"); + assertThat(policyInfo.getServiceId()).isEqualTo("service1"); } @Test @@ -867,14 +875,14 @@ class ApplicationTest { String url = "/policy-instances?policytype_id=type1"; String rsp = restClient().get(url).block(); logger.info(rsp); - assertThat(rsp).contains("id1") // - .contains("id2") // + assertThat(rsp).contains("id1") + .contains("id2") .doesNotContain("id3"); url = "/policy-instances?policytype_id=type1&service_id=service2"; rsp = restClient().get(url).block(); logger.info(rsp); - assertThat(rsp).doesNotContain("id1") // + assertThat(rsp).doesNotContain("id1") .contains("id2") // .doesNotContain("id3"); @@ -882,7 +890,7 @@ class ApplicationTest { rsp = restClient().get(url).block(); assertThat(rsp).contains("id1") // .contains("id2") // - .doesNotContain("id3") // + .doesNotContain("id3") .contains("id4"); // Test get policies for non existing type @@ -905,21 +913,19 @@ class ApplicationTest { String url = "/policies?policytype_id=type1"; String rsp = restClient().get(url).block(); logger.info(rsp); - assertThat(rsp).contains("id1") // - .contains("id2") // + assertThat(rsp).contains("id1") + .contains("id2") .doesNotContain("id3"); url = "/policies?policytype_id=type1&service_id=service1&ric=ric1"; rsp = restClient().get(url).block(); - PolicyIdList respList = gson.fromJson(rsp, PolicyIdList.class); - assertThat(respList.policyIds.iterator().next()).isEqualTo("id1"); + PolicyIdList respList = objectMapper.readValue(rsp, PolicyIdList.class); + assertThat(respList.getPolicyIds().iterator().next()).isEqualTo("id1"); - url = "/policies?policytype_name=type1&service_id=service1"; + url = "/policies?type_name=type1&service_id=service1"; rsp = restClient().get(url).block(); - assertThat(rsp).contains("id1") // - .contains("id3") // - .contains("id4"); - assertThat(gson.fromJson(rsp, PolicyIdList.class).policyIds).hasSize(3); + assertThat(rsp).contains("id1").contains("id4"); + assertThat(objectMapper.readValue(rsp, PolicyIdList.class).getPolicyIds()).hasSize(2); // Test get policy ids for non existing type url = "/policies?policytype_id=type1XXX"; @@ -930,6 +936,7 @@ class ApplicationTest { testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND); } + @Test @DisplayName("test Put And Get Service") void testPutAndGetService() throws Exception { @@ -941,11 +948,11 @@ class ApplicationTest { // GET one service String url = "/services?service_id=" + serviceName; String rsp = restClient().get(url).block(); - ServiceStatusList info = gson.fromJson(rsp, ServiceStatusList.class); - assertThat(info.statusList).hasSize(1); - ServiceStatus status = info.statusList.iterator().next(); - assertThat(status.keepAliveIntervalSeconds).isZero(); - assertThat(status.serviceId).isEqualTo(serviceName); + ServiceStatusList info = objectMapper.readValue(rsp, ServiceStatusList.class); + assertThat(info.getServiceList()).hasSize(1); + ServiceStatus status = info.getServiceList().iterator().next(); + assertThat(status.getKeepAliveIntervalSeconds()).isZero(); + assertThat(status.getServiceId()).isEqualTo(serviceName); // GET (all) url = "/services"; @@ -982,7 +989,7 @@ class ApplicationTest { @Test @DisplayName("test Service Supervision") void testServiceSupervision() throws Exception { - putService("service1", 1, HttpStatus.CREATED); + putService("service1", 2, HttpStatus.CREATED); addPolicyType("type1", "ric1"); String policyBody = putPolicyBody("service1", "ric1", "type1", "instance1"); @@ -991,7 +998,7 @@ class ApplicationTest { assertThat(policies.size()).isEqualTo(1); assertThat(services.size()).isEqualTo(1); - // Timeout after ~1 second + // Timeout after ~2 second await().untilAsserted(() -> assertThat(policies.size()).isZero()); assertThat(services.size()).isZero(); } @@ -1003,9 +1010,9 @@ class ApplicationTest { assertThat(policies.size()).isEqualTo(1); String url = "/policies/id/status"; - String rsp = restClient().get(url).block(); - PolicyStatusInfo info = gson.fromJson(rsp, PolicyStatusInfo.class); - assertThat(info.status).isEqualTo("OK"); + String response = restClient().get(url).block(); + PolicyStatusInfo info = objectMapper.readValue(response, PolicyStatusInfo.class); + assertThat(info.getStatus()).isEqualTo("OK"); // GET non existing policy status url = "/policies/XXX/status"; @@ -1016,9 +1023,9 @@ class ApplicationTest { url = "/policies/id/status"; WebClientResponseException a1Exception = new WebClientResponseException(404, "", null, null, null); doReturn(Mono.error(a1Exception)).when(a1Client).getPolicyStatus(any()); - rsp = restClient().get(url).block(); - info = gson.fromJson(rsp, PolicyStatusInfo.class); - assertThat(info.status).hasToString("{}"); + response = restClient().get(url).block(); + info = objectMapper.readValue(response, PolicyStatusInfo.class); + assertThat(info.getStatus()).hasToString("{}"); } @Test @@ -1065,15 +1072,15 @@ class ApplicationTest { private Policy addPolicy(String id, String typeName, String service, String ric) throws ServiceException { addRic(ric); - Policy policy = Policy.builder() // - .id(id) // - .json(jsonString()) // - .ownerServiceId(service) // - .ric(rics.getRic(ric)) // - .type(addPolicyType(typeName, ric)) // - .lastModified(Instant.now()) // - .isTransient(false) // - .statusNotificationUri("/policy-status?id=XXX") // + Policy policy = Policy.builder() + .id(id) + .json(gson.toJson(jsonString())) + .ownerServiceId(service) + .ric(rics.getRic(ric)) + .type(addPolicyType(typeName, ric)) + .lastModified(Instant.now()) + .isTransient(false) + .statusNotificationUri("/policy-status?id=XXX") .build(); policies.put(policy); return policy; @@ -1083,23 +1090,24 @@ class ApplicationTest { return addPolicy(id, typeName, service, "ric"); } - private String createServiceJson(String name, long keepAliveIntervalSeconds) { + private String createServiceJson(String name, long keepAliveIntervalSeconds) throws JsonProcessingException { String callbackUrl = baseUrl() + RappSimulatorController.SERVICE_CALLBACK_URL; return createServiceJson(name, keepAliveIntervalSeconds, callbackUrl); } - private String createServiceJson(String name, long keepAliveIntervalSeconds, String url) { - ServiceRegistrationInfo service = new ServiceRegistrationInfo(name, keepAliveIntervalSeconds, url); + private String createServiceJson(String name, long keepAliveIntervalSeconds, String url) throws JsonProcessingException { + ServiceRegistrationInfo service = new ServiceRegistrationInfo(name) + .keepAliveIntervalSeconds(keepAliveIntervalSeconds) + .callbackUrl(url); - String json = gson.toJson(service); - return json; + return objectMapper.writeValueAsString(service); } - private void putService(String name) { + private void putService(String name) throws JsonProcessingException { putService(name, 0, null); } - private void putService(String name, long keepAliveIntervalSeconds, @Nullable HttpStatus expectedStatus) { + private void putService(String name, long keepAliveIntervalSeconds, @Nullable HttpStatus expectedStatus) throws JsonProcessingException { String url = "/services"; String body = createServiceJson(name, keepAliveIntervalSeconds); ResponseEntity<String> resp = restClient().putForEntity(url, body).block(); @@ -1108,8 +1116,10 @@ class ApplicationTest { } } - private String jsonString() { - return "{\"servingCellNrcgi\":\"1\"}"; + private Map<String,String> jsonString() { + Map<String,String> policyDataInMap = new HashMap<>(); + policyDataInMap.put("servingCellNrcgi","1"); + return policyDataInMap; } @Test @@ -1154,15 +1164,15 @@ class ApplicationTest { private AsyncRestClient restClient(String baseUrl, boolean useTrustValidation) { WebClientConfig config = this.applicationConfig.getWebClientConfig(); - config = WebClientConfig.builder() // - .keyStoreType(config.getKeyStoreType()) // - .keyStorePassword(config.getKeyStorePassword()) // - .keyStore(config.getKeyStore()) // - .keyPassword(config.getKeyPassword()) // - .isTrustStoreUsed(useTrustValidation) // - .trustStore(config.getTrustStore()) // - .trustStorePassword(config.getTrustStorePassword()) // - .httpProxyConfig(config.getHttpProxyConfig()) // + config = WebClientConfig.builder() + .keyStoreType(config.getKeyStoreType()) + .keyStorePassword(config.getKeyStorePassword()) + .keyStore(config.getKeyStore()) + .keyPassword(config.getKeyPassword()) + .isTrustStoreUsed(useTrustValidation) + .trustStore(config.getTrustStore()) + .trustStorePassword(config.getTrustStorePassword()) + .httpProxyConfig(config.getHttpProxyConfig()) .build(); AsyncRestClientFactory f = new AsyncRestClientFactory(config, new SecurityContext("")); @@ -1196,10 +1206,10 @@ class ApplicationTest { private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains, boolean expectApplicationProblemJsonMediaType) { - StepVerifier.create(request) // - .expectSubscription() // + StepVerifier.create(request) + .expectSubscription() .expectErrorMatches( - t -> checkWebClientError(t, expStatus, responseContains, expectApplicationProblemJsonMediaType)) // + t -> checkWebClientError(t, expStatus, responseContains, expectApplicationProblemJsonMediaType)) .verify(); } @@ -1227,9 +1237,9 @@ class ApplicationTest { } private PolicyType createPolicyType(String policyTypeName) { - return PolicyType.builder() // - .id(policyTypeName) // - .schema("{\"title\":\"" + policyTypeName + "\"}") // + return PolicyType.builder() + .id(policyTypeName) + .schema("{\"title\":\"" + policyTypeName + "\"}") .build(); } @@ -1249,10 +1259,10 @@ class ApplicationTest { if (managedElement != null) { mes.add(managedElement); } - return RicConfig.builder() // - .ricId(ricId) // - .baseUrl(ricId) // - .managedElementIds(mes) // + return RicConfig.builder() + .ricId(ricId) + .baseUrl(ricId) + .managedElementIds(mes) .build(); } diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConcurrencyTestRunnable.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConcurrencyTestRunnable.java index 0bf212a7..888325b2 100644 --- a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConcurrencyTestRunnable.java +++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ConcurrencyTestRunnable.java @@ -20,14 +20,19 @@ package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.lang.invoke.MethodHandles; import java.time.Instant; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import org.onap.ccsdk.oran.a1policymanagementservice.clients.AsyncRestClient; +import org.onap.ccsdk.oran.a1policymanagementservice.models.v2.PolicyInfo; import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policy; import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyType; import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyTypes; @@ -38,6 +43,7 @@ import org.onap.ccsdk.oran.a1policymanagementservice.utils.MockA1Client; import org.onap.ccsdk.oran.a1policymanagementservice.utils.MockA1ClientFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; /** @@ -55,6 +61,8 @@ class ConcurrencyTestRunnable implements Runnable { private final PolicyTypes types; private boolean failed = false; + private ObjectMapper objectMapper = new ObjectMapper(); + private static Gson gson = new GsonBuilder().create(); ConcurrencyTestRunnable(AsyncRestClient client, RicSupervision supervision, MockA1ClientFactory a1ClientFactory, @@ -140,25 +148,30 @@ class ConcurrencyTestRunnable implements Runnable { webClient.getForEntity(uri).block(); } - private void putPolicy(String name) { + private void putPolicy(String name) throws JsonProcessingException { String putUrl = "/policies"; String body = putPolicyBody("service1", "ric", "type1", name, false); webClient.putForEntity(putUrl, body).block(); } private String putPolicyBody(String serviceName, String ricId, String policyTypeName, String policyInstanceId, - boolean isTransient) { - PolicyInfo info = new PolicyInfo(); - info.policyId = policyInstanceId; - info.policyTypeId = policyTypeName; - info.ricId = ricId; - info.serviceId = serviceName; - info.policyData = gson.fromJson("{}", Object.class); - - if (isTransient) { - info.isTransient = isTransient; - } - return gson.toJson(info); + boolean isTransient) throws JsonProcessingException { + + PolicyInfo policyInfo = new PolicyInfo(); + policyInfo.setPolicyId(policyInstanceId); + policyInfo.setPolicytypeId(policyTypeName); + policyInfo.setRicId(ricId); + policyInfo.setServiceId(serviceName); + policyInfo.setPolicyData(policyData()); + policyInfo.setStatusNotificationUri("/status"); + policyInfo.setTransient(isTransient); + return objectMapper.writeValueAsString(policyInfo); + } + + private Map<String,String> policyData() { + Map<String,String> policyDataInMap = new HashMap<>(); + policyDataInMap.put("servingCellNrcgi","1"); + return policyDataInMap; } private void deletePolicy(String name) { diff --git a/csit/scripts/healthcheck/test/health_check.sh b/csit/scripts/healthcheck/test/health_check.sh index 05bfeae5..ad23632f 100755 --- a/csit/scripts/healthcheck/test/health_check.sh +++ b/csit/scripts/healthcheck/test/health_check.sh @@ -35,34 +35,42 @@ chmod +x docker-compose checkStatus(){ - for i in {1..60}; do - res=$($1) + for ((i=0; i<$1; i++)); do + res=$($2) echo "$res" - expect=$2 + expect=$3 if [ "$res" == "$expect" ]; then - echo -e "$3 is alive!\n" + echo -e "$i sec: $4 is alive!\n" + return 0 break; else - sleep $i + sleep 1 fi done + echo -e "$i sec: $4 is NOT alive!\n" + exit -1 } + # Healthcheck docker containers # check SIM1 status echo "check SIM1 status:" -checkStatus "curl -skw %{http_code} http://localhost:30001/" "OK200" "SIM1" +checkStatus 120 "curl -sSkw %{http_code} http://localhost:30001/ " "OK200" "SIM1" # check SIM2 status echo "check SIM2 status:" -checkStatus "curl -skw %{http_code} http://localhost:30003/" "OK200" "SIM2" +checkStatus 120 "curl -sSkw %{http_code} http://localhost:30003/ " "OK200" "SIM2" # check SIM3 status echo "check SIM3 status:" -checkStatus "curl -skw %{http_code} http://localhost:30005/" "OK200" "SIM3" +checkStatus 120 "curl -sSkw %{http_code} http://localhost:30005/ " "OK200" "SIM3" + +# check PMS status (HTTPS) +echo "check PMS status (HTTPS):" +checkStatus 120 "curl -sSkw %{http_code} https://localhost:8433/status " "success200" "PMS (HTTPS)" -# check PMS status -echo "check PMS status:" -checkStatus "curl -skw %{http_code} http://localhost:8081/status" "success200" "PMS" +# check PMS status (HTTPS) +echo "check PMS status (HTTPS):" +checkStatus 120 "curl -sSkw %{http_code} http://localhost:8081/status " "success200" "PMS (HTTP)" echo "NONRTRIC health check passed." diff --git a/csit/scripts/healthcheck/test/pms_a1sim.sh b/csit/scripts/healthcheck/test/pms_a1sim.sh index 8ba4ef44..d91821f4 100755 --- a/csit/scripts/healthcheck/test/pms_a1sim.sh +++ b/csit/scripts/healthcheck/test/pms_a1sim.sh @@ -30,35 +30,36 @@ chmod +x docker-compose ./docker-compose --env-file .env up -d checkStatus(){ - for i in {1..60}; do - res=$($1) + for ((i=0; i<$1; i++)); do + res=$($2) echo "$res" - expect=$2 + expect=$3 if [ "$res" == "$expect" ]; then - echo -e "$3 is alive!\n" + echo -e "$4 is alive!\n" break; else - sleep $i + sleep 1 fi done } + # Healthcheck docker containers # check SIM1 status echo "check SIM1 status:" -checkStatus "curl -skw %{http_code} http://localhost:30001/" "OK200" "SIM1" +checkStatus 120 "curl -sSkw %{http_code} http://localhost:30001/ " "OK200" "SIM1" # check SIM2 status echo "check SIM2 status:" -checkStatus "curl -skw %{http_code} http://localhost:30003/" "OK200" "SIM2" +checkStatus 120 "curl -sSkw %{http_code} http://localhost:30003/ " "OK200" "SIM2" # check SIM3 status echo "check SIM3 status:" -checkStatus "curl -skw %{http_code} http://localhost:30005/" "OK200" "SIM3" +checkStatus 120 "curl -sSkw %{http_code} http://localhost:30005/ " "OK200" "SIM3" # check PMS status echo "check PMS status:" -checkStatus "curl -skw %{http_code} http://localhost:8081/status" "success200" "PMS" +checkStatus 120 "curl -sSkw %{http_code} http://localhost:8081/status " "success200" "PMS" cd ${SHELL_FOLDER}/../data ./preparePmsData.sh diff --git a/csit/scripts/healthcheck/test/pms_a1sim_sdnc.sh b/csit/scripts/healthcheck/test/pms_a1sim_sdnc.sh index a71e3b1d..6513f789 100755 --- a/csit/scripts/healthcheck/test/pms_a1sim_sdnc.sh +++ b/csit/scripts/healthcheck/test/pms_a1sim_sdnc.sh @@ -37,38 +37,41 @@ checkStatus(){ echo "$res" expect=$3 if [ "$res" == "$expect" ]; then - echo -e "$4 is alive!\n" + echo -e "$i sec: $4 is alive!\n" + return 0 break; else sleep 1 fi done + echo -e "$i sec: $4 is NOT alive!\n" + exit -1 } + # Healthcheck docker containers # check SIM1 status echo "check SIM1 status:" -checkStatus 60 "curl -skw %{http_code} http://localhost:30001/" "OK200" "SIM1" +checkStatus 120 "curl -sSkw %{http_code} http://localhost:30001/ " "OK200" "SIM1" # check SIM2 status echo "check SIM2 status:" -checkStatus 60 "curl -skw %{http_code} http://localhost:30003/" "OK200" "SIM2" +checkStatus 120 "curl -sSkw %{http_code} http://localhost:30003/ " "OK200" "SIM2" # check SIM3 status echo "check SIM3 status:" -checkStatus 60 "curl -skw %{http_code} http://localhost:30005/" "OK200" "SIM3" +checkStatus 120 "curl -sSkw %{http_code} http://localhost:30005/ " "OK200" "SIM3" # check PMS status echo "check PMS status:" -checkStatus 60 "curl -skw %{http_code} http://localhost:8081/status" "success200" "PMS" +checkStatus 120 "curl -sSkw %{http_code} http://localhost:8081/status " "success200" "PMS" -curl -skw %{http_code} http://localhost:8081/actuator/loggers/org.onap.ccsdk.oran.a1policymanagementservice -X POST -H Content-Type:application/json -d '{"configuredLevel":"debug"}' -curl -skw %{http_code} http://localhost:8081/actuator/loggers/org.onap.ccsdk.oran.a1policymanagementservice.tasks -X POST -H Content-Type:application/json -d '{"configuredLevel":"trace"}' +curl -sSkw %{http_code} http://localhost:8081/actuator/loggers/org.onap.ccsdk.oran.a1policymanagementservice -X POST -H Content-Type:application/json -d '{"configuredLevel":"debug"}' +curl -sSkw %{http_code} http://localhost:8081/actuator/loggers/org.onap.ccsdk.oran.a1policymanagementservice.tasks -X POST -H Content-Type:application/json -d '{"configuredLevel":"trace"}' # check SDNC status echo "check SDNC status:" -checkStatus 300 "curl -s -o /dev/null -I -w %{http_code} http://localhost:8282/apidoc/explorer/" "200" "SDNC" +checkStatus 300 "curl -sS -o /dev/null -I -w %{http_code} http://localhost:8282/apidoc/explorer/ " "200" "SDNC" cd ${SHELL_FOLDER}/../data ./preparePmsData.sh - |