diff options
author | 2020-04-08 09:31:13 +0200 | |
---|---|---|
committer | 2020-04-08 09:43:31 +0000 | |
commit | 3c494af52c476a86ae1389991b464914517774b8 (patch) | |
tree | e6d9b4f261eac5f7b3fd0f42e740840a106842e6 /pnfsimulator | |
parent | 75496bfc5b2f7e03e49ab4929d1f20962b39c992 (diff) |
Move PNF simulator from /test/mocks to new project
This code is a copy of pnfsimulator located in integration repository
(/test/mocks/pnfsimulator) with added profile "docker" in pom.xml
located in pnfsimulator and netconfsimulator subprojects
Issue-ID: INT-1517
Signed-off-by: Bartosz Gardziejewski <bartosz.gardziejewski@nokia.com>
Change-Id: I725fa0530c41b13cb12705979dee8b8b354dc1a1
Diffstat (limited to 'pnfsimulator')
137 files changed, 10101 insertions, 0 deletions
diff --git a/pnfsimulator/.gitignore b/pnfsimulator/.gitignore new file mode 100644 index 0000000..3fa204a --- /dev/null +++ b/pnfsimulator/.gitignore @@ -0,0 +1,4 @@ +.idea +target +*.iml +logs diff --git a/pnfsimulator/Dockerfile b/pnfsimulator/Dockerfile new file mode 100644 index 0000000..aafea0e --- /dev/null +++ b/pnfsimulator/Dockerfile @@ -0,0 +1,8 @@ +FROM openjdk:8-jre-alpine +ADD target/libs /app/libs +ADD target/pnfsimulator-5.0.0-SNAPSHOT.jar /app/pnf-simulator.jar +CMD apk update +CMD apk add ca-certificates +ADD certificates /usr/local/share/ca-certificates/ +RUN update-ca-certificates +CMD java -Dspring.config.location=file:/app/application.properties -cp /app/libs/*:/app/pnf-simulator.jar org.onap.pnfsimulator.Main diff --git a/pnfsimulator/README.md b/pnfsimulator/README.md new file mode 100644 index 0000000..6caa644 --- /dev/null +++ b/pnfsimulator/README.md @@ -0,0 +1,333 @@ +# PNF Simulator +Simulator that generates VES events related to PNF PNP integration. + +## Usage of simulator +### Setting up +Preferred way to start simulator is to use `docker-compose up -d` command. +All required docker images will be downloaded from ONAP Nexus, however there is possibility to build those +images locally. It can be achieve by invoking `mvn clean package docker:build` from top directory. + +### API +Simulator provides REST endpoints which can be used to trigger sending events to VES. + +*Periodic event sending* +To trigger sending use following endpoint *http://<simulator_ip>:5000/simulator/start*. +Supported method: *POST* +Headers: + - Content-Type - application/json +Parameters: + + simulatorParams: + repeatCount - determines how many events will be sent + repeatInterval - time (in seconds) between events + vesServerUrl - valid path to VES Collector + templateName - name of template file (check *Templates* section) + patch - part of event which will be merged into template + + +Sample Request: + + { + "simulatorParams": { + "repeatCount": 5, + "repeatInterval": 2, + "vesServerUrl": "http://VES-HOST:8080/eventListener/v7" + }, + "templateName": "validExampleMeasurementEvent.json", + "patch": { + "event": { + "commonEventHeader": { + "eventId": "PATCHED_eventId", + "sourceName": "PATCHED_sourceName", + "version": 3.0 + } + } + } + } + +*One-time event sending* +Enables direct, immediate event sending without need to have template deployed on backend. +Keywords are supported,thus once passed, will also be substituted with proper strings. +Passed event body must be valid and complete event according to VES Collector interface. +To trigger sending use following endpoint *http://<simulator_ip>:5000/simulator/event*. + +Supported method: *POST* +Headers: + - Content-Type - application/json +Parameters: + + vesServerUrl - valid URL to VES Collector event listener + event - body of event to be sent directly to VES Collector (it can contain keyword expressions) + + +Sample Request: + + { + "vesServerUrl": "http://VES-HOST:8080/eventListener/v7", + "event": { + "commonEventHeader": { + "eventId": "#RandomString(20)", + "sourceName": "PATCHED_sourceName", + "version": 3.0 + } + } + } + +### Changing simulator configuration +Utility of default configuration has been introduced so as to facilitate sending requests. so far only vesServerUrl states default simulator configuration. +On simulator startup, vesServerUrl is initialized with default value, but must be replaced with correct VES server url by user. +Once vesServerUrl is properly set on simulator, this parameter does not need to be incorporated into every trigger event request. +If user does not provide vesServerUrl in trigger request, default value will be used. +If use does provide vesServerUrl in trigger request, then passed value will be used instead of default one (default value will not be overwritten by provided one). + +It is possible to get and update configuration (current target vesServerUrl) using offered REST API - */simulator/config* endpoint is exposed for that. +To get current configuration *GET* method must be used. +To update vesServerUrl *PUT* method is used, example request: + + { + "vesServerUrl": "http://10.154.164.117:8080/eventListener/v7" + } + +Note: passed vesServerUrl must be wellformed URL. + + +### Running simulator +The recommended way is to checkout PNF Simulator project from ONAP Git repository and use *simulator*.sh script. +If you copy *simulator.sh* script to another location, keep in mind to copy also *docker-compose.yml* and directories: *config and templates*. +In order to run simulator, invoke ./simulator.sh -e build to build required images and then invoke ./simulator.sh -e start +Script downloads if necessary needed Docker images and runs instances of these images. +After simulator start it is advisable to setup default value for target vesServerUrl. + +Example request: + + PUT to http://<simulator_ip>:<simulator_port>/simulator/config + + { + "vesServerUrl": "PUT HERE VALID URL TO YOUR VES EVENT LISTENER" + } + +### Templates +Template is a draft event. Merging event with patch will result in valid VES event. Template itself should be a correct VES event as well as valid json object. +In order to apply custom template, just copy it to ./templates directory. +*notification.json* and *registration.json* are available by default in *./templates* directory. + +#### Template management +The simulator provides means for managing templates. Supported actions: adding, editing (overriding) and deleting are available via HTTP endpoint */template* + +```GET /template/list``` +Lists all templates known to the simulator. + +```GET /template/get-content/{name}``` +Gets template content based on *name* path variable. + +```POST /template/upload?override=true``` +Saves template content under *name* path variable. The non-mandatory parameter *override* allows overwriting an existing template. + +Sample payload: +``` +{ + "name": "someTemplate", + "template": { + "commonEventHeader": { + "domain": "notification", + "eventName": "vFirewallBroadcastPackets" + }, + "notificationFields": { + "arrayOfNamedHashMap": [{ + "name": "A20161221.1031-1041.bin.gz", + "hashMap": { + "fileformatType": "org.3GPP.32.435#measCollec" + } + }] + } + } +} +``` + +### Searching for key-value conditions in stored templates +Simulator allows to search through stored templates and retrieve names of those that satisfy given criteria passed in form of key-value pairs (See examples below). +Following data types are supported in search as values: +-integer +-string +-double +-boolean +Searching for null values as well as incorporating regex expression with intention to find a match is not supported. +Search expression must be valid JSON, thus no duplicate keys are allowed - user could specify the same parameter multiple times, but only last occurrence will be applied to query. +Example search expression: + +{"domain": "notification", "sequence": 1, "startEpochMicrosec": 1531616794, "sampleDouble": 2.5} + +will find all templates that contain all of passed key-value entries. There is an AND condition beetwen given criteria - all of them must be satisfied to qualify template as matching item. + Keys of search expressions are searched in case insensitive way as well as string values. +Where it comes to values of numerical and boolean type exact match is expected. + +API usage: + +```POST /template/search``` +Produces query that returns templates that contain searched criteria + +Sample payload: +``` +{ + "searchExpr": { + "domain": "notification", + "sequence": 1, + "startEpochMicrosec": 1531616794, + "sampleDouble": 2.5 + } +} +``` +Sample response: +``` +[notification.json] +``` + + +Note: Manually deployed templates, or actually existing ones, but modified inside the templates catalog '/app/templates', will be automatically synchronized with schemas stored inside the database. That means that a user can dynamically change the template content using vi editor at simulator container, as well as use any editor at any machine and then push the changes to the template folder. All the changes will be processed 'on the fly' and accessible via the rest API. + +### Periodic events +Simulator has ability to send event periodically. Rest API support parameters: +* repeatCount - count of times that event will be sent to VES +* repeatInterval - interval (in second) between two events. +(Checkout example to see how to use them) + +### Patching +User is able to provide patch in request, which will be merged into template. + +Warning: Patch should be a valid json object (no json primitives nor json arrays are allowed as a full body of patch). + +This mechanism allows to override part of template. +If in "patch" section there are additional parameters (absent in template), those parameters with values will be added to event. +Patching mechanism supports also keywords that enables automatic value generation of appropriate type + +### Keyword support +Simulator supports corresponding keywords: +- \#RandomInteger(start,end) - substitutes keyword with random positive integer within given range (range borders inclusive) +- \#RandomPrimitiveInteger(start,end) - the same as #RandomInteger(start,end), but returns long as result +- \#RandomInteger - substitutes keyword with random positive integer +- \#RandomString(length) - substitutes keyword with random ASCII string with specified length +- \#RandomString - substitutes keyword with random ASCII string with length of 20 characters +- \#Timestamp - substitutes keyword with current timestamp in epoch (calculated just before sending event) +- \#TimestampPrimitive - the same as \#Timestamp, but returns long as result +- \#Increment - substitutes keyword with positive integer starting from 1 - for each consecutive event, value of increment property is incremented by 1 + +Additional hints and restrictions: +All keywords without 'Primitive' in name return string as result. To specify keyword with 2 arguments e.g. #RandomInteger(start,end) no whitespaces between arguments are allowed. +Maximal value of arguments for RandomInteger is limited to the java integer range. Minimal is always 0. (Negative values are prohibited and wont be treated as a correct parts of keyword). +RandomInteger with parameters will automatically find minimal and maximal value form the given attributes so no particular order of those is expected. + +How does it work? +When user do not want to fill in parameter values that are not relevant from user perspective but are mandatory by end system, then keyword feature should be used. +In template, keyword strings are substituted in runtime with appropriate values autogenerated by simulator. +Example can be shown below: + +Example template with keywords: + + { + "event": { + "commonEventHeader": { + "eventId": "123#RandomInteger(8,8)", + "eventType": "pnfRegistration", + "startEpochMicrosec": "#Timestamp", + "vesEventListenerVersion": "7.0.1", + "lastEpochMicrosec": 1539239592379 + }, + "pnfRegistrationFields": { + "pnfRegistrationFieldsVersion":"2.0", + "serialNumber": "#RandomString(7)", + "vendorName": "Nokia", + "oamV4IpAddress": "val3", + "oamV6IpAddress": "val4" + } + } + } + +Corresponding result of keyword substitution (event that will be sent): + + { + "event": { + "commonEventHeader": { + "eventId": "1238", + "eventType": "pnfRegistration", + "startEpochMicrosec": "154046405117", + "vesEventListenerVersion": "7.0.1", + "lastEpochMicrosec": 1539239592379 + }, + "pnfRegistrationFields": { + "pnfRegistrationFieldsVersion":"2.0", + "serialNumber": "6061ZW3", + "vendorName": "Nokia", + "oamV4IpAddress": "val3", + "oamV6IpAddress": "val4" + } + } + } + + +### Logging +Every start of simulator will generate new logs that can be found in docker pnf-simualtor container under path: +/var/log/ONAP/pnfsimulator/pnfsimulator_output.log + +### Swagger +Detailed view of simulator REST API is available via Swagger UI +Swagger UI is available on *http://<simulator_ip>:5000/swagger-ui.html* + +### History +User is able to view events history. +In order to browse history, go to *http://<simulator_ip>:8081/db/pnf_simulator/eventData* + +### TLS Support +Simulator is able to communicate with VES using HTTPS protocol. +CA certificates are incorporated into simulator docker image, thus no additional actions are required from user. + +Certificates can be found in docker container under path: */usr/local/share/ca-certificates/* + +Simulator works with VES that uses both self-signed certificate (already present in keystore) and VES integrated to AAF. + + +## Developers Guide + +### Integration tests +Integration tests are located in folder 'integration'. Tests are using docker-compose from root folder. +This docker-compose has pnfsimulator image set on nexus3.onap.org:10003/onap/pnf-simulator:5.0.0-SNAPSHOT. +To test your local changes before running integration tests please build project using: + + 'mvn clean package docker:build' + +then go to 'integration' folder and run: + + 'mvn test' + +### Client certificate authentication +Simulator can cooperate with VES server in different security types in particular ```auth.method=certBasicAuth``` which means that it needs to authenticate using client private certificate. + +Warning: according to VES implementation which uses certificate with Common Name set to DCAELOCAL we decided not to use strict hostname verification, so at least this parameter is skipped during checking of the client certificate. + +#### How to generate client correct keystore for pnf-simulator + The Root CA cert is available in certs folder in VES repository. The password for rootCA.key is collector. + + The procedure of generating client's certificate: + 1. Generate a private key for the SSL client: ```openssl genrsa -out client.key 2048``` + 2. Use the client’s private key to generate a cert request: ```openssl req -new -key client.key -out client.csr``` + 3. Issue the client certificate using the cert request and the CA cert/key: ```openssl x509 -req -in client.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out client.crt -days 500 -sha256``` + 4. Convert the client certificate and private key to pkcs#12 format: openssl pkcs12 -export -inkey client.key -in client.cer -out client.p12 + 5. Copy pkcs file into pnf simulators folder: ```/app/store/``` + +#### How to generate correct truststore for pnf-simulator + Create truststore with rootCA.crt: + 1. ```keytool -import -file rootCA.crt -alias firstCA -keystore trustStore``` + 2. Copy truststore to ```/app/store/``` + +#### How to refresh configuration of app +Depends your needs, you are able to change client certificate, replace trustStore to accept new server certificate change keystore and truststore passwords or completely disable client cert authentication. + +For this purpose: +1. Go to the pnf simulator container into the /app folder. +2. If you want to replace keystore or truststore put them into the /app/store folder. +3. Edit /app/application.properties file as follow: +- ssl.clientCertificateEnabled=true (to disable/enable client authentication) +- ssl.clientCertificateDir=/app/store/client.p12 (to replace keystore file) +- ssl.clientCertificatePassword=collector (to replace password for keystore) +- ssl.trustStoreDir=/app/store/trustStore (to replace truststore file) +- ssl.trustStorePassword=collector (to replace password for truststore) +4. Refresh configuration sending simple POST request to correct actuator endpoint at: ```curl http://localhost:5001/refresh -H 'Content-type: application/json' -X POST --data '{}'``` diff --git a/pnfsimulator/certificates/AAF_RootCA.crt b/pnfsimulator/certificates/AAF_RootCA.crt new file mode 100644 index 0000000..e9a50d7 --- /dev/null +++ b/pnfsimulator/certificates/AAF_RootCA.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFPjCCAyagAwIBAgIJAJ6u7cCnzrWdMA0GCSqGSIb3DQEBCwUAMCwxDjAMBgNV +BAsMBU9TQUFGMQ0wCwYDVQQKDARPTkFQMQswCQYDVQQGEwJVUzAeFw0xODA0MDUx +NDE1MjhaFw0zODAzMzExNDE1MjhaMCwxDjAMBgNVBAsMBU9TQUFGMQ0wCwYDVQQK +DARPTkFQMQswCQYDVQQGEwJVUzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAMA5pkgRs7NhGG4ew5JouhyYakgYUyFaG121+/h8qbSdt0hVQv56+EA41Yq7 +XGie7RYDQK9NmAFF3gruE+6X7wvJiChp+Cyd7sFMnb65uWhxEdxWTM2BJFrgfzUn +H8ZCxgaCo3XH4PzlKRy2LQQJEJECwl/RZmRCXijMt5e9h8XoZY/fKkKcZZUsWNCM +pTo266wjvA9MXLmdgReRj0+vrCjrNqy+htwJDztoiHWiYPqT6o8EvGcgjNqjlZx7 +NUNf8MfLDByqKF6+wRbHv1GKjn3/Vijd45Fv8riyRYROiFanvbV6jIfBkv8PZbXg +2VDWsYsgp8NAvMxK+iV8cO+Ck3lBI2GOPZbCEqpPVTYbLUz6sczAlCXwQoPzDIZY +wYa3eR/gYLY1gP2iEVHORag3bLPap9ZX5E8DZkzTNTjovvLk8KaCmfcaUMJsBtDd +ApcUitz10cnRyZc1sX3gE1f3DpzQM6t9C5sOVyRhDcSrKqqwb9m0Ss04XAS9FsqM +P3UWYQyqDXSxlUAYaX892u8mV1hxnt2gjb22RloXMM6TovM3sSrJS0wH+l1nznd6 +aFXftS/G4ZVIVZ/LfT1is4StoyPWZCwwwly1z8qJQ/zhip5NgZTxQw4mi7ww35DY +PdAQOCoajfSvFjqslQ/cPRi/MRCu079heVb5fQnnzVtnpFQRAgMBAAGjYzBhMB0G +A1UdDgQWBBRTVTPyS+vQUbHBeJrBKDF77+rtSTAfBgNVHSMEGDAWgBRTVTPyS+vQ +UbHBeJrBKDF77+rtSTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAN +BgkqhkiG9w0BAQsFAAOCAgEAPx/IaK94n02wPxpnYTy+LVLIxwdq/kawNd6IbiMz +L87zmNMDmHcGbfoRCj8OkhuggX9Lx1/CkhpXimuYsZOFQi5blr/u+v4mIbsgbmi9 +7j+cUHDP0zLycvSvxKHty51LwmaX9a4wkJl5zBU4O1sd/H9tWcEmwJ39ltKoBKBx +c94Zc3iMm5ytRWGj+0rKzLDAXEWpoZ5bE5PLJauA6UDCxDLfs3FwhbS7uDggxYvf +jySF5FCNET94oJ+m8s7VeHvoa8iPGKvXrIqdd7XDHnqJJlVKr7m9S0fMbyEB8ci2 +RtOXDt93ifY1uhoEtEykn4dqBSp8ezvNMnwoXdYPDvTd9uCAFeWFLVreBAWxd25h +PsBTkZA5hpa/rA+mKv6Af4VBViYr8cz4dZCsFChuioVebe9ighrfjB//qKepFjPF +CyjzKN1u0JKm/2x/ORqxkTONG8p3uDwoIOyimUcTtTMv42bfYD88RKakqSFXE9G+ +Z0LlaKABqfjK49o/tsAp+c5LoNlYllKhnetO3QAdraHwdmC36BhoghzR1jpX751A +cZn2VH3Q4XKyp01cJNCJIrua+A+bx6zh3RyW6zIIkbRCbET+UD+4mr8WIcSE3mtR +ZVlnhUDO4z9//WKMVzwS9Rh8/kuszrGFI1KQozXCHLrce3YP6RYZfOed79LXaRwX +dYY= +-----END CERTIFICATE----- diff --git a/pnfsimulator/certificates/dcaelocal.crt b/pnfsimulator/certificates/dcaelocal.crt new file mode 100644 index 0000000..1be5a6f --- /dev/null +++ b/pnfsimulator/certificates/dcaelocal.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDSDCCAjCgAwIBAgIEWAkZ5jANBgkqhkiG9w0BAQUFADBmMQswCQYDVQQGEwJV +UzELMAkGA1UECBMCTkoxEzARBgNVBAcTCk1pZGRsZXRvd24xDTALBgNVBAoTBERD +QUUxEjAQBgNVBAsTCU9QRU4tRENBRTESMBAGA1UEAxMJRENBRUxPQ0FMMB4XDTE2 +MTAyMDE5MjQyMloXDTE3MDExODE5MjQyMlowZjELMAkGA1UEBhMCVVMxCzAJBgNV +BAgTAk5KMRMwEQYDVQQHEwpNaWRkbGV0b3duMQ0wCwYDVQQKEwREQ0FFMRIwEAYD +VQQLEwlPUEVOLURDQUUxEjAQBgNVBAMTCURDQUVMT0NBTDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALoR0omXk1Xou3TdDydwhCF9V0ZSgQtMlMr8qYxe +wLg/UGZbTea5HHqBmjWTVEKFGea7V7pnEiGWCPftIy/4D8ZSDaEQQ0WYCf6jNxeI +T6PSiM+db/TwPToqPNMQwoftpsAEkJEJFB9rgUXoDD9FY5kUQW+fYOLyUeOb/rDE +cRnSZX2qp1M/jAm1puIeNQcqiPExOMHqnN2bIgAZoHaFucdyOQUxuhIAgxoqe8Zt +s451hm94g42F92I8KLy4EyOhXmSMjaLmgOqdjOPyBubOde4R39+6KAyQNGAnm5I4 +xq2J80R7qU0+4nnfjs2ScfAB/HUsWoVaGr9Ii4e34CW8JG8CAwEAATANBgkqhkiG +9w0BAQUFAAOCAQEARqQmWg1gtwbgPbamWy0vdNWLQZm78y1ETR0ro9cazD25sD5/ +anDJ2RA97pGQFgncAI+Fzg4YygWBIext0OE92wQeKaHkxSujAe09F0wPcwc00Vyq +NtBPcP17n18FkpFW1hkurlWiHOpGDRW2MmwhLj4lSFJmxMBAbzlfKrTBgj116UT+ +d4AGyuovS4LkmBWYFN//yoddGyrO26ar1M9ORdbDkjzOK4DkioTx3bwbdKPW7V4a ++Ns1KDFZ7FpjcWPZc6uDV4lBIhNUZuQZLy5hWBUeNhh4i2lL6xMrPzRa5kV1M7og +ipv/ReVCixJqsGhx+8I4OPUbPoUYzRF+JmYUzA== +-----END CERTIFICATE-----
\ No newline at end of file diff --git a/pnfsimulator/config/config.json b/pnfsimulator/config/config.json new file mode 100644 index 0000000..af45632 --- /dev/null +++ b/pnfsimulator/config/config.json @@ -0,0 +1,9 @@ +{ + "simulatorParams": { + "vesServerUrl": "http://VES-HOST:VES-PORT/eventListener/v7", + "repeatInterval": 10, + "repeatCount": 2 + }, + "templateName": "notification.json", + "patch": {} +} diff --git a/pnfsimulator/db/pnf_simulator.js b/pnfsimulator/db/pnf_simulator.js new file mode 100644 index 0000000..f5a03c3 --- /dev/null +++ b/pnfsimulator/db/pnf_simulator.js @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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========================================================= + */ + +const res = [ + db.createUser({ user: 'pnf_simulator_user', pwd: 'zXcVbN123!', roles: ['readWrite', 'dbAdmin'] }), + db.simulatorConfig.insert({"vesServerUrl": "http://xdcae-ves-collector.onap:8080/eventListener/v7"}), + db.createCollection("template"), + db.createView("flatTemplatesView", "template", [{"$project":{"keyValues":{"$objectToArray": "$$ROOT.flatContent"}}}]) +]; + +printjson(res); diff --git a/pnfsimulator/deployment/PnP_PNF_sim_heat_template.yml b/pnfsimulator/deployment/PnP_PNF_sim_heat_template.yml new file mode 100644 index 0000000..6f9b5f0 --- /dev/null +++ b/pnfsimulator/deployment/PnP_PNF_sim_heat_template.yml @@ -0,0 +1,118 @@ +description: Heat template that deploys PnP PNF simulator +heat_template_version: '2013-05-23' +parameters: + flavor_name: {description: Type of instance (flavor) to be used, label: Flavor, + type: string} + image_name: {description: Image to be used for compute instance, label: Image name + or ID, type: string} + key_name: {description: Public/Private key pair name, label: Key pair name, type: string} + public_net_id: {description: Public network that enables remote connection to VNF, + label: Public network name or ID, type: string} + private_net_id: {type: string, description: Private network id, label: Private network name or ID} + private_subnet_id: {type: string, description: Private subnet id, label: Private subnetwork name or ID} + proxy: {type: string, description: Proxy, label: Proxy, default: ""} +resources: + PNF_PnP_simualtor: + type: OS::Nova::Server + properties: + key_name: { get_param: key_name } + image: { get_param: image_name } + flavor: { get_param: flavor_name } + networks: + - port: { get_resource: PNF_PnP_simualtor_port0 } + user_data_format: RAW + user_data: + str_replace: + template: | + #!/bin/bash + + set_versions () { + DOCKER_COMPOSE_VERSION=1.22.0 + } + + + enable_root_ssh () { + sed -i 's/PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config + sed -i 's/PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config + service sshd restart + echo -e "arthur\narthur" | passwd root + } + + update_os () { + dnf -y install fedora-upgrade + } + + docker_remove () { + dnf -y remove docker \ + docker-client \ + docker-client-latest \ + docker-common \ + docker-latest \ + docker-latest-logrotate \ + docker-logrotate \ + docker-selinux \ + docker-engine-selinux \ + docker-engine + } + + docker_install_and_configure () { + dnf -y install dnf-plugins-core + dnf config-manager \ + --add-repo \ + https://download.docker.com/linux/fedora/docker-ce.repo + dnf -y install docker-ce + systemctl start docker + mkdir -p /etc/systemd/system/docker.service.d/ + cat > /etc/systemd/system/docker.service.d/override.conf<< EOF + [Service] + Environment="HTTP_PROXY=$proxy" + Environment="HTTPS_PROXY=$proxy" + EOF + systemctl daemon-reload + systemctl restart docker + } + docker_compose_install () { + curl -L https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose + chmod +x /usr/local/bin/docker-compose + } + pnf_sim_file_checkout () { + cd /root; git clone https://gerrit.onap.org/r/integration + printf "{\n "simulatorParams": {\n "vesServerUrl": "http://VES-HOST:VES-PORT/eventListener/v7",\n "testDuration": "10",\n "messageInterval": "1"\n },\n "commonEventHeaderParams": {\n "eventName": "pnfRegistration_Nokia_5gDu",\n "nfNamingCode": "gNB",\n "nfcNamingCode": "oam",\n "sourceName": "NOK6061ZW3",\n "sourceId": "val13",\n "reportingEntityName": "NOK6061ZW3"\n },\n "pnfRegistrationParams": {\n "serialNumber": "6061ZW3",\n "vendorName": "Nokia",\n "oamV4IpAddress": "val3",\n "oamV6IpAddress": "val4",\n "unitFamily": "BBU",\n "modelNumber": "val6",\n "softwareVersion": "val7",\n "unitType": "val8"\n }\n}" > integration/test/mocks/pnfsimulator/config/config.json + } + + start_simulator () { + docker login -u docker -p docker nexus3.onap.org:10003 + cd ~/integration/test/mocks/pnfsimulator + ./simulator.sh start + } + + set_versions + enable_root_ssh + update_os + docker_remove + docker_install_and_configure + docker_compose_install + pnf_sim_file_checkout + start_simulator + params: + $proxy: { get_param: proxy } + PNF_PnP_simualtor_port0: + type: OS::Neutron::Port + properties: + network_id: { get_param: private_net_id } + security_groups: + - default + fixed_ips: + - subnet_id: { get_param: private_subnet_id } + PNF_PnP_simualtor_public: + type: OS::Neutron::FloatingIP + properties: + floating_network_id: { get_param: public_net_id } + port_id: { get_resource: PNF_PnP_simualtor_port0 } +outputs: + PNF_PnP_simualtor_private_ip: + description: IP address of PNF_PnP_simualtor in private network + value: { get_attr: [ PNF_PnP_simualtor, first_address ] } + PNF_PnP_simualtor_public_ip: + description: Floating IP address of PNF_PnP_simualtor in public network + value: { get_attr: [ PNF_PnP_simualtor_public, floating_ip_address ] } diff --git a/pnfsimulator/docker-compose.yml b/pnfsimulator/docker-compose.yml new file mode 100644 index 0000000..23797fe --- /dev/null +++ b/pnfsimulator/docker-compose.yml @@ -0,0 +1,38 @@ +version: '3' + +services: + + mongo: + image: mongo + restart: always + environment: + MONGO_INITDB_ROOT_USERNAME: root + MONGO_INITDB_ROOT_PASSWORD: zXcVbN123! + MONGO_INITDB_DATABASE: pnf_simulator + volumes: + - ./db:/docker-entrypoint-initdb.d + ports: + - "27017:27017" + + mongo-express: + image: mongo-express + restart: always + ports: + - 8081:8081 + environment: + ME_CONFIG_MONGODB_ADMINUSERNAME: root + ME_CONFIG_MONGODB_ADMINPASSWORD: zXcVbN123! + + pnf-simulator: + image: nexus3.onap.org:10003/onap/pnfsimulator + ports: + - "5000:5000" + volumes: + - ./logs:/var/log + - ./templates:/app/templates + - ./store:/app/store + - ./src/main/resources/application.properties:/app/application.properties + restart: on-failure + depends_on: + - mongo + - mongo-express diff --git a/pnfsimulator/integration/pom.xml b/pnfsimulator/integration/pom.xml new file mode 100644 index 0000000..21c2f3c --- /dev/null +++ b/pnfsimulator/integration/pom.xml @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + Simulator + ================================================================================ + Copyright (C) 2019 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========================================================= + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.onap.simulator</groupId> + <artifactId>simulator-parent</artifactId> + <version>5.0.0-SNAPSHOT</version> + </parent> + + <artifactId>pnf-simulator-integration</artifactId> + <repositories> + <repository> + <id>dl.bintray.com</id> + <url>https://dl.bintray.com/palantir/releases</url> + </repository> + </repositories> + + <properties> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + </properties> + + <dependencies> + + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>3.9.1</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter</artifactId> + <version>2.0.2.RELEASE</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + <version>2.0.2.RELEASE</version> + </dependency> + + <dependency> + <groupId>io.rest-assured</groupId> + <artifactId>rest-assured</artifactId> + <version>3.2.0</version> + </dependency> + <dependency> + <groupId>org.mongodb</groupId> + <artifactId>mongo-java-driver</artifactId> + <version>3.9.1</version> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <version>5.0.4.RELEASE</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <version>2.0.1.RELEASE</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.8.2</version> + </dependency> + <dependency> + <groupId>com.palantir.docker.compose</groupId> + <artifactId>docker-compose-rule-junit4</artifactId> + <version>0.34.0</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <executions> + <execution> + <id>onap-license</id> + <phase>none</phase> + </execution> + <execution> + <id>onap-java-style</id> + <phase>none</phase> + </execution> + </executions> + <artifactId>maven-checkstyle-plugin</artifactId> + <version>2.17</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.12.1</version> + <configuration> + <includes> + <!--Execute only suites from the test folder--> + <include>**/*Suite.java</include> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/Main.java b/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/Main.java new file mode 100644 index 0000000..7288c2a --- /dev/null +++ b/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/Main.java @@ -0,0 +1,35 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.integration; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; + +@SpringBootApplication +@EnableAsync +public class Main { + + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } +} + + diff --git a/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.java b/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.java new file mode 100644 index 0000000..70e0c60 --- /dev/null +++ b/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.java @@ -0,0 +1,59 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.integration; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequestMapping("ves-simulator") +@RestController +public class VesSimulatorController { + + private final VesSimulatorService vesSimulatorService; + private final Gson gson; + + @Autowired + public VesSimulatorController(VesSimulatorService vesSimulatorService, Gson gson) { + this.vesSimulatorService = vesSimulatorService; + this.gson = gson; + } + + @PostMapping("eventListener/v5") + String sendEventToDmaapV5(@RequestBody String body) { + System.out.println("Received event" + body); + JsonObject jsonObject = gson.fromJson(body, JsonObject.class); + vesSimulatorService.sendEventToDmaapV5(jsonObject); + return "MessageAccepted"; + } + + @PostMapping("eventListener/v7") + String sendEventToDmaapV7(@RequestBody String body) { + System.out.println("Received event" + body); + JsonObject jsonObject = gson.fromJson(body, JsonObject.class); + vesSimulatorService.sendEventToDmaapV7(jsonObject); + return "MessageAccepted"; + } +} diff --git a/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorService.java b/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorService.java new file mode 100644 index 0000000..65e5d3e --- /dev/null +++ b/pnfsimulator/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorService.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.integration; + +import com.google.gson.JsonObject; +import org.springframework.stereotype.Service; + +@Service +public class VesSimulatorService { + + void sendEventToDmaapV5(JsonObject jsonObject) { + //JUST FOR TESTING PURPOSE + } + + void sendEventToDmaapV7(JsonObject jsonObject) { + //JUST FOR TESTING PURPOSE + } +} diff --git a/pnfsimulator/integration/src/main/resources/application.properties b/pnfsimulator/integration/src/main/resources/application.properties new file mode 100644 index 0000000..205ed95 --- /dev/null +++ b/pnfsimulator/integration/src/main/resources/application.properties @@ -0,0 +1 @@ +server.port=8000
\ No newline at end of file diff --git a/pnfsimulator/integration/src/main/resources/keystore b/pnfsimulator/integration/src/main/resources/keystore Binary files differnew file mode 100644 index 0000000..26a16f7 --- /dev/null +++ b/pnfsimulator/integration/src/main/resources/keystore diff --git a/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java b/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java new file mode 100644 index 0000000..9f11a00 --- /dev/null +++ b/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java @@ -0,0 +1,235 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.integration; + +import static io.restassured.RestAssured.given; +import static io.restassured.RestAssured.when; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.hamcrest.Matchers.equalTo; + +import com.google.gson.JsonObject; +import java.io.IOException; +import java.net.Inet4Address; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.UUID; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.mockito.internal.util.Timer; +import org.mockito.internal.verification.VerificationOverTimeImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = WebEnvironment.DEFINED_PORT) +public class BasicAvailabilityTest { + + @Autowired + VesSimulatorController vesSimulatorController; + + @Autowired + VesSimulatorService vesSimulatorService; + + private final String ACTION_START = "start"; + + private String currenVesSimulatorIp; + + @Before + public void setUp() throws Exception { + currenVesSimulatorIp = getCurrentIpAddress(); + } + + @After + public void tearDown() { + Mockito.reset(vesSimulatorService); + } + + @Test + public void simulatorShouldFailWhenTriggeredNonexistentTemplate(){ + //given + String startUrl = prepareRequestUrl(ACTION_START); + String body = "{\n" + + "\"templateName\": \"any_nonexistent_template.json\",\n" + + "\"patch\":{},\n" + + "\"simulatorParams\": {\n" + + "\"vesServerUrl\": \"https://" + currenVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n" + + "\"repeatInterval\": 1,\n" + + "\"repeatCount\": 1\n" + + "}\n" + + "}"; + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(startUrl) + .then() + .statusCode(400) + .body("message", equalTo("Cannot start simulator - template any_nonexistent_template.json not found.")); + } + + @Test + public void whenTriggeredSimulatorShouldSendSingleEventToVes() { + //given + String startUrl = prepareRequestUrl(ACTION_START); + String body = "{\n" + + "\"templateName\": \"notification.json\",\n" + + "\"patch\":{},\n" + + "\"simulatorParams\": {\n" + + "\"vesServerUrl\": \"https://" + currenVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n" + + "\"repeatInterval\": 1,\n" + + "\"repeatCount\": 1\n" + + "}\n" + + "}"; + ArgumentCaptor<JsonObject> parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(startUrl) + .then() + .statusCode(200) + .body("message", equalTo("Request started")); + + Mockito.verify(vesSimulatorService, + Mockito.timeout(3000)) + .sendEventToDmaapV5(parameterCaptor.capture()); + + assertThat(parameterCaptor.getValue() + .getAsJsonObject("event") + .getAsJsonObject("commonEventHeader") + .get("domain").getAsString()).isEqualTo("notification"); + } + + @Test + public void simulatorShouldCorrectlyRespondOnCancellAllEvent() { + //given + String ACTION_CANCEL_ALL = "cancel"; + String cancelAllUrl = prepareRequestUrl(ACTION_CANCEL_ALL); + + //when + when() + .post(cancelAllUrl) + .then() + .statusCode(200) + .body("message", equalTo("Event(s) was cancelled")); + + } + + @Test + public void simulatorBeAbleToUseNewlyAddedTemplate() throws IOException { + //given + String templateBody = "{\"fake\":\"template\"}\n"; + String fileName = UUID.randomUUID() + ".json"; + String requestBody = "{\n" + + "\"templateName\": \"" + fileName + "\",\n" + + "\"patch\":{},\n" + + "\"simulatorParams\": {\n" + + "\"vesServerUrl\": \"https://" + currenVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n" + + "\"repeatInterval\": 1,\n" + + "\"repeatCount\": 1\n" + + "}\n" + + "}"; + ArgumentCaptor<JsonObject> parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + Path newFile = Files.createFile(Paths.get("..", "templates", fileName)); + Files.write(newFile, templateBody.getBytes()); + + given() + .contentType("application/json") + .body(requestBody) + .when() + .post(prepareRequestUrl(ACTION_START)); + + Files.delete(newFile); + + //then + Mockito.verify(vesSimulatorService, Mockito.timeout(3000)) + .sendEventToDmaapV5(parameterCaptor.capture()); + assertThat(parameterCaptor.getValue() + .get("fake").getAsString()).isEqualTo("template"); + + } + + @Test + public void whenTriggeredSimulatorShouldSendGivenAmountOfEventsToVes() { + //given + String startUrl = prepareRequestUrl(ACTION_START); + String body = "{\n" + + "\"templateName\": \"notification.json\",\n" + + "\"patch\":{},\n" + + "\"simulatorParams\": {\n" + + "\"vesServerUrl\": \"https://" + currenVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n" + + "\"repeatInterval\": 1,\n" + + "\"repeatCount\": 4\n" + + "}\n" + + "}"; + ArgumentCaptor<JsonObject> parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(startUrl) + .then() + .statusCode(200) + .body("message", equalTo("Request started")); + + VerificationOverTimeImpl verificator = new VerificationOverTimeImpl(100, Mockito.times(4), false, new Timer(6000)); + Mockito.verify(vesSimulatorService, verificator).sendEventToDmaapV5(parameterCaptor.capture()); + + for (JsonObject value : parameterCaptor.getAllValues()) { + assertThat(value + .getAsJsonObject("event") + .getAsJsonObject("commonEventHeader") + .get("domain").getAsString()).isEqualTo("notification"); + } + } + + private String prepareRequestUrl(String action) { + return "http://0.0.0.0:5000/simulator/" + action; + } + + private String getCurrentIpAddress() throws SocketException { + return Collections.list(NetworkInterface.getNetworkInterfaces()).stream() + .flatMap(i -> Collections.list(i.getInetAddresses()).stream()) + .filter(ip -> ip instanceof Inet4Address) + .map(e -> (Inet4Address) e) + .findFirst() + .orElseThrow(RuntimeException::new) + .getHostAddress(); + } +} diff --git a/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java b/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java new file mode 100644 index 0000000..a5ffe4d --- /dev/null +++ b/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java @@ -0,0 +1,204 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.integration; + +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.hamcrest.Matchers.equalTo; + +import com.google.gson.JsonObject; +import com.mongodb.MongoClient; +import com.mongodb.MongoClientOptions; +import com.mongodb.MongoCredential; +import com.mongodb.ServerAddress; +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoCursor; +import com.mongodb.client.MongoDatabase; +import java.time.Instant; +import java.net.Inet4Address; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Collections; +import org.assertj.core.api.Assertions; +import org.bson.Document; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = WebEnvironment.DEFINED_PORT) +public class OptionalTemplatesTest { + + private static final String PNF_SIMULATOR_DB = "pnf_simulator"; + private static final String COMMON_EVENT_HEADER = "commonEventHeader"; + private static final String PNF_SIMULATOR_DB_PSWD = "zXcVbN123!"; + private static final String PNF_SIMULATOR_DB_USER = "pnf_simulator_user"; + private static final String PATCHED = "patched"; + private static final String SINGLE_EVENT_URL = "http://0.0.0.0:5000/simulator/event"; + + @Autowired + VesSimulatorController vesSimulatorController; + + @Autowired + private VesSimulatorService vesSimulatorService; + + private String currentVesSimulatorIp; + + @Before + public void setUp() throws Exception { + currentVesSimulatorIp = getCurrentIpAddress(); + } + + @After + public void tearDown() { + Mockito.reset(vesSimulatorService); + } + + @Test + public void whenTriggeredSimulatorWithoutTemplateShouldSendSingleEventToVes() { + //given + long currentTimestamp = Instant.now().getEpochSecond(); + + String body = "{\n" + + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n" + + "\"event\": { \n" + + "\"commonEventHeader\": {\n" + + "\"eventId1\": \"#RandomString(20)\",\n" + + "\"eventId2\": \"#RandomInteger(10,10)\",\n" + + "\"eventId3\": \"#Increment\",\n" + + "\"eventId4\": \"#RandomPrimitiveInteger(10,10)\",\n" + + "\"eventId5\": \"#TimestampPrimitive\",\n" + + "\"sourceName\": \"Single_sourceName\",\n" + + "\"version\": 3" + + "}\n" + + "}\n" + + "}"; + ArgumentCaptor<JsonObject> parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(SINGLE_EVENT_URL) + .then() + .statusCode(202) + .body("message", equalTo("One-time direct event sent successfully")); + + //then + long afterExecution = Instant.now().getEpochSecond(); + Mockito.verify(vesSimulatorService, + Mockito.timeout(3000)) + .sendEventToDmaapV5(parameterCaptor.capture()); + + JsonObject value = parameterCaptor.getValue(); + assertThat(value + .getAsJsonObject(COMMON_EVENT_HEADER) + .get("sourceName").getAsString()).isEqualTo("Single_sourceName"); + assertThat(value + .getAsJsonObject(COMMON_EVENT_HEADER) + .get("eventId1").getAsString().length()).isEqualTo(20); + assertThat(value + .getAsJsonObject(COMMON_EVENT_HEADER) + .get("eventId2").getAsString()).isEqualTo("10"); + assertThat(value + .getAsJsonObject(COMMON_EVENT_HEADER) + .get("eventId3").getAsString()).isEqualTo("1"); + assertThat(value + .getAsJsonObject(COMMON_EVENT_HEADER) + .get("eventId4").getAsInt()).isEqualTo(10); + assertThat(value + .getAsJsonObject(COMMON_EVENT_HEADER) + .get("eventId5").getAsLong()).isBetween(currentTimestamp, afterExecution); + } + + @Test + public void whenTriggeredSimulatorWithoutTemplateEventShouldBeVisibleInDB() throws UnknownHostException { + //given + String body = "{\n" + + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n" + + "\"event\": { \n" + + "\"commonEventHeader\": {\n" + + "\"sourceName\": \"HistoricalEvent\",\n" + + "\"version\": 3" + + "}\n" + + "}\n" + + "}"; + ArgumentCaptor<JsonObject> parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(SINGLE_EVENT_URL) + .then() + .statusCode(202) + .body("message", equalTo("One-time direct event sent successfully")); + + //then + Mockito.verify(vesSimulatorService, + Mockito.timeout(3000)) + .sendEventToDmaapV5(parameterCaptor.capture()); + + Document sourceNameInMongoDB = findSourceNameInMongoDB(); + Assertions.assertThat(sourceNameInMongoDB.get(PATCHED)) + .isEqualTo("{\"commonEventHeader\":{\"sourceName\":\"HistoricalEvent\",\"version\":3}}"); + } + + private Document findSourceNameInMongoDB() throws UnknownHostException { + MongoCredential credential = MongoCredential + .createCredential(PNF_SIMULATOR_DB_USER, PNF_SIMULATOR_DB, PNF_SIMULATOR_DB_PSWD.toCharArray()); + MongoClient mongoClient = new MongoClient(new ServerAddress(Inet4Address.getLocalHost(), 27017), + credential, MongoClientOptions.builder().build()); + MongoDatabase pnfSimulatorDb = mongoClient.getDatabase(PNF_SIMULATOR_DB); + MongoCollection<Document> table = pnfSimulatorDb.getCollection("eventData"); + Document searchQuery = new Document(); + searchQuery.put(PATCHED, new Document("$regex", ".*" + "HistoricalEvent" + ".*")); + FindIterable<Document> findOfPatched = table.find(searchQuery); + Document dbObject = null; + MongoCursor<Document> cursor = findOfPatched.iterator(); + if (cursor.hasNext()) { + dbObject = cursor.next(); + } + return dbObject; + } + + private String getCurrentIpAddress() throws SocketException { + return Collections.list(NetworkInterface.getNetworkInterfaces()).stream() + .flatMap(i -> Collections.list(i.getInetAddresses()).stream()) + .filter(ip -> ip instanceof Inet4Address) + .map(e -> (Inet4Address) e) + .findFirst() + .orElseThrow(RuntimeException::new) + .getHostAddress(); + } + +} diff --git a/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/SearchInTemplatesTest.java b/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/SearchInTemplatesTest.java new file mode 100644 index 0000000..9d4ff3b --- /dev/null +++ b/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/SearchInTemplatesTest.java @@ -0,0 +1,269 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.integration; + +import static io.restassured.RestAssured.given; +import static java.nio.file.Files.readAllBytes; + +import io.restassured.http.Header; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import org.hamcrest.Matchers; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.util.ResourceUtils; + +public class SearchInTemplatesTest { + + private static final String UPLOAD = "upload"; + private static final String SEARCH = "search"; + private static final String APPLICATION_JSON = "application/json"; + private static final String CONTENT_TYPE = "Content-Type"; + + @BeforeClass + public static void setUp() throws IOException { + for (File file : readFileFromTemplatesFolder()) { + byte[] body = readAllBytes(file.toPath()); + + given() + .body(body) + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(UPLOAD) + "?override=true") + .then() + .statusCode(201); + } + } + + @Test + public void shouldFindNothingWhenNonexistentValueIsProvided(){ + given() + .body("{\"searchExpr\": { \"child3\": \"nonexistentValue\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.empty()); + } + + @Test + public void shouldFindNothingWhenNonexistentKeyIsProvided(){ + given() + .body("{\"searchExpr\": { \"nonexistentKey\": \"Any value 1\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.empty()); + } + + @Test + public void shouldFindNothingWhenPartOfKeyIsProvided(){ + given() + .body("{\"searchExpr\": { \"child\": \"Any value 1\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.empty()); + } + + @Test + public void shouldFindNothingWhenPartOfValueIsProvided(){ + given() + .body("{\"searchExpr\": { \"child5\": \"Any\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.empty()); + } + + @Test + public void shouldBeAbleToSearchForString(){ + given() + .body("{\"searchExpr\": { \"child1\": \"Any value 1\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_array.json", "complicated_template.json", "simple_template.json")); + + given() + .body("{\"searchExpr\": { \"child2\": \"any value 4\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_array.json")); + } + + @Test + public void shouldBeAbleToSearchForManyStrings(){ + given() + .body("{\"searchExpr\": { \"child1\": \"Any value 1\", \"child2\": \"any value 2\"}}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("simple_template.json", "complicated_template.json")); + } + + @Test + public void shouldBeAbleToSearchForStarSign(){ + given() + .body("{\"searchExpr\": { \"child2\": \"*\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("complicated_template.json")); + } + + @Test + public void shouldBeAbleToSearchForQuestionMark(){ + given() + .body("{\"searchExpr\": { \"child1\": \"?\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("complicated_template.json")); + } + + @Test + public void shouldBeAbleToSearchForBrackets(){ + given() + .body("{\"searchExpr\": { \"parent2\": \"[]\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_array.json")); + } + + @Test + public void shouldInformThatSearchForNullsIsProhibited(){ + given() + .body("{\"searchExpr\": { \"child3\": null }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(400); + } + + @Test + public void shouldBeAbleToSearchForURI(){ + given() + .body("{\"searchExpr\": { \"child3\": \"https://url.com?param1=test¶m2=*\" }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("complicated_template.json")); + } + + @Test + public void shouldBeAbleToSearchForFloats(){ + given() + .body("{\"searchExpr\": { \"child2\": 4.44 }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_array.json")); + + given() + .body("{\"searchExpr\": { \"child5\": 4.4 }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("complicated_template.json", "template_with_floats.json")); + } + + @Test + public void shouldBeAbleToSearchForIntegers(){ + given() + .body("{\"searchExpr\": { \"child2\": 1 }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_array.json", "template_with_ints.json")); + + given() + .body("{\"searchExpr\": { \"child2\": 4 }}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_array.json")); + } + + @Test + public void shouldBeAbleToSearchForBooleans(){ + given() + .body("{\"searchExpr\": { \"child4\": true}}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_booleans.json")); + + given() + .body("{\"searchExpr\": { \"parent2\": false}}") + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(SEARCH)) + .then() + .statusCode(200) + .body("", Matchers.hasItems("template_with_booleans.json")); + } + + + private static String prepareRequestUrl(String action) { + return "http://0.0.0.0:5000/template/" + action; + } + + private static File[] readFileFromTemplatesFolder() throws FileNotFoundException { + return ResourceUtils.getFile("classpath:templates/search").listFiles(); + } + +} diff --git a/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TemplatesManagementTest.java b/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TemplatesManagementTest.java new file mode 100644 index 0000000..7e74dd4 --- /dev/null +++ b/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TemplatesManagementTest.java @@ -0,0 +1,175 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.integration; + +import static io.restassured.RestAssured.given; + +import io.restassured.http.Header; +import io.restassured.path.json.JsonPath; +import io.restassured.path.json.config.JsonPathConfig; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; +import org.hamcrest.Matchers; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.ResourceUtils; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = WebEnvironment.DEFINED_PORT) +public class TemplatesManagementTest { + + private static final String LIST_URL = "list"; + private static final String GET_URL = "get/"; + private static final String UPLOAD = "upload"; + private static final String NOTIFICATION_JSON = "notification.json"; + private static final String REGISTRATION_JSON = "registration.json"; + private static final String UPLOAD_TEMPLATE_JSON = "upload_template.json"; + private static final String OVERWRITE_TEMPLATE_JSON = "overwrite_template.json"; + private static final String OVERWRITTEN_TEMPLATE_JSON = "overwritten_template.json"; + private static final String APPLICATION_JSON = "application/json"; + private static final String CONTENT_TYPE = "Content-Type"; + private static final String FORCE_FLAG = "?override=true"; + private static final String CONTENT = "content"; + private static final String TEMPLATE = "template"; + private static final String ID = "id"; + + @Test + public void whenCallingGetShouldReceiveNotificationTemplate() throws IOException { + given() + .when() + .get(prepareRequestUrl(GET_URL) + NOTIFICATION_JSON) + .then() + .statusCode(200) + .body(ID, Matchers.equalTo(NOTIFICATION_JSON)) + .body(CONTENT, Matchers.equalTo(readTemplateFromResources(NOTIFICATION_JSON).getMap(CONTENT))); + } + + @Test + public void whenCallingGetShouldReceiveRegistrationTemplate() throws IOException { + given() + .when() + .get(prepareRequestUrl(GET_URL) + REGISTRATION_JSON) + .then() + .statusCode(200) + .body(ID, Matchers.equalTo(REGISTRATION_JSON)) + .body(CONTENT, Matchers.equalTo(readTemplateFromResources(REGISTRATION_JSON).getMap(CONTENT))); + } + + @Test + public void whenCallingListShouldReceiveAllPredefinedTemplates() throws IOException { + Map<Object, Object> registration = readTemplateFromResources(REGISTRATION_JSON).getMap(CONTENT); + Map<Object, Object> notification = readTemplateFromResources(NOTIFICATION_JSON).getMap(CONTENT); + + given() + .when() + .get(prepareRequestUrl(LIST_URL)) + .then() + .statusCode(200) + .body(CONTENT, Matchers.<Map>hasItems( + registration, + notification + )); + } + + @Test + public void whenCallingUploadAndGetShouldReceiveNewTemplate() throws IOException { + byte[] body = Files.readAllBytes(readFileFromTemplatesFolder(UPLOAD_TEMPLATE_JSON)); + + given() + .body(body) + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(UPLOAD)) + .then() + .statusCode(201); + + given() + .when() + .get(prepareRequestUrl(GET_URL) + UPLOAD_TEMPLATE_JSON) + .then() + .statusCode(200) + .body(ID, Matchers.equalTo(UPLOAD_TEMPLATE_JSON)) + .body(CONTENT, Matchers.equalTo(readTemplateFromResources(UPLOAD_TEMPLATE_JSON).getMap(TEMPLATE))); + } + + @Test + public void whenCallingOverrideAndGetShouldReceiveNewTemplate() throws IOException, JSONException { + byte[] body = Files.readAllBytes(readFileFromTemplatesFolder(OVERWRITE_TEMPLATE_JSON)); + + given() + .body(body) + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(UPLOAD)) + .then() + .statusCode(201); + + JSONObject overwrittenBody = new JSONObject(new String(body)); + JSONObject overwrittenTemplate = new JSONObject("{\"field1\": \"overwritten_field1\"}"); + overwrittenBody.put(TEMPLATE, overwrittenTemplate); + + given() + .body(overwrittenBody.toString().getBytes()) + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(UPLOAD)) + .then() + .statusCode(409); + + given() + .body(overwrittenBody.toString().getBytes()) + .header(new Header(CONTENT_TYPE, APPLICATION_JSON)) + .when() + .post(prepareRequestUrl(UPLOAD + FORCE_FLAG)) + .then() + .statusCode(201); + + given() + .when() + .get(prepareRequestUrl(GET_URL) + OVERWRITE_TEMPLATE_JSON) + .then() + .statusCode(200) + .body(ID, Matchers.equalTo(OVERWRITE_TEMPLATE_JSON)) + .body(CONTENT, Matchers.equalTo(readTemplateFromResources(OVERWRITTEN_TEMPLATE_JSON).getMap(CONTENT))); + } + + private String prepareRequestUrl(String action) { + return "http://0.0.0.0:5000/template/" + action; + } + + private JsonPath readTemplateFromResources(String templateName) throws IOException { + byte[] content = Files.readAllBytes(readFileFromTemplatesFolder(templateName)); + return new JsonPath(new String(content)).using(new JsonPathConfig("UTF-8")); + } + + private Path readFileFromTemplatesFolder(String templateName) throws FileNotFoundException { + return ResourceUtils.getFile("classpath:templates/"+templateName).toPath(); + } + +} diff --git a/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TestConfiguration.java b/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TestConfiguration.java new file mode 100644 index 0000000..19ae050 --- /dev/null +++ b/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/TestConfiguration.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.integration; + +import org.mockito.Mockito; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +@Configuration +public class TestConfiguration { + + @Bean + @Primary + VesSimulatorService provideVesSimulatorService() { + return Mockito.mock(VesSimulatorService.class); + } +} diff --git a/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java b/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java new file mode 100644 index 0000000..cc2ac58 --- /dev/null +++ b/pnfsimulator/integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.integration.suites; + +import com.palantir.docker.compose.DockerComposeRule; +import com.palantir.docker.compose.connection.waiting.HealthChecks; +import org.junit.ClassRule; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; +import org.onap.pnfsimulator.integration.BasicAvailabilityTest; +import org.onap.pnfsimulator.integration.OptionalTemplatesTest; +import org.onap.pnfsimulator.integration.SearchInTemplatesTest; +import org.onap.pnfsimulator.integration.TemplatesManagementTest; + +@RunWith(Suite.class) +@SuiteClasses({BasicAvailabilityTest.class, TemplatesManagementTest.class, OptionalTemplatesTest.class, + SearchInTemplatesTest.class}) +public class DockerBasedTestsSuite { + + @ClassRule + public static DockerComposeRule docker = DockerComposeRule.builder() + .file("../docker-compose.yml") + .waitingForService("pnf-simulator", HealthChecks.toHaveAllPortsOpen()) + .waitingForService("mongo", HealthChecks.toHaveAllPortsOpen()) + .build(); + +} diff --git a/pnfsimulator/integration/src/test/resources/application.properties b/pnfsimulator/integration/src/test/resources/application.properties new file mode 100644 index 0000000..c3e1472 --- /dev/null +++ b/pnfsimulator/integration/src/test/resources/application.properties @@ -0,0 +1,6 @@ +server.port=9443 +security.require-ssl=true +server.ssl.key-store=src/main/resources/keystore +server.ssl.key-store-password=collector +server.ssl.keyStoreType=JKS +server.ssl.keyAlias=tomcat
\ No newline at end of file diff --git a/pnfsimulator/integration/src/test/resources/templates/notification.json b/pnfsimulator/integration/src/test/resources/templates/notification.json new file mode 100644 index 0000000..0b4ff2e --- /dev/null +++ b/pnfsimulator/integration/src/test/resources/templates/notification.json @@ -0,0 +1,45 @@ +{ + "id": "notification.json", + "content": { + "event": { + "commonEventHeader": { + "domain": "notification", + "eventName": "vFirewallBroadcastPackets", + "eventId": "4cfc-91cf-31a46", + "priority": "Normal", + "reportingEntityName": "myVNF", + "sequence": 1, + "sourceName": "ClosedLoopVNF", + "startEpochMicrosec": 1531616794, + "lastEpochMicrosec": 1531719042, + "vesEventListenerVersion": "7.0.1", + "version": "4.0.1" + }, + "notificationFields": { + "changeIdentifier": "PM_MEAS_FILES", + "changeType": "FileReady", + "arrayOfNamedHashMap": [ + { + "name": "A20161221.1031-1041.bin.gz", + "hashMap": { + "fileformatType": "org.3GPP.32.435#measCollec", + "fileFormatVersion": "V10", + "location": "ftpes://192.169.0.1:22/ftp/rop/A20161224.1030-1045.bin.gz", + "compression": "gzip" + } + }, + { + "name": "A20161222.1042-1102.bin.gz", + "hashMap": { + "fileFormatType": "org.3GPP.32.435#measCollec", + "fileFormatVersion": "V10", + "location": "ftpes://192.168.0.102:22/ftp/rop/A20161224.1045-1100.bin.gz", + "compression": "gzip" + } + } + ], + "notificationFieldsVersion": "2.0" + } + } + } +} diff --git a/pnfsimulator/integration/src/test/resources/templates/overwrite_template.json b/pnfsimulator/integration/src/test/resources/templates/overwrite_template.json new file mode 100644 index 0000000..55bf763 --- /dev/null +++ b/pnfsimulator/integration/src/test/resources/templates/overwrite_template.json @@ -0,0 +1,6 @@ +{ + "name": "overwrite_template.json", + "template": { + "field1": "field1" + } +} diff --git a/pnfsimulator/integration/src/test/resources/templates/overwritten_template.json b/pnfsimulator/integration/src/test/resources/templates/overwritten_template.json new file mode 100644 index 0000000..28e7381 --- /dev/null +++ b/pnfsimulator/integration/src/test/resources/templates/overwritten_template.json @@ -0,0 +1,6 @@ +{ + "id": "overwrite_template.json", + "content": { + "field1": "overwritten_field1" + } +} diff --git a/pnfsimulator/integration/src/test/resources/templates/registration.json b/pnfsimulator/integration/src/test/resources/templates/registration.json new file mode 100644 index 0000000..8b7908e --- /dev/null +++ b/pnfsimulator/integration/src/test/resources/templates/registration.json @@ -0,0 +1,36 @@ +{ + "id": "registration.json", + "content": { + "event": { + "commonEventHeader": { + "eventId": "registration_39239592", + "eventType": "pnfRegistration", + "reportingEntityName": "NOK6061ZW3", + "domain": "pnfRegistration", + "nfcNamingCode": "oam", + "sequence": 0, + "sourceId": "val13", + "internalHeaderFields": {}, + "priority": "Normal", + "sourceName": "NOK6061ZW3", + "eventName": "pnfRegistration_Nokia_5gDu", + "version": "4.0.1", + "nfNamingCode": "gNB", + "startEpochMicrosec": 1539239592379, + "vesEventListenerVersion": "7.0.1", + "lastEpochMicrosec": 1539239592379 + }, + "pnfRegistrationFields": { + "pnfRegistrationFieldsVersion": "2.0", + "serialNumber": "6061ZW3", + "vendorName": "Nokia", + "oamV4IpAddress": "val3", + "oamV6IpAddress": "val4", + "unitFamily": "BBU", + "modelNumber": "val6", + "softwareVersion": "val7", + "unitType": "val8" + } + } + } +} diff --git a/pnfsimulator/integration/src/test/resources/templates/search/complicated_template.json b/pnfsimulator/integration/src/test/resources/templates/search/complicated_template.json new file mode 100644 index 0000000..962600d --- /dev/null +++ b/pnfsimulator/integration/src/test/resources/templates/search/complicated_template.json @@ -0,0 +1,43 @@ +{ + "name": "complicated_template.json", + "template": { + "parent": { + "child1": "Any value 1", + "child2": { + "parent": { + "child1": "Any value 1", + "child2": "Any value 2", + "child3": { + "child4": "Any value 4" + }, + "child4": [ + "Any value 1", + "Any value 2, Any value 3" + ], + "child5": [ + "Any value 4", + 1, + 2, + 4.4, + { + "child6": [ + 1, + 2, + 4.4 + ] + } + ] + } + }, + "child3": { + "child4": "Any value 4" + } + }, + "parent2": "Any value 2", + "parent3": { + "child1": "?", + "child2": "*", + "child3": "https://url.com?param1=test¶m2=*" + } + } +} diff --git a/pnfsimulator/integration/src/test/resources/templates/search/simple_template.json b/pnfsimulator/integration/src/test/resources/templates/search/simple_template.json new file mode 100644 index 0000000..d209a9e --- /dev/null +++ b/pnfsimulator/integration/src/test/resources/templates/search/simple_template.json @@ -0,0 +1,12 @@ +{ + "name": "simple_template.json", + "template": { + "parent": { + "child1": "Any value 1", + "child2": "Any value 2", + "child3": { + "child4": "Any value 4" + } + } + } +} diff --git a/pnfsimulator/integration/src/test/resources/templates/search/template_with_array.json b/pnfsimulator/integration/src/test/resources/templates/search/template_with_array.json new file mode 100644 index 0000000..0ed4326 --- /dev/null +++ b/pnfsimulator/integration/src/test/resources/templates/search/template_with_array.json @@ -0,0 +1,23 @@ +{ + "name": "template_with_array.json", + "template": { + "parent": { + "child1": [ + { + "child1": "Any value 1", + "child2": [ + 4, + 4.44 + ] + } + ], + "child2": [ + 1, + "Any value 4", + 3.3, + 5 + ] + }, + "parent2": "[]" + } +} diff --git a/pnfsimulator/integration/src/test/resources/templates/search/template_with_booleans.json b/pnfsimulator/integration/src/test/resources/templates/search/template_with_booleans.json new file mode 100644 index 0000000..4954663 --- /dev/null +++ b/pnfsimulator/integration/src/test/resources/templates/search/template_with_booleans.json @@ -0,0 +1,12 @@ +{ + "name": "template_with_booleans.json", + "template": { + "parent": { + "child1": true, + "child3": { + "child4": true + } + }, + "parent2": false + } +} diff --git a/pnfsimulator/integration/src/test/resources/templates/search/template_with_floats.json b/pnfsimulator/integration/src/test/resources/templates/search/template_with_floats.json new file mode 100644 index 0000000..2b8caf4 --- /dev/null +++ b/pnfsimulator/integration/src/test/resources/templates/search/template_with_floats.json @@ -0,0 +1,13 @@ +{ + "name": "template_with_floats.json", + "template": { + "parent": { + "child1": 6.4, + "child2": 1.2, + "child3": { + "child5": 4.4, + "child2": "1" + } + } + } +} diff --git a/pnfsimulator/integration/src/test/resources/templates/search/template_with_ints.json b/pnfsimulator/integration/src/test/resources/templates/search/template_with_ints.json new file mode 100644 index 0000000..369b0b4 --- /dev/null +++ b/pnfsimulator/integration/src/test/resources/templates/search/template_with_ints.json @@ -0,0 +1,12 @@ +{ + "name": "template_with_ints.json", + "template": { + "parent": { + "child1": 6, + "child2": 1, + "child3": { + "child4": 4 + } + } + } +} diff --git a/pnfsimulator/integration/src/test/resources/templates/upload_template.json b/pnfsimulator/integration/src/test/resources/templates/upload_template.json new file mode 100644 index 0000000..df3ae28 --- /dev/null +++ b/pnfsimulator/integration/src/test/resources/templates/upload_template.json @@ -0,0 +1,6 @@ +{ + "name": "upload_template.json", + "template": { + "field1": "field1" + } +} diff --git a/pnfsimulator/pom.xml b/pnfsimulator/pom.xml new file mode 100644 index 0000000..9a8e796 --- /dev/null +++ b/pnfsimulator/pom.xml @@ -0,0 +1,403 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + Simulator + ================================================================================ + Copyright (C) 2019 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========================================================= + --> + + +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.onap.simulator</groupId> + <artifactId>simulator-parent</artifactId> + <version>5.0.0-SNAPSHOT</version> + </parent> + + <artifactId>pnfsimulator</artifactId> + <version>5.0.0-SNAPSHOT</version> + + <name>pnfsimulator</name> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format> + + <simulator.main.class>org.onap.pnfsimulator.Main</simulator.main.class> + <docker.image.tag>latest</docker.image.tag> + <junit.jupiter.version>5.1.0</junit.jupiter.version> + <junit.vintage.version>5.1.0</junit.vintage.version> + <spring.boot.version>2.1.0.RELEASE</spring.boot.version> + <docker.image.name>onap/${project.artifactId}</docker.image.name> + + <dependency.directory.name>libs</dependency.directory.name> + <dependency.directory.location>${project.build.directory}/${dependency.directory.name} + </dependency.directory.location> + + <onap.nexus.dockerregistry.daily>nexus3.onap.org:10003</onap.nexus.dockerregistry.daily> + <onap.nexus.url>http://nexus3.onap.org</onap.nexus.url> + </properties> + + <dependencies> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter</artifactId> + <version>${spring.boot.version}</version> + <exclusions> + <exclusion> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + <version>${spring.boot.version}</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-mongodb</artifactId> + <version>${spring.boot.version}</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-actuator</artifactId> + <version>${spring.boot.version}</version> + </dependency> + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-config-client</artifactId> + <version>2.1.4.RELEASE</version> + </dependency> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + <version>1.2.3</version> + </dependency> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-core</artifactId> + <version>1.2.3</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>1.7.25</version> + </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.6</version> + </dependency> + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + <version>20180130</version> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.8.2</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.5.5</version> + </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>21.0</version> + </dependency> + <dependency> + <groupId>commons-cli</groupId> + <artifactId>commons-cli</artifactId> + <version>1.4</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.7</version> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.2</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-jdk8</artifactId> + <version>2.9.7</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-jsr310</artifactId> + <version>2.9.7</version> + </dependency> + <dependency> + <groupId>io.vavr</groupId> + <artifactId>vavr-match</artifactId> + <version>0.9.2</version> + </dependency> + <dependency> + <groupId>io.vavr</groupId> + <artifactId>vavr</artifactId> + <version>0.9.2</version> + </dependency> + + + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <version>${junit.jupiter.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-migrationsupport</artifactId> + <version>${junit.jupiter.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>3.9.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>2.18.3</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <version>5.0.4.RELEASE</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <version>${spring.boot.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger2</artifactId> + <version>2.9.2</version> + </dependency> + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger-ui</artifactId> + <version>2.9.2</version> + </dependency> + <dependency> + <groupId>org.quartz-scheduler</groupId> + <artifactId>quartz</artifactId> + <version>2.2.1</version> + </dependency> + <dependency> + <groupId>org.quartz-scheduler</groupId> + <artifactId>quartz-jobs</artifactId> + <version>2.2.1</version> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <descriptor>src/assembly/resources.xml</descriptor> + <finalName>${project.artifactId}-${project.version}</finalName> + </configuration> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.7.0</version> + <configuration> + <source>${maven.compiler.source}</source> + <target>${maven.compiler.target}</target> + <showWarnings>true</showWarnings> + <showDeprecation>true</showDeprecation> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>3.0.2</version> + <configuration> + <archive> + <manifestEntries> + <Main-Class>${simulator.main.class}</Main-Class> + <Build-Time>${maven.build.timestamp}</Build-Time> + </manifestEntries> + </archive> + </configuration> + </plugin> + <plugin> + <groupId>pl.project13.maven</groupId> + <artifactId>git-commit-id-plugin</artifactId> + <version>2.2.4</version> + <executions> + <execution> + <id>get-commit-info</id> + <goals> + <goal>revision</goal> + </goals> + </execution> + </executions> + <configuration> + <dotGitDirectory>${project.basedir}/.git</dotGitDirectory> + <generateGitPropertiesFile>true</generateGitPropertiesFile> + <includeOnlyProperties>git.commit.id.abbrev</includeOnlyProperties> + </configuration> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.19</version> + <dependencies> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-surefire-provider</artifactId> + <version>1.1.1</version> + </dependency> + </dependencies> + <configuration> + <detail>true</detail> + <printSummary>true</printSummary> + <useSystemClassLoader>false</useSystemClassLoader> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <configuration> + <outputDirectory>${dependency.directory.location}</outputDirectory> + <includeScope>runtime</includeScope> + <silent>true</silent> + </configuration> + <executions> + <execution> + <id>copy-external-dependencies</id> + <phase>package</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <version>0.8.1</version> + <configuration> + <excludes> + <exclude>org/onap/pnfsimulator/Main.class</exclude> + </excludes> + </configuration> + <executions> + <execution> + <id>default-prepare-agent</id> + <goals> + <goal>prepare-agent</goal> + </goals> + </execution> + <execution> + <id>report</id> + <phase>prepare-package</phase> + <goals> + <goal>report</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + <profiles> + <profile> + <id>docker</id> + <activation> + <activeByDefault>false</activeByDefault> + </activation> + <properties> + <os.detected.name>linux</os.detected.name> + <os.detected.arch>x86_64</os.detected.arch> + <os.detected.classifier>${os.detected.name}-${os.detected.arch}</os.detected.classifier> + </properties> + <build> + <plugins> + <plugin> + <groupId>io.fabric8</groupId> + <artifactId>docker-maven-plugin</artifactId> + <version>${docker-maven-plugin.version}</version> + <executions> + <execution> + <id>docker-build-image</id> + <phase>package</phase> + <goals> + <goal>build</goal> + </goals> + </execution> + <execution> + <id>docker-push-image</id> + <phase>deploy</phase> + <goals> + <goal>push</goal> + </goals> + </execution> + </executions> + <configuration> + <skipPush>${skipDockerPush}</skipPush> + <verbose>true</verbose> + <imagePullPolicy>IfNotPresent</imagePullPolicy> + <images> + <image> + <alias>${project.artifactId}</alias> + <name>${onap.nexus.dockerregistry.daily}/${docker.image.name}</name> + <registry>${onap.nexus.dockerregistry.daily}</registry> + <build> + <dockerFileDir>${project.basedir}</dockerFileDir> + <tags> + <tag>${project.version}-${maven.build.timestamp}Z</tag> + </tags> + </build> + </image> + </images> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> diff --git a/pnfsimulator/src/assembly/resources.xml b/pnfsimulator/src/assembly/resources.xml new file mode 100644 index 0000000..35dd3b2 --- /dev/null +++ b/pnfsimulator/src/assembly/resources.xml @@ -0,0 +1,57 @@ +<!-- + ============LICENSE_START======================================================= + Simulator + ================================================================================ + Copyright (C) 2019 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========================================================= + --> + +<assembly> + <id>resources</id> + <formats> + <format>zip</format> + </formats> + + <fileSets> + <fileSet> + <includes> + <include>simulator.sh</include> + </includes> + <lineEnding>unix</lineEnding> + <fileMode>0755</fileMode> + </fileSet> + <fileSet> + <includes> + <include>docker-compose.yml</include> + </includes> + <lineEnding>unix</lineEnding> + <fileMode>0644</fileMode> + </fileSet> + <fileSet> + <directory>config</directory> + <outputDirectory>config</outputDirectory> + <includes> + <include>**/*</include> + </includes> + </fileSet> + <fileSet> + <directory>deployment</directory> + <outputDirectory>deployment</outputDirectory> + <includes> + <include>**/*</include> + </includes> + </fileSet> + </fileSets> +</assembly> diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/Main.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/Main.java new file mode 100644 index 0000000..e0eace2 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/Main.java @@ -0,0 +1,57 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator; + +import javax.annotation.PostConstruct; + +import org.onap.pnfsimulator.filesystem.WatcherService; +import org.onap.pnfsimulator.template.FsToDbTemplateSynchronizer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; + +@SpringBootApplication +@EnableAsync +public class Main { + + private final WatcherService watcherService; + private final FsToDbTemplateSynchronizer fsToDbTemplateSynchronizer; + + @Autowired + public Main(WatcherService watcherService, + FsToDbTemplateSynchronizer fsToDbTemplateSynchronizer) { + this.watcherService = watcherService; + this.fsToDbTemplateSynchronizer = fsToDbTemplateSynchronizer; + } + + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } + + @PostConstruct + public void createWatchers() { + fsToDbTemplateSynchronizer.synchronize(); + watcherService.createWatcher(); + } +} + + diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/SwaggerConfig.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/SwaggerConfig.java new file mode 100644 index 0000000..6e0e18e --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/SwaggerConfig.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator; + +import org.onap.pnfsimulator.simulator.client.utils.ssl.SSLAuthenticationHelper; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@Configuration +@EnableConfigurationProperties(SSLAuthenticationHelper.class) +@EnableSwagger2 +public class SwaggerConfig { + + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.basePackage("org.onap.pnfsimulator")) + .paths(PathSelectors.any()) + .build(); + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/db/Row.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/db/Row.java new file mode 100644 index 0000000..f9a167b --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/db/Row.java @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.db; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Field; + +public abstract class Row { + @Id + @Field("_id") + protected String id; + + public String getId() { + return id; + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/db/Storage.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/db/Storage.java new file mode 100644 index 0000000..ad98ce0 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/db/Storage.java @@ -0,0 +1,41 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.db; + +import com.google.gson.JsonObject; + +import java.util.List; +import java.util.Optional; + +public interface Storage<T extends Row> { + + List<T> getAll(); + + Optional<T> get(String rowId); + + void persist(T row); + + boolean tryPersistOrOverwrite(T row, boolean overwrite); + + void delete(String rowId); + + List<String> getIdsByContentCriteria(JsonObject queryJson); +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventData.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventData.java new file mode 100644 index 0000000..23b1c21 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventData.java @@ -0,0 +1,76 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.event; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Field; + +@Builder +@Getter +@Setter +public class EventData { + @Id + private String id; + + @Field("template") + @JsonInclude + private String template; + + @Field("patched") + @JsonInclude + private String patched; + + @Field("input") + @JsonInclude + private String input; + + @Field("keywords") + @JsonInclude + private String keywords; + + @Field("incrementValue") + @JsonInclude + private int incrementValue; + + protected EventData(String id, String template, String patched, String input, String keywords, int incrementValue) { + this.id = id; + this.template = template; + this.patched = patched; + this.input = input; + this.keywords = keywords; + this.incrementValue = incrementValue; + } + + @Override + public String toString() { + return "EventData{" + + "id='" + id + '\'' + + ", template='" + template + '\'' + + ", patched='" + patched + '\'' + + ", input='" + input + '\'' + + ", keywords='" + keywords + '\'' + + '}'; + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventDataRepository.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventDataRepository.java new file mode 100644 index 0000000..d1a66ab --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventDataRepository.java @@ -0,0 +1,26 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.event; + +import org.springframework.data.mongodb.repository.MongoRepository; + +public interface EventDataRepository extends MongoRepository<EventData, String> { +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventDataService.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventDataService.java new file mode 100644 index 0000000..3568f01 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/event/EventDataService.java @@ -0,0 +1,63 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.event; + +import com.google.gson.JsonObject; +import java.util.List; +import java.util.Optional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class EventDataService { + private final EventDataRepository repository; + + @Autowired + public EventDataService(EventDataRepository repository) { + this.repository = repository; + } + + private EventData persistEventData(String templateString, String patchedString, String inputString, String keywordsString) { + EventData eventData = EventData.builder() + .template(templateString) + .patched(patchedString) + .input(inputString) + .keywords(keywordsString) + .build(); + return repository.save(eventData); + } + + public EventData persistEventData(JsonObject templateJson, JsonObject patchedJson, JsonObject inputJson, + JsonObject keywordsJson) { + return persistEventData(templateJson.toString(), + patchedJson.toString(), + inputJson.toString(), + keywordsJson.toString()); + } + + public List<EventData> getAllEvents() { + return repository.findAll(); + } + + public Optional<EventData> getById(String id) { + return repository.findById(id); + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherConfig.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherConfig.java new file mode 100644 index 0000000..3535e33 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherConfig.java @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.filesystem; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.task.TaskExecutor; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +@Configuration +public class WatcherConfig { + + @Bean + public TaskExecutor watcherTaskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setThreadNamePrefix("pnfsimulator_fs_watcher"); + executor.initialize(); + return executor; + } + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java new file mode 100644 index 0000000..56a5696 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java @@ -0,0 +1,110 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.filesystem; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardWatchEventKinds; +import java.nio.file.WatchEvent; +import java.nio.file.WatchEvent.Kind; +import java.time.Instant; +import java.util.Arrays; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import lombok.extern.slf4j.Slf4j; +import org.bson.json.JsonParseException; +import org.onap.pnfsimulator.db.Storage; +import org.onap.pnfsimulator.template.Template; +import org.bson.Document; + +@Slf4j +public enum WatcherEventProcessor { + CREATED(StandardWatchEventKinds.ENTRY_CREATE) { + @Override + public void processEvent(Path path, Storage<Template> storage) throws IOException { + String content = getContent(path); + String fileName = path.getFileName().toString(); + Document documentsContent = Document.parse(content); + storage.persist(new Template(fileName, documentsContent, Instant.now().getNano())); + log.info("DB record created for template: " + fileName); + } + }, + MODIFIED(StandardWatchEventKinds.ENTRY_MODIFY) { + @Override + public void processEvent(Path path, Storage<Template> storage) throws IOException { + String fileName = path.getFileName().toString(); + String content = getContent(path); + Document documentsContent = Document.parse(content); + Template template = storage.get(fileName).orElse(new Template(fileName, documentsContent, Instant.now().getNano())); + template.setContent(documentsContent); + storage.persist(template); + log.info("DB record modified for template: " + fileName); + } + }, + DELETED(StandardWatchEventKinds.ENTRY_DELETE) { + @Override + public void processEvent(Path path, Storage<Template> storage) { + String fileName = path.getFileName().toString(); + storage.delete(fileName); + log.info("DB record deleted for template: " + fileName); + } + }; + + private final Kind<Path> pathKind; + + String getContent(Path path) throws IOException { + try (Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8)) { + return lines.collect(Collectors.joining(System.lineSeparator())); + } catch (IOException e) { + log.error("Could not get content due to: " + e.getMessage() + " " + e.getCause(), e); + throw e; + } + } + + WatcherEventProcessor(Kind<Path> pathKind) { + this.pathKind = pathKind; + } + + public abstract void processEvent(Path templateName, Storage<Template> storage) throws IOException; + + static void process(WatchEvent<?> event, Storage<Template> storage, Path templatesDir) { + Optional<WatcherEventProcessor> watcherEventProcessor = getWatcherEventProcessor(event); + watcherEventProcessor.ifPresent(processor -> { + try { + final Path templatePath = templatesDir.resolve((Path) event.context()); + processor.processEvent(templatePath, storage); + } catch (IOException e) { + log.error("Error during processing DB record for template.", e); + } catch (JsonParseException e) { + log.error("Invalid JSON format provided for template.", e); + } + }); + } + + private static Optional<WatcherEventProcessor> getWatcherEventProcessor(WatchEvent<?> event) { + return Arrays.stream(values()).filter(value -> value.pathKind.equals(event.kind())).findFirst(); + } + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherService.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherService.java new file mode 100644 index 0000000..26b684d --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherService.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.filesystem; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.core.task.TaskExecutor; +import org.springframework.stereotype.Service; + +@Service +public class WatcherService { + + private TaskExecutor taskExecutor; + private ApplicationContext applicationContext; + + @Autowired + public WatcherService(ApplicationContext applicationContext, TaskExecutor taskExecutor) { + this.taskExecutor = taskExecutor; + this.applicationContext = applicationContext; + } + + public void createWatcher() { + taskExecutor.execute(applicationContext.getBean(WatcherThread.class)); + } + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherThread.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherThread.java new file mode 100644 index 0000000..a202b1f --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/filesystem/WatcherThread.java @@ -0,0 +1,81 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.filesystem; + +import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardWatchEventKinds; +import java.nio.file.WatchEvent; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; +import lombok.extern.slf4j.Slf4j; +import org.onap.pnfsimulator.db.Storage; +import org.onap.pnfsimulator.template.Template; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class WatcherThread implements Runnable { + + private final WatchService watchService; + private final Storage<Template> storage; + private final Path templatesDir; + + WatcherThread(String templatesDir, WatchService watchService, Storage<Template> storage) throws IOException { + this.watchService = watchService; + this.storage = storage; + this.templatesDir = Paths.get(templatesDir); + registerDirectory(this.templatesDir); + } + + @Autowired + public WatcherThread(@Value("${templates.dir}") String templatesDir, Storage<Template> storage) throws IOException { + this(templatesDir, FileSystems.getDefault().newWatchService(), storage); + } + + private void registerDirectory(Path path) throws IOException { + path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, + StandardWatchEventKinds.ENTRY_MODIFY); + } + + @Override + public void run() { + while (true) { + WatchKey key; + try { + key = watchService.take(); + for (WatchEvent<?> event : key.pollEvents()) { + WatcherEventProcessor.process(event, storage, templatesDir); + } + key.reset(); + } catch (InterruptedException e) { + log.error("Watch service interrupted.", e.getMessage()); + Thread.currentThread().interrupt(); + return; + } + + } + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/logging/MDCVariables.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/logging/MDCVariables.java new file mode 100644 index 0000000..5678f4f --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/logging/MDCVariables.java @@ -0,0 +1,35 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.logging; + +public final class MDCVariables { + + public static final String X_ONAP_REQUEST_ID = "X-ONAP-RequestID"; + public static final String X_INVOCATION_ID = "X-InvocationID"; + public static final String REQUEST_ID = "RequestID"; + public static final String INVOCATION_ID = "InvocationID"; + public static final String INSTANCE_UUID = "InstanceUUID"; + public static final String RESPONSE_CODE = "ResponseCode"; + public static final String SERVICE_NAME = "ServiceName"; + + private MDCVariables() { + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/SimulatorController.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/SimulatorController.java new file mode 100644 index 0000000..0e4bd56 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/SimulatorController.java @@ -0,0 +1,219 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.rest; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.JsonSyntaxException; +import org.json.JSONException; +import org.onap.pnfsimulator.event.EventData; +import org.onap.pnfsimulator.event.EventDataService; +import org.onap.pnfsimulator.rest.model.FullEvent; +import org.onap.pnfsimulator.rest.model.SimulatorRequest; +import org.onap.pnfsimulator.rest.util.DateUtil; +import org.onap.pnfsimulator.rest.util.ResponseBuilder; +import org.onap.pnfsimulator.simulator.SimulatorService; +import org.onap.pnfsimulator.simulatorconfig.SimulatorConfig; +import org.quartz.SchedulerException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; +import java.io.IOException; +import java.net.MalformedURLException; +import java.security.GeneralSecurityException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static org.onap.pnfsimulator.logging.MDCVariables.INSTANCE_UUID; +import static org.onap.pnfsimulator.logging.MDCVariables.INVOCATION_ID; +import static org.onap.pnfsimulator.logging.MDCVariables.REQUEST_ID; +import static org.onap.pnfsimulator.logging.MDCVariables.RESPONSE_CODE; +import static org.onap.pnfsimulator.logging.MDCVariables.SERVICE_NAME; +import static org.onap.pnfsimulator.logging.MDCVariables.X_INVOCATION_ID; +import static org.onap.pnfsimulator.logging.MDCVariables.X_ONAP_REQUEST_ID; +import static org.onap.pnfsimulator.rest.util.ResponseBuilder.MESSAGE; +import static org.onap.pnfsimulator.rest.util.ResponseBuilder.TIMESTAMP; +import static org.springframework.http.HttpStatus.ACCEPTED; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; +import static org.springframework.http.HttpStatus.NOT_FOUND; +import static org.springframework.http.HttpStatus.OK; + +@RestController +@RequestMapping("/simulator") +public class SimulatorController { + + private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorController.class); + private static final Marker ENTRY = MarkerFactory.getMarker("ENTRY"); + private static final String INCORRECT_TEMPLATE_MESSAGE = "Cannot start simulator, template %s is not in valid format: %s"; + private static final String NOT_EXISTING_TEMPLATE = "Cannot start simulator - template %s not found."; + private final DateFormat responseDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss,SSS"); + private final SimulatorService simulatorService; + private EventDataService eventDataService; + + @Autowired + public SimulatorController(SimulatorService simulatorService, + EventDataService eventDataService) { + this.simulatorService = simulatorService; + this.eventDataService = eventDataService; + } + + @PostMapping("test") + @Deprecated + public ResponseEntity test(@Valid @RequestBody SimulatorRequest simulatorRequest) { + MDC.put("test", "test"); + LOGGER.info(ENTRY, simulatorRequest.toString()); + return buildResponse(OK, ImmutableMap.of(MESSAGE, "message1234")); + } + + @PostMapping(value = "start") + public ResponseEntity start(@RequestHeader HttpHeaders headers, + @Valid @RequestBody SimulatorRequest triggerEventRequest) { + logContextHeaders(headers, "/simulator/start"); + LOGGER.info(ENTRY, "Simulator started"); + + try { + return processRequest(triggerEventRequest); + + } catch (JSONException | JsonSyntaxException e) { + MDC.put(RESPONSE_CODE, BAD_REQUEST.toString()); + LOGGER.warn("Cannot trigger event, invalid json format: {}", e.getMessage()); + LOGGER.debug("Received json has invalid format", e); + return buildResponse(BAD_REQUEST, ImmutableMap.of(MESSAGE, String + .format(INCORRECT_TEMPLATE_MESSAGE, triggerEventRequest.getTemplateName(), + e.getMessage()))); + } catch (GeneralSecurityException e ){ + MDC.put(RESPONSE_CODE, INTERNAL_SERVER_ERROR.toString() ); + LOGGER.error("Client certificate validation failed: {}", e.getMessage()); + return buildResponse(INTERNAL_SERVER_ERROR, + ImmutableMap.of(MESSAGE, "Invalid or misconfigured client certificate")); + } + catch (IOException e) { + MDC.put(RESPONSE_CODE, BAD_REQUEST.toString()); + LOGGER.warn("Json validation failed: {}", e.getMessage()); + return buildResponse(BAD_REQUEST, + ImmutableMap.of(MESSAGE, String.format(NOT_EXISTING_TEMPLATE, triggerEventRequest.getTemplateName()))); + } catch (Exception e) { + MDC.put(RESPONSE_CODE, INTERNAL_SERVER_ERROR.toString()); + LOGGER.error("Cannot trigger event - unexpected exception", e); + return buildResponse(INTERNAL_SERVER_ERROR, + ImmutableMap.of(MESSAGE, "Unexpected exception: " + e.getMessage())); + } finally { + MDC.clear(); + } + } + + @GetMapping("all-events") + @Deprecated + public ResponseEntity allEvents() { + List<EventData> eventDataList = eventDataService.getAllEvents(); + StringBuilder sb = new StringBuilder(); + eventDataList.forEach(e -> sb.append(e).append(System.lineSeparator())); + + return ResponseBuilder + .status(OK).put(MESSAGE, sb.toString()) + .build(); + } + + @GetMapping("config") + public ResponseEntity getConfig() { + SimulatorConfig configToGet = simulatorService.getConfiguration(); + return buildResponse(OK, ImmutableMap.of("simulatorConfig", configToGet)); + } + + @PutMapping("config") + public ResponseEntity updateConfig(@Valid @RequestBody SimulatorConfig newConfig) { + SimulatorConfig updatedConfig = simulatorService.updateConfiguration(newConfig); + return buildResponse(OK, ImmutableMap.of("simulatorConfig", updatedConfig)); + } + + @PostMapping("cancel/{jobName}") + public ResponseEntity cancelEvent(@PathVariable String jobName) throws SchedulerException { + LOGGER.info(ENTRY, "Cancel called on {}.", jobName); + boolean isCancelled = simulatorService.cancelEvent(jobName); + return createCancelEventResponse(isCancelled); + } + + @PostMapping("cancel") + public ResponseEntity cancelAllEvent() throws SchedulerException { + LOGGER.info(ENTRY, "Cancel called on all jobs"); + boolean isCancelled = simulatorService.cancelAllEvents(); + return createCancelEventResponse(isCancelled); + } + + @PostMapping("event") + public ResponseEntity sendEventDirectly(@RequestHeader HttpHeaders headers, @Valid @RequestBody FullEvent event) + throws IOException, GeneralSecurityException{ + logContextHeaders(headers, "/simulator/event"); + LOGGER.info(ENTRY, "Trying to send one-time event directly to VES Collector"); + simulatorService.triggerOneTimeEvent(event); + return buildResponse(ACCEPTED, ImmutableMap.of(MESSAGE, "One-time direct event sent successfully")); + } + + private ResponseEntity processRequest(SimulatorRequest triggerEventRequest) + throws IOException, SchedulerException, GeneralSecurityException { + + String jobName = simulatorService.triggerEvent(triggerEventRequest); + MDC.put(RESPONSE_CODE, OK.toString()); + return buildResponse(OK, ImmutableMap.of(MESSAGE, "Request started", "jobName", jobName)); + } + + private ResponseEntity buildResponse(HttpStatus endStatus, Map<String, Object> parameters) { + ResponseBuilder builder = ResponseBuilder + .status(endStatus) + .put(TIMESTAMP, DateUtil.getTimestamp(responseDateFormat)); + parameters.forEach(builder::put); + return builder.build(); + } + + private void logContextHeaders(HttpHeaders headers, String serviceName) { + MDC.put(REQUEST_ID, headers.getFirst(X_ONAP_REQUEST_ID)); + MDC.put(INVOCATION_ID, headers.getFirst(X_INVOCATION_ID)); + MDC.put(INSTANCE_UUID, UUID.randomUUID().toString()); + MDC.put(SERVICE_NAME, serviceName); + } + + private ResponseEntity createCancelEventResponse(boolean isCancelled) { + if (isCancelled) { + return buildResponse(OK, ImmutableMap.of(MESSAGE, "Event(s) was cancelled")); + } else { + return buildResponse(NOT_FOUND, ImmutableMap.of(MESSAGE, "Simulator was not able to cancel event(s)")); + } + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/TemplateController.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/TemplateController.java new file mode 100644 index 0000000..444e23b --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/TemplateController.java @@ -0,0 +1,105 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.rest; + +import java.time.Instant; +import java.util.List; +import java.util.Optional; +import javax.validation.Valid; + +import org.onap.pnfsimulator.db.Storage; +import org.onap.pnfsimulator.rest.model.TemplateRequest; +import org.onap.pnfsimulator.rest.model.SearchExp; +import org.onap.pnfsimulator.template.Template; +import org.onap.pnfsimulator.template.search.IllegalJsonValueException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + + +@RestController +@RequestMapping("/template") +public class TemplateController { + static final String TEMPLATE_NOT_FOUND_MSG = "A template with given name does not exist"; + static final String CANNOT_OVERRIDE_TEMPLATE_MSG = "Cannot overwrite existing template. Use override=true to override"; + private final Storage<Template> service; + private static final Logger LOG = LoggerFactory.getLogger(TemplateController.class); + + @Autowired + public TemplateController(Storage<Template> service) { + this.service = service; + } + + @GetMapping("list") + public ResponseEntity<?> list() { + return new ResponseEntity<>(service.getAll(), HttpStatus.OK); + } + + @GetMapping("get/{templateName}") + public ResponseEntity<?> get(@PathVariable String templateName) { + Optional<Template> template = service.get(templateName); + if (!template.isPresent()) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.TEXT_PLAIN); + return new ResponseEntity<>(TEMPLATE_NOT_FOUND_MSG, headers, HttpStatus.NOT_FOUND); + } + return new ResponseEntity<>(template, HttpStatus.OK); + } + + @PostMapping("upload") + public ResponseEntity<?> upload( + @RequestBody @Valid TemplateRequest templateRequest, + @RequestParam(required = false) boolean override) { + String msg = ""; + HttpStatus status = HttpStatus.CREATED; + Template template = new Template(templateRequest.getName(), templateRequest.getTemplate(), Instant.now().getNano()); + if (!service.tryPersistOrOverwrite(template, override)) { + status = HttpStatus.CONFLICT; + msg = CANNOT_OVERRIDE_TEMPLATE_MSG; + } + return new ResponseEntity<>(msg, status); + } + + @PostMapping("search") + public ResponseEntity<?> searchByCriteria(@RequestBody SearchExp queryJson) { + try { + List<String> templateNames = service.getIdsByContentCriteria(queryJson.getSearchExpr()); + return new ResponseEntity<>(templateNames, HttpStatus.OK); + } catch (IllegalJsonValueException ex) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, String.format("Try again with correct parameters. Cause: %s", ex.getMessage()), ex); + } + + } + + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/FullEvent.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/FullEvent.java new file mode 100644 index 0000000..77d9b3d --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/FullEvent.java @@ -0,0 +1,48 @@ +/* + * ============LICENSE_START======================================================= + * FULL-EVENT + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.rest.model; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.JsonObject; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.onap.pnfsimulator.rest.util.JsonObjectDeserializer; +import org.springframework.lang.Nullable; + +import javax.validation.constraints.NotNull; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +@ToString +@EqualsAndHashCode +public class FullEvent { + + @Nullable + private String vesServerUrl; + + @NotNull + @JsonDeserialize(using = JsonObjectDeserializer.class) + private JsonObject event; +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/SearchExp.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/SearchExp.java new file mode 100644 index 0000000..41d112f --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/SearchExp.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.rest.model; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.JsonObject; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.onap.pnfsimulator.rest.util.JsonObjectDeserializer; + +import javax.validation.constraints.NotNull; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class SearchExp { + + @NotNull + @JsonDeserialize(using = JsonObjectDeserializer.class) + private JsonObject searchExpr; +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/SimulatorParams.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/SimulatorParams.java new file mode 100644 index 0000000..787583e --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/SimulatorParams.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.rest.model; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import org.springframework.lang.Nullable; + +@Getter +@EqualsAndHashCode +@AllArgsConstructor +@NoArgsConstructor +public class SimulatorParams { + + @NotNull + private String vesServerUrl; + + @Nullable + private Integer repeatInterval; + + @Nullable + private Integer repeatCount; + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/SimulatorRequest.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/SimulatorRequest.java new file mode 100644 index 0000000..2b06658 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/SimulatorRequest.java @@ -0,0 +1,51 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.rest.model; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.gson.JsonObject; +import javax.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.onap.pnfsimulator.rest.util.JsonObjectDeserializer; +import org.springframework.lang.Nullable; + +@Getter +@ToString +@EqualsAndHashCode +@AllArgsConstructor +@NoArgsConstructor +public class SimulatorRequest { + + @NotNull + private SimulatorParams simulatorParams; + + @NotNull + private String templateName; + + @Nullable + @JsonDeserialize(using = JsonObjectDeserializer.class) + private JsonObject patch; + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/TemplateRequest.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/TemplateRequest.java new file mode 100644 index 0000000..d5a77f0 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/model/TemplateRequest.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.rest.model; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.bson.Document; + +@Getter +@Setter +@ToString +public class TemplateRequest { + private String name; + private Document template; + + public TemplateRequest(String name, Document template) { + this.name = name; + this.template = template; + } + + public TemplateRequest() { + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/util/DateUtil.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/util/DateUtil.java new file mode 100644 index 0000000..9a5c9ca --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/util/DateUtil.java @@ -0,0 +1,35 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.rest.util; + +import java.text.DateFormat; +import java.util.Date; + +public final class DateUtil { + + private DateUtil() { + } + + public static String getTimestamp(DateFormat dateFormat) { + + return dateFormat.format(new Date()); + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/util/JsonObjectDeserializer.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/util/JsonObjectDeserializer.java new file mode 100644 index 0000000..f89c4a7 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/util/JsonObjectDeserializer.java @@ -0,0 +1,42 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.rest.util; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.ObjectCodec; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import java.io.IOException; + +public class JsonObjectDeserializer extends JsonDeserializer<JsonObject> { + private Gson gson = new Gson(); + + @Override + public JsonObject deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + ObjectCodec oc = jsonParser.getCodec(); + JsonNode node = oc.readTree(jsonParser); + return gson.fromJson(node.toString(), JsonObject.class); + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/util/ResponseBuilder.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/util/ResponseBuilder.java new file mode 100644 index 0000000..5fca25a --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/rest/util/ResponseBuilder.java @@ -0,0 +1,62 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.rest.util; + +import java.util.LinkedHashMap; +import java.util.Map; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +public class ResponseBuilder { + + public static final String TIMESTAMP = "timestamp"; + public static final String MESSAGE = "message"; + public static final String SIMULATOR_STATUS = "simulatorStatus"; + public static final String REMAINING_TIME = "remainingTime"; + + private HttpStatus httpStatus; + private Map<String, Object> body = new LinkedHashMap<>(); + + private ResponseBuilder(HttpStatus httpStatus) { + this.httpStatus = httpStatus; + } + + public static ResponseBuilder status(HttpStatus httpStatus) { + + return new ResponseBuilder(httpStatus); + } + + public ResponseBuilder put(String key, Object value) { + + body.put(key, value); + return this; + } + + public ResponseEntity build() { + + if (body.isEmpty()) { + return ResponseEntity.status(httpStatus).build(); + } + + return ResponseEntity.status(httpStatus).body(body); + } + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/DBTemplateReader.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/DBTemplateReader.java new file mode 100644 index 0000000..6c11254 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/DBTemplateReader.java @@ -0,0 +1,49 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.simulator; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import java.io.IOException; +import org.onap.pnfsimulator.template.Template; +import org.onap.pnfsimulator.template.TemplateService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class DBTemplateReader implements TemplateReader { + private final TemplateService service; + private final Gson gson; + + @Autowired + public DBTemplateReader(TemplateService service, Gson gson) { + this.service = service; + this.gson = gson; + } + + @Override + public JsonObject readTemplate(String templateName) throws IOException { + Template template = service.get(templateName).orElseThrow(() -> new IOException("Template does not exist")); + JsonElement jsonElement = gson.toJsonTree(template.getContent()); + return jsonElement.getAsJsonObject(); + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/EventNotFoundException.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/EventNotFoundException.java new file mode 100644 index 0000000..4f43d8c --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/EventNotFoundException.java @@ -0,0 +1,28 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +public class EventNotFoundException extends RuntimeException { + private static final String NOT_FOUND = "Not found an event with id: "; + public EventNotFoundException(String eventId) { + super(NOT_FOUND + eventId); + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/FilesystemTemplateReader.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/FilesystemTemplateReader.java new file mode 100644 index 0000000..a405a2e --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/FilesystemTemplateReader.java @@ -0,0 +1,54 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class FilesystemTemplateReader implements TemplateReader { + + private final Path templatesDir; + private final Gson gson; + + @Autowired + FilesystemTemplateReader(@Value("${templates.dir}") String templatesDir, Gson gson) { + this.templatesDir = Paths.get(templatesDir); + this.gson = gson; + } + + public JsonObject readTemplate(String templateFileName) throws IOException { + Path absTemplateFilePath = templatesDir.resolve(templateFileName); + try (Stream<String> lines = Files.lines(absTemplateFilePath)) { + String content = lines.collect(Collectors.joining("\n")); + return gson.fromJson(content, JsonObject.class); + } + } +} + diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/IncrementProvider.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/IncrementProvider.java new file mode 100644 index 0000000..ea87ae6 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/IncrementProvider.java @@ -0,0 +1,26 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +@FunctionalInterface +public interface IncrementProvider { + int getAndIncrement(String id); +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/IncrementProviderImpl.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/IncrementProviderImpl.java new file mode 100644 index 0000000..16c0a0e --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/IncrementProviderImpl.java @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import org.onap.pnfsimulator.event.EventData; +import org.onap.pnfsimulator.event.EventDataRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class IncrementProviderImpl implements IncrementProvider { + private final EventDataRepository repository; + + @Autowired + public IncrementProviderImpl(EventDataRepository repository) { + this.repository = repository; + } + + @Override + public int getAndIncrement(String id) { + EventData eventData = repository.findById(id) + .orElseThrow(() -> new EventNotFoundException(id)); + int value = eventData.getIncrementValue() + 1; + eventData.setIncrementValue(value); + repository.save(eventData); + return value; + } + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/JsonTokenProcessor.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/JsonTokenProcessor.java new file mode 100644 index 0000000..da0026a --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/JsonTokenProcessor.java @@ -0,0 +1,134 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.stream.Collectors; + +public enum JsonTokenProcessor { + STRING(JsonToken.STRING) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + String originalString = reader.nextString(); + if (keywordsExtractor.isPrimitive(originalString)) { + writer.value(keywordsExtractor.substitutePrimitiveKeyword(originalString)); + } else { + String possibleSubstitution = Arrays.stream(originalString.split(" ")) + .map(singleWord -> keywordsExtractor.substituteStringKeyword(singleWord, incrementValue)).collect( + Collectors.joining(" ")); + writer.value(originalString.equals(possibleSubstitution) ? originalString : possibleSubstitution); + } + } + }, + BEGIN_ARRAY(JsonToken.BEGIN_ARRAY) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + reader.beginArray(); + writer.beginArray(); + } + }, + END_ARRAY(JsonToken.END_ARRAY) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + reader.endArray(); + writer.endArray(); + } + }, + BEGIN_OBJECT(JsonToken.BEGIN_OBJECT) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + reader.beginObject(); + writer.beginObject(); + } + }, + END_OBJECT(JsonToken.END_OBJECT) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + reader.endObject(); + writer.endObject(); + } + }, + NAME(JsonToken.NAME) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + writer.name(reader.nextName()); + } + }, + NUMBER(JsonToken.NUMBER) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + writer.value(new BigDecimal(reader.nextString())); + } + }, + BOOLEAN(JsonToken.BOOLEAN) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + writer.value(reader.nextBoolean()); + } + }, + NULL(JsonToken.NULL) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + reader.nextNull(); + writer.nullValue(); + } + }, + END_DOCUMENT(JsonToken.END_DOCUMENT) { + @Override + void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) + throws IOException { + // do nothing + } + }; + + private JsonToken jsonToken; + + JsonTokenProcessor(JsonToken jsonToken) { + this.jsonToken = jsonToken; + } + + boolean isProcessorFor(JsonToken jsonToken) { + return this.jsonToken == jsonToken; + } + + abstract void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) throws IOException; + + private static final String INVALID_JSON_BODY_UNSUPPORTED_JSON_TOKEN = "Invalid json body. Unsupported JsonToken."; + + static JsonTokenProcessor getProcessorFor(JsonToken jsonToken) throws IOException { + return Arrays.stream(JsonTokenProcessor.values()).filter(processor -> processor.isProcessorFor(jsonToken)).findFirst() + .orElseThrow(() -> new IOException(INVALID_JSON_BODY_UNSUPPORTED_JSON_TOKEN)); + } + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/KeywordsExtractor.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/KeywordsExtractor.java new file mode 100644 index 0000000..23c383f --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/KeywordsExtractor.java @@ -0,0 +1,118 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import static io.vavr.API.$; +import static io.vavr.API.Case; +import static io.vavr.API.Match; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getEpochSecond; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomLimitedInteger; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomInteger; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomLimitedString; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomString; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomPrimitiveInteger; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getTimestampPrimitive; +import static org.onap.pnfsimulator.simulator.keywords.NonParameterKeywordPatterns.$nonParameterKeyword; +import static org.onap.pnfsimulator.simulator.keywords.SingleParameterKeywordPatterns.$singleParameterKeyword; +import static org.onap.pnfsimulator.simulator.keywords.TwoParameterKeywordPatterns.$twoParameterKeyword; +import io.vavr.API.Match.Pattern1; +import org.onap.pnfsimulator.simulator.keywords.Keyword; +import org.onap.pnfsimulator.simulator.keywords.NonParameterKeyword; +import org.onap.pnfsimulator.simulator.keywords.SingleParameterKeyword; +import org.onap.pnfsimulator.simulator.keywords.TwoParameterKeyword; +import org.springframework.stereotype.Component; + +@Component +public class KeywordsExtractor { + + String substituteStringKeyword(String text, int increment) { + return Match(text).of( + Case(isRandomStringParamKeyword(), + spk -> spk.substituteKeyword(getRandomString().apply(spk.getAdditionalParameter()))), + Case(isRandomStringNonParamKeyword(), + npk -> npk.substituteKeyword(getRandomLimitedString().apply())), + Case(isRandomIntegerParamKeyword(), + tpk -> tpk.substituteKeyword(getRandomInteger().apply(tpk.getAdditionalParameter1(), tpk.getAdditionalParameter2()))), + Case(isRandomIntegerNonParamKeyword(), + npk -> npk.substituteKeyword(getRandomLimitedInteger().apply())), + Case(isIncrementKeyword(), + ik -> ik.substituteKeyword(String.valueOf(increment))), + Case(isTimestampNonParamKeyword(), + npk -> npk.substituteKeyword(getEpochSecond().apply())), + Case( + $(), + () -> text + )); + } + + Long substitutePrimitiveKeyword(String text) { + return Match(text).of( + Case(isRandomPrimitiveIntegerParamKeyword(), + tpk -> + getRandomPrimitiveInteger().apply(tpk.getAdditionalParameter1(), tpk.getAdditionalParameter2())), + Case(isTimestampPrimitiveNonParamKeyword(), + tpk -> + getTimestampPrimitive().apply()), + Case( + $(), + () -> 0L + )); + } + + boolean isPrimitive(String text) { + return Match(text).of( + Case(isRandomPrimitiveIntegerParamKeyword(), () -> true), + Case(isTimestampPrimitiveNonParamKeyword(), () -> true), + Case($(), () -> false)); + } + + private Pattern1<String, SingleParameterKeyword> isRandomStringParamKeyword() { + return $singleParameterKeyword($(spk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(spk, "RandomString"))); + } + + private Pattern1<String, NonParameterKeyword> isRandomStringNonParamKeyword() { + return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "RandomString"))); + } + + private Pattern1<String, NonParameterKeyword> isIncrementKeyword() { + return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "Increment"))); + } + + private Pattern1<String, TwoParameterKeyword> isRandomIntegerParamKeyword() { + return $twoParameterKeyword($(tpk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(tpk, "RandomInteger"))); + } + + private Pattern1<String, TwoParameterKeyword> isRandomPrimitiveIntegerParamKeyword() { + return $twoParameterKeyword($(tpk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(tpk, "RandomPrimitiveInteger"))); + } + + private Pattern1<String, NonParameterKeyword> isTimestampPrimitiveNonParamKeyword() { + return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "TimestampPrimitive"))); + } + + private Pattern1<String, NonParameterKeyword> isRandomIntegerNonParamKeyword() { + return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "RandomInteger"))); + } + + private Pattern1<String, NonParameterKeyword> isTimestampNonParamKeyword() { + return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "Timestamp"))); + } + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandler.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandler.java new file mode 100644 index 0000000..51e0c1f --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandler.java @@ -0,0 +1,72 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import org.springframework.stereotype.Component; + +@Component +public class KeywordsHandler { + + private KeywordsExtractor keywordsExtractor; + private IncrementProvider incrementProvider; + + public KeywordsHandler(KeywordsExtractor keywordsExtractor, IncrementProvider incrementProvider) { + this.keywordsExtractor = keywordsExtractor; + this.incrementProvider = incrementProvider; + } + + public JsonElement substituteKeywords(JsonElement jsonBody, String jobId) { + int counter = incrementProvider.getAndIncrement(jobId); + try ( + JsonReader reader = new JsonReader(new StringReader(jsonBody.toString())); + StringWriter stringWriter = new StringWriter(); + JsonWriter jsonWriter = new JsonWriter(stringWriter); + ) { + modify(reader, jsonWriter, counter); + return new Gson().fromJson(stringWriter.getBuffer().toString(), JsonElement.class); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void modify(JsonReader reader, JsonWriter writer, int incrementValue) throws IOException { + JsonTokenProcessor jsonTokenProcessor; + do { + JsonToken token = reader.peek(); + jsonTokenProcessor = JsonTokenProcessor.getProcessorFor(token); + jsonTokenProcessor.process(reader, writer, incrementValue, keywordsExtractor); + } while (isJsonProcessingFinished(jsonTokenProcessor)); + } + + private boolean isJsonProcessingFinished(JsonTokenProcessor jsonTokenProcessor) { + return !jsonTokenProcessor.isProcessorFor(JsonToken.END_DOCUMENT); + } + +} + + diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/KeywordsValueProvider.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/KeywordsValueProvider.java new file mode 100644 index 0000000..3bcfa5b --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/KeywordsValueProvider.java @@ -0,0 +1,80 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import io.vavr.Function0; +import io.vavr.Function1; +import io.vavr.Function2; + +import java.time.Instant; +import java.util.Random; + +import org.apache.commons.lang3.RandomStringUtils; + +class KeywordsValueProvider { + + private KeywordsValueProvider() { + } + + static final int DEFAULT_STRING_LENGTH = 20; + public static final int RANDOM_INTEGER_MAX_LIMITATION = 9; + public static final int RANDOM_INTEGER_MIN_LIMITATION = 0; + + private static Function2<Integer, Integer, Integer> bigger = (left, right) -> left >= right ? left : right; + private static Function2<Integer, Integer, Integer> smaller = (left, right) -> left < right ? left : right; + private static Function2<Integer, Integer, Integer> randomPrimitiveIntegerFromSortedRange = (min, max) -> new Random().nextInt(max - min + 1) + min; + private static Function2<Integer, Integer, String> randomIntegerFromSortedRange = (min, max) -> Integer.toString(new Random().nextInt(max - min + 1) + min); + + private static Function1<Integer, String> randomString = RandomStringUtils::randomAscii; + private static Function2<Integer, Integer, String> randomInteger = (left, right) -> randomIntegerFromSortedRange.apply(smaller.apply(left, right), bigger.apply(left, right)); + private static Function0<String> randomLimitedInteger = () -> randomInteger.apply(RANDOM_INTEGER_MIN_LIMITATION, RANDOM_INTEGER_MAX_LIMITATION); + private static Function0<String> randomLimitedString = () -> RandomStringUtils.randomAscii(DEFAULT_STRING_LENGTH); + private static Function0<String> epochSecond = () -> Long.toString(Instant.now().getEpochSecond()); + private static Function2<Integer, Integer, Long> randomPrimitiveInteger = (left, right) -> randomPrimitiveIntegerFromSortedRange.apply(smaller.apply(left, right), bigger.apply(left, right)).longValue(); + private static Function0<Long> timestampPrimitive = () -> Instant.now().getEpochSecond(); + + public static Function1<Integer, String> getRandomString() { + return randomString; + } + + public static Function2<Integer, Integer, String> getRandomInteger() { + return randomInteger; + } + + public static Function0<String> getRandomLimitedInteger() { + return randomLimitedInteger; + } + + public static Function0<String> getRandomLimitedString() { + return randomLimitedString; + } + + public static Function0<String> getEpochSecond() { + return epochSecond; + } + + public static Function2<Integer, Integer, Long> getRandomPrimitiveInteger() { + return randomPrimitiveInteger; + } + + public static Function0<Long> getTimestampPrimitive() { + return timestampPrimitive; + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/SimulatorService.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/SimulatorService.java new file mode 100644 index 0000000..155c0ff --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/SimulatorService.java @@ -0,0 +1,121 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import com.google.common.base.Strings; +import com.google.gson.JsonObject; +import java.io.IOException; +import java.net.MalformedURLException; +import java.security.GeneralSecurityException; +import java.util.Optional; +import org.onap.pnfsimulator.event.EventData; +import org.onap.pnfsimulator.event.EventDataService; +import org.onap.pnfsimulator.rest.model.FullEvent; +import org.onap.pnfsimulator.rest.model.SimulatorParams; +import org.onap.pnfsimulator.rest.model.SimulatorRequest; +import org.onap.pnfsimulator.simulator.client.HttpClientAdapter; +import org.onap.pnfsimulator.simulator.client.HttpClientAdapterImpl; +import org.onap.pnfsimulator.simulator.client.utils.ssl.SSLAuthenticationHelper; +import org.onap.pnfsimulator.simulator.scheduler.EventScheduler; +import org.onap.pnfsimulator.simulatorconfig.SimulatorConfig; +import org.onap.pnfsimulator.simulatorconfig.SimulatorConfigService; +import org.quartz.SchedulerException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class SimulatorService { + + private final TemplatePatcher templatePatcher; + private final TemplateReader templateReader; + private final EventDataService eventDataService; + private final EventScheduler eventScheduler; + private final SSLAuthenticationHelper sslAuthenticationHelper; + private SimulatorConfigService simulatorConfigService; + private static final JsonObject EMPTY_JSON_OBJECT = new JsonObject(); + + @Autowired + public SimulatorService(TemplatePatcher templatePatcher, TemplateReader templateReader, + EventScheduler eventScheduler, EventDataService eventDataService, + SimulatorConfigService simulatorConfigService, SSLAuthenticationHelper sslAuthenticationHelper) { + this.templatePatcher = templatePatcher; + this.templateReader = templateReader; + this.eventDataService = eventDataService; + this.eventScheduler = eventScheduler; + this.simulatorConfigService = simulatorConfigService; + this.sslAuthenticationHelper = sslAuthenticationHelper; + } + + public String triggerEvent(SimulatorRequest simulatorRequest) throws IOException, SchedulerException, GeneralSecurityException { + String templateName = simulatorRequest.getTemplateName(); + SimulatorParams simulatorParams = simulatorRequest.getSimulatorParams(); + JsonObject template = templateReader.readTemplate(templateName); + JsonObject input = Optional.ofNullable(simulatorRequest.getPatch()).orElse(new JsonObject()); + JsonObject patchedJson = templatePatcher + .mergeTemplateWithPatch(template, input); + JsonObject keywords = new JsonObject(); + + EventData eventData = eventDataService.persistEventData(template, patchedJson, input, keywords); + + String targetVesUrl = getDefaultUrlIfNotProvided(simulatorParams.getVesServerUrl()); + return eventScheduler + .scheduleEvent(targetVesUrl, Optional.ofNullable(simulatorParams.getRepeatInterval()).orElse(1), + Optional.ofNullable(simulatorParams.getRepeatCount()).orElse(1), simulatorRequest.getTemplateName(), + eventData.getId(), + patchedJson); + } + + public void triggerOneTimeEvent(FullEvent event) throws IOException, GeneralSecurityException { + KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), id -> 1); + JsonObject withKeywordsSubstituted = keywordsHandler.substituteKeywords(event.getEvent(), "").getAsJsonObject(); + + HttpClientAdapter client = createHttpClientAdapter(event.getVesServerUrl()); + eventDataService.persistEventData(EMPTY_JSON_OBJECT, withKeywordsSubstituted, event.getEvent(), EMPTY_JSON_OBJECT); + + client.send(withKeywordsSubstituted.toString()); + } + + public SimulatorConfig getConfiguration() { + return simulatorConfigService.getConfiguration(); + } + + public SimulatorConfig updateConfiguration(SimulatorConfig newConfig) { + return simulatorConfigService.updateConfiguration(newConfig); + } + + public boolean cancelAllEvents() throws SchedulerException { + return eventScheduler.cancelAllEvents(); + } + + public boolean cancelEvent(String jobName) throws SchedulerException { + return eventScheduler.cancelEvent(jobName); + } + + HttpClientAdapter createHttpClientAdapter(String vesServerUrl) throws IOException, GeneralSecurityException { + String targetVesUrl = getDefaultUrlIfNotProvided(vesServerUrl); + return new HttpClientAdapterImpl(targetVesUrl, sslAuthenticationHelper); + } + + private String getDefaultUrlIfNotProvided(String vesUrlSimulatorParam) { + return Strings.isNullOrEmpty(vesUrlSimulatorParam) + ? simulatorConfigService.getConfiguration().getVesServerUrl().toString() : vesUrlSimulatorParam; + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/TemplatePatcher.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/TemplatePatcher.java new file mode 100644 index 0000000..1114d3c --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/TemplatePatcher.java @@ -0,0 +1,53 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.springframework.stereotype.Component; + +import java.util.Map; + +@Component +class TemplatePatcher { + + JsonObject mergeTemplateWithPatch(JsonObject templateJson, JsonObject patchJson) { + JsonObject template = templateJson.deepCopy(); + patchTemplateNode(template, patchJson); + return template; + } + + private void patchTemplateNode(JsonObject templateJson, JsonObject patchJson) { + for (Map.Entry<String, JsonElement> stringJsonElementEntry : patchJson.entrySet()) { + String patchKey = stringJsonElementEntry.getKey(); + JsonElement patchValue = stringJsonElementEntry.getValue(); + JsonElement templateElement = templateJson.get(patchKey); + + if (!patchValue.isJsonObject() || templateElement == null || !templateElement.isJsonObject()) { + templateJson.remove(patchKey); + templateJson.add(patchKey, patchValue); + } else { + patchTemplateNode(templateElement.getAsJsonObject(), patchValue.getAsJsonObject()); + } + + } + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/TemplateReader.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/TemplateReader.java new file mode 100644 index 0000000..bf06381 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/TemplateReader.java @@ -0,0 +1,28 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import com.google.gson.JsonObject; +import java.io.IOException; + +public interface TemplateReader { + JsonObject readTemplate(String templateName) throws IOException; +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapter.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapter.java new file mode 100644 index 0000000..e7d113d --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapter.java @@ -0,0 +1,26 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator.client; + +public interface HttpClientAdapter { + + void send(String content); +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImpl.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImpl.java new file mode 100644 index 0000000..6ea1157 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImpl.java @@ -0,0 +1,104 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator.client; + +import static org.onap.pnfsimulator.logging.MDCVariables.REQUEST_ID; +import static org.onap.pnfsimulator.logging.MDCVariables.X_INVOCATION_ID; +import static org.onap.pnfsimulator.logging.MDCVariables.X_ONAP_REQUEST_ID; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.GeneralSecurityException; +import java.util.UUID; + +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.util.EntityUtils; +import org.onap.pnfsimulator.simulator.client.utils.ssl.SSLAuthenticationHelper; +import org.onap.pnfsimulator.simulator.client.utils.ssl.SslSupportLevel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +public class HttpClientAdapterImpl implements HttpClientAdapter { + + private static final int CONNECTION_TIMEOUT = 1000; + private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientAdapterImpl.class); + private static final String CONTENT_TYPE = "Content-Type"; + private static final String APPLICATION_JSON = "application/json"; + private static final RequestConfig CONFIG = RequestConfig.custom() + .setConnectTimeout(CONNECTION_TIMEOUT) + .setConnectionRequestTimeout(CONNECTION_TIMEOUT) + .setSocketTimeout(CONNECTION_TIMEOUT) + .build(); + private static final Marker INVOKE = MarkerFactory.getMarker("INVOKE"); + private SslSupportLevel sslSupportLevel; + private HttpClient client; + private final String targetUrl; + + public HttpClientAdapterImpl(String targetUrl, SSLAuthenticationHelper sslAuthenticationHelper) + throws IOException, GeneralSecurityException { + this.sslSupportLevel = sslAuthenticationHelper.isClientCertificateEnabled() ? + SslSupportLevel.CLIENT_CERT_AUTH : SslSupportLevel.getSupportLevelBasedOnProtocol(targetUrl); + this.client = sslSupportLevel.getClient(CONFIG, sslAuthenticationHelper); + this.targetUrl = targetUrl; + } + + HttpClientAdapterImpl(HttpClient client, String targetUrl) { + this.client = client; + this.targetUrl = targetUrl; + } + + @Override + public void send(String content) { + try { + HttpPost request = createRequest(content); + HttpResponse response = client.execute(request); + + //response has to be fully consumed otherwise apache won't release connection + EntityUtils.consumeQuietly(response.getEntity()); + LOGGER.info(INVOKE, "Message sent, ves response code: {}", response.getStatusLine()); + } catch (IOException e) { + LOGGER.warn("Error sending message to ves: " + e.getMessage(), e.getCause()); + } + } + + public SslSupportLevel getSslSupportLevel(){ + return sslSupportLevel; + } + + private HttpPost createRequest(String content) throws UnsupportedEncodingException { + HttpPost request = new HttpPost(this.targetUrl); + StringEntity stringEntity = new StringEntity(content); + request.addHeader(CONTENT_TYPE, APPLICATION_JSON); + request.addHeader(X_ONAP_REQUEST_ID, MDC.get(REQUEST_ID)); + request.addHeader(X_INVOCATION_ID, UUID.randomUUID().toString()); + request.setEntity(stringEntity); + return request; + } + + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLAuthenticationHelper.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLAuthenticationHelper.java new file mode 100644 index 0000000..eda17ef --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLAuthenticationHelper.java @@ -0,0 +1,79 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.simulator.client.utils.ssl; + +import java.io.Serializable; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties(prefix = "ssl") +@RefreshScope +@Primary +public class SSLAuthenticationHelper implements Serializable { + + private boolean clientCertificateEnabled; + private String clientCertificateDir; + private String clientCertificatePassword; + private String trustStoreDir; + private String trustStorePassword; + + public boolean isClientCertificateEnabled() { + return clientCertificateEnabled; + } + + public void setClientCertificateEnabled(boolean clientCertificateEnabled) { + this.clientCertificateEnabled = clientCertificateEnabled; + } + + public String getClientCertificateDir() { + return clientCertificateDir; + } + + public void setClientCertificateDir(String clientCertificateDir) { + this.clientCertificateDir = clientCertificateDir; + } + + public String getClientCertificatePassword() { + return clientCertificatePassword; + } + + public void setClientCertificatePassword(String clientCertificatePassword) { + this.clientCertificatePassword = clientCertificatePassword; + } + + public String getTrustStoreDir() { + return trustStoreDir; + } + + public void setTrustStoreDir(String trustStoreDir) { + this.trustStoreDir = trustStoreDir; + } + + public String getTrustStorePassword() { + return trustStorePassword; + } + + public void setTrustStorePassword(String trustStorePassword) { + this.trustStorePassword = trustStorePassword; + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslSupportLevel.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslSupportLevel.java new file mode 100644 index 0000000..264a7d1 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslSupportLevel.java @@ -0,0 +1,120 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator.client.utils.ssl; + +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.TrustAllStrategy; +import org.apache.http.conn.ssl.TrustSelfSignedStrategy; +import org.apache.http.conn.ssl.TrustStrategy; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.ssl.SSLContextBuilder; +import org.apache.http.ssl.SSLContexts; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLContext; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.GeneralSecurityException; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.util.Optional; + +public enum SslSupportLevel { + + NONE { + public HttpClient getClient(RequestConfig requestConfig, SSLAuthenticationHelper sslAuthenticationHelper) { + LOGGER.info("<!-----IN SslSupportLevel.NONE, Creating BasicHttpClient for http protocol----!>"); + return HttpClientBuilder + .create() + .setDefaultRequestConfig(requestConfig) + .build(); + } + }, + ALWAYS_TRUST { + public HttpClient getClient(RequestConfig requestConfig, SSLAuthenticationHelper sslAuthenticationHelper) + throws GeneralSecurityException, IOException { + LoggerFactory.getLogger(SslSupportLevel.class).info("<!-----IN SslSupportLevel.ALWAYS_TRUST, Creating client with SSL support for https protocol----!>"); + HttpClient client; + try { + SSLContext alwaysTrustSslContext = SSLContextBuilder.create().loadTrustMaterial(TRUST_STRATEGY_ALWAYS).build(); + client = HttpClients.custom() + .setSSLContext(alwaysTrustSslContext) + .setSSLHostnameVerifier(new NoopHostnameVerifier()) + .setDefaultRequestConfig(requestConfig) + .build(); + + } catch (GeneralSecurityException e) { + LOGGER.error("Could not initialize client due to SSL exception: {}. Default client without SSL support will be used instead.\nCause: {}", e.getMessage(), e.getCause()); + client = NONE.getClient(requestConfig, sslAuthenticationHelper); + } + return client; + } + }, + CLIENT_CERT_AUTH { + @Override + public HttpClient getClient(RequestConfig requestConfig, SSLAuthenticationHelper sslAuthenticationHelper) + throws GeneralSecurityException, IOException { + + SSLContext sslContext = SSLContexts.custom() + .loadKeyMaterial(readCertificate(sslAuthenticationHelper.getClientCertificateDir(), sslAuthenticationHelper.getClientCertificatePassword(), "PKCS12"), getPasswordAsCharArray(sslAuthenticationHelper.getClientCertificatePassword())) + .loadTrustMaterial(readCertificate(sslAuthenticationHelper.getTrustStoreDir(), sslAuthenticationHelper.getTrustStorePassword(), "JKS"), new TrustSelfSignedStrategy()) + .build(); + + return HttpClients.custom() + .setSSLContext(sslContext) + .setSSLHostnameVerifier(new NoopHostnameVerifier()) + .setDefaultRequestConfig(requestConfig) + .build(); + } + + private KeyStore readCertificate(String certificate, String password, String type) throws GeneralSecurityException, IOException { + try (InputStream keyStoreStream = new FileInputStream(certificate)) { + KeyStore keyStore = KeyStore.getInstance(type); + keyStore.load(keyStoreStream, getPasswordAsCharArray(password)); + return keyStore; + } + } + + private char[] getPasswordAsCharArray(String clientCertificatePassword) { + return Optional.ofNullable(clientCertificatePassword).map(String::toCharArray).orElse(null); + } + }; + + private static final Logger LOGGER = LoggerFactory.getLogger(SslSupportLevel.class); + private static final TrustStrategy TRUST_STRATEGY_ALWAYS = new TrustAllStrategy(); + + public static SslSupportLevel getSupportLevelBasedOnProtocol(String url) throws MalformedURLException { + return "https".equals(new URL(url).getProtocol()) ? SslSupportLevel.ALWAYS_TRUST : SslSupportLevel.NONE; + } + + public abstract HttpClient getClient(RequestConfig config, SSLAuthenticationHelper sslAuthenticationHelper) + throws GeneralSecurityException, IOException; + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/Keyword.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/Keyword.java new file mode 100644 index 0000000..edafe8f --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/Keyword.java @@ -0,0 +1,74 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator.keywords; + +import io.vavr.Function1; +import io.vavr.Function2; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.stream.Collectors; +import lombok.Getter; + +@Getter +public class Keyword { + + protected static final String LETTERS_REGEX = "([a-zA-Z]+)"; + protected static final String NONLETTERS_REGEX = "([^a-zA-Z]+)"; + + protected static final Function1<String, String> OPTIONAL = + (regex) -> regex + "?"; + + private final String name; + private final List<String> meaningfulParts; + + public static final Function2<Keyword, String, Boolean> IS_MATCHING_KEYWORD_NAME = (keyword, key) -> + keyword != null && keyword.getName() != null && keyword.getName().equals(key); + + /** + * Returns list of independent parts inside the keyword. Current implementation assumes that customer can join keywords with integer values, so + * keyword is decomposed to parts then some parts of the keyword is skipped because of replacement process. + * + * @param matcher - Matcher to check find independent groups inside the keyword + * @param skipGroups Informs this method about which groups should be consider as part of the replacement process + * @return list of independent parts inside the keywords + */ + static List<String> extractPartsFrom(Matcher matcher, List skipGroups) { + List<String> parts = new ArrayList<String>(); + for (int i = 1; i <= matcher.groupCount(); i++) { + if (matcher.group(i) != null && !skipGroups.contains(i)) { + parts.add(matcher.group(i)); + } + } + return parts; + } + + Keyword(String name, List<String> meaningfulParts) { + this.name = name; + this.meaningfulParts = meaningfulParts; + } + + public String substituteKeyword(String substitution) { + return meaningfulParts.stream() + .map(part -> part.equals(name) ? substitution : part) + .collect(Collectors.joining()); + } + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/NonParameterKeyword.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/NonParameterKeyword.java new file mode 100644 index 0000000..5e44550 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/NonParameterKeyword.java @@ -0,0 +1,65 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator.keywords; + +import io.vavr.Tuple; +import io.vavr.Tuple1; +import io.vavr.match.annotation.Patterns; +import io.vavr.match.annotation.Unapply; +import java.util.Collections; +import java.util.List; +import java.util.regex.Pattern; +import lombok.Getter; +import lombok.Setter; +import lombok.val; + +@Patterns +@Getter +@Setter +public class NonParameterKeyword extends Keyword { + + public static final int KEYWORD_NAME_GROUP = 2; + + private static final String KEYWORD_REGEX = new StringBuilder() + .append(OPTIONAL.apply(NONLETTERS_REGEX)) + .append("#") + .append(LETTERS_REGEX) + .append("(?!\\()") + .append(OPTIONAL.apply(NONLETTERS_REGEX)) + .toString(); + + private NonParameterKeyword(String name, List<String> meaningfulParts) { + super(name, meaningfulParts); + } + + @Unapply + static Tuple1<NonParameterKeyword> nonParameterKeyword(String keyword) { + val matcher = Pattern.compile(KEYWORD_REGEX).matcher(keyword); + NonParameterKeyword npk = null; + if (matcher.find()) { + npk = new NonParameterKeyword( + matcher.group(KEYWORD_NAME_GROUP), + extractPartsFrom(matcher, Collections.emptyList()) + ); + } + return Tuple.of(npk); + } + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/SingleParameterKeyword.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/SingleParameterKeyword.java new file mode 100644 index 0000000..b1c38c8 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/SingleParameterKeyword.java @@ -0,0 +1,73 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator.keywords; + +import io.vavr.Tuple; +import io.vavr.Tuple1; +import io.vavr.match.annotation.Patterns; +import io.vavr.match.annotation.Unapply; +import java.util.Collections; +import java.util.List; +import java.util.regex.Pattern; +import lombok.Getter; +import lombok.Setter; +import lombok.val; + +@Patterns +@Getter +@Setter +public class SingleParameterKeyword extends Keyword { + + public static final int KEYWORD_NAME_GROUP = 2; + public static final int ADDITIONAL_PARAMETER_GROUP = 3; + + private static final String KEYWORD_REGEX = new StringBuilder() + .append(OPTIONAL.apply(NONLETTERS_REGEX)) + .append("#") + .append(LETTERS_REGEX) + .append("\\((\\d+)\\)") + .append(OPTIONAL.apply(NONLETTERS_REGEX)) + .toString(); + public static final int SKIPPED_GROUP_NUMBER = 3; + + private Integer additionalParameter; + + private SingleParameterKeyword(String name, List<String> meaningfulParts, + Integer additionalParameter) { + super(name, meaningfulParts); + this.additionalParameter = additionalParameter; + } + + @Unapply + static Tuple1<SingleParameterKeyword> singleParameterKeyword(String keyword) { + val matcher = Pattern.compile(KEYWORD_REGEX).matcher(keyword); + SingleParameterKeyword spk = null; + if (matcher.find()) { + spk = new SingleParameterKeyword( + matcher.group(KEYWORD_NAME_GROUP), + extractPartsFrom(matcher, Collections.singletonList(SKIPPED_GROUP_NUMBER)), + Integer.parseInt(matcher.group(ADDITIONAL_PARAMETER_GROUP)) + ); + } + return Tuple.of(spk); + } +} + + diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeyword.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeyword.java new file mode 100644 index 0000000..6fecfa6 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeyword.java @@ -0,0 +1,80 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator.keywords; + +import io.vavr.Tuple; +import io.vavr.Tuple1; +import io.vavr.match.annotation.Patterns; +import io.vavr.match.annotation.Unapply; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; +import lombok.Getter; +import lombok.Setter; +import lombok.val; + +@Patterns +@Getter +@Setter +public class TwoParameterKeyword extends Keyword { + + public static final int ADDITIONAL_PARAMETER_1_GROUP = 3; + public static final int ADDITIONAL_PARAMETER_2_GROUP = 4; + public static final int KEYWORD_NAME_GROUP = 2; + protected static final List<Integer> ADDITIONAL_PARAMETERS_GROUPS = Arrays.asList(ADDITIONAL_PARAMETER_1_GROUP, ADDITIONAL_PARAMETER_2_GROUP); + + private static final String NON_LIMITED_NUMBER_REGEX = "\\((\\d+)"; + private static final String COLON_REGEX = "\\s?,\\s?"; + private static final String OPTIONAL_NUMBER_PARAM_REGEX = "(\\d+)\\)"; + + private static final String KEYWORD_REGEX = OPTIONAL.apply(NONLETTERS_REGEX) + + "#" + + LETTERS_REGEX + + NON_LIMITED_NUMBER_REGEX + + COLON_REGEX + + OPTIONAL_NUMBER_PARAM_REGEX + + OPTIONAL.apply(NONLETTERS_REGEX); + + private Integer additionalParameter1; + private Integer additionalParameter2; + + private TwoParameterKeyword(String name, List<String> meaningfulParts, Integer additionalParameter1, + Integer additionalParameter2) { + super(name, meaningfulParts); + this.additionalParameter1 = additionalParameter1; + this.additionalParameter2 = additionalParameter2; + } + + @Unapply + static Tuple1<TwoParameterKeyword> twoParameterKeyword(String keyword) { + val matcher = Pattern.compile(KEYWORD_REGEX).matcher(keyword); + TwoParameterKeyword tpk = null; + if (matcher.find()) { + tpk = new TwoParameterKeyword( + matcher.group(KEYWORD_NAME_GROUP), + extractPartsFrom(matcher, ADDITIONAL_PARAMETERS_GROUPS), + Integer.parseInt(matcher.group(ADDITIONAL_PARAMETER_1_GROUP)), + Integer.parseInt(matcher.group(ADDITIONAL_PARAMETER_2_GROUP)) + ); + } + return Tuple.of(tpk); + } + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventJob.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventJob.java new file mode 100644 index 0000000..c4b40fc --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventJob.java @@ -0,0 +1,93 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator.scheduler; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.onap.pnfsimulator.simulator.KeywordsHandler; +import org.onap.pnfsimulator.simulator.client.HttpClientAdapter; +import org.onap.pnfsimulator.simulator.client.HttpClientAdapterImpl; +import org.onap.pnfsimulator.simulator.client.utils.ssl.SSLAuthenticationHelper; +import org.quartz.Job; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.security.GeneralSecurityException; +import java.util.Optional; + +public class EventJob implements Job { + + private static final Logger LOGGER = LoggerFactory.getLogger(EventJob.class); + + static final String TEMPLATE_NAME = "TEMPLATE_NAME"; + static final String VES_URL = "VES_URL"; + static final String BODY = "BODY"; + static final String CLIENT_ADAPTER = "CLIENT_ADAPTER"; + static final String KEYWORDS_HANDLER = "KEYWORDS_HANDLER"; + static final String EVENT_ID = "EVENT_ID"; + + @Override + public void execute(JobExecutionContext jobExecutionContext) { + JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap(); + String templateName = jobDataMap.getString(TEMPLATE_NAME); + String vesUrl = jobDataMap.getString(VES_URL); + JsonObject body = (JsonObject) jobDataMap.get(BODY); + String id = jobDataMap.getString(EVENT_ID); + Optional<HttpClientAdapter> httpClientAdapter = getHttpClientAdapter(jobDataMap, vesUrl); + + if (httpClientAdapter.isPresent()) { + KeywordsHandler keywordsHandler = (KeywordsHandler) jobDataMap.get(KEYWORDS_HANDLER); + JsonElement processedBody = keywordsHandler.substituteKeywords(body, id); + String processedBodyString = processedBody.toString(); + String jobKey = jobExecutionContext.getJobDetail().getKey().toString(); + + logEventDetails(templateName, vesUrl, body.toString(), jobKey); + httpClientAdapter.get().send(processedBodyString); + } else { + LOGGER.error("Could not send event as client is not available"); + } + } + private Optional<HttpClientAdapter> getHttpClientAdapter(JobDataMap jobDataMap, String vesUrl) { + HttpClientAdapter adapter = null; + try { + adapter = (HttpClientAdapter) (jobDataMap.containsKey(CLIENT_ADAPTER) ? jobDataMap.get(CLIENT_ADAPTER) : + new HttpClientAdapterImpl(vesUrl, new SSLAuthenticationHelper())); + } catch (MalformedURLException e) { + LOGGER.error("Invalid format of vesServerUr: {}", vesUrl); + } catch (IOException | GeneralSecurityException e){ + LOGGER.error("Invalid configuration of client certificate"); + } + return Optional.ofNullable(adapter); + } + + private void logEventDetails(String templateName, String vesUrl, String body, String jobKey) { + LOGGER.info(String.format("Job %s:Sending event to %s from template %s", + jobKey, vesUrl, templateName)); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(String.format("Job %s: Request body %s", jobKey, body)); + } + } + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventScheduler.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventScheduler.java new file mode 100644 index 0000000..08e24f8 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventScheduler.java @@ -0,0 +1,121 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator.scheduler; + + +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.BODY; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.CLIENT_ADAPTER; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.EVENT_ID; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.KEYWORDS_HANDLER; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.TEMPLATE_NAME; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.VES_URL; +import static org.quartz.SimpleScheduleBuilder.simpleSchedule; + +import com.google.gson.JsonObject; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.security.GeneralSecurityException; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import org.onap.pnfsimulator.simulator.KeywordsHandler; +import org.onap.pnfsimulator.simulator.client.HttpClientAdapterImpl; +import org.onap.pnfsimulator.simulator.client.utils.ssl.SSLAuthenticationHelper; +import org.quartz.JobBuilder; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.JobExecutionContext; +import org.quartz.JobKey; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.SimpleTrigger; +import org.quartz.TriggerBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class EventScheduler { + + + private final Scheduler scheduler; + private final KeywordsHandler keywordsHandler; + private final SSLAuthenticationHelper SSLAuthenticationHelper; + + @Autowired + public EventScheduler(Scheduler scheduler, KeywordsHandler keywordsHandler, SSLAuthenticationHelper SSLAuthenticationHelper) { + this.scheduler = scheduler; + this.keywordsHandler = keywordsHandler; + this.SSLAuthenticationHelper = SSLAuthenticationHelper; + } + + public String scheduleEvent(String vesUrl, Integer repeatInterval, Integer repeatCount, + String templateName, String eventId, JsonObject body) + throws SchedulerException, IOException, GeneralSecurityException { + + JobDetail jobDetail = createJobDetail(vesUrl, templateName, eventId, body); + SimpleTrigger trigger = createTrigger(repeatInterval, repeatCount); + + scheduler.scheduleJob(jobDetail, trigger); + return jobDetail.getKey().getName(); + } + + public boolean cancelAllEvents() throws SchedulerException { + List<JobKey> jobKeys = getActiveJobsKeys(); + return scheduler.deleteJobs(jobKeys); + } + + public boolean cancelEvent(String jobName) throws SchedulerException { + Optional<JobKey> activeJobKey = getActiveJobsKeys().stream().filter(e -> e.getName().equals(jobName)).findFirst(); + return activeJobKey.isPresent() && scheduler.deleteJob(activeJobKey.get()); + } + + private SimpleTrigger createTrigger(int interval, int repeatCount) { + return TriggerBuilder.newTrigger() + .withSchedule(simpleSchedule() + .withIntervalInSeconds(interval) + .withRepeatCount(repeatCount - 1)) + .build(); + } + + private JobDetail createJobDetail(String vesUrl, String templateName, String eventId, JsonObject body) throws IOException, GeneralSecurityException { + JobDataMap jobDataMap = new JobDataMap(); + jobDataMap.put(TEMPLATE_NAME, templateName); + jobDataMap.put(VES_URL, vesUrl); + jobDataMap.put(EVENT_ID, eventId); + jobDataMap.put(KEYWORDS_HANDLER, keywordsHandler); + jobDataMap.put(BODY, body); + jobDataMap.put(CLIENT_ADAPTER, new HttpClientAdapterImpl(vesUrl, SSLAuthenticationHelper)); + + return JobBuilder + .newJob(EventJob.class) + .withDescription(templateName) + .usingJobData(jobDataMap) + .build(); + } + + private List<JobKey> getActiveJobsKeys() throws SchedulerException { + return scheduler.getCurrentlyExecutingJobs() + .stream() + .map(JobExecutionContext::getJobDetail) + .map(JobDetail::getKey) + .collect(Collectors.toList()); + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/scheduler/QuartzConfiguration.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/scheduler/QuartzConfiguration.java new file mode 100644 index 0000000..2beb9dc --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/scheduler/QuartzConfiguration.java @@ -0,0 +1,38 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator.scheduler; + +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.impl.StdSchedulerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +class QuartzConfiguration { + + @Bean + Scheduler provideScheduler() throws SchedulerException { + StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory(); + Scheduler scheduler = stdSchedulerFactory.getScheduler(); + scheduler.start(); + return scheduler; + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfig.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfig.java new file mode 100644 index 0000000..0baa477 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfig.java @@ -0,0 +1,49 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulatorconfig; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Field; + +import javax.validation.constraints.NotNull; +import java.net.URL; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@ToString +public class SimulatorConfig { + + @JsonIgnore + @Id + private String id; + + @NotNull + @Field("vesServerUrl") + private URL vesServerUrl; +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigRepository.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigRepository.java new file mode 100644 index 0000000..5e63ee4 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigRepository.java @@ -0,0 +1,26 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulatorconfig; + +import org.springframework.data.mongodb.repository.MongoRepository; + +public interface SimulatorConfigRepository extends MongoRepository<SimulatorConfig, String> { +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigService.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigService.java new file mode 100644 index 0000000..2063351 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigService.java @@ -0,0 +1,52 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulatorconfig; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class SimulatorConfigService { + + private final SimulatorConfigRepository repository; + + @Autowired + public SimulatorConfigService(SimulatorConfigRepository repository) { + this.repository = repository; + } + + + public SimulatorConfig getConfiguration() { + List<SimulatorConfig> configs = repository.findAll(); + if (configs.isEmpty()) { + throw new IllegalStateException("No configuration found in db"); + } + return configs.get(0); + } + + public SimulatorConfig updateConfiguration(SimulatorConfig configuration) { + SimulatorConfig currentConfig = getConfiguration(); + currentConfig.setVesServerUrl(configuration.getVesServerUrl()); + return repository.save(currentConfig); + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/FsToDbTemplateSynchronizer.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/FsToDbTemplateSynchronizer.java new file mode 100644 index 0000000..881585b --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/FsToDbTemplateSynchronizer.java @@ -0,0 +1,74 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.template; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.stream.Stream; + +import org.bson.json.JsonParseException; +import org.onap.pnfsimulator.db.Storage; +import org.onap.pnfsimulator.filesystem.WatcherEventProcessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +public class FsToDbTemplateSynchronizer { + + private static final String CANNOT_SYNC = "Cannot synchronize templates. Check whether the proper folder exists."; + private static final Logger LOGGER = LoggerFactory.getLogger(FsToDbTemplateSynchronizer.class); + + private final String templatesDir; + private final Storage<Template> storage; + + @Autowired + public FsToDbTemplateSynchronizer(@Value("${templates.dir}") String templatesDir, + Storage<Template> storage) { + this.templatesDir = templatesDir; + this.storage = storage; + } + + public void synchronize() { + try { + processTemplatesFolder(); + } catch (IOException e) { + LOGGER.error(CANNOT_SYNC, e); + } + } + + private void processTemplatesFolder() throws IOException { + try (Stream<Path> walk = Files.walk(Paths.get(templatesDir))) { + walk.filter(Files::isRegularFile).forEach(path -> { + try { + WatcherEventProcessor.MODIFIED.processEvent(path, storage); + } catch (IOException | JsonParseException e) { + LOGGER + .error("Cannot synchronize template: " + path.getFileName().toString(), e); + } + }); + } + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/Template.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/Template.java new file mode 100644 index 0000000..c84b8d0 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/Template.java @@ -0,0 +1,92 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.template; + +import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.onap.pnfsimulator.db.Row; +import org.bson.Document; +import org.onap.pnfsimulator.template.search.JsonUtils; +import org.springframework.data.mongodb.core.mapping.Field; + +@NoArgsConstructor +@ToString +public class Template extends Row { + + @Field("content") + private Document content; + + @Field("flatContent") + private Document flatContent; + + @Field("lmod") + private long lmod; + + public Template(String name, Document content, long lmod) { + this.id = name; + this.content = content; + this.lmod = lmod; + this.flatContent = new JsonUtils().flatten(content); + } + + public Template(String name, String template, long lmod) { + this.id = name; + this.content = Document.parse(template); + this.lmod = lmod; + this.flatContent = new JsonUtils().flatten(this.content); + } + + public void setContent(Document content) { + this.content = content; + this.flatContent = new JsonUtils().flatten(content); + } + + public Document getContent() { + return new Document(this.content); + } + + @JsonIgnore + public Document getFlatContent() { + return new Document(this.flatContent); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Template template = (Template) o; + return Objects.equals(content, template.content) + && Objects.equals(id, template.id) + && Objects.equals(lmod, template.lmod); + } + + @Override + public int hashCode() { + return Objects.hash(content, id); + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/TemplateRepository.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/TemplateRepository.java new file mode 100644 index 0000000..78c9c77 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/TemplateRepository.java @@ -0,0 +1,26 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.template; + +import org.springframework.data.mongodb.repository.MongoRepository; + +public interface TemplateRepository extends MongoRepository<Template, String> { +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/TemplateService.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/TemplateService.java new file mode 100644 index 0000000..3e245e1 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/TemplateService.java @@ -0,0 +1,81 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.template; + +import java.util.List; +import java.util.Optional; + +import com.google.gson.JsonObject; +import org.onap.pnfsimulator.db.Storage; +import org.onap.pnfsimulator.template.search.TemplateSearchHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +@Primary +@Service +public class TemplateService implements Storage<Template> { + + private final TemplateRepository templateRepository; + private TemplateSearchHelper searchHelper; + + + @Autowired + public TemplateService(TemplateRepository templateRepository, TemplateSearchHelper searchHelper) { + this.templateRepository = templateRepository; + this.searchHelper = searchHelper; + } + + @Override + public List<Template> getAll() { + return templateRepository.findAll(); + } + + @Override + public Optional<Template> get(String name) { + return templateRepository.findById(name); + } + + @Override + public void persist(Template template) { + templateRepository.save(template); + } + + @Override + public boolean tryPersistOrOverwrite(Template template, boolean overwrite) { + if (templateRepository.existsById(template.getId()) && !overwrite) { + return false; + } + templateRepository.save(template); + return true; + } + + @Override + public void delete(String templateName) { + templateRepository.deleteById(templateName); + } + + @Override + public List<String> getIdsByContentCriteria(JsonObject stringQueryJson) { + return searchHelper.getIdsOfDocumentMatchingCriteria(stringQueryJson); + } + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/IllegalJsonValueException.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/IllegalJsonValueException.java new file mode 100644 index 0000000..6890382 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/IllegalJsonValueException.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.template.search; + +public class IllegalJsonValueException extends IllegalArgumentException { + + IllegalJsonValueException(String s) { + super(s); + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/JsonUtils.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/JsonUtils.java new file mode 100644 index 0000000..b595b4f --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/JsonUtils.java @@ -0,0 +1,104 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.template.search; + +import com.google.common.base.Strings; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import org.bson.Document; + +/** + * This util flattens nested json and produces json with keys transformed to form of json path + * where default separator between parent object key and object key is ':' + * For easing searching of boolean values, they are converted to its string representation + */ +public class JsonUtils { + + private static final String DEFAULT_PARENT_KEY_TO_OBJECT_KEY_SEPARATOR = ":"; + private static final String SEED_PREFIX = ""; + private static final Gson GSON = new Gson(); + + public JsonObject flatten(JsonObject original) { + return flattenWithPrefixedKeys(DEFAULT_PARENT_KEY_TO_OBJECT_KEY_SEPARATOR, original.deepCopy(), SEED_PREFIX, new JsonObject()); + } + + public JsonObject flatten(String parentKeyToKeySeparator, JsonObject original) { + return flattenWithPrefixedKeys(parentKeyToKeySeparator, original.deepCopy(), SEED_PREFIX, new JsonObject()); + } + + public Document flatten(Document original) { + return flatten(DEFAULT_PARENT_KEY_TO_OBJECT_KEY_SEPARATOR, original); + } + + public Document flatten(String parentKeyToKeySeparator, Document original) { + JsonObject originalJsonObject = GSON.fromJson(original.toJson(), JsonObject.class); + JsonObject flattenedJson = flatten(parentKeyToKeySeparator, originalJsonObject); + return Document.parse(flattenedJson.toString()); + } + + private JsonObject flattenWithPrefixedKeys(String parentKeyToKeySeparator, JsonElement topLevelElem, String prefix, JsonObject acc) { + if (topLevelElem.isJsonPrimitive()) { + handleJsonPrimitive(topLevelElem, prefix, acc); + } else if (topLevelElem.isJsonArray()) { + handleJsonArray(parentKeyToKeySeparator, topLevelElem, prefix, acc); + } else if (topLevelElem.isJsonObject()) { + handleJsonObject(parentKeyToKeySeparator, topLevelElem, prefix, acc); + } else { + acc.add(prefix, topLevelElem.getAsJsonNull()); + } + return acc.deepCopy(); + } + + private void handleJsonObject(String parentKeyToKeySeparator, JsonElement topLevelElem, String prefix, JsonObject acc) { + boolean isEmpty = true; + JsonObject thisToplevelObj = topLevelElem.getAsJsonObject(); + for (String key : thisToplevelObj.keySet()) { + isEmpty = false; + String keyPrefix = String.format("%s%s%s", prefix, parentKeyToKeySeparator, key); + flattenWithPrefixedKeys(parentKeyToKeySeparator, thisToplevelObj.get(key), keyPrefix, acc); + } + if (isEmpty && !Strings.isNullOrEmpty(prefix)) { + acc.add(prefix, new JsonObject()); + } + } + + private void handleJsonArray(String parentKeyToKeySeparator, JsonElement topLevelElem, String prefix, JsonObject acc) { + JsonArray asJsonArray = topLevelElem.getAsJsonArray(); + if (asJsonArray.size() == 0) { + acc.add(prefix, new JsonArray()); + } + for (int i = 0; i < asJsonArray.size(); i++) { + flattenWithPrefixedKeys(parentKeyToKeySeparator, asJsonArray.get(i), String.format("%s[%s]", prefix, i), acc); + } + } + + private void handleJsonPrimitive(JsonElement topLevelElem, String prefix, JsonObject acc) { + JsonPrimitive jsonPrimitive = topLevelElem.getAsJsonPrimitive(); + if (jsonPrimitive.isBoolean()) { + acc.add(prefix, new JsonPrimitive(jsonPrimitive.getAsString())); + } else { + acc.add(prefix, topLevelElem.getAsJsonPrimitive()); + } + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/TemplateSearchHelper.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/TemplateSearchHelper.java new file mode 100644 index 0000000..3f22b1a --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/TemplateSearchHelper.java @@ -0,0 +1,95 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.template.search; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.onap.pnfsimulator.template.search.handler.PrimitiveValueCriteriaBuilder; +import org.onap.pnfsimulator.template.search.viewmodel.FlatTemplateContent; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +@Component +public class TemplateSearchHelper { + private static final String PARENT_TO_CHILD_KEY_SEPARATOR = ":"; //compliant with flat json stored in db + private static final String FLATTENED_JSON_KEY_REGEX = PARENT_TO_CHILD_KEY_SEPARATOR + "%s(?:(\\[[\\d]+\\]))?$"; + private static final String FLATTENED_TEMPLATES_VIEW = "flatTemplatesView"; + + private MongoTemplate mongoTemplate; + private PrimitiveValueCriteriaBuilder criteriaBuilder; + + @Autowired + public TemplateSearchHelper(MongoTemplate mongoTemplate) { + this.mongoTemplate = mongoTemplate; + this.criteriaBuilder = new PrimitiveValueCriteriaBuilder(); + } + + public List<String> getIdsOfDocumentMatchingCriteria(JsonObject jsonCriteria) { + if (isNullValuePresentInCriteria(jsonCriteria)) { + throw new IllegalJsonValueException("Null values in search criteria are not supported."); + } + Criteria mongoDialectCriteria = composeCriteria(jsonCriteria); + Query query = new Query(mongoDialectCriteria); + List<FlatTemplateContent> flatTemplateContents = mongoTemplate.find(query, FlatTemplateContent.class, FLATTENED_TEMPLATES_VIEW); + return flatTemplateContents + .stream() + .map(FlatTemplateContent::getId) + .collect(Collectors.toList()); + } + + + private Criteria composeCriteria(JsonObject criteria) { + Criteria[] criteriaArr = criteria.entrySet() + .stream() + .map(this::mapEntryCriteriaWithRegex) + .toArray(Criteria[]::new); + return criteriaArr.length > 0 ? new Criteria().andOperator(criteriaArr) : new Criteria(); + } + + private Criteria mapEntryCriteriaWithRegex(Map.Entry<String, JsonElement> entry) { + Pattern primitiveOrArrayElemKeyRegex = getCaseInsensitive(String.format(FLATTENED_JSON_KEY_REGEX, entry.getKey())); + Criteria criteriaForJsonKey = Criteria.where("k").regex(primitiveOrArrayElemKeyRegex); + Criteria criteriaWithValue = criteriaBuilder.applyValueCriteriaBasedOnPrimitiveType(criteriaForJsonKey.and("v"), entry.getValue().getAsJsonPrimitive()); + return Criteria.where("keyValues").elemMatch(criteriaWithValue); + + } + + private boolean isNullValuePresentInCriteria(JsonObject jsonObject) { + return jsonObject.entrySet() + .stream() + .map(Map.Entry::getValue) + .anyMatch(JsonElement::isJsonNull); + } + + static Pattern getCaseInsensitive(String base) { + return Pattern.compile(base, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + } +} + + diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilder.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilder.java new file mode 100644 index 0000000..79d64b7 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilder.java @@ -0,0 +1,103 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.template.search.handler; + +import com.google.common.collect.Lists; +import com.google.gson.JsonPrimitive; +import org.springframework.data.mongodb.core.query.Criteria; + +import java.util.List; +import java.util.regex.Pattern; + +/** + * This class is a helper class for constructing apropriate criteria for query send to mongodb based on type of value. + * Query is build to search mongodb for templates that contains key-value pairs that satisfy given criteria. + * Value is oftype JsonPrimitive, based on its primitive java type following criteria are build to get proper document: + * -for string - there is a regex expression that ignores every meta character inside passed argument and searches for exact literal match ignoring case; + * -for number - all numbers are treated as double (mongodb number type equivalent) + * -for boolean - exact match, used string representation of boolean in search + **/ + +public class PrimitiveValueCriteriaBuilder { + + private final List<ValueTypeHandler> typeHandlers; + + public PrimitiveValueCriteriaBuilder() { + typeHandlers = Lists.newArrayList(new StringValueHandler(), new NumberValueHandler(), new BoolValueHandler()); + } + + public Criteria applyValueCriteriaBasedOnPrimitiveType(Criteria baseCriteria, JsonPrimitive jsonPrimitive) { + ValueTypeHandler typeHandler = typeHandlers.stream() + .filter(el -> el.isProperTypeHandler(jsonPrimitive)) + .findFirst() + .orElseThrow(() -> + new IllegalArgumentException(String.format( + "Expected json primitive, but given value: %s is of type: %s and could not be decoded", + jsonPrimitive, jsonPrimitive.getClass().toString()))); + return typeHandler.chainCriteriaForValue(baseCriteria, jsonPrimitive); + } + + private interface ValueTypeHandler { + boolean isProperTypeHandler(JsonPrimitive value); + + Criteria chainCriteriaForValue(Criteria criteria, JsonPrimitive value); + } + + private class BoolValueHandler implements ValueTypeHandler { + public boolean isProperTypeHandler(JsonPrimitive value) { + return value.isBoolean(); + } + + public Criteria chainCriteriaForValue(Criteria criteria, JsonPrimitive value) { + return criteria.is(value.getAsString()); + } + + } + + private class NumberValueHandler implements ValueTypeHandler { + public boolean isProperTypeHandler(JsonPrimitive value) { + return value.isNumber(); + } + + public Criteria chainCriteriaForValue(Criteria baseCriteria, JsonPrimitive value) { + return baseCriteria.is(value.getAsDouble()); + } + } + + private class StringValueHandler implements ValueTypeHandler { + public boolean isProperTypeHandler(JsonPrimitive value) { + return value.isString(); + } + + public Criteria chainCriteriaForValue(Criteria baseCriteria, JsonPrimitive value) { + return baseCriteria.regex(makeRegexCaseInsensitive(value.getAsString())); + } + + private Pattern makeRegexCaseInsensitive(String base) { + String metaCharEscaped = convertToIgnoreMetaChars(base); + return Pattern.compile("^" + metaCharEscaped + "$", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + } + + private String convertToIgnoreMetaChars(String valueWithMetaChars) { + return Pattern.quote(valueWithMetaChars); + } + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/viewmodel/FlatTemplateContent.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/viewmodel/FlatTemplateContent.java new file mode 100644 index 0000000..84235f7 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/viewmodel/FlatTemplateContent.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.template.search.viewmodel; + + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.onap.pnfsimulator.db.Row; + +import java.util.List; + +@Getter +@NoArgsConstructor +@ToString +public class FlatTemplateContent extends Row { + + private List<KeyValuePair> keyValues; + + + public FlatTemplateContent(String name, List<KeyValuePair> keyValues) { + this.id = name; + this.keyValues = keyValues; + } +} + + diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/viewmodel/KeyValuePair.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/viewmodel/KeyValuePair.java new file mode 100644 index 0000000..5e44452 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/template/search/viewmodel/KeyValuePair.java @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.template.search.viewmodel; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@ToString +@NoArgsConstructor +@AllArgsConstructor +/** + * POJO for mongo structure after $objectToArray mapping where object consists of fields: k and v + */ +public class KeyValuePair { + + private String k; + private String v; + +} diff --git a/pnfsimulator/src/main/resources/application.properties b/pnfsimulator/src/main/resources/application.properties new file mode 100644 index 0000000..e2c7639 --- /dev/null +++ b/pnfsimulator/src/main/resources/application.properties @@ -0,0 +1,18 @@ +server.port=5000 +templates.dir=/app/templates +spring.data.mongodb.host=mongo +spring.data.mongodb.port=27017 +spring.data.mongodb.username=pnf_simulator_user +spring.data.mongodb.password=zXcVbN123! +spring.data.mongodb.database=pnf_simulator +management.endpoints.enabled-by-default=true +management.endpoint.configprops.enabled=true +management.endpoints.web.base-path=/ +management.server.port=5001 +management.endpoints.web.exposure.include=refresh + +ssl.clientCertificateEnabled=true +ssl.clientCertificateDir=/app/store/client.p12 +ssl.clientCertificatePassword=collector +ssl.trustStoreDir=/app/store/trustStore +ssl.trustStorePassword=collector diff --git a/pnfsimulator/src/main/resources/logback.xml b/pnfsimulator/src/main/resources/logback.xml new file mode 100644 index 0000000..8569b56 --- /dev/null +++ b/pnfsimulator/src/main/resources/logback.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + Simulator + ================================================================================ + Copyright (C) 2019 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========================================================= + --> + +<Configuration complete="true" compact="true"> + + <Property name="outputFilename" value="pnfsimulator_output"/> + <Property name="log-path" value="/var/log/ONAP/pnfsimulator"/> + <Property name="archive" value="/var/log/ONAP/pnfsimulator/archive"/> + <property name="maxFileSize" value="50MB"/> + <property name="maxHistory" value="30"/> + <property name="totalSizeCap" value="10GB"/> + + <appender name="Console" target="SYSTEM_OUT" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <Pattern>%nopexception%logger + |%date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX,UTC} + |%level + |%replace(%replace(%message){'\t','\\\\t'}){'\n','\\\\n'} + |%replace(%replace(%mdc){'\t','\\\\t'}){'\n','\\\\n'} + |%replace(%replace(%rootException){'\t','\\\\t'}){'\n','\\\\n'} + |%replace(%replace(%marker){'\t','\\\\t'}){'\n','\\\\n'} + |%thread + |%n</Pattern> + </encoder> + </appender> + + <appender name="ROLLING-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <encoder> + <pattern>%nopexception%logger + |%date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX,UTC} + |%level + |%replace(%replace(%message){'\t','\\\\t'}){'\n','\\\\n'} + |%replace(%replace(%mdc){'\t','\\\\t'}){'\n','\\\\n'} + |%replace(%replace(%rootException){'\t','\\\\t'}){'\n','\\\\n'} + |%replace(%replace(%marker){'\t','\\\\t'}){'\n','\\\\n'} + |%thread + |%n</pattern> + </encoder> + <File>${log-path}/${outputFilename}.log</File> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <FileNamePattern>${archive}/${outputFilename}.%d{yyyy-MM-dd}.%i.log.zip</FileNamePattern> + <MaxFileSize>${maxFileSize}</MaxFileSize> + <MaxHistory>${maxHistory}</MaxHistory> + <TotalSizeCap>${totalSizeCap}</TotalSizeCap> + </rollingPolicy> + </appender> + + <root level="info"> + <appender-ref ref="Console" /> + <appender-ref ref="ROLLING-FILE" /> + </root> +</Configuration> diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/event/EventDataServiceTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/event/EventDataServiceTest.java new file mode 100644 index 0000000..5ed51cc --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/event/EventDataServiceTest.java @@ -0,0 +1,133 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.event; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.hamcrest.collection.IsIterableContainingInOrder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +public class EventDataServiceTest { + + @Mock + private EventDataRepository repositoryMock; + + @InjectMocks + private EventDataService service; + + private static EventData sampleEventData(String id, String template, + String patched, String input, String keywords) { + return EventData.builder() + .id(id) + .template(template) + .patched(patched) + .input(input) + .keywords(keywords) + .build(); + } + + @BeforeEach + void resetMocks() { + initMocks(this); + } + + @Test + void persistEventDataJsonObjectTest() { + JsonParser parser = new JsonParser(); + JsonObject template = parser.parse("{ \"bla1\": \"bla2\"}").getAsJsonObject(); + JsonObject patched = parser.parse("{ \"bla3\": \"bla4\"}").getAsJsonObject(); + JsonObject input = parser.parse("{ \"bla5\": \"bla6\"}").getAsJsonObject(); + JsonObject keywords = parser.parse("{ \"bla7\": \"bla8\"}").getAsJsonObject(); + ArgumentCaptor<EventData> argumentCaptor = ArgumentCaptor.forClass(EventData.class); + + service.persistEventData(template, patched, input, keywords); + + verify(repositoryMock).save(argumentCaptor.capture()); + EventData captured = argumentCaptor.getValue(); + + assertEquals(captured.getTemplate(), template.toString()); + assertEquals(captured.getPatched(), patched.toString()); + assertEquals(captured.getInput(), input.toString()); + assertEquals(captured.getKeywords(), keywords.toString()); + } + + @Test + void getAllEventsTest() { + + List<EventData> eventDataList = new ArrayList<>(); + EventData ed1 = sampleEventData("id1", "t1", "p1", "i1", "k1"); + EventData ed2 = sampleEventData("id2", "t2", "p2", "i2", "k2"); + eventDataList.add(ed1); + eventDataList.add(ed2); + + when(repositoryMock.findAll()).thenReturn(eventDataList); + List<EventData> actualList = service.getAllEvents(); + + assertEquals(eventDataList.size(), actualList.size()); + assertThat(actualList, IsIterableContainingInOrder.contains(ed1, ed2)); + } + + @Test + void findByIdPresentTest() { + String id = "some_object"; + EventData eventData = sampleEventData(id, "template", "patched", "input", "keywords"); + Optional<EventData> optional = Optional.of(eventData); + + when(repositoryMock.findById(id)).thenReturn(optional); + + Optional<EventData> actualOptional = service.getById(id); + assertTrue(actualOptional.isPresent()); + EventData actualObject = actualOptional.get(); + assertEquals(eventData.getId(), actualObject.getId()); + assertEquals(eventData.getTemplate(), actualObject.getTemplate()); + assertEquals(eventData.getPatched(), actualObject.getPatched()); + assertEquals(eventData.getInput(), actualObject.getInput()); + assertEquals(eventData.getKeywords(), actualObject.getKeywords()); + + } + + @Test + void findByIdNotPresentTest() { + String id = "some_object"; + Optional<EventData> optional = Optional.empty(); + + when(repositoryMock.findById(id)).thenReturn(optional); + + Optional<EventData> actualOptional = service.getById(id); + assertTrue(!actualOptional.isPresent()); + } +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/filesystem/InMemoryTemplateStorage.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/filesystem/InMemoryTemplateStorage.java new file mode 100644 index 0000000..98c4bc5 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/filesystem/InMemoryTemplateStorage.java @@ -0,0 +1,71 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.filesystem; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import com.google.gson.JsonObject; +import org.onap.pnfsimulator.db.Storage; +import org.onap.pnfsimulator.template.Template; + +public class InMemoryTemplateStorage implements Storage<Template> { + + private List<Template> storage = new ArrayList<>(); + + @Override + public List<Template> getAll() { + return new ArrayList<>(storage); + } + + @Override + public Optional<Template> get(String name) { + return storage.stream().filter(template -> template.getId().equals(name)).findFirst(); + } + + @Override + public void persist(Template template) { + if (!storage.contains(template)){ + storage.add(template); + } + } + + @Override + public boolean tryPersistOrOverwrite(Template template, boolean overwrite) { + if (!storage.contains(template) || overwrite){ + storage.add(template); + return true; + } + return false; + } + + @Override + public void delete(String templateName) { + get(templateName).ifPresent(template -> storage.remove(template)); + } + + @Override + public List<String> getIdsByContentCriteria(JsonObject queryJson) { + throw new RuntimeException("Method is not implemented."); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessorTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessorTest.java new file mode 100644 index 0000000..42ed4d3 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessorTest.java @@ -0,0 +1,124 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.filesystem; + +import static junit.framework.TestCase.fail; +import static org.mockito.MockitoAnnotations.initMocks; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardWatchEventKinds; +import java.nio.file.WatchEvent; +import java.time.Instant; +import java.util.Collections; +import java.util.HashMap; +import java.util.Optional; +import org.bson.Document; +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.mockito.Mock; +import org.mockito.Mockito; +import org.onap.pnfsimulator.db.Storage; +import org.onap.pnfsimulator.template.Template; + +class WatcherEventProcessorTest { + + @Mock + private WatchEvent watchEvent; + @Mock + private Path templatesDir; + + private Storage<Template> storage; + private static Path jsonFilePath; + + @BeforeAll + static void init() { + jsonFilePath = Paths.get("src/test/resources/org/onap/pnfsimulator/simulator/filesystem/test1.json"); + } + + @BeforeEach + void resetMocks() { + initMocks(this); + storage = new InMemoryTemplateStorage(); + initStubs(); + } + + @Test + void shouldProcessCreatedEventTest() { + // when + Mockito.when(watchEvent.kind()).thenReturn(StandardWatchEventKinds.ENTRY_CREATE); + WatcherEventProcessor.process(watchEvent, storage, templatesDir); + // then + verifyPersistedValue(); + } + + @Test + void shouldProcessModifiedEventTest() { + //given + storage.persist(new Template("test1.json", new Document(Collections.emptyMap()), Instant.now().getNano())); + // when + Mockito.when(watchEvent.kind()).thenReturn(StandardWatchEventKinds.ENTRY_MODIFY); + WatcherEventProcessor.process(watchEvent, storage, templatesDir); + // then + verifyPersistedValue(); + } + + private void verifyPersistedValue() { + Assertions.assertEquals(storage.getAll().size(), 1); + Optional<Template> templateFromStorage = storage.get("test1.json"); + if (templateFromStorage.isPresent()) { + Template retrievedTemplate = templateFromStorage.get(); + Document templateContent = retrievedTemplate.getContent(); + Document flatContent = retrievedTemplate.getFlatContent(); + Assertions.assertEquals(templateContent.getString("field1"), "value1"); + Assertions.assertEquals(templateContent.getInteger("field2", 0), 2); + Assertions.assertEquals(flatContent.getInteger(":nested:key1[0]", 0), 1); + Assertions.assertEquals(flatContent.getInteger(":nested:key1[1]", 0), 2); + Assertions.assertEquals(flatContent.getInteger(":nested:key1[2]", 0), 3); + Assertions.assertEquals(flatContent.getString(":nested:key2"), "sampleValue2"); + } else { + fail(); + } + } + + @Test + void shouldProcessDeletedEventTest() { + //given + HashMap<String, Object> legacyObject = new HashMap<>(); + legacyObject.put("field1", "value1"); + legacyObject.put("field2", 2); + + storage.persist(new Template("test1.json", new Document(legacyObject), Instant.now().getNano())); + // when + Mockito.when(watchEvent.kind()).thenReturn(StandardWatchEventKinds.ENTRY_DELETE); + WatcherEventProcessor.process(watchEvent, storage, templatesDir); + // then + Assertions.assertEquals(storage.getAll().size(), 0); + } + + private void initStubs() { + Mockito.when(templatesDir.resolve(jsonFilePath)).thenReturn(jsonFilePath); + Mockito.when(watchEvent.context()).thenReturn(jsonFilePath); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/SimulatorControllerTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/SimulatorControllerTest.java new file mode 100644 index 0000000..dae16c7 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/SimulatorControllerTest.java @@ -0,0 +1,212 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.rest; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.onap.pnfsimulator.rest.model.FullEvent; +import org.onap.pnfsimulator.rest.model.SimulatorParams; +import org.onap.pnfsimulator.rest.model.SimulatorRequest; +import org.onap.pnfsimulator.rest.util.JsonObjectDeserializer; +import org.onap.pnfsimulator.simulator.SimulatorService; +import org.onap.pnfsimulator.simulatorconfig.SimulatorConfig; +import org.quartz.SchedulerException; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import java.io.IOException; +import java.net.URL; +import java.security.GeneralSecurityException; + +import static org.assertj.core.api.Java6Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +class SimulatorControllerTest { + + private static final String START_ENDPOINT = "/simulator/start"; + private static final String CONFIG_ENDPOINT = "/simulator/config"; + private static final String EVENT_ENDPOINT = "/simulator/event"; + private static final String JSON_MSG_EXPRESSION = "$.message"; + + private static final String NEW_URL = "http://0.0.0.0:8090/eventListener/v7"; + private static final String UPDATE_SIM_CONFIG_VALID_JSON = "{\"vesServerUrl\": \"" + NEW_URL + "\"}"; + private static final String SAMPLE_ID = "sampleId"; + private static final Gson GSON_OBJ = new Gson(); + private static String simulatorRequestBody; + private MockMvc mockMvc; + @InjectMocks + private SimulatorController controller; + @Mock + private SimulatorService simulatorService; + + @BeforeAll + static void beforeAll() { + SimulatorParams simulatorParams = new SimulatorParams("http://0.0.0.0:8080", 1, 1); + SimulatorRequest simulatorRequest = new SimulatorRequest(simulatorParams, + "testTemplate.json", new JsonObject()); + + simulatorRequestBody = GSON_OBJ.toJson(simulatorRequest); + } + + @BeforeEach + void setup() throws IOException, SchedulerException, GeneralSecurityException { + MockitoAnnotations.initMocks(this); + when(simulatorService.triggerEvent(any())).thenReturn("jobName"); + mockMvc = MockMvcBuilders + .standaloneSetup(controller) + .build(); + } + + @Test + void shouldStartSimulatorProperly() throws Exception { + startSimulator(); + SimulatorRequest simulatorRequest = new Gson().fromJson(simulatorRequestBody, SimulatorRequest.class); + + verify(simulatorService).triggerEvent(eq(simulatorRequest)); + } + + @Test + void testShouldGetConfigurationWhenRequested() throws Exception { + String newUrl = "http://localhost:8090/eventListener/v7"; + SimulatorConfig expectedConfig = new SimulatorConfig(SAMPLE_ID, new URL(newUrl)); + when(simulatorService.getConfiguration()).thenReturn(expectedConfig); + + MvcResult getResult = mockMvc + .perform(get(CONFIG_ENDPOINT) + .contentType(MediaType.APPLICATION_JSON) + .content(UPDATE_SIM_CONFIG_VALID_JSON)) + .andExpect(status().isOk()) + .andReturn(); + + String expectedVesUrlJsonPart = createStringReprOfJson("vesServerUrl", newUrl); + assertThat(getResult.getResponse().getContentAsString()).contains(expectedVesUrlJsonPart); + } + + @Test + void testShouldSuccessfullyUpdateConfigurationWithNewVesUrl() throws Exception { + String oldUrl = "http://localhost:8090/eventListener/v7"; + SimulatorConfig expectedConfigBeforeUpdate = new SimulatorConfig(SAMPLE_ID, new URL(oldUrl)); + SimulatorConfig expectedConfigAfterUpdate = new SimulatorConfig(SAMPLE_ID, new URL(NEW_URL)); + + when(simulatorService.getConfiguration()).thenReturn(expectedConfigBeforeUpdate); + when(simulatorService.updateConfiguration(any(SimulatorConfig.class))).thenReturn(expectedConfigAfterUpdate); + + MvcResult postResult = mockMvc + .perform(put(CONFIG_ENDPOINT) + .contentType(MediaType.APPLICATION_JSON) + .content(UPDATE_SIM_CONFIG_VALID_JSON)) + .andExpect(status().isOk()) + .andReturn(); + + String expectedVesUrlJsonPart = createStringReprOfJson("vesServerUrl", expectedConfigAfterUpdate.getVesServerUrl().toString()); + assertThat(postResult.getResponse().getContentAsString()).contains(expectedVesUrlJsonPart); + } + + @Test + void testShouldRaiseExceptionWhenUpdateConfigWithIncorrectPayloadWasSent() throws Exception { + mockMvc + .perform(put(CONFIG_ENDPOINT) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"vesUrl\": \"" + NEW_URL + "\"}")) + .andExpect(status().isBadRequest()); + } + + @Test + void testShouldRaiseExceptionWhenUrlInInvalidFormatIsSent() throws Exception { + mockMvc + .perform(put(CONFIG_ENDPOINT) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"vesUrl\": \"http://0.0.0.0:VES-PORT/eventListener/v7\"}")) + .andExpect(status().isBadRequest()); + } + + @Test + void testShouldSendEventDirectly() throws Exception { + String contentAsString = mockMvc + .perform(post(EVENT_ENDPOINT) + .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE) + .content("{\"vesServerUrl\":\"http://0.0.0.0:8080/simulator/v7\",\n" + + " \"event\":{ \n" + + " \"commonEventHeader\":{ \n" + + " \"domain\":\"notification\",\n" + + " \"eventName\":\"vFirewallBroadcastPackets\"\n" + + " },\n" + + " \"notificationFields\":{ \n" + + " \"arrayOfNamedHashMap\":[ \n" + + " { \n" + + " \"name\":\"A20161221.1031-1041.bin.gz\",\n" + + " \"hashMap\":{ \n" + + " \"fileformatType\":\"org.3GPP.32.435#measCollec\"}}]}}}")) + .andExpect(status().isAccepted()).andReturn().getResponse().getContentAsString(); + assertThat(contentAsString).contains("One-time direct event sent successfully"); + } + + @Test + void testShouldReplaceKeywordsAndSendEventDirectly() throws Exception { + String contentAsString = mockMvc + .perform(post(EVENT_ENDPOINT) + .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE) + .content("{\"vesServerUrl\": \"http://localhost:9999/eventListener\",\n" + + " \"event\": {\n" + + " \"commonEventHeader\": {\n" + + " \"eventId\": \"#RandomString(20)\",\n" + + " \"sourceName\": \"PATCHED_sourceName\",\n" + + " \"version\": 3.0\n}}}")) + .andExpect(status().isAccepted()).andReturn().getResponse().getContentAsString(); + assertThat(contentAsString).contains("One-time direct event sent successfully"); + + verify(simulatorService, Mockito.times(1)).triggerOneTimeEvent(any(FullEvent.class)); + } + + + private void startSimulator() throws Exception { + mockMvc + .perform(post(START_ENDPOINT) + .content(simulatorRequestBody) + .contentType(MediaType.APPLICATION_JSON).characterEncoding("utf-8")) + .andExpect(status().isOk()) + .andExpect(jsonPath(JSON_MSG_EXPRESSION).value("Request started")); + + } + + private String createStringReprOfJson(String key, String value) { + return GSON_OBJ.toJson(ImmutableMap.of(key, value)); + } +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/TemplateControllerTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/TemplateControllerTest.java new file mode 100644 index 0000000..f34d73c --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/TemplateControllerTest.java @@ -0,0 +1,256 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.rest; + +import static org.assertj.core.api.Java6Assertions.assertThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.onap.pnfsimulator.rest.TemplateController.CANNOT_OVERRIDE_TEMPLATE_MSG; +import static org.onap.pnfsimulator.rest.TemplateController.TEMPLATE_NOT_FOUND_MSG; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.assertj.core.util.Lists; +import org.bson.Document; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import static org.mockito.Mockito.times; +import org.mockito.MockitoAnnotations; +import org.onap.pnfsimulator.db.Storage; +import org.onap.pnfsimulator.rest.model.SearchExp; +import org.onap.pnfsimulator.template.Template; +import org.onap.pnfsimulator.template.search.IllegalJsonValueException; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +class TemplateControllerTest { + + private static final String LIST_URL = "/template/list"; + private static final String GET_FORMAT_STR = "/template/get/%s"; + private static final String SEARCH_ENDPOINT = "/template/search"; + private static final String UPLOAD_URL_NOFORCE = "/template/upload"; + private static final String UPLOAD_URL_FORCE = "/template/upload?override=true"; + private static final String SAMPLE_TEMPLATE_JSON = "{\"event\": {\n" + + " \"commonEventHeader\": {\n" + + " \"domain\": \"measurementsForVfScaling\",\n" + + " \"eventName\": \"vFirewallBroadcastPackets\",\n" + + " }" + + "}}"; + + public static final String TEMPLATE_REQUEST = "{\n" + + " \"name\": \"someTemplate\",\n" + + " \"template\": {\n" + + " \"commonEventHeader\": {\n" + + " \"domain\": \"notification\",\n" + + " \"eventName\": \"vFirewallBroadcastPackets\"\n" + + " },\n" + + " \"notificationFields\": {\n" + + " \"arrayOfNamedHashMap\": [{\n" + + " \"name\": \"A20161221.1031-1041.bin.gz\",\n" + + "\n" + + " \"hashMap\": {\n" + + " \"fileformatType\": \"org.3GPP.32.435#measCollec\"\n" + + " }\n" + + " }]\n" + + " }\n" + + " }\n" + + "}"; + private static final Document SAMPLE_TEMPLATE_BSON = Document.parse(SAMPLE_TEMPLATE_JSON); + private static final List<String> SAMPLE_TEMPLATE_NAME_LIST = Lists.newArrayList("notification.json", "registration.json"); + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private static final Gson GSON_OBJ = new GsonBuilder().create(); + private MockMvc mockMvc; + + @Mock + private Storage<Template> templateService; + @InjectMocks + private TemplateController controller; + + @BeforeEach + void setup() { + MockitoAnnotations.initMocks(this); + mockMvc = MockMvcBuilders + .standaloneSetup(controller) + .build(); + } + + @Test + void shouldGetAllTemplates() throws Exception { + List<Template> templateList = createTemplatesList(); + when(templateService.getAll()).thenReturn(templateList); + + MvcResult getResult = mockMvc + .perform(get(LIST_URL) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andReturn(); + + Type listType = new TypeToken<ArrayList<Template>>() {}.getType(); + List<Template> resultList = GSON_OBJ.fromJson(getResult.getResponse().getContentAsString(), listType); + assertThat(resultList).containsExactlyInAnyOrderElementsOf(templateList); + } + + @Test + void shouldListEmptyCollectionWhenNoTemplatesAvailable() throws Exception { + List<Template> templateList = Collections.emptyList(); + when(templateService.getAll()).thenReturn(templateList); + + MvcResult getResult = mockMvc + .perform(get(LIST_URL)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andReturn(); + + String templatesAsString = GSON_OBJ.toJson(templateList); + assertThat(getResult.getResponse().getContentAsString()).containsSequence(templatesAsString); + } + + @Test + void shouldSuccessfullyGetExisitngTemplateByName() throws Exception { + String sampleTemplateName = "someTemplate"; + String requestUrl = String.format(GET_FORMAT_STR, sampleTemplateName); + Template sampleTemplate = new Template(sampleTemplateName, SAMPLE_TEMPLATE_BSON, 0L); + + when(templateService.get(sampleTemplateName)).thenReturn(Optional.of(sampleTemplate)); + + MvcResult getResult = mockMvc + .perform(get(requestUrl)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andReturn(); + + Template result = new Gson().fromJson(getResult.getResponse().getContentAsString(), Template.class); + assertThat(result).isEqualTo(sampleTemplate); + } + + @Test + void shouldReturnNotFoundWhenGetNonExisitngTemplateByName() throws Exception { + String sampleTemplateName = "doesNotExist"; + String requestUrl = String.format(GET_FORMAT_STR, sampleTemplateName); + + when(templateService.get(sampleTemplateName)).thenReturn(Optional.empty()); + + MvcResult getResult = mockMvc + .perform(get(requestUrl)) + .andExpect(status().isNotFound()) + .andExpect(content().contentType(MediaType.TEXT_PLAIN_VALUE)) + .andReturn(); + + assertThat(getResult.getResponse().getContentLength()).isEqualTo(TEMPLATE_NOT_FOUND_MSG.length()); + } + + + @Test + void shouldReturnNamesOfTemplatesThatSatisfyGivenCriteria() throws Exception { + when(templateService.getIdsByContentCriteria(any(JsonObject.class))).thenReturn(SAMPLE_TEMPLATE_NAME_LIST); + SearchExp expr = new SearchExp(new JsonObject()); + + String responseContent = mockMvc + .perform(post(SEARCH_ENDPOINT).content(GSON_OBJ.toJson(expr)).contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andReturn().getResponse().getContentAsString(); + + List<String> actualTemplates = OBJECT_MAPPER.readValue(responseContent, new TypeReference<List<String>>() {}); + verify(templateService, times(1)).getIdsByContentCriteria(any(JsonObject.class)); + assertThat(actualTemplates).isEqualTo(SAMPLE_TEMPLATE_NAME_LIST); + } + + @Test + void shouldRaiseBadRequestWhenNullValueProvidedInSearchJsonAsJsonValue() throws Exception { + when(templateService.getIdsByContentCriteria(any(JsonObject.class))).thenThrow(IllegalJsonValueException.class); + SearchExp expr = new SearchExp(new JsonObject()); + + mockMvc.perform(post(SEARCH_ENDPOINT) + .content(GSON_OBJ.toJson(expr)) + .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andExpect(status().isBadRequest()); + } + + + @Test + void testTryUploadNewTemplate() throws Exception { + when(templateService.tryPersistOrOverwrite(any(Template.class), eq(false))).thenReturn(true); + + MvcResult postResult = mockMvc + .perform(post(UPLOAD_URL_NOFORCE) + .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE) + .content(TEMPLATE_REQUEST)) + .andExpect(status().isCreated()) + .andReturn(); + } + + @Test + void testTryUploadNewTemplateWithForce() throws Exception { + when(templateService.tryPersistOrOverwrite(any(Template.class), eq(true))).thenReturn(true); + + MvcResult postResult = mockMvc + .perform(post(UPLOAD_URL_FORCE) + .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE) + .content(TEMPLATE_REQUEST)) + .andExpect(status().isCreated()) + .andReturn(); + } + + @Test + void testOverrideExistingTemplateWithoutForceShouldFail() throws Exception { + when(templateService.tryPersistOrOverwrite(any(Template.class), eq(true))).thenReturn(false); + + MvcResult postResult = mockMvc + .perform(post(UPLOAD_URL_FORCE) + .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE) + .content(TEMPLATE_REQUEST)) + .andExpect(status().isConflict()) + .andReturn(); + + assertThat(postResult.getResponse().getContentAsString()).isEqualTo(CANNOT_OVERRIDE_TEMPLATE_MSG); + } + + private List<Template> createTemplatesList() { + return Arrays.asList( + new Template("1", SAMPLE_TEMPLATE_BSON, 0L), + new Template("2", SAMPLE_TEMPLATE_BSON, 0L), + new Template("3", SAMPLE_TEMPLATE_BSON, 0L)); + } +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/util/DateUtilTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/util/DateUtilTest.java new file mode 100644 index 0000000..1591a59 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/util/DateUtilTest.java @@ -0,0 +1,38 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.rest.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import org.junit.jupiter.api.Test; + +class DateUtilTest { + + @Test + void getFormattedDate() { + Calendar currentCalendar = Calendar.getInstance(); + String expectedResult = String.valueOf(currentCalendar.get(Calendar.YEAR)); + + assertEquals(expectedResult, DateUtil.getTimestamp(new SimpleDateFormat("yyyy"))); + } +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/util/ResponseBuilderTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/util/ResponseBuilderTest.java new file mode 100644 index 0000000..0d62ee9 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/rest/util/ResponseBuilderTest.java @@ -0,0 +1,65 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.rest.util; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +class ResponseBuilderTest { + + + private static final HttpStatus SAMPLE_STATUS = HttpStatus.OK; + + @Test + void response_should_have_empty_body_when_built_immediately() { + ResponseEntity responseEntity = ResponseBuilder.status(SAMPLE_STATUS).build(); + + assertAll( + () -> assertEquals(responseEntity.getStatusCode(), SAMPLE_STATUS), + () -> assertNull(responseEntity.getBody()) + ); + } + + @Test + void builder_should_set_response_status_and_body() { + String key = "key"; + String value = "value"; + ResponseEntity response = ResponseBuilder + .status(SAMPLE_STATUS) + .put(key, value) + .build(); + + Map<String, Object> body = (Map<String, Object>) response.getBody(); + + assertAll( + () -> assertEquals(SAMPLE_STATUS, response.getStatusCode()), + () -> assertEquals(value, body.get(key)) + ); + } + + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/IncrementProviderImplTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/IncrementProviderImplTest.java new file mode 100644 index 0000000..53f02da --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/IncrementProviderImplTest.java @@ -0,0 +1,78 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.onap.pnfsimulator.event.EventData; +import org.onap.pnfsimulator.event.EventDataRepository; + +public class IncrementProviderImplTest { + private IncrementProvider incrementProvider; + + @Mock + private EventDataRepository eventDataRepositoryMock; + + @BeforeEach + void setUp() { + eventDataRepositoryMock = mock(EventDataRepository.class); + incrementProvider = new IncrementProviderImpl(eventDataRepositoryMock); + } + + @Test + public void getAndIncrementTest() { + ArgumentCaptor<EventData> eventDataArgumentCaptor = ArgumentCaptor.forClass(EventData.class); + String eventId = "1"; + int initialIncrementValue = 0; + int expectedValue = initialIncrementValue + 1; + EventData eventData = EventData.builder().id(eventId).incrementValue(initialIncrementValue).build(); + Optional<EventData> optional = Optional.of(eventData); + + when(eventDataRepositoryMock.findById(eventId)).thenReturn(optional); + + int value = incrementProvider.getAndIncrement(eventId); + + verify(eventDataRepositoryMock).save(eventDataArgumentCaptor.capture()); + + assertThat(value).isEqualTo(expectedValue); + assertThat(eventDataArgumentCaptor.getValue().getIncrementValue()).isEqualTo(expectedValue); + + } + + @Test + public void shouldThrowOnNonExistingEvent() { + Optional<EventData> emptyOptional = Optional.empty(); + String nonExistingEventId = "THIS_DOES_NOT_EXIST"; + when(eventDataRepositoryMock.findById(nonExistingEventId)).thenReturn(emptyOptional); + + assertThrows(EventNotFoundException.class, + () -> incrementProvider.getAndIncrement(nonExistingEventId)); + } +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomIntegerTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomIntegerTest.java new file mode 100644 index 0000000..8198e95 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomIntegerTest.java @@ -0,0 +1,67 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.Collection; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class KeywordsExtractorInvalidRandomIntegerTest { + + private final String keyword; + private KeywordsExtractor keywordsExtractor; + + private static final Collection INVALID_INTEGER_KEYWORDS = Arrays.asList(new Object[][]{ + {"#RandoInteger"}, + {"#Randominteger(23,11)"}, + {"#randomInteger(11,34)"}, + {"#Random_Integer(11,13)"}, + {"#RandomInteger(11)"}, + {"RandomInteger(11)"}, + {"RandomInteger"} + }); + + public KeywordsExtractorInvalidRandomIntegerTest(String keyword) { + this.keyword = keyword; + } + + @Before + public void setUp() { + this.keywordsExtractor = new KeywordsExtractor(); + } + + @Parameterized.Parameters + public static Collection data() { + return INVALID_INTEGER_KEYWORDS; + } + + @Test + public void checkValidRandomStringKeyword() { + assertEquals(keywordsExtractor.substituteStringKeyword(this.keyword, 1), this.keyword); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomStringTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomStringTest.java new file mode 100644 index 0000000..6834c0d --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomStringTest.java @@ -0,0 +1,67 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.Collection; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class KeywordsExtractorInvalidRandomStringTest { + + private final String keyword; + private KeywordsExtractor keywordsExtractor; + + private static final Collection INVALID_STRING_KEYWORDS = Arrays.asList(new Object[][]{ + {"#RandoString"}, + {"#Randomstring(23)"}, + {"#randomString(11)"}, + {"#Random_String(11)"}, + {"#RandomString(11,10)"}, + {"RandomString(11)"}, + {"RandomString"} + }); + + public KeywordsExtractorInvalidRandomStringTest(String keyword) { + this.keyword = keyword; + } + + @Before + public void setUp() { + this.keywordsExtractor = new KeywordsExtractor(); + } + + @Parameterized.Parameters + public static Collection data() { + return INVALID_STRING_KEYWORDS; + } + + @Test + public void checkValidRandomStringKeyword() { + assertEquals(keywordsExtractor.substituteStringKeyword(this.keyword, 1).length(), this.keyword.length()); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidTimestampTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidTimestampTest.java new file mode 100644 index 0000000..eda4070 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidTimestampTest.java @@ -0,0 +1,65 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.Collection; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class KeywordsExtractorInvalidTimestampTest { + + private final String keyword; + private KeywordsExtractor keywordsExtractor; + + private static final Collection INVALID_TIMESTAMP_KEYWORDS = Arrays.asList(new Object[][]{ + {"#Timesamp"}, + {"#Timestamp(10)"}, + {"#timestamp"}, + {"#Timestamp(11,13)"}, + {"Timestamp"} + }); + + public KeywordsExtractorInvalidTimestampTest(String keyword) { + this.keyword = keyword; + } + + @Before + public void setUp() { + this.keywordsExtractor = new KeywordsExtractor(); + } + + @Parameterized.Parameters + public static Collection data() { + return INVALID_TIMESTAMP_KEYWORDS; + } + + @Test + public void checkValidRandomStringKeyword() { + assertEquals(keywordsExtractor.substituteStringKeyword(this.keyword, 1), this.keyword); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomIntegerTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomIntegerTest.java new file mode 100644 index 0000000..be79488 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomIntegerTest.java @@ -0,0 +1,66 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.Collection; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class KeywordsExtractorValidRandomIntegerTest { + + private final String keyword; + private final String shouldParseTo; + private KeywordsExtractor keywordsExtractor; + + private static final Collection VALID_INTEGER_KEYWORDS = Arrays.asList(new Object[][]{ + {"#RandomInteger(23,23)", "23"}, + {"#RandomInteger(6, 6)12", "612"}, + {"1#RandomInteger(11,11)", "111"}, + {"1#RandomInteger(11,11)2", "1112"} + }); + + public KeywordsExtractorValidRandomIntegerTest(String keyword, String shouldParseTo) { + this.keyword = keyword; + this.shouldParseTo = shouldParseTo; + } + + @Before + public void setUp() { + this.keywordsExtractor = new KeywordsExtractor(); + } + + @Parameterized.Parameters + public static Collection data() { + return VALID_INTEGER_KEYWORDS; + } + + @Test + public void checkValidRandomStringKeyword() { + assertEquals(keywordsExtractor.substituteStringKeyword(this.keyword, 1), this.shouldParseTo); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomPrimitiveIntegerTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomPrimitiveIntegerTest.java new file mode 100644 index 0000000..0843ad1 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomPrimitiveIntegerTest.java @@ -0,0 +1,66 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.Collection; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class KeywordsExtractorValidRandomPrimitiveIntegerTest { + + private final String keyword; + private final Integer shouldParseTo; + private KeywordsExtractor keywordsExtractor; + + private static final Collection VALID_INTEGER_KEYWORDS = Arrays.asList(new Object[][]{ + {"#RandomPrimitiveInteger(23,23)", 23}, + {"#RandomPrimitiveInteger(6, 6)12", 6}, + {"1#RandomPrimitiveInteger(11,11)", 11}, + {"1#RandomPrimitiveInteger(11,11)2", 11} + }); + + public KeywordsExtractorValidRandomPrimitiveIntegerTest(String keyword, Integer shouldParseTo) { + this.keyword = keyword; + this.shouldParseTo = shouldParseTo; + } + + @Before + public void setUp() { + this.keywordsExtractor = new KeywordsExtractor(); + } + + @Parameterized.Parameters + public static Collection data() { + return VALID_INTEGER_KEYWORDS; + } + + @Test + public void checkValidRandomStringKeyword() { + assertEquals(keywordsExtractor.substitutePrimitiveKeyword(this.keyword), Long.valueOf(this.shouldParseTo)); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomStringTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomStringTest.java new file mode 100644 index 0000000..f0fdc0f --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomStringTest.java @@ -0,0 +1,69 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.DEFAULT_STRING_LENGTH; + +import java.util.Arrays; +import java.util.Collection; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class KeywordsExtractorValidRandomStringTest { + + private final String keyword; + private final int length; + private KeywordsExtractor keywordsExtractor; + + private static final Collection VALID_STRING_KEYWORDS = Arrays.asList(new Object[][]{ + {"#RandomString", DEFAULT_STRING_LENGTH}, + {"1#RandomString2", 1 + DEFAULT_STRING_LENGTH + 1}, + {"#RandomString(23)", 23}, + {"#RandomString(11)12", 11 + 2}, + {"1#RandomString(11)", 1 + 11}, + {"1#RandomString(11)2", 1 + 11 + 1} + }); + + public KeywordsExtractorValidRandomStringTest(String keyword, int length) { + this.keyword = keyword; + this.length = length; + } + + @Before + public void setUp() { + this.keywordsExtractor = new KeywordsExtractor(); + } + + @Parameterized.Parameters + public static Collection data() { + return VALID_STRING_KEYWORDS; + } + + @Test + public void checkValidRandomStringKeyword() { + assertEquals(keywordsExtractor.substituteStringKeyword(this.keyword, 1).length(), this.length); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampPrimitiveTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampPrimitiveTest.java new file mode 100644 index 0000000..7743e55 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampPrimitiveTest.java @@ -0,0 +1,66 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.simulator; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.time.Instant; +import java.util.Arrays; +import java.util.Collection; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(Parameterized.class) +public class KeywordsExtractorValidTimestampPrimitiveTest { + private final String keyword; + private KeywordsExtractor keywordsExtractor; + + private static final Collection VALID_TIMESTAMP_KEYWORDS = Arrays.asList(new Object[][]{ + {"#TimestampPrimitive"} + }); + + public KeywordsExtractorValidTimestampPrimitiveTest(String keyword) { + this.keyword = keyword; + } + + @Before + public void setUp() { + this.keywordsExtractor = new KeywordsExtractor(); + } + + @Parameterized.Parameters + public static Collection data() { + return VALID_TIMESTAMP_KEYWORDS; + } + + @Test + public void checkValidRandomStringKeyword() { + long currentTimestamp = Instant.now().getEpochSecond(); + Long timestamp = keywordsExtractor.substitutePrimitiveKeyword(this.keyword); + long afterExecution = Instant.now().getEpochSecond(); + + assertThat(timestamp).isBetween(currentTimestamp, afterExecution); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampTest.java new file mode 100644 index 0000000..f5c12c3 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampTest.java @@ -0,0 +1,67 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.Collection; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class KeywordsExtractorValidTimestampTest { + + private final String keyword; + private final int length; + private KeywordsExtractor keywordsExtractor; + + private static final Collection VALID_TIMESTAMP_KEYWORDS = Arrays.asList(new Object[][]{ + {"#Timestamp", 10}, + {"#Timestamp12", 10 + 2}, + {"1#Timestamp", 1 + 10}, + {"1#Timestamp2", 1 + 10 +1} + }); + + public KeywordsExtractorValidTimestampTest(String keyword, Integer length) { + this.keyword = keyword; + this.length = length; + } + + @Before + public void setUp() { + this.keywordsExtractor = new KeywordsExtractor(); + } + + @Parameterized.Parameters + public static Collection data() { + return VALID_TIMESTAMP_KEYWORDS; + } + + @Test + public void checkValidRandomStringKeyword() { + String substitution = keywordsExtractor.substituteStringKeyword(this.keyword, 1); + assertEquals(substitution.length(), this.length); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsHandlerTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsHandlerTest.java new file mode 100644 index 0000000..e67d4a3 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsHandlerTest.java @@ -0,0 +1,304 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.DEFAULT_STRING_LENGTH; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.Queue; +import org.junit.jupiter.api.Test; + +class KeywordsHandlerTest { + + private static final String TEMPLATE_JSON = "{\n" + + " \"event\": {\n" + + " \"commonEventHeader\": {\n" + + " \"domain\": \"#RandomString\"\n" + + " },\n" + + " \"measurementsForVfScalingFields\": {\n" + + " \"measurementsForVfSclaingFieldsVersion\": 2.0,\n" + + " \"additionalMeasurements\": {\n" + + " \"name\": \"licenseUsage\",\n" + + " \"extraFields\": {\n" + + " \"name\": \"#RandomString(4)\",\n" + + " \"value\": \"1\"\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + private static final String TEMPLATE_JSON_WITH_MANY_KEYWORDS_INSIDE_SINGLE_VALUE = "{\n" + + " \"event\": {\n" + + " \"commonEventHeader\": {\n" + + " \"domain1\": \"#RandomString(1) #RandomString(2) #RandomString(3)\",\n" + + " \"domain2\": \"1 #RandomString(1) 2\"\n" + + " },\n" + + " \"measurementsForVfScalingFields\": {\n" + + " \"measurementsForVfSclaingFieldsVersion\": 2.0,\n" + + " \"additionalMeasurements\": {\n" + + " \"name\": \"licenseUsage\",\n" + + " \"extraFields\": {\n" + + " \"value\": \"1\"\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + private static final String TEMPLATE_JSON_WITH_ARRAY = "{\n" + + " \"event\": {\n" + + " \"commonEventHeader\": {\n" + + " \"domain\": \"#RandomString(1)\",\n" + + " \"version\": 2.0\n" + + " },\n" + + " \"measurementsForVfScalingFields\": {\n" + + " \"additionalMeasurements\": [\n" + + " {\n" + + " \"name\": \"licenseUsage\",\n" + + " \"arrayOfFields\": [\n" + + " {\n" + + " \"name\": \"G711AudioPort\",\n" + + " \"value\": \"1\"\n" + + " },\n" + + " {\n" + + " \"name\": [\"1\",\"2\"],\n" + + " \"value\": \"#RandomString(2)\"\n" + + " },\n" + + " {\n" + + " \"name\": \"G722AudioPort\",\n" + + " \"value\": \"1\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + " }\n" + + " }\n" + + "}"; + + private static final String TEMPLATE_ONE_INCREMENT_JSON = "{\n" + + " \"event\": {\n" + + " \"commonEventHeader\": {\n" + + " \"domain\": \"#RandomString\"\n" + + " },\n" + + " \"measurementsForVfScalingFields\": {\n" + + " \"measurementsForVfSclaingFieldsVersion\": 2.0,\n" + + " \"additionalMeasurements\": {\n" + + " \"name\": \"licenseUsage\",\n" + + " \"extraFields\": {\n" + + " \"name\": \"#RandomString(4)\",\n" + + " \"value\": \"#Increment\"\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + private static final String TEMPLATE_WITH_SIMPLE_VALUE= "\"#RandomString(4)\""; + + private static final String TEMPLATE_WITH_ARRAY_OF_PRIMITIVES = "[ 1, \"#RandomString(5)\", 3]"; + + private static final String TEMPLATE_TWO_INCREMENT_JSON = "{\n" + + " \"event\": {\n" + + " \"commonEventHeader\": {\n" + + " \"domain\": \"#RandomString\"\n" + + " },\n" + + " \"measurementsForVfScalingFields\": {\n" + + " \"measurementsForVfSclaingFieldsVersion\": 2.0,\n" + + " \"additionalMeasurements\": {\n" + + " \"name\": \"licenseUsage\",\n" + + " \"extraFields\": {\n" + + " \"name\": \"#RandomString(4)\",\n" + + " \"value\": \"#Increment\",\n" + + " \"otherValue\": \"#Increment\"\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + private Gson gson = new Gson(); + + @Test + void shouldReplaceRandomStringKeyword() { + // given + JsonObject templateJson = gson.fromJson(TEMPLATE_JSON, JsonObject.class); + KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), (id) -> 1); + + // when + JsonObject resultJson = keywordsHandler.substituteKeywords(templateJson, "").getAsJsonObject(); + + // then + String extraFields = resultJson + .get("event").getAsJsonObject() + .get("measurementsForVfScalingFields").getAsJsonObject() + .get("additionalMeasurements").getAsJsonObject() + .get("extraFields").getAsJsonObject() + .get("name").getAsString(); + String newDomain = resultJson + .get("event").getAsJsonObject() + .get("commonEventHeader").getAsJsonObject() + .get("domain").getAsString(); + + assertThat(extraFields.length()).isEqualTo(4); + assertThat(newDomain.length()).isEqualTo(DEFAULT_STRING_LENGTH); + } + + @Test + void shouldReplaceRandomStringKeywordsInsideSingleValue() { + // given + JsonObject templateJson = gson.fromJson(TEMPLATE_JSON_WITH_MANY_KEYWORDS_INSIDE_SINGLE_VALUE, JsonObject.class); + KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), (id) -> 1); + + // when + JsonObject resultJson = keywordsHandler.substituteKeywords(templateJson, "").getAsJsonObject(); + + // then + String newDomain1 = resultJson + .get("event").getAsJsonObject() + .get("commonEventHeader").getAsJsonObject() + .get("domain1").getAsString(); + String newDomain2 = resultJson + .get("event").getAsJsonObject() + .get("commonEventHeader").getAsJsonObject() + .get("domain2").getAsString(); + + assertThat(newDomain1.length()).isEqualTo(1+1+2+1+3); + assertThat(newDomain2.length()).isEqualTo(1+1+1+1+1); + } + + @Test + void shouldReplaceRandomStringKeywordInTeplateAsArrayWithPrimitves() { + // given + JsonElement templateJson = gson.fromJson(TEMPLATE_WITH_ARRAY_OF_PRIMITIVES, JsonElement.class); + KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), (id) -> 1); + + // when + JsonElement resultJson = keywordsHandler.substituteKeywords(templateJson, ""); + assertThat(resultJson.getAsJsonArray().get(1).getAsString().length()).isEqualTo(5); + } + + @Test + void shouldReplaceRandomStringKeywordInTeplateAsSimpleValue() { + // given + JsonElement templateJson = gson.fromJson(TEMPLATE_WITH_SIMPLE_VALUE, JsonElement.class); + KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), (id) -> 1); + + // when + JsonElement resultJson = keywordsHandler.substituteKeywords(templateJson, ""); + + // then + assertThat(resultJson.getAsString().length()).isEqualTo(4); + } + + @Test + void shouldReplaceRandomStringKeywordInTeplateWithJsonArray() { + // given + JsonElement templateJson = gson.fromJson(TEMPLATE_JSON_WITH_ARRAY, JsonElement.class); + KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), (id) -> 1); + + // when + JsonObject resultJson = keywordsHandler.substituteKeywords(templateJson, "").getAsJsonObject(); + + // then + String actualValue = resultJson + .get("event").getAsJsonObject() + .get("measurementsForVfScalingFields").getAsJsonObject() + .get("additionalMeasurements").getAsJsonArray() + .get(0).getAsJsonObject() + .get("arrayOfFields").getAsJsonArray() + .get(1).getAsJsonObject() + .get("value").getAsString(); + String otherActualValue = resultJson + .get("event").getAsJsonObject() + .get("commonEventHeader").getAsJsonObject() + .get("domain").getAsString(); + + assertThat(otherActualValue.length()).isEqualTo(1); + assertThat(actualValue.length()).isEqualTo(2); + } + + @Test + void shouldReplaceOneIncrementKeyword() { + // given + final Integer newIncrementedValue = 2; + JsonObject templateJson = gson.fromJson(TEMPLATE_ONE_INCREMENT_JSON, JsonObject.class); + KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), (id) -> newIncrementedValue); + + // when + JsonObject resultJson = keywordsHandler.substituteKeywords(templateJson, "some random id").getAsJsonObject(); + + // then + String actualValue = resultJson + .get("event").getAsJsonObject() + .get("measurementsForVfScalingFields").getAsJsonObject() + .get("additionalMeasurements").getAsJsonObject() + .get("extraFields").getAsJsonObject() + .get("value").getAsString(); + + assertThat(actualValue).isEqualTo(newIncrementedValue.toString()); + } + + @Test + void shouldReplaceTwoIncrementKeyword() { + // given + final Integer firstIncrementValue = 2; + final Integer secondIncrementValue = 3; + JsonObject templateJson = gson.fromJson(TEMPLATE_TWO_INCREMENT_JSON, JsonObject.class); + KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), new IncrementProvider() { + Queue<Integer> sequenceOfValues = new LinkedList<>( + Arrays.asList(firstIncrementValue, secondIncrementValue)); + + @Override + public int getAndIncrement(String id) { + return sequenceOfValues.poll(); + } + }); + + // when + JsonObject resultJson = keywordsHandler.substituteKeywords(templateJson, "some random id").getAsJsonObject(); + resultJson = keywordsHandler.substituteKeywords(templateJson, "some random id").getAsJsonObject(); + + // then + String actualValue = resultJson + .get("event").getAsJsonObject() + .get("measurementsForVfScalingFields").getAsJsonObject() + .get("additionalMeasurements").getAsJsonObject() + .get("extraFields").getAsJsonObject() + .get("value").getAsString(); + + String actualOtherValue = resultJson + .get("event").getAsJsonObject() + .get("measurementsForVfScalingFields").getAsJsonObject() + .get("additionalMeasurements").getAsJsonObject() + .get("extraFields").getAsJsonObject() + .get("otherValue").getAsString(); + + assertThat(actualValue).isEqualTo(secondIncrementValue.toString()); + assertThat(actualOtherValue).isEqualTo(secondIncrementValue.toString()); + + } +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsValueProviderTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsValueProviderTest.java new file mode 100644 index 0000000..73e4c31 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/KeywordsValueProviderTest.java @@ -0,0 +1,81 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.DEFAULT_STRING_LENGTH; + +import java.util.Random; +import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; + +class KeywordsValueProviderTest { + + @RepeatedTest(10) + void randomLimitedStringTest() { + String supplierResult = KeywordsValueProvider.getRandomLimitedString().apply(); + assertEquals(supplierResult.length(), DEFAULT_STRING_LENGTH); + } + + @RepeatedTest(10) + void randomStringTest() { + int length = new Random().nextInt(15) + 1; + String supplierResult = KeywordsValueProvider.getRandomString().apply(length); + assertEquals(supplierResult.length(), length); + } + + @RepeatedTest(10) + void randomIntegerTest(){ + int min = new Random().nextInt(10) + 1; + int max = new Random().nextInt(1000) + 20; + String supplierResult = KeywordsValueProvider.getRandomInteger().apply(min, max); + assertTrue(Integer.parseInt(supplierResult)>=min); + assertTrue(Integer.parseInt(supplierResult)<=max); + } + + @Test + void randomIntegerContainsMaximalAndMinimalValuesTest(){ + int anyNumber = new Random().nextInt(10) + 1; + String supplierResult = KeywordsValueProvider.getRandomInteger().apply(anyNumber, anyNumber); + assertEquals(Integer.parseInt(supplierResult), anyNumber); + } + + @Test + void randomIntegerFromNegativeRangeTest(){ + String supplierResult = KeywordsValueProvider.getRandomInteger().apply(-20, -20); + assertEquals(Integer.parseInt(supplierResult), -20); + } + + @RepeatedTest(10) + void randomIntegerFromParametersWithDifferentOrdersTest(){ + String supplierResult = KeywordsValueProvider.getRandomInteger().apply(-20, -10); + assertTrue(Integer.parseInt(supplierResult)>=-20); + assertTrue(Integer.parseInt(supplierResult)<=-10); + } + + @RepeatedTest(10) + void epochSecondGeneratedInCorrectFormatTest(){ + String supplierResult = KeywordsValueProvider.getEpochSecond().apply(); + assertEquals(supplierResult.length(), 10); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/SimulatorServiceTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/SimulatorServiceTest.java new file mode 100644 index 0000000..0196eb0 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/SimulatorServiceTest.java @@ -0,0 +1,227 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.onap.pnfsimulator.event.EventData; +import org.onap.pnfsimulator.event.EventDataService; +import org.onap.pnfsimulator.rest.model.FullEvent; +import org.onap.pnfsimulator.rest.model.SimulatorParams; +import org.onap.pnfsimulator.rest.model.SimulatorRequest; +import org.onap.pnfsimulator.simulator.client.HttpClientAdapter; +import org.onap.pnfsimulator.simulator.client.utils.ssl.SSLAuthenticationHelper; +import org.onap.pnfsimulator.simulator.scheduler.EventScheduler; +import org.onap.pnfsimulator.simulatorconfig.SimulatorConfig; +import org.onap.pnfsimulator.simulatorconfig.SimulatorConfigService; +import org.quartz.SchedulerException; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.GeneralSecurityException; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.internal.verification.VerificationModeFactory.times; + +class SimulatorServiceTest { + + private static final String VES_URL = "http://0.0.0.0:8080"; + private static final Gson GSON = new Gson(); + private static final JsonObject VALID_PATCH = GSON.fromJson("{\"event\": {\n" + + " \"commonEventHeader\": {\n" + + " \"sourceName\": \"SomeCustomSource\"}}}\n", JsonObject.class); + private static JsonObject VALID_FULL_EVENT = GSON.fromJson("{\"event\": {\n" + + " \"commonEventHeader\": {\n" + + " \"domain\": \"notification\",\n" + + " \"eventName\": \"vFirewallBroadcastPackets\"\n" + + " },\n" + + " \"notificationFields\": {\n" + + " \"arrayOfNamedHashMap\": [{\n" + + " \"name\": \"A20161221.1031-1041.bin.gz\",\n" + + " \"hashMap\": {\n" + + " \"fileformatType\": \"org.3GPP.32.435#measCollec\"}}]}}}", JsonObject.class); + private static JsonObject FULL_EVENT_WITH_KEYWORDS = GSON.fromJson("{\"event\":{ \n" + + " \"commonEventHeader\":{ \n" + + " \"domain\":\"notification\",\n" + + " \"eventName\":\"#RandomString(20)\",\n" + + " \"eventOrderNo\":\"#Increment\"}}}", JsonObject.class); + private static final String SOME_CUSTOM_SOURCE = "SomeCustomSource"; + private static final String CLOSED_LOOP_VNF ="ClosedLoopVNF"; + private static final String SAMPLE_ID = "sampleId"; + private static final EventData SAMPLE_EVENT = EventData.builder().id("1").build(); + private final ArgumentCaptor<JsonObject> bodyCaptor = ArgumentCaptor.forClass(JsonObject.class); + private final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); + private final ArgumentCaptor<Integer> repeatCountCaptor = ArgumentCaptor + .forClass(Integer.class); + private final ArgumentCaptor<String> templateNameCaptor = ArgumentCaptor.forClass(String.class); + private final ArgumentCaptor<String> eventIdCaptor = ArgumentCaptor.forClass(String.class); + private final ArgumentCaptor<String> vesUrlCaptor = ArgumentCaptor.forClass(String.class); + private final ArgumentCaptor<String> eventContentCaptor = ArgumentCaptor.forClass(String.class); + private SimulatorService simulatorService; + private EventDataService eventDataService; + private EventScheduler eventScheduler; + private SimulatorConfigService simulatorConfigService; + private static TemplatePatcher templatePatcher = new TemplatePatcher(); + private static TemplateReader templateReader = new FilesystemTemplateReader( + "src/test/resources/org/onap/pnfsimulator/simulator/", GSON); + + @BeforeEach + void setUp() { + eventDataService = mock(EventDataService.class); + eventScheduler = mock(EventScheduler.class); + simulatorConfigService = mock(SimulatorConfigService.class); + + simulatorService = new SimulatorService(templatePatcher, templateReader, + eventScheduler, eventDataService, simulatorConfigService, new SSLAuthenticationHelper()); + } + + @Test + void shouldTriggerEventWithGivenParams() throws IOException, SchedulerException, GeneralSecurityException { + String templateName = "validExampleMeasurementEvent.json"; + SimulatorParams simulatorParams = new SimulatorParams(VES_URL, 1, 1); + SimulatorRequest simulatorRequest = new SimulatorRequest(simulatorParams, + templateName, VALID_PATCH); + + doReturn(SAMPLE_EVENT).when(eventDataService).persistEventData(any(JsonObject.class), any(JsonObject.class), any(JsonObject.class), any(JsonObject.class)); + + simulatorService.triggerEvent(simulatorRequest); + + assertEventHasExpectedStructure(VES_URL, templateName, SOME_CUSTOM_SOURCE); + } + + @Test + void shouldTriggerEventWithDefaultVesUrlWhenNotProvidedInRequest() throws IOException, SchedulerException, GeneralSecurityException { + String templateName = "validExampleMeasurementEvent.json"; + SimulatorRequest simulatorRequest = new SimulatorRequest( + new SimulatorParams("", 1, 1), + templateName, VALID_PATCH); + + URL inDbVesUrl = new URL("http://0.0.0.0:8080/eventListener/v6"); + doReturn(SAMPLE_EVENT).when(eventDataService).persistEventData(any(JsonObject.class), any(JsonObject.class), any(JsonObject.class), any(JsonObject.class)); + when(simulatorConfigService.getConfiguration()).thenReturn(new SimulatorConfig(SAMPLE_ID, inDbVesUrl)); + + simulatorService.triggerEvent(simulatorRequest); + + assertEventHasExpectedStructure(inDbVesUrl.toString(), templateName, SOME_CUSTOM_SOURCE); + } + + @Test + void shouldThrowJsonSyntaxWhenInvalidJson() { + //given + JsonObject patch = GSON.fromJson("{\n" + + " \"event\": {\n" + + " \"commonEventHeader\": {\n" + + " \"sourceName\": \"" + SOME_CUSTOM_SOURCE + "\"\n" + + " }\n" + + " }\n" + + "}\n", JsonObject.class); + EventData eventData = EventData.builder().id("1").build(); + + SimulatorParams simulatorParams = new SimulatorParams(VES_URL, 1, 1); + SimulatorRequest simulatorRequest = new SimulatorRequest(simulatorParams, + "invalidJsonStructureEvent.json", patch); + doReturn(eventData).when(eventDataService).persistEventData(any(JsonObject.class), any(JsonObject.class), any(JsonObject.class), any(JsonObject.class)); + + //when + assertThrows(JsonSyntaxException.class, + () -> simulatorService.triggerEvent(simulatorRequest)); + } + + @Test + void shouldHandleNonExistingPatchSection() throws IOException, SchedulerException, GeneralSecurityException { + String templateName = "validExampleMeasurementEvent.json"; + SimulatorRequest simulatorRequest = new SimulatorRequest( + new SimulatorParams("", 1, 1), + templateName, null); + + URL inDbVesUrl = new URL("http://0.0.0.0:8080/eventListener/v6"); + doReturn(SAMPLE_EVENT).when(eventDataService).persistEventData(any(JsonObject.class), any(JsonObject.class), any(JsonObject.class), any(JsonObject.class)); + doReturn(new SimulatorConfig(SAMPLE_ID, inDbVesUrl)).when(simulatorConfigService).getConfiguration(); + + simulatorService.triggerEvent(simulatorRequest); + + assertEventHasExpectedStructure(inDbVesUrl.toString(), templateName, CLOSED_LOOP_VNF); + } + + @Test + void shouldSuccessfullySendOneTimeEventWithVesUrlWhenPassed() throws IOException, GeneralSecurityException { + SimulatorService spiedTestedService = spy(new SimulatorService(templatePatcher,templateReader, eventScheduler, eventDataService, simulatorConfigService, new SSLAuthenticationHelper())); + + HttpClientAdapter adapterMock = mock(HttpClientAdapter.class); + doNothing().when(adapterMock).send(eventContentCaptor.capture()); + doReturn(adapterMock).when(spiedTestedService).createHttpClientAdapter(any(String.class)); + FullEvent event = new FullEvent(VES_URL, VALID_FULL_EVENT); + + spiedTestedService.triggerOneTimeEvent(event); + + assertThat(eventContentCaptor.getValue()).isEqualTo(VALID_FULL_EVENT.toString()); + verify(eventDataService, times(1)).persistEventData(any(JsonObject.class), any(JsonObject.class), any(JsonObject.class), any(JsonObject.class)); + verify(adapterMock, times(1)).send(VALID_FULL_EVENT.toString()); + } + + @Test + void shouldSubstituteKeywordsAndSuccessfullySendOneTimeEvent() throws IOException, GeneralSecurityException { + SimulatorService spiedTestedService = spy(new SimulatorService(templatePatcher,templateReader, eventScheduler, eventDataService, simulatorConfigService, new SSLAuthenticationHelper())); + + HttpClientAdapter adapterMock = mock(HttpClientAdapter.class); + doNothing().when(adapterMock).send(eventContentCaptor.capture()); + doReturn(adapterMock).when(spiedTestedService).createHttpClientAdapter(any(String.class)); + FullEvent event = new FullEvent(VES_URL, FULL_EVENT_WITH_KEYWORDS); + + spiedTestedService.triggerOneTimeEvent(event); + + JsonObject sentContent = GSON.fromJson(eventContentCaptor.getValue(), JsonElement.class).getAsJsonObject(); + assertThat(sentContent.getAsJsonObject("event").getAsJsonObject("commonEventHeader").get("eventOrderNo").getAsString()).isEqualTo("1"); + assertThat(sentContent.getAsJsonObject("event").getAsJsonObject("commonEventHeader").get("eventName").getAsString()).hasSize(20); + } + + + private void assertEventHasExpectedStructure(String expectedVesUrl, String templateName, String sourceNameString) throws SchedulerException, IOException, GeneralSecurityException { + verify(eventScheduler, times(1)).scheduleEvent(vesUrlCaptor.capture(), intervalCaptor.capture(), + repeatCountCaptor.capture(), templateNameCaptor.capture(), eventIdCaptor.capture(), bodyCaptor.capture()); + assertThat(vesUrlCaptor.getValue()).isEqualTo(expectedVesUrl); + assertThat(intervalCaptor.getValue()).isEqualTo(1); + assertThat(repeatCountCaptor.getValue()).isEqualTo(1); + assertThat(templateNameCaptor.getValue()).isEqualTo(templateName); + String actualSourceName = GSON.fromJson(bodyCaptor.getValue(), JsonObject.class) + .get("event").getAsJsonObject() + .get("commonEventHeader").getAsJsonObject() + .get("sourceName").getAsString(); + assertThat(actualSourceName).isEqualTo(sourceNameString); + verify(eventDataService) + .persistEventData(any(JsonObject.class), any(JsonObject.class), any(JsonObject.class), + any(JsonObject.class)); + } +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/TemplatePatcherTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/TemplatePatcherTest.java new file mode 100644 index 0000000..52e0d6a --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/TemplatePatcherTest.java @@ -0,0 +1,164 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.assertj.core.api.AssertionsForInterfaceTypes; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class TemplatePatcherTest { + + private static final String TEMPLATE_JSON = "{\n" + + " \"event\": {\n" + + " \"commonEventHeader\": {\n" + + " \"domain\": \"measurementsForVfScaling\"\n" + + " },\n" + + " \"measurementsForVfScalingFields\": {\n" + + " \"measurementsForVfSclaingFieldsVersion\": 2.0,\n" + + " \"additionalMeasurements\": {\n" + + " \"name\": \"licenseUsage\",\n" + + " \"extraFields\": {\n" + + " \"name\": \"G711AudioPort\",\n" + + " \"value\": \"1\"\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + private TemplatePatcher templatePatcher; + private Gson gson = new Gson(); + private JsonObject templateJson; + + @BeforeEach + void setUp() { + templatePatcher = new TemplatePatcher(); + templateJson = gson.fromJson(TEMPLATE_JSON, JsonObject.class); + } + + @Test + void shouldReplaceJsonElementsInTemplate() { + //given + String patchJsonString = "{\n" + + " \"event\": {\n" + + " \"commonEventHeader\": {\n" + + " \"domain\": \"newDomain\"\n" + + " }\n" + + " }\n" + + "}"; + JsonObject patchJson = gson.fromJson(patchJsonString, JsonObject.class); + + //when + JsonObject requestJson = templatePatcher.mergeTemplateWithPatch(templateJson, patchJson); + + //then + String newDomain = requestJson + .get("event").getAsJsonObject() + .get("commonEventHeader").getAsJsonObject() + .get("domain").getAsString(); + assertThat(newDomain).isEqualTo("newDomain"); + } + + @Test + void shouldAddWholeJsonObjectToTemplateWhenItFinished() { + //given + String patchJsonString = + "{\n" + + " \"event\": {\n" + + " \"commonEventHeader\": {\n" + + " \"domain\": {\n" + + " \"extraFields\": {\n" + + " \"name\": \"G711AudioPort\",\n" + + " \"value\": \"1\"\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + JsonObject patchJson = gson.fromJson(patchJsonString, JsonObject.class); + + //when + JsonObject requestJson = templatePatcher.mergeTemplateWithPatch(templateJson, patchJson); + + //then + JsonElement newDomain = requestJson + .get("event").getAsJsonObject() + .get("commonEventHeader").getAsJsonObject() + .get("domain"); + assertThat(newDomain.isJsonObject()).isTrue(); + JsonObject newDomainJO = newDomain.getAsJsonObject(); + AssertionsForInterfaceTypes.assertThat(newDomainJO.keySet()).containsExactly("extraFields"); + JsonObject newDomainExtraFields = newDomainJO.get("extraFields").getAsJsonObject(); + AssertionsForInterfaceTypes.assertThat(newDomainExtraFields.keySet()).containsExactly("name", "value"); + } + + @Test + void shouldReplaceJsonObjectWithJsonElementFromPatch() { + //given + String patchJsonString = "{ \"event\": \"test\" }"; + JsonObject patchJson = gson.fromJson(patchJsonString, JsonObject.class); + + //when + JsonObject requestJson = templatePatcher.mergeTemplateWithPatch(templateJson, patchJson); + + //then + assertThat(requestJson.get("event").isJsonObject()).isFalse(); + assertThat(requestJson.get("event").getAsString()).isEqualTo("test"); + } + + @Test + void shouldAddNewKeyIfPatchHasItAndTempleteDoesnt() { + //given + String patchJsonString = "{ \"newTestKey\": { \"newTestKeyChild\":\"newTestValue\" }}"; + JsonObject patchJson = gson.fromJson(patchJsonString, JsonObject.class); + + //when + JsonObject requestJson = templatePatcher.mergeTemplateWithPatch(templateJson, patchJson); + + //then + assertThat(requestJson.get("event").isJsonObject()).isTrue(); + assertThat(requestJson.get("newTestKey").isJsonObject()).isTrue(); + JsonObject newTestKey = requestJson.get("newTestKey").getAsJsonObject(); + AssertionsForInterfaceTypes.assertThat(newTestKey.keySet()).containsExactly("newTestKeyChild"); + assertThat(newTestKey.get("newTestKeyChild").getAsString()).isEqualTo("newTestValue"); + + } + + + @Test + void shouldNotChangeInputTemplateParam() { + //given + String patchJsonString = "{ \"newTestKey\": { \"newTestKeyChild\":\"newTestValue\" }}"; + JsonObject patchJson = gson.fromJson(patchJsonString, JsonObject.class); + + //when + templatePatcher.mergeTemplateWithPatch(templateJson, patchJson); + + //then + assertThat(templateJson).isEqualTo(gson.fromJson(TEMPLATE_JSON, JsonObject.class)); + + } +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/TemplateReaderTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/TemplateReaderTest.java new file mode 100644 index 0000000..f029fce --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/TemplateReaderTest.java @@ -0,0 +1,51 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.test.context.TestPropertySource; + +import java.io.IOException; + +import static org.assertj.core.api.Java6Assertions.assertThat; + +@TestPropertySource +class TemplateReaderTest { + + private FilesystemTemplateReader templateReader = new FilesystemTemplateReader("src/test/resources/org/onap/pnfsimulator/simulator/", new Gson()); + + @Test + void testShouldReadJsonFromFile() throws IOException { + JsonObject readJson = templateReader.readTemplate("validExampleMeasurementEvent.json"); + assertThat(readJson.keySet()).containsOnly("event"); + assertThat(readJson.get("event").getAsJsonObject().keySet()).containsExactlyInAnyOrder("commonEventHeader", "measurementsForVfScalingFields"); + } + + @Test + void testShouldRaiseExceptionWhenInvalidJsonIsRead() { + Assertions.assertThrows(JsonSyntaxException.class, () -> templateReader.readTemplate("invalidJsonStructureEvent.json")); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImplTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImplTest.java new file mode 100644 index 0000000..63c1b72 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImplTest.java @@ -0,0 +1,99 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator.client; + +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.pnfsimulator.simulator.client.utils.ssl.SSLAuthenticationHelper; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.security.GeneralSecurityException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +class HttpClientAdapterImplTest { + + private static final String HTTPS_URL = "https://0.0.0.0:8443/"; + private static final String HTTP_URL = "http://0.0.0.0:8000/"; + + private HttpClient httpClient; + private HttpResponse httpResponse; + + @BeforeEach + void setup() { + httpClient = mock(HttpClient.class); + httpResponse = mock(HttpResponse.class); + } + + @Test + void sendShouldSuccessfullySendRequestGivenValidUrl() throws IOException { + assertAdapterSentRequest("http://valid-url:8080"); + } + + @Test + void sendShouldSuccessfullySendRequestGivenValidUrlUsingHTTPS() throws IOException { + assertAdapterSentRequest("https://valid-url:8443"); + } + + @Test + void shouldThrowExceptionWhenMalformedVesUrlPassed(){ + assertThrows(MalformedURLException.class, () -> new HttpClientAdapterImpl("http://blablabla:VES-PORT", new SSLAuthenticationHelper())); + } + @Test + void shouldCreateAdapterWithClientNotSupportingSSLConnection() throws IOException, GeneralSecurityException { + HttpClientAdapter adapterWithHttps = new HttpClientAdapterImpl(HTTPS_URL, new SSLAuthenticationHelper()); + try { + adapterWithHttps.send("sample"); + } catch (Exception actualException) { + assertThat(actualException).hasStackTraceContaining(SSLConnectionSocketFactory.class.toString()); + } + } + + @Test + void shouldCreateAdapterWithClientSupportingPlainConnectionOnly() throws IOException, GeneralSecurityException { + HttpClientAdapter adapterWithHttps = new HttpClientAdapterImpl(HTTP_URL, new SSLAuthenticationHelper()); + try { + adapterWithHttps.send("sample"); + } catch (Exception actualException) { + assertThat(actualException).hasStackTraceContaining(PlainConnectionSocketFactory.class.toString()); + } + } + + private void assertAdapterSentRequest(String targetUrl) throws IOException { + HttpClientAdapter adapter = new HttpClientAdapterImpl(httpClient, targetUrl); + doReturn(httpResponse).when(httpClient).execute(any()); + + adapter.send("test-msg"); + + verify(httpClient).execute(any()); + verify(httpResponse).getStatusLine(); + } +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslSupportLevelTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslSupportLevelTest.java new file mode 100644 index 0000000..ff41c44 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslSupportLevelTest.java @@ -0,0 +1,52 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator.client.utils.ssl; + +import org.junit.jupiter.api.Test; + +import java.net.MalformedURLException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class SslSupportLevelTest { + + private static final String HTTPS_URL = "https://127.0.0.1:8443/"; + private static final String HTTP_URL = "http://127.0.0.1:8080/"; + + @Test + void testShouldReturnAlwaysTrustSupportLevelForHttpsUrl() throws MalformedURLException { + SslSupportLevel actualSupportLevel = SslSupportLevel.getSupportLevelBasedOnProtocol(HTTPS_URL); + assertEquals(actualSupportLevel, SslSupportLevel.ALWAYS_TRUST); + } + + @Test + void testShouldReturnNoneSupportLevelForHttpUrl() throws MalformedURLException { + SslSupportLevel actualSupportLevel = SslSupportLevel.getSupportLevelBasedOnProtocol(HTTP_URL); + assertEquals(actualSupportLevel, SslSupportLevel.NONE); + } + + @Test + void testShouldRaiseExceptionWhenInvalidUrlPassed(){ + assertThrows(MalformedURLException.class, () -> SslSupportLevel.getSupportLevelBasedOnProtocol("http://bla:VES-PORT/")); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventJobTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventJobTest.java new file mode 100644 index 0000000..25ed84c --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventJobTest.java @@ -0,0 +1,90 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator.scheduler; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.BODY; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.CLIENT_ADAPTER; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.EVENT_ID; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.KEYWORDS_HANDLER; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.TEMPLATE_NAME; +import static org.onap.pnfsimulator.simulator.scheduler.EventJob.VES_URL; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.onap.pnfsimulator.simulator.KeywordsExtractor; +import org.onap.pnfsimulator.simulator.KeywordsHandler; +import org.onap.pnfsimulator.simulator.client.HttpClientAdapter; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.JobExecutionContext; +import org.quartz.JobKey; + +class EventJobTest { + + @Test + void shouldSendEventWhenExecuteCalled() { + //given + EventJob eventJob = new EventJob(); + String templateName = "template name"; + String vesUrl = "http://someurl:80/"; + String eventId = "1"; + JsonParser parser = new JsonParser(); + JsonObject body = parser.parse("{\"a\": \"A\"}").getAsJsonObject(); + HttpClientAdapter clientAdapter = mock(HttpClientAdapter.class); + JobExecutionContext jobExecutionContext = + createMockJobExecutionContext(templateName, eventId, vesUrl, body, clientAdapter); + + ArgumentCaptor<String> vesUrlCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor<String> bodyCaptor = ArgumentCaptor.forClass(String.class); + + //when + eventJob.execute(jobExecutionContext); + + //then + verify(clientAdapter).send(bodyCaptor.capture()); + assertThat(bodyCaptor.getValue()).isEqualTo(body.toString()); + } + + private JobExecutionContext createMockJobExecutionContext(String templateName, String eventId, String vesURL, + JsonObject body, HttpClientAdapter clientAdapter) { + + JobDataMap jobDataMap = new JobDataMap(); + jobDataMap.put(TEMPLATE_NAME, templateName); + jobDataMap.put(KEYWORDS_HANDLER, new KeywordsHandler(new KeywordsExtractor(), (id) -> 1)); + jobDataMap.put(EVENT_ID, eventId); + jobDataMap.put(VES_URL, vesURL); + jobDataMap.put(BODY, body); + jobDataMap.put(CLIENT_ADAPTER, clientAdapter); + + JobExecutionContext jobExecutionContext = mock(JobExecutionContext.class); + JobDetail jobDetail = mock(JobDetail.class); + when(jobExecutionContext.getJobDetail()).thenReturn(jobDetail); + when(jobDetail.getJobDataMap()).thenReturn(jobDataMap); + when(jobDetail.getKey()).thenReturn(new JobKey("jobId", "group")); + return jobExecutionContext; + } +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventSchedulerTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventSchedulerTest.java new file mode 100644 index 0000000..84df5e9 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventSchedulerTest.java @@ -0,0 +1,149 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulator.scheduler; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.gson.JsonObject; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.security.GeneralSecurityException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.pnfsimulator.simulator.client.utils.ssl.SSLAuthenticationHelper; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.JobExecutionContext; +import org.quartz.JobKey; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.SimpleTrigger; + +class EventSchedulerTest { + + @InjectMocks + EventScheduler eventScheduler; + + @Mock + Scheduler quartzScheduler; + + @Mock + SSLAuthenticationHelper sslAuthenticationHelper; + + @BeforeEach + void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + void shouldTriggerEventWithGivenConfiguration() throws SchedulerException, IOException, GeneralSecurityException { + //given + ArgumentCaptor<JobDetail> jobDetailCaptor = ArgumentCaptor.forClass(JobDetail.class); + ArgumentCaptor<SimpleTrigger> triggerCaptor = ArgumentCaptor.forClass(SimpleTrigger.class); + + String vesUrl = "http://some:80/"; + int repeatInterval = 1; + int repeatCount = 4; + String testName = "testName"; + String eventId = "1"; + JsonObject body = new JsonObject(); + + //when + eventScheduler.scheduleEvent(vesUrl, repeatInterval, repeatCount, testName, eventId, body); + + //then + verify(quartzScheduler).scheduleJob(jobDetailCaptor.capture(), triggerCaptor.capture()); + JobDataMap actualJobDataMap = jobDetailCaptor.getValue().getJobDataMap(); + assertThat(actualJobDataMap.get(EventJob.BODY)).isEqualTo(body); + assertThat(actualJobDataMap.get(EventJob.TEMPLATE_NAME)).isEqualTo(testName); + assertThat(actualJobDataMap.get(EventJob.VES_URL)).isEqualTo(vesUrl); + + SimpleTrigger actualTrigger = triggerCaptor.getValue(); + // repeat count adds 1 to given value + assertThat(actualTrigger.getRepeatCount()).isEqualTo(repeatCount - 1); + + //getRepeatInterval returns interval in ms + assertThat(actualTrigger.getRepeatInterval()).isEqualTo(repeatInterval * 1000); + } + + @Test + void shouldCancelAllEvents() throws SchedulerException { + //given + List<JobKey> jobsKeys = Arrays.asList(new JobKey("jobName1"), new JobKey("jobName2"), + new JobKey("jobName3"), new JobKey("jobName4")); + List<JobExecutionContext> jobExecutionContexts = createExecutionContextWithKeys(jobsKeys); + when(quartzScheduler.getCurrentlyExecutingJobs()).thenReturn(jobExecutionContexts); + when(quartzScheduler.deleteJobs(jobsKeys)).thenReturn(true); + + //when + boolean isCancelled = eventScheduler.cancelAllEvents(); + + //then + assertThat(isCancelled).isTrue(); + } + + @Test + void shouldCancelSingleEvent() throws SchedulerException { + //given + JobKey jobToRemove = new JobKey("jobName3"); + List<JobKey> jobsKeys = Arrays.asList(new JobKey("jobName1"), new JobKey("jobName2"), + jobToRemove, new JobKey("jobName4")); + List<JobExecutionContext> jobExecutionContexts = createExecutionContextWithKeys(jobsKeys); + + when(quartzScheduler.getCurrentlyExecutingJobs()).thenReturn(jobExecutionContexts); + when(quartzScheduler.deleteJob(jobToRemove)).thenReturn(true); + + //when + boolean isCancelled = eventScheduler.cancelEvent("jobName3"); + + //then + assertThat(isCancelled).isTrue(); + } + + private List<JobExecutionContext> createExecutionContextWithKeys(List<JobKey> jobsKeys) { + List<JobExecutionContext> contexts = new ArrayList<>(); + for (JobKey key : jobsKeys) { + contexts.add(createExecutionContextFromKey(key)); + } + return contexts; + } + + private JobExecutionContext createExecutionContextFromKey(JobKey key) { + JobExecutionContext context = mock(JobExecutionContext.class); + JobDetail jobDetail = mock(JobDetail.class); + when(context.getJobDetail()).thenReturn(jobDetail); + when(jobDetail.getKey()).thenReturn(key); + return context; + } + + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigServiceTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigServiceTest.java new file mode 100644 index 0000000..4ed0972 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigServiceTest.java @@ -0,0 +1,104 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 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.pnfsimulator.simulatorconfig; + +import org.assertj.core.util.Lists; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + +import static org.assertj.core.api.Java6Assertions.assertThat; +import static org.assertj.core.api.Java6Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +class SimulatorConfigServiceTest { + + private static final String SAMPLE_ID = "sampleId"; + private static final String SAMPLE_NEW_VES_URL = "http://localhost:8090/eventListener/v7"; + @Mock + private SimulatorConfigRepository repository; + + @InjectMocks + private SimulatorConfigService service; + + @BeforeEach + void resetMocks() { + initMocks(this); + } + + @Test + void testShouldReturnConfiguration() throws MalformedURLException { + List<SimulatorConfig> expectedConfig = getExpectedConfig(); + when(repository.findAll()).thenReturn(expectedConfig); + + SimulatorConfig configs = service.getConfiguration(); + + assertThat(configs).isNotNull(); + } + + @Test + void testShouldRaiseExceptionWhenNoConfigurationPresent() { + when(repository.findAll()).thenReturn(Lists.emptyList()); + + assertThatThrownBy(() -> service.getConfiguration()) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("No configuration found in db"); + } + + @Test + void testShouldUpdateConfigurationWithVesUrl() throws MalformedURLException { + URL updatedUrl = new URL("http://localhost:8090/listener/v8"); + SimulatorConfig configWithUpdates = new SimulatorConfig("sampleId", updatedUrl); + List<SimulatorConfig> expectedConfig = getExpectedConfig(); + + when(repository.findAll()).thenReturn(expectedConfig); + when(repository.save(any(SimulatorConfig.class))).thenReturn(configWithUpdates); + + SimulatorConfig updatedConfig = service.updateConfiguration(configWithUpdates); + + assertThat(updatedConfig).isEqualToComparingFieldByField(configWithUpdates); + } + + @Test + void testShouldRaiseExceptionWhenNoConfigInDbPresentOnUpdate() throws MalformedURLException { + when(repository.findAll()).thenReturn(Lists.emptyList()); + + SimulatorConfig configWithUpdates = new SimulatorConfig(SAMPLE_ID, new URL(SAMPLE_NEW_VES_URL)); + + assertThatThrownBy(() -> service.updateConfiguration(configWithUpdates)) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("No configuration found in db"); + } + + private List<SimulatorConfig> getExpectedConfig() throws MalformedURLException { + URL sampleVesUrl = new URL("http://localhost:8080/eventListener/v7"); + SimulatorConfig config = new SimulatorConfig(SAMPLE_ID, sampleVesUrl); + return Lists.newArrayList(config); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/TemplateServiceTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/TemplateServiceTest.java new file mode 100644 index 0000000..0746960 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/TemplateServiceTest.java @@ -0,0 +1,152 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.template; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.assertj.core.util.Lists; +import org.bson.Document; +import org.junit.Assert; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock;; +import org.onap.pnfsimulator.template.search.viewmodel.FlatTemplateContent; +import org.onap.pnfsimulator.template.search.TemplateSearchHelper; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Query; + +import java.time.Instant; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyObject; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +class TemplateServiceTest { + private static final Gson GSON = new Gson(); + private static final Template SAMPLE_TEMPLATE = new Template("sample name", new Document(), Instant.now().getNano()); + private static final List<Template> SAMPLE_TEMPLATE_LIST = Collections.singletonList(SAMPLE_TEMPLATE); + + @Mock + private TemplateRepository templateRepositoryMock; + + @Mock + private MongoTemplate mongoTemplate; + + @InjectMocks + private TemplateService service; + + @BeforeEach + void setUp() { + initMocks(this); + TemplateSearchHelper searchHelper = new TemplateSearchHelper(mongoTemplate); + service = new TemplateService(templateRepositoryMock, searchHelper); + } + + @Test + void testShouldReturnAllTemplates() { + when(templateRepositoryMock.findAll()).thenReturn(SAMPLE_TEMPLATE_LIST); + + List<Template> actual = service.getAll(); + assertThat(actual).containsExactly(SAMPLE_TEMPLATE_LIST.get(0)); + } + + + @Test + void testShouldGetTemplateBySpecifiedName() { + when(templateRepositoryMock.findById("sample name")).thenReturn(Optional.of(SAMPLE_TEMPLATE)); + + Optional<Template> actualTemplate = service.get("sample name"); + assertThat(actualTemplate).isPresent(); + assertThat(actualTemplate.get()).isEqualTo(SAMPLE_TEMPLATE); + } + + @Test + void testShouldSaveTemplate() { + service.persist(SAMPLE_TEMPLATE); + + verify(templateRepositoryMock, times(1)).save(SAMPLE_TEMPLATE); + } + + @Test + void testShouldDeleteTemplateByName() { + service.delete("sample name"); + + verify(templateRepositoryMock, times(1)).deleteById("sample name"); + } + + + @Test + void testShouldReturnTemplatesAccordingToGivenSearchCriteria() { + doReturn(Lists.emptyList()).when(mongoTemplate).find(any(Query.class), anyObject(), any(String.class)); + + List<String> idsByContentCriteria = service.getIdsByContentCriteria(GSON.fromJson("{\"domain\": \"notification.json\"}", JsonObject.class)); + + assertThat(idsByContentCriteria).isEmpty(); + } + + @Test + void shouldReturnNamesForGivenComposedSearchCriteria(){ + JsonObject composedCriteriaObject = GSON.fromJson("{\"eventName\": \"pnfRegistration_Nokia_5gDu\", \"sequence\": 1}", JsonObject.class); + List<FlatTemplateContent> arr = Lists.newArrayList(new FlatTemplateContent("sampleId", null)); + + doReturn(arr).when(mongoTemplate).find(any(Query.class), anyObject(), any(String.class)); + + List<String> idsByContentCriteria = service.getIdsByContentCriteria(composedCriteriaObject); + assertThat(idsByContentCriteria).containsOnly("sampleId"); + } + + @Test + void shouldReturnFalseWhenOverwritingWithoutForce() { + String id = "someTemplate"; + Template template = new Template(id, new Document(), Instant.now().getNano()); + when(templateRepositoryMock.existsById(id)).thenReturn(true); + boolean actual = service.tryPersistOrOverwrite(template, false); + Assert.assertFalse(actual); + } + + @Test + void shouldReturnTrueWhenOverwritingWithForce() { + String id = "someTemplate"; + Template template = new Template(id, new Document(), Instant.now().getNano()); + when(templateRepositoryMock.existsById(id)).thenReturn(true); + boolean actual = service.tryPersistOrOverwrite(template, true); + Assert.assertTrue(actual); + } + + @Test + void shouldReturnTrueWhenSavingNonExistingTemplate() { + String id = "someTemplate"; + Template template = new Template(id, new Document(), Instant.now().getNano()); + when(templateRepositoryMock.existsById(id)).thenReturn(false); + boolean actual = service.tryPersistOrOverwrite(template, false); + Assert.assertTrue(actual); + } + +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/search/JsonUtilsTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/search/JsonUtilsTest.java new file mode 100644 index 0000000..fa0bed1 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/search/JsonUtilsTest.java @@ -0,0 +1,166 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.template.search; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.bson.Document; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Java6Assertions.assertThat; + +class JsonUtilsTest { + + private static final Gson GSON_HELPER = new Gson(); + private JsonUtils utils; + + @BeforeEach + void setUp() { + utils = new JsonUtils(); + } + + private static final String NOTIFICATION_JSON = "{\n\"event\": {\n" + + " \"commonEventHeader\": {\n" + + " \"domain\": \"notification\",\n" + + " \"eventName\": \"vFirewallBroadcastPackets\"\n" + + " },\n" + + " \"notificationFields\": {\n" + + " \"changeIdentifier\": \"PM_MEAS_FILES\",\n" + + " \"arrayOfNamedHashMap\": [{\n" + + " \"name\": \"A20161221.1031-1041.bin.gz\",\n" + + " \"hashMap\": {\n" + + " \"fileformatType\": \"org.3GPP.32.435#measCollec\",\n" + + " \"fileFormatVersion\": \"V10\"\n"+ + " }\n" + + " }, {\n" + + " \"name\": \"A20161222.1042-1102.bin.gz\",\n" + + " \"hashMap\": {\n" + + " \"fileFormatType\": \"org.3GPP.32.435#measCollec\",\n" + + " \"fileFormatVersion\": \"1.0.0\"\n" + + " }\n" + + " }],\n" + + " \"notificationFieldsVersion\": \"2.0\"\n}\n\n}}"; + private static final String EXPECTED_FLATTENED_NOTIFICATION = "{" + + " \":event:commonEventHeader:domain\" : \"notification\"," + + " \":event:commonEventHeader:eventName\" : \"vFirewallBroadcastPackets\"," + + " \":event:notificationFields:changeIdentifier\" : \"PM_MEAS_FILES\"," + + " \":event:notificationFields:arrayOfNamedHashMap[0]:name\" : \"A20161221.1031-1041.bin.gz\"," + + " \":event:notificationFields:arrayOfNamedHashMap[0]:hashMap:fileformatType\" : \"org.3GPP.32.435#measCollec\"," + + " \":event:notificationFields:arrayOfNamedHashMap[0]:hashMap:fileFormatVersion\" : \"V10\"," + + " \":event:notificationFields:arrayOfNamedHashMap[1]:name\" : \"A20161222.1042-1102.bin.gz\"," + + " \":event:notificationFields:arrayOfNamedHashMap[1]:hashMap:fileFormatType\" : \"org.3GPP.32.435#measCollec\"," + + " \":event:notificationFields:arrayOfNamedHashMap[1]:hashMap:fileFormatVersion\" : \"1.0.0\"," + + " \":event:notificationFields:notificationFieldsVersion\" : \"2.0\" }"; + + @Test + void shouldFlattenNestedJsonAndSeparateKeysWithDoubleHash(){ + JsonObject templateJson = GSON_HELPER.fromJson(NOTIFICATION_JSON, JsonObject.class); + + JsonObject result = utils.flatten(templateJson); + + assertThat(result).isEqualTo(GSON_HELPER.fromJson(EXPECTED_FLATTENED_NOTIFICATION, JsonObject.class)); + } + + @Test + void shouldWorkOnEmptyJsonObject(){ + JsonObject result = utils.flatten(new JsonObject()); + + assertThat(result.toString()).isEqualTo("{}"); + } + + @Test + void shouldFlattenObjectWithArrayValue(){ + String expectedFlattenedObjectWithArray = "{" + + " \":sample[0]\": 1," + + " \":sample[1]\": 2," + + " \":sample[2]\": 3}"; + JsonObject jsonWithPrimitivesArray = GSON_HELPER.fromJson("{\"sample\": [1, 2, 3]}", JsonObject.class); + + JsonObject result = utils.flatten(jsonWithPrimitivesArray); + + assertThat(result).isEqualTo(GSON_HELPER.fromJson(expectedFlattenedObjectWithArray, JsonObject.class)); + } + + @Test + void shouldFlattenObjectWithEmptyArrayValue(){ + String expectedFlattenedObjectWithEmptyArray = "{\":sample\": []}"; + JsonObject jsonWithEmptyArrayValue = GSON_HELPER.fromJson("{\"sample\": []}", JsonObject.class); + + JsonObject result = utils.flatten(jsonWithEmptyArrayValue); + + assertThat(result).isEqualTo(GSON_HELPER.fromJson(expectedFlattenedObjectWithEmptyArray, JsonObject.class)); + } + + @Test + void shouldFlattenNestedObjectWithEmptyObjectValue(){ + String expectedFlattenedNestedObjectWithEmptyObject = "{\":sample:key\": {}}"; + JsonObject nestedJsonWithEmptyObject = GSON_HELPER.fromJson("{\"sample\": {\"key\":{}}}", JsonObject.class); + + JsonObject result = utils.flatten(nestedJsonWithEmptyObject); + + assertThat(result).isEqualTo(GSON_HELPER.fromJson(expectedFlattenedNestedObjectWithEmptyObject, JsonObject.class)); + } + + @Test + void shouldFlattenObjectWithDifferentDataTypes(){ + String jsonWithDifferentDataTypes = "{ \"topLevelKey\": {\"sampleInt\": 1, \"sampleBool\": false, \"sampleDouble\": 10.0, \"sampleString\": \"str\"}}"; + String expectedResult = "{\":topLevelKey:sampleInt\": 1," + + " \":topLevelKey:sampleBool\": \"false\"," + + " \":topLevelKey:sampleDouble\": 10.0," + + " \":topLevelKey:sampleString\": \"str\"}"; + JsonObject templateJson = GSON_HELPER.fromJson(jsonWithDifferentDataTypes, JsonObject.class); + + JsonObject result = utils.flatten(templateJson); + + assertThat(result).isEqualTo(GSON_HELPER.fromJson(expectedResult, JsonObject.class)); + } + + @Test + void shouldHandleNullValues(){ + String jsonWithNullValue = "{ \"topLevelKey\": {\"sampleNull\": null, \"sampleString\": \"str\"}}"; + String expectedResult = "{\":topLevelKey:sampleNull\": null," + + " \":topLevelKey:sampleString\": \"str\"}"; + JsonObject templateJson = GSON_HELPER.fromJson(jsonWithNullValue, JsonObject.class); + + JsonObject result = utils.flatten(templateJson); + + assertThat(result).isEqualTo(GSON_HELPER.fromJson(expectedResult, JsonObject.class)); + } + + @Test + void shouldFlattenBsonDocument(){ + Document documentInput = Document.parse(NOTIFICATION_JSON); + + Document result = utils.flatten(documentInput); + + assertThat(result.toJson()).isEqualTo(EXPECTED_FLATTENED_NOTIFICATION); + } + + @Test + void shouldNotChangeEmptyBsonDocument(){ + Document input = Document.parse("{}"); + + Document result = utils.flatten(input); + + assertThat(result.toJson()).isEqualTo("{ }"); + } +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/search/TemplateSearchHelperTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/search/TemplateSearchHelperTest.java new file mode 100644 index 0000000..aeef870 --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/search/TemplateSearchHelperTest.java @@ -0,0 +1,160 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.template.search; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.mongodb.BasicDBList; +import org.assertj.core.util.Lists; +import org.bson.Document; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.onap.pnfsimulator.template.search.viewmodel.FlatTemplateContent; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.BasicQuery; +import org.springframework.data.mongodb.core.query.Query; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Java6Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyObject; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + + +class TemplateSearchHelperTest { + + private static final Gson GSON = new Gson(); + private static final String FLATTENED_TEMPLATES_VIEW = "flatTemplatesView"; + + @Mock + private MongoTemplate mongoTemplate; + + @InjectMocks + private TemplateSearchHelper helper; + + private static final ArgumentCaptor<Query> QUERY_CAPTOR = ArgumentCaptor.forClass(Query.class); + private static final ArgumentCaptor<String> COLLECTION_NAME_CAPTOR = ArgumentCaptor.forClass(String.class); + private static final ArgumentCaptor<Class<FlatTemplateContent>> CLASS_TYPE_CAPTOR = ArgumentCaptor.forClass((Class) FlatTemplateContent.class); + + + @BeforeEach + void setUp() { + initMocks(this); + } + + @Test + void shouldReturnNamesForGivenComposedSearchCriteria(){ + String expectedComposedQueryString = "{\"$and\":[{\"keyValues\":{\"$elemMatch\":{\"k\":{\"$regex\":\":eventName(?:(\\\\[[\\\\d]+\\\\]))?$\",\"$options\":\"iu\"},\"v\":{\"$regex\":\"^\\\\QpnfRegistration_Nokia_5gDu\\\\E$\",\"$options\":\"iu\"}}}},{\"keyValues\":{\"$elemMatch\":{\"k\":{\"$regex\":\":sequence(?:(\\\\[[\\\\d]+\\\\]))?$\",\"$options\":\"iu\"},\"v\":1.0}}}]}"; + Query expectedQuery = new BasicQuery(expectedComposedQueryString); + + String composedCriteriaInputJson = "{\"eventName\": \"pnfRegistration_Nokia_5gDu\", \"sequence\": 1}"; + JsonObject composedCriteriaObject = GSON.fromJson(composedCriteriaInputJson, JsonObject.class); + + when(mongoTemplate.find(any(Query.class), anyObject(), any(String.class))).thenReturn(Lists.newArrayList(new FlatTemplateContent("sampleId1", null), new FlatTemplateContent("sampleId2", null))); + + List<String> idsOfDocumentMatchingCriteria = helper.getIdsOfDocumentMatchingCriteria(composedCriteriaObject); + + assertThat(idsOfDocumentMatchingCriteria).containsOnly("sampleId1", "sampleId2"); + verify(mongoTemplate, times(1)).find(QUERY_CAPTOR.capture(), CLASS_TYPE_CAPTOR.capture(), COLLECTION_NAME_CAPTOR.capture()); + assertThat(QUERY_CAPTOR.getValue().toString()).isEqualTo(expectedQuery.toString()); + assertThat(COLLECTION_NAME_CAPTOR.getValue()).isEqualTo(FLATTENED_TEMPLATES_VIEW); + assertThat(CLASS_TYPE_CAPTOR.getValue()).isEqualTo(FlatTemplateContent.class); + } + + @Test + void shouldReturnTemplatesAccordingToGivenSearchCriteria() { + Query expectedQueryStructure = new BasicQuery("{\"$and\":[{\"keyValues\": { \"$elemMatch\" : { \"k\" : { \"$regex\" : \":domain(?:(\\\\[[\\\\d]+\\\\]))?$\", \"$options\" : \"iu\" }, \"v\" : { \"$regex\" : \"^\\\\Qnotification\\\\E$\", \"$options\" : \"iu\" }}}}]}"); + + helper.getIdsOfDocumentMatchingCriteria(GSON.fromJson("{\"domain\": \"notification\"}", JsonObject.class)); + + + verify(mongoTemplate, times(1)).find(QUERY_CAPTOR.capture(), CLASS_TYPE_CAPTOR.capture(), COLLECTION_NAME_CAPTOR.capture()); + + assertThat(QUERY_CAPTOR.getValue().toString()).isEqualTo(expectedQueryStructure.toString()); + assertThat(COLLECTION_NAME_CAPTOR.getValue()).isEqualTo(FLATTENED_TEMPLATES_VIEW); + assertThat(CLASS_TYPE_CAPTOR.getValue()).isEqualTo(FlatTemplateContent.class); + } + + @Test + void shouldGetQueryForEmptyJson(){ + JsonObject jsonObject = GSON.fromJson("{}", JsonObject.class); + + String expectedComposedQueryString = "{}"; + Query expectedQuery = new BasicQuery(expectedComposedQueryString); + + helper.getIdsOfDocumentMatchingCriteria(jsonObject); + + verify(mongoTemplate, times(1)).find(QUERY_CAPTOR.capture(), CLASS_TYPE_CAPTOR.capture(), COLLECTION_NAME_CAPTOR.capture()); + Query queryBasedOnCriteria = QUERY_CAPTOR.getValue(); + + assertThat(QUERY_CAPTOR.getValue().toString()).isEqualTo(expectedQuery.toString()); + assertThat(COLLECTION_NAME_CAPTOR.getValue()).isEqualTo(FLATTENED_TEMPLATES_VIEW); + assertThat(CLASS_TYPE_CAPTOR.getValue()).isEqualTo(FlatTemplateContent.class); + } + + + @Test + void shouldGetQueryWithAllTypeValues(){ + JsonObject jsonObject = GSON.fromJson("{\"stringKey\": \"stringValue\", \"numberKey\": 16.00, \"boolKey\": false}", JsonObject.class); + + helper.getIdsOfDocumentMatchingCriteria(jsonObject); + + verify(mongoTemplate, times(1)).find(QUERY_CAPTOR.capture(), CLASS_TYPE_CAPTOR.capture(), COLLECTION_NAME_CAPTOR.capture()); + Query queryBasedOnCriteria = QUERY_CAPTOR.getValue(); + + assertThat(queryBasedOnCriteria.getQueryObject().get("$and")).isInstanceOf(List.class); + List<Document> conditionDocuments = new ArrayList<>((List<Document>) queryBasedOnCriteria.getQueryObject().get("$and")); + List<Document> conditions = conditionDocuments.stream().map(el -> (Document) el.get("keyValues")).map(el -> (Document) el.get("$elemMatch")).collect(Collectors.toList()); + + assertThat(conditionDocuments).hasSize(3); + assertJsonPreparedKeyHasCorrectStructure(conditions.get(0), "stringKey"); + assertThat(conditions.get(0).get("v").toString()).isEqualTo(TemplateSearchHelper.getCaseInsensitive("^\\QstringValue\\E$").toString()); + + assertJsonPreparedKeyHasCorrectStructure(conditions.get(1), "numberKey"); + assertThat(conditions.get(1).get("v")).isEqualTo(16.0); + + assertJsonPreparedKeyHasCorrectStructure(conditions.get(2), "boolKey"); + assertThat(conditions.get(2).get("v")).isEqualTo("false"); + } + + @Test + void shouldThrowExceptionWhenNullIsPresentAsCriteriaValue(){ + JsonObject jsonObject = GSON.fromJson("{\"stringKey\": \"stringValue\", \"nullKey\": null}", JsonObject.class); + + assertThrows(IllegalJsonValueException.class, () -> helper.getIdsOfDocumentMatchingCriteria(jsonObject)); + } + + private void assertJsonPreparedKeyHasCorrectStructure(Document actual, String expectedPattern){ + assertThat(actual.get("k").toString()).isEqualTo(Pattern.compile(String.format(":%s(?:(\\[[\\d]+\\]))?$", expectedPattern)).toString()); + + } +} diff --git a/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilderTest.java b/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilderTest.java new file mode 100644 index 0000000..31bcf1c --- /dev/null +++ b/pnfsimulator/src/test/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilderTest.java @@ -0,0 +1,75 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2019 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.pnfsimulator.template.search.handler; + +import com.google.gson.JsonPrimitive; +import org.junit.jupiter.api.Test; +import org.springframework.data.mongodb.core.query.Criteria; + +import static org.assertj.core.api.Java6Assertions.assertThat; + +class PrimitiveValueCriteriaBuilderTest { + + private PrimitiveValueCriteriaBuilder builder = new PrimitiveValueCriteriaBuilder(); + + @Test + void testShouldAddRegexLikeCriteriaForStringType(){ + Criteria criteria = builder.applyValueCriteriaBasedOnPrimitiveType(Criteria.where("k").is("10").and("v"), new JsonPrimitive("sample")); + + assertThat(criteria.getCriteriaObject().toJson()).isEqualTo("{ \"k\" : \"10\", \"v\" : { \"$regex\" : \"^\\\\Qsample\\\\E$\", \"$options\" : \"iu\" } }"); + } + + @Test + void testShouldAddRegexLikeAndEscapeStringWithMetaChars(){ + Criteria criteria = builder.applyValueCriteriaBasedOnPrimitiveType(Criteria.where("k").is("10").and("v"), new JsonPrimitive("[1,2,3,4,5]")); + + assertThat(criteria.getCriteriaObject().toJson()).isEqualTo("{ \"k\" : \"10\", \"v\" : { \"$regex\" : \"^\\\\Q[1,2,3,4,5]\\\\E$\", \"$options\" : \"iu\" } }"); + } + + @Test + void testShouldAddRegexLikeCriteriaForIntType(){ + Criteria criteria = builder.applyValueCriteriaBasedOnPrimitiveType(Criteria.where("k").is("10").and("v"), new JsonPrimitive(1)); + + assertThat(criteria.getCriteriaObject().toJson()).isEqualTo("{ \"k\" : \"10\", \"v\" : 1.0 }"); + } + + @Test + void testShouldAddRegexLikeCriteriaForLongType(){ + Criteria criteria = builder.applyValueCriteriaBasedOnPrimitiveType(Criteria.where("k").is("10").and("v"), new JsonPrimitive(Long.MAX_VALUE)); + + assertThat(criteria.getCriteriaObject().toJson()).isEqualTo("{ \"k\" : \"10\", \"v\" : 9.223372036854776E18 }"); + } + + @Test + void testShouldAddRegexLikeCriteriaForDoubleType(){ + Criteria criteria = builder.applyValueCriteriaBasedOnPrimitiveType(Criteria.where("k").is("10").and("v"), new JsonPrimitive(2.5)); + + assertThat(criteria.getCriteriaObject().toJson()).isEqualTo("{ \"k\" : \"10\", \"v\" : 2.5 }"); + } + + @Test + void testShouldAddRegexLikeCriteriaForBooleanType(){ + Criteria criteria = builder.applyValueCriteriaBasedOnPrimitiveType(Criteria.where("k").is("10").and("v"), new JsonPrimitive(true)); + + assertThat(criteria.getCriteriaObject().toJson()).isEqualTo("{ \"k\" : \"10\", \"v\" : \"true\" }"); + } + +} diff --git a/pnfsimulator/src/test/resources/application.properties b/pnfsimulator/src/test/resources/application.properties new file mode 100644 index 0000000..6815680 --- /dev/null +++ b/pnfsimulator/src/test/resources/application.properties @@ -0,0 +1,2 @@ +templates.dir=src/test/resources/org/onap/pnfsimulator/simulator +ssl.clientCertificateEnabled=false diff --git a/pnfsimulator/src/test/resources/client.p12 b/pnfsimulator/src/test/resources/client.p12 Binary files differnew file mode 100644 index 0000000..0bbec38 --- /dev/null +++ b/pnfsimulator/src/test/resources/client.p12 diff --git a/pnfsimulator/src/test/resources/logback-test.xml b/pnfsimulator/src/test/resources/logback-test.xml new file mode 100644 index 0000000..ad4f0c8 --- /dev/null +++ b/pnfsimulator/src/test/resources/logback-test.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + Simulator + ================================================================================ + Copyright (C) 2019 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========================================================= + --> + +<Configuration complete="true" compact="true"> + + <Property name="outputFilename" value="pnfsimulator_output"/> + <Property name="log-path" value="${java.io.tmpdir}"/> + <property name="maxFileSize" value="50MB"/> + <property name="maxHistory" value="30"/> + <property name="totalSizeCap" value="10GB"/> + + <appender name="Console" target="SYSTEM_OUT" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <Pattern>%nopexception%logger + |%date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX,UTC} + |%level + |%replace(%replace(%message){'\t','\\\\t'}){'\n','\\\\n'} + |%replace(%replace(%mdc){'\t','\\\\t'}){'\n','\\\\n'} + |%replace(%replace(%rootException){'\t','\\\\t'}){'\n','\\\\n'} + |%replace(%replace(%marker){'\t','\\\\t'}){'\n','\\\\n'} + |%thread + |%n</Pattern> + </encoder> + </appender> + + <appender name="ROLLING-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <encoder> + <pattern>%nopexception%logger + |%date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX,UTC} + |%level + |%replace(%replace(%message){'\t','\\\\t'}){'\n','\\\\n'} + |%replace(%replace(%mdc){'\t','\\\\t'}){'\n','\\\\n'} + |%replace(%replace(%rootException){'\t','\\\\t'}){'\n','\\\\n'} + |%replace(%replace(%marker){'\t','\\\\t'}){'\n','\\\\n'} + |%thread + |%n</pattern> + </encoder> + <File>${log-path}/${outputFilename}.log</File> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <FileNamePattern>${log-path}/${outputFilename}.%d{yyyy-MM-dd}.%i.log.zip</FileNamePattern> + <MaxFileSize>${maxFileSize}</MaxFileSize> + <MaxHistory>${maxHistory}</MaxHistory> + <TotalSizeCap>${totalSizeCap}</TotalSizeCap> + </rollingPolicy> + </appender> + + <root level="info"> + <appender-ref ref="Console" /> + <appender-ref ref="ROLLING-FILE" /> + </root> +</Configuration> diff --git a/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/filesystem/test1.json b/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/filesystem/test1.json new file mode 100644 index 0000000..89e4a76 --- /dev/null +++ b/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/filesystem/test1.json @@ -0,0 +1,12 @@ +{ + "field1": "value1", + "field2": 2, + "nested": { + "key1": [ + 1, + 2, + 3 + ], + "key2": "sampleValue2" + } +} diff --git a/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/invalidJsonStructureEvent.json b/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/invalidJsonStructureEvent.json new file mode 100644 index 0000000..4d6ef7d --- /dev/null +++ b/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/invalidJsonStructureEvent.json @@ -0,0 +1 @@ +{"sampleKey1": [{"sampleKey2": "1"}, {"sampleKey2": "2"}] diff --git a/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/validExampleMeasurementEvent.json b/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/validExampleMeasurementEvent.json new file mode 100644 index 0000000..989d6ea --- /dev/null +++ b/pnfsimulator/src/test/resources/org/onap/pnfsimulator/simulator/validExampleMeasurementEvent.json @@ -0,0 +1,89 @@ +{ + "event": { + "commonEventHeader": { + "domain": "measurementsForVfScaling", + "eventName": "vFirewallBroadcastPackets", + "eventId": "4cfc-91cf-31a46", + "nfType": "mrfx", + "priority": "Normal", + "reportingEntityName": "myVNF", + "sequence": 1, + "sourceName": "ClosedLoopVNF", + "startEpochMicrosec": 1531616794, + "lastEpochMicrosec": 1531719042, + "version": 2.0 + }, + "measurementsForVfScalingFields": { + "measurementsForVfSclaingFieldsVersion": 2.0, + "measurementsForVfScalingVersion": 2.0, + "measurementInterval": 180, + "concurrentSessions": 2, + "cpuUsageArray": [ + { + "cpuIdentifier": "INTEL_CORE_I7_1", + "percentUsage": 50 + }, + { + "cpuIdentifier": "INTEL_CORE_I7_2", + "percentUsage": 70 + } + ], + "memoryUsageArray": [ + { + "vmIdentifier": "vmIdentifier", + "memoryFree": 50, + "memoryUsed": 10 + } + ], + "vNicUsageArray": [ + { + "receivedTotalPacketsDelta": 30 + } + ], + "numberOfMediaPortsInUse": 100, + "additionalMeasurements": [ + { + "name": "licenseUsage", + "arrayOfFields": [ + { + "name": "G711AudioPort", + "value": "1" + }, + { + "name": "G729AudioPort", + "value": "1" + }, + { + "name": "G722AudioPort", + "value": "1" + }, + { + "name": "AMRAudioPort", + "value": "4" + }, + { + "name": "AMRWBAudioPort", + "value": "5" + }, + { + "name": "OpusAudioPort", + "value": "6" + }, + { + "name": "H263VideoPort", + "value": "7" + }, + { + "name": "H264NonHCVideoPort", + "value": "8" + }, + { + "name": "H264HCVideoPort", + "value": "9" + } + ] + } + ] + } + } +} diff --git a/pnfsimulator/src/test/resources/trustStore b/pnfsimulator/src/test/resources/trustStore Binary files differnew file mode 100644 index 0000000..e90b710 --- /dev/null +++ b/pnfsimulator/src/test/resources/trustStore diff --git a/pnfsimulator/store/client.p12 b/pnfsimulator/store/client.p12 Binary files differnew file mode 100644 index 0000000..0bbec38 --- /dev/null +++ b/pnfsimulator/store/client.p12 diff --git a/pnfsimulator/store/trustStore b/pnfsimulator/store/trustStore Binary files differnew file mode 100644 index 0000000..e90b710 --- /dev/null +++ b/pnfsimulator/store/trustStore diff --git a/pnfsimulator/templates/measurement.json b/pnfsimulator/templates/measurement.json new file mode 100644 index 0000000..a29b063 --- /dev/null +++ b/pnfsimulator/templates/measurement.json @@ -0,0 +1,44 @@ +{ + "event": { + "commonEventHeader": { + "domain": "measurementsForVfScaling", + "eventName": "vFirewallBroadcastPackets", + "eventId": "eventID123121312323", + "nfType": "mrfx", + "priority": "Normal", + "reportingEntityName": "vnf", + "sequence": 1, + "sourceName": "sample-vnf-#RandomInteger(1,10)", + "startEpochMicrosec": "#TimestampPrimitive", + "lastEpochMicrosec": "#TimestampPrimitive", + "version": 1.0 + }, + "measurementsForVfScalingFields": { + "measurementsForVfScalingFieldsVersion": 2.0, + "measurementsForVfScalingVersion": 2.0, + "measurementInterval": 180, + "concurrentSessions": 2, + "requestRate": "#RandomPrimitiveInteger(50,100)", + "meanRequestLatency": "#RandomPrimitiveInteger(1,1000)", + "cpuUsageArray": [ + { + "cpuIdentifier": "INTEL_CORE_I7_1", + "percentUsage": "#RandomPrimitiveInteger(1,100)" + }, + { + "cpuIdentifier": "INTEL_CORE_I7_2", + "percentUsage": "#RandomPrimitiveInteger(1,100)" + } + ], + "memoryUsageArray": [ + { + "vmIdentifier": "vmIdentifier", + "memoryFree": 50, + "memoryUsed": 10 + } + ], + "numberOfMediaPortsInUse": 100, + "additionalMeasurements": [] + } + } +} diff --git a/pnfsimulator/templates/notification.json b/pnfsimulator/templates/notification.json new file mode 100644 index 0000000..74888fb --- /dev/null +++ b/pnfsimulator/templates/notification.json @@ -0,0 +1,42 @@ +{ + "event": { + "commonEventHeader": { + "domain": "notification", + "eventName": "vFirewallBroadcastPackets", + "eventId": "4cfc-91cf-31a46", + "priority": "Normal", + "reportingEntityName": "myVNF", + "sequence": 1, + "sourceName": "ClosedLoopVNF", + "startEpochMicrosec": 1531616794, + "lastEpochMicrosec": 1531719042, + "vesEventListenerVersion": "7.0.1", + "version": "4.0.1" + }, + "notificationFields": { + "changeIdentifier": "PM_MEAS_FILES", + "changeType": "FileReady", + "arrayOfNamedHashMap": [ + { + "name": "A20161221.1031-1041.bin.gz", + "hashMap": { + "fileformatType": "org.3GPP.32.435#measCollec", + "fileFormatVersion": "V10", + "location": "ftpes://192.169.0.1:22/ftp/rop/A20161224.1030-1045.bin.gz", + "compression": "gzip" + } + }, + { + "name": "A20161222.1042-1102.bin.gz", + "hashMap": { + "fileFormatType": "org.3GPP.32.435#measCollec", + "fileFormatVersion": "V10", + "location": "ftpes://192.168.0.102:22/ftp/rop/A20161224.1045-1100.bin.gz", + "compression": "gzip" + } + } + ], + "notificationFieldsVersion": "2.0" + } + } +} diff --git a/pnfsimulator/templates/registration.json b/pnfsimulator/templates/registration.json new file mode 100644 index 0000000..5c4dea5 --- /dev/null +++ b/pnfsimulator/templates/registration.json @@ -0,0 +1,33 @@ +{ + "event": { + "commonEventHeader": { + "eventId": "registration_39239592", + "eventType": "pnfRegistration", + "reportingEntityName": "NOK6061ZW3", + "domain": "pnfRegistration", + "nfcNamingCode": "oam", + "sequence": 0, + "sourceId": "val13", + "internalHeaderFields": {}, + "priority": "Normal", + "sourceName": "NOK6061ZW3", + "eventName": "pnfRegistration_Nokia_5gDu", + "version": "4.0.1", + "nfNamingCode": "gNB", + "startEpochMicrosec": 1539239592379, + "vesEventListenerVersion": "7.0.1", + "lastEpochMicrosec": 1539239592379 + }, + "pnfRegistrationFields": { + "pnfRegistrationFieldsVersion": "2.0", + "serialNumber": "6061ZW3", + "vendorName": "Nokia", + "oamV4IpAddress": "val3", + "oamV6IpAddress": "val4", + "unitFamily": "BBU", + "modelNumber": "val6", + "softwareVersion": "val7", + "unitType": "val8" + } + } +} |