From 4af5241ab25b0103d8ea680789aaf9a8696dfc75 Mon Sep 17 00:00:00 2001 From: Bogumil Zebek Date: Tue, 9 Mar 2021 12:54:38 +0100 Subject: Move pnf simulator to the new repo In the first phase we renamed project from pnf simulator to vesclient. Next steps: package rename, update Readme.md, upgrade project dependencies. Issue-ID: INT-1869 Signed-off-by: Bogumil Zebek Change-Id: I7714792f9739eb746c9c533e8ef41b9618a3a1d9 --- .gitignore | 17 + Dockerfile | 18 + Makefile | 13 + README.md | 436 ++++++++++++++++++ certificates/AAF_RootCA.crt | 31 ++ certificates/dcaelocal.crt | 20 + config/config.json | 9 + config/mongo_db_schema_creation.py | 48 ++ config/requirements.txt | 1 + db/pnf_simulator.js | 28 ++ deployment/PnP_PNF_sim_heat_template.yml | 118 +++++ docker-compose.yml | 40 ++ integration/pom.xml | 128 ++++++ .../org/onap/pnfsimulator/integration/Main.java | 35 ++ .../integration/VesSimulatorController.java | 71 +++ .../integration/VesSimulatorService.java | 36 ++ .../src/main/resources/application.properties | 1 + integration/src/main/resources/keystore | Bin 0 -> 2196 bytes .../integration/BasicAvailabilityTest.java | 234 ++++++++++ .../integration/OptionalTemplatesTest.java | 161 +++++++ .../integration/SearchInTemplatesTest.java | 269 +++++++++++ .../pnfsimulator/integration/SingleEventTest.java | 151 +++++++ .../integration/TemplatesManagementTest.java | 175 ++++++++ .../integration/TestConfiguration.java | 36 ++ .../onap/pnfsimulator/integration/TestUtils.java | 57 +++ .../integration/VariablesReplacement.java | 80 ++++ .../integration/suites/DockerBasedTestsSuite.java | 90 ++++ .../src/test/resources/application.properties | 6 + .../test/resources/templates/cmNotification.json | 32 ++ .../src/test/resources/templates/notification.json | 45 ++ .../resources/templates/overwrite_template.json | 6 + .../resources/templates/overwritten_template.json | 6 + .../src/test/resources/templates/registration.json | 36 ++ .../templates/search/complicated_template.json | 43 ++ .../templates/search/simple_template.json | 12 + .../templates/search/template_with_array.json | 23 + .../templates/search/template_with_booleans.json | 12 + .../templates/search/template_with_floats.json | 13 + .../templates/search/template_with_ints.json | 12 + .../test/resources/templates/upload_template.json | 6 + lombok.config | 2 + pom.xml | 498 +++++++++++++++++++++ src/assembly/resources.xml | 57 +++ src/main/java/org/onap/pnfsimulator/Main.java | 59 +++ .../java/org/onap/pnfsimulator/SwaggerConfig.java | 46 ++ src/main/java/org/onap/pnfsimulator/db/Row.java | 39 ++ .../java/org/onap/pnfsimulator/db/Storage.java | 41 ++ .../org/onap/pnfsimulator/event/EventData.java | 67 +++ .../pnfsimulator/event/EventDataRepository.java | 26 ++ .../onap/pnfsimulator/event/EventDataService.java | 65 +++ .../pnfsimulator/filesystem/WatcherConfig.java | 39 ++ .../filesystem/WatcherEventProcessor.java | 111 +++++ .../pnfsimulator/filesystem/WatcherService.java | 44 ++ .../pnfsimulator/filesystem/WatcherThread.java | 81 ++++ .../onap/pnfsimulator/logging/MdcVariables.java | 35 ++ .../pnfsimulator/rest/SimulatorController.java | 241 ++++++++++ .../onap/pnfsimulator/rest/TemplateController.java | 112 +++++ .../onap/pnfsimulator/rest/model/FullEvent.java | 48 ++ .../onap/pnfsimulator/rest/model/SearchExp.java | 42 ++ .../pnfsimulator/rest/model/SimulatorParams.java | 46 ++ .../pnfsimulator/rest/model/SimulatorRequest.java | 55 +++ .../pnfsimulator/rest/model/TemplateRequest.java | 38 ++ .../org/onap/pnfsimulator/rest/util/DateUtil.java | 35 ++ .../rest/util/JsonObjectDeserializer.java | 42 ++ .../pnfsimulator/rest/util/ResponseBuilder.java | 62 +++ .../pnfsimulator/simulator/DbTemplateReader.java | 51 +++ .../simulator/EventNotFoundException.java | 29 ++ .../simulator/FilesystemTemplateReader.java | 54 +++ .../pnfsimulator/simulator/IncrementProvider.java | 26 ++ .../simulator/IncrementProviderImpl.java | 47 ++ .../pnfsimulator/simulator/JsonTokenProcessor.java | 134 ++++++ .../pnfsimulator/simulator/KeywordsExtractor.java | 129 ++++++ .../pnfsimulator/simulator/KeywordsHandler.java | 74 +++ .../simulator/KeywordsHandlerException.java | 28 ++ .../simulator/KeywordsValueProvider.java | 80 ++++ .../pnfsimulator/simulator/SimulatorService.java | 132 ++++++ .../pnfsimulator/simulator/TemplatePatcher.java | 53 +++ .../pnfsimulator/simulator/TemplateReader.java | 29 ++ .../simulator/TemplateVariablesReplacer.java | 50 +++ .../client/HttpApacheResponseAdapterFactory.java | 45 ++ .../simulator/client/HttpClientAdapter.java | 27 ++ .../simulator/client/HttpClientAdapterImpl.java | 119 +++++ .../simulator/client/HttpResponseAdapter.java | 41 ++ .../utils/ssl/CertAuthSslContextFactory.java | 53 +++ .../client/utils/ssl/CertificateReader.java | 46 ++ .../client/utils/ssl/HttpClientFactory.java | 104 +++++ .../client/utils/ssl/HttpClientFactoryFacade.java | 40 ++ .../client/utils/ssl/PasswordConverter.java | 32 ++ .../client/utils/ssl/SSLContextFactory.java | 48 ++ .../client/utils/ssl/SslAuthenticationHelper.java | 45 ++ .../pnfsimulator/simulator/keywords/Keyword.java | 76 ++++ .../simulator/keywords/NonParameterKeyword.java | 65 +++ .../simulator/keywords/SingleParameterKeyword.java | 73 +++ .../simulator/keywords/TwoParameterKeyword.java | 80 ++++ .../pnfsimulator/simulator/scheduler/EventJob.java | 99 ++++ .../simulator/scheduler/EventScheduler.java | 120 +++++ .../simulator/scheduler/QuartzConfiguration.java | 38 ++ .../simulatorconfig/SimulatorConfig.java | 49 ++ .../simulatorconfig/SimulatorConfigRepository.java | 26 ++ .../simulatorconfig/SimulatorConfigService.java | 52 +++ .../template/FsToDbTemplateSynchronizer.java | 74 +++ .../org/onap/pnfsimulator/template/Template.java | 92 ++++ .../pnfsimulator/template/TemplateRepository.java | 26 ++ .../pnfsimulator/template/TemplateService.java | 81 ++++ .../template/search/IllegalJsonValueException.java | 28 ++ .../pnfsimulator/template/search/JsonUtils.java | 104 +++++ .../template/search/TemplateSearchHelper.java | 95 ++++ .../handler/PrimitiveValueCriteriaBuilder.java | 103 +++++ .../search/viewmodel/FlatTemplateContent.java | 45 ++ .../template/search/viewmodel/KeyValuePair.java | 40 ++ src/main/resources/application.properties | 18 + src/main/resources/logback.xml | 55 +++ .../pnfsimulator/event/EventDataServiceTest.java | 133 ++++++ .../filesystem/InMemoryTemplateStorage.java | 71 +++ .../filesystem/WatcherEventProcessorTest.java | 125 ++++++ .../pnfsimulator/rest/SimulatorControllerTest.java | 329 ++++++++++++++ .../pnfsimulator/rest/TemplateControllerTest.java | 256 +++++++++++ .../onap/pnfsimulator/rest/util/DateUtilTest.java | 38 ++ .../rest/util/ResponseBuilderTest.java | 66 +++ .../simulator/DbTemplateReaderTest.java | 81 ++++ .../simulator/IncrementProviderImplTest.java | 79 ++++ .../KeywordsExtractorInvalidRandomIntegerTest.java | 67 +++ .../KeywordsExtractorInvalidRandomStringTest.java | 67 +++ .../KeywordsExtractorInvalidTimestampTest.java | 65 +++ .../KeywordsExtractorValidRandomIntegerTest.java | 66 +++ ...dsExtractorValidRandomPrimitiveIntegerTest.java | 66 +++ .../KeywordsExtractorValidRandomStringTest.java | 69 +++ ...ywordsExtractorValidTimestampPrimitiveTest.java | 66 +++ .../KeywordsExtractorValidTimestampTest.java | 68 +++ .../simulator/KeywordsHandlerTest.java | 306 +++++++++++++ .../simulator/KeywordsValueProviderTest.java | 82 ++++ .../simulator/SimulatorServiceTest.java | 308 +++++++++++++ .../simulator/TemplatePatcherTest.java | 164 +++++++ .../pnfsimulator/simulator/TemplateReaderTest.java | 51 +++ .../simulator/TemplateVariablesReplacerTest.java | 174 +++++++ .../HttpApacheResponseAdapterFactoryTest.java | 98 ++++ .../client/HttpClientAdapterImplTest.java | 157 +++++++ .../simulator/client/HttpTestUtils.java | 55 +++ .../utils/ssl/CertAuthSslContextFactoryTest.java | 141 ++++++ .../utils/ssl/HttpClientFactoryFacadeTest.java | 35 ++ .../client/utils/ssl/HttpClientFactoryTest.java | 143 ++++++ .../client/utils/ssl/PasswordConverterTest.java | 44 ++ .../client/utils/ssl/SSLContextFactoryTest.java | 61 +++ .../keywords/TwoParameterKeywordTest.java | 48 ++ .../simulator/scheduler/EventJobTest.java | 90 ++++ .../simulator/scheduler/EventSchedulerTest.java | 148 ++++++ .../SimulatorConfigServiceTest.java | 104 +++++ .../template/FsToDbTemplateSynchronizerTest.java | 53 +++ .../pnfsimulator/template/TemplateServiceTest.java | 152 +++++++ .../template/search/JsonUtilsTest.java | 166 +++++++ .../template/search/TemplateSearchHelperTest.java | 160 +++++++ .../handler/PrimitiveValueCriteriaBuilderTest.java | 75 ++++ src/test/resources/application.properties | 2 + src/test/resources/certificates/client.p12 | Bin 0 -> 2685 bytes src/test/resources/certificates/client.pass | 1 + .../resources/certificates/client_invalid.pass | 1 + src/test/resources/certificates/truststore | Bin 0 -> 1455 bytes src/test/resources/certificates/truststore.pass | 1 + .../resources/certificates/truststore_invalid.pass | 1 + src/test/resources/logback-test.xml | 55 +++ .../pnfsimulator/simulator/filesystem/test1.json | 12 + .../simulator/invalidJsonStructureEvent.json | 1 + .../simulator/validExampleMeasurementEvent.json | 86 ++++ store/cert.p12 | Bin 0 -> 2685 bytes store/p12.pass | 1 + store/trust.jks | Bin 0 -> 1455 bytes store/truststore.pass | 1 + templates/cmNotification.json | 32 ++ templates/measurement.json | 44 ++ templates/notification.json | 42 ++ templates/notificationHttpServer.json | 52 +++ templates/registration.json | 33 ++ version.properties | 13 + 173 files changed, 12346 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 Makefile create mode 100644 README.md create mode 100644 certificates/AAF_RootCA.crt create mode 100644 certificates/dcaelocal.crt create mode 100644 config/config.json create mode 100644 config/mongo_db_schema_creation.py create mode 100644 config/requirements.txt create mode 100644 db/pnf_simulator.js create mode 100644 deployment/PnP_PNF_sim_heat_template.yml create mode 100644 docker-compose.yml create mode 100644 integration/pom.xml create mode 100644 integration/src/main/java/org/onap/pnfsimulator/integration/Main.java create mode 100644 integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.java create mode 100644 integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorService.java create mode 100644 integration/src/main/resources/application.properties create mode 100644 integration/src/main/resources/keystore create mode 100644 integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java create mode 100644 integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java create mode 100644 integration/src/test/java/org/onap/pnfsimulator/integration/SearchInTemplatesTest.java create mode 100644 integration/src/test/java/org/onap/pnfsimulator/integration/SingleEventTest.java create mode 100644 integration/src/test/java/org/onap/pnfsimulator/integration/TemplatesManagementTest.java create mode 100644 integration/src/test/java/org/onap/pnfsimulator/integration/TestConfiguration.java create mode 100644 integration/src/test/java/org/onap/pnfsimulator/integration/TestUtils.java create mode 100644 integration/src/test/java/org/onap/pnfsimulator/integration/VariablesReplacement.java create mode 100644 integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java create mode 100644 integration/src/test/resources/application.properties create mode 100644 integration/src/test/resources/templates/cmNotification.json create mode 100644 integration/src/test/resources/templates/notification.json create mode 100644 integration/src/test/resources/templates/overwrite_template.json create mode 100644 integration/src/test/resources/templates/overwritten_template.json create mode 100644 integration/src/test/resources/templates/registration.json create mode 100644 integration/src/test/resources/templates/search/complicated_template.json create mode 100644 integration/src/test/resources/templates/search/simple_template.json create mode 100644 integration/src/test/resources/templates/search/template_with_array.json create mode 100644 integration/src/test/resources/templates/search/template_with_booleans.json create mode 100644 integration/src/test/resources/templates/search/template_with_floats.json create mode 100644 integration/src/test/resources/templates/search/template_with_ints.json create mode 100644 integration/src/test/resources/templates/upload_template.json create mode 100644 lombok.config create mode 100644 pom.xml create mode 100644 src/assembly/resources.xml create mode 100644 src/main/java/org/onap/pnfsimulator/Main.java create mode 100644 src/main/java/org/onap/pnfsimulator/SwaggerConfig.java create mode 100644 src/main/java/org/onap/pnfsimulator/db/Row.java create mode 100644 src/main/java/org/onap/pnfsimulator/db/Storage.java create mode 100644 src/main/java/org/onap/pnfsimulator/event/EventData.java create mode 100644 src/main/java/org/onap/pnfsimulator/event/EventDataRepository.java create mode 100644 src/main/java/org/onap/pnfsimulator/event/EventDataService.java create mode 100644 src/main/java/org/onap/pnfsimulator/filesystem/WatcherConfig.java create mode 100644 src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java create mode 100644 src/main/java/org/onap/pnfsimulator/filesystem/WatcherService.java create mode 100644 src/main/java/org/onap/pnfsimulator/filesystem/WatcherThread.java create mode 100644 src/main/java/org/onap/pnfsimulator/logging/MdcVariables.java create mode 100644 src/main/java/org/onap/pnfsimulator/rest/SimulatorController.java create mode 100644 src/main/java/org/onap/pnfsimulator/rest/TemplateController.java create mode 100644 src/main/java/org/onap/pnfsimulator/rest/model/FullEvent.java create mode 100644 src/main/java/org/onap/pnfsimulator/rest/model/SearchExp.java create mode 100644 src/main/java/org/onap/pnfsimulator/rest/model/SimulatorParams.java create mode 100644 src/main/java/org/onap/pnfsimulator/rest/model/SimulatorRequest.java create mode 100644 src/main/java/org/onap/pnfsimulator/rest/model/TemplateRequest.java create mode 100644 src/main/java/org/onap/pnfsimulator/rest/util/DateUtil.java create mode 100644 src/main/java/org/onap/pnfsimulator/rest/util/JsonObjectDeserializer.java create mode 100644 src/main/java/org/onap/pnfsimulator/rest/util/ResponseBuilder.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/DbTemplateReader.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/EventNotFoundException.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/FilesystemTemplateReader.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/IncrementProvider.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/IncrementProviderImpl.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/JsonTokenProcessor.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/KeywordsExtractor.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandler.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandlerException.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/KeywordsValueProvider.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/SimulatorService.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/TemplatePatcher.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/TemplateReader.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/TemplateVariablesReplacer.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/client/HttpApacheResponseAdapterFactory.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapter.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImpl.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/client/HttpResponseAdapter.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertAuthSslContextFactory.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertificateReader.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactory.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacade.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverter.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactory.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslAuthenticationHelper.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/keywords/Keyword.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/keywords/NonParameterKeyword.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/keywords/SingleParameterKeyword.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeyword.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventJob.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventScheduler.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulator/scheduler/QuartzConfiguration.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfig.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigRepository.java create mode 100644 src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigService.java create mode 100644 src/main/java/org/onap/pnfsimulator/template/FsToDbTemplateSynchronizer.java create mode 100644 src/main/java/org/onap/pnfsimulator/template/Template.java create mode 100644 src/main/java/org/onap/pnfsimulator/template/TemplateRepository.java create mode 100644 src/main/java/org/onap/pnfsimulator/template/TemplateService.java create mode 100644 src/main/java/org/onap/pnfsimulator/template/search/IllegalJsonValueException.java create mode 100644 src/main/java/org/onap/pnfsimulator/template/search/JsonUtils.java create mode 100644 src/main/java/org/onap/pnfsimulator/template/search/TemplateSearchHelper.java create mode 100644 src/main/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilder.java create mode 100644 src/main/java/org/onap/pnfsimulator/template/search/viewmodel/FlatTemplateContent.java create mode 100644 src/main/java/org/onap/pnfsimulator/template/search/viewmodel/KeyValuePair.java create mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/logback.xml create mode 100644 src/test/java/org/onap/pnfsimulator/event/EventDataServiceTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/filesystem/InMemoryTemplateStorage.java create mode 100644 src/test/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessorTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/rest/SimulatorControllerTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/rest/TemplateControllerTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/rest/util/DateUtilTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/rest/util/ResponseBuilderTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/DbTemplateReaderTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/IncrementProviderImplTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomIntegerTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomStringTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidTimestampTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomIntegerTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomPrimitiveIntegerTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomStringTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampPrimitiveTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/KeywordsHandlerTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/KeywordsValueProviderTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/SimulatorServiceTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/TemplatePatcherTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/TemplateReaderTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/TemplateVariablesReplacerTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/client/HttpApacheResponseAdapterFactoryTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImplTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/client/HttpTestUtils.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertAuthSslContextFactoryTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacadeTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverterTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactoryTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeywordTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventJobTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventSchedulerTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigServiceTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/template/FsToDbTemplateSynchronizerTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/template/TemplateServiceTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/template/search/JsonUtilsTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/template/search/TemplateSearchHelperTest.java create mode 100644 src/test/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilderTest.java create mode 100644 src/test/resources/application.properties create mode 100644 src/test/resources/certificates/client.p12 create mode 100644 src/test/resources/certificates/client.pass create mode 100644 src/test/resources/certificates/client_invalid.pass create mode 100644 src/test/resources/certificates/truststore create mode 100644 src/test/resources/certificates/truststore.pass create mode 100644 src/test/resources/certificates/truststore_invalid.pass create mode 100644 src/test/resources/logback-test.xml create mode 100644 src/test/resources/org/onap/pnfsimulator/simulator/filesystem/test1.json create mode 100644 src/test/resources/org/onap/pnfsimulator/simulator/invalidJsonStructureEvent.json create mode 100644 src/test/resources/org/onap/pnfsimulator/simulator/validExampleMeasurementEvent.json create mode 100644 store/cert.p12 create mode 100644 store/p12.pass create mode 100644 store/trust.jks create mode 100644 store/truststore.pass create mode 100644 templates/cmNotification.json create mode 100644 templates/measurement.json create mode 100644 templates/notification.json create mode 100644 templates/notificationHttpServer.json create mode 100644 templates/registration.json create mode 100644 version.properties diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..01974a7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# Compiled class files +*.class + +# Log files +*.log + +# Environment configurations +.classpath +.project +.settings +.vscode +.idea +*.iml + +# folders +target +logs diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ae26b36 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM docker.io/openjdk:11-jre-slim +COPY --from=python:3.6 / / + +ARG VERSION=${version} + +ADD target/libs /app/libs +ADD config /opt/db/config +ADD ./templates /app/templates +ADD ./src/main/resources/application.properties /app/application.properties +ADD target/vesclient-${VERSION}.jar /app/vesclient.jar +CMD apk update +CMD apk add ca-certificates +RUN python -m pip install -r /opt/db/config/requirements.txt +ADD certificates /usr/local/share/ca-certificates/ +RUN update-ca-certificates +CMD python /opt/db/config/mongo_db_schema_creation.py \ + && if [ -f /app/store/trust.pass ]; then cp /app/store/trust.pass /app/store/truststore.pass; fi \ + && java -Dspring.config.location=file:/app/application.properties -cp /app/libs/*:/app/vesclient.jar org.onap.pnfsimulator.Main \ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b851bcb --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +all: start + +.PHONY: start + +start: + @echo "##### Start Ves client #####" + docker-compose up -d + @echo "##### DONE #####" + +stop: + @echo "##### Stop Ves client #####" + docker-compose down + @echo "##### DONE #####" diff --git a/README.md b/README.md new file mode 100644 index 0000000..fffb368 --- /dev/null +++ b/README.md @@ -0,0 +1,436 @@ +# VES Client 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 a possibility to build those +images locally. It can be achieved by invoking `mvn clean install -P docker` 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://: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 + variables - correct json containing variables to merge with patched 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 + } + } + }, + "variables": { + "dn":"Abcd", + "anyObject": { + "key": "value" + } + } + } + +*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://:5000/simulator/event*. +After sending event, response message from VES will be passed as response message from Simulator. +Thanks to that when sending one-time event user will receive information about request. +This is helpful when authentication fail or VES response with "Forbidden" when using http instead of https. +In a situation when given URL address is not pointing to VES, Simulator response with status ```421``` +and information about communication problem. + +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. + +### 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/{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 a valid JSON, thus no duplicated 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 does't 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" + } + } + } + +### In place variables support +Simulator supports dynamic keywords e.g. #dN to automatically substitute selected phrases in defined json schema. +Keywords have to be specified as separate json values, so no mixing keywords inside textual fields are acceptable. Current implementation +supports placing variables in json templates as well as in patches latter sent as part of the requests. + +####Example: + +Request: +```json +{ + "simulatorParams": { + "repeatCount": 1, + "repeatInterval": 1, + "vesServerUrl": "http://ves:5123" + }, + "templateName": "cmNotification.json", + "patch": {}, + "variables": { + "dN": "NRNB=5, NRCEL=1234", + "attributeList": { + "threshXHighQ": "50", + "threshXHighP": "52" + } + } +} +``` + +cmNotification.json template is installed automatically after startup of the simulator but can be found also in repository in 'templates' folder: +```json +{ + "event": { + "otherFields": { + "otherFieldsVersion": "3.0", + "jsonObjects": [ + { + "objectName": "CustomNotification", + "objectInstances": [ + { + "objectInstance": { + "cm3gppNotifyFields": { + "dN": "#dN", + "notificationType": "notifyMOIAttributeValueChange", + "notificationId": "notificationID123121312323", + "sourceIndicator": "sONOperation", + "eventTime": "#Timestamp", + "systemDN": "NRNB=5", + "attributeList": "#attributeList", + "correlatedNotifications": { + "notificationID-notifyMOIAttributeValueChange": "sONOperation" + }, + "additionalText": "sometext", + "cm3gppNotifyFieldsVersion": "1.0" + } + } + } + ] + } + ] + } + } +} +``` + +Expected output of such request (body of an event being send to a ves) should be as follows: +```json +{ + "event": { + "otherFields": { + "otherFieldsVersion": "3.0", + "jsonObjects": [{ + "objectName": "CustomNotification", + "objectInstances": [{ + "objectInstance": { + "cm3gppNotifyFields": { + "dN": "NRNB=5, NRCEL=1234", + "notificationType": "notifyMOIAttributeValueChange", + "notificationId": "notificationID123121312323", + "sourceIndicator": "sONOperation", + "eventTime": "1571306716", + "systemDN": "NRNB=5", + "attributeList": { + "threshXHighQ": "50", + "threshXHighP": "52" + }, + "correlatedNotifications": { + "notificationID-notifyMOIAttributeValueChange": "sONOperation" + }, + "additionalText": "sometext", + "cm3gppNotifyFieldsVersion": "1.0" + } + } + }] + }] + } + } +} +``` + +### 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://:5000/swagger-ui.html* + +### History +User is able to view events history. +In order to browse history, go to *http://: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. + +Certification loading can be disabled by setting environment variable ```USE_CERTIFICATE_FOR_AUTHORIZATION``` to false. +Once certificate are not used for authorization, user can set up VES url using username and password. + + { + "vesServerUrl": "http://:@:/eventListener/v7" + } + +## 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:1.0.1-SNAPSHOT. +To test your local changes before running integration tests please build project using: + + 'mvn clean install -P docerk' + +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.crt -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/``` + +#### Testing keystore with real/mocked ves server +```curl --cacert rootCA.crt --cert client.crt --key client.key https://VES_SECURED_URL -d "{}" -X POST -H "Content-type: application/json" -kv``` + +#### How to refresh configuration of app +Depending on 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.strictHostnameVerification=true (to disable/enable hostname verification) +- ssl.clientCertificatePath=/app/store/client.p12 (to replace with keystore file) +- ssl.clientCertificatePasswordPath=/app/store/keystore.pass (to replace with keystore password file) +- ssl.trustStorePath=/app/store/trustStore (to replace with truststore file) +- ssl.trustStorePasswordPath=/app/store/truststore.pass (to replace with truststore password file) +4. Refresh configuration by 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/certificates/AAF_RootCA.crt b/certificates/AAF_RootCA.crt new file mode 100644 index 0000000..e9a50d7 --- /dev/null +++ b/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/certificates/dcaelocal.crt b/certificates/dcaelocal.crt new file mode 100644 index 0000000..1be5a6f --- /dev/null +++ b/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/config/config.json b/config/config.json new file mode 100644 index 0000000..af45632 --- /dev/null +++ b/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/config/mongo_db_schema_creation.py b/config/mongo_db_schema_creation.py new file mode 100644 index 0000000..3e79805 --- /dev/null +++ b/config/mongo_db_schema_creation.py @@ -0,0 +1,48 @@ +## ============LICENSE_START======================================================= +## mongo_db_schema_creation +## ================================================================================ +## Copyright (C) 2020 Nokia. All rights reserved. +## ================================================================================ +## Licensed under the Apache License, Version 2.0 (the "License"); +## you may not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## ============LICENSE_END========================================================= + +from pymongo import MongoClient +import argparse + +parser = argparse.ArgumentParser(description='Script creates configuration in pnf simulator mongodb if it doesn\'t exists.') +args = parser.parse_args() + +MONGO_DB_PASSWORD = "zXcVbN123!" + +def create_db_with_user_permissions(client): + client.pnf_simulator.add_user( 'pnf_simulator_user', MONGO_DB_PASSWORD, roles= [{'role':'readWrite', 'db':'pnf_simulator'},{'role':'dbAdmin', 'db':'pnf_simulator'}]) + +def init_mongo_db(client, col_list): + if 'simulatorConfig' not in col_list: + client.pnf_simulator.simulatorConfig.insert_one({"vesServerUrl": "https://dcae-ves-collector.onap:8443/eventListener/v7"}) + if 'template' not in col_list: + client.pnf_simulator.create_collection('template') + if 'flatTemplatesView' not in col_list: + client.pnf_simulator.create_collection("flatTemplatesView", viewOn="template",pipeline=[{"$project":{"keyValues":{"$objectToArray": "$$ROOT.flatContent"}}}]) + + +if __name__ == "__main__": + client = MongoClient(host='mongo', + port=27017, + username='root', + password=MONGO_DB_PASSWORD, + authSource="admin") + col_list=client.pnf_simulator.list_collection_names() + create_db_with_user_permissions(client) + init_mongo_db(client, col_list) + print("Following colections are present in simualtor db: " , client.pnf_simulator.list_collection_names()) diff --git a/config/requirements.txt b/config/requirements.txt new file mode 100644 index 0000000..12a7e47 --- /dev/null +++ b/config/requirements.txt @@ -0,0 +1 @@ +pymongo==3.11.0 \ No newline at end of file diff --git a/db/pnf_simulator.js b/db/pnf_simulator.js new file mode 100644 index 0000000..f5a03c3 --- /dev/null +++ b/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/deployment/PnP_PNF_sim_heat_template.yml b/deployment/PnP_PNF_sim_heat_template.yml new file mode 100644 index 0000000..6f9b5f0 --- /dev/null +++ b/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/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2e1f3b7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,40 @@ +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: onap/org.onap.integration.nfsimulator.vesclient + ports: + - "5000:5000" + environment: + USE_CERTIFICATE_FOR_AUTHORIZATION: "true" + 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/integration/pom.xml b/integration/pom.xml new file mode 100644 index 0000000..e56d838 --- /dev/null +++ b/integration/pom.xml @@ -0,0 +1,128 @@ + + + + + 4.0.0 + + + org.onap.integration.nfsimulator + vesclient + 1.0.0-SNAPSHOT + ../../pom.xml + + + pnf-simulator-integration + 1.0.0-SNAPSHOT + vesclient-integration + + + + dl.bintray.com + https://dl.bintray.com/palantir/releases + + + + + 11 + 11 + 3.2.0 + 3.9.1 + + + + + + org.assertj + assertj-core + test + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + + io.rest-assured + rest-assured + ${rest-assured.version} + + + org.mongodb + mongo-java-driver + ${mongo-java-driver.version} + + + + org.springframework + spring-test + test + + + org.springframework.boot + spring-boot-starter-test + test + + + com.google.code.gson + gson + + + com.palantir.docker.compose + docker-compose-rule-junit4 + + + + + + + + + onap-license + none + + + onap-java-style + none + + + maven-checkstyle-plugin + 2.17 + + + org.apache.maven.plugins + maven-surefire-plugin + + + + **/*Suite.java + + + + + + diff --git a/integration/src/main/java/org/onap/pnfsimulator/integration/Main.java b/integration/src/main/java/org/onap/pnfsimulator/integration/Main.java new file mode 100644 index 0000000..7288c2a --- /dev/null +++ b/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/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.java b/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.java new file mode 100644 index 0000000..304df60 --- /dev/null +++ b/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.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.integration; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +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 static final Logger LOGGER = LoggerFactory.getLogger(VesSimulatorController.class); + private final VesSimulatorService vesSimulatorService; + private final Gson gson; + private final ResponseEntity response = ResponseEntity + .status(HttpStatus.ACCEPTED) + .body("Accepted"); + + @Autowired + public VesSimulatorController(VesSimulatorService vesSimulatorService, Gson gson) { + this.vesSimulatorService = vesSimulatorService; + this.gson = gson; + } + + @PostMapping("eventListener/v5") + public ResponseEntity sendEventToDmaapV5(@RequestBody String body) { + JsonObject jsonObject = getJsonObjectFromBody(body); + vesSimulatorService.sendEventToDmaapV5(jsonObject); + return response; + } + + @PostMapping("eventListener/v7") + public ResponseEntity sendEventToDmaapV7(@RequestBody String body) { + JsonObject jsonObject = getJsonObjectFromBody(body); + vesSimulatorService.sendEventToDmaapV7(jsonObject); + return response; + } + + private JsonObject getJsonObjectFromBody(@RequestBody String body) { + LOGGER.info(String.format("Received event: %s", body)); + return gson.fromJson(body, JsonObject.class); + } +} diff --git a/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorService.java b/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorService.java new file mode 100644 index 0000000..65e5d3e --- /dev/null +++ b/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/integration/src/main/resources/application.properties b/integration/src/main/resources/application.properties new file mode 100644 index 0000000..205ed95 --- /dev/null +++ b/integration/src/main/resources/application.properties @@ -0,0 +1 @@ +server.port=8000 \ No newline at end of file diff --git a/integration/src/main/resources/keystore b/integration/src/main/resources/keystore new file mode 100644 index 0000000..26a16f7 Binary files /dev/null and b/integration/src/main/resources/keystore differ diff --git a/integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java b/integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java new file mode 100644 index 0000000..323243c --- /dev/null +++ b/integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java @@ -0,0 +1,234 @@ +/*- + * ============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 static org.onap.pnfsimulator.integration.TestUtils.getCurrentIpAddress; + +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 io.restassured.response.Response; +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.http.HttpStatus; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = WebEnvironment.DEFINED_PORT) +public class BasicAvailabilityTest { + + private static final int VERIFICATION_TIMEOUT_MILLIS = 10000; + + @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(HttpStatus.BAD_REQUEST.value()) + .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 parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(startUrl) + .then() + .statusCode(HttpStatus.OK.value()) + .body("message", equalTo("Request started")); + + Mockito.verify(vesSimulatorService, + Mockito.timeout(VERIFICATION_TIMEOUT_MILLIS)) + .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(HttpStatus.OK.value()) + .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 parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + Path newFile = Files.createFile(Paths.get("..", "templates", fileName)); + Files.write(newFile, templateBody.getBytes()); + + Response postResponse = given() + .contentType("application/json") + .body(requestBody) + .when() + .post(prepareRequestUrl(ACTION_START)); + + Files.delete(newFile); + + //then + assertThat(postResponse.statusCode()).isEqualTo(HttpStatus.OK.value()); + Mockito.verify(vesSimulatorService, Mockito.timeout(VERIFICATION_TIMEOUT_MILLIS)) + .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 parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(startUrl) + .then() + .statusCode(HttpStatus.OK.value()) + .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; + } + +} diff --git a/integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java b/integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java new file mode 100644 index 0000000..50ad1cd --- /dev/null +++ b/integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java @@ -0,0 +1,161 @@ +/*- + * ============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 static org.onap.pnfsimulator.integration.TestUtils.COMMON_EVENT_HEADER; +import static org.onap.pnfsimulator.integration.TestUtils.PATCHED; +import static org.onap.pnfsimulator.integration.TestUtils.SINGLE_EVENT_URL; +import static org.onap.pnfsimulator.integration.TestUtils.findSourceNameInMongoDB; +import static org.onap.pnfsimulator.integration.TestUtils.getCurrentIpAddress; + +import com.google.gson.JsonObject; +import java.time.Instant; +import java.net.UnknownHostException; + +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.http.HttpStatus; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = WebEnvironment.DEFINED_PORT) +public class OptionalTemplatesTest { + + @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 parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(SINGLE_EVENT_URL) + .then() + .statusCode(HttpStatus.ACCEPTED.value()) + .body("message", equalTo("Accepted")); + + //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()).hasSize(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 parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(SINGLE_EVENT_URL) + .then() + .statusCode(HttpStatus.ACCEPTED.value()) + .body("message", equalTo("Accepted")); + + //then + Mockito.verify(vesSimulatorService, + Mockito.timeout(3000)) + .sendEventToDmaapV5(parameterCaptor.capture()); + + Document sourceNameInMongoDB = findSourceNameInMongoDB(); + Assertions.assertThat(sourceNameInMongoDB.get(PATCHED)) + .isEqualTo("{\"commonEventHeader\":{\"sourceName\":\"HistoricalEvent\",\"version\":3}}"); + } + +} diff --git a/integration/src/test/java/org/onap/pnfsimulator/integration/SearchInTemplatesTest.java b/integration/src/test/java/org/onap/pnfsimulator/integration/SearchInTemplatesTest.java new file mode 100644 index 0000000..9d4ff3b --- /dev/null +++ b/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/integration/src/test/java/org/onap/pnfsimulator/integration/SingleEventTest.java b/integration/src/test/java/org/onap/pnfsimulator/integration/SingleEventTest.java new file mode 100644 index 0000000..3ad1385 --- /dev/null +++ b/integration/src/test/java/org/onap/pnfsimulator/integration/SingleEventTest.java @@ -0,0 +1,151 @@ +/*- + * ============LICENSE_START======================================================= + * Simulator + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.integration; + +import com.google.gson.JsonObject; +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.http.HttpStatus; +import org.springframework.test.context.junit4.SpringRunner; + +import java.net.UnknownHostException; +import java.util.List; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.stringContainsInOrder; +import static org.onap.pnfsimulator.integration.TestUtils.PATCHED; +import static org.onap.pnfsimulator.integration.TestUtils.SINGLE_EVENT_URL; +import static org.onap.pnfsimulator.integration.TestUtils.findSourceNameInMongoDB; +import static org.onap.pnfsimulator.integration.TestUtils.getCurrentIpAddress; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +public class SingleEventTest { + + @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 whenTriggeredSimulatorWithWrongVesAddressInformationShouldBeReturned() { + //given + String body = "{\n" + + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + ":8080/ves-simulator/eventListener/v5\",\n" + + "\"event\": { \n" + + "\"commonEventHeader\": {\n" + + "\"sourceName\": \"HistoricalEvent\",\n" + + "\"version\": 3" + + "}\n" + + "}\n" + + "}"; + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(SINGLE_EVENT_URL) + .then() + .statusCode(421) + .body("message", + equalTo( + "Fail to connect with ves: Connect to "+currentVesSimulatorIp+":8080 " + + "[/"+currentVesSimulatorIp+"] " + + "failed: Connection refused (Connection refused)")); + } + + @Test + public void whenTriggeredSimulatorWithWrongEventShouldReturnedError() { + //given + String body = "{\n" + + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n" + + "\"event\": { \n" + + "this is not JSON {}" + + "}\n" + + "}"; + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(SINGLE_EVENT_URL) + .then() + .statusCode(HttpStatus.BAD_REQUEST.value()) + .body("message", + stringContainsInOrder(List.of("JSON parse error:","Unexpected character ('t' (code 116)):")) + ); + } + + @Test + public void whenTriggeredSimulatorWithUsernameAndPasswordInUrlVesShouldAcceptRequest() throws UnknownHostException { + //given + String body = "{\n" + + "\"vesServerUrl\": \"https://user1:pass1@" + currentVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n" + + "\"event\": { \n" + + "\"commonEventHeader\": {\n" + + "\"sourceName\": \"HistoricalEvent\",\n" + + "\"version\": 3" + + "}\n" + + "}\n" + + "}"; + ArgumentCaptor parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + //when + given() + .contentType("application/json") + .body(body) + .when() + .post(SINGLE_EVENT_URL) + .then() + .statusCode(HttpStatus.ACCEPTED.value()) + .body("message", equalTo("Accepted")); + + //then + Mockito.verify(vesSimulatorService, + Mockito.timeout(3000)) + .sendEventToDmaapV5(parameterCaptor.capture()); + + Document sourceNameInMongoDB = findSourceNameInMongoDB(); + Assertions.assertThat(sourceNameInMongoDB.get(PATCHED)) + .isEqualTo("{\"commonEventHeader\":{\"sourceName\":\"HistoricalEvent\",\"version\":3}}"); + } +} diff --git a/integration/src/test/java/org/onap/pnfsimulator/integration/TemplatesManagementTest.java b/integration/src/test/java/org/onap/pnfsimulator/integration/TemplatesManagementTest.java new file mode 100644 index 0000000..7e74dd4 --- /dev/null +++ b/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 registration = readTemplateFromResources(REGISTRATION_JSON).getMap(CONTENT); + Map notification = readTemplateFromResources(NOTIFICATION_JSON).getMap(CONTENT); + + given() + .when() + .get(prepareRequestUrl(LIST_URL)) + .then() + .statusCode(200) + .body(CONTENT, Matchers.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/integration/src/test/java/org/onap/pnfsimulator/integration/TestConfiguration.java b/integration/src/test/java/org/onap/pnfsimulator/integration/TestConfiguration.java new file mode 100644 index 0000000..19ae050 --- /dev/null +++ b/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/integration/src/test/java/org/onap/pnfsimulator/integration/TestUtils.java b/integration/src/test/java/org/onap/pnfsimulator/integration/TestUtils.java new file mode 100644 index 0000000..f7df5e9 --- /dev/null +++ b/integration/src/test/java/org/onap/pnfsimulator/integration/TestUtils.java @@ -0,0 +1,57 @@ +package org.onap.pnfsimulator.integration; + +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 org.bson.Document; + +import java.net.Inet4Address; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Collections; + +public class TestUtils { + + private TestUtils() {} + + public static final String PNF_SIMULATOR_DB = "pnf_simulator"; + public static final String COMMON_EVENT_HEADER = "commonEventHeader"; + public static final String PNF_SIMULATOR_DB_PSWD = "zXcVbN123!"; + public static final String PNF_SIMULATOR_DB_USER = "pnf_simulator_user"; + public static final String PATCHED = "patched"; + public static final String SINGLE_EVENT_URL = "http://0.0.0.0:5000/simulator/event"; + + public static 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 table = pnfSimulatorDb.getCollection("eventData"); + Document searchQuery = new Document(); + searchQuery.put(PATCHED, new Document("$regex", ".*" + "HistoricalEvent" + ".*")); + FindIterable findOfPatched = table.find(searchQuery); + Document dbObject = null; + MongoCursor cursor = findOfPatched.iterator(); + if (cursor.hasNext()) { + dbObject = cursor.next(); + } + return dbObject; + } + + public static 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/integration/src/test/java/org/onap/pnfsimulator/integration/VariablesReplacement.java b/integration/src/test/java/org/onap/pnfsimulator/integration/VariablesReplacement.java new file mode 100644 index 0000000..ae7970c --- /dev/null +++ b/integration/src/test/java/org/onap/pnfsimulator/integration/VariablesReplacement.java @@ -0,0 +1,80 @@ +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 static org.onap.pnfsimulator.integration.TestUtils.getCurrentIpAddress; + +import com.google.gson.JsonObject; +import java.net.Inet4Address; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Collections; +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.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Main.class, TestConfiguration.class}, + webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +public class VariablesReplacement { + + @Autowired + private VesSimulatorService vesSimulatorService; + + private String currentVesSimulatorIp; + + @Before + public void setUp() throws Exception { + currentVesSimulatorIp = getCurrentIpAddress(); + } + + @Test + public void whenTriggeredSimulatorShouldReplaceStringKeyword() { + String startUrl = prepareRequestUrl(); + String body = "{\n" + "\"templateName\": \"cmNotification.json\",\n" + "\"patch\":{},\n" + "\"variables\":{\n" + + "\"dN\": \"NRNB=5, NRCEL=1234\",\n" + "\"attributeList\":{\n" + + "\"threshXHighQ\": \"50\",\n" + "\"threshXHighP\": \"52\"\n" + "}\n" + "},\n" + + "\"simulatorParams\": {\n" + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + + ":9443/ves-simulator/eventListener/v5\",\n" + "\"repeatInterval\": 1,\n" + + "\"repeatCount\": 1\n" + "}\n" + "}"; + ArgumentCaptor parameterCaptor = ArgumentCaptor.forClass(JsonObject.class); + + 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()); + + assertAttributeList(parameterCaptor); + assertDn(parameterCaptor); + } + + private void assertDn(ArgumentCaptor parameterCaptor) { + String dn = parameterCaptor.getValue().getAsJsonObject("event").getAsJsonObject("otherFields") + .getAsJsonArray("jsonObjects").get(0) + .getAsJsonObject().getAsJsonArray("objectInstances") + .get(0).getAsJsonObject().getAsJsonObject("objectInstance") + .getAsJsonObject("cm3gppNotifyFields").getAsJsonPrimitive("dN").getAsString(); + assertThat(dn).isEqualTo("NRNB=5, NRCEL=1234"); + } + + private void assertAttributeList(ArgumentCaptor parameterCaptor) { + JsonObject attributeList = parameterCaptor.getValue().getAsJsonObject("event").getAsJsonObject("otherFields") + .getAsJsonArray("jsonObjects").get(0).getAsJsonObject() + .getAsJsonArray("objectInstances").get(0).getAsJsonObject() + .getAsJsonObject("objectInstance").getAsJsonObject("cm3gppNotifyFields") + .getAsJsonObject("attributeList"); + assertThat(attributeList.get("threshXHighQ").getAsString()).isEqualTo("50"); + assertThat(attributeList.get("threshXHighP").getAsString()).isEqualTo("52"); + } + + private String prepareRequestUrl() { + return "http://0.0.0.0:5000/simulator/start"; + } + +} diff --git a/integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java b/integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java new file mode 100644 index 0000000..f6a4c24 --- /dev/null +++ b/integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java @@ -0,0 +1,90 @@ +/*- + * ============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.BeforeClass; +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.SingleEventTest; +import org.onap.pnfsimulator.integration.TemplatesManagementTest; +import org.onap.pnfsimulator.integration.VariablesReplacement; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; + +import static io.restassured.RestAssured.given; + +@RunWith(Suite.class) +@SuiteClasses({BasicAvailabilityTest.class, TemplatesManagementTest.class, OptionalTemplatesTest.class, + SearchInTemplatesTest.class, VariablesReplacement.class, SingleEventTest.class}) +public class DockerBasedTestsSuite { + + private static final Logger LOGGER = LoggerFactory.getLogger(DockerBasedTestsSuite.class); + + private static final String HEALTH_CHECK_ADDRESS = "http://0.0.0.0:5000/health"; + private static final int RETRY_COUNT = 10; + private static final int RETRY_INTERVAL = 1000; + + @ClassRule + public static DockerComposeRule docker = DockerComposeRule.builder() + .file("../docker-compose.yml") + .waitingForService("pnf-simulator", HealthChecks.toHaveAllPortsOpen()) + .waitingForService("mongo", HealthChecks.toHaveAllPortsOpen()) + .build(); + + @BeforeClass + public static void waitForPnfSimulatorToBeHealthy() throws InterruptedException { + boolean isHealthy = false; + int retry = 0; + while (!isHealthy && retry < RETRY_COUNT) { + retry++; + LOGGER.info("Checking PNF health, try {} out of {}", retry, RETRY_COUNT); + isHealthy = performHealthCheck(); + if (isHealthy) { + LOGGER.info("PNF is healthy"); + } else { + LOGGER.info("PNF no healthy retrying in {}", RETRY_COUNT); + Thread.sleep(RETRY_INTERVAL); + } + } + } + + private static boolean performHealthCheck() { + boolean isUp = false; + try { + int statusCode = given().get(HEALTH_CHECK_ADDRESS).getStatusCode(); + if (statusCode == HttpStatus.OK.value()) { + isUp = true; + } + } catch (Exception e) { + e.printStackTrace(); + } + return isUp; + } + +} diff --git a/integration/src/test/resources/application.properties b/integration/src/test/resources/application.properties new file mode 100644 index 0000000..c3e1472 --- /dev/null +++ b/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/integration/src/test/resources/templates/cmNotification.json b/integration/src/test/resources/templates/cmNotification.json new file mode 100644 index 0000000..750ce30 --- /dev/null +++ b/integration/src/test/resources/templates/cmNotification.json @@ -0,0 +1,32 @@ +{ + "event": { + "otherFields": { + "otherFieldsVersion": "3.0", + "jsonObjects": [ + { + "objectName": "CustomNotification", + "objectInstances": [ + { + "objectInstance": { + "cm3gppNotifyFields": { + "dN": "#dN", + "notificationType": "notifyMOIAttributeValueChange", + "notificationId": "notificationID123121312323", + "sourceIndicator": "sONOperation", + "eventTime": "#Timestamp", + "systemDN": "NRNB=5", + "attributeList": "#attributeList", + "correlatedNotifications": { + "notificationID-notifyMOIAttributeValueChange": "sONOperation" + }, + "additionalText": "sometext", + "cm3gppNotifyFieldsVersion": "1.0" + } + } + } + ] + } + ] + } + } +} diff --git a/integration/src/test/resources/templates/notification.json b/integration/src/test/resources/templates/notification.json new file mode 100644 index 0000000..0b4ff2e --- /dev/null +++ b/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/integration/src/test/resources/templates/overwrite_template.json b/integration/src/test/resources/templates/overwrite_template.json new file mode 100644 index 0000000..55bf763 --- /dev/null +++ b/integration/src/test/resources/templates/overwrite_template.json @@ -0,0 +1,6 @@ +{ + "name": "overwrite_template.json", + "template": { + "field1": "field1" + } +} diff --git a/integration/src/test/resources/templates/overwritten_template.json b/integration/src/test/resources/templates/overwritten_template.json new file mode 100644 index 0000000..28e7381 --- /dev/null +++ b/integration/src/test/resources/templates/overwritten_template.json @@ -0,0 +1,6 @@ +{ + "id": "overwrite_template.json", + "content": { + "field1": "overwritten_field1" + } +} diff --git a/integration/src/test/resources/templates/registration.json b/integration/src/test/resources/templates/registration.json new file mode 100644 index 0000000..8b7908e --- /dev/null +++ b/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/integration/src/test/resources/templates/search/complicated_template.json b/integration/src/test/resources/templates/search/complicated_template.json new file mode 100644 index 0000000..962600d --- /dev/null +++ b/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/integration/src/test/resources/templates/search/simple_template.json b/integration/src/test/resources/templates/search/simple_template.json new file mode 100644 index 0000000..d209a9e --- /dev/null +++ b/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/integration/src/test/resources/templates/search/template_with_array.json b/integration/src/test/resources/templates/search/template_with_array.json new file mode 100644 index 0000000..0ed4326 --- /dev/null +++ b/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/integration/src/test/resources/templates/search/template_with_booleans.json b/integration/src/test/resources/templates/search/template_with_booleans.json new file mode 100644 index 0000000..4954663 --- /dev/null +++ b/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/integration/src/test/resources/templates/search/template_with_floats.json b/integration/src/test/resources/templates/search/template_with_floats.json new file mode 100644 index 0000000..2b8caf4 --- /dev/null +++ b/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/integration/src/test/resources/templates/search/template_with_ints.json b/integration/src/test/resources/templates/search/template_with_ints.json new file mode 100644 index 0000000..369b0b4 --- /dev/null +++ b/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/integration/src/test/resources/templates/upload_template.json b/integration/src/test/resources/templates/upload_template.json new file mode 100644 index 0000000..df3ae28 --- /dev/null +++ b/integration/src/test/resources/templates/upload_template.json @@ -0,0 +1,6 @@ +{ + "name": "upload_template.json", + "template": { + "field1": "field1" + } +} diff --git a/lombok.config b/lombok.config new file mode 100644 index 0000000..a23edb4 --- /dev/null +++ b/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling = true +lombok.addLombokGeneratedAnnotation = true \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..546d44a --- /dev/null +++ b/pom.xml @@ -0,0 +1,498 @@ + + + + + + 4.0.0 + + + org.onap.oparent + oparent + 2.1.0 + + + org.onap.integration.simulators.nf-simulator.ves-client + vesclient + 1.0.0-SNAPSHOT + + vesclient + + + UTF-8 + 11 + 11 + yyyyMMdd'T'HHmmss + org.onap.pnfsimulator.Main + latest + libs + ${project.build.directory}/${dependency.directory.name} + + nexus3.onap.org:10003 + http://nexus3.onap.org + 3.7.0 + 3.0.2 + 2.2.4 + 2.19 + 1.1.1 + + + https://nexus.onap.org + /content/repositories/snapshots/ + /content/repositories/releases/ + /content/repositories/staging/ + onap + org.onap.integration.nfsimulator + UTF-8 + 11 + 11 + 0.31.0 + true + ${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml + + + + + 2.17 + 0.31.0 + 2.1.6.RELEASE + 2.1.6.RELEASE + 2.1.6.RELEASE + 2.1.0.RELEASE + 2.1.0.RELEASE + 2.1.4.RELEASE + 1.18.2 + 1.0 + 2.2.7.RELEASE + 1.4 + 1.1 + 4.5.6 + 4.5.6 + 2.9.2 + 2.9.2 + 1.2.3 + 1.7.25 + 2.6 + 20180130 + 2.8.2 + 3.7 + 2.9.7 + 2.9.7 + 0.9.2 + 0.9.2 + 2.2.1 + 2.2.1 + 21.0 + 1.2.3 + 3.7.0.1746 + + + + 3.9.1 + 2.18.3 + 5.3.1 + 5.3.1 + 4.12 + 2.1.6.RELEASE + 2.2.7.RELEASE + 0.1.0 + 0.34.0 + 5.0.4.RELEASE + 5.1.0 + 1.5.0 + + true + false + + + + + + + + + org.springframework.boot + spring-boot-starter + ${spring-boot-starter.version} + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-web + ${spring-boot-starter-web.version} + + + org.springframework.boot + spring-boot-starter-data-mongodb + ${spring-boot-starter-data-mongodb.version} + + + + + + + + org.springframework.cloud + spring-cloud-config-client + ${spring-cloud-config-client.version} + + + org.projectlombok + lombok + provided + ${lombok.version} + + + ch.qos.logback + logback-classic + ${logback-classic.version} + + + + + + + + + + + + + + + + + + org.json + json + ${json.version} + + + com.google.code.gson + gson + ${gson.version} + + + org.apache.httpcomponents + httpclient + ${apache.httpclient.version} + + + + + + + + + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + + + + + + + + + + io.vavr + vavr-match + ${vavr-match.version} + + + io.vavr + vavr + ${vavr.version} + + + io.springfox + springfox-swagger2 + ${springfox-swagger2.version} + + + io.springfox + springfox-swagger-ui + ${springfox-swagger-ui.version} + + + org.quartz-scheduler + quartz + ${quartz.version} + + + org.quartz-scheduler + quartz-jobs + ${quartz-jobs.version} + + + + + + org.junit.jupiter + junit-jupiter-engine + test + ${junit-jupiter-engine.version} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.springframework.boot + spring-boot-starter-test + test + ${spring.boot.version} + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + src/assembly/resources.xml + ${project.artifactId}-${project.version} + + + + package + + single + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + true + true + + + + org.apache.maven.plugins + maven-jar-plugin + ${maven-jar-plugin.version} + + + + ${simulator.main.class} + ${maven.build.timestamp} + + + + + + pl.project13.maven + git-commit-id-plugin + ${git-commit-id-plugin.version} + + + get-commit-info + + revision + + + + + ${project.basedir}/.git + true + git.commit.id.abbrev + + + + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + org.junit.platform + junit-platform-surefire-provider + ${junit-platform-surefire-provider.version} + + + + ${skip-unit-tests} + true + true + false + + + + org.apache.maven.plugins + maven-dependency-plugin + + ${dependency.directory.location} + runtime + true + + + + copy-external-dependencies + package + + copy-dependencies + + + + + + org.jacoco + jacoco-maven-plugin + + + prepare-agent + + prepare-agent + + + + report + + report + + + ${project.build.directory}/code-coverage/jacoco.exec + ${project.reporting.outputDirectory}/jacoco-ut + + + + + + + + + docker + + false + + + linux + x86_64 + ${os.detected.name}-${os.detected.arch} + + + + + io.fabric8 + docker-maven-plugin + ${docker-maven-plugin.version} + + + docker-build-image + package + + build + + + + docker-push-image + deploy + + push + + + + + ${skipDockerPush} + true + IfNotPresent + + + ${project.artifactId} + ${docker-image.namespace}/${docker-image.name.prefix}.${artifactId} + ${onap.nexus.dockerregistry.daily} + + ${project.basedir} + + ${project.version}-STAGE-${maven.build.timestamp}Z + + + + + + + + + + + + + + ecomp-releases + Integration simulators Release Repository + ${nexusproxy}${releaseNexusPath} + + + ecomp-snapshots + Integration simulators Snapshot Repository + ${nexusproxy}${snapshotNexusPath} + + + ecomp-site + dav:${nexusproxy}${sitePath} + + + + diff --git a/src/assembly/resources.xml b/src/assembly/resources.xml new file mode 100644 index 0000000..35dd3b2 --- /dev/null +++ b/src/assembly/resources.xml @@ -0,0 +1,57 @@ + + + + resources + + zip + + + + + + simulator.sh + + unix + 0755 + + + + docker-compose.yml + + unix + 0644 + + + config + config + + **/* + + + + deployment + deployment + + **/* + + + + diff --git a/src/main/java/org/onap/pnfsimulator/Main.java b/src/main/java/org/onap/pnfsimulator/Main.java new file mode 100644 index 0000000..708f27f --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/Main.java @@ -0,0 +1,59 @@ +/* + * ============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; + } + + // We are excluding this line in Sonar due to fact that + // Spring is handling arguments + public static void main(String[] args) { // NOSONAR + SpringApplication.run(Main.class, args); + } + + @PostConstruct + public void createWatchers() { + fsToDbTemplateSynchronizer.synchronize(); + watcherService.createWatcher(); + } +} + + diff --git a/src/main/java/org/onap/pnfsimulator/SwaggerConfig.java b/src/main/java/org/onap/pnfsimulator/SwaggerConfig.java new file mode 100644 index 0000000..b6c6187 --- /dev/null +++ b/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/src/main/java/org/onap/pnfsimulator/db/Row.java b/src/main/java/org/onap/pnfsimulator/db/Row.java new file mode 100644 index 0000000..12745bf --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/db/Row.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.db; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Field; + +public abstract class Row { + @Id + @Field("_id") + @Getter + @Setter + private String id; + + + public String getId() { + return id; + } +} diff --git a/src/main/java/org/onap/pnfsimulator/db/Storage.java b/src/main/java/org/onap/pnfsimulator/db/Storage.java new file mode 100644 index 0000000..ad98ce0 --- /dev/null +++ b/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 { + + List getAll(); + + Optional get(String rowId); + + void persist(T row); + + boolean tryPersistOrOverwrite(T row, boolean overwrite); + + void delete(String rowId); + + List getIdsByContentCriteria(JsonObject queryJson); +} diff --git a/src/main/java/org/onap/pnfsimulator/event/EventData.java b/src/main/java/org/onap/pnfsimulator/event/EventData.java new file mode 100644 index 0000000..ff85367 --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/event/EventData.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.event; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Field; + +@Builder +@Getter +@Setter +@ToString(exclude = "incrementValue") +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; + } +} diff --git a/src/main/java/org/onap/pnfsimulator/event/EventDataRepository.java b/src/main/java/org/onap/pnfsimulator/event/EventDataRepository.java new file mode 100644 index 0000000..d1a66ab --- /dev/null +++ b/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 { +} diff --git a/src/main/java/org/onap/pnfsimulator/event/EventDataService.java b/src/main/java/org/onap/pnfsimulator/event/EventDataService.java new file mode 100644 index 0000000..266d56b --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/event/EventDataService.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.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 getAllEvents() { + return repository.findAll(); + } + + public Optional getById(String id) { + return repository.findById(id); + } +} diff --git a/src/main/java/org/onap/pnfsimulator/filesystem/WatcherConfig.java b/src/main/java/org/onap/pnfsimulator/filesystem/WatcherConfig.java new file mode 100644 index 0000000..3535e33 --- /dev/null +++ b/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/src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java b/src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java new file mode 100644 index 0000000..c03491a --- /dev/null +++ b/src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java @@ -0,0 +1,111 @@ +/*- + * ============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.BSONException; +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