diff options
40 files changed, 4333 insertions, 291 deletions
diff --git a/Changelog.md b/Changelog.md index 124e913a..51211b43 100644 --- a/Changelog.md +++ b/Changelog.md @@ -21,5 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [DCAEGEN2-2254](https://jira.onap.org/browse/DCAEGEN2-2254) - Add new data-format for 30.2_ONAP schema version ## [1.7.2] - 04/08/2020 - [DCAEGEN2-1771](https://jira.onap.org/browse/DCAEGEN2-1771) - Add StndDefined event routing to dmaap streams defined in namespace event field - no second stage event validation. - - [DCAEGEN2-1771](https://jira.onap.org/browse/DCAEGEN2-1771) - Fix error response model - - [DCAEGEN2-1771](https://jira.onap.org/browse/DCAEGEN2-1771) - Update DPO model + Fix error response model + Update DPO model +## [1.7.3] - 10/08/2020 + - [DCAEGEN2-2264](https://jira.onap.org/browse/DCAEGEN2-2264) - Add implementation of stndDefined fields validation
\ No newline at end of file diff --git a/dpo/data-formats/ConsulConfig.json b/dpo/data-formats/ConsulConfig.json index 1249afe4..dc04abcf 100644 --- a/dpo/data-formats/ConsulConfig.json +++ b/dpo/data-formats/ConsulConfig.json @@ -68,6 +68,11 @@ } } }, + "collector.externalSchema.2ndStageValidation": 1, + "collector.externalSchema.schemasLocation": "./etc/externalRepo", + "collector.externalSchema.mappingFileLocation": "./etc/externalRepo/schema-map.json", + "collector.externalSchema.schemaRefPath": "/event/stndDefinedFields/schemaReference", + "collector.externalSchema.stndDefinedDataPath": "/event/stndDefinedFields/data", "collector.service.secure.port": "8443", "auth.method": "noAuth", "collector.keystore.file.location": "/opt/app/VESCollector/etc/keystore", diff --git a/etc/collector.properties b/etc/collector.properties index 0d408cc4..b0bffaac 100755 --- a/etc/collector.properties +++ b/etc/collector.properties @@ -50,6 +50,17 @@ collector.truststore.passwordfile=etc/trustpasswordfile collector.schema.checkflag=1
collector.schema.file={\"v1\":\"./etc/CommonEventFormat_27.2.json\",\"v2\":\"./etc/CommonEventFormat_27.2.json\",\"v3\":\"./etc/CommonEventFormat_27.2.json\",\"v4\":\"./etc/CommonEventFormat_27.2.json\",\"v5\":\"./etc/CommonEventFormat_28.4.1.json\",\"v7\":\"./etc/CommonEventFormat_30.2_ONAP.json\"}
+## Schema StndDefinedFields Validation checkflag
+## default no validation checkflag (-1)
+## If enabled (1) - schema files locations must be specified, mapping file path must be specified, schema reference path
+## in event json must be specified, path to stndDefined data field in event json must be specified
+collector.externalSchema.checkflag=1
+collector.externalSchema.schemasLocation=./etc/externalRepo/
+collector.externalSchema.mappingFileLocation=./etc/externalRepo/schema-map.json
+event.externalSchema.schemaRefPath=/event/stndDefinedFields/schemaReference
+event.externalSchema.stndDefinedDataPath=/event/stndDefinedFields/data
+
+
## List all streamid per domain to be supported. The streamid should match to channel name on dmaapfile
collector.dmaap.streamid=fault=ves-fault|syslog=ves-syslog|heartbeat=ves-heartbeat|measurementsForVfScaling=ves-measurement|mobileFlow=ves-mobileflow|other=ves-other|stateChange=ves-statechange|thresholdCrossingAlert=ves-thresholdCrossingAlert|voiceQuality=ves-voicequality|sipSignaling=ves-sipsignaling|notification=ves-notification|pnfRegistration=ves-pnfRegistration|3GPP-FaultSupervision=ves-3gpp-fault-supervision|3GPP-Heartbeat=ves-3gpp-heartbeat|3GPP-Provisioning=ves-3gpp-provisioning|3GPP-PerformanceAssurance=ves-3gpp-performance-assurance
collector.dmaapfile=./etc/DmaapConfig.json
diff --git a/etc/externalRepo/3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/PerDataFileReportMnS.yaml b/etc/externalRepo/3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/PerDataFileReportMnS.yaml new file mode 100644 index 00000000..dfacc14f --- /dev/null +++ b/etc/externalRepo/3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/PerDataFileReportMnS.yaml @@ -0,0 +1,272 @@ +openapi: 3.0.1 +info: + title: TS 28.532 Performance data file reporting Service + version: 16.4.0 + description: >- + OAS 3.0.1 specification of the Performance data file reporting Management Service © 2020, + 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). All + rights reserved. +externalDocs: + description: 3GPP TS 28.532 V16.4.0; Generic management services + url: 'http://www.3gpp.org/ftp/Specs/archive/28_series/28.532/' +servers: + - url: '{MnSRoot}/PerfDataFileReportMnS/v1640' + variables: + MnSRoot: + description: See subclause 4.4 of TS 32.158 + default: http://example.com/3GPPManagement +paths: + /Files: + get: + summary: Read resources of information of available files + description: 'With HTTP GET, resources of information of available files are read. The resources to be read are identified with the path component (base resource) and the query component (managementDataType, beginTime and endTime) of the URI. The fields query component allows to select the resource properties to be returned.' + parameters: + - name: managementDataType + in: query + description: This parameter identifies the type of management data that the file contains to select the resources from the collection resources identified with the path component of the URI. + required: true + $ref: '#/components/schemas/managementDataType-Type' + - name: beginTime + in: query + description: This parameter identifies the time stamp no later than which the file became available to select the resources from the collection resources identified with the path component of the URI. + required: true + $ref: '#/components/schemas/dateTime-Type' + - name: endTime + in: query + description: This parameter identifies the time stamp no earlier than which the file became available to select the resources from the collection resources identified with the path component of the URI. + required: true + $ref: '#/components/schemas/dateTime-Type' + responses: + '200': + description: 'Success case ("200 OK"). The resources identified in the request for retrieval are returned in the response message body. In case the fields query parameter is used, the selected resources are returned.' + content: + application/json: + schema: + $ref: '#/components/schemas/fileInfoRetrieval-ResponseType' + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/error-ResponseType' + /subscriptions: + post: + summary: Create a subscription + description: To create a subscription the representation of the subscription is POSTed on the /subscriptions collection resource. + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/subscription-RequestType' + responses: + '201': + description: Success case ("201 Created"). The representation of the newly created subscription resource shall be returned. + content: + application/json: + schema: + $ref: '#/components/schemas/subscription-ResponseType' + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/error-ResponseType' + callbacks: + notifyFileReady: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/notifyFileReady-NotifType' + responses: + '204': + description: Success case ("204 No Content"). The notification is successfully delivered. The response message body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/error-ResponseType' + notifyFilePreparationError: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/notifyFilePreparationError-NotifType' + responses: + '204': + description: Success case ("204 No Content"). The notification is successfully delivered. The response message body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/error-ResponseType' + delete: + summary: Delete all subscriptions made with a specific consumerReferenceId + description: The subscriptions are deleted by deleting the corresponding subscription resources. The resources to be deleted are identified with the path component of the URI pointing to the /subscription collection resource and filtering on the consumerReferenceId provided in the query part. + parameters: + - name: consumerReferenceId + in: query + description: Identifies the subscriptions to be deleted. + required: true + schema: + $ref: '#/components/schemas/consumerReferenceId-QueryType' + responses: + '204': + description: Success case ("204 No Content"). The subscription resources have been deleted. The response message body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/error-ResponseType' + '/subscriptions/{subscriptionId}': + delete: + summary: Delete a single subscription + description: The subscription is deleted by deleting the corresponding subscription resource. The resource to be deleted is identified with the path component of the URI. + parameters: + - name: subscriptionId + in: path + description: Identifies the subscription to be deleted. + required: true + schema: + $ref: '#/components/schemas/subscriptionId-PathType' + responses: + '204': + description: Success case ("204 No Content"). The subscription resource has been deleted. The response message body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/error-ResponseType' +components: + schemas: + dateTime-Type: + type: string + format: date-Time + uri-Type: + type: string + long-Type: + type: string + format: long + additionalText-Type: + type: string + reason-Type: + type: string + fileInfoRetrieval-ResponseType: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/fileInfo-Type' + fileInfo-Type: + type: object + properties: + fileLocation: + $ref: '#/components/schemas/uri-Type' + fileSize: + $ref: '#/components/schemas/long-Type' + fileReadyTime: + $ref: '#/components/schemas/dateTime-Type' + fileExpirationTime: + $ref: '#/components/schemas/dateTime-Type' + fileCompression: + type: string + fileFormat: + type: string + error-ResponseType: + type: object + properties: + error: + type: object + properties: + errorInfo: + type: string + managementDataType-Type: + type: string + enum: + - PM + header-Type: + description: Header used in notifications as notification header + type: object + properties: + uri: + $ref: '#/components/schemas/uri-Type' + notificationId: + $ref: '#/components/schemas/notificationId-Type' + notificationType: + $ref: '#/components/schemas/notificationType-Type' + eventTime: + $ref: '#/components/schemas/dateTime-Type' + subscriptionId-PathType: + type: string + filter-Type: + type: string + notificationId-Type: + $ref: '#/components/schemas/long-Type' + notificationType-Type: + type: string + enum: + - notifyFileReady + - notifyFilePreparationError + subscription-ResourceType: + type: object + properties: + consumerReference: + $ref: '#/components/schemas/uri-Type' + timeTick: + $ref: '#/components/schemas/long-Type' + filter: + $ref: '#/components/schemas/filter-Type' + subscription-RequestType: + type: object + properties: + data: + $ref: '#/components/schemas/subscription-ResourceType' + subscription-ResponseType: + type: object + properties: + data: + $ref: '#/components/schemas/subscription-ResourceType' + consumerReferenceId-QueryType: + $ref: '#/components/schemas/uri-Type' + notifyFileReady-NotifType: + type: object + properties: + header: + $ref: '#/components/schemas/header-Type' + body: + type: object + properties: + fileInfoList: + type: array + items: + $ref: '#/components/schemas/fileInfo-Type' + additionalText: + $ref: '#/components/schemas/additionalText-Type' + notifyFilePreparationError-NotifType: + type: object + properties: + header: + $ref: '#/components/schemas/header-Type' + body: + type: object + properties: + fileInfoList: + type: array + items: + $ref: '#/components/schemas/fileInfo-Type' + reason: + $ref: '#/components/schemas/reason-Type' + additionalText: + $ref: '#/components/schemas/additionalText-Type' diff --git a/etc/externalRepo/3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml b/etc/externalRepo/3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml new file mode 100644 index 00000000..499123b9 --- /dev/null +++ b/etc/externalRepo/3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml @@ -0,0 +1,1144 @@ +openapi: 3.0.1 +info: + title: Fault Supervision MnS + version: 16.4.0 + description: >- + OAS 3.0.1 definition of the Fault Supervision MnS + © 2020, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). + All rights reserved. +externalDocs: + description: 3GPP TS 28.532 V16.4.0; Generic management services + url: http://www.3gpp.org/ftp/Specs/archive/28_series/28.532/ +servers: + - url: '{MnSRoot}/FaultSupervisionMnS/{version}' + variables: + MnSRoot: + description: See subclause 4.4.3 of TS 32.158 + default: http://example.com/3GPPManagement + version: + description: Versi on number of the OpenAPI definition + default: XXX +paths: + /alarms: + get: + summary: Retrieve multiple alarms + description: >- + Retrieves the alarms identified by alarmAckState, baseObjectInstance + and filter. + parameters: + - name: alarmAckState + in: query + required: false + schema: + $ref: '#/components/schemas/AlarmAckState' + - name: baseObjectInstance + in: query + required: false + schema: + $ref: '#/components/schemas/Dn' + - name: filter + in: query + required: false + schema: + $ref: '#/components/schemas/Filter' + responses: + '200': + description: >- + Success case ("200 OK"). + Returns the alarms identified in the request. The alarmId is the key + of the map. + content: + application/json: + schema: + type: object + additionalProperties: + type: object + allOf: + - type: object + properties: + lastNotificationHeader: + $ref: '#/components/schemas/NotificationHeader' + - $ref: '#/components/schemas/AlarmRecord' + - type: object + properties: + comments: + $ref: '#/components/schemas/Comments' + default: + description: Response in case of error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + patch: + summary: 'Clear, acknowledge or unacknowledge multiple alarms' + description: >- + Clears, acknowledges or unacknowledges multiple alarms using patch. Depending + on which action is to be performed, different merge patch documents need + to be used. + requestBody: + description: >- + Patch documents for acknowledging and unacknowledging, or clearing multiple + alarms. The keys in the map are the alarmIds to be patched. + content: + application/merge-patch+json: + schema: + oneOf: + - type: object + additionalProperties: + $ref: '#/components/schemas/MergePatchAcknowledgeAlarm' + - type: object + additionalProperties: + $ref: '#/components/schemas/MergePatchClearAlarm' + responses: + '204': + description: >- + Success case ("204 No content"). + The response message body is empty. + default: + description: Response in case of error. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/FailedAlarm' + /alarms/alarmCount: + get: + summary: Get the alarm count per perceived severity + parameters: + - name: alarmAckState + in: query + required: false + schema: + $ref: '#/components/schemas/AlarmAckState' + - name: filter + in: query + required: false + schema: + type: string + responses: + '200': + description: >- + Success case ("200 OK"). + The alarm count per perceived severity is returned. + content: + application/json: + schema: + $ref: '#/components/schemas/AlarmCount' + default: + description: Response in case of error. The error case needs rework. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /alarms/{alarmId}: + patch: + summary: 'Clear, acknowledge or unacknowledge a single alarm' + description: >- + Clears, acknowledges or uncknowldeges a single alarm by patching the alarm + information. A conditional acknowledge request based on the perceived + severity is not supported. + parameters: + - name: alarmId + in: path + description: Identifies the alarm to be patched. + required: true + schema: + type: string + requestBody: + required: true + content: + application/merge-patch+json: + schema: + oneOf: + - $ref: '#/components/schemas/MergePatchAcknowledgeAlarm' + - $ref: '#/components/schemas/MergePatchClearAlarm' + responses: + '204': + description: >- + Success case (204 No content). + The response message body is absent. + default: + description: Response in case of error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /alarms/{alarmId}/comments: + post: + summary: Add a comment to a single alarm + description: >- + Adds a comment to an alarm identified by alarmId. The id of the new comment + is allocated by the producer. + parameters: + - name: alarmId + in: path + description: Identifies the alarm to which the comment shall be added. + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Comment' + responses: + '201': + description: >- + Success case (201 Created). + The representation of the newly created comment resource shall be returned. + content: + application/json: + schema: + $ref: '#/components/schemas/Comment' + headers: + Location: + description: URI of the newly created comment resource. + required: true + schema: + type: string + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /subscriptions: + post: + summary: Create a subscription + description: >- + To create a subscription the representation of the subscription is + POSTed on the /subscriptions collection resource. + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Subscription' + responses: + '201': + description: >- + Success case ("201 Created"). + The representation of the newly created subscription resource shall + be returned. + content: + application/json: + schema: + $ref: '#/components/schemas/Subscription' + headers: + Location: + description: URI of the newly created subscription resource + required: true + schema: + type: string + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + callbacks: + notifyNewAlarm: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/NotifyNewAlarm' + - $ref: '#/components/schemas/NotifyNewSecAlarm' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyClearedAlarm: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotifyClearedAlarm' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyChangedAlarm: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotifyChangedAlarm' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyChangedAlarmGeneral: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/NotifyChangedAlarmGeneral' + - $ref: '#/components/schemas/NotifyChangedSecAlarmGeneral' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyCorrelatedNotificationChanged: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotifyCorrelatedNotificationChanged' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyAckStateChanged: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotifyAckStateChanged' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyComments: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotifyComments' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyPotentialFaultyAlarmList: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotifyPotentialFaultyAlarmList' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyAlarmListRebuilt: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotifyAlarmListRebuilt' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /subscriptions/{subscriptionId}: + delete: + summary: Delete a subscription + description: >- + The subscription is deleted by deleting the corresponding subscription + resource. The resource to be deleted is identified with the path + component of the URI. + parameters: + - name: subscriptionId + in: path + description: Identifies the subscription to be deleted. + required: true + schema: + type: string + responses: + '204': + description: >- + Success case ("204 No Content"). + The subscription resource has been deleted. The response message body + is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + + #---- Definitions to be moved to comDefs.yaml --------------------------------------# + + Long: + type: string + format: long + Float: + type: string + format: float + DateTime: + type: string + format: date-Time + + Dn: + type: string + Uri: + type: string + + AttributeNameValuePairSet: + type: object + minProperties: 1 + AttributeValueChangeSet: + description: >- + The key in this map is the attribute name. The value of each key is an array. + When only one item is present in the array, it carries the new attribute + value. If two items are present, then the first item carries the old value + and the second item the new value. The items can be of any type including null. + type: object + additionalProperties: + type: array + minItems: 1 + maxItems: 2 + items: + nullable: true + + Filter: + type: string + SystemDN: + type: string + + NotificationId: + type: integer + NotificationHeader: + description: >- + Header used for all notification types + type: object + required: + - href + - notificationId + - notificationType + - eventTime + - systemDN + properties: + uri: + $ref: '#/components/schemas/Uri' + notificationId: + $ref: '#/components/schemas/NotificationId' + notificationType: + oneOf: + - $ref: '#/components/schemas/AlarmNotificationTypes' + #- $ref: 'faultMnS.yaml#/components/schemas/AlarmNotificationTypes' + #- $ref: 'provMnS.yaml#/components/schemas/CmNotificationTypes' + # more to be added + eventTime: + $ref: '#/components/schemas/DateTime' + systemDN: + $ref: '#/components/schemas/SystemDN' + + ErrorResponse: + description: >- + Default schema for the response message body in case the request is not + successful. + type: object + properties: + error: + type: object + properties: + errorInfo: + type: string + + #---- End of definitions to be moved to comDefs.yaml -------------------------------# + + #---- Definition of AlarmRecord ----------------------------------------------------# + + AlarmId: + type: string + AlarmType: + type: string + enum: + - COMMUNICATIONS_ALARM + - QUALITY_OF_SERVICE_ALARM + - PROCESSING_ERROR_ALARM + - EQUIPMENT_ALARM + - ENVIRONMENTAL_ALARM + - INTEGRITY_VIOLATION + - OPERATIONAL_VIOLATION + - PHYSICAL_VIOLATION + - SECURITY_SERVICE_OR_MECHANISM_VIOLATION + - TIME_DOMAIN_VIOLATION + ProbableCause: + description: >- + The value of the probable cause may be a specific standardized string, or any + vendor provided string. Probable cause strings are not standardized in the + present document. They may be added in a future version. Up to then the + mapping of the generic probable cause strings "PROBABLE_CAUSE_001" to + "PROBABLE_CAUSE_005" is vendor specific. + The value of the probable cause may also be an integer. The mapping of integer + values to probable causes is vendor specific. + oneOf: + - anyOf: + - type: string + enum: + - PROBABLE_CAUSE_001 + - PROBABLE_CAUSE_002 + - PROBABLE_CAUSE_003 + - PROBABLE_CAUSE_004 + - PROBABLE_CAUSE_005 + - type: string + - type: integer + SpecificProblem: + oneOf: + - type: string + - type: integer + PerceivedSeverity: + type: string + enum: + - INDETERMINATE + - CRITICAL + - MAJOR + - MINOR + - WARNING + - CLEARED + TrendIndication: + type: string + enum: + - MORE_SEVERE + - NO_CHANGE + - LESS_SEVERE + ThresholdHysteresis: + type: object + required: + - high + properties: + high: + oneOf: + - type: integer + - $ref: '#/components/schemas/Float' + low: + $ref: '#/components/schemas/Float' + ThresholdLevelInd: + type: object + required: + - up + properties: + up: + $ref: '#/components/schemas/ThresholdHysteresis' + low: + $ref: '#/components/schemas/ThresholdHysteresis' + ThresholdInfo: + type: object + required: + - observedMeasurement + - observedValue + properties: + observedMeasurement: + type: string + observedValue: + oneOf: + - type: integer + - $ref: '#/components/schemas/Float' + thresholdLevelInd: + $ref: '#/components/schemas/ThresholdLevelInd' + armTime: + $ref: '#/components/schemas/DateTime' + CorrelatedNotification: + type: object + required: + - source + - notificationId + properties: + sourceObjectInstance: + $ref: '#/components/schemas/Dn' + notificationIds: + type: array + items: + $ref: '#/components/schemas/NotificationId' + CorrelatedNotifications: + type: array + items: + $ref: '#/components/schemas/CorrelatedNotification' + AckState: + type: string + enum: + - ACKNOWLEDGED + - UNACKNOWLEDGED + + AlarmRecord: + description: >- + The alarmId is not a property of an alarm record. It is used as key + in the map of alarm records instead. + type: object + properties: + # alarmId: + # $ref: '#/components/schemas/AlarmId' + objectInstance: + $ref: '#/components/schemas/Dn' + notificationId: + $ref: '#/components/schemas/NotificationId' + alarmRaisedTime: + $ref: '#/components/schemas/DateTime' + alarmChangedTime: + $ref: '#/components/schemas/DateTime' + alarmClearedTime: + $ref: '#/components/schemas/DateTime' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + specificProblem: + $ref: '#/components/schemas/SpecificProblem' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + backedUpStatus: + type: boolean + backUpObject: + $ref: '#/components/schemas/Dn' + trendIndication: + $ref: '#/components/schemas/TrendIndication' + thresholdinfo: + $ref: '#/components/schemas/ThresholdInfo' + correlatedNotifications: + $ref: '#/components/schemas/CorrelatedNotifications' + stateChangeDefinition: + $ref: '#/components/schemas/AttributeValueChangeSet' + monitoredAttributes: + $ref: '#/components/schemas/AttributeNameValuePairSet' + proposedRepairActions: + type: string + additionalText: + type: string + additionalInformation: + $ref: '#/components/schemas/AttributeNameValuePairSet' + + rootCauseIndicator: + type: boolean + + ackTime: + $ref: '#/components/schemas/DateTime' + ackUserId: + type: string + ackSystemId: + type: string + ackState: + $ref: '#/components/schemas/AckState' + + clearUserId: + type: string + clearSystemId: + type: string + serviceUser: + type: string + serviceProvider: + type: string + securityAlarmDetector: + type: string + + #---- Definition of alarm notifications --------------------------------------------# + + AlarmNotificationTypes: + type: string + enum: + - notifyNewAlarm + - notifyChangedAlarm + - notifyChangedAlarmGeneral + - notifyAckStateChanged + - notifyCorrelatedNotificationChanged + - notifyComments + - notifyClearedAlarm + - notifyAlarmListRebuiltAlarm + - notifyPotentialFaultyAlarmList + AlarmListAlignmentRequirement: + type: string + enum: + - ALIGNMENT_REQUIRED + - ALIGNMENT_NOT_REQUIRED + + NotifyNewAlarm: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + specificProblem: + $ref: '#/components/schemas/SpecificProblem' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + backedUpStatus: + type: boolean + backUpObject: + $ref: '#/components/schemas/Dn' + trendIndication: + $ref: '#/components/schemas/TrendIndication' + thresholdInfo: + $ref: '#/components/schemas/ThresholdInfo' + correlatedNotifications: + $ref: '#/components/schemas/CorrelatedNotifications' + stateChangeDefinition: + $ref: '#/components/schemas/AttributeValueChangeSet' + monitoredAttributes: + $ref: '#/components/schemas/AttributeNameValuePairSet' + proposedRepairActions: + type: string + additionalText: + type: string + additionalInformation: + $ref: '#/components/schemas/AttributeNameValuePairSet' + rootCauseIndicator: + type: boolean + NotifyNewSecAlarm: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + - serviceUser + - serviceProvider + - securityAlarmDetector + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + correlatedNotifications: + $ref: '#/components/schemas/CorrelatedNotifications' + additionalText: + type: string + additionalInformation: + $ref: '#/components/schemas/AttributeNameValuePairSet' + rootCauseIndicator: + type: boolean + serviceUser: + type: string + serviceProvider: + type: string + securityAlarmDetector: + type: string + NotifyClearedAlarm: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + correlatedNotifications: + $ref: '#/components/schemas/CorrelatedNotifications' + clearUserId: + type: string + clearSystemId: + type: string + NotifyChangedAlarm: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + NotifyChangedAlarmGeneral: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + - changedAlarmAttributes + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + specificProblem: + $ref: '#/components/schemas/SpecificProblem' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + correlatedNotifications: + $ref: '#/components/schemas/CorrelatedNotifications' + backedUpStatus: + type: boolean + backUpObject: + $ref: '#/components/schemas/Dn' + trendIndication: + $ref: '#/components/schemas/TrendIndication' + thresholdInfo: + $ref: '#/components/schemas/ThresholdInfo' + stateChangeDefinition: + $ref: '#/components/schemas/AttributeValueChangeSet' + monitoredAttributes: + $ref: '#/components/schemas/AttributeNameValuePairSet' + proposedRepairActions: + type: string + additionalText: + type: string + additionalInformation: + $ref: '#/components/schemas/AttributeNameValuePairSet' + rootCauseIndicator: + type: boolean + changedAlarmAttributes: + $ref: '#/components/schemas/AttributeNameValuePairSet' + NotifyChangedSecAlarmGeneral: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + - serviceUser + - serviceProvider + - securityAlarmDetector + - changedAlarmAttributes + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + correlatedNotifications: + $ref: '#/components/schemas/CorrelatedNotifications' + additionalText: + type: string + additionalInformation: + $ref: '#/components/schemas/AttributeNameValuePairSet' + rootCauseIndicator: + type: boolean + serviceUser: + type: string + serviceProvider: + type: string + securityAlarmDetector: + type: string + changedAlarmAttributes: + $ref: '#/components/schemas/AttributeNameValuePairSet' + NotifyCorrelatedNotificationChanged: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - correlatedNotifications + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + correlatedNotifications: + $ref: '#/components/schemas/CorrelatedNotifications' + rootCauseIndicator: + type: boolean + NotifyAckStateChanged: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + - ackState + - ackUserId + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + ackState: + $ref: '#/components/schemas/AckState' + ackUserId: + type: string + ackSystemId: + type: string + NotifyComments: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + - comments + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + comments: + $ref: '#/components/schemas/Comments' + NotifyPotentialFaultyAlarmList: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - reason + properties: + reason: + type: string + NotifyAlarmListRebuilt: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - reason + properties: + reason: + type: string + alarmListAlignmentRequirement: + $ref: '#/components/schemas/AlarmListAlignmentRequirement' + + #---- Definition of query parameters -----------------------------------------------# + + AlarmAckState: + type: string + enum: + - ALL_ALARMS + - ALL_ACTIVE_ALARMS + - ALL_ACTIVE_AND_ACKNOWLEDGED_ALARMS + - ALL_ACTIVE_AND_UNACKNOWLEDGED_ALARMS + - ALL_CLEARED_AND_UNACKNOWLEDGED_ALARMS + - ALL_UNACKNOWLEDGED_ALARMS + + #---- Definition of patch documents ------------------------------------------------# + + MergePatchAcknowledgeAlarm: + description: >- + Patch document acknowledging or unacknowledging a single alarm. For + acknowleding an alarm the value of ackState is ACKNOWLEDGED, for unacknowleding + an alarm the value of ackState is UNACKNOWLEDGED. + type: object + required: + - ackUserId + - ackState + properties: + ackUserId: + type: string + ackSystemId: + type: string + ackState: + $ref: '#/components/schemas/AckState' + MergePatchClearAlarm: + description: Patch document for clearing a single alarm + type: object + required: + - clearUserId + - perceivedSeverity + properties: + clearUserId: + type: string + clearSystemId: + type: string + perceivedSeverity: + type: string + enum: + - CLEARED + + #---- Definition of method responses -----------------------------------------------# + + FailedAlarm: + type: object + required: + - alarmId + - failureReason + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + failureReason: + type: string + + #---- Definition of resources ------------------------------------------------------# + + AlarmCount: + type: object + required: + - criticalCount + - majorCount + - minorCount + - warningCount + - indeterminateCount + - clearedCount + properties: + criticalCount: + type: integer + majorCount: + type: integer + minorCount: + type: integer + warningCount: + type: integer + indeterminateCount: + type: integer + clearedCount: + type: integer + Comment: + type: object + properties: + commentTime: + $ref: '#/components/schemas/DateTime' + commentUserId: + type: string + commentSystemId: + type: string + commentText: + type: string + Comments: + description: >- + Collection of comments. The comment identifiers are allocated by the + MnS producer and used as key in the map. + type: object + additionalProperties: + $ref: '#/components/schemas/Comment' + Subscription: + type: object + properties: + consumerReference: + $ref: '#/components/schemas/Uri' + timeTick: + $ref: '#/components/schemas/Long' + filter: + $ref: '#/components/schemas/Filter' diff --git a/etc/externalRepo/3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/heartbeatNtf.yaml b/etc/externalRepo/3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/heartbeatNtf.yaml new file mode 100644 index 00000000..afde5066 --- /dev/null +++ b/etc/externalRepo/3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/heartbeatNtf.yaml @@ -0,0 +1,23 @@ +openapi: 3.0.1 +info: + title: Heartbeat notification + version: 16.3.0 + description: >- + OAS 3.0.1 specification of the heartbeat notification + © 2020, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). + All rights reserved. +externalDocs: + description: 3GPP TS 28.532 V16.3.0; Heartbeat notification + url: http://www.3gpp.org/ftp/Specs/archive/28_series/28.6532/ +paths: {} +components: + schemas: + hearbeatNtfPeriod-Type: + type: integer + notifyHeartbeat-NotifType: + allOf: + - $ref: 'provMnS.yaml#/components/schemas/header-Type' + - type: object + properties: + heartbeatNtfPeriod: + $ref: '#/components/schemas/hearbeatNtfPeriod-Type' diff --git a/etc/externalRepo/3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/provMnS.yaml b/etc/externalRepo/3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/provMnS.yaml new file mode 100644 index 00000000..b2f84a4d --- /dev/null +++ b/etc/externalRepo/3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/provMnS.yaml @@ -0,0 +1,579 @@ +openapi: 3.0.1 +info: + title: Provisioning MnS + version: 16.4.0 + description: >- + OAS 3.0.1 definition of the Provisioning MnS + © 2020, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). + All rights reserved. +externalDocs: + description: 3GPP TS 28.532 V16.4.0; Generic management services + url: http://www.3gpp.org/ftp/Specs/archive/28_series/28.532/ +servers: + - url: 'http://{URI-DN-prefix}/{root}/ProvMnS/v1640/{LDN-first-part}' + variables: + URI-DN-prefix: + description: See subclause 4.4 of TS 32.158 + default: example.com + root: + description: See subclause 4.4 of TS 32.158 + default: 3GPPManagement + LDN-first-part: + description: See subclause 4.4 of TS 32.158 + default: '' +paths: + '/{className}={id}': + parameters: + - name: className + in: path + required: true + schema: + $ref: '#/components/schemas/className-PathType' + - name: id + in: path + required: true + schema: + $ref: '#/components/schemas/id-PathType' + put: + summary: Replaces a complete single resource or creates it if it does not exist + description: >- + With HTTP PUT a complete resource is replaced or created if it does not + exist. The target resource is identified by the target URI. + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/resourcePut-RequestType' + responses: + '200': + description: >- + Success case ("200 OK"). + This status code shall be returned when the resource is replaced, and + when the replaced resource representation is not identical to the resource + representation in the request. + This status code may be retourned when the resource is updated and when the + updated resource representation is identical to the resource representation + in the request. + The representation of the updated resource is returned in the response + message body. + content: + application/json: + schema: + $ref: '#/components/schemas/resourceUpdate-ResponseType' + '201': + description: >- + Success case ("201 Created"). + This status code shall be returned when the resource is created. + The representation of the created resource is returned in the response + message body. + content: + application/json: + schema: + $ref: '#/components/schemas/resourceCreation-ResponseType' + '204': + description: >- + Success case ("204 No Content"). + This status code may be returned only when the replaced resource + representation is identical to the representation in the request. + The response has no message body. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/error-ResponseType' + callbacks: + notifyMOICreation: + '{request.body#/notificationRecipientAddress}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/notifyMOICreation-NotifType' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response + has no message body. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/error-ResponseType' + notifyMOIDeletion: + '{request.body#/notificationRecipientAddress}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/notifyMOIDeletion-NotifType' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response + has no message body. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/error-ResponseType' + notifyMOIAttributeValueChange: + '{request.body#/notificationRecipientAddress}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/notifyMOIAttributeValueChange-NotifType' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response + has no message body. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/error-ResponseType' + notifyMOIChanges: + '{request.body#/notificationRecipientAddress}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/notifyMOIChanges-NotifType' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response + has no message body. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/error-ResponseType' + get: + summary: Reads one or multiple resources + description: >- + With HTTP GET resources are read. The resources to be retrieved are + identified with the target URI. The attributes and fields parameter + of the query components allow to select the resource properties to be returned. + parameters: + - name: scope + in: query + description: >- + This parameter extends the set of targeted resources beyond the base + resource identified with the path component of the URI. No scoping + mechanism is specified in the present document. + required: false + schema: + $ref: '#/components/schemas/scope-QueryType' + style: form + explode: true + - name: filter + in: query + description: >- + This parameter reduces the targeted set of resources by applying a + filter to the scoped set of resource representations. Only resource + representations for which the filter construct evaluates to "true" + are targeted. No filter language is specified in the present + document. + required: false + schema: + $ref: '#/components/schemas/filter-QueryType' + - name: attributes + in: query + description: >- + This parameter specifies the attributes of the scoped resources that + are returned. + required: true + schema: + $ref: '#/components/schemas/attributes-QueryType' + style: form + explode: false + - name: fields + in: query + description: >- + This parameter specifies the attribute field of the scoped resources + that are returned. + required: false + schema: + $ref: '#/components/schemas/fields-QueryType' + style: form + explode: false + responses: + '200': + description: >- + Success case ("200 OK"). + The resources identified in the request for retrieval are returned + in the response message body. In case the attributes or fields query + parameters are used, only the selected attributes or sub-attributes are + returned. The response message body is constructed according to the + hierarchical response construction method (TS 32.158 [15]). + content: + application/json: + schema: + $ref: '#/components/schemas/resourceRetrieval-ResponseType' + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/error-ResponseType' + patch: + summary: Patches one or multiple resources + description: >- + With HTTP PATCH resources are created, updated or deleted. The resources + to be modified are identified with the target URI (base resource) and + the patch document included in the request message body. + requestBody: + description: >- + The request body describes changes to be made to the target resources. + The following patch media types are available + - "application/merge-patch+json" (RFC 7396) + - "application/3gpp-merge-patch+json" (TS 32.158) + - "application/json-patch+json" (RFC 6902) + - "application/3gpp-json-patch+json" (TS 32.158) + required: true + content: + application/merge-patch+json: + schema: + $ref: '#/components/schemas/jsonMergePatch-RequestType' + application/3gpp-merge-patch+json: + schema: + $ref: '#/components/schemas/3gppJsonMergePatch-RequestType' + application/json-patch+json: + schema: + $ref: '#/components/schemas/jsonPatch-RequestType' + application/3gpp-json-patch+json: + schema: + $ref: '#/components/schemas/3gppJsonPatch-RequestType' + responses: + '200': + description: >- + Success case ("200 OK"). + This status code is returned when the updated the resource representations + shall be returned for some reason. + The resource representations are returned in the response message body. The + response message body is constructed according to the hierarchical response + construction method (TS 32.158 [15]) + content: + application/json: + schema: + $ref: '#/components/schemas/resourceUpdate-ResponseType' + '204': + description: >- + Success case ("204 No Content"). + This status code is returned when there is no need to return the updated + resource representations. + The response message body is empty. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/error-ResponseType' + delete: + summary: Deletes one or multiple resources + description: >- + With HTTP DELETE resources are deleted. The resources to be deleted are + identified with the target URI. + parameters: + - name: scope + in: query + description: >- + This parameter extends the set of targeted resources beyond the base + resource identified with the path component of the URI. No scoping + mechanism is specified in the present document. + required: false + schema: + $ref: '#/components/schemas/scope-QueryType' + - name: filter + in: query + description: >- + This parameter reduces the targeted set of resources by applying a + filter to the scoped set of resource representations. Only resources + representations for which the filter construct evaluates to "true" + are returned. No filter language is specified in the present + document. + required: false + schema: + $ref: '#/components/schemas/filter-QueryType' + responses: + '200': + description: >- + Success case ("200 OK"). + This status code shall be returned, when query parameters are present in + the request and one or multiple resources are deleted. + The URIs of the deleted resources are returned in the response message body. + '204': + description: >- + Success case ("204 No Content"). + This status code shall be returned, when no query parameters are present in + the request and only one resource is deleted. + The message body is empty. + content: + application/json: + schema: + $ref: '#/components/schemas/resourceDeletion-ResponseType' + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/error-ResponseType' +components: + schemas: + dateTime-Type: + type: string + format: date-time + long-Type: + type: integer + format: int64 + uri-Type: + type: string + correlatedNotification-Type: + type: object + properties: + source: + $ref: '#/components/schemas/uri-Type' + notificationIds: + type: array + items: + $ref: '#/components/schemas/notificationId-Type' + notificationId-Type: + $ref: '#/components/schemas/long-Type' + notificationType-Type: + type: string + enum: + - notifyMOICreation + - notifyMOIDeletion + - notifyMOIAttributeValueChange + systemDN-Type: + type: string + additionalText-Type: + type: string + sourceIndicator-Type: + type: string + enum: + - resourceOperation + - mangementOperation + - sONOperation + - unknown + header-Type: + type: object + properties: + href: + $ref: '#/components/schemas/uri-Type' + notificationId: + $ref: '#/components/schemas/notificationId-Type' + notificationType: + $ref: '#/components/schemas/notificationType-Type' + eventTime: + $ref: '#/components/schemas/dateTime-Type' + systemDN: + $ref: '#/components/schemas/systemDN-Type' + required: + - href + - notificationId + - notificationType + - eventTime + - systemDN + scopeType-Type: + type: string + enum: + - BASE_ONLY + - BASE_NTH_LEVEL + - BASE_SUBTREE + - BASE_ALL + scopeLevel-Type: + type: integer + className-PathType: + type: string + id-PathType: + type: string + attributes-QueryType: + type: array + items: + type: string + fields-QueryType: + type: array + items: + type: string + filter-QueryType: + type: string + scope-QueryType: + type: object + properties: + scopeType: + $ref: '#/components/schemas/scopeType-Type' + scopeLevel: + $ref: '#/components/schemas/scopeLevel-Type' + + resourcePut-RequestType: + $ref: '#/components/schemas/resourceRepresentation-Type' + jsonMergePatch-RequestType: + $ref: '#/components/schemas/resourceRepresentation-Type' + 3gppJsonMergePatch-RequestType: + $ref: '#/components/schemas/resourceRepresentation-Type' + jsonPatch-RequestType: + type: array + items: + type: object + 3gppJsonPatch-RequestType: + type: array + items: + type: object + + error-ResponseType: + type: object + properties: + error: + type: object + properties: + errorInfo: + type: string + resourceRetrieval-ResponseType: + $ref: '#/components/schemas/resourceRepresentation-Type' + resourceCreation-ResponseType: + $ref: '#/components/schemas/resourceRepresentation-Type' + resourceUpdate-ResponseType: + $ref: '#/components/schemas/resourceRepresentation-Type' + resourceDeletion-ResponseType: + type: array + items: + $ref: '#/components/schemas/uri-Type' + + resourceRepresentation-Type: + oneOf: + - type: object + properties: + id: + type: string + attributes: + type: object + additionalProperties: + type: array + items: + type: object + - anyOf: + - $ref: 'genericNrm.yaml#/components/schemas/resources-genericNrm' + - $ref: 'nrNrm.yaml#/components/schemas/resources-nrNrm' + - $ref: '5gcNrm.yaml#/components/schemas/resources-5gcNrm' + - $ref: 'sliceNrm.yaml#/components/schemas/resources-sliceNrm' + + mOIChange-Type: + type: object + properties: + notificationId: + $ref: '#/components/schemas/notificationId-Type' + correlatedNotifications: + type: array + items: + $ref: '#/components/schemas/correlatedNotification-Type' + additionalText: + $ref: '#/components/schemas/additionalText-Type' + sourceIndicator: + $ref: '#/components/schemas/sourceIndicator-Type' + path: + $ref: '#/components/schemas/uri-Type' + operation: + type: string + enum: + - CREATE + - DELETE + - REPLACE + value: + oneOf: + - type: object + additionalProperties: + nullable: true + - type: array + items: + type: object + minItems: 1 + maxItems: 2 + + notifyMOICreation-NotifType: + allOf: + - $ref: '#/components/schemas/header-Type' + - type: object + properties: + correlatedNotifications: + type: array + items: + $ref: '#/components/schemas/correlatedNotification-Type' + additionalText: + $ref: '#/components/schemas/additionalText-Type' + sourceIndicator: + $ref: '#/components/schemas/sourceIndicator-Type' + attributeList: + type: object + additionalProperties: + nullable: true + notifyMOIDeletion-NotifType: + allOf: + - $ref: '#/components/schemas/header-Type' + - type: object + properties: + correlatedNotifications: + type: array + items: + $ref: '#/components/schemas/correlatedNotification-Type' + additionalText: + $ref: '#/components/schemas/additionalText-Type' + sourceIndicator: + $ref: '#/components/schemas/sourceIndicator-Type' + attributeList: + type: object + additionalProperties: true + notifyMOIAttributeValueChange-NotifType: + allOf: + - $ref: '#/components/schemas/header-Type' + - type: object + properties: + correlatedNotifications: + type: array + items: + $ref: '#/components/schemas/correlatedNotification-Type' + additionalText: + $ref: '#/components/schemas/additionalText-Type' + sourceIndicator: + $ref: '#/components/schemas/sourceIndicator-Type' + attributeValueChange: + type: object + additionalProperties: + type: array + minItems: 1 + maxItems: 2 + items: + nullable: true + required: + - attributeValueChange + notifyMOIChanges-NotifType: + allOf: + - $ref: '#/components/schemas/header-Type' + - type: object + properties: + mOIChanges: + type: array + items: + $ref: '#/components/schemas/mOIChange-Type' + required: + - mOIChanges diff --git a/etc/externalRepo/schema-map.json b/etc/externalRepo/schema-map.json new file mode 100644 index 00000000..b6849dd2 --- /dev/null +++ b/etc/externalRepo/schema-map.json @@ -0,0 +1,18 @@ +[ + { + "publicURL": "https://forge.3gpp.org/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml", + "localURL": "3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml" + }, + { + "publicURL": "https://forge.3gpp.org/rep/sa5/data-models/blob/REL-16/OpenAPI/heartbeatNtf.yaml", + "localURL": "3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/heartbeatNtf.yaml" + }, + { + "publicURL": "https://forge.3gpp.org/rep/sa5/data-models/blob/REL-16/OpenAPI/PerDataFileReportMnS.yaml", + "localURL": "3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/PerDataFileReportMnS.yaml" + }, + { + "publicURL": "https://forge.3gpp.org/rep/sa5/data-models/blob/master/OpenAPI/provMnS.yaml", + "localURL": "3gpp/rep/sa5/data-models/blob/REL-16/OpenAPI/provMnS.yaml" + } +]
\ No newline at end of file @@ -24,7 +24,7 @@ </parent>
<groupId>org.onap.dcaegen2.collectors.ves</groupId>
<artifactId>VESCollector</artifactId>
- <version>1.7.2-SNAPSHOT</version>
+ <version>1.7.3-SNAPSHOT</version>
<name>dcaegen2-collectors-ves</name>
<description>VESCollector</description>
<properties>
@@ -78,6 +78,7 @@ <spring-boot-starter-test.version>2.1.0.RELEASE</spring-boot-starter-test.version>
<api-custom-header.version>1.1.4</api-custom-header.version>
<functionaljava.version>4.8.1</functionaljava.version>
+ <external-schema-manager.version>1.4.1</external-schema-manager.version>
</properties>
<build>
<pluginManagement>
@@ -441,6 +442,11 @@ <version>${crypt-password.version}</version>
</dependency>
<dependency>
+ <groupId>org.onap.dcaegen2.services.sdk</groupId>
+ <artifactId>dcaegen2-services-sdk-services-external-schema-manager</artifactId>
+ <version>${external-schema-manager.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
</dependency>
diff --git a/src/main/java/org/onap/dcae/ApplicationSettings.java b/src/main/java/org/onap/dcae/ApplicationSettings.java index 33ad5bc7..7d5c7db2 100644 --- a/src/main/java/org/onap/dcae/ApplicationSettings.java +++ b/src/main/java/org/onap/dcae/ApplicationSettings.java @@ -55,6 +55,8 @@ public class ApplicationSettings { private static final Logger log = LoggerFactory.getLogger(ApplicationSettings.class); private static final String FALLBACK_VES_VERSION = "v5"; + private static final int DISABLED = -1; + private static final int ENABLED = 1; private final String appInvocationDir; private final String configurationFileLocation; private final PropertiesConfiguration properties = new PropertiesConfiguration(); @@ -96,7 +98,7 @@ public class ApplicationSettings { } public boolean eventSchemaValidationEnabled() { - return properties.getInt("collector.schema.checkflag", -1) > 0; + return properties.getInt("collector.schema.checkflag", DISABLED) > 0; } public JsonSchema jsonSchema(String version) { @@ -126,7 +128,7 @@ public class ApplicationSettings { } public boolean eventTransformingEnabled() { - return properties.getInt("event.transform.flag", 1) > 0; + return properties.getInt("event.transform.flag", ENABLED) > 0; } public String keystorePasswordFileLocation() { @@ -170,6 +172,26 @@ public class ApplicationSettings { } } + public boolean getExternalSchemaValidationCheckflag() { + return properties.getInt("collector.externalSchema.checkflag", DISABLED) > 0; + } + + public String getExternalSchemaSchemasLocation() { + return properties.getString("collector.externalSchema.schemasLocation", "./etc/externalRepo"); + } + + public String getExternalSchemaMappingFileLocation() { + return properties.getString("collector.externalSchema.mappingFileLocation", "./etc/externalRepo/schema-map.json"); + } + + public String getExternalSchemaSchemaRefPath() { + return properties.getString("event.externalSchema.schemaRefPath", "/event/stndDefinedFields/schemaReference"); + } + + public String getExternalSchemaStndDefinedDataPath() { + return properties.getString("event.externalSchema.stndDefinedDataPath", "/event/stndDefinedFields/data"); + } + public List<EventTransformation> getEventTransformations() { return eventTransformations; } diff --git a/src/main/java/org/onap/dcae/VesApplication.java b/src/main/java/org/onap/dcae/VesApplication.java index 9f628b5c..bb785dbd 100644 --- a/src/main/java/org/onap/dcae/VesApplication.java +++ b/src/main/java/org/onap/dcae/VesApplication.java @@ -27,10 +27,12 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.onap.dcae.common.EventSender; +import org.onap.dcae.common.validator.StndDefinedValidatorResolver; import org.onap.dcae.common.publishing.DMaaPConfigurationParser; import org.onap.dcae.common.publishing.EventPublisher; import org.onap.dcae.common.publishing.PublisherConfig; import org.onap.dcae.controller.ConfigLoader; +import org.onap.dcaegen2.services.sdk.services.external.schema.manager.service.StndDefinedValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Qualifier; @@ -136,4 +138,9 @@ public class VesApplication { return new EventSender(eventPublisher, applicationSettings.getDmaapStreamIds()); } + @Bean + public StndDefinedValidator getStndDefinedValidator(StndDefinedValidatorResolver resolver) { + return resolver.resolve(); + } + } diff --git a/src/main/java/org/onap/dcae/common/ConfigProcessors.java b/src/main/java/org/onap/dcae/common/ConfigProcessors.java index c459bb1c..d1c5e5a0 100644 --- a/src/main/java/org/onap/dcae/common/ConfigProcessors.java +++ b/src/main/java/org/onap/dcae/common/ConfigProcessors.java @@ -54,8 +54,9 @@ public class ConfigProcessors { if (filter == null || isFilterMet(filter)) { getEventObjectVal(field); - } else + } else { log.info(FILTER_NOT_MET); + } } @@ -65,8 +66,9 @@ public class ConfigProcessors { final JSONObject filter = jsonObject.optJSONObject(FILTER); if (filter == null || isFilterMet(filter)) { setEventObjectVal(field, value); - } else + } else { log.info(FILTER_NOT_MET); + } } @@ -85,8 +87,9 @@ public class ConfigProcessors { if (filter == null || isFilterMet(filter)) { setEventObjectVal("suppressEvent", "true"); - } else + } else { log.info(FILTER_NOT_MET); + } } @@ -99,8 +102,9 @@ public class ConfigProcessors { if (filter == null || isFilterMet(filter)) { setEventObjectVal(field, value, fieldType); - } else + } else { log.info(FILTER_NOT_MET); + } } @@ -111,8 +115,9 @@ public class ConfigProcessors { final JSONObject filter = jsonObject.optJSONObject(FILTER); if (filter == null || isFilterMet(filter)) { setEventObjectVal(field, value); - } else + } else { log.info(FILTER_NOT_MET); + } } @@ -123,8 +128,9 @@ public class ConfigProcessors { if (filter == null || isFilterMet(filter)) { removeEventKey(field); - } else + } else { log.info(FILTER_NOT_MET); + } } @@ -152,8 +158,9 @@ public class ConfigProcessors { removeEventKey(oldfsplit[0]); setEventObjectVal(fsplit[0], ja); } - } else + } else { log.info(FILTER_NOT_MET); + } } private void renameObject(JSONObject jsonObject) // map @@ -170,29 +177,30 @@ public class ConfigProcessors { setEventObjectVal(field, oldValue); removeEventKey(oldField); } - } else + } else { log.info(FILTER_NOT_MET); + } } - + public void map(JSONObject jsonObject) { final String field = jsonObject.getString(FIELD); final String mapType = jsonObject.optString(MAP_TYPE, ""); if (field.contains("[]")) { - if (field.matches(".*\\[\\]\\..*\\[\\]")) + if (field.matches(".*\\[\\]\\..*\\[\\]")) { renameArrayInArray(jsonObject); - else + } else { mapToJArray(jsonObject); + } + } else if ("hashmapToNameValueArray".equals(mapType)) { + mapHashmapToNameValueArray(jsonObject); + } else if ("nameValueArrayToHashmap".equals(mapType)) { + mapNameValueArrayToHashmap(jsonObject); + } else if ("renameObject".equals(mapType)) { + renameObject(jsonObject); + } else { + mapAttribute(jsonObject); } - else if (mapType.equals("hashmapToNameValueArray")) - mapHashmapToNameValueArray(jsonObject); - else if (mapType.equals("nameValueArrayToHashmap")) - mapNameValueArrayToHashmap(jsonObject); - else if (mapType.equals("renameObject")) - renameObject(jsonObject); - - else - mapAttribute(jsonObject); } private String performOperation(String operation, String value) { @@ -216,15 +224,17 @@ public class ConfigProcessors { value = getEventObjectVal(oldField).toString(); if (!value.equals(OBJECT_NOT_FOUND)) { - if (operation != null && !operation.isEmpty()) + if (operation != null && !operation.isEmpty()) { value = performOperation(operation, value); + } setEventObjectVal(field, value); removeEventKey(oldField); } - } else + } else { log.info(FILTER_NOT_MET); + } } @@ -270,16 +280,21 @@ public class ConfigProcessors { setEventObjectVal(field, ja); } } else // if new array + { setEventObjectVal(field + "[0]", new JSONObject(value), "JArray"); + } } else // oldfield is jsonArray + { setEventObjectVal(field, new JSONArray(value)); + } removeEventKey(oldField); } - } else + } else { log.info(FILTER_NOT_MET); + } } - + // this method is to support the mapping 5.x to VES7.x format for additionalInformation field private void mapNameValueArrayToHashmap(JSONObject jsonObject) { log.info("mapNameValueArrayToHashmap"); @@ -288,17 +303,17 @@ public class ConfigProcessors { final JSONObject filter = jsonObject.optJSONObject(FILTER); if (filter == null || isFilterMet(filter)) { - JSONObject newHashMap = new JSONObject(); // this will hold the newly mapped hashmap elements + JSONObject newHashMap = new JSONObject(); // this will hold the newly mapped hashmap elements JSONArray arrayValue = (JSONArray) getEventObjectVal(oldField); // old Array structure value - JSONObject tempJObj = null; - String tempName = ""; - String tempValue = ""; + JSONObject tempJObj; + String tempName; + String tempValue; if (!arrayValue.toString().equals(OBJECT_NOT_FOUND)) { log.info("old value ==" + arrayValue.toString()); // Loop thru the JSONArray, get the name:value pair and write to new JSONObject as hashmap elements for (int i = 0; i < arrayValue.length(); i++) { - tempJObj = arrayValue.getJSONObject(i); + tempJObj = arrayValue.getJSONObject(i); if (tempJObj != null) { tempName = tempJObj.get("name").toString(); tempValue = tempJObj.get(VALUE).toString(); @@ -310,11 +325,12 @@ public class ConfigProcessors { //Add the new Hashmap setEventObjectVal(field, newHashMap); } - } else + } else { log.info(FILTER_NOT_MET); + } } - - // this method is to support the mapping 7.x to VES5.x format for additionalInformation field + + // this method is to support the mapping 7.x to VES5.x format for additionalInformation field private void mapHashmapToNameValueArray(JSONObject jsonObject) { log.info("mapHashmapToNameValueArray"); System.out.println("mapHashmapToNameValueArray"); @@ -323,29 +339,30 @@ public class ConfigProcessors { final JSONObject filter = jsonObject.optJSONObject(FILTER); if (filter == null || isFilterMet(filter)) { - JSONArray newArray = new JSONArray(); // this will hold the new name:value JSONObject - JSONObject nameValJObj; - System.out.println("object ==" + getEventObjectVal(oldField).toString()); - if (!getEventObjectVal(oldField).toString().equals(OBJECT_NOT_FOUND)) { - - JSONObject hashMap = (JSONObject) getEventObjectVal(oldField); // old hashmap structure value - if (hashMap != null) { - log.info("old value ==" + hashMap.toString()); - // Loop thru the hashMap JSONObject, get the hashmap elements add them as name:value JsonObject into the newArray - for (String key : hashMap.keySet()) { - nameValJObj = new JSONObject(); //create new object so not to overwrite in memory for Array insertion - nameValJObj.put("name", key); - nameValJObj.put("value", hashMap.get(key)); - newArray.put(nameValJObj); - } - // remove the old hashMap structure - removeEventKey(oldField); - //Add the newArray containing the name:value Object - setEventObjectVal(field, newArray); - } - } - } else + JSONArray newArray = new JSONArray(); // this will hold the new name:value JSONObject + JSONObject nameValJObj; + System.out.println("object ==" + getEventObjectVal(oldField).toString()); + if (!getEventObjectVal(oldField).toString().equals(OBJECT_NOT_FOUND)) { + + JSONObject hashMap = (JSONObject) getEventObjectVal(oldField); // old hashmap structure value + if (hashMap != null) { + log.info("old value ==" + hashMap.toString()); + // Loop thru the hashMap JSONObject, get the hashmap elements add them as name:value JsonObject into the newArray + for (String key : hashMap.keySet()) { + nameValJObj = new JSONObject(); //create new object so not to overwrite in memory for Array insertion + nameValJObj.put("name", key); + nameValJObj.put("value", hashMap.get(key)); + newArray.put(nameValJObj); + } + // remove the old hashMap structure + removeEventKey(oldField); + //Add the newArray containing the name:value Object + setEventObjectVal(field, newArray); + } + } + } else { log.info(FILTER_NOT_MET); + } } /** @@ -367,16 +384,18 @@ public class ConfigProcessors { String tempVal = evaluate(values.getString(i)); if (!tempVal.equals(OBJECT_NOT_FOUND)) { - if (i == 0) + if (i == 0) { value.append(tempVal); - else + } else { value.append(delimiter).append(tempVal); + } } } setEventObjectVal(field, value.toString()); - } else + } else { log.info(FILTER_NOT_MET); + } } public void subtractValue(JSONObject jsonObject) { @@ -391,16 +410,18 @@ public class ConfigProcessors { String tempVal = evaluate(values.getString(i)); log.info("tempVal==" + tempVal); if (!tempVal.equals(OBJECT_NOT_FOUND)) { - if (i == 0) - value = value + Float.valueOf(tempVal); - else - value = value - Float.valueOf(tempVal); + if (i == 0) { + value = value + Float.parseFloat(tempVal); + } else { + value = value - Float.parseFloat(tempVal); + } } } log.info("value ==" + value); setEventObjectVal(field, value, "number"); - } else + } else { log.info(FILTER_NOT_MET); + } } @@ -470,12 +491,14 @@ public class ConfigProcessors { if ("not".equals(key)) { JSONObject njo = jo.getJSONObject(key); for (String njoKey : njo.keySet()) { - if (!checkFilter(njo, njoKey, key)) + if (!checkFilter(njo, njoKey, key)) { return false; + } } } else { - if (!checkFilter(jo, key, key)) + if (!checkFilter(jo, key, key)) { return false; + } } } return true; @@ -491,8 +514,9 @@ public class ConfigProcessors { keySeriesStr = keySeriesStr.replaceAll("\\.\\.", "."); } - if (keySeriesStr.lastIndexOf(".") == keySeriesStr.length() - 1) + if (keySeriesStr.lastIndexOf(".") == keySeriesStr.length() - 1) { keySeriesStr = keySeriesStr.substring(0, keySeriesStr.length() - 1); + } String[] keySet = keySeriesStr.split("\\.", keySeriesStr.length()); Object keySeriesObj = event; for (String aKeySet : keySet) { @@ -512,8 +536,9 @@ public class ConfigProcessors { } } - if (keySeriesObj == null) + if (keySeriesObj == null) { return OBJECT_NOT_FOUND; + } return keySeriesObj; } @@ -532,8 +557,9 @@ public class ConfigProcessors { } log.info("fieldType==" + fieldType); - if (keySeriesStr.lastIndexOf(".") == keySeriesStr.length() - 1) + if (keySeriesStr.lastIndexOf(".") == keySeriesStr.length() - 1) { keySeriesStr = keySeriesStr.substring(0, keySeriesStr.length() - 1); + } String[] keySet = keySeriesStr.split("\\.", keySeriesStr.length()); Object keySeriesObj = event; for (int i = 0; i < (keySet.length - 1); i++) { @@ -552,9 +578,11 @@ public class ConfigProcessors { { log.info("Object is null, must add it"); if (keySet[i + 1].matches("[0-9]*")) // if index then array + { ((JSONArray) keySeriesObj).put(Integer.parseInt(keySet[i]), new JSONArray()); - else + } else { ((JSONArray) keySeriesObj).put(Integer.parseInt(keySet[i]), new JSONObject()); + } } keySeriesObj = ((JSONArray) keySeriesObj).optJSONObject(Integer.parseInt(keySet[i])); @@ -570,9 +598,11 @@ public class ConfigProcessors { // it { if (keySet[i + 1].matches("[0-9]*")) // if index then array + { ((JSONObject) keySeriesObj).put(keySet[i], new JSONArray()); - else + } else { ((JSONObject) keySeriesObj).put(keySet[i], new JSONObject()); + } log.info("Object is null, must add it"); } keySeriesObj = ((JSONObject) keySeriesObj).opt(keySet[i]); @@ -582,17 +612,20 @@ public class ConfigProcessors { } if ("number".equals(fieldType)) { DecimalFormat df = new DecimalFormat("#.0"); - if (value instanceof String) + if (value instanceof String) { ((JSONObject) keySeriesObj).put(keySet[keySet.length - 1], Float.valueOf(df.format(Float.valueOf((String) value)))); - else + } else { ((JSONObject) keySeriesObj).put(keySet[keySet.length - 1], Float.valueOf(df.format(value))); - } else if ("integer".equals(fieldType) && value instanceof String) + } + } else if ("integer".equals(fieldType) && value instanceof String) { ((JSONObject) keySeriesObj).put(keySet[keySet.length - 1], Integer.valueOf((String) value)); - else if ("JArray".equals(fieldType)) + } else if ("JArray".equals(fieldType)) { + assert keySeriesObj instanceof JSONArray; ((JSONArray) keySeriesObj).put(value); - else + } else { ((JSONObject) keySeriesObj).put(keySet[keySet.length - 1], value); + } } } diff --git a/src/main/java/org/onap/dcae/common/model/VesEvent.java b/src/main/java/org/onap/dcae/common/model/VesEvent.java index ce709d1c..6c9a8ee2 100644 --- a/src/main/java/org/onap/dcae/common/model/VesEvent.java +++ b/src/main/java/org/onap/dcae/common/model/VesEvent.java @@ -19,6 +19,9 @@ */ package org.onap.dcae.common.model; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import org.json.JSONObject; /** @@ -35,6 +38,8 @@ public class VesEvent { private static final String DOMAIN = "domain"; private static final String STND_DEFINED_NAMESPACE = "stndDefinedNamespace"; private static final String STND_DEFINED_DOMAIN = "stndDefined"; + private static final String STND_DEFINED_FIELDS = "stndDefinedFields"; + private static final String SCHEMA_REFERENCE = "schemaReference"; private final JSONObject event; @@ -66,6 +71,16 @@ public class VesEvent { return getEventHeader().getString(DOMAIN); } + public String getSchemaReference() { + return getStndDefinedFields().getString(SCHEMA_REFERENCE); + } + + private JSONObject getStndDefinedFields() { + return event + .getJSONObject(EVENT_LITERAL) + .getJSONObject(STND_DEFINED_FIELDS); + } + private String resolveDomainForStndDefinedEvent() { final JSONObject eventHeader = getEventHeader(); if(eventHeader.has(STND_DEFINED_NAMESPACE)) { @@ -108,6 +123,11 @@ public class VesEvent { return new JSONObject(event.toString()); } + public JsonNode asJsonNode() throws JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readTree(event.toString()); + } + /** * Checks if type of event is same as given in paramaters. * diff --git a/src/main/java/org/onap/dcae/common/validator/GeneralEventValidator.java b/src/main/java/org/onap/dcae/common/validator/GeneralEventValidator.java new file mode 100644 index 00000000..5cd5dc25 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/validator/GeneralEventValidator.java @@ -0,0 +1,75 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020 Nokia. 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.dcae.common.validator; + +import com.networknt.schema.JsonSchema; +import org.onap.dcae.ApplicationSettings; +import org.onap.dcae.common.model.VesEvent; +import org.onap.dcae.restapi.ApiException; +import org.onap.dcae.restapi.EventValidatorException; + +/** + * This class is using ApplicationSetting and SchemaValidator to validate VES event. + * + * @author Zebek + */ +public class GeneralEventValidator { + + private final SchemaValidator schemaValidator; + private final ApplicationSettings applicationSettings; + + public GeneralEventValidator(ApplicationSettings applicationSettings) { + this(applicationSettings, new SchemaValidator()); + } + + GeneralEventValidator(ApplicationSettings applicationSettings, SchemaValidator schemaValidator) { + this.applicationSettings = applicationSettings; + this.schemaValidator = schemaValidator; + } + + /** + * This method is validating given event using schema adn throws exception if event is not valid + * + * @param vesEvent event that will be validate + * @param type expected type of event + * @param version json schema version that will be used + * @throws EventValidatorException when event is not valid or have wrong type + */ + public void validate(VesEvent vesEvent, String type, String version) throws EventValidatorException { + if (applicationSettings.eventSchemaValidationEnabled()) { + doValidation(vesEvent, type, version); + } + } + + private void doValidation(VesEvent vesEvent, String type, String version) throws EventValidatorException { + if (vesEvent.hasType(type)) { + if (!isEventMatchToSchema(vesEvent, applicationSettings.jsonSchema(version))) { + throw new EventValidatorException(ApiException.SCHEMA_VALIDATION_FAILED); + } + } else { + throw new EventValidatorException(ApiException.INVALID_JSON_INPUT); + } + } + + private boolean isEventMatchToSchema(VesEvent vesEvent, JsonSchema schema) { + return schemaValidator.conformsToSchema(vesEvent.asJsonObject(), schema); + } +} diff --git a/src/main/java/org/onap/dcae/restapi/SchemaValidator.java b/src/main/java/org/onap/dcae/common/validator/SchemaValidator.java index 94638071..80c8f6e7 100644 --- a/src/main/java/org/onap/dcae/restapi/SchemaValidator.java +++ b/src/main/java/org/onap/dcae/common/validator/SchemaValidator.java @@ -18,7 +18,7 @@ * limitations under the License.
* ============LICENSE_END=========================================================
*/
-package org.onap.dcae.restapi;
+package org.onap.dcae.common.validator;
import com.fasterxml.jackson.databind.JsonNode;
@@ -47,8 +47,8 @@ class SchemaValidator { return true;
}
- log.warn("Schema validation failed for event: " + payload);
- messageSet.stream().forEach(it->log.warn(it.getMessage()) );
+ log.warn("Schema validation failed for event: {}", payload);
+ messageSet.forEach(it->log.warn(it.getMessage()) );
return false;
} catch (Exception e) {
diff --git a/src/main/java/org/onap/dcae/common/validator/StndDefinedDataValidator.java b/src/main/java/org/onap/dcae/common/validator/StndDefinedDataValidator.java new file mode 100644 index 00000000..d936f272 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/validator/StndDefinedDataValidator.java @@ -0,0 +1,83 @@ +/* + * ============LICENSE_START======================================================= + * VES + * ================================================================================ + * Copyright (C) 2020 Nokia. 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.dcae.common.validator; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import org.json.JSONException; +import org.onap.dcae.common.model.VesEvent; +import org.onap.dcae.restapi.ApiException; +import org.onap.dcae.restapi.EventValidatorException; +import org.onap.dcaegen2.services.sdk.services.external.schema.manager.exception.IncorrectInternalFileReferenceException; +import org.onap.dcaegen2.services.sdk.services.external.schema.manager.exception.NoLocalReferenceException; +import org.onap.dcaegen2.services.sdk.services.external.schema.manager.service.StndDefinedValidator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class StndDefinedDataValidator { + + private static final String STND_DEFINED_DOMAIN = "stndDefined"; + + private final StndDefinedValidator stndDefinedValidator; + + @Autowired + public StndDefinedDataValidator(StndDefinedValidator validator) { + this.stndDefinedValidator = validator; + } + + /** + * Validates incoming event + * + * @param event as JsonNode + * @throws EventValidatorException exceptions related to failing StndDefined validation + */ + public void validate(VesEvent event) throws EventValidatorException { + try { + if (shouldBeValidated(event) && !doValidation(event.asJsonNode())) { + throw new EventValidatorException(ApiException.STND_DEFINED_VALIDATION_FAILED); + } + } catch (JsonProcessingException ex) { + throw new EventValidatorException(ApiException.INVALID_JSON_INPUT); + } + } + + private boolean doValidation(JsonNode event) throws EventValidatorException { + try { + return stndDefinedValidator.validate(event); + } catch (NoLocalReferenceException e) { + throw new EventValidatorException(ApiException.NO_LOCAL_SCHEMA_REFERENCE); + } catch (IncorrectInternalFileReferenceException e) { + throw new EventValidatorException(ApiException.INCORRECT_INTERNAL_FILE_REFERENCE); + } + } + + private boolean shouldBeValidated(VesEvent event) { + boolean shouldBeValidated; + try { + shouldBeValidated = STND_DEFINED_DOMAIN.equals(event.getDomain()) + && !event.getSchemaReference().isEmpty(); + } catch (JSONException e) { + shouldBeValidated = false; + } + return shouldBeValidated; + } +} diff --git a/src/main/java/org/onap/dcae/common/validator/StndDefinedValidatorResolver.java b/src/main/java/org/onap/dcae/common/validator/StndDefinedValidatorResolver.java new file mode 100644 index 00000000..3f06d0ae --- /dev/null +++ b/src/main/java/org/onap/dcae/common/validator/StndDefinedValidatorResolver.java @@ -0,0 +1,53 @@ +/* + * ============LICENSE_START======================================================= + * VES + * ================================================================================ + * Copyright (C) 2020 Nokia. 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.dcae.common.validator; + +import org.onap.dcae.ApplicationSettings; +import org.onap.dcaegen2.services.sdk.services.external.schema.manager.service.StndDefinedValidator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class StndDefinedValidatorResolver { + + private final ApplicationSettings settings; + + @Autowired + public StndDefinedValidatorResolver(ApplicationSettings settings) { + this.settings = settings; + } + + /** + * Creates StndDefinedValidator using settings defined in collector.properties + * + * @return StndDefinedValidator object for validation of configured fields of event + */ + public StndDefinedValidator resolve() { + return new StndDefinedValidator.ValidatorBuilder() + .mappingFilePath(settings.getExternalSchemaMappingFileLocation()) + .schemaRefPath(settings.getExternalSchemaSchemaRefPath()) + .schemasPath(settings.getExternalSchemaSchemasLocation()) + .stndDefinedDataPath(settings.getExternalSchemaStndDefinedDataPath()) + .build(); + } +} + + diff --git a/src/main/java/org/onap/dcae/restapi/ApiException.java b/src/main/java/org/onap/dcae/restapi/ApiException.java index 9ea02076..dbd41a4d 100644 --- a/src/main/java/org/onap/dcae/restapi/ApiException.java +++ b/src/main/java/org/onap/dcae/restapi/ApiException.java @@ -37,7 +37,11 @@ public enum ApiException { INVALID_CUSTOM_HEADER(ExceptionType.SERVICE_EXCEPTION, "SVC0002", "Bad Parameter (Incorrect request api version)", 400), MISSING_NAMESPACE_PARAMETER(ExceptionType.SERVICE_EXCEPTION, "SVC2006", "Mandatory input %1 %2 is missing from request", List.of("attribute", "event.commonEventHeader.stndDefinedNamespace"), 400), EMPTY_NAMESPACE_PARAMETER(ExceptionType.SERVICE_EXCEPTION, "SVC2006", "Mandatory input %1 %2 is empty in request", List.of("attribute", "event.commonEventHeader.stndDefinedNamespace"), 400), - NO_SERVER_RESOURCES(ExceptionType.SERVICE_EXCEPTION, "SVC1000", "No server resources (internal processing queue full)", 503); + NO_SERVER_RESOURCES(ExceptionType.SERVICE_EXCEPTION, "SVC1000", "No server resources (internal processing queue full)", 503), + STND_DEFINED_VALIDATION_FAILED(ExceptionType.SERVICE_EXCEPTION, "SVC2000", "The following service error occurred: %1. Error code is %2", List.of("event.stndDefinedFields.data invalid against event.stndDefinedFields.schemaReference", "400"), 400), + NO_LOCAL_SCHEMA_REFERENCE(ExceptionType.SERVICE_EXCEPTION, "SVC2004", "Invalid input value for %1 %2: %3", List.of("attribute", "event.stndDefinedFields.schemaReference", "Referred external schema not present in schema repository"), 400), + INCORRECT_INTERNAL_FILE_REFERENCE(ExceptionType.SERVICE_EXCEPTION, "SVC2000", "The following service error occurred: %1. Error code is %2", List.of("event.stndDefinedFields.schemaReference value does not correspond to any external event schema file in externalSchema repo", "400"), 400); + public final int httpStatusCode; private final ExceptionType type; diff --git a/src/main/java/org/onap/dcae/restapi/EventValidator.java b/src/main/java/org/onap/dcae/restapi/EventValidator.java deleted file mode 100644 index 0eb0967a..00000000 --- a/src/main/java/org/onap/dcae/restapi/EventValidator.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * Copyright (C) 2020 Nokia. 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.dcae.restapi; - -import com.networknt.schema.JsonSchema; -import org.onap.dcae.ApplicationSettings; -import org.onap.dcae.common.model.VesEvent; - -/** - * This class is using ApplicationSetting and SchemaValidator to validate VES event. - * - * @author Zebek - */ -public class EventValidator { - - private final SchemaValidator schemaValidator; - private final ApplicationSettings applicationSettings; - - public EventValidator(ApplicationSettings applicationSettings) { - this(applicationSettings, new SchemaValidator()); - } - - EventValidator(ApplicationSettings applicationSettings, SchemaValidator schemaValidator) { - this.applicationSettings = applicationSettings; - this.schemaValidator = schemaValidator; - } - - /** - * This method is validating given event using schema adn throws exception if event is not valid - * - * @param vesEvent event that will be validate - * @param type expected type of event - * @param version json schema version that will be used - * @throws EventValidatorException when event is not valid or have wrong type - */ - public void validate(VesEvent vesEvent, String type, String version) throws EventValidatorException { - if (applicationSettings.eventSchemaValidationEnabled()) { - doValidation(vesEvent, type, version); - } - } - - private void doValidation(VesEvent vesEvent, String type, String version) throws EventValidatorException { - if (vesEvent.hasType(type)) { - if (!isEventMatchToSchema(vesEvent, applicationSettings.jsonSchema(version))) { - throw new EventValidatorException(ApiException.SCHEMA_VALIDATION_FAILED); - } - } else { - throw new EventValidatorException(ApiException.INVALID_JSON_INPUT); - } - } - - private boolean isEventMatchToSchema(VesEvent vesEvent, JsonSchema schema) { - return schemaValidator.conformsToSchema(vesEvent.asJsonObject(), schema); - } -} diff --git a/src/main/java/org/onap/dcae/restapi/EventValidatorException.java b/src/main/java/org/onap/dcae/restapi/EventValidatorException.java index 65ad457f..380694d1 100644 --- a/src/main/java/org/onap/dcae/restapi/EventValidatorException.java +++ b/src/main/java/org/onap/dcae/restapi/EventValidatorException.java @@ -19,7 +19,7 @@ */ package org.onap.dcae.restapi; -public class EventValidatorException extends Exception { +public class EventValidatorException extends RuntimeException { private final ApiException apiException; public EventValidatorException(ApiException apiException) { diff --git a/src/main/java/org/onap/dcae/restapi/VesRestController.java b/src/main/java/org/onap/dcae/restapi/VesRestController.java index f6dde6d2..de0392e6 100644 --- a/src/main/java/org/onap/dcae/restapi/VesRestController.java +++ b/src/main/java/org/onap/dcae/restapi/VesRestController.java @@ -29,6 +29,8 @@ import org.onap.dcae.ApplicationSettings; import org.onap.dcae.common.EventSender; import org.onap.dcae.common.EventUpdater; import org.onap.dcae.common.HeaderUtils; +import org.onap.dcae.common.validator.GeneralEventValidator; +import org.onap.dcae.common.validator.StndDefinedDataValidator; import org.onap.dcae.common.VESLogger; import org.onap.dcae.common.model.StndDefinedNamespaceParameterHasEmptyValueException; import org.onap.dcae.common.model.StndDefinedNamespaceParameterNotDefinedException; @@ -61,18 +63,20 @@ public class VesRestController { private final Logger requestLogger; private EventSender eventSender; private final HeaderUtils headerUtils; - private final EventValidator eventValidator; + private final GeneralEventValidator generalEventValidator; private final EventUpdater eventUpdater; + private final StndDefinedDataValidator stndDefinedValidator; - @Autowired - VesRestController(ApplicationSettings settings, - @Qualifier("incomingRequestsLogger") Logger incomingRequestsLogger, - @Qualifier("eventSender") EventSender eventSender, HeaderUtils headerUtils) { + @Autowired + VesRestController(ApplicationSettings settings, @Qualifier("incomingRequestsLogger") Logger incomingRequestsLogger, + @Qualifier("eventSender") EventSender eventSender, HeaderUtils headerUtils, + StndDefinedDataValidator stndDefinedDataValidator) { this.settings = settings; this.requestLogger = incomingRequestsLogger; this.eventSender = eventSender; this.headerUtils = headerUtils; - this.eventValidator = new EventValidator(settings); + this.stndDefinedValidator = stndDefinedDataValidator; + this.generalEventValidator = new GeneralEventValidator(settings); this.eventUpdater = new EventUpdater(settings); } @@ -84,7 +88,6 @@ public class VesRestController { return badRequest().contentType(MediaType.APPLICATION_JSON).body(String.format("API version %s is not supported", version)); } - @PostMapping(value = {"/eventListener/{version}/eventBatch"}, consumes = "application/json") ResponseEntity<String> events(@RequestBody String events, @PathVariable String version, HttpServletRequest request) { if (settings.isVersionSupported(version)) { @@ -100,13 +103,14 @@ public class VesRestController { final String requestURI = request.getRequestURI(); return handleEvent(vesEvent, version, type, headerUtils, requestURI); } - return badRequest().body(String.format(ApiException.INVALID_CUSTOM_HEADER.toString())); + return badRequest().body(ApiException.INVALID_CUSTOM_HEADER.toString()); } private ResponseEntity<String> handleEvent(VesEvent vesEvent, String version, String type, CustomHeaderUtils headerUtils, String requestURI) { try { - eventValidator.validate(vesEvent, type, version); + generalEventValidator.validate(vesEvent, type, version); List<VesEvent> vesEvents = transformEvent(vesEvent, type, version, requestURI); + executeStndDefinedValidation(vesEvents); eventSender.send(vesEvents); } catch (EventValidatorException e) { return ResponseEntity.status(e.getApiException().httpStatusCode) @@ -124,6 +128,12 @@ public class VesRestController { .contentType(MediaType.APPLICATION_JSON).body("Accepted"); } + private void executeStndDefinedValidation(List<VesEvent> vesEvents) { + if (settings.getExternalSchemaValidationCheckflag()) { + vesEvents.forEach(stndDefinedValidator::validate); + } + } + private CustomHeaderUtils createHeaderUtils(String version, HttpServletRequest request) { return new CustomHeaderUtils(version.toLowerCase().replace("v", ""), headerUtils.extractHeaders(request), @@ -133,8 +143,7 @@ public class VesRestController { } private List<VesEvent> transformEvent(VesEvent vesEvent, String type, String version, String requestURI) { - return this.eventUpdater.convert( - vesEvent, version, generateUUID(vesEvent, version, requestURI), type); + return this.eventUpdater.convert(vesEvent, version, generateUUID(vesEvent, version, requestURI), type); } private UUID generateUUID(VesEvent vesEvent, String version, String uri) { @@ -148,4 +157,4 @@ public class VesRestController { LoggingContext localLC = VESLogger.getLoggingContextForThread(uuid); localLC.put(EcompFields.kBeginTimestampMs, SaClock.now()); } -} +}
\ No newline at end of file diff --git a/src/test/java/org/onap/dcae/ApplicationSettingsTest.java b/src/test/java/org/onap/dcae/ApplicationSettingsTest.java index 6560b1ce..6ea94ab5 100644 --- a/src/test/java/org/onap/dcae/ApplicationSettingsTest.java +++ b/src/test/java/org/onap/dcae/ApplicationSettingsTest.java @@ -21,20 +21,13 @@ package org.onap.dcae; -import static java.util.Collections.singletonList; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.onap.dcae.CLIUtils.processCmdLine; -import static org.onap.dcae.TestingUtilities.createTemporaryFile; - import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.networknt.schema.JsonSchema; import io.vavr.collection.HashMap; import io.vavr.collection.Map; +import org.junit.Test; + import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -42,7 +35,15 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.Objects; -import org.junit.Test; + +import static java.util.Collections.singletonList; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.onap.dcae.CLIUtils.processCmdLine; +import static org.onap.dcae.TestingUtilities.createTemporaryFile; public class ApplicationSettingsTest { @@ -70,7 +71,7 @@ public class ApplicationSettingsTest { @Test public void shouldMakeApplicationSettingsOutOfCLIArgumentsAndAConfigurationFile() - throws IOException { + throws IOException { // given File tempConfFile = File.createTempFile("doesNotMatter", "doesNotMatter"); Files.write(tempConfFile.toPath(), Arrays.asList("section.subSection1=abc", "section.subSection2=zxc")); @@ -111,7 +112,7 @@ public class ApplicationSettingsTest { public void shouldReturnHTTPPort() throws IOException { // when int applicationPort = fromTemporaryConfiguration("collector.service.port=8090") - .httpPort(); + .httpPort(); // then assertEquals(8090, applicationPort); @@ -130,7 +131,7 @@ public class ApplicationSettingsTest { public void shouldReturnIfHTTPSIsEnabled() throws IOException { // when boolean httpsEnabled = fromTemporaryConfiguration("collector.service.secure.port=8443") - .httpsEnabled(); + .httpsEnabled(); // then assertTrue(httpsEnabled); @@ -157,7 +158,7 @@ public class ApplicationSettingsTest { public void shouldReturnHTTPSPort() throws IOException { // when int httpsPort = fromTemporaryConfiguration("collector.service.secure.port=8443") - .httpsPort(); + .httpsPort(); // then assertEquals(8443, httpsPort); @@ -167,7 +168,7 @@ public class ApplicationSettingsTest { public void shouldReturnConfigurationUpdateInterval() throws IOException { // when int updateFrequency = fromTemporaryConfiguration("collector.dynamic.config.update.frequency=10") - .configurationUpdateFrequency(); + .configurationUpdateFrequency(); // then assertEquals(10, updateFrequency); @@ -177,7 +178,7 @@ public class ApplicationSettingsTest { public void shouldReturnDefaultConfigurationUpdateInterval() throws IOException { // when int updateFrequency = fromTemporaryConfiguration() - .configurationUpdateFrequency(); + .configurationUpdateFrequency(); // then assertEquals(5, updateFrequency); @@ -187,7 +188,7 @@ public class ApplicationSettingsTest { public void shouldReturnLocationOfThePasswordFile() throws IOException { // when String passwordFileLocation = fromTemporaryConfiguration("collector.keystore.passwordfile=/somewhere/password") - .keystorePasswordFileLocation(); + .keystorePasswordFileLocation(); // then assertEquals(sanitizePath("/somewhere/password"), passwordFileLocation); @@ -206,7 +207,7 @@ public class ApplicationSettingsTest { public void shouldReturnLocationOfTheKeystoreFile() throws IOException { // when String keystoreFileLocation = fromTemporaryConfiguration("collector.keystore.file.location=/somewhere/keystore") - .keystoreFileLocation(); + .keystoreFileLocation(); // then assertEquals(sanitizePath("/somewhere/keystore"), keystoreFileLocation); @@ -225,7 +226,7 @@ public class ApplicationSettingsTest { public void shouldReturnDMAAPConfigFileLocation() throws IOException { // when String dmaapConfigFileLocation = fromTemporaryConfiguration("collector.dmaapfile=/somewhere/dmaapFile") - .dMaaPConfigurationFileLocation(); + .dMaaPConfigurationFileLocation(); // then assertEquals(sanitizePath("/somewhere/dmaapFile"), dmaapConfigFileLocation); @@ -244,7 +245,7 @@ public class ApplicationSettingsTest { public void shouldTellIfSchemaValidationIsEnabled() throws IOException { // when boolean jsonSchemaValidationEnabled = fromTemporaryConfiguration("collector.schema.checkflag=1") - .eventSchemaValidationEnabled(); + .eventSchemaValidationEnabled(); // then assertTrue(jsonSchemaValidationEnabled); @@ -266,8 +267,8 @@ public class ApplicationSettingsTest { // when JsonSchema schema = fromTemporaryConfiguration( - String.format("collector.schema.file={\"v1\": \"%s\"}", temporarySchemaFile)) - .jsonSchema("v1"); + String.format("collector.schema.file={\"v1\": \"%s\"}", temporarySchemaFile)) + .jsonSchema("v1"); // then JsonNode incorrectTestObject = new ObjectMapper().readTree("{ \"state\": 1 }"); @@ -295,7 +296,7 @@ public class ApplicationSettingsTest { public void shouldReturnExceptionConfigFileLocation() throws IOException { // when String exceptionConfigFileLocation = fromTemporaryConfiguration("exceptionConfig=/somewhere/exceptionFile") - .exceptionConfigFileLocation(); + .exceptionConfigFileLocation(); // then assertEquals("/somewhere/exceptionFile", exceptionConfigFileLocation); @@ -315,14 +316,14 @@ public class ApplicationSettingsTest { public void shouldReturnDMAAPStreamId() throws IOException { // given Map<String, String[]> expected = HashMap.of( - "log", new String[]{"ves-syslog", "ves-auditlog"}, - "fault", new String[]{"ves-fault"} + "log", new String[]{"ves-syslog", "ves-auditlog"}, + "fault", new String[]{"ves-fault"} ); // when Map<String, String[]> dmaapStreamID = fromTemporaryConfiguration( - "collector.dmaap.streamid=fault=ves-fault|log=ves-syslog,ves-auditlog") - .getDmaapStreamIds(); + "collector.dmaap.streamid=fault=ves-fault|log=ves-syslog,ves-auditlog") + .getDmaapStreamIds(); // then assertArrayEquals(expected.get("log").get(), Objects.requireNonNull(dmaapStreamID).get("log").get()); @@ -352,11 +353,11 @@ public class ApplicationSettingsTest { public void shouldReturnValidCredentials() throws IOException { // when Map<String, String> allowedUsers = fromTemporaryConfiguration( - "header.authlist=pasza,c2ltcGxlcGFzc3dvcmQNCg==|someoneelse,c2ltcGxlcGFzc3dvcmQNCg==" + "header.authlist=pasza,c2ltcGxlcGFzc3dvcmQNCg==|someoneelse,c2ltcGxlcGFzc3dvcmQNCg==" ).validAuthorizationCredentials(); // then - assertEquals( "c2ltcGxlcGFzc3dvcmQNCg==", allowedUsers.get("pasza").get()); + assertEquals("c2ltcGxlcGFzc3dvcmQNCg==", allowedUsers.get("pasza").get()); assertEquals("c2ltcGxlcGFzc3dvcmQNCg==", allowedUsers.get("someoneelse").get()); } @@ -364,7 +365,7 @@ public class ApplicationSettingsTest { public void shouldbyDefaultThereShouldBeNoValidCredentials() throws IOException { // when Map<String, String> userToBase64PasswordDelimitedByCommaSeparatedByPipes = fromTemporaryConfiguration(). - validAuthorizationCredentials(); + validAuthorizationCredentials(); // then assertTrue(userToBase64PasswordDelimitedByCommaSeparatedByPipes.isEmpty()); @@ -374,7 +375,7 @@ public class ApplicationSettingsTest { public void shouldReturnIfEventTransformingIsEnabled() throws IOException { // when boolean isEventTransformingEnabled = fromTemporaryConfiguration("event.transform.flag=0") - .eventTransformingEnabled(); + .eventTransformingEnabled(); // then assertFalse(isEventTransformingEnabled); @@ -393,8 +394,8 @@ public class ApplicationSettingsTest { public void shouldReturnCambriaConfigurationFileLocation() throws IOException { // when String cambriaConfigurationFileLocation = fromTemporaryConfiguration( - "collector.dmaapfile=/somewhere/dmaapConfig") - .dMaaPConfigurationFileLocation(); + "collector.dmaapfile=/somewhere/dmaapConfig") + .dMaaPConfigurationFileLocation(); // then assertEquals(sanitizePath("/somewhere/dmaapConfig"), cambriaConfigurationFileLocation); @@ -404,14 +405,64 @@ public class ApplicationSettingsTest { public void shouldReturnDefaultCambriaConfigurationFileLocation() throws IOException { // when String cambriaConfigurationFileLocation = fromTemporaryConfiguration() - .dMaaPConfigurationFileLocation(); + .dMaaPConfigurationFileLocation(); // then assertEquals(sanitizePath("etc/DmaapConfig.json"), cambriaConfigurationFileLocation); } + @Test + public void shouldReturnDefaultExternalSchemaSchemasLocation() throws IOException { + //when + String externalSchemaSchemasLocation = fromTemporaryConfiguration() + .getExternalSchemaSchemasLocation(); + + //then + assertEquals(sanitizePath("./etc/externalRepo"), externalSchemaSchemasLocation); + } + + @Test + public void shouldReturnDefaultExternalSchemaMappingFileLocation() throws IOException { + //when + String externalSchemaMappingFileLocation = fromTemporaryConfiguration() + .getExternalSchemaMappingFileLocation(); + + //then + assertEquals(sanitizePath("./etc/externalRepo/schema-map.json"), externalSchemaMappingFileLocation); + } + + @Test + public void shouldReturnDefaultExternalSchemaSchemaRefPath() throws IOException { + //when + String externalSchemaSchemaRefPath = fromTemporaryConfiguration() + .getExternalSchemaSchemaRefPath(); + + //then + assertEquals(sanitizePath("/event/stndDefinedFields/schemaReference"), externalSchemaSchemaRefPath); + } + + @Test + public void shouldReturnDefaultExternalSchemaStndDefinedDataPath() throws IOException { + //when + String externalSchemaStndDefinedDataPath = fromTemporaryConfiguration() + .getExternalSchemaStndDefinedDataPath(); + + //then + assertEquals(sanitizePath("/event/stndDefinedFields/data"), externalSchemaStndDefinedDataPath); + } + + @Test + public void shouldReturnEnabledExternalSchema2ndStageValidation() throws IOException { + //when + boolean externalSchema2ndStageValidation = fromTemporaryConfiguration("collector.externalSchema.2ndStageValidation=-1") + .getExternalSchemaValidationCheckflag(); + + //then + assertFalse(externalSchema2ndStageValidation); + } + private static ApplicationSettings fromTemporaryConfiguration(String... fileLines) - throws IOException { + throws IOException { File tempConfFile = File.createTempFile("doesNotMatter", "doesNotMatter"); Files.write(tempConfFile.toPath(), Arrays.asList(fileLines)); tempConfFile.deleteOnExit(); diff --git a/src/test/java/org/onap/dcae/TLSTest.java b/src/test/java/org/onap/dcae/TLSTest.java index e55b6052..424ddf8b 100644 --- a/src/test/java/org/onap/dcae/TLSTest.java +++ b/src/test/java/org/onap/dcae/TLSTest.java @@ -37,6 +37,11 @@ import static org.onap.dcae.TLSTest.HttpsConfigurationWithTLSAuthenticationAndBa public class TLSTest extends TLSTestBase { + private static final String MAPPING_FILE_LOCATION = "./etc/externalRepo/schema-map.json"; + private static final String SCHEMA_FILES_LOCATION = "./etc/externalRepo"; + private static final String STND_DEFINED_DATA_PATH = "/event/stndDefinedFields/data"; + private static final String SCHEMA_REF_PATH = "/event/stndDefinedFields/schemaReference"; + @Nested @Import(HttpConfiguration.class) class HttpTest extends TestClassBase { @@ -69,10 +74,16 @@ public class TLSTest extends TLSTestBase { // ApplicationSettings configurations static class HttpConfiguration extends TLSTestBase.ConfigurationBase { + @Override protected void configureSettings(ApplicationSettings settings) { when(settings.authMethod()).thenReturn(AuthMethodType.NO_AUTH.value()); when(settings.httpPort()).thenReturn(1111); + when(settings.getExternalSchemaMappingFileLocation()).thenReturn(MAPPING_FILE_LOCATION); + when(settings.getExternalSchemaSchemasLocation()).thenReturn(SCHEMA_FILES_LOCATION); + when(settings.getExternalSchemaSchemaRefPath()).thenReturn(SCHEMA_REF_PATH); + when(settings.getExternalSchemaStndDefinedDataPath()).thenReturn(STND_DEFINED_DATA_PATH); + } } @@ -89,6 +100,10 @@ public class TLSTest extends TLSTestBase { when(settings.truststorePasswordFileLocation()).thenReturn(TRUSTSTORE_PASSWORD_FILE.toString()); when(settings.certSubjectMatcher()).thenReturn(CERT_SUBJECT_MATCHER.toString()); when(settings.httpPort()).thenReturn(1111); + when(settings.getExternalSchemaMappingFileLocation()).thenReturn(MAPPING_FILE_LOCATION); + when(settings.getExternalSchemaSchemasLocation()).thenReturn(SCHEMA_FILES_LOCATION); + when(settings.getExternalSchemaSchemaRefPath()).thenReturn(SCHEMA_REF_PATH); + when(settings.getExternalSchemaStndDefinedDataPath()).thenReturn(STND_DEFINED_DATA_PATH); } } }
\ No newline at end of file diff --git a/src/test/java/org/onap/dcae/restapi/EventValidatorTest.java b/src/test/java/org/onap/dcae/common/validator/GeneralEventValidatorTest.java index 0ca5c424..e5e21177 100644 --- a/src/test/java/org/onap/dcae/restapi/EventValidatorTest.java +++ b/src/test/java/org/onap/dcae/common/validator/GeneralEventValidatorTest.java @@ -18,31 +18,34 @@ * ============LICENSE_END========================================================= */ -package org.onap.dcae.restapi; +package org.onap.dcae.common.validator; import com.networknt.schema.JsonSchema; import com.networknt.schema.JsonSchemaFactory; import org.json.JSONObject; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.onap.dcae.ApplicationSettings; import org.onap.dcae.FileReader; import org.onap.dcae.common.model.VesEvent; +import org.onap.dcae.restapi.ApiException; +import org.onap.dcae.restapi.EventValidatorException; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) -class EventValidatorTest { +class GeneralEventValidatorTest { private static final String DUMMY_SCHEMA_VERSION = "v5"; private static final String DUMMY_TYPE = "type"; private final String newSchemaV7 = FileReader.readFileAsString("etc/CommonEventFormat_30.2_ONAP.json"); @@ -54,9 +57,9 @@ class EventValidatorTest { @Mock private ApplicationSettings settings; - private SchemaValidator schemaValidator = spy( new SchemaValidator()); + private SchemaValidator schemaValidator = Mockito.spy( new SchemaValidator()); - private EventValidator sut; + private GeneralEventValidator sut; @BeforeAll @@ -66,7 +69,7 @@ class EventValidatorTest { @BeforeEach public void setUp(){ - this.sut = new EventValidator(settings, schemaValidator); + this.sut = new GeneralEventValidator(settings, schemaValidator); } @Test @@ -92,7 +95,7 @@ class EventValidatorTest { sut.validate(new VesEvent(jsonObject), "wrongType", DUMMY_SCHEMA_VERSION); } catch (EventValidatorException e) { //then - assertEquals(ApiException.INVALID_JSON_INPUT, e.getApiException()); + Assertions.assertEquals(ApiException.INVALID_JSON_INPUT, e.getApiException()); } @@ -149,7 +152,7 @@ class EventValidatorTest { @Test void shouldReturnNoErrorsWhenValidatingValidEventWithStndDefinedFields() { //given - sentEvent = new JSONObject(FileReader.readFileAsString("src/test/resources/ves7_valid_eventWithStndDefinedFields.json")); + sentEvent = new JSONObject(FileReader.readFileAsString("src/test/resources/ves_stdnDefined_valid.json")); mockJsonSchema(newSchemaV7); when(settings.eventSchemaValidationEnabled()).thenReturn(true); @@ -191,4 +194,4 @@ class EventValidatorTest { JsonSchema schema = factory.getSchema(jsonSchemaContent); when(settings.jsonSchema(any())).thenReturn(schema); } -} +}
\ No newline at end of file diff --git a/src/test/java/org/onap/dcae/common/validator/StndDefinedDataValidatorTest.java b/src/test/java/org/onap/dcae/common/validator/StndDefinedDataValidatorTest.java new file mode 100644 index 00000000..1058b21f --- /dev/null +++ b/src/test/java/org/onap/dcae/common/validator/StndDefinedDataValidatorTest.java @@ -0,0 +1,149 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.ves + * ================================================================================ + * Copyright (C) 2020 Nokia. 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.dcae.common.validator; + +import org.jetbrains.annotations.NotNull; +import org.json.JSONObject; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.dcae.ApplicationSettings; +import org.onap.dcae.FileReader; +import org.onap.dcae.common.model.VesEvent; +import org.onap.dcae.restapi.ApiException; +import org.onap.dcae.restapi.EventValidatorException; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class StndDefinedDataValidatorTest { + + @Mock + private ApplicationSettings settings; + private StndDefinedDataValidator stndDefinedDataValidator; + + private static final String MAPPING_FILE_LOCATION = "./src/test/resources/stndDefined/schema-map.json"; + private static final String SCHEMA_FILES_LOCATION = "./src/test/resources/stndDefined"; + private static final String STND_DEFINED_DATA_PATH = "/event/stndDefinedFields/data"; + private static final String SCHEMA_REF_PATH = "/event/stndDefinedFields/schemaReference"; + + @BeforeEach + public void setUp() { + mockStndDefinedValidationProps(); + StndDefinedValidatorResolver stndDefinedValidatorResolver = new StndDefinedValidatorResolver(settings); + stndDefinedDataValidator = new StndDefinedDataValidator(stndDefinedValidatorResolver.resolve()); + } + + @Test + public void shouldReturnTrueWhenEventIsValid() throws EventValidatorException { + //given + VesEvent event = getVesEvent("src/test/resources/ves_stdnDefined_valid.json"); + + //when + //then + assertDoesNotThrow(() -> stndDefinedDataValidator.validate(event)); + } + + @Test + public void shouldReturnFalseWhenEventIsInvalid() throws EventValidatorException { + //given + VesEvent event = getVesEvent("src/test/resources/ves_stdnDefined_invalid.json"); + + try { + //when + stndDefinedDataValidator.validate(event); + } catch (EventValidatorException e) { + //then + assertEquals(ApiException.STND_DEFINED_VALIDATION_FAILED, e.getApiException()); + } + } + + @Test + void shouldReturnErrorWhenMissingLocalSchemaReferenceInMappingFile() { + //given + VesEvent event = getVesEvent("src/test/resources/ves_stdnDefined_missing_local_schema_reference.json"); + try { + //when + stndDefinedDataValidator.validate(event); + } catch (EventValidatorException e) { + //then + assertEquals(ApiException.NO_LOCAL_SCHEMA_REFERENCE, e.getApiException()); + } + } + + @Test + void shouldReturnErrorWhenIncorrectInternalFileReference() { + //given + VesEvent event = getVesEvent("src/test/resources/ves_stdnDefined_wrong_internal_file_reference.json"); + try { + //when + stndDefinedDataValidator.validate(event); + } catch (EventValidatorException e) { + //then + assertEquals(ApiException.INCORRECT_INTERNAL_FILE_REFERENCE, e.getApiException()); + } + } + + @Test + void shouldReturnErrorWhenStndDefinedFieldsDataIsEmpty() { + //given + VesEvent event = getVesEvent("src/test/resources/ves_stdnDefined_with_empty_stndDefined_fields_data.json"); + try { + //when + stndDefinedDataValidator.validate(event); + } catch (EventValidatorException e) { + //then + assertEquals(ApiException.STND_DEFINED_VALIDATION_FAILED, e.getApiException()); + } + } + + @Test + void shouldNotReturnErrorWhenValidatingInvalidEventAndStndDefinedReferenceMissing() { + //given + VesEvent event = getVesEvent("src/test/resources/ves_stdnDefined_without_schema_reference.json"); + + //when + //then + assertDoesNotThrow(() -> stndDefinedDataValidator.validate(event)); + } + + @NotNull + private VesEvent getVesEvent(String filename) { + JSONObject jsonObjectEvent = getJsonObjectEvent(filename); + return new VesEvent(jsonObjectEvent); + } + + private JSONObject getJsonObjectEvent(String fileName) { + String eventContent = FileReader.readFileAsString(fileName); + return new JSONObject(eventContent); + } + + private void mockStndDefinedValidationProps() { + when(settings.getExternalSchemaMappingFileLocation()).thenReturn(MAPPING_FILE_LOCATION); + when(settings.getExternalSchemaSchemaRefPath()).thenReturn(SCHEMA_REF_PATH); + when(settings.getExternalSchemaSchemasLocation()).thenReturn(SCHEMA_FILES_LOCATION); + when(settings.getExternalSchemaStndDefinedDataPath()).thenReturn(STND_DEFINED_DATA_PATH); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/dcae/common/validator/StndDefinedValidatorResolverTest.java b/src/test/java/org/onap/dcae/common/validator/StndDefinedValidatorResolverTest.java new file mode 100644 index 00000000..9cdfdcbd --- /dev/null +++ b/src/test/java/org/onap/dcae/common/validator/StndDefinedValidatorResolverTest.java @@ -0,0 +1,65 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.ves + * ================================================================================ + * Copyright (C) 2020 Nokia. 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.dcae.common.validator; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.dcae.ApplicationSettings; + +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class StndDefinedValidatorResolverTest { + + @Mock + private ApplicationSettings settings; + + private static final String MAPPING_FILE_LOCATION = "./src/test/resources/stndDefined/schema-map.json"; + private static final String SCHEMA_FILES_LOCATION = "./src/test/resources/stndDefined"; + private static final String STND_DEFINED_DATA_PATH = "/event/stndDefinedFields/data"; + private static final String SCHEMA_REF_PATH = "/event/stndDefinedFields/schemaReference"; + StndDefinedValidatorResolver stndDefinedValidatorResolver; + + @BeforeEach + public void setUp() { + mockStndDefinedValidationProps(); + stndDefinedValidatorResolver = new StndDefinedValidatorResolver(settings); + } + + @Test + public void shouldReturnStndValidatorWithDefaultSchemaConfigurations() { + //then + Assertions.assertDoesNotThrow(() -> stndDefinedValidatorResolver.resolve()); + } + + private void mockStndDefinedValidationProps() { + when(settings.getExternalSchemaMappingFileLocation()).thenReturn(MAPPING_FILE_LOCATION); + when(settings.getExternalSchemaSchemaRefPath()).thenReturn(SCHEMA_REF_PATH); + when(settings.getExternalSchemaSchemasLocation()).thenReturn(SCHEMA_FILES_LOCATION); + when(settings.getExternalSchemaStndDefinedDataPath()).thenReturn(STND_DEFINED_DATA_PATH); + } + + +}
\ No newline at end of file diff --git a/src/test/java/org/onap/dcae/restapi/VesRestControllerTest.java b/src/test/java/org/onap/dcae/restapi/VesRestControllerTest.java index 10423053..765f2b43 100644 --- a/src/test/java/org/onap/dcae/restapi/VesRestControllerTest.java +++ b/src/test/java/org/onap/dcae/restapi/VesRestControllerTest.java @@ -40,6 +40,7 @@ import org.onap.dcae.common.EventSender; import org.onap.dcae.common.EventTransformation; import org.onap.dcae.common.HeaderUtils; import org.onap.dcae.common.JsonDataLoader; +import org.onap.dcae.common.validator.StndDefinedDataValidator; import org.onap.dcae.common.publishing.EventPublisher; import org.slf4j.Logger; import org.springframework.http.ResponseEntity; @@ -85,16 +86,17 @@ public class VesRestControllerTest { @Mock private EventPublisher eventPublisher; + @Mock + private StndDefinedDataValidator stndDefinedDataValidator; + @Before public void setUp(){ - final HashMap<String, String[]> streamIds = HashMap.of( "fault", new String[]{VES_FAULT_TOPIC}, "3GPP-FaultSupervision", new String[]{VES_3_GPP_FAULT_SUPERVISION_TOPIC} ); - this.vesRestController = new VesRestController( - applicationSettings, logger, new EventSender(eventPublisher, streamIds),headerUtils - ); + this.vesRestController = new VesRestController(applicationSettings, logger, + new EventSender(eventPublisher, streamIds), headerUtils, stndDefinedDataValidator); } @Test @@ -229,7 +231,6 @@ public class VesRestControllerTest { configureHeadersForEventListener(); MockHttpServletRequest request = givenMockHttpServletRequest(); - String validEvent = JsonDataLoader.loadContent("/ves_stdnDefined_valid_unknown_topic.json"); //when @@ -241,6 +242,44 @@ public class VesRestControllerTest { verifyThatEventWasNotSend(); } + @Test + public void shouldExecuteStndDefinedValidationWhenFlagIsOnTrue() throws IOException { + //given + configureEventTransformations(); + configureHeadersForEventListener(); + + MockHttpServletRequest request = givenMockHttpServletRequest(); + String validEvent = JsonDataLoader.loadContent("/ves7_batch_with_stndDefined_valid.json"); + when(applicationSettings.getExternalSchemaValidationCheckflag()).thenReturn(true); + + //when + final ResponseEntity<String> response = vesRestController.events(validEvent, VERSION_V7, request); + + //then + assertThat(response.getStatusCodeValue()).isEqualTo(HttpStatus.SC_ACCEPTED); + assertThat(response.getBody()).isEqualTo(ACCEPTED); + verify(stndDefinedDataValidator, times(2)).validate(any()); + } + + @Test + public void shouldNotExecuteStndDefinedValidationWhenFlagIsOnFalse() throws IOException { + //given + configureEventTransformations(); + configureHeadersForEventListener(); + + MockHttpServletRequest request = givenMockHttpServletRequest(); + String validEvent = JsonDataLoader.loadContent("/ves7_batch_with_stndDefined_valid.json"); + when(applicationSettings.getExternalSchemaValidationCheckflag()).thenReturn(false); + + //when + final ResponseEntity<String> response = vesRestController.events(validEvent, VERSION_V7, request); + + //then + assertThat(response.getStatusCodeValue()).isEqualTo(HttpStatus.SC_ACCEPTED); + assertThat(response.getBody()).isEqualTo(ACCEPTED); + verify(stndDefinedDataValidator, times(0)).validate(any()); + } + private void verifyThatEventWasNotSend() { verify(eventPublisher, never()).sendEvent(any(), any()); } diff --git a/src/test/resources/stndDefined/OpenAPI_faultMnS.yaml b/src/test/resources/stndDefined/OpenAPI_faultMnS.yaml new file mode 100644 index 00000000..499123b9 --- /dev/null +++ b/src/test/resources/stndDefined/OpenAPI_faultMnS.yaml @@ -0,0 +1,1144 @@ +openapi: 3.0.1 +info: + title: Fault Supervision MnS + version: 16.4.0 + description: >- + OAS 3.0.1 definition of the Fault Supervision MnS + © 2020, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). + All rights reserved. +externalDocs: + description: 3GPP TS 28.532 V16.4.0; Generic management services + url: http://www.3gpp.org/ftp/Specs/archive/28_series/28.532/ +servers: + - url: '{MnSRoot}/FaultSupervisionMnS/{version}' + variables: + MnSRoot: + description: See subclause 4.4.3 of TS 32.158 + default: http://example.com/3GPPManagement + version: + description: Versi on number of the OpenAPI definition + default: XXX +paths: + /alarms: + get: + summary: Retrieve multiple alarms + description: >- + Retrieves the alarms identified by alarmAckState, baseObjectInstance + and filter. + parameters: + - name: alarmAckState + in: query + required: false + schema: + $ref: '#/components/schemas/AlarmAckState' + - name: baseObjectInstance + in: query + required: false + schema: + $ref: '#/components/schemas/Dn' + - name: filter + in: query + required: false + schema: + $ref: '#/components/schemas/Filter' + responses: + '200': + description: >- + Success case ("200 OK"). + Returns the alarms identified in the request. The alarmId is the key + of the map. + content: + application/json: + schema: + type: object + additionalProperties: + type: object + allOf: + - type: object + properties: + lastNotificationHeader: + $ref: '#/components/schemas/NotificationHeader' + - $ref: '#/components/schemas/AlarmRecord' + - type: object + properties: + comments: + $ref: '#/components/schemas/Comments' + default: + description: Response in case of error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + patch: + summary: 'Clear, acknowledge or unacknowledge multiple alarms' + description: >- + Clears, acknowledges or unacknowledges multiple alarms using patch. Depending + on which action is to be performed, different merge patch documents need + to be used. + requestBody: + description: >- + Patch documents for acknowledging and unacknowledging, or clearing multiple + alarms. The keys in the map are the alarmIds to be patched. + content: + application/merge-patch+json: + schema: + oneOf: + - type: object + additionalProperties: + $ref: '#/components/schemas/MergePatchAcknowledgeAlarm' + - type: object + additionalProperties: + $ref: '#/components/schemas/MergePatchClearAlarm' + responses: + '204': + description: >- + Success case ("204 No content"). + The response message body is empty. + default: + description: Response in case of error. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/FailedAlarm' + /alarms/alarmCount: + get: + summary: Get the alarm count per perceived severity + parameters: + - name: alarmAckState + in: query + required: false + schema: + $ref: '#/components/schemas/AlarmAckState' + - name: filter + in: query + required: false + schema: + type: string + responses: + '200': + description: >- + Success case ("200 OK"). + The alarm count per perceived severity is returned. + content: + application/json: + schema: + $ref: '#/components/schemas/AlarmCount' + default: + description: Response in case of error. The error case needs rework. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /alarms/{alarmId}: + patch: + summary: 'Clear, acknowledge or unacknowledge a single alarm' + description: >- + Clears, acknowledges or uncknowldeges a single alarm by patching the alarm + information. A conditional acknowledge request based on the perceived + severity is not supported. + parameters: + - name: alarmId + in: path + description: Identifies the alarm to be patched. + required: true + schema: + type: string + requestBody: + required: true + content: + application/merge-patch+json: + schema: + oneOf: + - $ref: '#/components/schemas/MergePatchAcknowledgeAlarm' + - $ref: '#/components/schemas/MergePatchClearAlarm' + responses: + '204': + description: >- + Success case (204 No content). + The response message body is absent. + default: + description: Response in case of error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /alarms/{alarmId}/comments: + post: + summary: Add a comment to a single alarm + description: >- + Adds a comment to an alarm identified by alarmId. The id of the new comment + is allocated by the producer. + parameters: + - name: alarmId + in: path + description: Identifies the alarm to which the comment shall be added. + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Comment' + responses: + '201': + description: >- + Success case (201 Created). + The representation of the newly created comment resource shall be returned. + content: + application/json: + schema: + $ref: '#/components/schemas/Comment' + headers: + Location: + description: URI of the newly created comment resource. + required: true + schema: + type: string + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /subscriptions: + post: + summary: Create a subscription + description: >- + To create a subscription the representation of the subscription is + POSTed on the /subscriptions collection resource. + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Subscription' + responses: + '201': + description: >- + Success case ("201 Created"). + The representation of the newly created subscription resource shall + be returned. + content: + application/json: + schema: + $ref: '#/components/schemas/Subscription' + headers: + Location: + description: URI of the newly created subscription resource + required: true + schema: + type: string + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + callbacks: + notifyNewAlarm: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/NotifyNewAlarm' + - $ref: '#/components/schemas/NotifyNewSecAlarm' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyClearedAlarm: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotifyClearedAlarm' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyChangedAlarm: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotifyChangedAlarm' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyChangedAlarmGeneral: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/NotifyChangedAlarmGeneral' + - $ref: '#/components/schemas/NotifyChangedSecAlarmGeneral' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyCorrelatedNotificationChanged: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotifyCorrelatedNotificationChanged' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyAckStateChanged: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotifyAckStateChanged' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyComments: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotifyComments' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyPotentialFaultyAlarmList: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotifyPotentialFaultyAlarmList' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + notifyAlarmListRebuilt: + '{request.body#/consumerReference}': + post: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NotifyAlarmListRebuilt' + responses: + '204': + description: >- + Success case ("204 No Content"). + The notification is successfully delivered. The response message + body is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /subscriptions/{subscriptionId}: + delete: + summary: Delete a subscription + description: >- + The subscription is deleted by deleting the corresponding subscription + resource. The resource to be deleted is identified with the path + component of the URI. + parameters: + - name: subscriptionId + in: path + description: Identifies the subscription to be deleted. + required: true + schema: + type: string + responses: + '204': + description: >- + Success case ("204 No Content"). + The subscription resource has been deleted. The response message body + is absent. + default: + description: Error case. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + + #---- Definitions to be moved to comDefs.yaml --------------------------------------# + + Long: + type: string + format: long + Float: + type: string + format: float + DateTime: + type: string + format: date-Time + + Dn: + type: string + Uri: + type: string + + AttributeNameValuePairSet: + type: object + minProperties: 1 + AttributeValueChangeSet: + description: >- + The key in this map is the attribute name. The value of each key is an array. + When only one item is present in the array, it carries the new attribute + value. If two items are present, then the first item carries the old value + and the second item the new value. The items can be of any type including null. + type: object + additionalProperties: + type: array + minItems: 1 + maxItems: 2 + items: + nullable: true + + Filter: + type: string + SystemDN: + type: string + + NotificationId: + type: integer + NotificationHeader: + description: >- + Header used for all notification types + type: object + required: + - href + - notificationId + - notificationType + - eventTime + - systemDN + properties: + uri: + $ref: '#/components/schemas/Uri' + notificationId: + $ref: '#/components/schemas/NotificationId' + notificationType: + oneOf: + - $ref: '#/components/schemas/AlarmNotificationTypes' + #- $ref: 'faultMnS.yaml#/components/schemas/AlarmNotificationTypes' + #- $ref: 'provMnS.yaml#/components/schemas/CmNotificationTypes' + # more to be added + eventTime: + $ref: '#/components/schemas/DateTime' + systemDN: + $ref: '#/components/schemas/SystemDN' + + ErrorResponse: + description: >- + Default schema for the response message body in case the request is not + successful. + type: object + properties: + error: + type: object + properties: + errorInfo: + type: string + + #---- End of definitions to be moved to comDefs.yaml -------------------------------# + + #---- Definition of AlarmRecord ----------------------------------------------------# + + AlarmId: + type: string + AlarmType: + type: string + enum: + - COMMUNICATIONS_ALARM + - QUALITY_OF_SERVICE_ALARM + - PROCESSING_ERROR_ALARM + - EQUIPMENT_ALARM + - ENVIRONMENTAL_ALARM + - INTEGRITY_VIOLATION + - OPERATIONAL_VIOLATION + - PHYSICAL_VIOLATION + - SECURITY_SERVICE_OR_MECHANISM_VIOLATION + - TIME_DOMAIN_VIOLATION + ProbableCause: + description: >- + The value of the probable cause may be a specific standardized string, or any + vendor provided string. Probable cause strings are not standardized in the + present document. They may be added in a future version. Up to then the + mapping of the generic probable cause strings "PROBABLE_CAUSE_001" to + "PROBABLE_CAUSE_005" is vendor specific. + The value of the probable cause may also be an integer. The mapping of integer + values to probable causes is vendor specific. + oneOf: + - anyOf: + - type: string + enum: + - PROBABLE_CAUSE_001 + - PROBABLE_CAUSE_002 + - PROBABLE_CAUSE_003 + - PROBABLE_CAUSE_004 + - PROBABLE_CAUSE_005 + - type: string + - type: integer + SpecificProblem: + oneOf: + - type: string + - type: integer + PerceivedSeverity: + type: string + enum: + - INDETERMINATE + - CRITICAL + - MAJOR + - MINOR + - WARNING + - CLEARED + TrendIndication: + type: string + enum: + - MORE_SEVERE + - NO_CHANGE + - LESS_SEVERE + ThresholdHysteresis: + type: object + required: + - high + properties: + high: + oneOf: + - type: integer + - $ref: '#/components/schemas/Float' + low: + $ref: '#/components/schemas/Float' + ThresholdLevelInd: + type: object + required: + - up + properties: + up: + $ref: '#/components/schemas/ThresholdHysteresis' + low: + $ref: '#/components/schemas/ThresholdHysteresis' + ThresholdInfo: + type: object + required: + - observedMeasurement + - observedValue + properties: + observedMeasurement: + type: string + observedValue: + oneOf: + - type: integer + - $ref: '#/components/schemas/Float' + thresholdLevelInd: + $ref: '#/components/schemas/ThresholdLevelInd' + armTime: + $ref: '#/components/schemas/DateTime' + CorrelatedNotification: + type: object + required: + - source + - notificationId + properties: + sourceObjectInstance: + $ref: '#/components/schemas/Dn' + notificationIds: + type: array + items: + $ref: '#/components/schemas/NotificationId' + CorrelatedNotifications: + type: array + items: + $ref: '#/components/schemas/CorrelatedNotification' + AckState: + type: string + enum: + - ACKNOWLEDGED + - UNACKNOWLEDGED + + AlarmRecord: + description: >- + The alarmId is not a property of an alarm record. It is used as key + in the map of alarm records instead. + type: object + properties: + # alarmId: + # $ref: '#/components/schemas/AlarmId' + objectInstance: + $ref: '#/components/schemas/Dn' + notificationId: + $ref: '#/components/schemas/NotificationId' + alarmRaisedTime: + $ref: '#/components/schemas/DateTime' + alarmChangedTime: + $ref: '#/components/schemas/DateTime' + alarmClearedTime: + $ref: '#/components/schemas/DateTime' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + specificProblem: + $ref: '#/components/schemas/SpecificProblem' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + backedUpStatus: + type: boolean + backUpObject: + $ref: '#/components/schemas/Dn' + trendIndication: + $ref: '#/components/schemas/TrendIndication' + thresholdinfo: + $ref: '#/components/schemas/ThresholdInfo' + correlatedNotifications: + $ref: '#/components/schemas/CorrelatedNotifications' + stateChangeDefinition: + $ref: '#/components/schemas/AttributeValueChangeSet' + monitoredAttributes: + $ref: '#/components/schemas/AttributeNameValuePairSet' + proposedRepairActions: + type: string + additionalText: + type: string + additionalInformation: + $ref: '#/components/schemas/AttributeNameValuePairSet' + + rootCauseIndicator: + type: boolean + + ackTime: + $ref: '#/components/schemas/DateTime' + ackUserId: + type: string + ackSystemId: + type: string + ackState: + $ref: '#/components/schemas/AckState' + + clearUserId: + type: string + clearSystemId: + type: string + serviceUser: + type: string + serviceProvider: + type: string + securityAlarmDetector: + type: string + + #---- Definition of alarm notifications --------------------------------------------# + + AlarmNotificationTypes: + type: string + enum: + - notifyNewAlarm + - notifyChangedAlarm + - notifyChangedAlarmGeneral + - notifyAckStateChanged + - notifyCorrelatedNotificationChanged + - notifyComments + - notifyClearedAlarm + - notifyAlarmListRebuiltAlarm + - notifyPotentialFaultyAlarmList + AlarmListAlignmentRequirement: + type: string + enum: + - ALIGNMENT_REQUIRED + - ALIGNMENT_NOT_REQUIRED + + NotifyNewAlarm: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + specificProblem: + $ref: '#/components/schemas/SpecificProblem' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + backedUpStatus: + type: boolean + backUpObject: + $ref: '#/components/schemas/Dn' + trendIndication: + $ref: '#/components/schemas/TrendIndication' + thresholdInfo: + $ref: '#/components/schemas/ThresholdInfo' + correlatedNotifications: + $ref: '#/components/schemas/CorrelatedNotifications' + stateChangeDefinition: + $ref: '#/components/schemas/AttributeValueChangeSet' + monitoredAttributes: + $ref: '#/components/schemas/AttributeNameValuePairSet' + proposedRepairActions: + type: string + additionalText: + type: string + additionalInformation: + $ref: '#/components/schemas/AttributeNameValuePairSet' + rootCauseIndicator: + type: boolean + NotifyNewSecAlarm: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + - serviceUser + - serviceProvider + - securityAlarmDetector + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + correlatedNotifications: + $ref: '#/components/schemas/CorrelatedNotifications' + additionalText: + type: string + additionalInformation: + $ref: '#/components/schemas/AttributeNameValuePairSet' + rootCauseIndicator: + type: boolean + serviceUser: + type: string + serviceProvider: + type: string + securityAlarmDetector: + type: string + NotifyClearedAlarm: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + correlatedNotifications: + $ref: '#/components/schemas/CorrelatedNotifications' + clearUserId: + type: string + clearSystemId: + type: string + NotifyChangedAlarm: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + NotifyChangedAlarmGeneral: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + - changedAlarmAttributes + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + specificProblem: + $ref: '#/components/schemas/SpecificProblem' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + correlatedNotifications: + $ref: '#/components/schemas/CorrelatedNotifications' + backedUpStatus: + type: boolean + backUpObject: + $ref: '#/components/schemas/Dn' + trendIndication: + $ref: '#/components/schemas/TrendIndication' + thresholdInfo: + $ref: '#/components/schemas/ThresholdInfo' + stateChangeDefinition: + $ref: '#/components/schemas/AttributeValueChangeSet' + monitoredAttributes: + $ref: '#/components/schemas/AttributeNameValuePairSet' + proposedRepairActions: + type: string + additionalText: + type: string + additionalInformation: + $ref: '#/components/schemas/AttributeNameValuePairSet' + rootCauseIndicator: + type: boolean + changedAlarmAttributes: + $ref: '#/components/schemas/AttributeNameValuePairSet' + NotifyChangedSecAlarmGeneral: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + - serviceUser + - serviceProvider + - securityAlarmDetector + - changedAlarmAttributes + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + correlatedNotifications: + $ref: '#/components/schemas/CorrelatedNotifications' + additionalText: + type: string + additionalInformation: + $ref: '#/components/schemas/AttributeNameValuePairSet' + rootCauseIndicator: + type: boolean + serviceUser: + type: string + serviceProvider: + type: string + securityAlarmDetector: + type: string + changedAlarmAttributes: + $ref: '#/components/schemas/AttributeNameValuePairSet' + NotifyCorrelatedNotificationChanged: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - correlatedNotifications + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + correlatedNotifications: + $ref: '#/components/schemas/CorrelatedNotifications' + rootCauseIndicator: + type: boolean + NotifyAckStateChanged: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + - ackState + - ackUserId + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + ackState: + $ref: '#/components/schemas/AckState' + ackUserId: + type: string + ackSystemId: + type: string + NotifyComments: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - alarmId + - alarmType + - probableCause + - perceivedSeverity + - comments + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + alarmType: + $ref: '#/components/schemas/AlarmType' + probableCause: + $ref: '#/components/schemas/ProbableCause' + perceivedSeverity: + $ref: '#/components/schemas/PerceivedSeverity' + comments: + $ref: '#/components/schemas/Comments' + NotifyPotentialFaultyAlarmList: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - reason + properties: + reason: + type: string + NotifyAlarmListRebuilt: + allOf: + - $ref: '#/components/schemas/NotificationHeader' + - type: object + required: + - reason + properties: + reason: + type: string + alarmListAlignmentRequirement: + $ref: '#/components/schemas/AlarmListAlignmentRequirement' + + #---- Definition of query parameters -----------------------------------------------# + + AlarmAckState: + type: string + enum: + - ALL_ALARMS + - ALL_ACTIVE_ALARMS + - ALL_ACTIVE_AND_ACKNOWLEDGED_ALARMS + - ALL_ACTIVE_AND_UNACKNOWLEDGED_ALARMS + - ALL_CLEARED_AND_UNACKNOWLEDGED_ALARMS + - ALL_UNACKNOWLEDGED_ALARMS + + #---- Definition of patch documents ------------------------------------------------# + + MergePatchAcknowledgeAlarm: + description: >- + Patch document acknowledging or unacknowledging a single alarm. For + acknowleding an alarm the value of ackState is ACKNOWLEDGED, for unacknowleding + an alarm the value of ackState is UNACKNOWLEDGED. + type: object + required: + - ackUserId + - ackState + properties: + ackUserId: + type: string + ackSystemId: + type: string + ackState: + $ref: '#/components/schemas/AckState' + MergePatchClearAlarm: + description: Patch document for clearing a single alarm + type: object + required: + - clearUserId + - perceivedSeverity + properties: + clearUserId: + type: string + clearSystemId: + type: string + perceivedSeverity: + type: string + enum: + - CLEARED + + #---- Definition of method responses -----------------------------------------------# + + FailedAlarm: + type: object + required: + - alarmId + - failureReason + properties: + alarmId: + $ref: '#/components/schemas/AlarmId' + failureReason: + type: string + + #---- Definition of resources ------------------------------------------------------# + + AlarmCount: + type: object + required: + - criticalCount + - majorCount + - minorCount + - warningCount + - indeterminateCount + - clearedCount + properties: + criticalCount: + type: integer + majorCount: + type: integer + minorCount: + type: integer + warningCount: + type: integer + indeterminateCount: + type: integer + clearedCount: + type: integer + Comment: + type: object + properties: + commentTime: + $ref: '#/components/schemas/DateTime' + commentUserId: + type: string + commentSystemId: + type: string + commentText: + type: string + Comments: + description: >- + Collection of comments. The comment identifiers are allocated by the + MnS producer and used as key in the map. + type: object + additionalProperties: + $ref: '#/components/schemas/Comment' + Subscription: + type: object + properties: + consumerReference: + $ref: '#/components/schemas/Uri' + timeTick: + $ref: '#/components/schemas/Long' + filter: + $ref: '#/components/schemas/Filter' diff --git a/src/test/resources/stndDefined/schema-map.json b/src/test/resources/stndDefined/schema-map.json new file mode 100644 index 00000000..6d19037c --- /dev/null +++ b/src/test/resources/stndDefined/schema-map.json @@ -0,0 +1,6 @@ +[ + { + "publicURL": "https://forge.3gpp.org/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml", + "localURL": "OpenAPI_faultMnS.yaml" + } +]
\ No newline at end of file diff --git a/src/test/resources/ves7_batch_with_stndDefined_valid.json b/src/test/resources/ves7_batch_with_stndDefined_valid.json new file mode 100644 index 00000000..10ab4b49 --- /dev/null +++ b/src/test/resources/ves7_batch_with_stndDefined_valid.json @@ -0,0 +1,109 @@ +{ + "eventList": [ + { + "commonEventHeader": { + "version": "4.1", + "vesEventListenerVersion": "7.2", + "domain": "stndDefined", + "eventId": "stndDefined-gNB_Nokia000001", + "eventName": "stndDefined-gNB-Nokia-PowerLost", + "stndDefinedNamespace": "3GPP-FaultSupervision", + "startEpochMicrosec": 1413378172000000, + "lastEpochMicrosec": 1413378172000000, + "reportingEntityName": "ibcx0001vm002oam001", + "sourceName": "scfx0001vm002cap001", + "sequence": 1, + "priority": "High" + }, + "stndDefinedFields": { + "schemaReference": "https://forge.3gpp.org/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml#components/schemas/NotifyNewAlarm", + "data": { + "href": 1, + "uri": "1", + "notificationId": 1, + "notificationType": "notifyNewAlarm", + "eventTime": "xyz", + "systemDN": "xyz", + "probableCause": 1, + "perceivedSeverity": "INDETERMINATE", + "rootCauseIndicator": false, + "specificProblem": "xyz", + "correlatedNotifications": [], + "backedUpStatus": true, + "backUpObject": "xyz", + "trendIndication": "MORE_SEVERE", + "thresholdInfo": { + "observedMeasurement": "new", + "observedValue": 123 + }, + "stateChangeDefinition": { + }, + "monitoredAttributes": { + "newAtt": "new" + }, + "proposedRepairActions": "xyz", + "additionalText": "xyz", + "additionalInformation": { + "addInfo": "new" + }, + "alarmId": "1", + "alarmType": "COMMUNICATIONS_ALARM" + }, + "stndDefinedFieldsVersion": "1.0" + } + }, + { + "commonEventHeader": { + "version": "4.1", + "vesEventListenerVersion": "7.2", + "domain": "stndDefined", + "eventId": "stndDefined-gNB_Nokia000001", + "eventName": "stndDefined-gNB-Nokia-PowerLost", + "stndDefinedNamespace": "3GPP-FaultSupervision", + "startEpochMicrosec": 1413378172000000, + "lastEpochMicrosec": 1413378172000000, + "reportingEntityName": "ibcx0001vm002oam001", + "sourceName": "scfx0001vm002cap001", + "sequence": 1, + "priority": "High" + }, + "stndDefinedFields": { + "schemaReference": "https://forge.3gpp.org/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml#components/schemas/NotifyNewAlarm", + "data": { + "href": 1, + "uri": "1", + "notificationId": 1, + "notificationType": "notifyNewAlarm", + "eventTime": "xyz", + "systemDN": "xyz", + "probableCause": 1, + "perceivedSeverity": "INDETERMINATE", + "rootCauseIndicator": false, + "specificProblem": "xyz", + "correlatedNotifications": [], + "backedUpStatus": true, + "backUpObject": "xyz", + "trendIndication": "MORE_SEVERE", + "thresholdInfo": { + "observedMeasurement": "new", + "observedValue": 123 + }, + "stateChangeDefinition": { + }, + "monitoredAttributes": { + "newAtt": "new" + }, + "proposedRepairActions": "xyz", + "additionalText": "xyz", + "additionalInformation": { + "addInfo": "new" + }, + "alarmId": "1", + "alarmType": "COMMUNICATIONS_ALARM" + }, + "stndDefinedFieldsVersion": "1.0" + } + } + ] +} + diff --git a/src/test/resources/ves7_valid_eventWithStndDefinedFields.json b/src/test/resources/ves7_valid_eventWithStndDefinedFields.json deleted file mode 100644 index 5d40b9d9..00000000 --- a/src/test/resources/ves7_valid_eventWithStndDefinedFields.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "event": { - "commonEventHeader": { - "domain": "stndDefined", - "eventId": "stndDefined-gNB_Nokia000001", - "eventName": "stndDefined-gNB-Nokia-PowerLost", - "stndDefinedNamespace": "3GPP-FaultSupervision", - "lastEpochMicrosec": 1234567890, - "priority": "Normal", - "reportingEntityName": "Nokia123456", - "sequence": 0, - "sourceName": "Nokia123456", - "startEpochMicrosec": 1234567890, - "version": "4.1", - "vesEventListenerVersion": "7.2" - }, - "stndDefinedFields": { - "schemaReference": "https://www.3gpp.org/Rel-16/TS28532_generic_fault_supervision.json#definitions/schemas/notifyNewAlarm-NotifType", - "data": { - "header": { - "uri": "xyz", - "notificationId": "xyz", - "notificationType": "notifyNewAlarm", - "eventTime": "xyz", - "systemDN": "xyz" - }, - "body": { - "probableCause": "xyz", - "perceivedSeverity": "Major", - "rootCauseIndicator": false, - "specificProblem": "xyz", - "correlatedNotifications": [], - "backedUpStatus": true, - "backUpObject": "xyz", - "trendIndication": "No change", - "thresholdInfo": {}, - "stateChangeDefinition": [], - "monitoredAttributes": [], - "proposedRepairActions": "xyz", - "additionalText": "xyz", - "additionalInformation": [], - "alarmId": "xyz", - "alarmType": "Environmental Alarm" - } - }, - "stndDefinedFieldsVersion": "1.0" - } - } -}
\ No newline at end of file diff --git a/src/test/resources/ves_stdnDefined_empty_namespace_invalid.json b/src/test/resources/ves_stdnDefined_empty_namespace_invalid.json index bf5f0953..a63bca17 100644 --- a/src/test/resources/ves_stdnDefined_empty_namespace_invalid.json +++ b/src/test/resources/ves_stdnDefined_empty_namespace_invalid.json @@ -15,7 +15,7 @@ "vesEventListenerVersion": "7.2" }, "stndDefinedFields": { - "schemaReference": "https://www.3gpp.org/Rel-16/TS28532_generic_fault_supervision.json#definitions/schemas/notifyNewAlarm-NotifType", + "schemaReference": "https://forge.3gpp.org/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml#definitions/schemas/notifyNewAlarm-NotifType", "data": { "uri": "xyz", "notificationId": "xyz", diff --git a/src/test/resources/ves_stdnDefined_invalid.json b/src/test/resources/ves_stdnDefined_invalid.json new file mode 100644 index 00000000..fce300ae --- /dev/null +++ b/src/test/resources/ves_stdnDefined_invalid.json @@ -0,0 +1,54 @@ +{ + "event": { + "commonEventHeader": { + "version": "4.1", + "vesEventListenerVersion": "7.2", + "domain": "stndDefined", + "eventId": "stndDefined-gNB_Nokia000001", + "eventName": "stndDefined-gNB-Nokia-PowerLost", + "stndDefinedNamespace": "3GPP-FaultSupervision", + "startEpochMicrosec": 1413378172000000, + "lastEpochMicrosec": 1413378172000000, + "reportingEntityName": "ibcx0001vm002oam001", + "sourceName": "scfx0001vm002cap001", + "sequence": 1, + "priority": "High" + }, + "stndDefinedFields": { + "schemaReference": "https://forge.3gpp.org/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml#components/schemas/NotifyNewAlarm", + "data": { + "href": 1, + "uri": "1", + "notificationId": 1, + "notificationType": "notifyNewAlarm", + "eventTime": "xyz", + "systemDN": "xyz", + "probableCause": 1, + "perceivedSeverity": 1, + "rootCauseIndicator": false, + "specificProblem": "xyz", + "correlatedNotifications": [], + "backedUpStatus": true, + "backUpObject": "xyz", + "trendIndication": "123", + "thresholdInfo": { + "observedMeasurement": "new", + "observedValue": 123 + }, + "stateChangeDefinition": { + }, + "monitoredAttributes": { + "newAtt": "new" + }, + "proposedRepairActions": "xyz", + "additionalText": "xyz", + "additionalInformation": { + "addInfo": "new" + }, + "alarmId": 1, + "alarmType": "COMMUNICATIONS_ALARM" + }, + "stndDefinedFieldsVersion": "1.0" + } + } +}
\ No newline at end of file diff --git a/src/test/resources/ves_stdnDefined_missing_local_schema_reference.json b/src/test/resources/ves_stdnDefined_missing_local_schema_reference.json new file mode 100644 index 00000000..1ee36532 --- /dev/null +++ b/src/test/resources/ves_stdnDefined_missing_local_schema_reference.json @@ -0,0 +1,54 @@ +{ + "event": { + "commonEventHeader": { + "version": "4.1", + "vesEventListenerVersion": "7.2", + "domain": "stndDefined", + "eventId": "stndDefined-gNB_Nokia000001", + "eventName": "stndDefined-gNB-Nokia-PowerLost", + "stndDefinedNamespace": "3GPP-FaultSupervision", + "startEpochMicrosec": 1413378172000000, + "lastEpochMicrosec": 1413378172000000, + "reportingEntityName": "ibcx0001vm002oam001", + "sourceName": "scfx0001vm002cap001", + "sequence": 1, + "priority": "High" + }, + "stndDefinedFields": { + "schemaReference": "https://forge.3gpp.org/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml", + "data": { + "href": 1, + "uri": "1", + "notificationId": 1, + "notificationType": "notifyNewAlarm", + "eventTime": "xyz", + "systemDN": "xyz", + "probableCause": 1, + "perceivedSeverity": "INDETERMINATE", + "rootCauseIndicator": false, + "specificProblem": "xyz", + "correlatedNotifications": [], + "backedUpStatus": true, + "backUpObject": "xyz", + "trendIndication": "MORE_SEVERE", + "thresholdInfo": { + "observedMeasurement": "new", + "observedValue": 123 + }, + "stateChangeDefinition": { + }, + "monitoredAttributes": { + "newAtt": "new" + }, + "proposedRepairActions": "xyz", + "additionalText": "xyz", + "additionalInformation": { + "addInfo": "new" + }, + "alarmId": "1", + "alarmType": "COMMUNICATIONS_ALARM" + }, + "stndDefinedFieldsVersion": "1.0" + } + } +}
\ No newline at end of file diff --git a/src/test/resources/ves_stdnDefined_missing_namespace_invalid.json b/src/test/resources/ves_stdnDefined_missing_namespace_invalid.json index 230dc54e..7a35286d 100644 --- a/src/test/resources/ves_stdnDefined_missing_namespace_invalid.json +++ b/src/test/resources/ves_stdnDefined_missing_namespace_invalid.json @@ -14,7 +14,7 @@ "vesEventListenerVersion": "7.2" }, "stndDefinedFields": { - "schemaReference": "https://www.3gpp.org/Rel-16/TS28532_generic_fault_supervision.json#definitions/schemas/notifyNewAlarm-NotifType", + "schemaReference": "https://forge.3gpp.org/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml#definitions/schemas/notifyNewAlarm-NotifType", "data": { "uri": "xyz", "notificationId": "xyz", diff --git a/src/test/resources/ves_stdnDefined_valid.json b/src/test/resources/ves_stdnDefined_valid.json index aa026e71..99b7ce37 100644 --- a/src/test/resources/ves_stdnDefined_valid.json +++ b/src/test/resources/ves_stdnDefined_valid.json @@ -1,45 +1,54 @@ { "event": { "commonEventHeader": { + "version": "4.1", + "vesEventListenerVersion": "7.2", "domain": "stndDefined", "eventId": "stndDefined-gNB_Nokia000001", "eventName": "stndDefined-gNB-Nokia-PowerLost", "stndDefinedNamespace": "3GPP-FaultSupervision", - "lastEpochMicrosec": 1234567890, - "priority": "Normal", - "reportingEntityName": "Nokia123456", - "sequence": 0, - "sourceName": "Nokia123456", - "startEpochMicrosec": 1234567890, - "version": "4.1", - "vesEventListenerVersion": "7.2" + "startEpochMicrosec": 1413378172000000, + "lastEpochMicrosec": 1413378172000000, + "reportingEntityName": "ibcx0001vm002oam001", + "sourceName": "scfx0001vm002cap001", + "sequence": 1, + "priority": "High" }, "stndDefinedFields": { - "schemaReference": "https://www.3gpp.org/Rel-16/TS28532_generic_fault_supervision.json#definitions/schemas/notifyNewAlarm-NotifType", + "schemaReference": "https://forge.3gpp.org/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml#components/schemas/NotifyNewAlarm", "data": { - "uri": "xyz", - "notificationId": "xyz", + "href": 1, + "uri": "1", + "notificationId": 1, "notificationType": "notifyNewAlarm", "eventTime": "xyz", "systemDN": "xyz", - "probableCause": "xyz", - "perceivedSeverity": "Major", + "probableCause": 1, + "perceivedSeverity": "INDETERMINATE", "rootCauseIndicator": false, "specificProblem": "xyz", "correlatedNotifications": [], "backedUpStatus": true, "backUpObject": "xyz", - "trendIndication": "No change", - "thresholdInfo": {}, - "stateChangeDefinition": [], - "monitoredAttributes": [], + "trendIndication": "MORE_SEVERE", + "thresholdInfo": { + "observedMeasurement": "new", + "observedValue": 123 + }, + "stateChangeDefinition": { + }, + "monitoredAttributes": { + "newAtt": "new" + }, "proposedRepairActions": "xyz", "additionalText": "xyz", - "additionalInformation": [], - "alarmId": "xyz", - "alarmType": "Environmental Alarm" + "additionalInformation": { + "addInfo": "new" + }, + "alarmId": "1", + "alarmType": "COMMUNICATIONS_ALARM" }, "stndDefinedFieldsVersion": "1.0" } } -} +}
\ No newline at end of file diff --git a/src/test/resources/ves_stdnDefined_with_empty_stndDefined_fields_data.json b/src/test/resources/ves_stdnDefined_with_empty_stndDefined_fields_data.json new file mode 100644 index 00000000..2d91c438 --- /dev/null +++ b/src/test/resources/ves_stdnDefined_with_empty_stndDefined_fields_data.json @@ -0,0 +1,24 @@ +{ + "event": { + "commonEventHeader": { + "version": "4.1", + "vesEventListenerVersion": "7.2", + "domain": "stndDefined", + "eventId": "stndDefined-gNB_Nokia000001", + "eventName": "stndDefined-gNB-Nokia-PowerLost", + "stndDefinedNamespace": "3GPP-FaultSupervision", + "startEpochMicrosec": 1413378172000000, + "lastEpochMicrosec": 1413378172000000, + "reportingEntityName": "ibcx0001vm002oam001", + "sourceName": "scfx0001vm002cap001", + "sequence": 1, + "priority": "High" + }, + "stndDefinedFields": { + "schemaReference": "https://forge.3gpp.org/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml#components/schemas/NotifyNewAlarm", + "data": { + }, + "stndDefinedFieldsVersion": "1.0" + } + } +} diff --git a/src/test/resources/ves_stdnDefined_without_schema_reference.json b/src/test/resources/ves_stdnDefined_without_schema_reference.json new file mode 100644 index 00000000..33342c6c --- /dev/null +++ b/src/test/resources/ves_stdnDefined_without_schema_reference.json @@ -0,0 +1,22 @@ +{ + "event": { + "commonEventHeader": { + "version": "4.1", + "vesEventListenerVersion": "7.2", + "domain": "stndDefined", + "eventId": "stndDefined-gNB_Nokia000001", + "eventName": "stndDefined-gNB-Nokia-PowerLost", + "stndDefinedNamespace": "3GPP-FaultSupervision", + "startEpochMicrosec": 1413378172000000, + "lastEpochMicrosec": 1413378172000000, + "reportingEntityName": "ibcx0001vm002oam001", + "sourceName": "scfx0001vm002cap001", + "sequence": 1, + "priority": "High" + }, + "stndDefinedFields": { + "data": {}, + "stndDefinedFieldsVersion": "1.0" + } + } +}
\ No newline at end of file diff --git a/src/test/resources/ves_stdnDefined_wrong_internal_file_reference.json b/src/test/resources/ves_stdnDefined_wrong_internal_file_reference.json new file mode 100644 index 00000000..9e835443 --- /dev/null +++ b/src/test/resources/ves_stdnDefined_wrong_internal_file_reference.json @@ -0,0 +1,54 @@ +{ + "event": { + "commonEventHeader": { + "version": "4.1", + "vesEventListenerVersion": "7.2", + "domain": "stndDefined", + "eventId": "stndDefined-gNB_Nokia000001", + "eventName": "stndDefined-gNB-Nokia-PowerLost", + "stndDefinedNamespace": "3GPP-FaultSupervision", + "startEpochMicrosec": 1413378172000000, + "lastEpochMicrosec": 1413378172000000, + "reportingEntityName": "ibcx0001vm002oam001", + "sourceName": "scfx0001vm002cap001", + "sequence": 1, + "priority": "High" + }, + "stndDefinedFields": { + "schemaReference": "https://forge.3gpp.org/rep/sa5/data-models/blob/REL-16/OpenAPI/faultMnS.yaml#components/schemas/dummyRef", + "data": { + "href": 1, + "uri": "1", + "notificationId": 1, + "notificationType": "notifyNewAlarm", + "eventTime": "xyz", + "systemDN": "xyz", + "probableCause": 1, + "perceivedSeverity": "INDETERMINATE", + "rootCauseIndicator": false, + "specificProblem": "xyz", + "correlatedNotifications": [], + "backedUpStatus": true, + "backUpObject": "xyz", + "trendIndication": "MORE_SEVERE", + "thresholdInfo": { + "observedMeasurement": "new", + "observedValue": 123 + }, + "stateChangeDefinition": { + }, + "monitoredAttributes": { + "newAtt": "new" + }, + "proposedRepairActions": "xyz", + "additionalText": "xyz", + "additionalInformation": { + "addInfo": "new" + }, + "alarmId": "1", + "alarmType": "COMMUNICATIONS_ALARM" + }, + "stndDefinedFieldsVersion": "1.0" + } + } +}
\ No newline at end of file diff --git a/version.properties b/version.properties index 75acd492..c3c1ab1c 100644 --- a/version.properties +++ b/version.properties @@ -1,6 +1,6 @@ major=1 minor=7 -patch=2 +patch=3 base_version=${major}.${minor}.${patch} release_version=${base_version} snapshot_version=${base_version}-SNAPSHOT |