summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore124
-rw-r--r--INFO.yaml86
-rw-r--r--components/bbs-event-processor/LICENSE.txt36
-rw-r--r--components/bbs-event-processor/README.md76
-rw-r--r--components/bbs-event-processor/dpo/blueprints/bbs-event-processor-input.yaml29
-rw-r--r--components/bbs-event-processor/dpo/blueprints/k8s-bbs-event-processor.yaml-template164
-rw-r--r--components/bbs-event-processor/dpo/data-formats/aai-interaction.json11
-rw-r--r--components/bbs-event-processor/dpo/data-formats/pnf-reregistration.json11
-rw-r--r--components/bbs-event-processor/dpo/spec/bbs-event-processor-spec.json307
-rw-r--r--components/bbs-event-processor/pom.xml421
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/Application.java84
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/AaiClientConfiguration.java74
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/AaiClientProperties.java66
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ApplicationConfiguration.java398
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ApplicationConstants.java39
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ConfigurationChangeObservable.java41
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ConfigurationChangeObserver.java29
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ConsulConfigurationGateway.java279
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/DmaapCpeAuthenticationConsumerProperties.java71
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/DmaapProducerProperties.java62
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/DmaapReRegistrationConsumerProperties.java71
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/GenericProperties.java87
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/SecurityProperties.java53
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/SwaggerConfiguration.java83
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/controllers/BbsEventProcessorController.java203
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/AaiTaskException.java28
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/ApplicationEnvironmentException.java28
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/ConfigurationParsingException.java28
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/DmaapException.java28
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/EmptyDmaapResponseException.java32
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/AuthenticationState.java40
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/ControlLoopPublisherDmaapModel.java75
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/CpeAuthenticationConsumerDmaapModel.java53
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/GeneratedAppConfigObject.java165
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/MetadataListAaiObject.java48
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/PnfAaiObject.java47
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/ReRegistrationConsumerDmaapModel.java48
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/RelationshipListAaiObject.java82
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/ServiceInstanceAaiObject.java45
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/pipelines/CpeAuthenticationPipeline.java333
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/pipelines/ReRegistrationPipeline.java347
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/pipelines/Scheduler.java245
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/AaiClientTask.java33
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/AaiClientTaskImpl.java63
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapCpeAuthenticationConsumerTask.java32
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapCpeAuthenticationConsumerTaskImpl.java113
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapPublisherTask.java31
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapPublisherTaskImpl.java94
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapReRegistrationConsumerTask.java32
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapReRegistrationConsumerTaskImpl.java113
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/AaiReactiveClient.java197
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CommonEventFields.java33
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ControlLoopJsonBodyBuilder.java59
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationDmaapConsumerJsonParser.java187
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationEventFields.java35
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationJsonBodyBuilder.java52
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/LoggingUtil.java54
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ReRegistrationDmaapConsumerJsonParser.java171
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ReRegistrationEventFields.java33
-rw-r--r--components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ReRegistrationJsonBodyBuilder.java51
-rw-r--r--components/bbs-event-processor/src/main/resources/application.yml79
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/AaiClientPropertiesTest.java70
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/ApplicationConfigurationTest.java375
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/ConsulConfigurationGatewayTest.java215
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/DmaapCpeAuthenticationConsumerPropertiesTest.java68
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/DmaapProducerPropertiesTest.java60
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/DmaapReRegistrationConsumerPropertiesTest.java68
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/GenericPropertiesTest.java77
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/SecurityPropertiesTest.java63
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/controllers/BbsEventProcessorControllerTest.java163
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/model/GsonSerializationsTest.java379
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/pipelines/CpeAuthenticationPipelineTest.java668
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/pipelines/ReRegistrationPipelineTest.java757
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/pipelines/SchedulerTest.java189
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/AaiClientTaskImplTest.java239
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/DmaapCpeAuthenticationConsumerTaskImplTest.java149
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/DmaapPublisherTaskImplTest.java173
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/DmaapReRegistrationConsumerTaskImplTest.java147
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/utilities/AaiReactiveClientTest.java257
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationDmaapConsumerJsonParserTest.java311
-rw-r--r--components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/utilities/ReRegistrationDmaapConsumerJsonParserTest.java297
-rw-r--r--components/bbs-event-processor/src/test/resources/logback-test.xml24
-rw-r--r--components/bbs-event-processor/version.properties6
-rw-r--r--pom.xml43
-rw-r--r--version.properties6
85 files changed, 10843 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..4ec8d6b6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,124 @@
+# Created by https://www.gitignore.io/api/java,maven,intellij
+# Edit at https://www.gitignore.io/?templates=java,maven,intellij
+
+### Intellij ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+.idea
+*.iml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### Intellij Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+# Sonarlint plugin
+.idea/sonarlint
+
+### Java ###
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+### Maven ###
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+.mvn/wrapper/maven-wrapper.jar
+
+# End of https://www.gitignore.io/api/java,maven,intellij
+
diff --git a/INFO.yaml b/INFO.yaml
new file mode 100644
index 00000000..df4239fa
--- /dev/null
+++ b/INFO.yaml
@@ -0,0 +1,86 @@
+---
+project: 'dcaegen2-services'
+project_creation_date: '2017-05-17'
+project_category: ''
+lifecycle_state: 'Incubation'
+project_lead: &onap_dcaegen2_ptl
+ name: 'Vijay Venkatesh Kumar'
+ email: 'vv770d@att.com'
+ id: 'vv770d'
+ company: 'ATT'
+ timezone: 'America/New_York'
+primary_contact: *onap_dcaegen2_ptl
+issue_tracking:
+ type: 'jira'
+ url: 'https://jira.onap.org/projects/DCAEGEN2'
+ key: 'DCAEGEN2'
+mailing_list:
+ type: 'groups.io'
+ url: 'lists.onap.org'
+ tag: '<[sub-project_name]>'
+realtime_discussion: ''
+meetings:
+ - type: 'zoom'
+ agenda: 'https://wiki.onap.org/display/DW/DCAE+Project+Meetings'
+ url: 'https://wiki.onap.org/pages/viewpage.action?pageId=6593119'
+ server: 'n/a'
+ channel: 'n/a'
+ repeats: 'weekly'
+ time: '13:00-14:00 UTC (DST), 15:30-16:30 UTC (post DST)'
+repositories:
+ - 'dcaegen2-services'
+committers:
+ - <<: *onap_dcaegen2_ptl
+ - name: 'Lusheng Ji'
+ email: 'lji@research.att.com'
+ company: 'ATT'
+ id: 'wrider'
+ timezone: 'America/New_York'
+ - name: 'Michael Hwang'
+ email: 'mhwang@research.att.com'
+ company: 'ATT'
+ id: 'researchmike'
+ timezone: 'America/New_York'
+ - name: 'Tony Hansen'
+ email: 'tony@att.com'
+ company: 'ATT'
+ id: 'TonyLHansen'
+ timezone: 'America/New_York'
+ - name: 'Yan Yang'
+ email: 'yangyanyj@chinamobile.com'
+ company: 'ChinaMobile'
+ id: 'yangyan'
+ timezone: 'Asia/Shanghai'
+ - name: 'Xinhui Li'
+ email: 'lxinhui@vmware.com'
+ company: 'VMware'
+ id: 'xinhuili'
+ timezone: 'Asia/Shanghai'
+ - name: 'Jack Lucas'
+ email: 'jflucas@research.att.com'
+ company: 'ATT'
+ id: 'jflucas'
+ timezone: 'America/New_York'
+ - name: 'Piotr Jaszczyk'
+ email: 'piotr.jaszczyk@nokia.com'
+ company: 'Nokia'
+ id: 'jaszczur'
+ timezone: 'Europe/Warsaw'
+ - name: 'Piotr Wielebski'
+ email: 'piotr.wielebski@nokia.com'
+ company: 'Nokia'
+ id: 'pwielebs'
+ timezone: 'Europe/Warsaw'
+ - name: 'Henrik Andersson'
+ email: 'henrik.b.andersson@est.tech'
+ company: 'EST'
+ id: 'elinuxhenrik'
+ timezone: 'Europe/Stockholm'
+tsc:
+ approval: 'https://lists.onap.org/pipermail/onap-tsc'
+ changes:
+ - type: 'Addition'
+ name: 'Piotr Jaszczyk'
+ name: 'Piotr Wielebski'
+ name: 'Henrik Andersson'
+ link: 'https://lists.onap.org/g/onap-tsc/message/4771'
diff --git a/components/bbs-event-processor/LICENSE.txt b/components/bbs-event-processor/LICENSE.txt
new file mode 100644
index 00000000..97ba6f64
--- /dev/null
+++ b/components/bbs-event-processor/LICENSE.txt
@@ -0,0 +1,36 @@
+/*
+* ============LICENSE_START==========================================
+* ===================================================================
+* Copyright (c) 2019 NOKIA Intellectual Property. All rights reserved.
+* ===================================================================
+*
+* Unless otherwise specified, all software contained herein is licensed
+* under the Apache License, Version 2.0 (the "License");
+* you may not use this software 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.
+*
+*
+*
+* Unless otherwise specified, all documentation contained herein is licensed
+* under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+* you may not use this documentation except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* https://creativecommons.org/licenses/by/4.0/
+*
+* Unless required by applicable law or agreed to in writing, documentation
+* 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============================================
+*/ \ No newline at end of file
diff --git a/components/bbs-event-processor/README.md b/components/bbs-event-processor/README.md
new file mode 100644
index 00000000..14ecc8ce
--- /dev/null
+++ b/components/bbs-event-processor/README.md
@@ -0,0 +1,76 @@
+# BBS use case event processor
+
+---
+
+## Overview
+
+BBE-ep is responsible for handling two types of events for the BBS use case.
+
+First are PNF re-registration internal events published by PRH (in **unauthenticated.PNF_UPDATE** DMaaP topic).
+BBS-ep must process these internal events to understand if they actually constitute ONT(CPE) relocation events.
+In the relocation case, it publishes an event towards **unauthenticated.DCAE_CL_OUTPUT** DMaaP topic to trigger
+further Policy actions related to BBS use case.
+
+Second type of events are CPE authentication events originally published by the Edge SDN M&C component of BBS
+use case architecture. Through RestConf-Collector or VES-Collector, these events are consumed by BBS-ep
+(in **unauthenticated.CPE_AUTHENTICATION** DMaaP topic) and they are forwarded towards **unauthenticated.DCAE_CL_OUTPUT**
+DMaaP topic to trigger further Policy actions related to BBS use case.
+
+BBE-ep periodically polls for the two events. Polling interval is configurable and can be changed dynamically from Consul. I
+Its implementation is based on Reactive Streams (Reactor library), so it is fully asynchronous and non-blocking.
+
+## Installation and Removal
+
+BBS-ep is delivered as a Spring-Boot application ready to be deployed in Docker (via docker-compose).
+
+For Dublin release, it will be a DCAE component that can dynamically be deployed via Cloudify blueprint installation.
+Steps to deploy are shown below
+
+- Transfer blueprint component file in DCAE bootstrap POD under /blueprints directory. Blueprint can be found in
+ <https://gerrit.onap.org/r/gitweb?p=dcaegen2/services.git;a=blob_plain;f=components/bbs-event-processor/dpo/blueprints/k8s-bbs-event-processor.yaml-template;hb=refs/heads/master>
+- Transfer blueprint component inputs file in DCAE bootstrap POD under / directory. Blueprint inputs file can be found in
+ <https://gerrit.onap.org/r/gitweb?p=dcaegen2/services.git;a=blob_plain;f=components/bbs-event-processor/dpo/blueprints/bbs-event-processor-input.yaml;h=36e69cf64bee3b46ee2e1b95f1a16380b7046482;hb=refs/heads/master>
+- Enter the Bootstrap POD
+- Validate blueprint
+ cfy blueprints validate /blueprints/k8s-bbs-event-processor.yaml-template
+- Upload validated blueprint
+ cfy blueprints upload -b bbs-ep /blueprints/k8s-bbs-event-processor.yaml-template
+- Create deployment
+ cfy deployments create -b bbs-ep -i /bbs-event-processor-input.yaml bbs-ep
+- Deploy blueprint
+ cfy executions start -d bbs-ep install
+
+To un-deploy BBS-ep, steps are shown below
+
+- Validate blueprint by running command
+ cfy uninstall bbs-ep
+- Validate blueprint by running command
+ cfy blueprints delete bbs-ep
+
+## Functionality
+
+For more details about the exact flows and where BBS-EP fits in the overall BBS flows, visit [use case official documentation](https://wiki.onap.org/display/DW/BBS+Notifications)
+
+## Compiling BBS-ep
+
+BBS-ep is a sub-project of dcaegen2/services (inside components directory).
+To build just the BBS-ep component, run the following maven command from within **components/bbs-event-processor** directory
+
+`mvn clean install`
+
+## Main API Endpoints
+
+Running with dev-mode of BBS-ep
+
+ - **Heartbeat**
+ - GET http://<container_address>:8100/heartbeat
+ - **Start Polling for events**
+ - POST http://<container_address>:8100/start-tasks
+ - **Stop Polling for events**
+ - POST http://<container_address>:8100/cancel-tasks
+ - **Execute just one polling for PNF re-registration internal events**
+ - POST http://<container_address>:8100/poll-reregistration-events
+ - **Execute just one polling for CPE authentication events**
+ - POST http://<container_address>:8100/poll-cpe-authentication-events
+ - **Change application logging level**
+ - POST http://<container_address>:8100/logging/{level} \ No newline at end of file
diff --git a/components/bbs-event-processor/dpo/blueprints/bbs-event-processor-input.yaml b/components/bbs-event-processor/dpo/blueprints/bbs-event-processor-input.yaml
new file mode 100644
index 00000000..a7adbbb2
--- /dev/null
+++ b/components/bbs-event-processor/dpo/blueprints/bbs-event-processor-input.yaml
@@ -0,0 +1,29 @@
+#============LICENSE_START========================================================
+#=================================================================================
+# Copyright (c) 2018 AT&T Intellectual Property. 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=========================================================
+
+
+tag_version: nexus3.onap.org:10001/onap/org.onap.dcaegen2.services.components.bbs-event-processor:1.0.0-SNAPSHOT
+pnf_reregistration_url: http:message-router:3904/events/unauthenticated.PNF_UPDATE
+cpe_authentication_url: http:message-router:3904/events/unauthenticated.CPE_AUTHENTICATION
+close_loop_url: http:message-router:3904/events/unauthenticated.DCAE_CL_OUTPUT
+application_rereg_policy_scope: policyScopeReReg
+application_rereg_cl_control_name: clControlNameReReg
+application_cpeAuth_policy_scope: policyScopeCpeAuth
+application_cpeAuth_cl_control_name: clControlNameCpeAuth
+application_cbs_polling_interval_sec: 120
+dmaap_consumer_id: c12
+dmaap_consumer_group: OpenDcae-c12 \ No newline at end of file
diff --git a/components/bbs-event-processor/dpo/blueprints/k8s-bbs-event-processor.yaml-template b/components/bbs-event-processor/dpo/blueprints/k8s-bbs-event-processor.yaml-template
new file mode 100644
index 00000000..2d2c7a5d
--- /dev/null
+++ b/components/bbs-event-processor/dpo/blueprints/k8s-bbs-event-processor.yaml-template
@@ -0,0 +1,164 @@
+# -*- indent-tabs-mode: nil -*- # vi: set expandtab:
+#
+# ============LICENSE_START====================================================
+# =============================================================================
+# Copyright (c) 2019 AT&T, NOKIA
+# =============================================================================
+# 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======================================================
+
+tosca_definitions_version: cloudify_dsl_1_3
+
+imports:
+ - "http://www.getcloudify.org/spec/cloudify/3.4/types.yaml"
+ - https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R4/k8splugin/1.4.11/k8splugin_types.yaml
+
+inputs:
+ aai_enrichment_host:
+ type: string
+ default: "aai"
+ aai_enrichment_port:
+ type: integer
+ default: 8443
+ aai_enrichment_protocol:
+ type: string
+ default: "https"
+ tag_version:
+ type: string
+ replicas:
+ type: integer
+ description: number of instances
+ default: 1
+ host_port:
+ description: port on Kubernetes host where bbs-event-processor API will be exposed
+ default: 0
+ pnf_reregistration_url:
+ type: string
+ cpe_authentication_url:
+ type: string
+ close_loop_url:
+ type: string
+ application_policy_version:
+ description: Policy version value for building CL events
+ type: string
+ default: "1.0.0.5"
+ application_cl_target_type:
+ description: Close Loop target type value for building CL events
+ type: string
+ default: "VM"
+ application_cl_event_status:
+ description: Close Loop event status value for building CL events
+ type: string
+ default: "ONSET"
+ application_cl_version:
+ description: Close Loop version value for building CL events
+ type: string
+ default: "1.0.2"
+ application_cl_target:
+ description: Close Loop target value for building CL events
+ type: string
+ default: "vserver.vserver-name"
+ application_cl_originator:
+ description: Close Loop originator value for building CL events
+ type: string
+ default: "DCAE-BBS-ep"
+ application_rereg_policy_scope:
+ description: Policy Scope value for building PNF relocation CL event
+ type: string
+ application_rereg_cl_control_name:
+ description: Close Loop control name value for building PNF relocation CL event
+ type: string
+ application_cpeAuth_policy_scope:
+ description: Policy Scope value for building CPE Authentication CL event
+ type: string
+ application_cpeAuth_cl_control_name:
+ description: Close Loop control name value for building CPE Authentication CL event
+ type: string
+ application_cbs_polling_interval_sec:
+ type: integer
+ default: 300
+ application_logging_level:
+ type: string
+ default: "INFO"
+ dmaap_consumer_id:
+ type: string
+ dmaap_consumer_group:
+ type: string
+node_templates:
+ bbs-event-processor:
+ type: dcae.nodes.ContainerizedPlatformComponent
+ properties:
+ application_config:
+ streams_subscribes:
+ pnf_reregistration:
+ type: message_router
+ dmaap_info:
+ topic_url: { get_input: pnf_reregistration_url }
+ cpe_authentication:
+ type: message_router
+ dmaap_info:
+ topic_url: { get_input: cpe_authentication_url }
+ streams_publishes:
+ close_loop:
+ type: message_router
+ dmaap_info:
+ topic_url: { get_input: close_loop_url }
+ dmaap.protocol: "http"
+ dmaap.contentType: "application/json"
+ dmaap.consumer.consumerId: { get_input: dmaap_consumer_id }
+ dmaap.consumer.consumerGroup: { get_input: dmaap_consumer_group }
+ dmaap.messageLimit: -1
+ dmaap.timeoutMs: -1
+ aai.host: { get_input: aai_enrichment_host }
+ aai.port: { get_input: aai_enrichment_port }
+ aai.protocol: { get_input: aai_enrichment_protocol }
+ aai.username: "AAI"
+ aai.password: "AAI"
+ aai.aaiIgnoreSslCertificateErrors: true
+ application.pipelinesPollingIntervalSec: 30
+ application.pipelinesTimeoutSec: 15
+ application.cbsPollingIntervalSec: { get_input: application_cbs_polling_interval_sec }
+ application.policyVersion: { get_input: application_policy_version }
+ application.clTargetType: { get_input: application_cl_target_type }
+ application.clEventStatus: { get_input: application_cl_event_status }
+ application.clVersion: { get_input: application_cl_version }
+ application.clTarget: { get_input: application_cl_target }
+ application.clOriginator: { get_input: application_cl_originator }
+ application.reregistration.policyScope: { get_input: application_rereg_policy_scope }
+ application.reregistration.clControlName: { get_input: application_rereg_cl_control_name }
+ application.cpe.authentication.policyScope: { get_input: application_cpeAuth_policy_scope }
+ application.cpe.authentication.clControlName: { get_input: application_cpeAuth_cl_control_name }
+ application.reregistration.configKey: "pnf_reregistration"
+ application.cpeAuth.configKey: "cpe_authentication"
+ application.closeLoop.configKey: "close_loop"
+ application.loggingLevel: { get_input: application_logging_level }
+ host_port:
+ { get_input: host_port }
+ container_port:
+ 8100
+ docker_config:
+ healthcheck:
+ endpoint: /heartbeat
+ interval: 180s
+ timeout: 5s
+ type: http
+ image:
+ { get_input: tag_version }
+ replicas: {get_input: replicas}
+ name: 'bbs-event-processor'
+ dns_name: 'bbs-event-processor'
+ log_info:
+ log_directory: "/opt/app/bbs-event-processor/logs"
+ tls_info:
+ cert_directory: '/opt/app/bbs-event-processor/etc/cert/'
+ use_tls: false \ No newline at end of file
diff --git a/components/bbs-event-processor/dpo/data-formats/aai-interaction.json b/components/bbs-event-processor/dpo/data-formats/aai-interaction.json
new file mode 100644
index 00000000..e502d866
--- /dev/null
+++ b/components/bbs-event-processor/dpo/data-formats/aai-interaction.json
@@ -0,0 +1,11 @@
+{
+ "self": {
+ "name": "AAI_Interaction",
+ "version": "1.0.0",
+ "description": "Messages exchanged between a microservice and AAI"
+ },
+ "dataformatversion": "1.0.0",
+ "unstructured": {
+ "encoding": "UTF-8"
+ }
+}
diff --git a/components/bbs-event-processor/dpo/data-formats/pnf-reregistration.json b/components/bbs-event-processor/dpo/data-formats/pnf-reregistration.json
new file mode 100644
index 00000000..f6fcbe6d
--- /dev/null
+++ b/components/bbs-event-processor/dpo/data-formats/pnf-reregistration.json
@@ -0,0 +1,11 @@
+{
+ "self": {
+ "name": "PNF_Reregistration_internal",
+ "version": "1.0.0",
+ "description": "Internal event sent by PRH for PNF re-registration"
+ },
+ "dataformatversion": "1.0.0",
+ "unstructured": {
+ "encoding": "UTF-8"
+ }
+}
diff --git a/components/bbs-event-processor/dpo/spec/bbs-event-processor-spec.json b/components/bbs-event-processor/dpo/spec/bbs-event-processor-spec.json
new file mode 100644
index 00000000..49b0e8f6
--- /dev/null
+++ b/components/bbs-event-processor/dpo/spec/bbs-event-processor-spec.json
@@ -0,0 +1,307 @@
+{
+ "self": {
+ "version": "1.0.0",
+ "name": "dcae-bbs-event-processor",
+ "description": "Processes events for PNF relocation and CPE authentication",
+ "component_type": "docker"
+ },
+ "streams": {
+ "subscribes": [
+ {
+ "format": "PNF_Reregistration_internal",
+ "version": "1.0.0",
+ "type": "message_router",
+ "config_key" : "pnf_reregistration"
+ },
+ {
+ "format": "VES_specification",
+ "version": "7.30.1",
+ "type": "message_router",
+ "config_key" : "cpe_authentication"
+ }
+ ],
+ "publishes": [
+ {
+ "format": "DCAE_CL_Output",
+ "version": "1.0.1",
+ "type": "message_router",
+ "config_key": "close_loop"
+ }
+ ]
+ },
+ "services": {
+ "calls": [
+ {
+ "config_key": "aai-interaction",
+ "request": {
+ "format": "AAI_Interaction",
+ "version": "1.0.0"
+ },
+ "response": {
+ "format": "AAI_Interaction",
+ "version": "1.0.0"
+ }
+ }
+ ],
+ "provides": []
+ },
+ "parameters": [
+ {
+ "name": "dmaap.protocol",
+ "value": "http",
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": false,
+ "description": "DMaaP protocol used for any DMaaP interaction"
+ },
+ {
+ "name": "dmaap.contentType",
+ "value": "application/json",
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": false,
+ "description": "DMaaP content type"
+ },
+ {
+ "name": "dmaap.consumer.consumerId",
+ "value": "c12",
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": true,
+ "description": "DMaaP consumer consumer ID"
+ },
+ {
+ "name": "dmaap.consumer.consumerGroup",
+ "value": "OpenDcae-c12",
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": true,
+ "description": "DMaaP consumer consumer group"
+ },
+ {
+ "name": "dmaap.messageLimit",
+ "value": 1,
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": false,
+ "description": "DMaaP message limit"
+ },
+ {
+ "name": "dmaap.timeoutMs",
+ "value": -1,
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": false,
+ "description": "DMaaP timeout in millis"
+ },
+ {
+ "name": "aai.host",
+ "value": "aai.onap.svc.cluster.local",
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": true,
+ "description": "AAI enrichment host"
+ },
+ {
+ "name": "aai.port",
+ "value": 8443,
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": true,
+ "description": "AAI enrichment port"
+ },
+ {
+ "name": "aai.protocol",
+ "value": "https",
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": true,
+ "description": "AAI protocol"
+ },
+ {
+ "name": "aai.username",
+ "value": "AAI",
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": false,
+ "description": "AAI username"
+ },
+ {
+ "name": "aai.password",
+ "value": "AAI",
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": false,
+ "description": "AAI password"
+ },
+ {
+ "name": "aai.aaiIgnoreSslCertificateErrors",
+ "value": true,
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": false,
+ "description": "Ignore SSL Certificate errors for AAI"
+ },
+ {
+ "name": "application.pipelinesPollingIntervalSec",
+ "value": 30,
+ "constraints": [
+ {
+ "greater_or_equal": 15
+ }
+ ],
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": false,
+ "description": "Polling interval in seconds for executing event processing reactive pipelines"
+ },
+ {
+ "name": "application.pipelinesTimeoutSec",
+ "value": 15,
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": false,
+ "description": "Timeout in seconds to wait in reactive pipelines processing"
+ },
+ {
+ "name": "application.cbsPollingIntervalSec",
+ "value": 300,
+ "constraints": [
+ {
+ "greater_or_equal": 30
+ }
+ ],
+ "designer_editable": true,
+ "policy_editable": false,
+ "sourced_at_deployment": true,
+ "description": "Polling interval in seconds for fetching configuration from Consul via CBS service"
+ },
+ {
+ "name": "application.policyVersion",
+ "value": "1.0.0.5",
+ "designer_editable": false,
+ "policy_editable": true,
+ "sourced_at_deployment": true,
+ "description": "Policy Version parameter in Policy triggering event to be published"
+ },
+ {
+ "name": "application.clTargetType",
+ "value": "VM",
+ "designer_editable": false,
+ "policy_editable": true,
+ "sourced_at_deployment": true,
+ "description": "Close Loop target type parameter in Policy triggering event to be published"
+ },
+ {
+ "name": "application.clEventStatus",
+ "value": "ONSET",
+ "designer_editable": false,
+ "policy_editable": true,
+ "sourced_at_deployment": true,
+ "description": "Close Loop event status parameter in Policy triggering event to be published"
+ },
+ {
+ "name": "application.clVersion",
+ "value": "1.0.2",
+ "designer_editable": false,
+ "policy_editable": true,
+ "sourced_at_deployment": true,
+ "description": "Close Loop version parameter in Policy triggering event to be published"
+ },
+ {
+ "name": "application.clTarget",
+ "value": "vserver.vserver-name",
+ "designer_editable": false,
+ "policy_editable": true,
+ "sourced_at_deployment": true,
+ "description": "Close Loop target parameter in Policy triggering event to be published"
+ },
+ {
+ "name": "application.clOriginator",
+ "value": "DCAE-BBS-ep",
+ "designer_editable": false,
+ "policy_editable": true,
+ "sourced_at_deployment": true,
+ "description": "Close Loop originator parameter in Policy triggering event to be published"
+ },
+ {
+ "name": "application.reregistration.policyScope",
+ "value": "policyScope",
+ "designer_editable": false,
+ "policy_editable": true,
+ "sourced_at_deployment": true,
+ "description": "Policy Scope parameter in Policy triggering event to be published"
+ },
+ {
+ "name": "application.reregistration.clControlName",
+ "value": "controlName",
+ "designer_editable": false,
+ "policy_editable": true,
+ "sourced_at_deployment": true,
+ "description": "Close Loop control name parameter in Policy triggering event to be published"
+ },
+ {
+ "name": "application.cpe.authentication.policyScope",
+ "value": "policyScope",
+ "designer_editable": false,
+ "policy_editable": true,
+ "sourced_at_deployment": true,
+ "description": "Policy Scope parameter in Policy triggering event to be published"
+ },
+ {
+ "name": "application.cpe.authentication.clControlName",
+ "value": "controlName",
+ "designer_editable": false,
+ "policy_editable": true,
+ "sourced_at_deployment": true,
+ "description": "Close Loop control nam parameter in Policy triggering event to be published"
+ },
+ {
+ "name": "application.reregistration.configKey",
+ "value": "pnf_reregistration",
+ "designer_editable": false,
+ "policy_editable": true,
+ "sourced_at_deployment": true,
+ "description": "Config-key for PNF re-registration"
+ }
+ ,
+ {
+ "name": "application.cpeAuth.configKey",
+ "value": "cpe_authentication",
+ "designer_editable": false,
+ "policy_editable": true,
+ "sourced_at_deployment": true,
+ "description": "Config-key for CPE authentication"
+ },
+ {
+ "name": "application.closeLoop.configKey",
+ "value": "close_loop",
+ "designer_editable": false,
+ "policy_editable": true,
+ "sourced_at_deployment": true,
+ "description": "Config-key for Close Loop"
+ },
+ {
+ "name": "application.loggingLevel",
+ "value": "INFO",
+ "designer_editable": false,
+ "policy_editable": false,
+ "sourced_at_deployment": true,
+ "description": "Application Logging Level"
+ }
+ ],
+ "auxilary": {
+ "healthcheck": {
+ "type": "http",
+ "interval": "180s",
+ "timeout": "5s",
+ "endpoint": "/heartbeat"
+ }
+ },
+ "artifacts": [
+ {
+ "uri": "nexus3.onap.org:10003/onap/org.onap.dcaegen2.services.components.bbs-event-processor:1.0.0-SNAPSHOT",
+ "type": "docker image"
+ }
+ ]
+}
diff --git a/components/bbs-event-processor/pom.xml b/components/bbs-event-processor/pom.xml
new file mode 100644
index 00000000..7ebe18ec
--- /dev/null
+++ b/components/bbs-event-processor/pom.xml
@@ -0,0 +1,421 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.oparent</groupId>
+ <artifactId>oparent</artifactId>
+ <version>1.2.3</version>
+ </parent>
+
+ <groupId>org.onap.dcaegen2.services.components</groupId>
+ <artifactId>bbs-event-processor</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+
+ <name>dcaegen2-services-bbs-event-processor</name>
+ <description>BBS Re-Registration and CPE Authentication Handler</description>
+ <packaging>jar</packaging>
+
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ </license>
+ </licenses>
+
+ <properties>
+ <java.version>8</java.version>
+ <immutables.version>2.7.5</immutables.version>
+ <spring-boot.version>2.1.3.RELEASE</spring-boot.version>
+ <tomcat.version>8.5.32</tomcat.version>
+ <slf4j.version>1.7.25</slf4j.version>
+ <junit-platform.version>1.1.0</junit-platform.version>
+ <jacoco.version>0.8.2</jacoco.version>
+ <sdk.version>1.1.2-SNAPSHOT</sdk.version>
+ <common.sdk.version>1.1.3</common.sdk.version>
+ <cbs.version>1.1.3</cbs.version>
+ <wiremock.version>2.21.0</wiremock.version>
+ <springfox-swagger.version>2.8.0</springfox-swagger.version>
+ <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format>
+ <bbs-event-processor.main.class>org.onap.bbs.event.processor.Application</bbs-event-processor.main.class>
+ <dependency.dir.name>libs</dependency.dir.name>
+ <dependency.dir.location>${project.build.directory}/${dependency.dir.name}</dependency.dir.location>
+ <docker.artifact.dir>/opt</docker.artifact.dir>
+ <docker.image.name>onap/${project.groupId}.${project.artifactId}</docker.image.name>
+ <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
+ <artifactId>cbs-client</artifactId>
+ <version>${cbs.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
+ <artifactId>aai-client</artifactId>
+ <version>${sdk.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
+ <artifactId>dmaap-client</artifactId>
+ <version>${sdk.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
+ <artifactId>common-dependency</artifactId>
+ <version>${common.sdk.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-swagger2</artifactId>
+ <version>${springfox-swagger.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-swagger-ui</artifactId>
+ <version>${springfox-swagger.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.immutables</groupId>
+ <artifactId>value</artifactId>
+ <version>${immutables.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.immutables</groupId>
+ <artifactId>gson</artifactId>
+ <version>${immutables.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${spring-boot.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.tomakehurst</groupId>
+ <artifactId>wiremock-jre8</artifactId>
+ <version>${wiremock.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
+ <artifactId>cbs-client</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
+ <artifactId>aai-client</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
+ <artifactId>dmaap-client</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
+ <artifactId>common-dependency</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-webflux</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-swagger2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-swagger-ui</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.projectreactor</groupId>
+ <artifactId>reactor-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-el</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-websocket</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.immutables</groupId>
+ <artifactId>value</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.immutables</groupId>
+ <artifactId>gson</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.projectreactor</groupId>
+ <artifactId>reactor-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.datatype</groupId>
+ <artifactId>jackson-datatype-jsr310</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.tomakehurst</groupId>
+ <artifactId>wiremock-jre8</artifactId>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.7.0</version>
+ <configuration>
+ <source>${java.version}</source>
+ <target>${java.version}</target>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ <showWarnings>true</showWarnings>
+ <showDeprecation>true</showDeprecation>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>3.1.0</version>
+ <configuration>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring-boot.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>pl.project13.maven</groupId>
+ <artifactId>git-commit-id-plugin</artifactId>
+ <version>2.2.6</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>3.1.1</version>
+ </plugin>
+ <plugin>
+ <groupId>com.spotify</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <version>1.2.0</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.19.1</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-surefire-provider</artifactId>
+ <version>${junit-platform.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>pl.project13.maven</groupId>
+ <artifactId>git-commit-id-plugin</artifactId>
+ <configuration>
+ <dateFormat>${maven.build.timestamp.format}</dateFormat>
+ <generateGitPropertiesFile>true</generateGitPropertiesFile>
+ <format>json</format>
+ <generateGitPropertiesFilename>${project.build.outputDirectory}/git_info.json</generateGitPropertiesFilename>
+ </configuration>
+ <executions>
+ <execution>
+ <id>get-git-info</id>
+ <goals>
+ <goal>revision</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ <classpathPrefix>./${dependency.dir.name}/</classpathPrefix>
+ <useUniqueVersions>false</useUniqueVersions>
+ <mainClass>${bbs-event-processor.main.class}</mainClass>
+ <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+ </manifest>
+ <manifestEntries>
+ <Build-Time>${maven.build.timestamp}</Build-Time>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <configuration>
+ <outputDirectory>${dependency.dir.location}</outputDirectory>
+ <includeScope>runtime</includeScope>
+ <silent>true</silent>
+ </configuration>
+ <executions>
+ <execution>
+ <id>copy-external-dependencies</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>com.spotify</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <configuration>
+ <serverId>${onap.nexus.dockerregistry.daily}</serverId>
+ <imageName>${docker.image.name}</imageName>
+ <imageTags>
+ <tag>latest</tag>
+ </imageTags>
+ <baseImage>openjdk:${java.version}-jre-alpine</baseImage>
+ <workdir>${docker.artifact.dir}</workdir>
+ <resources>
+ <resource>
+ <directory>${dependency.dir.location}</directory>
+ <targetPath>${dependency.dir.name}</targetPath>
+ </resource>
+ <resource>
+ <directory>${project.build.directory}</directory>
+ <include>${project.build.finalName}.jar</include>
+ </resource>
+ </resources>
+ <exposes>
+ <expose>8100</expose>
+ </exposes>
+ <entryPoint>["java", "-jar", "${project.build.finalName}.jar"]</entryPoint>
+ </configuration>
+ <executions>
+ <execution>
+ <id>build-bbs-event-processor-image</id>
+ <phase>deploy</phase>
+ <goals>
+ <goal>build</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>tag-and-push-image-latest</id>
+ <phase>deploy</phase>
+ <goals>
+ <goal>tag</goal>
+ </goals>
+ <configuration>
+ <image>${docker.image.name}:latest</image>
+ <newName>${onap.nexus.dockerregistry.daily}/${docker.image.name}:latest</newName>
+ <pushImage>true</pushImage>
+ </configuration>
+ </execution>
+ <execution>
+ <id>tag-and-push-image-with-version</id>
+ <phase>deploy</phase>
+ <goals>
+ <goal>tag</goal>
+ </goals>
+ <configuration>
+ <image>${docker.image.name}:latest</image>
+ <newName>${onap.nexus.dockerregistry.daily}/${docker.image.name}:${project.version}</newName>
+ <pushImage>true</pushImage>
+ </configuration>
+ </execution>
+ <execution>
+ <id>tag-and-push-image-with-version-and-date</id>
+ <phase>deploy</phase>
+ <goals>
+ <goal>tag</goal>
+ </goals>
+ <configuration>
+ <image>${docker.image.name}:latest</image>
+ <newName>${onap.nexus.dockerregistry.daily}/${docker.image.name}:${project.version}-${maven.build.timestamp}Z</newName>
+ <pushImage>true</pushImage>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/Application.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/Application.java
new file mode 100644
index 00000000..66e1f86d
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/Application.java
@@ -0,0 +1,84 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor;
+
+import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.INVOCATION_ID;
+import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.REQUEST_ID;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.TypeAdapterFactory;
+
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.UUID;
+
+import javax.annotation.PostConstruct;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.TaskScheduler;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+
+@SpringBootApplication
+@Configuration
+public class Application {
+
+ private Logger logger = LoggerFactory.getLogger(Application.class);
+
+ private static final int THREADS_IN_POOL = 5;
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ @Bean
+ Map<String, String> mdcContextMap() {
+ MDC.put(REQUEST_ID, "SampleRequestID");
+ MDC.put(INVOCATION_ID, UUID.randomUUID().toString());
+ return MDC.getCopyOfContextMap();
+ }
+
+ @Bean
+ Gson gson() {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory);
+ return gsonBuilder.create();
+ }
+
+ @Bean
+ TaskScheduler threadPoolTaskScheduler() {
+ ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
+ scheduler.setPoolSize(THREADS_IN_POOL);
+ scheduler.setThreadNamePrefix("pipeline-thrd-");
+ return scheduler;
+ }
+
+ @PostConstruct
+ public void postConstructionSetup() {
+ logger.info("bbs-event-processor application started");
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/AaiClientConfiguration.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/AaiClientConfiguration.java
new file mode 100644
index 00000000..93754ebc
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/AaiClientConfiguration.java
@@ -0,0 +1,74 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import org.immutables.gson.Gson;
+import org.immutables.value.Value;
+import org.springframework.stereotype.Component;
+
+@Component
+@Value.Immutable(prehash = true)
+@Value.Style(builder = "new")
+@Gson.TypeAdapters
+public abstract class AaiClientConfiguration implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Value.Parameter
+ public abstract String aaiHost();
+
+ @Value.Parameter
+ public abstract Integer aaiPort();
+
+ @Value.Parameter
+ public abstract String aaiProtocol();
+
+ @Value.Parameter
+ public abstract String aaiUserName();
+
+ @Value.Parameter
+ public abstract String aaiUserPassword();
+
+ @Value.Parameter
+ public abstract Boolean aaiIgnoreSslCertificateErrors();
+
+ @Value.Parameter
+ public abstract Map<String, String> aaiHeaders();
+
+ @Value.Parameter
+ public abstract String trustStorePath();
+
+ @Value.Parameter
+ public abstract String trustStorePasswordPath();
+
+ @Value.Parameter
+ public abstract String keyStorePath();
+
+ @Value.Parameter
+ public abstract String keyStorePasswordPath();
+
+ @Value.Parameter
+ public abstract Boolean enableAaiCertAuth();
+
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/AaiClientProperties.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/AaiClientProperties.java
new file mode 100644
index 00000000..97970c7f
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/AaiClientProperties.java
@@ -0,0 +1,66 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import java.util.Map;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
+
+@Configuration
+@ConfigurationProperties("configs.aai.client")
+@Getter
+@Setter
+@Validated
+public class AaiClientProperties {
+
+ @NotBlank
+ private String aaiHost;
+
+ @Min(1025)
+ @Max(65536)
+ private int aaiPort;
+
+ @NotBlank
+ @Pattern(regexp = "(http|https)")
+ private String aaiProtocol;
+
+ @NotBlank
+ private String aaiUserName;
+
+ @NotBlank
+ private String aaiUserPassword;
+
+ private boolean aaiIgnoreSslCertificateErrors;
+
+ @NotNull
+ private Map<String, String> aaiHeaders;
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ApplicationConfiguration.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ApplicationConfiguration.java
new file mode 100644
index 00000000..981d9633
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ApplicationConfiguration.java
@@ -0,0 +1,398 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import static org.onap.bbs.event.processor.config.ApplicationConstants.STREAMS_TYPE;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+import org.onap.bbs.event.processor.exceptions.ApplicationEnvironmentException;
+import org.onap.bbs.event.processor.exceptions.ConfigurationParsingException;
+import org.onap.bbs.event.processor.model.GeneratedAppConfigObject;
+import org.onap.bbs.event.processor.utilities.LoggingUtil;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapConsumerConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapPublisherConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapConsumerConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapPublisherConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ApplicationConfiguration implements ConfigurationChangeObservable {
+
+ private final AaiClientProperties aaiClientProperties;
+ private final DmaapReRegistrationConsumerProperties dmaapReRegistrationConsumerProperties;
+ private final DmaapCpeAuthenticationConsumerProperties dmaapCpeAuthenticationConsumerProperties;
+ private final DmaapProducerProperties dmaapProducerProperties;
+ private final SecurityProperties securityProperties;
+ private final GenericProperties genericProperties;
+
+ private DmaapConsumerConfiguration dmaapReRegistrationConsumerConfiguration;
+ private DmaapConsumerConfiguration dmaapCpeAuthenticationConsumerConfiguration;
+ private DmaapPublisherConfiguration dmaapPublisherConfiguration;
+ private AaiClientConfiguration aaiClientConfiguration;
+ private Set<ConfigurationChangeObserver> observers;
+
+ private int cbsPollingInterval;
+
+ /**
+ * Construct BBS event processor application configuration object.
+ * @param aaiClientProperties Properties for AAI client setup
+ * @param dmaapReRegistrationConsumerProperties Properties for DMaaP client setup (PNF re-registration)
+ * @param dmaapCpeAuthenticationConsumerProperties Properties for DMaaP client setup (CPE authentication)
+ * @param dmaapProducerProperties Properties for DMaaP client setup (Close Loop)
+ * @param securityProperties General security properties
+ * @param genericProperties General application properties
+ */
+ @Autowired
+ public ApplicationConfiguration(AaiClientProperties aaiClientProperties,
+ DmaapReRegistrationConsumerProperties dmaapReRegistrationConsumerProperties,
+ DmaapCpeAuthenticationConsumerProperties dmaapCpeAuthenticationConsumerProperties,
+ DmaapProducerProperties dmaapProducerProperties,
+ SecurityProperties securityProperties,
+ GenericProperties genericProperties) {
+ this.aaiClientProperties = aaiClientProperties;
+ this.dmaapReRegistrationConsumerProperties = dmaapReRegistrationConsumerProperties;
+ this.dmaapCpeAuthenticationConsumerProperties = dmaapCpeAuthenticationConsumerProperties;
+ this.dmaapProducerProperties = dmaapProducerProperties;
+ this.securityProperties = securityProperties;
+ this.genericProperties = genericProperties;
+ observers = new HashSet<>();
+ constructConfigurationObjects();
+ }
+
+ @Override
+ public synchronized void register(ConfigurationChangeObserver observer) {
+ observers.add(observer);
+ }
+
+ @Override
+ public synchronized void unRegister(ConfigurationChangeObserver observer) {
+ observers.remove(observer);
+ }
+
+ @Override
+ public synchronized void notifyObservers() {
+ observers.forEach(ConfigurationChangeObserver::updateConfiguration);
+ }
+
+ public synchronized DmaapConsumerConfiguration getDmaapReRegistrationConsumerConfiguration() {
+ return dmaapReRegistrationConsumerConfiguration;
+ }
+
+ public synchronized DmaapConsumerConfiguration getDmaapCpeAuthenticationConsumerConfiguration() {
+ return dmaapCpeAuthenticationConsumerConfiguration;
+ }
+
+ public synchronized DmaapPublisherConfiguration getDmaapPublisherConfiguration() {
+ return dmaapPublisherConfiguration;
+ }
+
+ public synchronized AaiClientConfiguration getAaiClientConfiguration() {
+ return aaiClientConfiguration;
+ }
+
+ public synchronized int getPipelinesPollingIntervalInSeconds() {
+ return genericProperties.getPipelinesPollingIntervalSec();
+ }
+
+ public synchronized int getPipelinesTimeoutInSeconds() {
+ return genericProperties.getPipelinesTimeoutSec();
+ }
+
+ public synchronized String getPolicyVersion() {
+ return genericProperties.getPolicyVersion();
+ }
+
+ public synchronized String getCloseLoopTargetType() {
+ return genericProperties.getClTargetType();
+ }
+
+ public synchronized String getCloseLoopEventStatus() {
+ return genericProperties.getClEventStatus();
+ }
+
+ public synchronized String getCloseLoopVersion() {
+ return genericProperties.getClVersion();
+ }
+
+ public synchronized String getCloseLoopTarget() {
+ return genericProperties.getClTarget();
+ }
+
+ public String getCloseLoopOriginator() {
+ return genericProperties.getClOriginator();
+ }
+
+ public synchronized int getCbsPollingInterval() {
+ return cbsPollingInterval;
+ }
+
+ public synchronized String getReRegistrationCloseLoopPolicyScope() {
+ return genericProperties.getReRegistration().getPolicyScope();
+ }
+
+ public synchronized String getReRegistrationCloseLoopControlName() {
+ return genericProperties.getReRegistration().getClControlName();
+ }
+
+ public synchronized String getCpeAuthenticationCloseLoopPolicyScope() {
+ return genericProperties.getCpeAuthentication().getPolicyScope();
+ }
+
+ public synchronized String getCpeAuthenticationCloseLoopControlName() {
+ return genericProperties.getCpeAuthentication().getClControlName();
+ }
+
+ /**
+ * Update current configuration based on the new configuration object fetched from Consul via CBS service of DCAE.
+ * @param newConfiguration updated configuration object
+ */
+ public void updateCurrentConfiguration(GeneratedAppConfigObject newConfiguration) {
+
+ synchronized (this) {
+ cbsPollingInterval = newConfiguration.cbsPollingIntervalSec();
+
+ GeneratedAppConfigObject.StreamsObject reRegObject =
+ getStreamsObject(newConfiguration.streamSubscribesMap(), newConfiguration.reRegConfigKey(),
+ "PNF Re-Registration");
+ TopicUrlInfo topicUrlInfo = parseTopicUrl(reRegObject.dmaapInfo().topicUrl());
+ dmaapReRegistrationConsumerProperties.setDmaapHostName(topicUrlInfo.getHost());
+ dmaapReRegistrationConsumerProperties.setDmaapPortNumber(topicUrlInfo.getPort());
+ dmaapReRegistrationConsumerProperties.setDmaapProtocol(newConfiguration.dmaapProtocol());
+ dmaapReRegistrationConsumerProperties.setDmaapContentType(newConfiguration.dmaapContentType());
+ dmaapReRegistrationConsumerProperties.setDmaapTopicName(topicUrlInfo.getTopicName());
+ dmaapReRegistrationConsumerProperties.setConsumerId(newConfiguration.dmaapConsumerConsumerId());
+ dmaapReRegistrationConsumerProperties.setConsumerGroup(newConfiguration.dmaapConsumerConsumerGroup());
+ dmaapReRegistrationConsumerProperties.setMessageLimit(newConfiguration.dmaapMessageLimit());
+ dmaapReRegistrationConsumerProperties.setTimeoutMs(newConfiguration.dmaapTimeoutMs());
+ constructDmaapReRegistrationConfiguration();
+
+ GeneratedAppConfigObject.StreamsObject cpeAuthObject =
+ getStreamsObject(newConfiguration.streamSubscribesMap(), newConfiguration.cpeAuthConfigKey(),
+ "CPE Authentication");
+ topicUrlInfo = parseTopicUrl(cpeAuthObject.dmaapInfo().topicUrl());
+ dmaapCpeAuthenticationConsumerProperties.setDmaapHostName(topicUrlInfo.getHost());
+ dmaapCpeAuthenticationConsumerProperties.setDmaapPortNumber(topicUrlInfo.getPort());
+ dmaapCpeAuthenticationConsumerProperties.setDmaapProtocol(newConfiguration.dmaapProtocol());
+ dmaapCpeAuthenticationConsumerProperties.setDmaapContentType(newConfiguration.dmaapContentType());
+ dmaapCpeAuthenticationConsumerProperties.setDmaapTopicName(topicUrlInfo.getTopicName());
+ dmaapCpeAuthenticationConsumerProperties.setConsumerId(newConfiguration.dmaapConsumerConsumerId());
+ dmaapCpeAuthenticationConsumerProperties.setConsumerGroup(newConfiguration.dmaapConsumerConsumerGroup());
+ dmaapCpeAuthenticationConsumerProperties.setMessageLimit(newConfiguration.dmaapMessageLimit());
+ dmaapCpeAuthenticationConsumerProperties.setTimeoutMs(newConfiguration.dmaapTimeoutMs());
+ constructDmaapCpeAuthenticationConfiguration();
+
+ GeneratedAppConfigObject.StreamsObject closeLoopObject =
+ getStreamsObject(newConfiguration.streamPublishesMap(), newConfiguration.closeLoopConfigKey(),
+ "Close Loop");
+ topicUrlInfo = parseTopicUrl(closeLoopObject.dmaapInfo().topicUrl());
+ dmaapProducerProperties.setDmaapHostName(topicUrlInfo.getHost());
+ dmaapProducerProperties.setDmaapPortNumber(topicUrlInfo.getPort());
+ dmaapProducerProperties.setDmaapProtocol(newConfiguration.dmaapProtocol());
+ dmaapProducerProperties.setDmaapContentType(newConfiguration.dmaapContentType());
+ dmaapProducerProperties.setDmaapTopicName(topicUrlInfo.getTopicName());
+ constructDmaapProducerConfiguration();
+
+ aaiClientProperties.setAaiHost(newConfiguration.aaiHost());
+ aaiClientProperties.setAaiPort(newConfiguration.aaiPort());
+ aaiClientProperties.setAaiProtocol(newConfiguration.aaiProtocol());
+ aaiClientProperties.setAaiUserName(newConfiguration.aaiUsername());
+ aaiClientProperties.setAaiUserPassword(newConfiguration.aaiPassword());
+ aaiClientProperties.setAaiIgnoreSslCertificateErrors(newConfiguration.aaiIgnoreSslCertificateErrors());
+ constructAaiConfiguration();
+
+ genericProperties.setPipelinesPollingIntervalSec(newConfiguration.pipelinesPollingIntervalSec());
+ genericProperties.setPipelinesTimeoutSec(newConfiguration.pipelinesTimeoutSec());
+ genericProperties.setPolicyVersion(newConfiguration.policyVersion());
+ genericProperties.setClTargetType(newConfiguration.closeLoopTargetType());
+ genericProperties.setClEventStatus(newConfiguration.closeLoopEventStatus());
+ genericProperties.setClVersion(newConfiguration.closeLoopVersion());
+ genericProperties.setClTarget(newConfiguration.closeLoopTarget());
+ genericProperties.setClOriginator(newConfiguration.closeLoopOriginator());
+ genericProperties.getReRegistration().setPolicyScope(newConfiguration.reRegistrationPolicyScope());
+ genericProperties.getReRegistration().setClControlName(newConfiguration.reRegistrationClControlName());
+ genericProperties.getCpeAuthentication().setPolicyScope(newConfiguration.cpeAuthPolicyScope());
+ genericProperties.getCpeAuthentication().setClControlName(newConfiguration.cpeAuthClControlName());
+
+ LoggingUtil.changeLoggingLevel(newConfiguration.loggingLevel());
+ }
+
+ notifyObservers();
+ }
+
+ @NotNull
+ private GeneratedAppConfigObject.StreamsObject getStreamsObject(
+ Map<String, GeneratedAppConfigObject.StreamsObject> map, String configKey, String messageName) {
+ GeneratedAppConfigObject.StreamsObject streamsObject = map.get(configKey);
+ if (!STREAMS_TYPE.equals(streamsObject.type())) {
+ throw new ApplicationEnvironmentException(String.format("%s requires information about"
+ + " message-router topic in ONAP", messageName));
+ }
+ return streamsObject;
+ }
+
+ private void constructConfigurationObjects() {
+ constructDmaapReRegistrationConfiguration();
+ constructDmaapCpeAuthenticationConfiguration();
+ constructDmaapProducerConfiguration();
+ constructAaiConfiguration();
+ }
+
+ private void constructDmaapReRegistrationConfiguration() {
+ dmaapReRegistrationConsumerConfiguration = new ImmutableDmaapConsumerConfiguration.Builder()
+ .dmaapHostName(dmaapReRegistrationConsumerProperties.getDmaapHostName())
+ .dmaapPortNumber(dmaapReRegistrationConsumerProperties.getDmaapPortNumber())
+ .dmaapProtocol(dmaapReRegistrationConsumerProperties.getDmaapProtocol())
+ .dmaapTopicName(dmaapReRegistrationConsumerProperties.getDmaapTopicName())
+ .dmaapUserName(
+ dmaapReRegistrationConsumerProperties.getDmaapUserName() == null ? "" :
+ dmaapReRegistrationConsumerProperties.getDmaapUserName())
+ .dmaapUserPassword(
+ dmaapReRegistrationConsumerProperties.getDmaapUserPassword() == null ? "" :
+ dmaapReRegistrationConsumerProperties.getDmaapUserPassword())
+ .dmaapContentType(dmaapReRegistrationConsumerProperties.getDmaapContentType())
+ .consumerId(dmaapReRegistrationConsumerProperties.getConsumerId())
+ .consumerGroup(dmaapReRegistrationConsumerProperties.getConsumerGroup())
+ .timeoutMs(dmaapReRegistrationConsumerProperties.getTimeoutMs())
+ .messageLimit(dmaapReRegistrationConsumerProperties.getMessageLimit())
+ .enableDmaapCertAuth(securityProperties.isEnableDmaapCertAuth())
+ .keyStorePath(securityProperties.getKeyStorePath())
+ .keyStorePasswordPath(securityProperties.getKeyStorePasswordPath())
+ .trustStorePath(securityProperties.getTrustStorePath())
+ .trustStorePasswordPath(securityProperties.getTrustStorePasswordPath())
+ .build();
+ }
+
+ private void constructDmaapCpeAuthenticationConfiguration() {
+ dmaapCpeAuthenticationConsumerConfiguration = new ImmutableDmaapConsumerConfiguration.Builder()
+ .dmaapHostName(dmaapCpeAuthenticationConsumerProperties.getDmaapHostName())
+ .dmaapPortNumber(dmaapCpeAuthenticationConsumerProperties.getDmaapPortNumber())
+ .dmaapProtocol(dmaapCpeAuthenticationConsumerProperties.getDmaapProtocol())
+ .dmaapTopicName(dmaapCpeAuthenticationConsumerProperties.getDmaapTopicName())
+ .dmaapUserName(
+ dmaapCpeAuthenticationConsumerProperties.getDmaapUserName() == null ? "" :
+ dmaapCpeAuthenticationConsumerProperties.getDmaapUserName())
+ .dmaapUserPassword(
+ dmaapCpeAuthenticationConsumerProperties.getDmaapUserPassword() == null ? "" :
+ dmaapCpeAuthenticationConsumerProperties.getDmaapUserPassword())
+ .dmaapContentType(dmaapCpeAuthenticationConsumerProperties.getDmaapContentType())
+ .consumerId(dmaapCpeAuthenticationConsumerProperties.getConsumerId())
+ .consumerGroup(dmaapCpeAuthenticationConsumerProperties.getConsumerGroup())
+ .timeoutMs(dmaapCpeAuthenticationConsumerProperties.getTimeoutMs())
+ .messageLimit(dmaapCpeAuthenticationConsumerProperties.getMessageLimit())
+ .enableDmaapCertAuth(securityProperties.isEnableDmaapCertAuth())
+ .keyStorePath(securityProperties.getKeyStorePath())
+ .keyStorePasswordPath(securityProperties.getKeyStorePasswordPath())
+ .trustStorePath(securityProperties.getTrustStorePath())
+ .trustStorePasswordPath(securityProperties.getTrustStorePasswordPath())
+ .build();
+ }
+
+ private void constructDmaapProducerConfiguration() {
+ dmaapPublisherConfiguration = new ImmutableDmaapPublisherConfiguration.Builder()
+ .dmaapHostName(dmaapProducerProperties.getDmaapHostName())
+ .dmaapPortNumber(dmaapProducerProperties.getDmaapPortNumber())
+ .dmaapProtocol(dmaapProducerProperties.getDmaapProtocol())
+ .dmaapTopicName(dmaapProducerProperties.getDmaapTopicName())
+ .dmaapUserName(
+ dmaapProducerProperties.getDmaapUserName() == null ? "" :
+ dmaapProducerProperties.getDmaapUserName())
+ .dmaapUserPassword(
+ dmaapProducerProperties.getDmaapUserPassword() == null ? "" :
+ dmaapProducerProperties.getDmaapUserPassword())
+ .dmaapContentType(dmaapProducerProperties.getDmaapContentType())
+ .enableDmaapCertAuth(securityProperties.isEnableDmaapCertAuth())
+ .keyStorePath(securityProperties.getKeyStorePath())
+ .keyStorePasswordPath(securityProperties.getKeyStorePasswordPath())
+ .trustStorePath(securityProperties.getTrustStorePath())
+ .trustStorePasswordPath(securityProperties.getTrustStorePasswordPath())
+ .build();
+ }
+
+ private void constructAaiConfiguration() {
+ aaiClientConfiguration = new ImmutableAaiClientConfiguration.Builder()
+ .aaiHost(aaiClientProperties.getAaiHost())
+ .aaiPort(aaiClientProperties.getAaiPort())
+ .aaiProtocol(aaiClientProperties.getAaiProtocol())
+ .aaiUserName(aaiClientProperties.getAaiUserName())
+ .aaiUserPassword(aaiClientProperties.getAaiUserPassword())
+ .aaiHeaders(aaiClientProperties.getAaiHeaders())
+ .aaiIgnoreSslCertificateErrors(aaiClientProperties.isAaiIgnoreSslCertificateErrors())
+ .enableAaiCertAuth(securityProperties.isEnableAaiCertAuth())
+ .keyStorePath(securityProperties.getKeyStorePath())
+ .keyStorePasswordPath(securityProperties.getKeyStorePasswordPath())
+ .trustStorePath(securityProperties.getTrustStorePath())
+ .trustStorePasswordPath(securityProperties.getTrustStorePasswordPath())
+ .build();
+ }
+
+ private TopicUrlInfo parseTopicUrl(String topicUrl) {
+ String[] urlTokens = topicUrl.split(":");
+ if (urlTokens.length != 3) {
+ throw new ConfigurationParsingException("Wrong topic URL format");
+ }
+ TopicUrlInfo topicUrlInfo = new TopicUrlInfo();
+ topicUrlInfo.setHost(urlTokens[1].replace("/", ""));
+
+ String[] tokensAfterHost = urlTokens[2].split("/events/");
+ if (tokensAfterHost.length != 2) {
+ throw new ConfigurationParsingException("Wrong topic name structure");
+ }
+ topicUrlInfo.setPort(Integer.valueOf(tokensAfterHost[0]));
+ topicUrlInfo.setTopicName("/events/" + tokensAfterHost[1]);
+
+ return topicUrlInfo;
+ }
+
+ private static class TopicUrlInfo {
+ private String host;
+ private int port;
+ private String topicName;
+
+ String getHost() {
+ return host;
+ }
+
+ void setHost(String host) {
+ this.host = host;
+ }
+
+ int getPort() {
+ return port;
+ }
+
+ void setPort(int port) {
+ this.port = port;
+ }
+
+ String getTopicName() {
+ return topicName;
+ }
+
+ void setTopicName(String topicName) {
+ this.topicName = topicName;
+ }
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ApplicationConstants.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ApplicationConstants.java
new file mode 100644
index 00000000..d2ac3c10
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ApplicationConstants.java
@@ -0,0 +1,39 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+public class ApplicationConstants {
+
+ public static final String CONSUME_REREGISTRATION_TASK_NAME = "Consume Re-registration DMaaP message";
+ public static final String CONSUME_CPE_AUTHENTICATION_TASK_NAME = "Consume CPE Authentication DMaaP message";
+ public static final String RETRIEVE_PNF_TASK_NAME = "PNF Retrieval";
+ public static final String RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME = "HSI CFS Service Instance Retrieval";
+
+ static final String STREAMS_TYPE = "message_router";
+
+ public static final String IN_SERVICE_NAME_IN_ONAP = "inService";
+ public static final String OUT_OF_SERVICE_NAME_IN_ONAP = "outOfService";
+
+ // Close Loop Constants
+ public static final String DCAE_BBS_EVENT_PROCESSOR_MS_INSTANCE = "DCAE.BBS_event_processor_mSInstance";
+
+ private ApplicationConstants() {}
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ConfigurationChangeObservable.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ConfigurationChangeObservable.java
new file mode 100644
index 00000000..1a395892
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ConfigurationChangeObservable.java
@@ -0,0 +1,41 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+public interface ConfigurationChangeObservable {
+
+ /**
+ * Register a new configuration changes observer.
+ * @param observer New Observer
+ */
+ void register(ConfigurationChangeObserver observer);
+
+ /**
+ * Un-register an existing configuration changes observer.
+ * @param observer Existing Observer
+ */
+ void unRegister(ConfigurationChangeObserver observer);
+
+ /**
+ * Notifies all observers about a new application configuration.
+ */
+ void notifyObservers();
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ConfigurationChangeObserver.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ConfigurationChangeObserver.java
new file mode 100644
index 00000000..c246aaed
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ConfigurationChangeObserver.java
@@ -0,0 +1,29 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+public interface ConfigurationChangeObserver {
+
+ /**
+ * Take actions upon updates in application configuration.
+ */
+ void updateConfiguration();
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ConsulConfigurationGateway.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ConsulConfigurationGateway.java
new file mode 100644
index 00000000..1d27fc0a
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/ConsulConfigurationGateway.java
@@ -0,0 +1,279 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import java.time.Duration;
+import java.util.AbstractMap;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+import org.onap.bbs.event.processor.exceptions.ApplicationEnvironmentException;
+import org.onap.bbs.event.processor.model.GeneratedAppConfigObject;
+import org.onap.bbs.event.processor.model.ImmutableDmaapInfo;
+import org.onap.bbs.event.processor.model.ImmutableGeneratedAppConfigObject;
+import org.onap.bbs.event.processor.model.ImmutableStreamsObject;
+import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.CbsClientFactory;
+import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.EnvProperties;
+import org.onap.dcaegen2.services.sdk.rest.services.model.logging.RequestDiagnosticContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import reactor.core.Disposable;
+
+@Component
+public class ConsulConfigurationGateway {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ConsulConfigurationGateway.class);
+
+ private static final String CONSUL_HOST = "CONSUL_HOST";
+ private static final String CONFIG_BINDING_SERVICE = "CONFIG_BINDING_SERVICE";
+ private static final String HOSTNAME = "HOSTNAME";
+
+ private final ApplicationConfiguration configuration;
+ private Gson gson;
+ private Disposable cbsFetchPipeline;
+
+ @Autowired
+ ConsulConfigurationGateway(ApplicationConfiguration configuration) {
+ this.configuration = configuration;
+ gson = new GsonBuilder().setPrettyPrinting().create();
+ }
+
+ /**
+ * Periodically fetch application configuration via CBS service of DCAE.
+ * @param initialDelay initial delay before initiation of polling
+ * @param period polling interval
+ */
+ public void periodicallyFetchConfigFromCbs(Duration initialDelay, Duration period) {
+ if (environmentNotReady()) {
+ throw new ApplicationEnvironmentException(
+ String.format("Application Environment missing critical parameters: %s",
+ getMissingEnvironmentVariables()));
+ }
+
+ fetchConfig(initialDelay, period);
+ }
+
+ boolean environmentNotReady() {
+ String consulHost = System.getenv().get(CONSUL_HOST);
+ String cbs = System.getenv().get(CONFIG_BINDING_SERVICE);
+ String hostname = System.getenv().get(HOSTNAME);
+ return consulHost == null || cbs == null || hostname == null;
+ }
+
+ /**
+ * Reschedule application configuration periodic retrieval via CBS service of DCAE.
+ * @param initialDelay initial delay before rescheduling
+ * @param period new polling interval
+ */
+ public void rescheduleCbsConfigurationRetrieval(Duration initialDelay, Duration period) {
+ if (cbsFetchPipeline != null && !cbsFetchPipeline.isDisposed()) {
+ LOGGER.info("Disposing old CBS Config fetch job");
+ cbsFetchPipeline.dispose();
+ }
+ periodicallyFetchConfigFromCbs(initialDelay, period);
+ }
+
+ private void parseConsulRetrievedConfiguration(JsonObject jsonObject) {
+
+ GeneratedAppConfigObject generatedAppConfigObject = generateAppConfigObject(jsonObject);
+ LOGGER.trace("Consul-Retrieved Application Generated Object:\n{}", generatedAppConfigObject);
+ configuration.updateCurrentConfiguration(generatedAppConfigObject);
+ }
+
+ private void handleErrors(Throwable throwable) {
+ LOGGER.error("Periodic CBS configuration polling was terminated with error: {}", throwable);
+ LOGGER.info("Will restart CBS configuration fetching job due to abnormal termination."
+ + " Will start fetching after 60 seconds (please correct configuration in the meantime)"
+ + " and it will then poll every {} seconds (reverting to default)",
+ configuration.getCbsPollingInterval());
+ fetchConfig(Duration.ofSeconds(60), Duration.ofSeconds(configuration.getCbsPollingInterval()));
+ }
+
+ private void fetchConfig(Duration initialDelay, Duration period) {
+ RequestDiagnosticContext diagnosticContext = RequestDiagnosticContext.create();
+
+ // Necessary properties from the environment (Consul host:port, service-name (hostname), CBS name)
+ EnvProperties env = EnvProperties.fromEnvironment();
+
+ // Create the client and use it to get the configuration
+ cbsFetchPipeline = CbsClientFactory.createCbsClient(env)
+ .doOnError(e -> LOGGER.warn("CBS Configuration fetch failed with error: {}", e))
+ .retry(e -> true)
+ .flatMapMany(cbsClient -> cbsClient.updates(diagnosticContext, initialDelay, period))
+ .subscribe(this::parseConsulRetrievedConfiguration, this::handleErrors);
+ }
+
+ @NotNull
+ GeneratedAppConfigObject generateAppConfigObject(JsonObject configObject) {
+
+ if (LOGGER.isInfoEnabled()) {
+ String configAsString = gson.toJson(configObject);
+ LOGGER.info("Received App Config object\n{}", configAsString);
+ }
+
+ final String dmaapProtocol = configObject.get("dmaap.protocol").getAsString();
+ final String dmaapContentType = configObject.get("dmaap.contentType").getAsString();
+ final String dmaapConsumerId = configObject.get("dmaap.consumer.consumerId").getAsString();
+ final String dmaapConsumerGroup = configObject.get("dmaap.consumer.consumerGroup").getAsString();
+ final int dmaapMessageLimit = configObject.get("dmaap.messageLimit").getAsInt();
+ final int dmaapTimeoutMs = configObject.get("dmaap.timeoutMs").getAsInt();
+
+ final String aaiHost = configObject.get("aai.host").getAsString();
+ final int aaiPort = configObject.get("aai.port").getAsInt();
+ final String aaiProtocol = configObject.get("aai.protocol").getAsString();
+ final String aaiUsername = configObject.get("aai.username").getAsString();
+ final String aaiPassword = configObject.get("aai.password").getAsString();
+ final boolean aaiIgnoreSslCertificateErrors =
+ configObject.get("aai.aaiIgnoreSslCertificateErrors").getAsBoolean();
+
+ final int pipelinesPollingIntervalSec = configObject.get("application.pipelinesPollingIntervalSec").getAsInt();
+ final int pipelinesTimeoutSec = configObject.get("application.pipelinesTimeoutSec").getAsInt();
+ final int cbsPollingIntervalSec = configObject.get("application.cbsPollingIntervalSec").getAsInt();
+
+ final String reRegPolicyScope = configObject.get("application.reregistration.policyScope").getAsString();
+ final String reRegClControlName = configObject.get("application.reregistration.clControlName").getAsString();
+ final String cpeAuthPolicyScope = configObject.get("application.cpe.authentication.policyScope").getAsString();
+ final String cpeAuthClControlName =
+ configObject.get("application.cpe.authentication.clControlName").getAsString();
+
+ final String policyVersion = configObject.get("application.policyVersion").getAsString();
+ final String closeLoopTargetType = configObject.get("application.clTargetType").getAsString();
+ final String closeLoopEventStatus = configObject.get("application.clEventStatus").getAsString();
+ final String closeLoopVersion = configObject.get("application.clVersion").getAsString();
+ final String closeLoopTarget = configObject.get("application.clTarget").getAsString();
+ final String closeLoopOriginator = configObject.get("application.clOriginator").getAsString();
+
+ final String reRegConfigKey = configObject.get("application.reregistration.configKey").getAsString();
+ final String cpeAuthConfigKey = configObject.get("application.cpeAuth.configKey").getAsString();
+ final String closeLoopConfigKey = configObject.get("application.closeLoop.configKey").getAsString();
+
+ final String loggingLevel = configObject.get("application.loggingLevel").getAsString();
+
+ final JsonObject streamsPublishes = configObject.getAsJsonObject("streams_publishes");
+ final JsonObject streamsSubscribes = configObject.getAsJsonObject("streams_subscribes");
+
+ return ImmutableGeneratedAppConfigObject.builder()
+ .dmaapProtocol(dmaapProtocol)
+ .dmaapContentType(dmaapContentType)
+ .dmaapConsumerConsumerId(dmaapConsumerId)
+ .dmaapConsumerConsumerGroup(dmaapConsumerGroup)
+ .dmaapMessageLimit(dmaapMessageLimit)
+ .dmaapTimeoutMs(dmaapTimeoutMs)
+ .aaiHost(aaiHost)
+ .aaiPort(aaiPort)
+ .aaiProtocol(aaiProtocol)
+ .aaiUsername(aaiUsername)
+ .aaiPassword(aaiPassword)
+ .aaiIgnoreSslCertificateErrors(aaiIgnoreSslCertificateErrors)
+ .pipelinesPollingIntervalSec(pipelinesPollingIntervalSec)
+ .pipelinesTimeoutSec(pipelinesTimeoutSec)
+ .cbsPollingIntervalSec(cbsPollingIntervalSec)
+ .reRegistrationPolicyScope(reRegPolicyScope)
+ .reRegistrationClControlName(reRegClControlName)
+ .policyVersion(policyVersion)
+ .closeLoopTargetType(closeLoopTargetType)
+ .closeLoopEventStatus(closeLoopEventStatus)
+ .closeLoopVersion(closeLoopVersion)
+ .closeLoopTarget(closeLoopTarget)
+ .closeLoopOriginator(closeLoopOriginator)
+ .cpeAuthPolicyScope(cpeAuthPolicyScope)
+ .cpeAuthClControlName(cpeAuthClControlName)
+ .reRegConfigKey(reRegConfigKey)
+ .cpeAuthConfigKey(cpeAuthConfigKey)
+ .closeLoopConfigKey(closeLoopConfigKey)
+ .loggingLevel(loggingLevel)
+ .streamSubscribesMap(parseStreamsObjects(streamsSubscribes))
+ .streamPublishesMap(parseStreamsObjects(streamsPublishes))
+ .build();
+ }
+
+ private Set<String> getMissingEnvironmentVariables() {
+ Set<String> missingVars = new HashSet<>();
+ if (System.getenv().get(CONSUL_HOST) == null) {
+ missingVars.add(CONSUL_HOST);
+ }
+ if (System.getenv().get(CONFIG_BINDING_SERVICE) == null) {
+ missingVars.add(CONFIG_BINDING_SERVICE);
+ }
+ if (System.getenv().get(HOSTNAME) == null) {
+ missingVars.add(HOSTNAME);
+ }
+ return missingVars;
+ }
+
+ private Map<String, GeneratedAppConfigObject.StreamsObject> parseStreamsObjects(
+ JsonObject jsonObject) {
+ Map<String, GeneratedAppConfigObject.StreamsObject> streams = new HashMap<>();
+
+ jsonObject.entrySet().stream()
+ .map(this::parseStreamsSingleObject)
+ .forEach(e -> streams.put(e.getKey(), e.getValue()));
+
+ return streams;
+ }
+
+ private Map.Entry<String, GeneratedAppConfigObject.StreamsObject> parseStreamsSingleObject(
+ Map.Entry<String, JsonElement> jsonEntry) {
+
+ JsonObject closeLoopOutput = (JsonObject) jsonEntry.getValue();
+
+ String type = closeLoopOutput.get("type").getAsString();
+ String aafUsername = closeLoopOutput.get("aaf_username") != null
+ ? closeLoopOutput.get("aaf_username").getAsString() : "";
+ String aafPassword = closeLoopOutput.get("aaf_password") != null
+ ? closeLoopOutput.get("aaf_password").getAsString() : "";
+
+ JsonObject dmaapInfo = closeLoopOutput.getAsJsonObject("dmaap_info");
+ String clientId = dmaapInfo.get("client_id") != null
+ ? dmaapInfo.get("client_id").getAsString() : "";
+ String clientRole = dmaapInfo.get("client_role") != null
+ ? dmaapInfo.get("client_role").getAsString() : "";
+ String location = dmaapInfo.get("location") != null
+ ? dmaapInfo.get("location").getAsString() : "";
+ String topicUrl = dmaapInfo.get("topic_url").getAsString();
+
+ GeneratedAppConfigObject.DmaapInfo dmaapInfoObject = ImmutableDmaapInfo.builder()
+ .clientId(clientId)
+ .clientRole(clientRole)
+ .location(location)
+ .topicUrl(topicUrl)
+ .build();
+ GeneratedAppConfigObject.StreamsObject streamsObject = ImmutableStreamsObject.builder()
+ .type(type)
+ .aafUsername(aafUsername)
+ .aafPassword(aafPassword)
+ .dmaapInfo(dmaapInfoObject)
+ .build();
+
+ return new AbstractMap.SimpleEntry<>(jsonEntry.getKey(), streamsObject);
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/DmaapCpeAuthenticationConsumerProperties.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/DmaapCpeAuthenticationConsumerProperties.java
new file mode 100644
index 00000000..ecc8d6b1
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/DmaapCpeAuthenticationConsumerProperties.java
@@ -0,0 +1,71 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
+
+@Configuration
+@ConfigurationProperties("configs.dmaap.consumer.cpe-authentication")
+@Getter
+@Setter
+@Validated
+public class DmaapCpeAuthenticationConsumerProperties {
+
+ @NotBlank
+ private String dmaapHostName;
+
+ @Min(1025)
+ @Max(65536)
+ private int dmaapPortNumber;
+
+ @NotBlank
+ private String dmaapTopicName;
+
+ @NotBlank
+ @Pattern(regexp = "(http|https)")
+ private String dmaapProtocol;
+
+ private String dmaapUserName;
+
+ private String dmaapUserPassword;
+
+ @NotBlank
+ private String dmaapContentType;
+
+ @NotBlank
+ private String consumerId;
+
+ @NotBlank
+ private String consumerGroup;
+
+ private int timeoutMs;
+ private int messageLimit;
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/DmaapProducerProperties.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/DmaapProducerProperties.java
new file mode 100644
index 00000000..919b4065
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/DmaapProducerProperties.java
@@ -0,0 +1,62 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
+
+@Configuration
+@ConfigurationProperties("configs.dmaap.producer")
+@Getter
+@Setter
+@Validated
+public class DmaapProducerProperties {
+
+ @NotBlank
+ private String dmaapHostName;
+
+ @Min(1025)
+ @Max(65536)
+ private int dmaapPortNumber;
+
+ @NotBlank
+ private String dmaapTopicName;
+
+ @NotBlank
+ @Pattern(regexp = "(http|https)")
+ private String dmaapProtocol;
+
+ private String dmaapUserName;
+
+ private String dmaapUserPassword;
+
+ @NotBlank
+ private String dmaapContentType;
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/DmaapReRegistrationConsumerProperties.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/DmaapReRegistrationConsumerProperties.java
new file mode 100644
index 00000000..d3076393
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/DmaapReRegistrationConsumerProperties.java
@@ -0,0 +1,71 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
+
+@Configuration
+@ConfigurationProperties("configs.dmaap.consumer.re-registration")
+@Getter
+@Setter
+@Validated
+public class DmaapReRegistrationConsumerProperties {
+
+ @NotBlank
+ private String dmaapHostName;
+
+ @Min(1025)
+ @Max(65536)
+ private int dmaapPortNumber;
+
+ @NotBlank
+ private String dmaapTopicName;
+
+ @NotBlank
+ @Pattern(regexp = "(http|https)")
+ private String dmaapProtocol;
+
+ private String dmaapUserName;
+
+ private String dmaapUserPassword;
+
+ @NotBlank
+ private String dmaapContentType;
+
+ @NotBlank
+ private String consumerId;
+
+ @NotBlank
+ private String consumerGroup;
+
+ private int timeoutMs;
+ private int messageLimit;
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/GenericProperties.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/GenericProperties.java
new file mode 100644
index 00000000..71fd5bbd
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/GenericProperties.java
@@ -0,0 +1,87 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import javax.validation.constraints.NotBlank;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
+
+@Configuration
+@ConfigurationProperties("configs.application")
+@Getter
+@Setter
+@Validated
+public class GenericProperties {
+
+ private int pipelinesPollingIntervalSec;
+
+ private int pipelinesTimeoutSec;
+
+ @NotBlank
+ private String policyVersion;
+
+ @NotBlank
+ private String clTargetType;
+
+ @NotBlank
+ private String clEventStatus;
+
+ @NotBlank
+ private String clVersion;
+
+ @NotBlank
+ private String clTarget;
+
+ @NotBlank
+ private String clOriginator;
+
+ private ReRegistrationGenericProperties reRegistration;
+
+ private CpeAuthenticationGenericProperties cpeAuthentication;
+
+ @Getter
+ @Setter
+ @Validated
+ static class ReRegistrationGenericProperties {
+
+ @NotBlank
+ private String policyScope;
+
+ @NotBlank
+ private String clControlName;
+ }
+
+ @Getter
+ @Setter
+ @Validated
+ static class CpeAuthenticationGenericProperties {
+ @NotBlank
+ private String policyScope;
+
+ @NotBlank
+ private String clControlName;
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/SecurityProperties.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/SecurityProperties.java
new file mode 100644
index 00000000..188cd658
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/SecurityProperties.java
@@ -0,0 +1,53 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import javax.validation.constraints.NotBlank;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
+
+@Configuration
+@ConfigurationProperties("configs.security")
+@Getter
+@Setter
+@Validated
+public class SecurityProperties {
+
+ @NotBlank
+ private String trustStorePath;
+
+ @NotBlank
+ private String trustStorePasswordPath;
+
+ @NotBlank
+ private String keyStorePath;
+
+ @NotBlank
+ private String keyStorePasswordPath;
+
+ private boolean enableAaiCertAuth;
+ private boolean enableDmaapCertAuth;
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/SwaggerConfiguration.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/SwaggerConfiguration.java
new file mode 100644
index 00000000..c3c87da2
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/config/SwaggerConfiguration.java
@@ -0,0 +1,83 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@EnableSwagger2
+@Configuration
+@Profile("production")
+public class SwaggerConfiguration extends WebMvcConfigurationSupport {
+
+ private static final String PACKAGE_PATH = "org.onap.bbs.event.processor";
+ private static final String API_TITLE = "BBS Event Processor";
+ private static final String DESCRIPTION = "This page lists bbs-event-processor REST API details";
+ private static final String VERSION = "1.0";
+ private static final String RESOURCES_PATH = "classpath:/META-INF/resources/";
+ private static final String WEBJARS_PATH = RESOURCES_PATH + "webjars/";
+ private static final String SWAGGER_UI = "swagger-ui.html";
+ private static final String WEBJARS = "/webjars/**";
+
+ /**
+ * Swagger configuration function for hosting it next to spring http website.
+ *
+ * @return Docket
+ */
+ @Bean
+ public Docket api() {
+ return new Docket(DocumentationType.SWAGGER_2)
+ .apiInfo(apiInfo())
+ .select()
+ .apis(RequestHandlerSelectors.basePackage(PACKAGE_PATH))
+ .paths(PathSelectors.any())
+ .build();
+ }
+
+ private ApiInfo apiInfo() {
+ return new ApiInfoBuilder()
+ .title(API_TITLE)
+ .description(DESCRIPTION)
+ .version(VERSION)
+ .build();
+ }
+
+
+ @Override
+ protected void addResourceHandlers(ResourceHandlerRegistry registry) {
+ registry.addResourceHandler(SWAGGER_UI)
+ .addResourceLocations(RESOURCES_PATH);
+
+ registry.addResourceHandler(WEBJARS)
+ .addResourceLocations(WEBJARS_PATH);
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/controllers/BbsEventProcessorController.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/controllers/BbsEventProcessorController.java
new file mode 100644
index 00000000..fda553fa
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/controllers/BbsEventProcessorController.java
@@ -0,0 +1,203 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.controllers;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+import java.util.concurrent.Executors;
+
+import org.onap.bbs.event.processor.pipelines.CpeAuthenticationPipeline;
+import org.onap.bbs.event.processor.pipelines.ReRegistrationPipeline;
+import org.onap.bbs.event.processor.pipelines.Scheduler;
+import org.onap.bbs.event.processor.utilities.LoggingUtil;
+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.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import reactor.core.publisher.Mono;
+
+@RestController
+@Api(value = "BbsEventProcessorController", description = "Manage bbs-event-processor microService")
+public class BbsEventProcessorController {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(BbsEventProcessorController.class);
+
+ private ReRegistrationPipeline reRegistrationPipeline;
+ private CpeAuthenticationPipeline cpeAuthenticationPipeline;
+ private Scheduler scheduler;
+
+ /**
+ * Constructs BBE event processor REST controller.
+ * @param reRegistrationPipeline processing pipeline for polling DMaaP for PNF re-registration events
+ * @param cpeAuthenticationPipeline processing pipeline for polling DMaaP for CPE authentication events
+ * @param scheduler application scheduler
+ */
+ @Autowired
+ public BbsEventProcessorController(ReRegistrationPipeline reRegistrationPipeline,
+ CpeAuthenticationPipeline cpeAuthenticationPipeline,
+ Scheduler scheduler) {
+ this.reRegistrationPipeline = reRegistrationPipeline;
+ this.cpeAuthenticationPipeline = cpeAuthenticationPipeline;
+ this.scheduler = scheduler;
+ }
+
+ /**
+ * Responds to health-check heartbeats.
+ * @return Proper HTTP response based on application health
+ */
+ @GetMapping("heartbeat")
+ @ApiOperation(value = "Returns liveness of bbs-event-processor microService")
+ @ApiResponses(value = {
+ @ApiResponse(code = 200, message = "bbs-event-processor microService is alive"),
+ @ApiResponse(code = 401, message = "Not authorized to view the resource"),
+ @ApiResponse(code = 403, message = "Resource access is forbidden"),
+ @ApiResponse(code = 404, message = "Resource is not found")})
+ public Mono<ResponseEntity<String>> handleHeartBeat() {
+ LOGGER.debug("bbs-event-processor has received a heartbeat request");
+ return Mono.defer(() ->
+ Mono.just(new ResponseEntity<>("bbs-event-processor is alive\n", HttpStatus.OK))
+ );
+ }
+
+ /**
+ * Polls DMaaP for PNF re-registration events just once.
+ * @return Proper HTTP response based on request submission result
+ */
+ @PostMapping("poll-reregistration-events")
+ @ApiOperation(value = "Returns result of request submission. PNF re-registration polling will occur asynchronously")
+ @ApiResponses(value = {
+ @ApiResponse(code = 200, message = "Polling Re-registration events task submitted successfully"),
+ @ApiResponse(code = 401, message = "Not authorized to view the resource"),
+ @ApiResponse(code = 403, message = "Resource access is forbidden"),
+ @ApiResponse(code = 404, message = "Resource is not found")})
+ public Mono<ResponseEntity<String>> handleReRegistrationRestCall() {
+ LOGGER.debug("bbs-event-processor has received a re-registration handling request");
+ Executors.newSingleThreadExecutor().submit(() -> reRegistrationPipeline.processPnfReRegistrationEvents());
+ return Mono.defer(() ->
+ Mono.just(new ResponseEntity<>("Request submitted\n", HttpStatus.OK))
+ );
+ }
+
+ /**
+ * Polls DMaaP for CPE authentication events just once.
+ * @return Proper HTTP response based on request submission result
+ */
+ @PostMapping("poll-cpe-authentication-events")
+ @ApiOperation(value = "Returns result of request submission. CPE authentication polling will occur asynchronously")
+ @ApiResponses(value = {
+ @ApiResponse(code = 200, message = "CPE authentication task submitted successfully"),
+ @ApiResponse(code = 401, message = "Not authorized to view the resource"),
+ @ApiResponse(code = 403, message = "Resource access is forbidden"),
+ @ApiResponse(code = 404, message = "Resource is not found")})
+ public Mono<ResponseEntity<String>> handleCpeAuthenticationRestCall() {
+ LOGGER.debug("bbs-event-processor has received a cpe-authentication handling request");
+ Executors.newSingleThreadExecutor().submit(() -> cpeAuthenticationPipeline.processPnfCpeAuthenticationEvents());
+ return Mono.defer(() ->
+ Mono.just(new ResponseEntity<>("Request submitted\n", HttpStatus.OK))
+ );
+ }
+
+ /**
+ * Reschedules DMaaP polling tasks.
+ * @return Proper HTTP response based on rescheduling result
+ */
+ @PostMapping("start-tasks")
+ @ApiOperation(value = "Returns result of request to start microservice tasks")
+ @ApiResponses(value = {
+ @ApiResponse(code = 200, message = "Tasks were successfully started"),
+ @ApiResponse(code = 401, message = "Not authorized to view the resource"),
+ @ApiResponse(code = 403, message = "Resource access is forbidden"),
+ @ApiResponse(code = 404, message = "Resource is not found"),
+ @ApiResponse(code = 406, message = "Task initiation failed. Check logs")})
+ public Mono<ResponseEntity<String>> reScheduleTasks() {
+ LOGGER.trace("bbs-event-processor has received a request to reschedule all running tasks");
+ if (scheduler.reScheduleProcessingTasks()) {
+ return Mono.defer(() ->
+ Mono.just(new ResponseEntity<>("Initiation of tasks was successful\n", HttpStatus.OK))
+ );
+ } else {
+ return Mono.defer(() ->
+ Mono.just(new ResponseEntity<>("Initiation of tasks failed\n", HttpStatus.NOT_ACCEPTABLE))
+ );
+ }
+ }
+
+ /**
+ * Cancels DMaaP polling tasks.
+ * @return Proper HTTP response based on cancellation result
+ */
+ @PostMapping("cancel-tasks")
+ @ApiOperation(value = "Returns result of request to cancel running microservice tasks")
+ @ApiResponses(value = {
+ @ApiResponse(code = 200, message = "Tasks were successfully cancelled"),
+ @ApiResponse(code = 401, message = "Not authorized to view the resource"),
+ @ApiResponse(code = 403, message = "Resource access is forbidden"),
+ @ApiResponse(code = 404, message = "Resource is not found"),
+ @ApiResponse(code = 406, message = "Cancellation failed. Check logs")})
+ public Mono<ResponseEntity<String>> cancelTasks() {
+ LOGGER.debug("bbs-event-processor has received a request to cancel all running tasks");
+ if (scheduler.cancelScheduledProcessingTasks()) {
+ return Mono.defer(() ->
+ Mono.just(new ResponseEntity<>("Cancellation was successful\n", HttpStatus.OK))
+ );
+ } else {
+ return Mono.defer(() ->
+ Mono.just(new ResponseEntity<>("Cancellation failed\n", HttpStatus.NOT_ACCEPTABLE))
+ );
+ }
+ }
+
+ /**
+ * Change logging level for BBS code.
+ * @param level new logging level
+ * @return Proper HTTP response based on change logging level result
+ */
+ @PostMapping("logging/{level}")
+ @ApiOperation(value = "Returns result of request to change application logging level")
+ @ApiResponses(value = {
+ @ApiResponse(code = 200, message = "Application logging level was successfully changed"),
+ @ApiResponse(code = 401, message = "Not authorized to view the resource"),
+ @ApiResponse(code = 403, message = "Resource access is forbidden"),
+ @ApiResponse(code = 404, message = "Resource is not found"),
+ @ApiResponse(code = 406, message = "Application logging level change failure. Check logs")})
+ public Mono<ResponseEntity<String>> changeLoggingLevel(@PathVariable String level) {
+ return Mono.defer(() -> {
+ if (LoggingUtil.changeLoggingLevel(level)) {
+ LOGGER.info("Changed logging level to {}", level);
+ return Mono.just(new ResponseEntity<>("Changed BBS event processor logging level\n",
+ HttpStatus.OK));
+ } else {
+ return Mono.just(new ResponseEntity<>("Unacceptable logging level\n",
+ HttpStatus.NOT_ACCEPTABLE));
+ }
+ }
+ );
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/AaiTaskException.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/AaiTaskException.java
new file mode 100644
index 00000000..91493573
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/AaiTaskException.java
@@ -0,0 +1,28 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.exceptions;
+
+public class AaiTaskException extends RuntimeException {
+
+ public AaiTaskException(String message) {
+ super(message);
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/ApplicationEnvironmentException.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/ApplicationEnvironmentException.java
new file mode 100644
index 00000000..2103589c
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/ApplicationEnvironmentException.java
@@ -0,0 +1,28 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.exceptions;
+
+public class ApplicationEnvironmentException extends RuntimeException {
+
+ public ApplicationEnvironmentException(String message) {
+ super(message);
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/ConfigurationParsingException.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/ConfigurationParsingException.java
new file mode 100644
index 00000000..55f27111
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/ConfigurationParsingException.java
@@ -0,0 +1,28 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.exceptions;
+
+public class ConfigurationParsingException extends RuntimeException {
+
+ public ConfigurationParsingException(String message) {
+ super(message);
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/DmaapException.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/DmaapException.java
new file mode 100644
index 00000000..d9a02014
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/DmaapException.java
@@ -0,0 +1,28 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.exceptions;
+
+public class DmaapException extends RuntimeException {
+
+ public DmaapException(String message) {
+ super(message);
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/EmptyDmaapResponseException.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/EmptyDmaapResponseException.java
new file mode 100644
index 00000000..1be4f43a
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/exceptions/EmptyDmaapResponseException.java
@@ -0,0 +1,32 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.exceptions;
+
+public class EmptyDmaapResponseException extends RuntimeException {
+
+ public EmptyDmaapResponseException() {
+ super();
+ }
+
+ public EmptyDmaapResponseException(String message) {
+ super(message);
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/AuthenticationState.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/AuthenticationState.java
new file mode 100644
index 00000000..fd170231
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/AuthenticationState.java
@@ -0,0 +1,40 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.model;
+
+import static org.onap.bbs.event.processor.config.ApplicationConstants.IN_SERVICE_NAME_IN_ONAP;
+import static org.onap.bbs.event.processor.config.ApplicationConstants.OUT_OF_SERVICE_NAME_IN_ONAP;
+
+public enum AuthenticationState {
+
+ IN_SERVICE(IN_SERVICE_NAME_IN_ONAP),
+ OUT_OF_SERVICE(OUT_OF_SERVICE_NAME_IN_ONAP);
+
+ private String nameInOnap;
+
+ AuthenticationState(String nameInOnap) {
+ this.nameInOnap = nameInOnap;
+ }
+
+ public String getNameInOnap() {
+ return nameInOnap;
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/ControlLoopPublisherDmaapModel.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/ControlLoopPublisherDmaapModel.java
new file mode 100644
index 00000000..8fa73e42
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/ControlLoopPublisherDmaapModel.java
@@ -0,0 +1,75 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.model;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.Map;
+
+import org.immutables.gson.Gson;
+import org.immutables.value.Value;
+import org.onap.dcaegen2.services.sdk.rest.services.model.DmaapModel;
+
+@Value.Immutable
+@Gson.TypeAdapters(fieldNamingStrategy = true)
+public interface ControlLoopPublisherDmaapModel extends DmaapModel {
+
+ @SerializedName(value = "closedLoopEventClient", alternate = "closedLoopEventClient")
+ String getClosedLoopEventClient();
+
+ @SerializedName(value = "policyVersion", alternate = "policyVersion")
+ String getPolicyVersion();
+
+ @SerializedName(value = "policyName", alternate = "policyName")
+ String getPolicyName();
+
+ @SerializedName(value = "policyScope", alternate = "policyScope")
+ String getPolicyScope();
+
+ @SerializedName(value = "target_type", alternate = "target_type")
+ String getTargetType();
+
+ // It will handle all pieces of information that the microservice needs to send
+ // towards Policy
+ @SerializedName(value = "AAI", alternate = "AAI")
+ Map<String, String> getAaiEnrichmentData();
+
+ @SerializedName(value = "closedLoopAlarmStart", alternate = "closedLoopAlarmStart")
+ long getClosedLoopAlarmStart();
+
+ @SerializedName(value = "closedLoopEventStatus", alternate = "closedLoopEventStatus")
+ String getClosedLoopEventStatus();
+
+ @SerializedName(value = "closedLoopControlName", alternate = "closedLoopControlName")
+ String getClosedLoopControlName();
+
+ @SerializedName(value = "version", alternate = "version")
+ String getVersion();
+
+ @SerializedName(value = "target", alternate = "target")
+ String getTarget();
+
+ @SerializedName(value = "requestID", alternate = "requestID")
+ String getRequestId();
+
+ @SerializedName(value = "from", alternate = "from")
+ String getOriginator();
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/CpeAuthenticationConsumerDmaapModel.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/CpeAuthenticationConsumerDmaapModel.java
new file mode 100644
index 00000000..42c9896f
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/CpeAuthenticationConsumerDmaapModel.java
@@ -0,0 +1,53 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.model;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.Optional;
+
+import org.immutables.gson.Gson;
+import org.immutables.value.Value;
+import org.onap.dcaegen2.services.sdk.rest.services.model.AaiModel;
+import org.onap.dcaegen2.services.sdk.rest.services.model.DmaapModel;
+
+@Value.Immutable
+@Gson.TypeAdapters(fieldNamingStrategy = true)
+public interface CpeAuthenticationConsumerDmaapModel extends AaiModel, DmaapModel {
+
+ @SerializedName(value = "correlationId", alternate = "correlationId")
+ String getCorrelationId();
+
+ @SerializedName(value = "old-authentication-state", alternate = "old-authentication-state")
+ String getOldAuthenticationState();
+
+ @SerializedName(value = "new-authentication-state", alternate = "new-authentication-state")
+ String getNewAuthenticationState();
+
+ @SerializedName(value = "state-interface", alternate = "state-interface")
+ Optional<String> getStateInterface();
+
+ @SerializedName(value = "rgw-mac-address", alternate = "rgw-mac-address")
+ Optional<String> getRgwMacAddress();
+
+ @SerializedName(value = "sw-version", alternate = "sw-version")
+ Optional<String> getSwVersion();
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/GeneratedAppConfigObject.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/GeneratedAppConfigObject.java
new file mode 100644
index 00000000..4fdb81be
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/GeneratedAppConfigObject.java
@@ -0,0 +1,165 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.model;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.Map;
+
+import org.immutables.gson.Gson;
+import org.immutables.value.Value;
+
+@Value.Immutable
+@Gson.TypeAdapters(fieldNamingStrategy = true, emptyAsNulls = true)
+public interface GeneratedAppConfigObject {
+
+ @SerializedName(value = "dmaap.protocol", alternate = "dmaap.protocol")
+ String dmaapProtocol();
+
+ @SerializedName(value = "dmaap.contentType", alternate = "dmaap.contentType")
+ String dmaapContentType();
+
+ @SerializedName(value = "dmaap.consumer.consumerId", alternate = "dmaap.consumer.consumerId")
+ String dmaapConsumerConsumerId();
+
+ @SerializedName(value = "dmaap.consumer.consumerGroup", alternate = "dmaap.consumer.consumerGroup")
+ String dmaapConsumerConsumerGroup();
+
+ @SerializedName(value = "dmaap.messageLimit", alternate = "dmaap.messageLimit")
+ int dmaapMessageLimit();
+
+ @SerializedName(value = "dmaap.timeoutMs", alternate = "dmaap.timeoutMs")
+ int dmaapTimeoutMs();
+
+ @SerializedName(value = "aai.host", alternate = "aai.host")
+ String aaiHost();
+
+ @SerializedName(value = "aai.port", alternate = "aai.port")
+ int aaiPort();
+
+ @SerializedName(value = "aai.protocol", alternate = "aai.protocol")
+ String aaiProtocol();
+
+ @SerializedName(value = "aai.username", alternate = "aai.username")
+ String aaiUsername();
+
+ @SerializedName(value = "aai.password", alternate = "aai.password")
+ String aaiPassword();
+
+ @SerializedName(value = "aai.aaiIgnoreSslCertificateErrors", alternate = "aai.aaiIgnoreSslCertificateErrors")
+ boolean aaiIgnoreSslCertificateErrors();
+
+ @SerializedName(value = "application.pipelinesPollingIntervalSec",
+ alternate = "application.pipelinesPollingIntervalSec")
+ int pipelinesPollingIntervalSec();
+
+ @SerializedName(value = "application.pipelinesTimeoutSec", alternate = "application.pipelinesTimeoutSec")
+ int pipelinesTimeoutSec();
+
+ @SerializedName(value = "application.cbsPollingIntervalSec", alternate = "application.cbsPollingIntervalSec")
+ int cbsPollingIntervalSec();
+
+ @SerializedName(value = "application.reregistration.policyScope",
+ alternate = "application.reregistration.policyScope")
+ String reRegistrationPolicyScope();
+
+ @SerializedName(value = "application.reregistration.clControlName",
+ alternate = "application.reregistration.clControlName")
+ String reRegistrationClControlName();
+
+ @SerializedName(value = "application.cpe.authentication.policyScope",
+ alternate = "application.reregistration.policyScope")
+ String cpeAuthPolicyScope();
+
+ @SerializedName(value = "application.cpe.authentication.clControlName",
+ alternate = "application.reregistration.clControlName")
+ String cpeAuthClControlName();
+
+ @SerializedName(value = "application.policyVersion", alternate = "application.policyVersion")
+ String policyVersion();
+
+ @SerializedName(value = "application.clTargetType", alternate = "application.clTargetType")
+ String closeLoopTargetType();
+
+ @SerializedName(value = "application.clEventStatus", alternate = "application.clEventStatus")
+ String closeLoopEventStatus();
+
+ @SerializedName(value = "application.clVersion", alternate = "application.clVersion")
+ String closeLoopVersion();
+
+ @SerializedName(value = "application.clTarget", alternate = "application.clTarget")
+ String closeLoopTarget();
+
+ @SerializedName(value = "application.clOriginator", alternate = "application.clOriginator")
+ String closeLoopOriginator();
+
+ @SerializedName(value = "application.reregistration.configKey", alternate = "application.reregistration.configKey")
+ String reRegConfigKey();
+
+ @SerializedName(value = "application.cpeAuth.configKey", alternate = "application.cpeAuth.configKey")
+ String cpeAuthConfigKey();
+
+ @SerializedName(value = "application.closeLoop.configKey", alternate = "application.closeLoop.configKey")
+ String closeLoopConfigKey();
+
+ @SerializedName(value = "application.loggingLevel", alternate = "application.loggingLevel")
+ String loggingLevel();
+
+ @SerializedName(value = "streams_subscribes", alternate = "streams_subscribes")
+ Map<String, StreamsObject> streamSubscribesMap();
+
+ @SerializedName(value = "streams_publishes", alternate = "streams_publishes")
+ Map<String, StreamsObject> streamPublishesMap();
+
+ @Value.Immutable
+ @Gson.TypeAdapters(fieldNamingStrategy = true)
+ interface StreamsObject {
+
+ @SerializedName(value = "type", alternate = "type")
+ String type();
+
+ @SerializedName(value = "aaf_username", alternate = "aaf_username")
+ String aafUsername();
+
+ @SerializedName(value = "aaf_password", alternate = "aaf_password")
+ String aafPassword();
+
+ @SerializedName(value = "dmaap_info", alternate = "dmaap_info")
+ DmaapInfo dmaapInfo();
+ }
+
+ @Value.Immutable
+ @Gson.TypeAdapters(fieldNamingStrategy = true)
+ interface DmaapInfo {
+
+ @SerializedName(value = "client_id", alternate = "client_id")
+ String clientId();
+
+ @SerializedName(value = "client_role", alternate = "client_role")
+ String clientRole();
+
+ @SerializedName(value = "location", alternate = "location")
+ String location();
+
+ @SerializedName(value = "topic_url", alternate = "topic_url")
+ String topicUrl();
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/MetadataListAaiObject.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/MetadataListAaiObject.java
new file mode 100644
index 00000000..221fade5
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/MetadataListAaiObject.java
@@ -0,0 +1,48 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.model;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+
+import org.immutables.gson.Gson;
+import org.immutables.value.Value;
+
+@Value.Immutable
+@Gson.TypeAdapters(fieldNamingStrategy = true, emptyAsNulls = true)
+public interface MetadataListAaiObject {
+
+ @SerializedName(value = "metadatum", alternate = "metadatum")
+ List<MetadataEntryAaiObject> getMetadataEntries();
+
+ @Value.Immutable
+ @Gson.TypeAdapters(fieldNamingStrategy = true)
+ interface MetadataEntryAaiObject {
+
+ @SerializedName(value = "metaname", alternate = "metaname")
+ String getMetaname();
+
+ @SerializedName(value = "metaval", alternate = "metaval")
+ String getMetavalue();
+
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/PnfAaiObject.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/PnfAaiObject.java
new file mode 100644
index 00000000..682c0641
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/PnfAaiObject.java
@@ -0,0 +1,47 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.model;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.Optional;
+
+import org.immutables.gson.Gson;
+import org.immutables.value.Value;
+import org.onap.dcaegen2.services.sdk.rest.services.model.ClientModel;
+
+@Value.Immutable
+@Gson.TypeAdapters(fieldNamingStrategy = true, emptyAsNulls = true)
+public interface PnfAaiObject extends ClientModel {
+
+ @SerializedName(value = "pnf-name", alternate = "pnf-name")
+ String getPnfName();
+
+ @SerializedName(value = "in-maint", alternate = "in-maint")
+ boolean isInMaintenance();
+
+ @SerializedName(value = "sw-version", alternate = "sw-version")
+ Optional<String> getSwVersion();
+
+ @SerializedName(value = "relationship-list", alternate = "relationship-list")
+ RelationshipListAaiObject getRelationshipListAaiObject();
+
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/ReRegistrationConsumerDmaapModel.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/ReRegistrationConsumerDmaapModel.java
new file mode 100644
index 00000000..07fb75aa
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/ReRegistrationConsumerDmaapModel.java
@@ -0,0 +1,48 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.model;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.immutables.gson.Gson;
+import org.immutables.value.Value;
+import org.onap.dcaegen2.services.sdk.rest.services.model.AaiModel;
+import org.onap.dcaegen2.services.sdk.rest.services.model.DmaapModel;
+
+@Value.Immutable
+@Gson.TypeAdapters(fieldNamingStrategy = true)
+public interface ReRegistrationConsumerDmaapModel extends AaiModel, DmaapModel {
+
+ @SerializedName(value = "correlationId", alternate = "correlationId")
+ String getCorrelationId();
+
+ @SerializedName(value = "attachment-point", alternate = "attachment-point")
+ String getAttachmentPoint();
+
+ @SerializedName(value = "remote-id", alternate = "remote-id")
+ String getRemoteId();
+
+ @SerializedName(value = "cvlan", alternate = "cvlan")
+ String getCVlan();
+
+ @SerializedName(value = "svlan", alternate = "svlan")
+ String getSVlan();
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/RelationshipListAaiObject.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/RelationshipListAaiObject.java
new file mode 100644
index 00000000..76aab92e
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/RelationshipListAaiObject.java
@@ -0,0 +1,82 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.model;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.immutables.gson.Gson;
+import org.immutables.value.Value;
+
+@Value.Immutable
+@Gson.TypeAdapters(fieldNamingStrategy = true, emptyAsNulls = true)
+public interface RelationshipListAaiObject {
+
+ @SerializedName(value = "relationship", alternate = "relationship")
+ List<RelationshipEntryAaiObject> getRelationshipEntries();
+
+ @Value.Immutable
+ @Gson.TypeAdapters(fieldNamingStrategy = true)
+ interface RelationshipEntryAaiObject {
+
+ @SerializedName(value = "related-to", alternate = "related-to")
+ String getRelatedTo();
+
+ @SerializedName(value = "relationship-label", alternate = "relationship-label")
+ Optional<String> getRelationshipLabel();
+
+ @SerializedName(value = "related-link", alternate = "related-link")
+ String getRelatedLink();
+
+ @SerializedName(value = "relationship-data", alternate = "relationship-data")
+ List<RelationshipDataEntryAaiObject> getRelationshipData();
+
+ @SerializedName(value = "related-to-property", alternate = "related-to-property")
+ Optional<List<PropertyAaiObject>> getRelatedToProperties();
+
+ }
+
+ @Value.Immutable
+ @Gson.TypeAdapters(fieldNamingStrategy = true)
+ interface RelationshipDataEntryAaiObject {
+
+ @SerializedName(value = "relationship-key", alternate = "relationship-key")
+ String getRelationshipKey();
+
+ @SerializedName(value = "relationship-value", alternate = "relationship-value")
+ String getRelationshipValue();
+
+ }
+
+ @Value.Immutable
+ @Gson.TypeAdapters(fieldNamingStrategy = true)
+ interface PropertyAaiObject {
+
+ @SerializedName(value = "property-key", alternate = "property-key")
+ String getPropertyKey();
+
+ @SerializedName(value = "property-value", alternate = "property-value")
+ Optional<String> getPropertyValue();
+
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/ServiceInstanceAaiObject.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/ServiceInstanceAaiObject.java
new file mode 100644
index 00000000..9b2d8ef7
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/model/ServiceInstanceAaiObject.java
@@ -0,0 +1,45 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.model;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.Optional;
+
+import org.immutables.gson.Gson;
+import org.immutables.value.Value;
+
+@Value.Immutable
+@Gson.TypeAdapters(fieldNamingStrategy = true, emptyAsNulls = true)
+public interface ServiceInstanceAaiObject {
+
+ @SerializedName(value = "service-instance-id", alternate = "service-instance-id")
+ String getServiceInstanceId();
+
+ @SerializedName(value = "orchestration-status", alternate = "orchestration-status")
+ Optional<String> getOrchestrationStatus();
+
+ @SerializedName(value = "relationship-list", alternate = "relationship-list")
+ RelationshipListAaiObject getRelationshipListAaiObject();
+
+ @SerializedName(value = "metadata", alternate = "metadata")
+ Optional<MetadataListAaiObject> getMetadataListAaiObject();
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/pipelines/CpeAuthenticationPipeline.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/pipelines/CpeAuthenticationPipeline.java
new file mode 100644
index 00000000..711ab185
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/pipelines/CpeAuthenticationPipeline.java
@@ -0,0 +1,333 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.pipelines;
+
+import static org.onap.bbs.event.processor.config.ApplicationConstants.CONSUME_CPE_AUTHENTICATION_TASK_NAME;
+import static org.onap.bbs.event.processor.config.ApplicationConstants.DCAE_BBS_EVENT_PROCESSOR_MS_INSTANCE;
+import static org.onap.bbs.event.processor.config.ApplicationConstants.RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME;
+import static org.onap.bbs.event.processor.config.ApplicationConstants.RETRIEVE_PNF_TASK_NAME;
+import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.INSTANCE_UUID;
+import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.RESPONSE_CODE;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.TimeoutException;
+
+import javax.net.ssl.SSLException;
+
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.exceptions.EmptyDmaapResponseException;
+import org.onap.bbs.event.processor.model.ControlLoopPublisherDmaapModel;
+import org.onap.bbs.event.processor.model.CpeAuthenticationConsumerDmaapModel;
+import org.onap.bbs.event.processor.model.ImmutableControlLoopPublisherDmaapModel;
+import org.onap.bbs.event.processor.model.MetadataListAaiObject;
+import org.onap.bbs.event.processor.model.PnfAaiObject;
+import org.onap.bbs.event.processor.model.RelationshipListAaiObject;
+import org.onap.bbs.event.processor.model.ServiceInstanceAaiObject;
+import org.onap.bbs.event.processor.tasks.AaiClientTask;
+import org.onap.bbs.event.processor.tasks.DmaapCpeAuthenticationConsumerTask;
+import org.onap.bbs.event.processor.tasks.DmaapPublisherTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+@Component
+public class CpeAuthenticationPipeline {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CpeAuthenticationPipeline.class);
+
+ private static final String POLICY_NAME = "CPE_Authentication";
+
+ private DmaapCpeAuthenticationConsumerTask consumerTask;
+ private DmaapPublisherTask publisherTask;
+ private AaiClientTask aaiClientTask;
+
+ private ApplicationConfiguration configuration;
+
+ private Map<String, String> mdcContextMap;
+
+ @Autowired
+ CpeAuthenticationPipeline(ApplicationConfiguration configuration,
+ DmaapCpeAuthenticationConsumerTask consumerTask,
+ DmaapPublisherTask publisherTask,
+ AaiClientTask aaiClientTask,
+ Map<String, String> mdcContextMap) {
+ this.configuration = configuration;
+ this.consumerTask = consumerTask;
+ this.publisherTask = publisherTask;
+ this.aaiClientTask = aaiClientTask;
+ this.mdcContextMap = mdcContextMap;
+ }
+
+ /**
+ * PNF CPE Authentication processing pipeline for BBS uS.
+ */
+ public void processPnfCpeAuthenticationEvents() {
+ MDC.setContextMap(mdcContextMap);
+ LOGGER.info("Process next CPE Authentication events");
+ executePipeline()
+ .subscribe(this::onSuccess, this::onError, this::onComplete);
+ LOGGER.trace("Reactive CPE Authentication pipeline subscribed - Execution started");
+ }
+
+ Flux<ResponseEntity<String>> executePipeline() {
+ return
+ // Consume CPE Authentication from DMaaP
+ consumeCpeAuthenticationFromDmaap()
+ // Fetch PNF from A&AI
+ .flatMap(this::fetchPnfFromAai)
+ // Fetch related HSI CFS instance from A&AI
+ .flatMap(this::fetchHsiCfsServiceInstanceFromAai)
+ // Trigger Policy for relocation
+ .flatMap(this::triggerPolicy);
+ }
+
+ private void onSuccess(ResponseEntity<String> responseCode) {
+ MDC.put(RESPONSE_CODE, responseCode.getStatusCode().toString());
+ LOGGER.info("CPE Authentication event successfully handled. "
+ + "Publishing to DMaaP for Policy returned a status code of ({} {})",
+ responseCode.getStatusCode().value(), responseCode.getStatusCode().getReasonPhrase());
+ MDC.remove(RESPONSE_CODE);
+ }
+
+ private void onError(Throwable throwable) {
+ LOGGER.error("Aborted CPE Authentication events processing. Error: {}", throwable.getMessage());
+ }
+
+ private void onComplete() {
+ LOGGER.info("CPE Authentication processing pipeline has been completed");
+ }
+
+ private Flux<PipelineState> consumeCpeAuthenticationFromDmaap() {
+ return Flux.defer(() -> {
+ MDC.put(INSTANCE_UUID, UUID.randomUUID().toString());
+ try {
+ return consumerTask.execute(CONSUME_CPE_AUTHENTICATION_TASK_NAME)
+ .timeout(Duration.ofSeconds(configuration.getPipelinesTimeoutInSeconds()))
+ .doOnError(e -> {
+ if (e instanceof TimeoutException) {
+ LOGGER.warn("Timed out waiting for DMaaP response");
+ } else if (e instanceof EmptyDmaapResponseException) {
+ LOGGER.info("Nothing to consume from DMaaP");
+ } else {
+ LOGGER.error("DMaaP Consumer error: {}", e.getMessage());
+ LOGGER.debug("Error\n", e);
+ }
+ })
+ .onErrorResume(
+ e -> e instanceof Exception,
+ e -> Mono.empty())
+ .map(event -> {
+ // For each message, we have to keep separate state. This state will be enhanced
+ // in each step and handed off to the next processing step
+ PipelineState state = new PipelineState();
+ state.setCpeAuthenticationEvent(event);
+ return state;
+ });
+ } catch (SSLException e) {
+ return Flux.error(e);
+ }
+ });
+ }
+
+ private Mono<PipelineState> fetchPnfFromAai(PipelineState state) {
+
+ CpeAuthenticationConsumerDmaapModel vesEvent = state.getCpeAuthenticationEvent();
+ String pnfName = vesEvent.getCorrelationId();
+ String url = String.format("/aai/v14/network/pnfs/pnf/%s?depth=all", pnfName);
+ LOGGER.debug("Processing Step: Retrieve PNF. Url: ({})", url);
+
+ return aaiClientTask.executePnfRetrieval(RETRIEVE_PNF_TASK_NAME, url)
+ .timeout(Duration.ofSeconds(configuration.getPipelinesTimeoutInSeconds()))
+ .doOnError(TimeoutException.class,
+ e -> LOGGER.warn("Timed out waiting for A&AI response")
+ )
+ .doOnError(e -> LOGGER.error("Error while retrieving PNF: {}",
+ e.getMessage())
+ )
+ .onErrorResume(
+ e -> e instanceof Exception,
+ e -> Mono.empty())
+ .map(p -> {
+ state.setPnfAaiObject(p);
+ return state;
+ });
+ }
+
+ private Mono<PipelineState> fetchHsiCfsServiceInstanceFromAai(PipelineState state) {
+
+ if (state == null || state.getPnfAaiObject() == null) {
+ return Mono.empty();
+ }
+
+ PnfAaiObject pnf = state.getPnfAaiObject();
+ // Assuming that the PNF will only have a single service-instance relationship pointing
+ // towards the HSI CFS service
+ String serviceInstanceId = pnf.getRelationshipListAaiObject().getRelationshipEntries()
+ .stream()
+ .filter(e -> "service-instance".equals(e.getRelatedTo()))
+ .flatMap(e -> e.getRelationshipData().stream())
+ .filter(d -> "service-instance.service-instance-id".equals(d.getRelationshipKey()))
+ .map(RelationshipListAaiObject.RelationshipDataEntryAaiObject::getRelationshipValue)
+ .findFirst().orElse("");
+
+ if (StringUtils.isEmpty(serviceInstanceId)) {
+ LOGGER.error("Unable to retrieve HSI CFS service instance from PNF {}",
+ state.getPnfAaiObject().getPnfName());
+ return Mono.empty();
+ }
+
+ String url = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ serviceInstanceId);
+ LOGGER.debug("Processing Step: Retrieve HSI CFS Service. Url: ({})", url);
+ return aaiClientTask.executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, url)
+ .timeout(Duration.ofSeconds(configuration.getPipelinesTimeoutInSeconds()))
+ .doOnError(TimeoutException.class,
+ e -> LOGGER.warn("Timed out waiting for A&AI response")
+ )
+ .doOnError(e -> LOGGER.error("Error while retrieving HSI CFS Service instance: {}",
+ e.getMessage())
+ )
+ .onErrorResume(
+ e -> e instanceof Exception,
+ e -> Mono.empty())
+ .map(s -> {
+ state.setHsiCfsServiceInstance(s);
+ return state;
+ });
+ }
+
+ private Mono<ResponseEntity<String>> triggerPolicy(PipelineState state) {
+
+ if (state == null || state.getHsiCfsServiceInstance() == null) {
+ return Mono.empty();
+ }
+
+ // At this point, we must check if the PNF RGW MAC address matches the value extracted from VES event
+ if (!isCorrectMacAddress(state)) {
+ LOGGER.warn("Processing stopped. RGW MAC address taken from event ({}) "
+ + "does not match with A&AI metadata corresponding value",
+ state.getCpeAuthenticationEvent().getRgwMacAddress());
+ return Mono.empty();
+ }
+
+ ControlLoopPublisherDmaapModel event = buildTriggeringPolicyEvent(state);
+ return publisherTask.execute(event)
+ .timeout(Duration.ofSeconds(configuration.getPipelinesTimeoutInSeconds()))
+ .doOnError(TimeoutException.class,
+ e -> LOGGER.warn("Timed out waiting for DMaaP publish confirmation")
+ )
+ .doOnError(e -> LOGGER.error("Error while triggering Policy: {}", e.getMessage()))
+ .onErrorResume(
+ e -> e instanceof Exception,
+ e -> Mono.empty());
+ }
+
+
+ private boolean isCorrectMacAddress(PipelineState state) {
+ // We need to check if the RGW MAC address received in VES event matches the one found in
+ // HSIA CFS service (in its metadata section)
+ Optional<MetadataListAaiObject> optionalMetadata = state.getHsiCfsServiceInstance()
+ .getMetadataListAaiObject();
+ String eventRgwMacAddress = state.getCpeAuthenticationEvent().getRgwMacAddress().orElse("");
+ return optionalMetadata
+ .map(list -> list.getMetadataEntries()
+ .stream()
+ .anyMatch(m -> "rgw-mac-address".equals(m.getMetaname())
+ && m.getMetavalue().equals(eventRgwMacAddress)))
+ .orElse(false);
+ }
+
+ private ControlLoopPublisherDmaapModel buildTriggeringPolicyEvent(PipelineState state) {
+
+ String cfsServiceInstanceId = state.getHsiCfsServiceInstance().getServiceInstanceId();
+
+ Map<String, String> enrichmentData = new HashMap<>();
+ enrichmentData.put("service-information.hsia-cfs-service-instance-id", cfsServiceInstanceId);
+ enrichmentData.put("cpe.old-authentication-state", state.cpeAuthenticationEvent.getOldAuthenticationState());
+ enrichmentData.put("cpe.new-authentication-state", state.cpeAuthenticationEvent.getNewAuthenticationState());
+ String swVersion = state.getCpeAuthenticationEvent().getSwVersion().orElse("");
+ if (!StringUtils.isEmpty(swVersion)) {
+ enrichmentData.put("cpe.swVersion", swVersion);
+ }
+
+ ControlLoopPublisherDmaapModel triggerEvent = ImmutableControlLoopPublisherDmaapModel.builder()
+ .closedLoopEventClient(DCAE_BBS_EVENT_PROCESSOR_MS_INSTANCE)
+ .policyVersion(configuration.getPolicyVersion())
+ .policyName(POLICY_NAME)
+ .policyScope(configuration.getCpeAuthenticationCloseLoopPolicyScope())
+ .targetType(configuration.getCloseLoopTargetType())
+ .aaiEnrichmentData(enrichmentData)
+ .closedLoopAlarmStart(Instant.now().getEpochSecond())
+ .closedLoopEventStatus(configuration.getCloseLoopEventStatus())
+ .closedLoopControlName(configuration.getCpeAuthenticationCloseLoopControlName())
+ .version(configuration.getCloseLoopVersion())
+ .target(configuration.getCloseLoopTarget())
+ .requestId(UUID.randomUUID().toString())
+ .originator(configuration.getCloseLoopOriginator())
+ .build();
+ LOGGER.debug("Processing Step: Publish for Policy");
+ LOGGER.trace("Trigger Policy event: ({})",triggerEvent);
+ return triggerEvent;
+ }
+
+ private static class PipelineState {
+
+ private CpeAuthenticationConsumerDmaapModel cpeAuthenticationEvent;
+ private PnfAaiObject pnfAaiObject;
+ private ServiceInstanceAaiObject hsiCfsServiceInstance;
+
+ CpeAuthenticationConsumerDmaapModel getCpeAuthenticationEvent() {
+ return cpeAuthenticationEvent;
+ }
+
+ void setCpeAuthenticationEvent(CpeAuthenticationConsumerDmaapModel cpeAuthenticationEvent) {
+ this.cpeAuthenticationEvent = cpeAuthenticationEvent;
+ }
+
+ PnfAaiObject getPnfAaiObject() {
+ return pnfAaiObject;
+ }
+
+ void setPnfAaiObject(PnfAaiObject pnfAaiObject) {
+ this.pnfAaiObject = pnfAaiObject;
+ }
+
+ ServiceInstanceAaiObject getHsiCfsServiceInstance() {
+ return hsiCfsServiceInstance;
+ }
+
+ void setHsiCfsServiceInstance(ServiceInstanceAaiObject hsiCfsServiceInstance) {
+ this.hsiCfsServiceInstance = hsiCfsServiceInstance;
+ }
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/pipelines/ReRegistrationPipeline.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/pipelines/ReRegistrationPipeline.java
new file mode 100644
index 00000000..9a42ed21
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/pipelines/ReRegistrationPipeline.java
@@ -0,0 +1,347 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.pipelines;
+
+import static org.onap.bbs.event.processor.config.ApplicationConstants.CONSUME_REREGISTRATION_TASK_NAME;
+import static org.onap.bbs.event.processor.config.ApplicationConstants.DCAE_BBS_EVENT_PROCESSOR_MS_INSTANCE;
+import static org.onap.bbs.event.processor.config.ApplicationConstants.RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME;
+import static org.onap.bbs.event.processor.config.ApplicationConstants.RETRIEVE_PNF_TASK_NAME;
+import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.INSTANCE_UUID;
+import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.RESPONSE_CODE;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.TimeoutException;
+
+import javax.net.ssl.SSLException;
+
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.exceptions.EmptyDmaapResponseException;
+import org.onap.bbs.event.processor.model.ControlLoopPublisherDmaapModel;
+import org.onap.bbs.event.processor.model.ImmutableControlLoopPublisherDmaapModel;
+import org.onap.bbs.event.processor.model.PnfAaiObject;
+import org.onap.bbs.event.processor.model.ReRegistrationConsumerDmaapModel;
+import org.onap.bbs.event.processor.model.RelationshipListAaiObject;
+import org.onap.bbs.event.processor.model.ServiceInstanceAaiObject;
+import org.onap.bbs.event.processor.tasks.AaiClientTask;
+import org.onap.bbs.event.processor.tasks.DmaapPublisherTask;
+import org.onap.bbs.event.processor.tasks.DmaapReRegistrationConsumerTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+@Component
+public class ReRegistrationPipeline {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ReRegistrationPipeline.class);
+
+ private static final String POLICY_NAME = "Nomadic_ONT";
+
+ private DmaapReRegistrationConsumerTask consumerTask;
+ private DmaapPublisherTask publisherTask;
+ private AaiClientTask aaiClientTask;
+
+ private ApplicationConfiguration configuration;
+
+ private Map<String, String> mdcContextMap;
+
+ @Autowired
+ ReRegistrationPipeline(ApplicationConfiguration configuration,
+ DmaapReRegistrationConsumerTask consumerTask,
+ DmaapPublisherTask publisherTask,
+ AaiClientTask aaiClientTask,
+ Map<String, String> mdcContextMap) {
+ this.configuration = configuration;
+ this.consumerTask = consumerTask;
+ this.publisherTask = publisherTask;
+ this.aaiClientTask = aaiClientTask;
+ this.mdcContextMap = mdcContextMap;
+ }
+
+ /**
+ * PNF re-registration processing pipeline for BBS uS.
+ */
+ public void processPnfReRegistrationEvents() {
+ MDC.setContextMap(mdcContextMap);
+ LOGGER.info("Process next Re-Registration events");
+ executePipeline()
+ .subscribe(this::onSuccess, this::onError, this::onComplete);
+ LOGGER.trace("Reactive PNF Re-registration pipeline subscribed - Execution started");
+ }
+
+ Flux<ResponseEntity<String>> executePipeline() {
+ return
+ // Consume Re-Registration from DMaaP
+ consumeReRegistrationsFromDmaap()
+ // Fetch PNF from A&AI
+ .flatMap(this::fetchPnfFromAai)
+ // Fetch related HSI CFS instance from A&AI
+ .flatMap(this::fetchHsiCfsServiceInstanceFromAai)
+ // Trigger Policy for relocation
+ .flatMap(this::triggerPolicy);
+ }
+
+ private void onSuccess(ResponseEntity<String> responseCode) {
+ MDC.put(RESPONSE_CODE, responseCode.getStatusCode().toString());
+ LOGGER.info("PNF Re-Registration event successfully handled. "
+ + "Publishing to DMaaP for Policy returned a status code of ({} {})",
+ responseCode.getStatusCode().value(), responseCode.getStatusCode().getReasonPhrase());
+ MDC.remove(RESPONSE_CODE);
+ }
+
+ private void onError(Throwable throwable) {
+ LOGGER.error("Aborted PNF Re-Registration events processing. Error: {}", throwable.getMessage());
+ }
+
+ private void onComplete() {
+ LOGGER.info("PNF Re-Registration processing pipeline has been completed");
+ }
+
+ private Flux<PipelineState> consumeReRegistrationsFromDmaap() {
+ return Flux.defer(() -> {
+ MDC.put(INSTANCE_UUID, UUID.randomUUID().toString());
+ try {
+ return consumerTask.execute(CONSUME_REREGISTRATION_TASK_NAME)
+ .timeout(Duration.ofSeconds(configuration.getPipelinesTimeoutInSeconds()))
+ .doOnError(e -> {
+ if (e instanceof TimeoutException) {
+ LOGGER.warn("Timed out waiting for DMaaP response");
+ } else if (e instanceof EmptyDmaapResponseException) {
+ LOGGER.info("Nothing to consume from DMaaP");
+ } else {
+ LOGGER.error("DMaaP Consumer error: {}", e.getMessage());
+ LOGGER.debug("Error\n", e);
+ }
+ })
+ .onErrorResume(
+ e -> e instanceof Exception,
+ e -> Mono.empty())
+ .map(event -> {
+ // For each message, we have to keep separate state. This state will be enhanced
+ // in each step and handed off to the next processing step
+ PipelineState state = new PipelineState();
+ state.setReRegistrationEvent(event);
+ return state;
+ });
+ } catch (SSLException e) {
+ return Flux.error(e);
+ }
+ });
+ }
+
+ private Mono<PipelineState> fetchPnfFromAai(PipelineState state) {
+
+ ReRegistrationConsumerDmaapModel vesEvent = state.getReRegistrationEvent();
+ String pnfName = vesEvent.getCorrelationId();
+ String url = String.format("/aai/v14/network/pnfs/pnf/%s?depth=all", pnfName);
+ LOGGER.debug("Processing Step: Retrieve PNF. Url: ({})", url);
+
+ return aaiClientTask.executePnfRetrieval(RETRIEVE_PNF_TASK_NAME, url)
+ .timeout(Duration.ofSeconds(configuration.getPipelinesTimeoutInSeconds()))
+ .doOnError(TimeoutException.class,
+ e -> LOGGER.warn("Timed out waiting for A&AI response")
+ )
+ .doOnError(e -> LOGGER.error("Error while retrieving PNF: {}",
+ e.getMessage())
+ )
+ .onErrorResume(
+ e -> e instanceof Exception,
+ e -> Mono.empty())
+ .map(p -> {
+ state.setPnfAaiObject(p);
+ return state;
+ });
+ }
+
+ private Mono<PipelineState> fetchHsiCfsServiceInstanceFromAai(PipelineState state) {
+
+ if (state == null || state.getPnfAaiObject() == null) {
+ return Mono.empty();
+ }
+
+ // At this point, we have both the VES-event of the re-registration and the PNF object retrieved from A&AI
+ // We can check if this processing needs to continue in case of a true relocation
+ if (isNotReallyAnOntRelocation(state)) {
+ return Mono.empty();
+ }
+
+ PnfAaiObject pnf = state.getPnfAaiObject();
+ // Assuming that the PNF will only have a single service-instance relationship pointing
+ // towards the HSI CFS service
+ String serviceInstanceId = pnf.getRelationshipListAaiObject().getRelationshipEntries()
+ .stream()
+ .filter(e -> "service-instance".equals(e.getRelatedTo()))
+ .flatMap(e -> e.getRelationshipData().stream())
+ .filter(d -> "service-instance.service-instance-id".equals(d.getRelationshipKey()))
+ .map(RelationshipListAaiObject.RelationshipDataEntryAaiObject::getRelationshipValue)
+ .findFirst().orElse("");
+
+ if (StringUtils.isEmpty(serviceInstanceId)) {
+ LOGGER.error("Unable to retrieve HSI CFS service instance from PNF {}",
+ state.getPnfAaiObject().getPnfName());
+ return Mono.empty();
+ }
+
+ String url = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ serviceInstanceId);
+ LOGGER.debug("Processing Step: Retrieve HSI CFS Service. Url: ({})", url);
+ return aaiClientTask.executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, url)
+ .timeout(Duration.ofSeconds(configuration.getPipelinesTimeoutInSeconds()))
+ .doOnError(TimeoutException.class,
+ e -> LOGGER.warn("Timed out waiting for A&AI response")
+ )
+ .doOnError(e -> LOGGER.error("Error while retrieving HSI CFS Service instance: {}",
+ e.getMessage())
+ )
+ .onErrorResume(
+ e -> e instanceof Exception,
+ e -> Mono.empty())
+ .map(s -> {
+ state.setHsiCfsServiceInstance(s);
+ return state;
+ });
+ }
+
+ private boolean isNotReallyAnOntRelocation(PipelineState state) {
+ List<RelationshipListAaiObject.RelationshipEntryAaiObject> relationshipEntries =
+ state.getPnfAaiObject().getRelationshipListAaiObject().getRelationshipEntries();
+
+ // If no logical-link, fail further processing
+ if (relationshipEntries.stream().noneMatch(e -> "logical-link".equals(e.getRelatedTo()))) {
+ LOGGER.warn("PNF {} does not have any logical-links bridged. Stop further processing",
+ state.getPnfAaiObject().getPnfName());
+ return true;
+ }
+
+ // Assuming PNF will only have one logical-link per BBS use case design
+ boolean isNotRelocation = relationshipEntries
+ .stream()
+ .filter(e -> "logical-link".equals(e.getRelatedTo()))
+ .flatMap(e -> e.getRelationshipData().stream())
+ .anyMatch(d -> d.getRelationshipValue()
+ .equals(state.getReRegistrationEvent().getAttachmentPoint()));
+
+
+ if (isNotRelocation) {
+ LOGGER.warn("Not a Relocation for PNF {} with attachment point {}",
+ state.getPnfAaiObject().getPnfName(),
+ state.getReRegistrationEvent().getAttachmentPoint());
+ }
+ return isNotRelocation;
+ }
+
+ private Mono<ResponseEntity<String>> triggerPolicy(PipelineState state) {
+
+ if (state == null || state.getHsiCfsServiceInstance() == null) {
+ return Mono.empty();
+ }
+
+ ControlLoopPublisherDmaapModel event = buildTriggeringPolicyEvent(state);
+ return publisherTask.execute(event)
+ .timeout(Duration.ofSeconds(configuration.getPipelinesTimeoutInSeconds()))
+ .doOnError(TimeoutException.class,
+ e -> LOGGER.warn("Timed out waiting for DMaaP confirmation")
+ )
+ .doOnError(e -> LOGGER.error("Error while triggering Policy: {}", e.getMessage()))
+ .onErrorResume(
+ e -> e instanceof Exception,
+ e -> Mono.empty());
+ }
+
+ private ControlLoopPublisherDmaapModel buildTriggeringPolicyEvent(PipelineState state) {
+
+ String cfsServiceInstanceId = state.getHsiCfsServiceInstance().getServiceInstanceId();
+
+ String attachmentPoint = state.getReRegistrationEvent().getAttachmentPoint();
+ String remoteId = state.getReRegistrationEvent().getRemoteId();
+ String cvlan = state.getReRegistrationEvent().getCVlan();
+ String svlan = state.getReRegistrationEvent().getSVlan();
+
+ Map<String, String> enrichmentData = new HashMap<>();
+ enrichmentData.put("service-information.hsia-cfs-service-instance-id", cfsServiceInstanceId);
+
+ enrichmentData.put("attachmentPoint", attachmentPoint);
+ enrichmentData.put("remoteId", remoteId);
+ enrichmentData.put("cvlan", cvlan);
+ enrichmentData.put("svlan", svlan);
+
+ ControlLoopPublisherDmaapModel triggerEvent = ImmutableControlLoopPublisherDmaapModel.builder()
+ .closedLoopEventClient(DCAE_BBS_EVENT_PROCESSOR_MS_INSTANCE)
+ .policyVersion(configuration.getPolicyVersion())
+ .policyName(POLICY_NAME)
+ .policyScope(configuration.getReRegistrationCloseLoopPolicyScope())
+ .targetType(configuration.getCloseLoopTargetType())
+ .aaiEnrichmentData(enrichmentData)
+ .closedLoopAlarmStart(Instant.now().getEpochSecond())
+ .closedLoopEventStatus(configuration.getCloseLoopEventStatus())
+ .closedLoopControlName(configuration.getReRegistrationCloseLoopControlName())
+ .version(configuration.getCloseLoopVersion())
+ .target(configuration.getCloseLoopTarget())
+ .requestId(UUID.randomUUID().toString())
+ .originator(configuration.getCloseLoopOriginator())
+ .build();
+ LOGGER.debug("Processing Step: Publish for Policy");
+ LOGGER.trace("Trigger Policy event: ({})",triggerEvent);
+ return triggerEvent;
+ }
+
+ private static class PipelineState {
+
+ private ReRegistrationConsumerDmaapModel reRegistrationEvent;
+ private PnfAaiObject pnfAaiObject;
+ private ServiceInstanceAaiObject hsiCfsServiceInstance;
+
+ ReRegistrationConsumerDmaapModel getReRegistrationEvent() {
+ return reRegistrationEvent;
+ }
+
+ void setReRegistrationEvent(ReRegistrationConsumerDmaapModel reRegistrationEvent) {
+ this.reRegistrationEvent = reRegistrationEvent;
+ }
+
+ PnfAaiObject getPnfAaiObject() {
+ return pnfAaiObject;
+ }
+
+ void setPnfAaiObject(PnfAaiObject pnfAaiObject) {
+ this.pnfAaiObject = pnfAaiObject;
+ }
+
+ ServiceInstanceAaiObject getHsiCfsServiceInstance() {
+ return hsiCfsServiceInstance;
+ }
+
+ void setHsiCfsServiceInstance(ServiceInstanceAaiObject hsiCfsServiceInstance) {
+ this.hsiCfsServiceInstance = hsiCfsServiceInstance;
+ }
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/pipelines/Scheduler.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/pipelines/Scheduler.java
new file mode 100644
index 00000000..5fbb0875
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/pipelines/Scheduler.java
@@ -0,0 +1,245 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.pipelines;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledFuture;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.config.ConfigurationChangeObserver;
+import org.onap.bbs.event.processor.config.ConsulConfigurationGateway;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.TaskScheduler;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@Configuration
+@EnableScheduling
+public class Scheduler implements ConfigurationChangeObserver {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Scheduler.class);
+
+ private static final int PIPELINES_INITIAL_DELAY_IN_SECONDS = 10;
+ private static final int DEFAULT_PIPELINES_POLLING_INTERVAL = 15;
+ private static final Duration CBS_INITIAL_DELAY = Duration.ofSeconds(1);
+ private static final int DEFAULT_CBS_POLLING_INTERVAL = 30;
+
+ private final ConsulConfigurationGateway configurationGateway;
+ private final TaskScheduler taskScheduler;
+ private final ReRegistrationPipeline reRegistrationPipeline;
+ private final CpeAuthenticationPipeline cpeAuthenticationPipeline;
+ private ApplicationConfiguration configuration;
+ private Map<String, ScheduledFuture> processingScheduledTasks;
+ private ScheduledFuture cbsScheduledTask;
+ private int currentPipelinesPollingInterval;
+ private int currentCbsPollingInterval;
+
+ @Autowired
+ Scheduler(ApplicationConfiguration configuration,
+ ConsulConfigurationGateway configurationGateway,
+ TaskScheduler taskScheduler,
+ ReRegistrationPipeline reRegistrationPipeline,
+ CpeAuthenticationPipeline cpeAuthenticationPipeline) {
+ this.configuration = configuration;
+ this.configurationGateway = configurationGateway;
+ this.taskScheduler = taskScheduler;
+ this.reRegistrationPipeline = reRegistrationPipeline;
+ this.cpeAuthenticationPipeline = cpeAuthenticationPipeline;
+ processingScheduledTasks = new ConcurrentHashMap<>();
+ }
+
+ /**
+ * Sets up Scheduler.
+ *
+ * <p>Initiates CBS configuration fetch periodic task and DMaaP PNF re-registration and CPE
+ * authentication event polling tasks.</p>
+ *
+ * <p>It also registers for application configuration changes notifications.</p>
+ */
+ @PostConstruct
+ public void setupScheduler() {
+
+ // Initiate periodic configuration fetching from CBS
+ currentCbsPollingInterval = verifyCbsPollingInterval();
+ cbsScheduledTask =
+ taskScheduler.schedule(() -> configurationGateway.periodicallyFetchConfigFromCbs(CBS_INITIAL_DELAY,
+ Duration.ofSeconds(currentCbsPollingInterval)), Instant.now());
+
+ // Initiate Processing tasks
+ currentPipelinesPollingInterval = validatePipelinesPollingInterval();
+ LOGGER.info("BBS event processing pipelines will start in {} seconds "
+ + "and will run periodically every {} seconds", PIPELINES_INITIAL_DELAY_IN_SECONDS,
+ currentPipelinesPollingInterval);
+ Instant desiredStartTime = Instant.now().plusSeconds(PIPELINES_INITIAL_DELAY_IN_SECONDS);
+ scheduleProcessingTasks(desiredStartTime, currentPipelinesPollingInterval);
+
+ // Register for configuration changes
+ configuration.register(this);
+ }
+
+ /**
+ * Un-registers from getting application configuration changes notifications.
+ */
+ @PreDestroy
+ public void unRegisterAsConfigChangeObserver() {
+ configuration.unRegister(this);
+ }
+
+ @Override
+ public void updateConfiguration() {
+ if (configuration.getPipelinesPollingIntervalInSeconds() != currentPipelinesPollingInterval) {
+ LOGGER.info("Pipelines Polling interval has changed. Re-scheduling processing pipelines");
+ cancelScheduledProcessingTasks();
+ reScheduleProcessingTasks();
+ }
+ int newCbsPollingInterval = configuration.getCbsPollingInterval();
+ if (newCbsPollingInterval != currentCbsPollingInterval) {
+ if (newCbsPollingInterval < DEFAULT_CBS_POLLING_INTERVAL) {
+ LOGGER.warn("CBS Polling interval is too small ({}). Will not re-schedule CBS job",
+ newCbsPollingInterval);
+ } else {
+ rescheduleCbsScheduledTask(newCbsPollingInterval);
+ }
+ }
+ }
+
+ private void rescheduleCbsScheduledTask(int newCbsPollingInterval) {
+ LOGGER.info("CBS Polling interval has changed. Re-scheduling CBS job");
+ currentCbsPollingInterval = newCbsPollingInterval;
+ if (!cbsScheduledTask.isDone()) {
+ if (cbsScheduledTask.cancel(true)) {
+ LOGGER.debug("CBS task has been cancelled");
+ } else {
+ LOGGER.error("Error while cancelling CBS task. Task status (isDone/isCanceled) is ({}/{})",
+ cbsScheduledTask.isDone(), cbsScheduledTask.isCancelled());
+ }
+ }
+ cbsScheduledTask = taskScheduler.schedule(() ->
+ configurationGateway.rescheduleCbsConfigurationRetrieval(CBS_INITIAL_DELAY,
+ Duration.ofSeconds(currentCbsPollingInterval)), Instant.now());
+ }
+
+ /**
+ * Cancels DMaaP polling tasks (PNF re-registration & CPE authentication).
+ * @return Tasks cancellation result
+ */
+ public boolean cancelScheduledProcessingTasks() {
+
+ if (processingScheduledTasks.isEmpty()) {
+ LOGGER.debug("No tasks found to cancel");
+ return true;
+ }
+
+ processingScheduledTasks.forEach((key, value) -> {
+ if (value.cancel(false)) {
+ LOGGER.debug("Task {} has been cancelled", key);
+ } else {
+ LOGGER.error("Error while cancelling task {}. Task status (isDone/isCanceled) is ({}/{})",
+ key, value.isDone(), value.isCancelled());
+ }
+ });
+ processingScheduledTasks.entrySet().removeIf(entry -> entry.getValue().isCancelled());
+ LOGGER.info("All cancelled tasks have been removed");
+ return processingScheduledTasks.isEmpty();
+ }
+
+ /**
+ * Reschedules DMaaP polling tasks (PNF re-registration & CPE authentication).
+ * @return Tasks rescheduling result
+ */
+ public boolean reScheduleProcessingTasks() {
+
+ if (processingScheduledTasks.size() != 0) {
+ // If every task is cancelled, we can remove and re-schedule
+ if (processingScheduledTasks.entrySet().stream()
+ .allMatch(e -> e.getValue().isCancelled())) {
+ processingScheduledTasks.clear();
+ LOGGER.debug("Old cancelled tasks have been removed");
+ } else {
+ LOGGER.error("Cannot reschedule. There are {} active tasks that must be first cancelled",
+ processingScheduledTasks.entrySet().stream()
+ .filter(e -> !e.getValue().isCancelled())
+ .count()
+ );
+ return false;
+ }
+ }
+ currentPipelinesPollingInterval = validatePipelinesPollingInterval();
+ LOGGER.info("Reschedule tasks");
+ scheduleProcessingTasks(Instant.now(), currentPipelinesPollingInterval);
+ return true;
+ }
+
+ int numberOfTotalTasks() {
+ return processingScheduledTasks.size();
+ }
+
+ long numberOfActiveTasks() {
+ return processingScheduledTasks.entrySet().stream()
+ .filter(e -> (!e.getValue().isCancelled()))
+ .count();
+ }
+
+ long numberOfCancelledTasks() {
+ return processingScheduledTasks.entrySet().stream()
+ .filter(e -> (e.getValue().isCancelled()))
+ .count();
+ }
+
+ private void scheduleProcessingTasks(Instant desiredStartTime, int pollingInterval) {
+ processingScheduledTasks.put("Re-registration",
+ taskScheduler.scheduleAtFixedRate(reRegistrationPipeline::processPnfReRegistrationEvents,
+ desiredStartTime, Duration.ofSeconds(pollingInterval)));
+ processingScheduledTasks.put("CPE Authentication",
+ taskScheduler.scheduleAtFixedRate(cpeAuthenticationPipeline::processPnfCpeAuthenticationEvents,
+ desiredStartTime, Duration.ofSeconds(pollingInterval)));
+ }
+
+ private int validatePipelinesPollingInterval() {
+ int pipelinesPollingInterval = configuration.getPipelinesPollingIntervalInSeconds();
+ boolean isSmallInterval = pipelinesPollingInterval < DEFAULT_PIPELINES_POLLING_INTERVAL;
+ int verifiedInterval = isSmallInterval ? DEFAULT_PIPELINES_POLLING_INTERVAL : pipelinesPollingInterval;
+ if (isSmallInterval) {
+ LOGGER.warn("Pipelines Polling interval is too small ({}). Defaulting to {}", pipelinesPollingInterval,
+ DEFAULT_PIPELINES_POLLING_INTERVAL);
+ }
+ return verifiedInterval;
+ }
+
+ private int verifyCbsPollingInterval() {
+ int cbsPollingInterval = configuration.getCbsPollingInterval();
+ boolean isSmallInterval = cbsPollingInterval < DEFAULT_CBS_POLLING_INTERVAL;
+ int verifiedInterval = isSmallInterval ? DEFAULT_CBS_POLLING_INTERVAL : cbsPollingInterval;
+ if (isSmallInterval) {
+ LOGGER.warn("CBS Polling interval is too small ({}). Defaulting to {}", cbsPollingInterval,
+ DEFAULT_CBS_POLLING_INTERVAL);
+ }
+ return verifiedInterval;
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/AaiClientTask.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/AaiClientTask.java
new file mode 100644
index 00000000..377fe0f6
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/AaiClientTask.java
@@ -0,0 +1,33 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.tasks;
+
+import org.onap.bbs.event.processor.model.PnfAaiObject;
+import org.onap.bbs.event.processor.model.ServiceInstanceAaiObject;
+
+import reactor.core.publisher.Mono;
+
+public interface AaiClientTask {
+
+ Mono<PnfAaiObject> executePnfRetrieval(String taskName, String url);
+
+ Mono<ServiceInstanceAaiObject> executeServiceInstanceRetrieval(String taskName, String url);
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/AaiClientTaskImpl.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/AaiClientTaskImpl.java
new file mode 100644
index 00000000..92516a04
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/AaiClientTaskImpl.java
@@ -0,0 +1,63 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.tasks;
+
+import org.onap.bbs.event.processor.exceptions.AaiTaskException;
+import org.onap.bbs.event.processor.model.PnfAaiObject;
+import org.onap.bbs.event.processor.model.ServiceInstanceAaiObject;
+import org.onap.bbs.event.processor.utilities.AaiReactiveClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import reactor.core.publisher.Mono;
+
+@Component
+public class AaiClientTaskImpl implements AaiClientTask {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AaiClientTaskImpl.class);
+ private final AaiReactiveClient reactiveClient;
+
+ @Autowired
+ AaiClientTaskImpl(AaiReactiveClient reactiveClient) {
+ this.reactiveClient = reactiveClient;
+ }
+
+ @Override
+ public Mono<PnfAaiObject> executePnfRetrieval(String taskName, String url) {
+ if (StringUtils.isEmpty(url)) {
+ throw new AaiTaskException("Cannot invoke an A&AI client task with an invalid URL");
+ }
+ LOGGER.info("Executing task ({}) for retrieving PNF object", taskName);
+ return reactiveClient.getPnfObjectDataFor(url);
+ }
+
+ @Override
+ public Mono<ServiceInstanceAaiObject> executeServiceInstanceRetrieval(String taskName, String url) {
+ if (StringUtils.isEmpty(url)) {
+ throw new AaiTaskException("Cannot invoke an A&AI client task with an invalid URL");
+ }
+ LOGGER.info("Executing task ({}) for retrieving Service Instance object", taskName);
+ return reactiveClient.getServiceInstanceObjectDataFor(url);
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapCpeAuthenticationConsumerTask.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapCpeAuthenticationConsumerTask.java
new file mode 100644
index 00000000..5b7ade12
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapCpeAuthenticationConsumerTask.java
@@ -0,0 +1,32 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.tasks;
+
+import javax.net.ssl.SSLException;
+
+import org.onap.bbs.event.processor.model.CpeAuthenticationConsumerDmaapModel;
+
+import reactor.core.publisher.Flux;
+
+public interface DmaapCpeAuthenticationConsumerTask {
+
+ Flux<CpeAuthenticationConsumerDmaapModel> execute(String object) throws SSLException;
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapCpeAuthenticationConsumerTaskImpl.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapCpeAuthenticationConsumerTaskImpl.java
new file mode 100644
index 00000000..e6bef523
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapCpeAuthenticationConsumerTaskImpl.java
@@ -0,0 +1,113 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.tasks;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.net.ssl.SSLException;
+
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.config.ConfigurationChangeObserver;
+import org.onap.bbs.event.processor.exceptions.EmptyDmaapResponseException;
+import org.onap.bbs.event.processor.model.CpeAuthenticationConsumerDmaapModel;
+import org.onap.bbs.event.processor.utilities.CpeAuthenticationDmaapConsumerJsonParser;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.ConsumerReactiveHttpClientFactory;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.DMaaPConsumerReactiveHttpClient;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.DMaaPReactiveWebClientFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+@Component
+public class DmaapCpeAuthenticationConsumerTaskImpl
+ implements DmaapCpeAuthenticationConsumerTask, ConfigurationChangeObserver {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DmaapCpeAuthenticationConsumerTaskImpl.class);
+ private ApplicationConfiguration configuration;
+ private final CpeAuthenticationDmaapConsumerJsonParser cpeAuthenticationDmaapConsumerJsonParser;
+ private final ConsumerReactiveHttpClientFactory httpClientFactory;
+
+ private static final EmptyDmaapResponseException EMPTY_DMAAP_EXCEPTION =
+ new EmptyDmaapResponseException("CPE Authentication: Got an empty response from DMaaP");
+
+ private DMaaPConsumerReactiveHttpClient httpClient;
+
+ @Autowired
+ public DmaapCpeAuthenticationConsumerTaskImpl(ApplicationConfiguration configuration) throws SSLException {
+ this(configuration, new CpeAuthenticationDmaapConsumerJsonParser(),
+ new ConsumerReactiveHttpClientFactory(new DMaaPReactiveWebClientFactory()));
+ }
+
+ DmaapCpeAuthenticationConsumerTaskImpl(ApplicationConfiguration configuration,
+ CpeAuthenticationDmaapConsumerJsonParser
+ cpeAuthenticationDmaapConsumerJsonParser,
+ ConsumerReactiveHttpClientFactory httpClientFactory) throws SSLException {
+ this.configuration = configuration;
+ this.cpeAuthenticationDmaapConsumerJsonParser = cpeAuthenticationDmaapConsumerJsonParser;
+ this.httpClientFactory = httpClientFactory;
+
+ httpClient = httpClientFactory.create(this.configuration.getDmaapCpeAuthenticationConsumerConfiguration());
+ }
+
+ @PostConstruct
+ void registerForConfigChanges() {
+ configuration.register(this);
+ }
+
+ @PreDestroy
+ void unRegisterForConfigChanges() {
+ configuration.unRegister(this);
+ }
+
+ @Override
+ public synchronized void updateConfiguration() {
+ try {
+ LOGGER.info("DMaaP CPE authentication consumer update due to new application configuration");
+ httpClient = httpClientFactory.create(this.configuration.getDmaapCpeAuthenticationConsumerConfiguration());
+ } catch (SSLException e) {
+ LOGGER.error("SSL error while updating HTTP Client after a config update");
+ LOGGER.debug("SSL exception\n", e);
+ }
+ }
+
+ @Override
+ public Flux<CpeAuthenticationConsumerDmaapModel> execute(String taskName) {
+ LOGGER.debug("Executing task for CPE-Authentication with name \"{}\"", taskName);
+ DMaaPConsumerReactiveHttpClient httpClient = getHttpClient();
+ Mono<String> response = httpClient.getDMaaPConsumerResponse();
+ return cpeAuthenticationDmaapConsumerJsonParser.extractModelFromDmaap(response)
+ .switchIfEmpty(Flux.error(EMPTY_DMAAP_EXCEPTION))
+ .doOnError(e -> {
+ if (!(e instanceof EmptyDmaapResponseException)) {
+ LOGGER.error("DMaaP Consumption Exception: {}", e.getMessage());
+ LOGGER.debug("Exception\n", e);
+ }
+ });
+ }
+
+ private synchronized DMaaPConsumerReactiveHttpClient getHttpClient() {
+ return httpClient;
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapPublisherTask.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapPublisherTask.java
new file mode 100644
index 00000000..bddd2ecc
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapPublisherTask.java
@@ -0,0 +1,31 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.tasks;
+
+import org.onap.bbs.event.processor.model.ControlLoopPublisherDmaapModel;
+import org.springframework.http.ResponseEntity;
+
+import reactor.core.publisher.Mono;
+
+public interface DmaapPublisherTask {
+
+ Mono<ResponseEntity<String>> execute(ControlLoopPublisherDmaapModel controlLoopPublisherDmaapModel);
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapPublisherTaskImpl.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapPublisherTaskImpl.java
new file mode 100644
index 00000000..7b227211
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapPublisherTaskImpl.java
@@ -0,0 +1,94 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.tasks;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.config.ConfigurationChangeObserver;
+import org.onap.bbs.event.processor.exceptions.DmaapException;
+import org.onap.bbs.event.processor.model.ControlLoopPublisherDmaapModel;
+import org.onap.bbs.event.processor.utilities.ControlLoopJsonBodyBuilder;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.producer.DMaaPPublisherReactiveHttpClient;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.producer.DmaaPRestTemplateFactory;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.producer.PublisherReactiveHttpClientFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+
+import reactor.core.publisher.Mono;
+
+@Component
+public class DmaapPublisherTaskImpl implements DmaapPublisherTask, ConfigurationChangeObserver {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DmaapPublisherTaskImpl.class);
+ private ApplicationConfiguration configuration;
+ private final PublisherReactiveHttpClientFactory httpClientFactory;
+
+ private DMaaPPublisherReactiveHttpClient httpClient;
+
+ @Autowired
+ DmaapPublisherTaskImpl(ApplicationConfiguration configuration) {
+ this(configuration, new PublisherReactiveHttpClientFactory(new DmaaPRestTemplateFactory(),
+ new ControlLoopJsonBodyBuilder()));
+ }
+
+ DmaapPublisherTaskImpl(ApplicationConfiguration configuration,
+ PublisherReactiveHttpClientFactory httpClientFactory) {
+ this.configuration = configuration;
+ this.httpClientFactory = httpClientFactory;
+
+ httpClient = httpClientFactory.create(this.configuration.getDmaapPublisherConfiguration());
+ }
+
+ @PostConstruct
+ void registerForConfigChanges() {
+ configuration.register(this);
+ }
+
+ @PreDestroy
+ void unRegisterForConfigChanges() {
+ configuration.unRegister(this);
+ }
+
+ @Override
+ public synchronized void updateConfiguration() {
+ LOGGER.info("DMaaP Publisher update due to new application configuration");
+ httpClient = httpClientFactory.create(this.configuration.getDmaapPublisherConfiguration());
+ }
+
+ @Override
+ public Mono<ResponseEntity<String>> execute(ControlLoopPublisherDmaapModel controlLoopPublisherDmaapModel) {
+ if (controlLoopPublisherDmaapModel == null) {
+ throw new DmaapException("Cannot invoke a DMaaP Publish task with a null message");
+ }
+ LOGGER.info("Executing task for publishing control loop message \n{}", controlLoopPublisherDmaapModel);
+ DMaaPPublisherReactiveHttpClient httpClient = getHttpClient();
+ return httpClient.getDMaaPProducerResponse(controlLoopPublisherDmaapModel);
+ }
+
+ private synchronized DMaaPPublisherReactiveHttpClient getHttpClient() {
+ return httpClient;
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapReRegistrationConsumerTask.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapReRegistrationConsumerTask.java
new file mode 100644
index 00000000..77f2ef8e
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapReRegistrationConsumerTask.java
@@ -0,0 +1,32 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.tasks;
+
+import javax.net.ssl.SSLException;
+
+import org.onap.bbs.event.processor.model.ReRegistrationConsumerDmaapModel;
+
+import reactor.core.publisher.Flux;
+
+public interface DmaapReRegistrationConsumerTask {
+
+ Flux<ReRegistrationConsumerDmaapModel> execute(String taskName) throws SSLException;
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapReRegistrationConsumerTaskImpl.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapReRegistrationConsumerTaskImpl.java
new file mode 100644
index 00000000..92f5a86f
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/tasks/DmaapReRegistrationConsumerTaskImpl.java
@@ -0,0 +1,113 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.tasks;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.net.ssl.SSLException;
+
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.config.ConfigurationChangeObserver;
+import org.onap.bbs.event.processor.exceptions.EmptyDmaapResponseException;
+import org.onap.bbs.event.processor.model.ReRegistrationConsumerDmaapModel;
+import org.onap.bbs.event.processor.utilities.ReRegistrationDmaapConsumerJsonParser;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.ConsumerReactiveHttpClientFactory;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.DMaaPConsumerReactiveHttpClient;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.DMaaPReactiveWebClientFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+@Component
+public class DmaapReRegistrationConsumerTaskImpl implements DmaapReRegistrationConsumerTask,
+ ConfigurationChangeObserver {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DmaapReRegistrationConsumerTaskImpl.class);
+ private ApplicationConfiguration configuration;
+ private final ReRegistrationDmaapConsumerJsonParser reRegistrationDmaapConsumerJsonParser;
+ private final ConsumerReactiveHttpClientFactory httpClientFactory;
+
+ private static final EmptyDmaapResponseException EMPTY_DMAAP_EXCEPTION =
+ new EmptyDmaapResponseException("PNF Re-Registration: Got an empty response from DMaaP");
+
+ private DMaaPConsumerReactiveHttpClient httpClient;
+
+ @Autowired
+ public DmaapReRegistrationConsumerTaskImpl(ApplicationConfiguration configuration) throws SSLException {
+ this(configuration, new ReRegistrationDmaapConsumerJsonParser(),
+ new ConsumerReactiveHttpClientFactory(new DMaaPReactiveWebClientFactory()));
+ }
+
+ DmaapReRegistrationConsumerTaskImpl(ApplicationConfiguration configuration,
+ ReRegistrationDmaapConsumerJsonParser reRegDmaapConsumerJsonParser,
+ ConsumerReactiveHttpClientFactory httpClientFactory)
+ throws SSLException {
+ this.configuration = configuration;
+ this.reRegistrationDmaapConsumerJsonParser = reRegDmaapConsumerJsonParser;
+ this.httpClientFactory = httpClientFactory;
+
+ httpClient = httpClientFactory.create(this.configuration.getDmaapReRegistrationConsumerConfiguration());
+ }
+
+ @PostConstruct
+ void registerForConfigChanges() {
+ configuration.register(this);
+ }
+
+ @PreDestroy
+ void unRegisterForConfigChanges() {
+ configuration.unRegister(this);
+ }
+
+ @Override
+ public synchronized void updateConfiguration() {
+ try {
+ LOGGER.info("DMaaP PNF reregistration consumer update due to new application configuration");
+ httpClient = httpClientFactory.create(this.configuration.getDmaapReRegistrationConsumerConfiguration());
+ } catch (SSLException e) {
+ LOGGER.error("SSL error while updating HTTP Client after a config update");
+ LOGGER.debug("SSL exception\n", e);
+ }
+ }
+
+ @Override
+ public Flux<ReRegistrationConsumerDmaapModel> execute(String taskName) {
+ LOGGER.debug("Executing task for Re-Registration with name \"{}\"", taskName);
+ DMaaPConsumerReactiveHttpClient httpClient = getHttpClient();
+ Mono<String> response = httpClient.getDMaaPConsumerResponse();
+ return reRegistrationDmaapConsumerJsonParser.extractModelFromDmaap(response)
+ .switchIfEmpty(Flux.error(EMPTY_DMAAP_EXCEPTION))
+ .doOnError(e -> {
+ if (!(e instanceof EmptyDmaapResponseException)) {
+ LOGGER.error("DMaaP Consumption Exception: {}", e.getMessage());
+ LOGGER.debug("Exception\n", e);
+ }
+ });
+ }
+
+ private synchronized DMaaPConsumerReactiveHttpClient getHttpClient() {
+ return httpClient;
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/AaiReactiveClient.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/AaiReactiveClient.java
new file mode 100644
index 00000000..19b81a80
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/AaiReactiveClient.java
@@ -0,0 +1,197 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.utilities;
+
+import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+
+import io.netty.handler.ssl.SslContext;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.net.ssl.SSLException;
+
+import org.onap.bbs.event.processor.config.AaiClientConfiguration;
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.config.ConfigurationChangeObserver;
+import org.onap.bbs.event.processor.exceptions.AaiTaskException;
+import org.onap.bbs.event.processor.model.PnfAaiObject;
+import org.onap.bbs.event.processor.model.ServiceInstanceAaiObject;
+import org.onap.dcaegen2.services.sdk.rest.services.ssl.SslFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.client.reactive.ClientHttpConnector;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.client.ClientResponse;
+import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import reactor.core.publisher.Mono;
+import reactor.netty.http.client.HttpClient;
+
+@Component
+public class AaiReactiveClient implements ConfigurationChangeObserver {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AaiReactiveClient.class);
+
+ private final Gson gson;
+ private WebClient webClient;
+ private SslFactory sslFactory;
+ private final ApplicationConfiguration configuration;
+ private AaiClientConfiguration aaiClientConfiguration;
+
+ @Autowired
+ AaiReactiveClient(ApplicationConfiguration configuration, Gson gson) throws SSLException {
+ this.configuration = configuration;
+ this.gson = gson;
+ this.sslFactory = new SslFactory();
+
+ aaiClientConfiguration = this.configuration.getAaiClientConfiguration();
+ setupWebClient();
+ }
+
+ @PostConstruct
+ public void registerForConfigChanges() {
+ configuration.register(this);
+ }
+
+ @PreDestroy
+ public void unRegisterForConfigChanges() {
+ configuration.unRegister(this);
+ }
+
+ @Override
+ public void updateConfiguration() {
+ AaiClientConfiguration newConfiguration = configuration.getAaiClientConfiguration();
+ if (aaiClientConfiguration.equals(newConfiguration)) {
+ LOGGER.info("No Configuration changes necessary for AAI Reactive client");
+ } else {
+ synchronized (this) {
+ LOGGER.info("AAI Reactive client must be re-configured");
+ aaiClientConfiguration = newConfiguration;
+ try {
+ setupWebClient();
+ } catch (SSLException e) {
+ LOGGER.error("AAI Reactive client SSL error while re-configuring WebClient");
+ LOGGER.debug("SSL Exception\n", e);
+ }
+ }
+ }
+ }
+
+ private void setupWebClient() throws SSLException {
+ SslContext sslContext = createSslContext();
+
+ ClientHttpConnector reactorClientHttpConnector = new ReactorClientHttpConnector(
+ HttpClient.create().secure(sslContextSpec -> sslContextSpec.sslContext(sslContext)));
+
+ this.webClient = WebClient.builder()
+ .baseUrl(aaiClientConfiguration.aaiProtocol() + "://" + aaiClientConfiguration.aaiHost()
+ + ":" + aaiClientConfiguration.aaiPort())
+ .clientConnector(reactorClientHttpConnector)
+ .defaultHeaders(httpHeaders -> httpHeaders.setAll(aaiClientConfiguration.aaiHeaders()))
+ .filter(basicAuthentication(aaiClientConfiguration.aaiUserName(),
+ aaiClientConfiguration.aaiUserPassword()))
+ .filter(logRequest())
+ .filter(logResponse())
+ .build();
+ }
+
+ public Mono<PnfAaiObject> getPnfObjectDataFor(String url) {
+
+ return performReactiveHttpGet(url, PnfAaiObject.class);
+ }
+
+ public Mono<ServiceInstanceAaiObject> getServiceInstanceObjectDataFor(String url) {
+
+ return performReactiveHttpGet(url, ServiceInstanceAaiObject.class);
+ }
+
+ private <T> Mono<T> performReactiveHttpGet(String url, Class<T> responseType) {
+ LOGGER.debug("Will issue Reactive GET request to URL ({}) for object ({})", url, responseType.getName());
+ WebClient webClient = getWebClient();
+ return webClient
+ .get()
+ .uri(url)
+ .retrieve()
+ .onStatus(HttpStatus::is4xxClientError,
+ response -> Mono.error(createExceptionObject(url, response)))
+ .onStatus(HttpStatus::is5xxServerError,
+ response -> Mono.error(createExceptionObject(url, response)))
+ .bodyToMono(String.class)
+ .flatMap(body -> extractMono(body, responseType));
+ }
+
+ private AaiTaskException createExceptionObject(String url, ClientResponse response) {
+ return new AaiTaskException(String.format("A&AI Request for (%s) failed with HTTP status code %d", url,
+ response.statusCode().value()));
+ }
+
+ private <T> Mono<T> extractMono(String body, Class<T> responseType) {
+ LOGGER.debug("Response body \n{}", body);
+ try {
+ return Mono.just(parseFromJsonReply(body, responseType));
+ } catch (JsonSyntaxException | IllegalStateException e) {
+ return Mono.error(e);
+ }
+ }
+
+ private <T> T parseFromJsonReply(String body, Class<T> responseType) {
+ return gson.fromJson(body, responseType);
+ }
+
+ private static ExchangeFilterFunction logRequest() {
+ return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
+ LOGGER.debug("Request: {} {}", clientRequest.method(), clientRequest.url());
+ clientRequest.headers()
+ .forEach((name, values) -> values.forEach(value -> LOGGER.debug("{}={}", name, value)));
+ return Mono.just(clientRequest);
+ });
+ }
+
+ private static ExchangeFilterFunction logResponse() {
+ return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
+ LOGGER.debug("Response status {}", clientResponse.statusCode());
+ return Mono.just(clientResponse);
+ });
+ }
+
+ private SslContext createSslContext() throws SSLException {
+ if (aaiClientConfiguration.enableAaiCertAuth()) {
+ return sslFactory.createSecureContext(
+ aaiClientConfiguration.keyStorePath(),
+ aaiClientConfiguration.keyStorePasswordPath(),
+ aaiClientConfiguration.trustStorePath(),
+ aaiClientConfiguration.trustStorePasswordPath()
+ );
+ }
+ return sslFactory.createInsecureContext();
+ }
+
+ private synchronized WebClient getWebClient() {
+ return webClient;
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CommonEventFields.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CommonEventFields.java
new file mode 100644
index 00000000..c2b67348
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CommonEventFields.java
@@ -0,0 +1,33 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.utilities;
+
+public class CommonEventFields {
+
+ static final String COMMON_FORMAT = "\": \"%s\"";
+ static final String EVENT = "event";
+ static final String COMMON_EVENT_HEADER = "commonEventHeader";
+ static final String SOURCE_NAME = "sourceName";
+ static final String CORRELATION_ID = "correlationId";
+
+ // Non-instantiable class
+ private CommonEventFields() {}
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ControlLoopJsonBodyBuilder.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ControlLoopJsonBodyBuilder.java
new file mode 100644
index 00000000..03ea0936
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ControlLoopJsonBodyBuilder.java
@@ -0,0 +1,59 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.utilities;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.TypeAdapterFactory;
+
+import java.util.ServiceLoader;
+
+import org.onap.bbs.event.processor.model.ControlLoopPublisherDmaapModel;
+import org.onap.bbs.event.processor.model.ImmutableControlLoopPublisherDmaapModel;
+import org.onap.dcaegen2.services.sdk.rest.services.model.JsonBodyBuilder;
+
+public class ControlLoopJsonBodyBuilder implements JsonBodyBuilder<ControlLoopPublisherDmaapModel> {
+
+ /**
+ * Serialize the Control Loop DMaaP model with GSON.
+ * @param publisherDmaapModel object to be serialized
+ * @return String output of serialization
+ */
+ @Override
+ public String createJsonBody(ControlLoopPublisherDmaapModel publisherDmaapModel) {
+ GsonBuilder gsonBuilder = new GsonBuilder().disableHtmlEscaping();
+ ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory);
+ return gsonBuilder.create().toJson(ImmutableControlLoopPublisherDmaapModel.builder()
+ .closedLoopEventClient(publisherDmaapModel.getClosedLoopEventClient())
+ .policyVersion(publisherDmaapModel.getPolicyVersion())
+ .policyName(publisherDmaapModel.getPolicyName())
+ .policyScope(publisherDmaapModel.getPolicyScope())
+ .targetType(publisherDmaapModel.getTargetType())
+ .aaiEnrichmentData(publisherDmaapModel.getAaiEnrichmentData())
+ .closedLoopAlarmStart(publisherDmaapModel.getClosedLoopAlarmStart())
+ .closedLoopEventStatus(publisherDmaapModel.getClosedLoopEventStatus())
+ .closedLoopControlName(publisherDmaapModel.getClosedLoopControlName())
+ .version(publisherDmaapModel.getVersion())
+ .target(publisherDmaapModel.getTarget())
+ .requestId(publisherDmaapModel.getRequestId())
+ .originator(publisherDmaapModel.getOriginator())
+ .build());
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationDmaapConsumerJsonParser.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationDmaapConsumerJsonParser.java
new file mode 100644
index 00000000..2bb5d98a
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationDmaapConsumerJsonParser.java
@@ -0,0 +1,187 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.utilities;
+
+import static org.onap.bbs.event.processor.utilities.CommonEventFields.COMMON_EVENT_HEADER;
+import static org.onap.bbs.event.processor.utilities.CommonEventFields.COMMON_FORMAT;
+import static org.onap.bbs.event.processor.utilities.CommonEventFields.CORRELATION_ID;
+import static org.onap.bbs.event.processor.utilities.CommonEventFields.EVENT;
+import static org.onap.bbs.event.processor.utilities.CommonEventFields.SOURCE_NAME;
+import static org.onap.bbs.event.processor.utilities.CpeAuthenticationEventFields.ADDITIONAL_FIELDS;
+import static org.onap.bbs.event.processor.utilities.CpeAuthenticationEventFields.NEW_AUTHENTICATION_STATE;
+import static org.onap.bbs.event.processor.utilities.CpeAuthenticationEventFields.OLD_AUTHENTICATION_STATE;
+import static org.onap.bbs.event.processor.utilities.CpeAuthenticationEventFields.RGW_MAC_ADDRESS;
+import static org.onap.bbs.event.processor.utilities.CpeAuthenticationEventFields.STATE_CHANGE_FIELDS;
+import static org.onap.bbs.event.processor.utilities.CpeAuthenticationEventFields.STATE_INTERFACE;
+import static org.onap.bbs.event.processor.utilities.CpeAuthenticationEventFields.SW_VERSION;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+
+import java.util.Optional;
+import java.util.stream.StreamSupport;
+
+import org.onap.bbs.event.processor.exceptions.DmaapException;
+import org.onap.bbs.event.processor.model.CpeAuthenticationConsumerDmaapModel;
+import org.onap.bbs.event.processor.model.ImmutableCpeAuthenticationConsumerDmaapModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.StringUtils;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class CpeAuthenticationDmaapConsumerJsonParser {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CpeAuthenticationDmaapConsumerJsonParser.class);
+ private static final Gson gson = new Gson();
+
+ private static final String CPE_AUTHENTICATION_DUMPING_TEMPLATE = "%n{"
+ + "\"" + CORRELATION_ID + COMMON_FORMAT + ","
+ + "\"" + OLD_AUTHENTICATION_STATE + COMMON_FORMAT + ","
+ + "\"" + NEW_AUTHENTICATION_STATE + COMMON_FORMAT + ","
+ + "\"" + STATE_INTERFACE + COMMON_FORMAT + ","
+ + "\"" + RGW_MAC_ADDRESS + COMMON_FORMAT + ","
+ + "\"" + SW_VERSION + COMMON_FORMAT
+ + "}";
+
+ private String pnfSourceName;
+
+ private String oldAuthenticationStatus;
+ private String newAuthenticationStatus;
+ private String stateInterface;
+ private String rgwMacAddress;
+ private String swVersion;
+
+ /**
+ * Translates a response from DMaaP to a reactive {@link CpeAuthenticationConsumerDmaapModel} model.
+ * @param dmaapResponse Response from DMaaP
+ * @return CPE Authentication Consumer DMaaP reactive model
+ */
+ public Flux<CpeAuthenticationConsumerDmaapModel> extractModelFromDmaap(Mono<String> dmaapResponse) {
+ return dmaapResponse
+ .flatMapMany(this::parseToMono)
+ .flatMap(this::createTargetFlux);
+ }
+
+ private Mono<JsonElement> parseToMono(String message) {
+ if (StringUtils.isEmpty(message)) {
+ LOGGER.warn("DMaaP response is empty");
+ return Mono.empty();
+ }
+ return Mono.fromCallable(() -> new JsonParser().parse(message))
+ .doOnError(e -> e instanceof JsonSyntaxException, e -> LOGGER.error("Invalid JSON. Ignoring"))
+ .onErrorResume(e -> e instanceof JsonSyntaxException, e -> Mono.empty());
+ }
+
+ private Flux<CpeAuthenticationConsumerDmaapModel> createTargetFlux(JsonElement jsonElement) {
+ if (jsonElement.isJsonObject()) {
+ return doCreateTargetFlux(Flux.defer(() -> Flux.just(jsonElement.getAsJsonObject())));
+ }
+ return doCreateTargetFlux(
+ Flux.defer(() -> Flux.fromStream(StreamSupport.stream(jsonElement.getAsJsonArray().spliterator(), false)
+ .map(jsonElementFromArray -> getJsonObjectFromAnArray(jsonElementFromArray)
+ .orElseGet(JsonObject::new)))));
+ }
+
+ private Flux<CpeAuthenticationConsumerDmaapModel> doCreateTargetFlux(Flux<JsonObject> jsonObject) {
+ return jsonObject
+ .flatMap(this::transform)
+ .onErrorResume(exception -> exception instanceof DmaapException, e -> Mono.empty());
+ }
+
+ private Mono<CpeAuthenticationConsumerDmaapModel> transform(JsonObject dmaapResponseJsonObject) {
+
+ LOGGER.trace("Event from DMaaP to be parsed: \n{}", gson.toJson(dmaapResponseJsonObject));
+
+ if (!containsProperHeaders(dmaapResponseJsonObject)) {
+ LOGGER.warn("Incorrect CPE Authentication JSON event - missing headers");
+ return Mono.empty();
+ }
+
+ JsonObject commonEventHeader = dmaapResponseJsonObject.getAsJsonObject(EVENT)
+ .getAsJsonObject(COMMON_EVENT_HEADER);
+ JsonObject stateChangeFields = dmaapResponseJsonObject.getAsJsonObject(EVENT)
+ .getAsJsonObject(STATE_CHANGE_FIELDS);
+
+ pnfSourceName = getValueFromJson(commonEventHeader, SOURCE_NAME);
+
+ oldAuthenticationStatus = getValueFromJson(stateChangeFields, OLD_AUTHENTICATION_STATE);
+ newAuthenticationStatus = getValueFromJson(stateChangeFields, NEW_AUTHENTICATION_STATE);
+ stateInterface = getValueFromJson(stateChangeFields, STATE_INTERFACE);
+
+ if (stateChangeFields.has(ADDITIONAL_FIELDS)) {
+ JsonObject additionalFields = stateChangeFields.getAsJsonObject(ADDITIONAL_FIELDS);
+ rgwMacAddress = getValueFromJson(additionalFields, RGW_MAC_ADDRESS);
+ swVersion = getValueFromJson(additionalFields, SW_VERSION);
+ }
+
+ if (StringUtils.isEmpty(pnfSourceName)
+ || authenticationStatusMissing(oldAuthenticationStatus)
+ || authenticationStatusMissing(newAuthenticationStatus)) {
+ String incorrectEvent = dumpJsonData();
+ LOGGER.warn("Incorrect CPE Authentication JSON event: {}", incorrectEvent);
+ return Mono.empty();
+ }
+
+ return Mono.just(ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(pnfSourceName)
+ .oldAuthenticationState(oldAuthenticationStatus)
+ .newAuthenticationState(newAuthenticationStatus)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress)
+ .swVersion(swVersion)
+ .build());
+ }
+
+ private boolean authenticationStatusMissing(String authenticationStatus) {
+ return StringUtils.isEmpty(authenticationStatus);
+ }
+
+ private boolean containsProperHeaders(JsonObject jsonObject) {
+ return jsonObject.has(EVENT) && jsonObject.getAsJsonObject(EVENT).has(COMMON_EVENT_HEADER)
+ && jsonObject.getAsJsonObject(EVENT).has(STATE_CHANGE_FIELDS);
+ }
+
+ private String dumpJsonData() {
+ return String.format(CPE_AUTHENTICATION_DUMPING_TEMPLATE,
+ pnfSourceName,
+ oldAuthenticationStatus,
+ newAuthenticationStatus,
+ stateInterface,
+ rgwMacAddress,
+ swVersion
+ );
+ }
+
+ Optional<JsonObject> getJsonObjectFromAnArray(JsonElement element) {
+ JsonParser jsonParser = new JsonParser();
+ return element.isJsonPrimitive() ? Optional.of(jsonParser.parse(element.getAsString()).getAsJsonObject())
+ : Optional.of(jsonParser.parse(element.toString()).getAsJsonObject());
+ }
+
+ private String getValueFromJson(JsonObject jsonObject, String jsonKey) {
+ return jsonObject.has(jsonKey) ? jsonObject.get(jsonKey).getAsString() : "";
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationEventFields.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationEventFields.java
new file mode 100644
index 00000000..00a3f5e0
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationEventFields.java
@@ -0,0 +1,35 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.utilities;
+
+class CpeAuthenticationEventFields {
+
+ static final String STATE_CHANGE_FIELDS = "stateChangeFields";
+ static final String NEW_AUTHENTICATION_STATE = "newState";
+ static final String OLD_AUTHENTICATION_STATE = "oldState";
+ static final String STATE_INTERFACE = "stateInterface";
+ static final String ADDITIONAL_FIELDS = "additionalFields";
+ static final String RGW_MAC_ADDRESS = "macAddress";
+ static final String SW_VERSION = "swVersion";
+
+ // Non-instantiable class
+ private CpeAuthenticationEventFields(){}
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationJsonBodyBuilder.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationJsonBodyBuilder.java
new file mode 100644
index 00000000..09aa7303
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationJsonBodyBuilder.java
@@ -0,0 +1,52 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.utilities;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.TypeAdapterFactory;
+
+import java.util.ServiceLoader;
+
+import org.onap.bbs.event.processor.model.CpeAuthenticationConsumerDmaapModel;
+import org.onap.bbs.event.processor.model.ImmutableCpeAuthenticationConsumerDmaapModel;
+import org.onap.dcaegen2.services.sdk.rest.services.model.JsonBodyBuilder;
+
+public class CpeAuthenticationJsonBodyBuilder implements JsonBodyBuilder<CpeAuthenticationConsumerDmaapModel> {
+
+ /**
+ * Serialize the CPE authentication DMaaP model with GSON.
+ * @param cpeAuthenticationConsumerDmaapModel object to be serialized
+ * @return String output of serialization
+ */
+ @Override
+ public String createJsonBody(CpeAuthenticationConsumerDmaapModel cpeAuthenticationConsumerDmaapModel) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory);
+ return gsonBuilder.create().toJson(ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(cpeAuthenticationConsumerDmaapModel.getCorrelationId())
+ .oldAuthenticationState(cpeAuthenticationConsumerDmaapModel.getOldAuthenticationState())
+ .newAuthenticationState(cpeAuthenticationConsumerDmaapModel.getNewAuthenticationState())
+ .stateInterface(cpeAuthenticationConsumerDmaapModel.getStateInterface().orElse(""))
+ .rgwMacAddress(cpeAuthenticationConsumerDmaapModel.getRgwMacAddress().orElse(""))
+ .swVersion(cpeAuthenticationConsumerDmaapModel.getSwVersion().orElse(""))
+ .build());
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/LoggingUtil.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/LoggingUtil.java
new file mode 100644
index 00000000..efb90d41
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/LoggingUtil.java
@@ -0,0 +1,54 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.utilities;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.slf4j.LoggerFactory;
+
+public class LoggingUtil {
+
+ private static final String BBS_EP_APPLICATION_PACKAGE = "org.onap.bbs";
+ private static final Logger applicationLogger = (Logger) LoggerFactory.getLogger(BBS_EP_APPLICATION_PACKAGE);
+ private static final List<String> loggingLevels =
+ Arrays.asList("OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE");
+
+ // Non-instantiable class
+ private LoggingUtil() {
+ }
+
+ /**
+ * Change Application logging level.
+ * @param level logging level. Must be one of OFF, ERROR, WARN, INFO, DEBUG, TRACE
+ * @return Flag indicating if it changed the level or not
+ */
+ public static boolean changeLoggingLevel(String level) {
+ if (loggingLevels.contains(level)) {
+ applicationLogger.setLevel(Level.toLevel(level));
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ReRegistrationDmaapConsumerJsonParser.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ReRegistrationDmaapConsumerJsonParser.java
new file mode 100644
index 00000000..947d7a7c
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ReRegistrationDmaapConsumerJsonParser.java
@@ -0,0 +1,171 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.utilities;
+
+import static org.onap.bbs.event.processor.utilities.CommonEventFields.COMMON_FORMAT;
+import static org.onap.bbs.event.processor.utilities.CommonEventFields.CORRELATION_ID;
+import static org.onap.bbs.event.processor.utilities.ReRegistrationEventFields.ADDITIONAL_FIELDS;
+import static org.onap.bbs.event.processor.utilities.ReRegistrationEventFields.ATTACHMENT_POINT;
+import static org.onap.bbs.event.processor.utilities.ReRegistrationEventFields.CVLAN;
+import static org.onap.bbs.event.processor.utilities.ReRegistrationEventFields.REMOTE_ID;
+import static org.onap.bbs.event.processor.utilities.ReRegistrationEventFields.SVLAN;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+
+import java.util.Optional;
+import java.util.stream.StreamSupport;
+
+import org.onap.bbs.event.processor.exceptions.DmaapException;
+import org.onap.bbs.event.processor.model.ImmutableReRegistrationConsumerDmaapModel;
+import org.onap.bbs.event.processor.model.ReRegistrationConsumerDmaapModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.StringUtils;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class ReRegistrationDmaapConsumerJsonParser {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ReRegistrationDmaapConsumerJsonParser.class);
+ private static final Gson gson = new Gson();
+
+ private static final String RE_REGISTRATION_DUMPING_TEMPLATE = "%n{"
+ + "\"" + CORRELATION_ID + COMMON_FORMAT + ","
+ + "\"" + ATTACHMENT_POINT + COMMON_FORMAT + ","
+ + "\"" + REMOTE_ID + COMMON_FORMAT + ","
+ + "\"" + CVLAN + COMMON_FORMAT + ","
+ + "\"" + SVLAN + COMMON_FORMAT
+ + "}";
+
+ private String pnfCorrelationId;
+
+ private String attachmentPoint;
+ private String remoteId;
+ private String cvlan;
+ private String svlan;
+
+ /**
+ * Translates a response from DMaaP to a reactive {@link ReRegistrationConsumerDmaapModel} model.
+ * @param dmaapResponse Response from DMaaP
+ * @return Re-Registration Consumer DMaaP reactive model
+ */
+ public Flux<ReRegistrationConsumerDmaapModel> extractModelFromDmaap(Mono<String> dmaapResponse) {
+ return dmaapResponse
+ .flatMapMany(this::parseToMono)
+ .flatMap(this::createTargetFlux);
+ }
+
+ private Mono<JsonElement> parseToMono(String message) {
+ if (StringUtils.isEmpty(message)) {
+ LOGGER.warn("DMaaP response is empty");
+ return Mono.empty();
+ }
+ return Mono.fromCallable(() -> new JsonParser().parse(message))
+ .doOnError(e -> e instanceof JsonSyntaxException, e -> LOGGER.error("Invalid JSON. Ignoring"))
+ .onErrorResume(e -> e instanceof JsonSyntaxException, e -> Mono.empty());
+ }
+
+ private Flux<ReRegistrationConsumerDmaapModel> createTargetFlux(JsonElement jsonElement) {
+ if (jsonElement.isJsonObject()) {
+ return doCreateTargetFlux(Flux.defer(() -> Flux.just(jsonElement.getAsJsonObject())));
+ }
+ return doCreateTargetFlux(
+ Flux.defer(() -> Flux.fromStream(StreamSupport.stream(jsonElement.getAsJsonArray().spliterator(), false)
+ .map(jsonElementFromArray -> getJsonObjectFromAnArray(jsonElementFromArray)
+ .orElseGet(JsonObject::new)))));
+ }
+
+ private Flux<ReRegistrationConsumerDmaapModel> doCreateTargetFlux(Flux<JsonObject> jsonObject) {
+ return jsonObject
+ .flatMap(this::transform)
+ .onErrorResume(exception -> exception instanceof DmaapException, e -> Mono.empty());
+ }
+
+ private Mono<ReRegistrationConsumerDmaapModel> transform(JsonObject dmaapResponseJsonObject) {
+
+ LOGGER.trace("Event from DMaaP to be parsed: \n{}", gson.toJson(dmaapResponseJsonObject));
+
+ if (!containsProperHeaders(dmaapResponseJsonObject)) {
+ LOGGER.warn("Incorrect JsonObject - missing headers");
+ return Mono.empty();
+ }
+
+ JsonObject pnfReRegistrationFields =
+ dmaapResponseJsonObject.getAsJsonObject(ADDITIONAL_FIELDS);
+
+ pnfCorrelationId = getValueFromJson(dmaapResponseJsonObject, CORRELATION_ID);
+
+ attachmentPoint = getValueFromJson(pnfReRegistrationFields, ATTACHMENT_POINT);
+ remoteId = getValueFromJson(pnfReRegistrationFields, REMOTE_ID);
+ cvlan = getValueFromJson(pnfReRegistrationFields, CVLAN);
+ svlan = getValueFromJson(pnfReRegistrationFields, SVLAN);
+
+ if (StringUtils.isEmpty(pnfCorrelationId) || anyImportantPropertyMissing()) {
+ String incorrectEvent = dumpJsonData();
+ LOGGER.warn("Incorrect Re-Registration JSON event: {}", incorrectEvent);
+ return Mono.empty();
+ }
+
+ return Mono.just(ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(pnfCorrelationId)
+ .attachmentPoint(attachmentPoint)
+ .remoteId(remoteId)
+ .cVlan(cvlan)
+ .sVlan(svlan)
+ .build());
+ }
+
+ private boolean anyImportantPropertyMissing() {
+ return StringUtils.isEmpty(attachmentPoint)
+ || StringUtils.isEmpty(remoteId)
+ || StringUtils.isEmpty(cvlan)
+ || StringUtils.isEmpty(svlan);
+ }
+
+ private boolean containsProperHeaders(JsonObject jsonObject) {
+ return jsonObject.has(ADDITIONAL_FIELDS);
+ }
+
+ private String dumpJsonData() {
+ return String.format(RE_REGISTRATION_DUMPING_TEMPLATE,
+ pnfCorrelationId,
+ attachmentPoint,
+ remoteId,
+ cvlan,
+ svlan
+ );
+ }
+
+ Optional<JsonObject> getJsonObjectFromAnArray(JsonElement element) {
+ JsonParser jsonParser = new JsonParser();
+ return element.isJsonPrimitive() ? Optional.of(jsonParser.parse(element.getAsString()).getAsJsonObject())
+ : Optional.of(jsonParser.parse(element.toString()).getAsJsonObject());
+ }
+
+ private String getValueFromJson(JsonObject jsonObject, String jsonKey) {
+ return jsonObject.has(jsonKey) ? jsonObject.get(jsonKey).getAsString() : "";
+ }
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ReRegistrationEventFields.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ReRegistrationEventFields.java
new file mode 100644
index 00000000..35e78b01
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ReRegistrationEventFields.java
@@ -0,0 +1,33 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.utilities;
+
+class ReRegistrationEventFields {
+
+ static final String ADDITIONAL_FIELDS = "additionalFields";
+ static final String ATTACHMENT_POINT = "attachment-point";
+ static final String REMOTE_ID = "remote-id";
+ static final String CVLAN = "cvlan";
+ static final String SVLAN = "svlan";
+
+ // Non-instantiable class
+ private ReRegistrationEventFields(){}
+}
diff --git a/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ReRegistrationJsonBodyBuilder.java b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ReRegistrationJsonBodyBuilder.java
new file mode 100644
index 00000000..867cfda7
--- /dev/null
+++ b/components/bbs-event-processor/src/main/java/org/onap/bbs/event/processor/utilities/ReRegistrationJsonBodyBuilder.java
@@ -0,0 +1,51 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.utilities;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.TypeAdapterFactory;
+
+import java.util.ServiceLoader;
+
+import org.onap.bbs.event.processor.model.ImmutableReRegistrationConsumerDmaapModel;
+import org.onap.bbs.event.processor.model.ReRegistrationConsumerDmaapModel;
+import org.onap.dcaegen2.services.sdk.rest.services.model.JsonBodyBuilder;
+
+public class ReRegistrationJsonBodyBuilder implements JsonBodyBuilder<ReRegistrationConsumerDmaapModel> {
+
+ /**
+ * Serialize the Re-Registration DMaaP model with GSON.
+ * @param reRegistrationConsumerDmaapModel object to be serialized
+ * @return String output of serialization
+ */
+ @Override
+ public String createJsonBody(ReRegistrationConsumerDmaapModel reRegistrationConsumerDmaapModel) {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory);
+ return gsonBuilder.create().toJson(ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(reRegistrationConsumerDmaapModel.getCorrelationId())
+ .attachmentPoint(reRegistrationConsumerDmaapModel.getAttachmentPoint())
+ .remoteId(reRegistrationConsumerDmaapModel.getRemoteId())
+ .cVlan(reRegistrationConsumerDmaapModel.getCVlan())
+ .sVlan(reRegistrationConsumerDmaapModel.getSVlan())
+ .build());
+ }
+}
diff --git a/components/bbs-event-processor/src/main/resources/application.yml b/components/bbs-event-processor/src/main/resources/application.yml
new file mode 100644
index 00000000..9092adae
--- /dev/null
+++ b/components/bbs-event-processor/src/main/resources/application.yml
@@ -0,0 +1,79 @@
+spring:
+ profiles:
+ active: production
+server:
+ port: 8100
+configs:
+ dmaap:
+ consumer:
+ re-registration:
+ dmaapHostName: localhost
+ dmaapPortNumber: 2222
+ dmaapTopicName: /events/unauthenticated.PNF_Update
+ dmaapProtocol: http
+ dmaapContentType: application/json
+ consumerId: c12
+ consumerGroup: OpenDcae-c12
+ timeoutMs: -1
+ messageLimit: 1
+ cpe-authentication:
+ dmaapHostName: localhost
+ dmaapPortNumber: 2222
+ dmaapTopicName: /events/unauthenticated.CPE_Authentication
+ dmaapProtocol: http
+ dmaapContentType: application/json
+ consumerId: c12
+ consumerGroup: OpenDcae-c12
+ timeoutMs: -1
+ messageLimit: 1
+ producer:
+ dmaapHostName: localhost
+ dmaapPortNumber: 2223
+ dmaapTopicName: /events/unauthenticated.DCAE_CL_OUTPUT
+ dmaapProtocol: http
+ dmaapContentType: application/json
+ aai:
+ client:
+ aaiHost: localhost
+ aaiPort: 8080
+ aaiProtocol: https
+ aaiUserName: AAI
+ aaiUserPassword: AAI
+ aaiIgnoreSslCertificateErrors: true
+ aaiHeaders:
+ X-FromAppId: bbs
+ X-TransactionId: 9999
+ Accept: application/json
+ Real-Time: true
+ Content-Type: application/json
+ security:
+ trustStorePath: change it
+ trustStorePasswordPath: change it
+ keyStorePath: change it
+ keyStorePasswordPath: change it
+ enableAaiCertAuth: false
+ enableDmaapCertAuth: false
+ application:
+ pipelinesPollingIntervalSec: 30
+ pipelinesTimeoutSec: 15
+ policyVersion: 1.0.0.5
+ clTargetType: VM
+ clEventStatus: ONSET
+ clVersion: 1.0.2
+ clTarget: vserver.vserver-name
+ clOriginator: DCAE-bbs-event-processor
+ re-registration:
+ policyScope: policyScope
+ clControlName: controlName
+ cpe-authentication:
+ policyScope: policyScope
+ clControlName: controlName
+logging:
+ level:
+ ROOT: ERROR
+ org.onap.bbs: INFO
+ org.onap.dcaegen2: WARN
+ reactor.ipc.netty.http.client: WARN
+ org.springframework: ERROR
+ org.springframework.data: ERROR
+ org.springframework.web.reactive: WARN \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/AaiClientPropertiesTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/AaiClientPropertiesTest.java
new file mode 100644
index 00000000..449be724
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/AaiClientPropertiesTest.java
@@ -0,0 +1,70 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+@SpringBootTest(classes = AaiClientProperties.class)
+@EnableConfigurationProperties
+@TestPropertySource(properties = {
+ "configs.aai.client.aaiHost=test localhost",
+ "configs.aai.client.aaiPort=1234",
+ "configs.aai.client.aaiProtocol=https",
+ "configs.aai.client.aaiUserName=AAI",
+ "configs.aai.client.aaiUserPassword=AAI",
+ "configs.aai.client.aaiIgnoreSslCertificateErrors=true",
+ "configs.aai.client.aaiHeaders.X-FromAppId=bbs",
+ "configs.aai.client.aaiHeaders.X-TransactionId=9999",
+ "configs.aai.client.aaiHeaders.Accept=application/json",
+ "configs.aai.client.aaiHeaders.Real-Time=true",
+ "configs.aai.client.aaiHeaders.Content-Type=application/merge-patch+json"})
+class AaiClientPropertiesTest {
+
+ private AaiClientProperties properties;
+
+ @Autowired
+ public AaiClientPropertiesTest(
+ AaiClientProperties properties) {
+ this.properties = properties;
+ }
+
+ @Test
+ void dmaapReRegistrationProperties_SuccessFullyLoaded() {
+ assertEquals("test localhost", properties.getAaiHost());
+ assertEquals(1234, properties.getAaiPort());
+ assertEquals("https", properties.getAaiProtocol());
+ assertEquals("AAI", properties.getAaiUserName());
+ assertEquals("AAI", properties.getAaiUserPassword());
+ assertTrue(properties.isAaiIgnoreSslCertificateErrors());
+ assertEquals("bbs", properties.getAaiHeaders().get("X-FromAppId"));
+ assertEquals("9999", properties.getAaiHeaders().get("X-TransactionId"));
+ assertEquals("application/json", properties.getAaiHeaders().get("Accept"));
+ assertEquals("true", properties.getAaiHeaders().get("Real-Time"));
+ assertEquals("application/merge-patch+json", properties.getAaiHeaders().get("Content-Type"));
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/ApplicationConfigurationTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/ApplicationConfigurationTest.java
new file mode 100644
index 00000000..220466bc
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/ApplicationConfigurationTest.java
@@ -0,0 +1,375 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.FixMethodOrder;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.runners.MethodSorters;
+import org.onap.bbs.event.processor.model.GeneratedAppConfigObject;
+import org.onap.bbs.event.processor.model.ImmutableDmaapInfo;
+import org.onap.bbs.event.processor.model.ImmutableGeneratedAppConfigObject;
+import org.onap.bbs.event.processor.model.ImmutableStreamsObject;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapConsumerConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapPublisherConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+@SpringBootTest(classes = {
+ AaiClientProperties.class,
+ DmaapReRegistrationConsumerProperties.class,
+ DmaapCpeAuthenticationConsumerProperties.class,
+ DmaapProducerProperties.class,
+ SecurityProperties.class,
+ GenericProperties.class})
+@EnableConfigurationProperties
+@TestPropertySource(properties = {
+ "configs.aai.client.aaiHost=test localhost",
+ "configs.aai.client.aaiPort=1234",
+ "configs.aai.client.aaiProtocol=https",
+ "configs.aai.client.aaiUserName=AAI",
+ "configs.aai.client.aaiUserPassword=AAI",
+ "configs.aai.client.aaiIgnoreSslCertificateErrors=true",
+ "configs.aai.client.aaiHeaders.X-FromAppId=bbs",
+ "configs.aai.client.aaiHeaders.X-TransactionId=9999",
+ "configs.aai.client.aaiHeaders.Accept=application/json",
+ "configs.aai.client.aaiHeaders.Real-Time=true",
+ "configs.aai.client.aaiHeaders.Content-Type=application/merge-patch+json",
+ "configs.dmaap.consumer.re-registration.dmaapHostName=test localhost",
+ "configs.dmaap.consumer.re-registration.dmaapPortNumber=1234",
+ "configs.dmaap.consumer.re-registration.dmaapTopicName=/events/unauthenticated.PNF_REREGISTRATION",
+ "configs.dmaap.consumer.re-registration.dmaapProtocol=http",
+ "configs.dmaap.consumer.re-registration.dmaapContentType=application/json",
+ "configs.dmaap.consumer.re-registration.consumerId=c12",
+ "configs.dmaap.consumer.re-registration.consumerGroup=OpenDcae-c12",
+ "configs.dmaap.consumer.re-registration.timeoutMs=-1",
+ "configs.dmaap.consumer.re-registration.messageLimit=1",
+ "configs.dmaap.consumer.cpe-authentication.dmaapHostName=test localhost",
+ "configs.dmaap.consumer.cpe-authentication.dmaapPortNumber=1234",
+ "configs.dmaap.consumer.cpe-authentication.dmaapTopicName=/events/unauthenticated.CPE_AUTHENTICATION",
+ "configs.dmaap.consumer.cpe-authentication.dmaapProtocol=http",
+ "configs.dmaap.consumer.cpe-authentication.dmaapContentType=application/json",
+ "configs.dmaap.consumer.cpe-authentication.consumerId=c12",
+ "configs.dmaap.consumer.cpe-authentication.consumerGroup=OpenDcae-c12",
+ "configs.dmaap.consumer.cpe-authentication.timeoutMs=-1",
+ "configs.dmaap.consumer.cpe-authentication.messageLimit=1",
+ "configs.dmaap.producer.dmaapHostName=test localhost",
+ "configs.dmaap.producer.dmaapPortNumber=1234",
+ "configs.dmaap.producer.dmaapTopicName=/events/unauthenticated.DCAE_CL_OUTPUT",
+ "configs.dmaap.producer.dmaapProtocol=http",
+ "configs.dmaap.producer.dmaapContentType=application/json",
+ "configs.security.trustStorePath=test trust store path",
+ "configs.security.trustStorePasswordPath=test trust store password path",
+ "configs.security.keyStorePath=test key store path",
+ "configs.security.keyStorePasswordPath=test key store password path",
+ "configs.security.enableDmaapCertAuth=true",
+ "configs.security.enableAaiCertAuth=true",
+ "configs.application.pipelinesPollingIntervalSec=30",
+ "configs.application.pipelinesTimeoutSec=15",
+ "configs.application.policyVersion=1.0.0",
+ "configs.application.clTargetType=VM",
+ "configs.application.clEventStatus=ONSET",
+ "configs.application.clVersion=1.0.2",
+ "configs.application.clTarget=vserver.vserver-name",
+ "configs.application.clOriginator=DCAE-bbs-event-processor",
+ "configs.application.re-registration.policyScope=reRegPolicyScope",
+ "configs.application.re-registration.clControlName=reRegControlName",
+ "configs.application.cpe-authentication.policyScope=cpeAuthPolicyScope",
+ "configs.application.cpe-authentication.clControlName=cpeAuthControlName"})
+@DisplayName("Application Configuration Unit-Tests")
+// Ordering tests because we need a first configuration population from @TestPropertySource
+// and then update of the config parameters based on a new Consul-retrieved Configuration object
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ApplicationConfigurationTest {
+
+ private ApplicationConfiguration configuration;
+
+ @Autowired
+ public ApplicationConfigurationTest(AaiClientProperties aaiClientProperties,
+ DmaapReRegistrationConsumerProperties dmaapReRegistrationConsumerProperties,
+ DmaapCpeAuthenticationConsumerProperties
+ dmaapCpeAuthenticationConsumerProperties,
+ DmaapProducerProperties dmaapProducerProperties,
+ SecurityProperties securityProperties,
+ GenericProperties genericProperties) {
+ this.configuration = new ApplicationConfiguration(aaiClientProperties,
+ dmaapReRegistrationConsumerProperties,
+ dmaapCpeAuthenticationConsumerProperties,
+ dmaapProducerProperties,
+ securityProperties,
+ genericProperties);
+ }
+
+ @Test
+ void testA_configurationObjectSuccessfullyPopulated() {
+
+ AaiClientConfiguration aaiClientConfiguration = configuration.getAaiClientConfiguration();
+ assertAll("AAI Client Configuration Properties",
+ () -> assertEquals("test localhost", aaiClientConfiguration.aaiHost()),
+ () -> assertEquals(Integer.valueOf(1234), aaiClientConfiguration.aaiPort()),
+ () -> assertEquals("https", aaiClientConfiguration.aaiProtocol()),
+ () -> assertEquals("AAI", aaiClientConfiguration.aaiUserName()),
+ () -> assertEquals("AAI", aaiClientConfiguration.aaiUserPassword()),
+ () -> assertTrue(aaiClientConfiguration.aaiIgnoreSslCertificateErrors()),
+ () -> assertEquals("bbs", aaiClientConfiguration.aaiHeaders().get("X-FromAppId")),
+ () -> assertEquals("9999", aaiClientConfiguration.aaiHeaders().get("X-TransactionId")),
+ () -> assertEquals("application/json", aaiClientConfiguration.aaiHeaders().get("Accept")),
+ () -> assertEquals("true", aaiClientConfiguration.aaiHeaders().get("Real-Time")),
+ () -> assertEquals("application/merge-patch+json",
+ aaiClientConfiguration.aaiHeaders().get("Content-Type"))
+ );
+
+ DmaapConsumerConfiguration dmaapConsumerReRegistrationConfig =
+ configuration.getDmaapReRegistrationConsumerConfiguration();
+ assertAll("DMaaP Consumer Re-Registration Configuration Properties",
+ () -> assertEquals("test localhost", dmaapConsumerReRegistrationConfig.dmaapHostName()),
+ () -> assertEquals(Integer.valueOf(1234), dmaapConsumerReRegistrationConfig.dmaapPortNumber()),
+ () -> assertEquals("/events/unauthenticated.PNF_REREGISTRATION",
+ dmaapConsumerReRegistrationConfig.dmaapTopicName()),
+ () -> assertEquals("http", dmaapConsumerReRegistrationConfig.dmaapProtocol()),
+ () -> assertEquals("", dmaapConsumerReRegistrationConfig.dmaapUserName()),
+ () -> assertEquals("", dmaapConsumerReRegistrationConfig.dmaapUserPassword()),
+ () -> assertEquals("application/json", dmaapConsumerReRegistrationConfig.dmaapContentType()),
+ () -> assertEquals("c12", dmaapConsumerReRegistrationConfig.consumerId()),
+ () -> assertEquals("OpenDcae-c12", dmaapConsumerReRegistrationConfig.consumerGroup()),
+ () -> assertEquals(Integer.valueOf(-1), dmaapConsumerReRegistrationConfig.timeoutMs()),
+ () -> assertEquals(Integer.valueOf(1), dmaapConsumerReRegistrationConfig.messageLimit())
+ );
+
+ DmaapConsumerConfiguration dmaapConsumerCpeAuthenticationConfig =
+ configuration.getDmaapCpeAuthenticationConsumerConfiguration();
+ assertAll("DMaaP Consumer CPE Authentication Configuration Properties",
+ () -> assertEquals("test localhost", dmaapConsumerCpeAuthenticationConfig.dmaapHostName()),
+ () -> assertEquals(Integer.valueOf(1234), dmaapConsumerCpeAuthenticationConfig.dmaapPortNumber()),
+ () -> assertEquals("/events/unauthenticated.CPE_AUTHENTICATION",
+ dmaapConsumerCpeAuthenticationConfig.dmaapTopicName()),
+ () -> assertEquals("http", dmaapConsumerCpeAuthenticationConfig.dmaapProtocol()),
+ () -> assertEquals("", dmaapConsumerCpeAuthenticationConfig.dmaapUserName()),
+ () -> assertEquals("", dmaapConsumerCpeAuthenticationConfig.dmaapUserPassword()),
+ () -> assertEquals("application/json", dmaapConsumerCpeAuthenticationConfig.dmaapContentType()),
+ () -> assertEquals("c12", dmaapConsumerCpeAuthenticationConfig.consumerId()),
+ () -> assertEquals("OpenDcae-c12", dmaapConsumerCpeAuthenticationConfig.consumerGroup()),
+ () -> assertEquals(Integer.valueOf(-1), dmaapConsumerCpeAuthenticationConfig.timeoutMs()),
+ () -> assertEquals(Integer.valueOf(1), dmaapConsumerCpeAuthenticationConfig.messageLimit())
+ );
+
+ DmaapPublisherConfiguration dmaapPublisherConfiguration = configuration.getDmaapPublisherConfiguration();
+ assertAll("DMaaP Publisher Configuration Properties",
+ () -> assertEquals("test localhost", dmaapPublisherConfiguration.dmaapHostName()),
+ () -> assertEquals(Integer.valueOf(1234), dmaapPublisherConfiguration.dmaapPortNumber()),
+ () -> assertEquals("/events/unauthenticated.DCAE_CL_OUTPUT",
+ dmaapPublisherConfiguration.dmaapTopicName()),
+ () -> assertEquals("http", dmaapPublisherConfiguration.dmaapProtocol()),
+ () -> assertEquals("", dmaapPublisherConfiguration.dmaapUserName()),
+ () -> assertEquals("", dmaapPublisherConfiguration.dmaapUserPassword()),
+ () -> assertEquals("application/json", dmaapPublisherConfiguration.dmaapContentType())
+ );
+
+ assertAll("Generic Application Properties",
+ () -> assertEquals(30, configuration.getPipelinesPollingIntervalInSeconds()),
+ () -> assertEquals(15, configuration.getPipelinesTimeoutInSeconds()),
+ () -> assertEquals("1.0.0", configuration.getPolicyVersion()),
+ () -> assertEquals("VM", configuration.getCloseLoopTargetType()),
+ () -> assertEquals("ONSET", configuration.getCloseLoopEventStatus()),
+ () -> assertEquals("1.0.2", configuration.getCloseLoopVersion()),
+ () -> assertEquals("vserver.vserver-name", configuration.getCloseLoopTarget()),
+ () -> assertEquals("DCAE-bbs-event-processor", configuration.getCloseLoopOriginator()),
+ () -> assertEquals("reRegPolicyScope", configuration.getReRegistrationCloseLoopPolicyScope()),
+ () -> assertEquals("cpeAuthPolicyScope", configuration.getCpeAuthenticationCloseLoopPolicyScope()),
+ () -> assertEquals("reRegControlName", configuration.getReRegistrationCloseLoopControlName()),
+ () -> assertEquals("cpeAuthControlName", configuration.getCpeAuthenticationCloseLoopControlName())
+ );
+ }
+
+ @Test
+ void testB_passingNewConfiguration_UpdateSucceeds() {
+ Map<String, GeneratedAppConfigObject.StreamsObject> subscribes = new HashMap<>();
+
+ GeneratedAppConfigObject.DmaapInfo dmaapInfo1 = ImmutableDmaapInfo.builder()
+ .clientId("1500462518108")
+ .clientRole("com.dcae.member")
+ .location("mtc00")
+ .topicUrl("https://we-are-message-router1.us:3901/events/unauthenticated.PNF_UPDATE")
+ .build();
+ GeneratedAppConfigObject.StreamsObject streamsObject1 = ImmutableStreamsObject.builder()
+ .type("message_router")
+ .aafUsername("some-user")
+ .aafPassword("some-password")
+ .dmaapInfo(dmaapInfo1)
+ .build();
+ GeneratedAppConfigObject.DmaapInfo dmaapInfo2 = ImmutableDmaapInfo.builder()
+ .clientId("1500462518108")
+ .clientRole("com.dcae.member")
+ .location("mtc00")
+ .topicUrl("https://we-are-message-router2.us:3902/events/unauthenticated.CPE_AUTHENTICATION")
+ .build();
+ GeneratedAppConfigObject.StreamsObject streamsObject2 = ImmutableStreamsObject.builder()
+ .type("message_router")
+ .aafUsername("some-user")
+ .aafPassword("some-password")
+ .dmaapInfo(dmaapInfo2)
+ .build();
+
+ subscribes.put("config_key_1", streamsObject1);
+ subscribes.put("config_key_2", streamsObject2);
+
+ // Create Publishes Objects
+ GeneratedAppConfigObject.DmaapInfo dmaapInfo3 = ImmutableDmaapInfo.builder()
+ .clientId("1500462518108")
+ .clientRole("com.dcae.member")
+ .location("mtc00")
+ .topicUrl("https://we-are-message-router3.us:3903/events/unauthenticated.DCAE_CL_OUTPUT")
+ .build();
+ GeneratedAppConfigObject.StreamsObject streamsObject3 = ImmutableStreamsObject.builder()
+ .type("message_router")
+ .aafUsername("some-user")
+ .aafPassword("some-password")
+ .dmaapInfo(dmaapInfo3)
+ .build();
+
+ // Final config object
+ GeneratedAppConfigObject updatedConfiguration = ImmutableGeneratedAppConfigObject.builder()
+ .dmaapProtocol("https")
+ .dmaapContentType("application/json")
+ .dmaapConsumerConsumerId("c13")
+ .dmaapConsumerConsumerGroup("OpenDcae-c13")
+ .dmaapMessageLimit(10)
+ .dmaapTimeoutMs(5)
+ .aaiHost("aai.onap.svc.cluster.local")
+ .aaiPort(8443)
+ .aaiProtocol("http")
+ .aaiUsername("AAI-update")
+ .aaiPassword("AAI-update")
+ .aaiIgnoreSslCertificateErrors(false)
+ .pipelinesPollingIntervalSec(20)
+ .pipelinesTimeoutSec(20)
+ .cbsPollingIntervalSec(180)
+ .policyVersion("2.0.0")
+ .closeLoopTargetType("VM2")
+ .closeLoopEventStatus("ONSET-update")
+ .closeLoopVersion("2.0.2")
+ .closeLoopTarget("Target-update")
+ .closeLoopOriginator("Originator-update")
+ .reRegistrationPolicyScope("policyScope-update")
+ .reRegistrationClControlName("controlName-update")
+ .cpeAuthPolicyScope("policyScope-update")
+ .cpeAuthClControlName("controlName-update")
+ .reRegConfigKey("config_key_1")
+ .cpeAuthConfigKey("config_key_2")
+ .closeLoopConfigKey("config_key_3")
+ .loggingLevel("TRACE")
+ .streamSubscribesMap(subscribes)
+ .streamPublishesMap(Collections.singletonMap("config_key_3", streamsObject3))
+ .build();
+
+ // Update the configuration
+ configuration.updateCurrentConfiguration(updatedConfiguration);
+
+ AaiClientConfiguration aaiClientConfiguration = configuration.getAaiClientConfiguration();
+ assertAll("AAI Client Configuration Properties",
+ () -> assertEquals("aai.onap.svc.cluster.local", aaiClientConfiguration.aaiHost()),
+ () -> assertEquals(Integer.valueOf(8443), aaiClientConfiguration.aaiPort()),
+ () -> assertEquals("http", aaiClientConfiguration.aaiProtocol()),
+ () -> assertEquals("AAI-update", aaiClientConfiguration.aaiUserName()),
+ () -> assertEquals("AAI-update", aaiClientConfiguration.aaiUserPassword()),
+ () -> assertFalse(aaiClientConfiguration.aaiIgnoreSslCertificateErrors()),
+ () -> assertEquals("bbs", aaiClientConfiguration.aaiHeaders().get("X-FromAppId")),
+ () -> assertEquals("9999", aaiClientConfiguration.aaiHeaders().get("X-TransactionId")),
+ () -> assertEquals("application/json", aaiClientConfiguration.aaiHeaders().get("Accept")),
+ () -> assertEquals("true", aaiClientConfiguration.aaiHeaders().get("Real-Time")),
+ () -> assertEquals("application/merge-patch+json",
+ aaiClientConfiguration.aaiHeaders().get("Content-Type"))
+ );
+
+ DmaapConsumerConfiguration dmaapConsumerReRegistrationConfig =
+ configuration.getDmaapReRegistrationConsumerConfiguration();
+ assertAll("DMaaP Consumer Re-Registration Configuration Properties",
+ () -> assertEquals("we-are-message-router1.us", dmaapConsumerReRegistrationConfig.dmaapHostName()),
+ () -> assertEquals(Integer.valueOf(3901), dmaapConsumerReRegistrationConfig.dmaapPortNumber()),
+ () -> assertEquals("/events/unauthenticated.PNF_UPDATE",
+ dmaapConsumerReRegistrationConfig.dmaapTopicName()),
+ () -> assertEquals("https", dmaapConsumerReRegistrationConfig.dmaapProtocol()),
+ () -> assertEquals("", dmaapConsumerReRegistrationConfig.dmaapUserName()),
+ () -> assertEquals("", dmaapConsumerReRegistrationConfig.dmaapUserPassword()),
+ () -> assertEquals("application/json", dmaapConsumerReRegistrationConfig.dmaapContentType()),
+ () -> assertEquals("c13", dmaapConsumerReRegistrationConfig.consumerId()),
+ () -> assertEquals("OpenDcae-c13", dmaapConsumerReRegistrationConfig.consumerGroup()),
+ () -> assertEquals(Integer.valueOf(5), dmaapConsumerReRegistrationConfig.timeoutMs()),
+ () -> assertEquals(Integer.valueOf(10), dmaapConsumerReRegistrationConfig.messageLimit())
+ );
+
+ DmaapConsumerConfiguration dmaapConsumerCpeAuthenticationConfig =
+ configuration.getDmaapCpeAuthenticationConsumerConfiguration();
+ assertAll("DMaaP Consumer CPE Authentication Configuration Properties",
+ () -> assertEquals("we-are-message-router2.us", dmaapConsumerCpeAuthenticationConfig.dmaapHostName()),
+ () -> assertEquals(Integer.valueOf(3902), dmaapConsumerCpeAuthenticationConfig.dmaapPortNumber()),
+ () -> assertEquals("/events/unauthenticated.CPE_AUTHENTICATION",
+ dmaapConsumerCpeAuthenticationConfig.dmaapTopicName()),
+ () -> assertEquals("https", dmaapConsumerCpeAuthenticationConfig.dmaapProtocol()),
+ () -> assertEquals("", dmaapConsumerCpeAuthenticationConfig.dmaapUserName()),
+ () -> assertEquals("", dmaapConsumerCpeAuthenticationConfig.dmaapUserPassword()),
+ () -> assertEquals("application/json", dmaapConsumerCpeAuthenticationConfig.dmaapContentType()),
+ () -> assertEquals("c13", dmaapConsumerCpeAuthenticationConfig.consumerId()),
+ () -> assertEquals("OpenDcae-c13", dmaapConsumerCpeAuthenticationConfig.consumerGroup()),
+ () -> assertEquals(Integer.valueOf(5), dmaapConsumerCpeAuthenticationConfig.timeoutMs()),
+ () -> assertEquals(Integer.valueOf(10), dmaapConsumerCpeAuthenticationConfig.messageLimit())
+ );
+
+ DmaapPublisherConfiguration dmaapPublisherConfiguration = configuration.getDmaapPublisherConfiguration();
+ assertAll("DMaaP Publisher Configuration Properties",
+ () -> assertEquals("we-are-message-router3.us", dmaapPublisherConfiguration.dmaapHostName()),
+ () -> assertEquals(Integer.valueOf(3903), dmaapPublisherConfiguration.dmaapPortNumber()),
+ () -> assertEquals("/events/unauthenticated.DCAE_CL_OUTPUT",
+ dmaapPublisherConfiguration.dmaapTopicName()),
+ () -> assertEquals("https", dmaapPublisherConfiguration.dmaapProtocol()),
+ () -> assertEquals("", dmaapPublisherConfiguration.dmaapUserName()),
+ () -> assertEquals("", dmaapPublisherConfiguration.dmaapUserPassword()),
+ () -> assertEquals("application/json", dmaapPublisherConfiguration.dmaapContentType())
+ );
+
+ assertAll("Generic Application Properties",
+ () -> assertEquals(20, configuration.getPipelinesPollingIntervalInSeconds()),
+ () -> assertEquals(20, configuration.getPipelinesTimeoutInSeconds()),
+ () -> assertEquals(180, configuration.getCbsPollingInterval()),
+ () -> assertEquals("2.0.0", configuration.getPolicyVersion()),
+ () -> assertEquals("VM2", configuration.getCloseLoopTargetType()),
+ () -> assertEquals("ONSET-update", configuration.getCloseLoopEventStatus()),
+ () -> assertEquals("2.0.2", configuration.getCloseLoopVersion()),
+ () -> assertEquals("Target-update", configuration.getCloseLoopTarget()),
+ () -> assertEquals("Originator-update", configuration.getCloseLoopOriginator()),
+ () -> assertEquals("policyScope-update", configuration.getReRegistrationCloseLoopPolicyScope()),
+ () -> assertEquals("policyScope-update", configuration.getCpeAuthenticationCloseLoopPolicyScope()),
+ () -> assertEquals("controlName-update", configuration.getReRegistrationCloseLoopControlName()),
+ () -> assertEquals("controlName-update", configuration.getCpeAuthenticationCloseLoopControlName())
+ );
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/ConsulConfigurationGatewayTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/ConsulConfigurationGatewayTest.java
new file mode 100644
index 00000000..9f5ce6dc
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/ConsulConfigurationGatewayTest.java
@@ -0,0 +1,215 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.doReturn;
+
+import com.google.gson.JsonParser;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.onap.bbs.event.processor.model.GeneratedAppConfigObject;
+import org.onap.bbs.event.processor.model.ImmutableDmaapInfo;
+import org.onap.bbs.event.processor.model.ImmutableGeneratedAppConfigObject;
+import org.onap.bbs.event.processor.model.ImmutableStreamsObject;
+
+class ConsulConfigurationGatewayTest {
+
+ private ConsulConfigurationGateway configurationGateway;
+ private static JsonParser jsonParser;
+
+ @BeforeAll
+ static void setup() {
+ jsonParser = new JsonParser();
+ }
+
+ ConsulConfigurationGatewayTest() {
+ ApplicationConfiguration configuration = Mockito.mock(ApplicationConfiguration.class);
+ this.configurationGateway = new ConsulConfigurationGateway(configuration);
+ }
+
+ @Test
+ void passingValidJson_constructsGeneratedAppConfigObject() {
+ final String validJson = "{"
+ + "\"dmaap.protocol\": \"http\","
+ + "\"dmaap.contentType\": \"application/json\","
+ + "\"dmaap.consumer.consumerId\": \"c12\","
+ + "\"dmaap.consumer.consumerGroup\": \"OpenDcae-c12\","
+ + "\"dmaap.messageLimit\": 1,"
+ + "\"dmaap.timeoutMs\": -1,"
+ + "\"aai.host\": \"aai.onap.svc.cluster.local\","
+ + "\"aai.port\": \"8443\","
+ + "\"aai.protocol\": \"https\","
+ + "\"aai.username\": \"AAI\","
+ + "\"aai.password\": \"AAI\","
+ + "\"aai.aaiIgnoreSslCertificateErrors\": true,"
+ + "\"application.pipelinesPollingIntervalSec\": 30,"
+ + "\"application.pipelinesTimeoutSec\": 15,"
+ + "\"application.cbsPollingIntervalSec\": 180,"
+ + "\"application.reregistration.policyScope\": \"policyScope\","
+ + "\"application.reregistration.clControlName\": \"controlName\","
+ + "\"application.cpe.authentication.policyScope\": \"policyScope\","
+ + "\"application.cpe.authentication.clControlName\": \"controlName\","
+ + "\"application.policyVersion\": \"1.0\","
+ + "\"application.clTargetType\": \"VM\","
+ + "\"application.clEventStatus\": \"ONSET\","
+ + "\"application.clVersion\": \"1.0.2\","
+ + "\"application.clTarget\": \"vserver.vserver-name\","
+ + "\"application.clOriginator\": \"DCAE-bbs-event-processor\","
+ + "\"application.reregistration.configKey\": \"config_key_2\","
+ + "\"application.cpeAuth.configKey\": \"config_key_1\","
+ + "\"application.closeLoop.configKey\": \"config_key_3\","
+ + "\"application.loggingLevel\": \"TRACE\","
+ + "\"streams_subscribes\": {"
+ + "\"config_key_1\": {"
+ + "\"type\": \"message_router\","
+ + "\"aaf_username\": \"some-user\","
+ + "\"aaf_password\": \"some-password\","
+ + "\"dmaap_info\": {"
+ + "\"client_id\": \"1500462518108\","
+ + "\"client_role\": \"com.dcae.member\","
+ + "\"location\": \"mtc00\","
+ + "\"topic_url\": \"https://we-are-message-router.us:3905/events/unauthenticated.CPE_AUTHENTICATION\""
+ + "}"
+ + "},"
+ + "\"config_key_2\": {"
+ + "\"type\": \"message_router\","
+ + "\"aaf_username\": \"some-user\","
+ + "\"aaf_password\": \"some-password\","
+ + "\"dmaap_info\": {"
+ + "\"client_id\": \"1500462518108\","
+ + "\"client_role\": \"com.dcae.member\","
+ + "\"location\": \"mtc00\","
+ + "\"topic_url\": \"https://we-are-message-router.us:3905/events/unauthenticated.PNF_UPDATE\""
+ + "}"
+ + "}"
+ + "},"
+ + "\"streams_publishes\": {"
+ + "\"config_key_3\": {"
+ + "\"type\": \"message_router\","
+ + "\"aaf_username\": \"some-user\","
+ + "\"aaf_password\": \"some-password\","
+ + "\"dmaap_info\": {"
+ + "\"client_id\": \"1500462518108\","
+ + "\"client_role\": \"com.dcae.member\","
+ + "\"location\": \"mtc00\","
+ + "\"topic_url\": \"https://we-are-message-router.us:3905/events/unauthenticated.DCAE_CL_OUTPUT\""
+ + "}"
+ + "}"
+ + "},"
+ + "\"services_calls\": {"
+ + "\"aai-interaction\": []"
+ + "}"
+ + "}";
+
+ // Create expected configuration
+ // Create Subscribes Objects
+ Map<String, GeneratedAppConfigObject.StreamsObject> subscribes = new HashMap<>();
+
+ GeneratedAppConfigObject.DmaapInfo dmaapInfo1 = ImmutableDmaapInfo.builder()
+ .clientId("1500462518108")
+ .clientRole("com.dcae.member")
+ .location("mtc00")
+ .topicUrl("https://we-are-message-router.us:3905/events/unauthenticated.CPE_AUTHENTICATION")
+ .build();
+ GeneratedAppConfigObject.StreamsObject streamsObject1 = ImmutableStreamsObject.builder()
+ .type("message_router")
+ .aafUsername("some-user")
+ .aafPassword("some-password")
+ .dmaapInfo(dmaapInfo1)
+ .build();
+ GeneratedAppConfigObject.DmaapInfo dmaapInfo2 = ImmutableDmaapInfo.builder()
+ .clientId("1500462518108")
+ .clientRole("com.dcae.member")
+ .location("mtc00")
+ .topicUrl("https://we-are-message-router.us:3905/events/unauthenticated.PNF_UPDATE")
+ .build();
+ GeneratedAppConfigObject.StreamsObject streamsObject2 = ImmutableStreamsObject.builder()
+ .type("message_router")
+ .aafUsername("some-user")
+ .aafPassword("some-password")
+ .dmaapInfo(dmaapInfo2)
+ .build();
+
+ subscribes.put("config_key_1", streamsObject1);
+ subscribes.put("config_key_2", streamsObject2);
+
+ // Create Publishes Objects
+ GeneratedAppConfigObject.DmaapInfo dmaapInfo3 = ImmutableDmaapInfo.builder()
+ .clientId("1500462518108")
+ .clientRole("com.dcae.member")
+ .location("mtc00")
+ .topicUrl("https://we-are-message-router.us:3905/events/unauthenticated.DCAE_CL_OUTPUT")
+ .build();
+ GeneratedAppConfigObject.StreamsObject streamsObject3 = ImmutableStreamsObject.builder()
+ .type("message_router")
+ .aafUsername("some-user")
+ .aafPassword("some-password")
+ .dmaapInfo(dmaapInfo3)
+ .build();
+
+ // Expected final config object
+ GeneratedAppConfigObject expectedConfiguration = ImmutableGeneratedAppConfigObject.builder()
+ .dmaapProtocol("http")
+ .dmaapContentType("application/json")
+ .dmaapConsumerConsumerId("c12")
+ .dmaapConsumerConsumerGroup("OpenDcae-c12")
+ .dmaapMessageLimit(1)
+ .dmaapTimeoutMs(-1)
+ .aaiHost("aai.onap.svc.cluster.local")
+ .aaiPort(8443)
+ .aaiProtocol("https")
+ .aaiUsername("AAI")
+ .aaiPassword("AAI")
+ .aaiIgnoreSslCertificateErrors(true)
+ .pipelinesPollingIntervalSec(30)
+ .pipelinesTimeoutSec(15)
+ .cbsPollingIntervalSec(180)
+ .reRegistrationPolicyScope("policyScope")
+ .reRegistrationClControlName("controlName")
+ .cpeAuthPolicyScope("policyScope")
+ .cpeAuthClControlName("controlName")
+ .policyVersion("1.0")
+ .closeLoopTargetType("VM")
+ .closeLoopEventStatus("ONSET")
+ .closeLoopVersion("1.0.2")
+ .closeLoopTarget("vserver.vserver-name")
+ .closeLoopOriginator("DCAE-bbs-event-processor")
+ .reRegConfigKey("config_key_2")
+ .cpeAuthConfigKey("config_key_1")
+ .closeLoopConfigKey("config_key_3")
+ .loggingLevel("TRACE")
+ .streamSubscribesMap(subscribes)
+ .streamPublishesMap(Collections.singletonMap("config_key_3", streamsObject3))
+ .build();
+
+ ConsulConfigurationGateway spiedGateway = Mockito.spy(configurationGateway);
+ doReturn(false).when(spiedGateway).environmentNotReady();
+ assertEquals(expectedConfiguration,
+ spiedGateway.generateAppConfigObject(jsonParser.parse(validJson).getAsJsonObject()));
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/DmaapCpeAuthenticationConsumerPropertiesTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/DmaapCpeAuthenticationConsumerPropertiesTest.java
new file mode 100644
index 00000000..103335ce
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/DmaapCpeAuthenticationConsumerPropertiesTest.java
@@ -0,0 +1,68 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+@SpringBootTest(classes = DmaapCpeAuthenticationConsumerProperties.class)
+@EnableConfigurationProperties
+@TestPropertySource(properties = {
+ "configs.dmaap.consumer.cpe-authentication.dmaapHostName=test localhost",
+ "configs.dmaap.consumer.cpe-authentication.dmaapPortNumber=1234",
+ "configs.dmaap.consumer.cpe-authentication.dmaapTopicName=/events/unauthenticated.PNF_CPE_AUTHENTICATION",
+ "configs.dmaap.consumer.cpe-authentication.dmaapProtocol=http",
+ "configs.dmaap.consumer.cpe-authentication.dmaapContentType=application/json",
+ "configs.dmaap.consumer.cpe-authentication.consumerId=c12",
+ "configs.dmaap.consumer.cpe-authentication.consumerGroup=OpenDcae-c12",
+ "configs.dmaap.consumer.cpe-authentication.timeoutMs=-1",
+ "configs.dmaap.consumer.cpe-authentication.messageLimit=1"})
+class DmaapCpeAuthenticationConsumerPropertiesTest {
+
+ private DmaapCpeAuthenticationConsumerProperties properties;
+
+ @Autowired
+ public DmaapCpeAuthenticationConsumerPropertiesTest(
+ DmaapCpeAuthenticationConsumerProperties properties) {
+ this.properties = properties;
+ }
+
+ @Test
+ void dmaapCpeAuthenticationProperties_SuccessFullyLoaded() {
+ assertEquals("test localhost", properties.getDmaapHostName());
+ assertEquals(1234, properties.getDmaapPortNumber());
+ assertEquals("/events/unauthenticated.PNF_CPE_AUTHENTICATION", properties.getDmaapTopicName());
+ assertEquals("http", properties.getDmaapProtocol());
+ assertNull(properties.getDmaapUserName());
+ assertNull(properties.getDmaapUserPassword());
+ assertEquals("application/json", properties.getDmaapContentType());
+ assertEquals("c12", properties.getConsumerId());
+ assertEquals("OpenDcae-c12", properties.getConsumerGroup());
+ assertEquals(-1, properties.getTimeoutMs());
+ assertEquals(1, properties.getMessageLimit());
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/DmaapProducerPropertiesTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/DmaapProducerPropertiesTest.java
new file mode 100644
index 00000000..7ba38f9e
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/DmaapProducerPropertiesTest.java
@@ -0,0 +1,60 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+@SpringBootTest(classes = DmaapProducerProperties.class)
+@EnableConfigurationProperties
+@TestPropertySource(properties = {
+ "configs.dmaap.producer.dmaapHostName=test localhost",
+ "configs.dmaap.producer.dmaapPortNumber=1234",
+ "configs.dmaap.producer.dmaapTopicName=/events/unauthenticated.DCAE_CL_OUTPUT",
+ "configs.dmaap.producer.dmaapProtocol=http",
+ "configs.dmaap.producer.dmaapContentType=application/json"})
+class DmaapProducerPropertiesTest {
+
+ private DmaapProducerProperties properties;
+
+ @Autowired
+ public DmaapProducerPropertiesTest(
+ DmaapProducerProperties properties) {
+ this.properties = properties;
+ }
+
+ @Test
+ void dmaapReRegistrationProperties_SuccessFullyLoaded() {
+ assertEquals("test localhost", properties.getDmaapHostName());
+ assertEquals(1234, properties.getDmaapPortNumber());
+ assertEquals("/events/unauthenticated.DCAE_CL_OUTPUT", properties.getDmaapTopicName());
+ assertEquals("http", properties.getDmaapProtocol());
+ assertNull(properties.getDmaapUserName());
+ assertNull(properties.getDmaapUserPassword());
+ assertEquals("application/json", properties.getDmaapContentType());
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/DmaapReRegistrationConsumerPropertiesTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/DmaapReRegistrationConsumerPropertiesTest.java
new file mode 100644
index 00000000..682d2f31
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/DmaapReRegistrationConsumerPropertiesTest.java
@@ -0,0 +1,68 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+@SpringBootTest(classes = DmaapReRegistrationConsumerProperties.class)
+@EnableConfigurationProperties
+@TestPropertySource(properties = {
+ "configs.dmaap.consumer.re-registration.dmaapHostName=test localhost",
+ "configs.dmaap.consumer.re-registration.dmaapPortNumber=1234",
+ "configs.dmaap.consumer.re-registration.dmaapTopicName=/events/unauthenticated.PNF_REREGISTRATION",
+ "configs.dmaap.consumer.re-registration.dmaapProtocol=http",
+ "configs.dmaap.consumer.re-registration.dmaapContentType=application/json",
+ "configs.dmaap.consumer.re-registration.consumerId=c12",
+ "configs.dmaap.consumer.re-registration.consumerGroup=OpenDcae-c12",
+ "configs.dmaap.consumer.re-registration.timeoutMs=-1",
+ "configs.dmaap.consumer.re-registration.messageLimit=1"})
+class DmaapReRegistrationConsumerPropertiesTest {
+
+ private DmaapReRegistrationConsumerProperties properties;
+
+ @Autowired
+ public DmaapReRegistrationConsumerPropertiesTest(
+ DmaapReRegistrationConsumerProperties properties) {
+ this.properties = properties;
+ }
+
+ @Test
+ void dmaapReRegistrationProperties_SuccessFullyLoaded() {
+ assertEquals("test localhost", properties.getDmaapHostName());
+ assertEquals(1234, properties.getDmaapPortNumber());
+ assertEquals("/events/unauthenticated.PNF_REREGISTRATION", properties.getDmaapTopicName());
+ assertEquals("http", properties.getDmaapProtocol());
+ assertNull(properties.getDmaapUserName());
+ assertNull(properties.getDmaapUserPassword());
+ assertEquals("application/json", properties.getDmaapContentType());
+ assertEquals("c12", properties.getConsumerId());
+ assertEquals("OpenDcae-c12", properties.getConsumerGroup());
+ assertEquals(-1, properties.getTimeoutMs());
+ assertEquals(1, properties.getMessageLimit());
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/GenericPropertiesTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/GenericPropertiesTest.java
new file mode 100644
index 00000000..91ebed8d
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/GenericPropertiesTest.java
@@ -0,0 +1,77 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+@SpringBootTest(classes = {GenericProperties.class,
+ GenericProperties.ReRegistrationGenericProperties.class,
+ GenericProperties.CpeAuthenticationGenericProperties.class})
+@EnableConfigurationProperties
+@TestPropertySource(properties = {
+ "configs.application.pipelinesPollingIntervalSec=30",
+ "configs.application.pipelinesTimeoutSec=15",
+ "configs.application.policyVersion=1.0.0",
+ "configs.application.clTargetType=VM",
+ "configs.application.clEventStatus=ONSET",
+ "configs.application.clVersion=1.0.2",
+ "configs.application.clTarget=vserver.vserver-name",
+ "configs.application.clOriginator=DCAE-bbs-event-processor",
+ "configs.application.re-registration.policyScope=reRegPolicyScope",
+ "configs.application.re-registration.clControlName=reRegControlName",
+ "configs.application.cpe-authentication.policyScope=cpeAuthPolicyScope",
+ "configs.application.cpe-authentication.clControlName=cpeAuthControlName"})
+class GenericPropertiesTest {
+
+ private GenericProperties genericProperties;
+
+ @Autowired
+ public GenericPropertiesTest(GenericProperties genericProperties) {
+ this.genericProperties = genericProperties;
+ }
+
+ @Test
+ void genericProperties_SuccessFullyLoaded() {
+ assertAll("Generic Application Properties",
+ () -> assertEquals(30, genericProperties.getPipelinesPollingIntervalSec()),
+ () -> assertEquals(15, genericProperties.getPipelinesTimeoutSec()),
+ () -> assertEquals("1.0.0", genericProperties.getPolicyVersion()),
+ () -> assertEquals("VM", genericProperties.getClTargetType()),
+ () -> assertEquals("ONSET", genericProperties.getClEventStatus()),
+ () -> assertEquals("1.0.2", genericProperties.getClVersion()),
+ () -> assertEquals("vserver.vserver-name", genericProperties.getClTarget()),
+ () -> assertEquals("DCAE-bbs-event-processor", genericProperties.getClOriginator()),
+ () -> assertEquals("reRegPolicyScope", genericProperties.getReRegistration().getPolicyScope()),
+ () -> assertEquals("cpeAuthPolicyScope",
+ genericProperties.getCpeAuthentication().getPolicyScope()),
+ () -> assertEquals("reRegControlName", genericProperties.getReRegistration().getClControlName()),
+ () -> assertEquals("cpeAuthControlName",
+ genericProperties.getCpeAuthentication().getClControlName())
+ );
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/SecurityPropertiesTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/SecurityPropertiesTest.java
new file mode 100644
index 00000000..0dd6d75d
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/config/SecurityPropertiesTest.java
@@ -0,0 +1,63 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.config;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+@SpringBootTest(classes = SecurityProperties.class)
+@EnableConfigurationProperties
+@TestPropertySource(properties = {
+ "configs.security.trustStorePath=test trust store path",
+ "configs.security.trustStorePasswordPath=test trust store password path",
+ "configs.security.keyStorePath=test key store path",
+ "configs.security.keyStorePasswordPath=test key store password path",
+ "configs.security.enableDmaapCertAuth=true",
+ "configs.security.enableAaiCertAuth=true"})
+class SecurityPropertiesTest {
+
+ private SecurityProperties securityProperties;
+
+ @Autowired
+ public SecurityPropertiesTest(SecurityProperties securityProperties) {
+ this.securityProperties = securityProperties;
+ }
+
+ @Test
+ void securityProperties_SuccessFullyLoaded() {
+ assertEquals("test key store path",
+ securityProperties.getKeyStorePath());
+ assertEquals("test key store password path",
+ securityProperties.getKeyStorePasswordPath());
+ assertEquals("test trust store path",
+ securityProperties.getTrustStorePath());
+ assertEquals("test trust store password path",
+ securityProperties.getTrustStorePasswordPath());
+ assertTrue(securityProperties.isEnableDmaapCertAuth());
+ assertTrue(securityProperties.isEnableAaiCertAuth());
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/controllers/BbsEventProcessorControllerTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/controllers/BbsEventProcessorControllerTest.java
new file mode 100644
index 00000000..bacb6c3e
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/controllers/BbsEventProcessorControllerTest.java
@@ -0,0 +1,163 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.controllers;
+
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.pipelines.CpeAuthenticationPipeline;
+import org.onap.bbs.event.processor.pipelines.ReRegistrationPipeline;
+import org.onap.bbs.event.processor.pipelines.Scheduler;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+
+@WebMvcTest(BbsEventProcessorController.class)
+@DisplayName("BBS Event Processor Controllers MVC Unit-Tests")
+class BbsEventProcessorControllerTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Autowired
+ private ReRegistrationPipeline reRegistrationPipeline;
+ @Autowired
+ private CpeAuthenticationPipeline cpeAuthenticationPipeline;
+ @Autowired
+ private Scheduler scheduler;
+ @Autowired
+ private ApplicationConfiguration configuration;
+
+ @BeforeEach
+ void resetInteractions() {
+ Mockito.reset(scheduler);
+ }
+
+ @Test
+ void sendingHeartBeatRestCall_RespondsWithAlive() throws Exception {
+ MvcResult heartBeatResult = mockMvc.perform(get("/heartbeat")).andReturn();
+
+ mockMvc.perform(asyncDispatch(heartBeatResult))
+ .andExpect(status().isOk())
+ .andExpect(content().string("bbs-event-processor is alive\n"));
+ }
+
+ @Test
+ void sendingReRegistrationSubmissionRestCall_RespondsWithOk() throws Exception {
+ MvcResult reregistrationSubmissionResult = mockMvc.perform(post("/poll-reregistration-events")).andReturn();
+
+ mockMvc.perform(asyncDispatch(reregistrationSubmissionResult))
+ .andExpect(status().isOk())
+ .andExpect(content().string("Request submitted\n"));
+ verify(reRegistrationPipeline, timeout(500)).processPnfReRegistrationEvents();
+ }
+
+ @Test
+ void sendingCpeAuthenticationSubmissionRestCall_RespondsWithOk() throws Exception {
+ MvcResult reregistrationSubmissionResult = mockMvc.perform(post("/poll-cpe-authentication-events")).andReturn();
+
+ mockMvc.perform(asyncDispatch(reregistrationSubmissionResult))
+ .andExpect(status().isOk())
+ .andExpect(content().string("Request submitted\n"));
+ verify(cpeAuthenticationPipeline, timeout(500)).processPnfCpeAuthenticationEvents();
+ }
+
+ @Test
+ void sendingStartTasksRestCall_ifItSucceeds_RespondsWithOk() throws Exception {
+ when(scheduler.reScheduleProcessingTasks()).thenReturn(true);
+ MvcResult startTasksResult = mockMvc.perform(post("/start-tasks")).andReturn();
+
+ mockMvc.perform(asyncDispatch(startTasksResult))
+ .andExpect(status().isOk())
+ .andExpect(content().string("Initiation of tasks was successful\n"));
+ verify(scheduler).reScheduleProcessingTasks();
+ }
+
+ @Test
+ void sendingStartTasksRestCall_ifItFails_RespondsWithNotAcceptable() throws Exception {
+ when(scheduler.reScheduleProcessingTasks()).thenReturn(false);
+ MvcResult startTasksResult = mockMvc.perform(post("/start-tasks")).andReturn();
+
+ mockMvc.perform(asyncDispatch(startTasksResult))
+ .andExpect(status().isNotAcceptable())
+ .andExpect(content().string("Initiation of tasks failed\n"));
+ verify(scheduler).reScheduleProcessingTasks();
+ }
+
+ @Test
+ void sendingCancelTasksRestCall_ifItSucceeds_RespondsWithOk() throws Exception {
+ when(scheduler.cancelScheduledProcessingTasks()).thenReturn(true);
+ MvcResult cancellationResult = mockMvc.perform(post("/cancel-tasks")).andReturn();
+
+ mockMvc.perform(asyncDispatch(cancellationResult))
+ .andExpect(status().isOk())
+ .andExpect(content().string("Cancellation was successful\n"));
+ verify(scheduler).cancelScheduledProcessingTasks();
+ }
+
+ @Test
+ void sendingCancelTasksRestCall_ifItFails_RespondsWithNotAcceptable() throws Exception {
+ when(scheduler.cancelScheduledProcessingTasks()).thenReturn(false);
+ MvcResult cancellationResult = mockMvc.perform(post("/cancel-tasks")).andReturn();
+
+ mockMvc.perform(asyncDispatch(cancellationResult))
+ .andExpect(status().isNotAcceptable())
+ .andExpect(content().string("Cancellation failed\n"));
+ verify(scheduler).cancelScheduledProcessingTasks();
+ }
+
+ @TestConfiguration
+ static class ControllerTestConfiguration {
+ @Bean
+ ReRegistrationPipeline reRegistrationPipeline() {
+ return Mockito.mock(ReRegistrationPipeline.class);
+ }
+
+ @Bean
+ CpeAuthenticationPipeline cpeAuthenticationPipeline() {
+ return Mockito.mock(CpeAuthenticationPipeline.class);
+ }
+
+ @Bean
+ Scheduler scheduler() {
+ return Mockito.mock(Scheduler.class);
+ }
+
+ @Bean
+ ApplicationConfiguration configuration() {
+ return Mockito.mock(ApplicationConfiguration.class);
+ }
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/model/GsonSerializationsTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/model/GsonSerializationsTest.java
new file mode 100644
index 00000000..fd43b8be
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/model/GsonSerializationsTest.java
@@ -0,0 +1,379 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.model;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.TypeAdapterFactory;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+import org.junit.jupiter.api.Test;
+import org.onap.bbs.event.processor.utilities.ControlLoopJsonBodyBuilder;
+import org.onap.bbs.event.processor.utilities.CpeAuthenticationJsonBodyBuilder;
+import org.onap.bbs.event.processor.utilities.ReRegistrationJsonBodyBuilder;
+
+class GsonSerializationsTest {
+
+ @Test
+ void creatingReRegistrationJsonBody_returnsJsonInString() {
+
+ String correlationId = "NokiaCorrelationId";
+ String attachmentPoint = "olt2/1/1";
+ String remoteId = "RemoteId";
+ String cvlan = "1005";
+ String svlan = "100";
+
+ String template = "{"
+ + "\"correlationId\":\"%s\","
+ + "\"attachment-point\":\"%s\","
+ + "\"remote-id\":\"%s\","
+ + "\"cvlan\":\"%s\","
+ + "\"svlan\":\"%s\""
+ + "}";
+
+ ReRegistrationConsumerDmaapModel model = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(correlationId)
+ .attachmentPoint(attachmentPoint)
+ .remoteId(remoteId)
+ .cVlan(cvlan)
+ .sVlan(svlan)
+ .build();
+
+
+ String expectedResult = String.format(template, correlationId, attachmentPoint, remoteId, cvlan, svlan);
+
+ assertEquals(expectedResult, new ReRegistrationJsonBodyBuilder().createJsonBody(model));
+ }
+
+ @Test
+ void creatingCpeAuthenticationJsonBody_returnsJsonInString() {
+
+ String correlationId = "NokiaCorrelationID";
+ AuthenticationState oldAuthenticationState = AuthenticationState.IN_SERVICE;
+ AuthenticationState newAuthenticationState = AuthenticationState.OUT_OF_SERVICE;
+ String stateInterface = "stateInterface";
+ String rgwMacAddress = "00:0a:95:8d:78:16";
+ String swVersion = "1.2";
+
+ String template = "{"
+ + "\"correlationId\":\"%s\","
+ + "\"old-authentication-state\":\"%s\","
+ + "\"new-authentication-state\":\"%s\","
+ + "\"state-interface\":\"%s\","
+ + "\"rgw-mac-address\":\"%s\","
+ + "\"sw-version\":\"%s\""
+ + "}";
+
+ CpeAuthenticationConsumerDmaapModel model = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(correlationId)
+ .oldAuthenticationState(oldAuthenticationState.getNameInOnap())
+ .newAuthenticationState(newAuthenticationState.getNameInOnap())
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress)
+ .swVersion(swVersion)
+ .build();
+
+
+ String expectedResult = String.format(template, correlationId, oldAuthenticationState.getNameInOnap(),
+ newAuthenticationState.getNameInOnap(), stateInterface, rgwMacAddress, swVersion);
+
+ assertEquals(expectedResult, new CpeAuthenticationJsonBodyBuilder().createJsonBody(model));
+ }
+
+ @Test
+ void creatingDcaeControlLoopJsonBody_returnsJsonInString() {
+
+ String closedLoopEventClient = "DCAE.BBS_mSInstance";
+ String policyVersion = "1.0.0.5";
+ String policyName = "CPE_Authentication";
+ String policyScope =
+ "service=HSIAService,type=SampleType,"
+ + "closedLoopControlName=CL-CPE_A-d925ed73-8231-4d02-9545-db4e101f88f8";
+ String targetType = "VM";
+ long closedLoopAlarmStart = 1484677482204798L;
+ String closedLoopEventStatus = "ONSET";
+ String closedLoopControlName = "ControlLoop-CPE_A-2179b738-fd36-4843-a71a-a8c24c70c88b";
+ String version = "1.0.2";
+ String target = "vserver.vserver-name";
+ String requestId = "97964e10-686e-4790-8c45-bdfa61df770f";
+ String from = "DCAE";
+
+ Map<String, String> aaiEnrichmentData = new LinkedHashMap<>();
+ aaiEnrichmentData.put("service-information.service-instance-id", "service-instance-id-example");
+ aaiEnrichmentData.put("cvlan-id", "example cvlan-id");
+ aaiEnrichmentData.put("svlan-id", "example svlan-id");
+
+ String template = "{"
+ + "\"closedLoopEventClient\":\"%s\","
+ + "\"policyVersion\":\"%s\","
+ + "\"policyName\":\"%s\","
+ + "\"policyScope\":\"%s\","
+ + "\"target_type\":\"%s\","
+ + "\"AAI\":{"
+ + "\"service-information.service-instance-id\":\"service-instance-id-example\","
+ + "\"cvlan-id\":\"example cvlan-id\","
+ + "\"svlan-id\":\"example svlan-id\""
+ + "},"
+ + "\"closedLoopAlarmStart\":%s,"
+ + "\"closedLoopEventStatus\":\"%s\","
+ + "\"closedLoopControlName\":\"%s\","
+ + "\"version\":\"%s\","
+ + "\"target\":\"%s\","
+ + "\"requestID\":\"%s\","
+ + "\"from\":\"%s\""
+ + "}";
+
+
+ ControlLoopPublisherDmaapModel model = ImmutableControlLoopPublisherDmaapModel.builder()
+ .closedLoopEventClient(closedLoopEventClient)
+ .policyVersion(policyVersion)
+ .policyName(policyName)
+ .policyScope(policyScope)
+ .targetType(targetType)
+ .aaiEnrichmentData(aaiEnrichmentData)
+ .closedLoopAlarmStart(closedLoopAlarmStart)
+ .closedLoopEventStatus(closedLoopEventStatus)
+ .closedLoopControlName(closedLoopControlName)
+ .version(version)
+ .target(target)
+ .requestId(requestId)
+ .originator(from)
+ .build();
+
+ String expectedResult = String.format(template,
+ closedLoopEventClient,
+ policyVersion,
+ policyName,
+ policyScope,
+ targetType,
+ closedLoopAlarmStart,
+ closedLoopEventStatus,
+ closedLoopControlName,
+ version,
+ target,
+ requestId,
+ from);
+
+ assertEquals(expectedResult, new ControlLoopJsonBodyBuilder().createJsonBody(model));
+ }
+
+ @Test
+ void pnfAaiObject_IsSerializedSuccessfully() {
+
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory);
+ Gson gson = gsonBuilder.create();
+
+ String pnfName = "NokiaCorrelationID";
+ String swVersion = "1.2";
+
+ String template = "{"
+ + "\"pnf-name\":\"%s\","
+ + "\"in-maint\":true,"
+ + "\"sw-version\":\"%s\","
+ + "\"relationship-list\":{"
+ + "\"relationship\":["
+ + "{"
+ + "\"related-to\":\"service-instance\","
+ + "\"relationship-label\":\"org.onap.relationships.inventory.ComposedOf\","
+ + "\"related-link\":\"/aai/v14/business/customers/customer/Demonstration/service-subscriptions"
+ + "/service-subscription/BBS/service-instances/service-instance/84003b26-6b76-4c75-b805-7b14ab4ffaef\","
+ + "\"relationship-data\":["
+ + "{"
+ + "\"relationship-key\":\"customer.global-customer-id\","
+ + "\"relationship-value\":\"Demonstration\""
+ + "},"
+ + "{"
+ + "\"relationship-key\":\"service-subscription.service-type\","
+ + "\"relationship-value\":\"BBS\""
+ + "},"
+ + "{"
+ + "\"relationship-key\":\"service-instance.service-instance-id\","
+ + "\"relationship-value\":\"84003b26-6b76-4c75-b805-7b14ab4ffaef\""
+ + "}"
+ + "],"
+ + "\"related-to-property\":["
+ + "{"
+ + "\"property-key\":\"service-instance.service-instance-name\","
+ + "\"property-value\":\"bbs-instance\""
+ + "}"
+ + "]"
+ + "},"
+ + "{"
+ + "\"related-to\":\"platform\","
+ + "\"relationship-label\":\"org.onap.relationships.inventory.Uses\","
+ + "\"related-link\":\"/aai/v14/business/platforms/platform/bbs-platform\","
+ + "\"relationship-data\":["
+ + "{"
+ + "\"relationship-key\":\"platform.platform-name\","
+ + "\"relationship-value\":\"bbs-platform\""
+ + "}"
+ + "]"
+ + "}"
+ + "]"
+ + "}"
+ + "}";
+
+ // Build Relationship Data
+ RelationshipListAaiObject.RelationshipEntryAaiObject firstRelationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("service-instance")
+ .relatedLink("/aai/v14/business/customers/customer/Demonstration/service-subscriptions"
+ + "/service-subscription/BBS/service-instances"
+ + "/service-instance/84003b26-6b76-4c75-b805-7b14ab4ffaef")
+ .relationshipLabel("org.onap.relationships.inventory.ComposedOf")
+ .relationshipData(Arrays.asList(
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("customer.global-customer-id")
+ .relationshipValue("Demonstration").build(),
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-subscription.service-type")
+ .relationshipValue("BBS").build(),
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-instance.service-instance-id")
+ .relationshipValue("84003b26-6b76-4c75-b805-7b14ab4ffaef").build())
+ )
+ .relatedToProperties(Collections.singletonList(
+ ImmutablePropertyAaiObject.builder()
+ .propertyKey("service-instance.service-instance-name")
+ .propertyValue("bbs-instance").build())
+ )
+ .build();
+
+ RelationshipListAaiObject.RelationshipEntryAaiObject secondRelationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("platform")
+ .relatedLink("/aai/v14/business/platforms/platform/bbs-platform")
+ .relationshipLabel("org.onap.relationships.inventory.Uses")
+ .relationshipData(Collections.singletonList(ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("platform.platform-name")
+ .relationshipValue("bbs-platform").build()))
+ .build();
+
+ RelationshipListAaiObject relationshipListAaiObject = ImmutableRelationshipListAaiObject.builder()
+ .relationshipEntries(Arrays.asList(firstRelationshipEntry, secondRelationshipEntry))
+ .build();
+
+ // Finally construct PNF object data
+ PnfAaiObject pnfAaiObject = ImmutablePnfAaiObject.builder()
+ .pnfName(pnfName)
+ .isInMaintenance(true)
+ .swVersion(swVersion)
+ .relationshipListAaiObject(relationshipListAaiObject)
+ .build();
+
+
+ String jsonPnfObject = String.format(template, pnfName, swVersion);
+
+ assertEquals(jsonPnfObject, gson.toJson(pnfAaiObject));
+ assertEquals(pnfAaiObject, gson.fromJson(jsonPnfObject, ImmutablePnfAaiObject.class));
+ }
+
+ @Test
+ void serviceInstanceAaiObject_IsSerializedSuccessfully() {
+
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory);
+ Gson gson = gsonBuilder.create();
+
+ String serviceInstanceId = "84003b26-6b76-4c75-b805-7b14ab4ffaef";
+ String orchestrationStatus = "active";
+
+ String template = "{"
+ + "\"service-instance-id\":\"%s\","
+ + "\"orchestration-status\":\"%s\","
+ + "\"relationship-list\":{"
+ + "\"relationship\":["
+ + "{"
+ + "\"related-to\":\"service-instance\","
+ + "\"relationship-label\":\"org.onap.relationships.inventory.ComposedOf\","
+ + "\"related-link\":\"/aai/v14/business/customers/customer/Demonstration/service-subscriptions"
+ + "/service-subscription/BBS-CFS"
+ + "/service-instances/service-instance/bb374844-44e4-488f-8381-fb5a0e3e6989\","
+ + "\"relationship-data\":["
+ + "{"
+ + "\"relationship-key\":\"service-instance.service-instance-id\","
+ + "\"relationship-value\":\"bb374844-44e4-488f-8381-fb5a0e3e6989\""
+ + "}"
+ + "]"
+ + "}"
+ + "]"
+ + "},"
+ + "\"metadata\":{"
+ + "\"metadatum\":["
+ + "{"
+ + "\"metaname\":\"cvlan\","
+ + "\"metaval\":\"1005\""
+ + "}"
+ + "]"
+ + "}"
+ + "}";
+
+ // Build Relationship Data
+ RelationshipListAaiObject.RelationshipEntryAaiObject relationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("service-instance")
+ .relatedLink("/aai/v14/business/customers/customer/Demonstration/service-subscriptions"
+ + "/service-subscription/BBS-CFS/service-instances"
+ + "/service-instance/bb374844-44e4-488f-8381-fb5a0e3e6989")
+ .relationshipLabel("org.onap.relationships.inventory.ComposedOf")
+ .relationshipData(Collections.singletonList(ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-instance.service-instance-id")
+ .relationshipValue("bb374844-44e4-488f-8381-fb5a0e3e6989").build()))
+ .build();
+
+ RelationshipListAaiObject relationshipListAaiObject = ImmutableRelationshipListAaiObject.builder()
+ .relationshipEntries(Collections.singletonList(relationshipEntry))
+ .build();
+
+ MetadataListAaiObject.MetadataEntryAaiObject metadataEntry =
+ ImmutableMetadataEntryAaiObject.builder()
+ .metaname("cvlan")
+ .metavalue("1005")
+ .build();
+
+ MetadataListAaiObject metadataListAaiObject = ImmutableMetadataListAaiObject.builder()
+ .metadataEntries(Collections.singletonList(metadataEntry))
+ .build();
+
+ // Finally construct Service Instance object data
+ ServiceInstanceAaiObject serviceInstanceAaiObject = ImmutableServiceInstanceAaiObject.builder()
+ .serviceInstanceId(serviceInstanceId)
+ .orchestrationStatus(orchestrationStatus)
+ .relationshipListAaiObject(relationshipListAaiObject)
+ .metadataListAaiObject(metadataListAaiObject)
+ .build();
+
+
+ String jsonServiceInstanceObject = String.format(template, serviceInstanceId, orchestrationStatus);
+
+ assertEquals(jsonServiceInstanceObject, gson.toJson(serviceInstanceAaiObject));
+ assertEquals(serviceInstanceAaiObject, gson.fromJson(jsonServiceInstanceObject,
+ ImmutableServiceInstanceAaiObject.class));
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/pipelines/CpeAuthenticationPipelineTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/pipelines/CpeAuthenticationPipelineTest.java
new file mode 100644
index 00000000..76d9659c
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/pipelines/CpeAuthenticationPipelineTest.java
@@ -0,0 +1,668 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.pipelines;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+import static org.onap.bbs.event.processor.config.ApplicationConstants.CONSUME_CPE_AUTHENTICATION_TASK_NAME;
+import static org.onap.bbs.event.processor.config.ApplicationConstants.RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME;
+import static org.onap.bbs.event.processor.config.ApplicationConstants.RETRIEVE_PNF_TASK_NAME;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.UUID;
+
+import javax.net.ssl.SSLException;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.exceptions.AaiTaskException;
+import org.onap.bbs.event.processor.exceptions.EmptyDmaapResponseException;
+import org.onap.bbs.event.processor.model.ControlLoopPublisherDmaapModel;
+import org.onap.bbs.event.processor.model.CpeAuthenticationConsumerDmaapModel;
+import org.onap.bbs.event.processor.model.ImmutableCpeAuthenticationConsumerDmaapModel;
+import org.onap.bbs.event.processor.model.ImmutableMetadataEntryAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableMetadataListAaiObject;
+import org.onap.bbs.event.processor.model.ImmutablePnfAaiObject;
+import org.onap.bbs.event.processor.model.ImmutablePropertyAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableRelationshipDataEntryAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableRelationshipEntryAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableRelationshipListAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableServiceInstanceAaiObject;
+import org.onap.bbs.event.processor.model.MetadataListAaiObject;
+import org.onap.bbs.event.processor.model.PnfAaiObject;
+import org.onap.bbs.event.processor.model.RelationshipListAaiObject;
+import org.onap.bbs.event.processor.model.ServiceInstanceAaiObject;
+import org.onap.bbs.event.processor.tasks.AaiClientTask;
+import org.onap.bbs.event.processor.tasks.DmaapCpeAuthenticationConsumerTask;
+import org.onap.bbs.event.processor.tasks.DmaapPublisherTask;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+// We can safely suppress unchecked assignment warnings for the ResponseEntity mock
+@SuppressWarnings("unchecked")
+@DisplayName("CPE Authentication Pipeline Unit-Tests")
+class CpeAuthenticationPipelineTest {
+
+ private CpeAuthenticationPipeline pipeline;
+ private ApplicationConfiguration configuration;
+ private DmaapCpeAuthenticationConsumerTask consumerTask;
+ private DmaapPublisherTask publisherTask;
+ private AaiClientTask aaiClientTask;
+
+ private ResponseEntity<String> responseEntity;
+
+ @BeforeEach
+ void setup() {
+
+ responseEntity = Mockito.mock(ResponseEntity.class);
+
+ configuration = Mockito.mock(ApplicationConfiguration.class);
+ consumerTask = Mockito.mock(DmaapCpeAuthenticationConsumerTask.class);
+ publisherTask = Mockito.mock(DmaapPublisherTask.class);
+ aaiClientTask = Mockito.mock(AaiClientTask.class);
+
+ when(configuration.getCpeAuthenticationCloseLoopControlName())
+ .thenReturn("controlName");
+ when(configuration.getCpeAuthenticationCloseLoopPolicyScope())
+ .thenReturn("policyScope");
+ when(configuration.getPolicyVersion())
+ .thenReturn("1.0.0");
+ when(configuration.getCloseLoopTargetType())
+ .thenReturn("VM");
+ when(configuration.getCloseLoopEventStatus())
+ .thenReturn("ONSET");
+ when(configuration.getCloseLoopVersion())
+ .thenReturn("1.0.2");
+ when(configuration.getCloseLoopTarget())
+ .thenReturn("CL-Target");
+ when(configuration.getCloseLoopOriginator())
+ .thenReturn("DCAE-BBS-ep");
+
+ pipeline = new CpeAuthenticationPipeline(configuration, consumerTask,
+ publisherTask, aaiClientTask, new HashMap<>());
+ }
+
+ @Test
+ void handleEmptyResponseFromDmaap() throws SSLException {
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(anyString()))
+ .thenReturn(Flux.error(new EmptyDmaapResponseException("Mock empty")));
+
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .verifyComplete();
+
+ verifyZeroInteractions(aaiClientTask);
+ verifyZeroInteractions(publisherTask);
+ }
+
+ @Test
+ void noResponseFromDmaap_PipelineTimesOut() throws SSLException {
+
+ // Prepare mocks
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(1);
+ when(consumerTask.execute(CONSUME_CPE_AUTHENTICATION_TASK_NAME))
+ .thenReturn(Flux.never());
+
+ // Execute pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .verifyComplete();
+
+ verifyZeroInteractions(aaiClientTask);
+ verifyZeroInteractions(publisherTask);
+ }
+
+ @Test
+ void noResponseFromAai_PipelineTimesOut() throws SSLException {
+
+ String pnfName = "olt1";
+ final String oldAuthenticationState = "outOfService";
+ final String newAuthenticationState = "inService";
+ final String stateInterface = "stateInterface";
+ final String rgwMacAddress = "00:0a:95:8d:78:16";
+ final String swVersion = "1.2";
+
+ // Prepare stubbed replies
+ CpeAuthenticationConsumerDmaapModel event = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(pnfName)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress)
+ .swVersion(swVersion)
+ .build();
+
+ // Prepare mocks
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(1);
+ when(consumerTask.execute(CONSUME_CPE_AUTHENTICATION_TASK_NAME)).thenReturn(Flux.just(event));
+ when(aaiClientTask.executePnfRetrieval(anyString(), anyString())).thenReturn(Mono.never());
+
+ // Execute pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .verifyComplete();
+
+ verifyZeroInteractions(publisherTask);
+ }
+
+ @Test
+ void noResponseWhilePublishing_PipelineTimesOut() throws SSLException {
+
+ String pnfName = "olt1";
+ final String oldAuthenticationState = "outOfService";
+ final String newAuthenticationState = "inService";
+ final String stateInterface = "stateInterface";
+ final String rgwMacAddress = "00:0a:95:8d:78:16";
+ final String swVersion = "1.2";
+ String hsiCfsServiceInstanceId = UUID.randomUUID().toString();
+
+ // Prepare stubbed replies
+ CpeAuthenticationConsumerDmaapModel event = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(pnfName)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress)
+ .swVersion(swVersion)
+ .build();
+
+ PnfAaiObject pnfAaiObject = constructPnfObject(pnfName, hsiCfsServiceInstanceId);
+ ServiceInstanceAaiObject hsiCfsServiceInstance =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId, pnfName, rgwMacAddress);
+
+ // Prepare Mocks
+ String cfsUrl = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance.getServiceInstanceId());
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(1);
+ when(consumerTask.execute(CONSUME_CPE_AUTHENTICATION_TASK_NAME)).thenReturn(Flux.just(event));
+
+ when(aaiClientTask.executePnfRetrieval(anyString(), anyString()))
+ .thenReturn(Mono.just(pnfAaiObject));
+
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl))
+ .thenReturn(Mono.just(hsiCfsServiceInstance));
+
+ when(publisherTask.execute(any(ControlLoopPublisherDmaapModel.class))).thenReturn(Mono.never());
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .verifyComplete();
+
+ verify(publisherTask).execute(any(ControlLoopPublisherDmaapModel.class));
+ }
+
+ @Test
+ void singleCorrectEvent_handleSuccessfully() throws SSLException {
+
+ String pnfName = "olt1";
+ final String oldAuthenticationState = "outOfService";
+ final String newAuthenticationState = "inService";
+ final String stateInterface = "stateInterface";
+ final String rgwMacAddress = "00:0a:95:8d:78:16";
+ final String swVersion = "1.2";
+ String hsiCfsServiceInstanceId = UUID.randomUUID().toString();
+
+ // Prepare stubbed replies
+ CpeAuthenticationConsumerDmaapModel event = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(pnfName)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress)
+ .swVersion(swVersion)
+ .build();
+
+ PnfAaiObject pnfAaiObject = constructPnfObject(pnfName, hsiCfsServiceInstanceId);
+ ServiceInstanceAaiObject hsiCfsServiceInstance =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId, pnfName, rgwMacAddress);
+
+ // Prepare Mocks
+ String cfsUrl = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance.getServiceInstanceId());
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(CONSUME_CPE_AUTHENTICATION_TASK_NAME)).thenReturn(Flux.just(event));
+
+ when(aaiClientTask.executePnfRetrieval(anyString(), anyString()))
+ .thenReturn(Mono.just(pnfAaiObject));
+
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl))
+ .thenReturn(Mono.just(hsiCfsServiceInstance));
+
+ when(responseEntity.getStatusCode()).thenReturn(HttpStatus.valueOf(HttpStatus.OK.value()));
+ when(publisherTask.execute(any(ControlLoopPublisherDmaapModel.class))).thenReturn(Mono.just(responseEntity));
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .assertNext(r -> assertEquals(HttpStatus.OK, r.getStatusCode()))
+ .verifyComplete();
+
+ verify(publisherTask).execute(any(ControlLoopPublisherDmaapModel.class));
+ }
+
+ @Test
+ void twoCorrectEvents_handleSuccessfully() throws SSLException {
+
+ String pnfName1 = "olt1";
+ String pnfName2 = "olt2";
+ final String oldAuthenticationState = "outOfService";
+ final String newAuthenticationState = "inService";
+ final String stateInterface = "stateInterface";
+ final String rgwMacAddress1 = "00:0a:95:8d:78:16";
+ final String rgwMacAddress2 = "00:0a:95:8d:78:17";
+ final String swVersion = "1.2";
+ String hsiCfsServiceInstanceId1 = UUID.randomUUID().toString();
+ String hsiCfsServiceInstanceId2 = UUID.randomUUID().toString();
+
+ // Prepare stubbed replies
+ CpeAuthenticationConsumerDmaapModel firstEvent = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(pnfName1)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress1)
+ .swVersion(swVersion)
+ .build();
+ CpeAuthenticationConsumerDmaapModel secondEvent = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(pnfName2)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress2)
+ .swVersion(swVersion)
+ .build();
+
+ PnfAaiObject pnfAaiObject1 = constructPnfObject(pnfName1, hsiCfsServiceInstanceId1);
+ PnfAaiObject pnfAaiObject2 = constructPnfObject(pnfName2, hsiCfsServiceInstanceId2);
+ ServiceInstanceAaiObject hsiCfsServiceInstance1 =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId1, pnfName1, rgwMacAddress1);
+ ServiceInstanceAaiObject hsiCfsServiceInstance2 =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId2, pnfName2, rgwMacAddress2);
+
+ // Prepare Mocks
+ String pnfUrl1 = String.format("/aai/v14/network/pnfs/pnf/%s?depth=all", pnfName1);
+ String pnfUrl2 = String.format("/aai/v14/network/pnfs/pnf/%s?depth=all", pnfName2);
+ String cfsUrl1 = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance1.getServiceInstanceId());
+ String cfsUrl2 = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance2.getServiceInstanceId());
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(CONSUME_CPE_AUTHENTICATION_TASK_NAME))
+ .thenReturn(Flux.fromIterable(Arrays.asList(firstEvent, secondEvent)));
+
+ when(aaiClientTask.executePnfRetrieval(RETRIEVE_PNF_TASK_NAME, pnfUrl1)).thenReturn(Mono.just(pnfAaiObject1));
+ when(aaiClientTask.executePnfRetrieval(RETRIEVE_PNF_TASK_NAME, pnfUrl2)).thenReturn(Mono.just(pnfAaiObject2));
+
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl1))
+ .thenReturn(Mono.just(hsiCfsServiceInstance1));
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl2))
+ .thenReturn(Mono.just(hsiCfsServiceInstance2));
+
+ when(responseEntity.getStatusCode()).thenReturn(HttpStatus.valueOf(HttpStatus.OK.value()));
+ when(publisherTask.execute(any(ControlLoopPublisherDmaapModel.class))).thenReturn(Mono.just(responseEntity));
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .assertNext(r -> assertEquals(HttpStatus.OK, r.getStatusCode()))
+ .assertNext(r -> assertEquals(HttpStatus.OK, r.getStatusCode()))
+ .verifyComplete();
+
+ verify(publisherTask, times(2)).execute(any(ControlLoopPublisherDmaapModel.class));
+ }
+
+ @Test
+ void singleEvent_withPnfErrorReply_handleGracefully() throws SSLException {
+
+ String pnfName = "olt1";
+ final String oldAuthenticationState = "outOfService";
+ final String newAuthenticationState = "inService";
+ final String stateInterface = "stateInterface";
+ final String rgwMacAddress = "00:0a:95:8d:78:16";
+ final String swVersion = "1.2";
+
+ // Prepare stubbed replies
+ CpeAuthenticationConsumerDmaapModel event = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(pnfName)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress)
+ .swVersion(swVersion)
+ .build();
+
+ // Prepare Mocks
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(CONSUME_CPE_AUTHENTICATION_TASK_NAME)).thenReturn(Flux.just(event));
+ when(aaiClientTask.executePnfRetrieval(anyString(), anyString()))
+ .thenReturn(Mono.error(new AaiTaskException("Mock A&AI exception")));
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .verifyComplete();
+
+ verify(aaiClientTask).executePnfRetrieval(anyString(), anyString());
+ verifyNoMoreInteractions(aaiClientTask);
+ verifyZeroInteractions(publisherTask);
+ }
+
+ @Test
+ void twoEvents_FirstOk_SecondUnmatchedMac_handleCorrectOnly() throws SSLException {
+
+ String pnfName1 = "olt1";
+ String pnfName2 = "olt2";
+ final String oldAuthenticationState = "outOfService";
+ final String newAuthenticationState = "inService";
+ final String stateInterface = "stateInterface";
+ final String rgwMacAddress1 = "00:0a:95:8d:78:16";
+ final String rgwMacAddress2 = "00:0a:95:8d:78:17";
+ final String swVersion = "1.2";
+ String hsiCfsServiceInstanceId1 = UUID.randomUUID().toString();
+ String hsiCfsServiceInstanceId2 = UUID.randomUUID().toString();
+
+ // Prepare stubbed replies
+ CpeAuthenticationConsumerDmaapModel firstEvent = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(pnfName1)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress1)
+ .swVersion(swVersion)
+ .build();
+ CpeAuthenticationConsumerDmaapModel secondEvent = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(pnfName2)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress2)
+ .swVersion(swVersion)
+ .build();
+
+ PnfAaiObject pnfAaiObject1 = constructPnfObject(pnfName1, hsiCfsServiceInstanceId1);
+ PnfAaiObject pnfAaiObject2 = constructPnfObject(pnfName2, hsiCfsServiceInstanceId2);
+ ServiceInstanceAaiObject hsiCfsServiceInstance1 =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId1, pnfName1, rgwMacAddress1);
+ ServiceInstanceAaiObject hsiCfsServiceInstance2 =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId2, pnfName2,
+ "Having unmatched RGW MAC address");
+
+ // Prepare Mocks
+ String pnfUrl1 = String.format("/aai/v14/network/pnfs/pnf/%s?depth=all", pnfName1);
+ String pnfUrl2 = String.format("/aai/v14/network/pnfs/pnf/%s?depth=all", pnfName2);
+ String cfsUrl1 = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance1.getServiceInstanceId());
+ String cfsUrl2 = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance2.getServiceInstanceId());
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(CONSUME_CPE_AUTHENTICATION_TASK_NAME))
+ .thenReturn(Flux.fromIterable(Arrays.asList(firstEvent, secondEvent)));
+
+ when(aaiClientTask.executePnfRetrieval(RETRIEVE_PNF_TASK_NAME, pnfUrl1)).thenReturn(Mono.just(pnfAaiObject1));
+ when(aaiClientTask.executePnfRetrieval(RETRIEVE_PNF_TASK_NAME, pnfUrl2)).thenReturn(Mono.just(pnfAaiObject2));
+
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl1))
+ .thenReturn(Mono.just(hsiCfsServiceInstance1));
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl2))
+ .thenReturn(Mono.just(hsiCfsServiceInstance2));
+
+ when(responseEntity.getStatusCode()).thenReturn(HttpStatus.valueOf(HttpStatus.OK.value()));
+ when(publisherTask.execute(any(ControlLoopPublisherDmaapModel.class))).thenReturn(Mono.just(responseEntity));
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .assertNext(r -> assertEquals(HttpStatus.OK, r.getStatusCode()))
+ .verifyComplete();
+
+ verify(publisherTask).execute(any(ControlLoopPublisherDmaapModel.class));
+ }
+
+ @Test
+ void twoEvents_firstOk_secondWithPnfErrorReply_handleCorrectOnly() throws SSLException {
+
+ String pnfName1 = "olt1";
+ String pnfName2 = "olt2";
+ final String oldAuthenticationState = "outOfService";
+ final String newAuthenticationState = "inService";
+ final String stateInterface = "stateInterface";
+ final String rgwMacAddress = "00:0a:95:8d:78:16";
+ final String swVersion = "1.2";
+ String hsiCfsServiceInstanceId = UUID.randomUUID().toString();
+
+ // Prepare stubbed replies
+ CpeAuthenticationConsumerDmaapModel firstEvent = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(pnfName1)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress)
+ .swVersion(swVersion)
+ .build();
+ CpeAuthenticationConsumerDmaapModel secondEvent = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(pnfName2)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress)
+ .swVersion(swVersion)
+ .build();
+
+ PnfAaiObject pnfAaiObject = constructPnfObject(pnfName1, hsiCfsServiceInstanceId);
+ ServiceInstanceAaiObject hsiCfsServiceInstance =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId, pnfName1, rgwMacAddress);
+
+ // Prepare Mocks
+ String cfsUrl = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance.getServiceInstanceId());
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(CONSUME_CPE_AUTHENTICATION_TASK_NAME))
+ .thenReturn(Flux.fromIterable(Arrays.asList(firstEvent, secondEvent)));
+ when(aaiClientTask.executePnfRetrieval(anyString(), anyString()))
+ .thenReturn(Mono.just(pnfAaiObject))
+ .thenReturn(Mono.error(new AaiTaskException("Mock A&AI exception")));
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl))
+ .thenReturn(Mono.just(hsiCfsServiceInstance));
+
+ when(responseEntity.getStatusCode()).thenReturn(HttpStatus.valueOf(HttpStatus.OK.value()));
+ when(publisherTask.execute(any(ControlLoopPublisherDmaapModel.class))).thenReturn(Mono.just(responseEntity));
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .assertNext(r -> assertEquals(HttpStatus.OK, r.getStatusCode()))
+ .verifyComplete();
+
+ verify(aaiClientTask, times(2)).executePnfRetrieval(anyString(), anyString());
+ verify(aaiClientTask).executeServiceInstanceRetrieval(anyString(), anyString());
+ verify(publisherTask).execute(any(ControlLoopPublisherDmaapModel.class));
+ }
+
+ @Test
+ void twoEvents_firstWithPnfErrorReply_secondOk_handleCorrectOnly() throws SSLException {
+
+ String pnfName1 = "olt1";
+ String pnfName2 = "olt2";
+ final String oldAuthenticationState = "outOfService";
+ final String newAuthenticationState = "inService";
+ final String stateInterface = "stateInterface";
+ final String rgwMacAddress = "00:0a:95:8d:78:16";
+ final String swVersion = "1.2";
+ String hsiCfsServiceInstanceId = UUID.randomUUID().toString();
+
+ // Prepare stubbed replies
+ CpeAuthenticationConsumerDmaapModel firstEvent = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(pnfName1)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress)
+ .swVersion(swVersion)
+ .build();
+ CpeAuthenticationConsumerDmaapModel secondEvent = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(pnfName2)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress)
+ .swVersion(swVersion)
+ .build();
+
+ PnfAaiObject pnfAaiObject = constructPnfObject(pnfName2, hsiCfsServiceInstanceId);
+ ServiceInstanceAaiObject hsiCfsServiceInstance =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId, pnfName2, rgwMacAddress);
+
+ // Prepare Mocks
+ String cfsUrl = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance.getServiceInstanceId());
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(CONSUME_CPE_AUTHENTICATION_TASK_NAME))
+ .thenReturn(Flux.fromIterable(Arrays.asList(firstEvent, secondEvent)));
+ when(aaiClientTask.executePnfRetrieval(anyString(), anyString()))
+ .thenReturn(Mono.error(new AaiTaskException("Mock A&AI exception")))
+ .thenReturn(Mono.just(pnfAaiObject));
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl))
+ .thenReturn(Mono.just(hsiCfsServiceInstance));
+
+ when(responseEntity.getStatusCode()).thenReturn(HttpStatus.valueOf(HttpStatus.OK.value()));
+ when(publisherTask.execute(any(ControlLoopPublisherDmaapModel.class))).thenReturn(Mono.just(responseEntity));
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .assertNext(r -> assertEquals(HttpStatus.OK, r.getStatusCode()))
+ .verifyComplete();
+
+ verify(aaiClientTask, times(2))
+ .executePnfRetrieval(anyString(), anyString());
+ verify(aaiClientTask).executeServiceInstanceRetrieval(anyString(), anyString());
+ verify(publisherTask).execute(any(ControlLoopPublisherDmaapModel.class));
+ }
+
+ private PnfAaiObject constructPnfObject(String pnfName, String hsiCfsServiceInstanceId) {
+
+ // Build Relationship Data
+ RelationshipListAaiObject.RelationshipEntryAaiObject relationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("service-instance")
+ .relatedLink("/aai/v14/business/customers/customer/Demonstration/service-subscriptions"
+ + "/service-subscription/BBS-CFS/service-instances"
+ + "/service-instance/" + hsiCfsServiceInstanceId)
+ .relationshipLabel("org.onap.relationships.inventory.ComposedOf")
+ .relationshipData(Arrays.asList(
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("customer.global-customer-id")
+ .relationshipValue("Demonstration").build(),
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-subscription.service-type")
+ .relationshipValue("BBS-CFS").build(),
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-instance.service-instance-id")
+ .relationshipValue(hsiCfsServiceInstanceId).build())
+ )
+ .relatedToProperties(Collections.singletonList(
+ ImmutablePropertyAaiObject.builder()
+ .propertyKey("service-instance.service-instance-name")
+ .propertyValue("bbs-instance").build())
+ )
+ .build();
+
+ RelationshipListAaiObject relationshipListAaiObject = ImmutableRelationshipListAaiObject.builder()
+ .relationshipEntries(Collections.singletonList(relationshipEntry))
+ .build();
+
+ // Finally construct PNF object data
+ return ImmutablePnfAaiObject.builder()
+ .pnfName(pnfName)
+ .isInMaintenance(true)
+ .relationshipListAaiObject(relationshipListAaiObject)
+ .build();
+ }
+
+ private ServiceInstanceAaiObject constructHsiCfsServiceInstanceObject(String hsiCfsServiceInstanceId,
+ String pnfName,
+ String rgwMacAddress) {
+ String orchestrationStatus = "active";
+
+ RelationshipListAaiObject.RelationshipEntryAaiObject relationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("pnf")
+ .relatedLink("/pnfs/pnf/" + pnfName)
+ .relationshipData(Collections.singletonList(ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("pnf.pnf-name")
+ .relationshipValue(pnfName).build()))
+ .build();
+
+ RelationshipListAaiObject relationshipListAaiObject = ImmutableRelationshipListAaiObject.builder()
+ .relationshipEntries(Collections.singletonList(relationshipEntry))
+ .build();
+
+ MetadataListAaiObject.MetadataEntryAaiObject metadataEntry =
+ ImmutableMetadataEntryAaiObject.builder()
+ .metaname("rgw-mac-address")
+ .metavalue(rgwMacAddress)
+ .build();
+
+ MetadataListAaiObject metadataListAaiObject = ImmutableMetadataListAaiObject.builder()
+ .metadataEntries(Collections.singletonList(metadataEntry))
+ .build();
+
+ // Finally construct Service Instance object data
+ return ImmutableServiceInstanceAaiObject.builder()
+ .serviceInstanceId(hsiCfsServiceInstanceId)
+ .orchestrationStatus(orchestrationStatus)
+ .relationshipListAaiObject(relationshipListAaiObject)
+ .metadataListAaiObject(metadataListAaiObject)
+ .build();
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/pipelines/ReRegistrationPipelineTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/pipelines/ReRegistrationPipelineTest.java
new file mode 100644
index 00000000..a1b6b148
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/pipelines/ReRegistrationPipelineTest.java
@@ -0,0 +1,757 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.pipelines;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+import static org.onap.bbs.event.processor.config.ApplicationConstants.CONSUME_REREGISTRATION_TASK_NAME;
+import static org.onap.bbs.event.processor.config.ApplicationConstants.RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME;
+import static org.onap.bbs.event.processor.config.ApplicationConstants.RETRIEVE_PNF_TASK_NAME;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.UUID;
+
+import javax.net.ssl.SSLException;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.exceptions.AaiTaskException;
+import org.onap.bbs.event.processor.exceptions.EmptyDmaapResponseException;
+import org.onap.bbs.event.processor.model.ControlLoopPublisherDmaapModel;
+import org.onap.bbs.event.processor.model.ImmutableMetadataEntryAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableMetadataListAaiObject;
+import org.onap.bbs.event.processor.model.ImmutablePnfAaiObject;
+import org.onap.bbs.event.processor.model.ImmutablePropertyAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableReRegistrationConsumerDmaapModel;
+import org.onap.bbs.event.processor.model.ImmutableRelationshipDataEntryAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableRelationshipEntryAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableRelationshipListAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableServiceInstanceAaiObject;
+import org.onap.bbs.event.processor.model.MetadataListAaiObject;
+import org.onap.bbs.event.processor.model.PnfAaiObject;
+import org.onap.bbs.event.processor.model.ReRegistrationConsumerDmaapModel;
+import org.onap.bbs.event.processor.model.RelationshipListAaiObject;
+import org.onap.bbs.event.processor.model.ServiceInstanceAaiObject;
+import org.onap.bbs.event.processor.tasks.AaiClientTask;
+import org.onap.bbs.event.processor.tasks.DmaapPublisherTask;
+import org.onap.bbs.event.processor.tasks.DmaapReRegistrationConsumerTask;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+// We can safely suppress unchecked assignment warnings for the ResponseEntity mock
+@SuppressWarnings("unchecked")
+@DisplayName("PNF Re-registration Pipeline Unit-Tests")
+class ReRegistrationPipelineTest {
+
+ private ReRegistrationPipeline pipeline;
+ private ApplicationConfiguration configuration;
+ private DmaapReRegistrationConsumerTask consumerTask;
+ private DmaapPublisherTask publisherTask;
+ private AaiClientTask aaiClientTask;
+
+ private ResponseEntity<String> responseEntity;
+
+ @BeforeEach
+ void setup() {
+
+ responseEntity = Mockito.mock(ResponseEntity.class);
+
+ configuration = Mockito.mock(ApplicationConfiguration.class);
+ consumerTask = Mockito.mock(DmaapReRegistrationConsumerTask.class);
+ publisherTask = Mockito.mock(DmaapPublisherTask.class);
+ aaiClientTask = Mockito.mock(AaiClientTask.class);
+
+ when(configuration.getReRegistrationCloseLoopControlName())
+ .thenReturn("controlName");
+ when(configuration.getReRegistrationCloseLoopPolicyScope())
+ .thenReturn("policyScope");
+ when(configuration.getPolicyVersion())
+ .thenReturn("1.0.0");
+ when(configuration.getCloseLoopTargetType())
+ .thenReturn("VM");
+ when(configuration.getCloseLoopEventStatus())
+ .thenReturn("ONSET");
+ when(configuration.getCloseLoopVersion())
+ .thenReturn("1.0.2");
+ when(configuration.getCloseLoopTarget())
+ .thenReturn("CL-Target");
+ when(configuration.getCloseLoopOriginator())
+ .thenReturn("DCAE-BBS-ep");
+
+ pipeline = new ReRegistrationPipeline(configuration, consumerTask,
+ publisherTask, aaiClientTask, new HashMap<>());
+ }
+
+ @Test
+ void handleEmptyResponseFromDmaap() throws SSLException {
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(anyString()))
+ .thenReturn(Flux.error(new EmptyDmaapResponseException("Mock empty")));
+
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .verifyComplete();
+
+ verifyZeroInteractions(aaiClientTask);
+ verifyZeroInteractions(publisherTask);
+ }
+
+ @Test
+ void noResponseFromDmaap_PipelineTimesOut() throws SSLException {
+
+ // Prepare mocks
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(1);
+ when(consumerTask.execute(CONSUME_REREGISTRATION_TASK_NAME))
+ .thenReturn(Flux.never());
+
+ // Execute pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .verifyComplete();
+
+ verifyZeroInteractions(aaiClientTask);
+ verifyZeroInteractions(publisherTask);
+ }
+
+ @Test
+ void noResponseFromAai_PipelineTimesOut() throws SSLException {
+
+ String pnfName = "olt1";
+ String attachmentPoint = "olt2-2-2";
+ String remoteId = "newRemoteId";
+ String cvlan = "1005";
+ String svlan = "100";
+
+ // Prepare stubbed replies
+ ReRegistrationConsumerDmaapModel event = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(pnfName)
+ .attachmentPoint(attachmentPoint)
+ .remoteId(remoteId)
+ .cVlan(cvlan)
+ .sVlan(svlan)
+ .build();
+
+ // Prepare mocks
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(1);
+ when(consumerTask.execute(CONSUME_REREGISTRATION_TASK_NAME)).thenReturn(Flux.just(event));
+ when(aaiClientTask.executePnfRetrieval(anyString(), anyString())).thenReturn(Mono.never());
+
+ // Execute pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .verifyComplete();
+
+ verifyZeroInteractions(publisherTask);
+ }
+
+ @Test
+ void noResponseWhilePublishing_PipelineTimesOut() throws SSLException {
+
+ String pnfName = "olt1";
+ String attachmentPoint = "olt2-2-2";
+ String remoteId = "newRemoteId";
+ String cvlan = "1005";
+ String svlan = "100";
+ String hsiCfsServiceInstanceId = UUID.randomUUID().toString();
+
+ // Prepare stubbed replies
+ ReRegistrationConsumerDmaapModel event = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(pnfName)
+ .attachmentPoint(attachmentPoint)
+ .remoteId(remoteId)
+ .cVlan(cvlan)
+ .sVlan(svlan)
+ .build();
+
+ PnfAaiObject pnfAaiObject = constructPnfObject(pnfName, "olt1-1-1", hsiCfsServiceInstanceId);
+ ServiceInstanceAaiObject hsiCfsServiceInstance =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId, pnfName, cvlan);
+
+ // Prepare Mocks
+ String cfsUrl = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance.getServiceInstanceId());
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(1);
+ when(consumerTask.execute(CONSUME_REREGISTRATION_TASK_NAME)).thenReturn(Flux.just(event));
+
+ when(aaiClientTask.executePnfRetrieval(anyString(), anyString()))
+ .thenReturn(Mono.just(pnfAaiObject));
+
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl))
+ .thenReturn(Mono.just(hsiCfsServiceInstance));
+
+ when(publisherTask.execute(any(ControlLoopPublisherDmaapModel.class))).thenReturn(Mono.never());
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .verifyComplete();
+
+ verify(publisherTask).execute(any(ControlLoopPublisherDmaapModel.class));
+ }
+
+ @Test
+ void singleCorrectEvent_PnfHavingNoLogicalLink_handleGracefully() throws SSLException {
+
+ String pnfName = "olt1";
+ String attachmentPoint = "olt2-2-2";
+ String remoteId = "newRemoteId";
+ String cvlan = "1005";
+ String svlan = "100";
+ String hsiCfsServiceInstanceId = UUID.randomUUID().toString();
+
+ // Prepare stubbed replies
+ ReRegistrationConsumerDmaapModel event = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(pnfName)
+ .attachmentPoint(attachmentPoint)
+ .remoteId(remoteId)
+ .cVlan(cvlan)
+ .sVlan(svlan)
+ .build();
+
+ PnfAaiObject pnfAaiObject = constructPnfObjectWithoutLogicalLink(pnfName, hsiCfsServiceInstanceId);
+ ServiceInstanceAaiObject hsiCfsServiceInstance =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId, pnfName, cvlan);
+
+ // Prepare Mocks
+ String cfsUrl = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance.getServiceInstanceId());
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(CONSUME_REREGISTRATION_TASK_NAME)).thenReturn(Flux.just(event));
+
+ when(aaiClientTask.executePnfRetrieval(anyString(), anyString()))
+ .thenReturn(Mono.just(pnfAaiObject));
+
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl))
+ .thenReturn(Mono.just(hsiCfsServiceInstance));
+
+ when(responseEntity.getStatusCode()).thenReturn(HttpStatus.valueOf(HttpStatus.OK.value()));
+ when(publisherTask.execute(any(ControlLoopPublisherDmaapModel.class))).thenReturn(Mono.just(responseEntity));
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .verifyComplete();
+
+ verify(aaiClientTask).executePnfRetrieval(anyString(), anyString());
+ verifyNoMoreInteractions(aaiClientTask);
+ verifyZeroInteractions(publisherTask);
+ }
+
+ @Test
+ void singleCorrectEvent_handleSuccessfully() throws SSLException {
+
+ String pnfName = "olt1";
+ String attachmentPoint = "olt2-2-2";
+ String remoteId = "newRemoteId";
+ String cvlan = "1005";
+ String svlan = "100";
+ String hsiCfsServiceInstanceId = UUID.randomUUID().toString();
+
+ // Prepare stubbed replies
+ ReRegistrationConsumerDmaapModel event = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(pnfName)
+ .attachmentPoint(attachmentPoint)
+ .remoteId(remoteId)
+ .cVlan(cvlan)
+ .sVlan(svlan)
+ .build();
+
+ PnfAaiObject pnfAaiObject = constructPnfObject(pnfName, "old-attachment-point", hsiCfsServiceInstanceId);
+ ServiceInstanceAaiObject hsiCfsServiceInstance =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId, pnfName, cvlan);
+
+ // Prepare Mocks
+ String cfsUrl = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance.getServiceInstanceId());
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(CONSUME_REREGISTRATION_TASK_NAME)).thenReturn(Flux.just(event));
+
+ when(aaiClientTask.executePnfRetrieval(anyString(), anyString()))
+ .thenReturn(Mono.just(pnfAaiObject));
+
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl))
+ .thenReturn(Mono.just(hsiCfsServiceInstance));
+
+ when(responseEntity.getStatusCode()).thenReturn(HttpStatus.valueOf(HttpStatus.OK.value()));
+ when(publisherTask.execute(any(ControlLoopPublisherDmaapModel.class))).thenReturn(Mono.just(responseEntity));
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .assertNext(r -> assertEquals(HttpStatus.OK, r.getStatusCode()))
+ .verifyComplete();
+
+ verify(publisherTask).execute(any(ControlLoopPublisherDmaapModel.class));
+ }
+
+ @Test
+ void twoCorrectEvents_handleSuccessfully() throws SSLException {
+
+ String pnfName1 = "olt1";
+ String pnfName2 = "olt2";
+ String attachmentPoint1 = "olt1-1-1";
+ String attachmentPoint2 = "olt2-2-2";
+ String remoteId1 = "newRemoteId1";
+ String remoteId2 = "newRemoteId2";
+ String cvlan1 = "1005";
+ String cvlan2 = "1006";
+ String svlan = "100";
+ String hsiCfsServiceInstanceId1 = UUID.randomUUID().toString();
+ String hsiCfsServiceInstanceId2 = UUID.randomUUID().toString();
+
+ // Prepare stubbed replies
+ ReRegistrationConsumerDmaapModel firstEvent = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(pnfName1)
+ .attachmentPoint(attachmentPoint1)
+ .remoteId(remoteId1)
+ .cVlan(cvlan1)
+ .sVlan(svlan)
+ .build();
+ ReRegistrationConsumerDmaapModel secondEvent = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(pnfName2)
+ .attachmentPoint(attachmentPoint2)
+ .remoteId(remoteId2)
+ .cVlan(cvlan2)
+ .sVlan(svlan)
+ .build();
+
+ PnfAaiObject pnfAaiObject1 = constructPnfObject(pnfName1, "olt1-1-0", hsiCfsServiceInstanceId1);
+ PnfAaiObject pnfAaiObject2 = constructPnfObject(pnfName2, "olt2-2-0", hsiCfsServiceInstanceId2);
+ ServiceInstanceAaiObject hsiCfsServiceInstance1 =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId1, pnfName1, cvlan1);
+ ServiceInstanceAaiObject hsiCfsServiceInstance2 =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId2, pnfName2, cvlan2);
+
+ // Prepare Mocks
+ String pnfUrl1 = String.format("/aai/v14/network/pnfs/pnf/%s?depth=all", pnfName1);
+ String pnfUrl2 = String.format("/aai/v14/network/pnfs/pnf/%s?depth=all", pnfName2);
+ String cfsUrl1 = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance1.getServiceInstanceId());
+ String cfsUrl2 = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance2.getServiceInstanceId());
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(CONSUME_REREGISTRATION_TASK_NAME))
+ .thenReturn(Flux.fromIterable(Arrays.asList(firstEvent, secondEvent)));
+
+ when(aaiClientTask.executePnfRetrieval(RETRIEVE_PNF_TASK_NAME, pnfUrl1)).thenReturn(Mono.just(pnfAaiObject1));
+ when(aaiClientTask.executePnfRetrieval(RETRIEVE_PNF_TASK_NAME, pnfUrl2)).thenReturn(Mono.just(pnfAaiObject2));
+
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl1))
+ .thenReturn(Mono.just(hsiCfsServiceInstance1));
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl2))
+ .thenReturn(Mono.just(hsiCfsServiceInstance2));
+
+ when(responseEntity.getStatusCode()).thenReturn(HttpStatus.valueOf(HttpStatus.OK.value()));
+ when(publisherTask.execute(any(ControlLoopPublisherDmaapModel.class))).thenReturn(Mono.just(responseEntity));
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .assertNext(r -> assertEquals(HttpStatus.OK, r.getStatusCode()))
+ .assertNext(r -> assertEquals(HttpStatus.OK, r.getStatusCode()))
+ .verifyComplete();
+
+ verify(publisherTask, times(2)).execute(any(ControlLoopPublisherDmaapModel.class));
+ }
+
+ @Test
+ void singleEvent_withPnfErrorReply_handleGracefully() throws SSLException {
+
+ String pnfName = "olt1";
+ String attachmentPoint = "olt2-2-2";
+ String remoteId = "newRemoteId";
+ String cvlan = "1005";
+ String svlan = "100";
+
+ // Prepare stubbed replies
+ ReRegistrationConsumerDmaapModel event = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(pnfName)
+ .attachmentPoint(attachmentPoint)
+ .remoteId(remoteId)
+ .cVlan(cvlan)
+ .sVlan(svlan)
+ .build();
+
+ // Prepare Mocks
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(CONSUME_REREGISTRATION_TASK_NAME)).thenReturn(Flux.just(event));
+ when(aaiClientTask.executePnfRetrieval(anyString(), anyString()))
+ .thenReturn(Mono.error(new AaiTaskException("Mock A&AI exception")));
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .verifyComplete();
+
+ verify(aaiClientTask).executePnfRetrieval(anyString(), anyString());
+ verifyNoMoreInteractions(aaiClientTask);
+ verifyZeroInteractions(publisherTask);
+ }
+
+ @Test
+ void twoEvents_FirstOk_SecondNotRelocation_handleCorrectOnly() throws SSLException {
+
+ String pnfName1 = "olt1";
+ String pnfName2 = "olt2";
+ String attachmentPoint1 = "olt1-1-1";
+ String attachmentPoint2 = "olt2-2-2";
+ String remoteId1 = "newRemoteId1";
+ String remoteId2 = "newRemoteId2";
+ String cvlan1 = "1005";
+ String cvlan2 = "1006";
+ String svlan = "100";
+ String hsiCfsServiceInstanceId1 = UUID.randomUUID().toString();
+ String hsiCfsServiceInstanceId2 = UUID.randomUUID().toString();
+
+ // Prepare stubbed replies
+ ReRegistrationConsumerDmaapModel firstEvent = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(pnfName1)
+ .attachmentPoint(attachmentPoint1)
+ .remoteId(remoteId1)
+ .cVlan(cvlan1)
+ .sVlan(svlan)
+ .build();
+ ReRegistrationConsumerDmaapModel secondEvent = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(pnfName2)
+ .attachmentPoint(attachmentPoint2)
+ .remoteId(remoteId2)
+ .cVlan(cvlan2)
+ .sVlan(svlan)
+ .build();
+
+ PnfAaiObject pnfAaiObject1 = constructPnfObject(pnfName1, "olt1-1-0", hsiCfsServiceInstanceId1);
+ PnfAaiObject pnfAaiObject2 = constructPnfObject(pnfName2, attachmentPoint2, hsiCfsServiceInstanceId2);
+ ServiceInstanceAaiObject hsiCfsServiceInstance1 =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId1, pnfName1, cvlan1);
+ ServiceInstanceAaiObject hsiCfsServiceInstance2 =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId2, pnfName2, cvlan2);
+
+ // Prepare Mocks
+ String pnfUrl1 = String.format("/aai/v14/network/pnfs/pnf/%s?depth=all", pnfName1);
+ String pnfUrl2 = String.format("/aai/v14/network/pnfs/pnf/%s?depth=all", pnfName2);
+ String cfsUrl1 = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance1.getServiceInstanceId());
+ String cfsUrl2 = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance2.getServiceInstanceId());
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(CONSUME_REREGISTRATION_TASK_NAME))
+ .thenReturn(Flux.fromIterable(Arrays.asList(firstEvent, secondEvent)));
+
+ when(aaiClientTask.executePnfRetrieval(RETRIEVE_PNF_TASK_NAME, pnfUrl1)).thenReturn(Mono.just(pnfAaiObject1));
+ when(aaiClientTask.executePnfRetrieval(RETRIEVE_PNF_TASK_NAME, pnfUrl2)).thenReturn(Mono.just(pnfAaiObject2));
+
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl1))
+ .thenReturn(Mono.just(hsiCfsServiceInstance1));
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl2))
+ .thenReturn(Mono.just(hsiCfsServiceInstance2));
+
+ when(responseEntity.getStatusCode()).thenReturn(HttpStatus.valueOf(HttpStatus.OK.value()));
+ when(publisherTask.execute(any(ControlLoopPublisherDmaapModel.class))).thenReturn(Mono.just(responseEntity));
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .assertNext(r -> assertEquals(HttpStatus.OK, r.getStatusCode()))
+ .verifyComplete();
+
+ verify(publisherTask).execute(any(ControlLoopPublisherDmaapModel.class));
+ }
+
+ @Test
+ void twoEvents_firstOk_secondWithPnfErrorReply_handleCorrectOnly() throws SSLException {
+
+ String pnfName1 = "olt1";
+ String pnfName2 = "olt2";
+ String attachmentPoint1 = "olt1-1-1";
+ String attachmentPoint2 = "olt2-2-2";
+ String remoteId1 = "newRemoteId1";
+ String remoteId2 = "newRemoteId2";
+ String cvlan1 = "1005";
+ String cvlan2 = "1006";
+ String svlan = "100";
+ String hsiCfsServiceInstanceId = UUID.randomUUID().toString();
+
+ // Prepare stubbed replies
+ ReRegistrationConsumerDmaapModel firstEvent = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(pnfName1)
+ .attachmentPoint(attachmentPoint1)
+ .remoteId(remoteId1)
+ .cVlan(cvlan1)
+ .sVlan(svlan)
+ .build();
+ ReRegistrationConsumerDmaapModel secondEvent = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(pnfName2)
+ .attachmentPoint(attachmentPoint2)
+ .remoteId(remoteId2)
+ .cVlan(cvlan2)
+ .sVlan(svlan)
+ .build();
+
+ PnfAaiObject pnfAaiObject = constructPnfObject(pnfName1, "old-attachment-point", hsiCfsServiceInstanceId);
+ ServiceInstanceAaiObject hsiCfsServiceInstance =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId, pnfName1, cvlan1);
+
+ // Prepare Mocks
+ String cfsUrl = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance.getServiceInstanceId());
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(CONSUME_REREGISTRATION_TASK_NAME))
+ .thenReturn(Flux.fromIterable(Arrays.asList(firstEvent, secondEvent)));
+ when(aaiClientTask.executePnfRetrieval(anyString(), anyString()))
+ .thenReturn(Mono.just(pnfAaiObject))
+ .thenReturn(Mono.error(new AaiTaskException("Mock A&AI exception")));
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl))
+ .thenReturn(Mono.just(hsiCfsServiceInstance));
+
+ when(responseEntity.getStatusCode()).thenReturn(HttpStatus.valueOf(HttpStatus.OK.value()));
+ when(publisherTask.execute(any(ControlLoopPublisherDmaapModel.class))).thenReturn(Mono.just(responseEntity));
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .assertNext(r -> assertEquals(HttpStatus.OK, r.getStatusCode()))
+ .verifyComplete();
+
+ verify(aaiClientTask, times(2)).executePnfRetrieval(anyString(), anyString());
+ verify(aaiClientTask).executeServiceInstanceRetrieval(anyString(), anyString());
+ verify(publisherTask).execute(any(ControlLoopPublisherDmaapModel.class));
+ }
+
+ @Test
+ void twoEvents_firstWithPnfErrorReply_secondOk_handleCorrectOnly() throws SSLException {
+
+ String pnfName1 = "olt1";
+ String pnfName2 = "olt2";
+ String attachmentPoint1 = "olt1-1-1";
+ String attachmentPoint2 = "olt2-2-2";
+ String remoteId1 = "newRemoteId1";
+ String remoteId2 = "newRemoteId2";
+ String cvlan1 = "1005";
+ String cvlan2 = "1006";
+ String svlan = "100";
+ String hsiCfsServiceInstanceId = UUID.randomUUID().toString();
+
+ // Prepare stubbed replies
+ ReRegistrationConsumerDmaapModel firstEvent = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(pnfName1)
+ .attachmentPoint(attachmentPoint1)
+ .remoteId(remoteId1)
+ .cVlan(cvlan1)
+ .sVlan(svlan)
+ .build();
+ ReRegistrationConsumerDmaapModel secondEvent = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(pnfName2)
+ .attachmentPoint(attachmentPoint2)
+ .remoteId(remoteId2)
+ .cVlan(cvlan2)
+ .sVlan(svlan)
+ .build();
+
+ PnfAaiObject pnfAaiObject = constructPnfObject(pnfName2, "old-attachment-point", hsiCfsServiceInstanceId);
+ ServiceInstanceAaiObject hsiCfsServiceInstance =
+ constructHsiCfsServiceInstanceObject(hsiCfsServiceInstanceId, pnfName2, cvlan2);
+
+ // Prepare Mocks
+ String cfsUrl = String.format("/aai/v14/nodes/service-instances/service-instance/%s?depth=all",
+ hsiCfsServiceInstance.getServiceInstanceId());
+
+ when(configuration.getPipelinesTimeoutInSeconds()).thenReturn(10);
+ when(consumerTask.execute(CONSUME_REREGISTRATION_TASK_NAME))
+ .thenReturn(Flux.fromIterable(Arrays.asList(firstEvent, secondEvent)));
+ when(aaiClientTask.executePnfRetrieval(anyString(), anyString()))
+ .thenReturn(Mono.error(new AaiTaskException("Mock A&AI exception")))
+ .thenReturn(Mono.just(pnfAaiObject));
+ when(aaiClientTask
+ .executeServiceInstanceRetrieval(RETRIEVE_HSI_CFS_SERVICE_INSTANCE_TASK_NAME, cfsUrl))
+ .thenReturn(Mono.just(hsiCfsServiceInstance));
+
+ when(responseEntity.getStatusCode()).thenReturn(HttpStatus.valueOf(HttpStatus.OK.value()));
+ when(publisherTask.execute(any(ControlLoopPublisherDmaapModel.class))).thenReturn(Mono.just(responseEntity));
+
+ // Execute the pipeline
+ StepVerifier.create(pipeline.executePipeline())
+ .expectSubscription()
+ .assertNext(r -> assertEquals(HttpStatus.OK, r.getStatusCode()))
+ .verifyComplete();
+
+ verify(aaiClientTask, times(2))
+ .executePnfRetrieval(anyString(), anyString());
+ verify(aaiClientTask).executeServiceInstanceRetrieval(anyString(), anyString());
+ verify(publisherTask).execute(any(ControlLoopPublisherDmaapModel.class));
+ }
+
+ private PnfAaiObject constructPnfObject(String pnfName, String attachmentPoint,
+ String hsiCfsServiceInstanceId) {
+
+ // Build Relationship Data
+ RelationshipListAaiObject.RelationshipEntryAaiObject firstRelationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("service-instance")
+ .relatedLink("/aai/v14/business/customers/customer/Demonstration/service-subscriptions"
+ + "/service-subscription/BBS-CFS/service-instances"
+ + "/service-instance/" + hsiCfsServiceInstanceId)
+ .relationshipLabel("org.onap.relationships.inventory.ComposedOf")
+ .relationshipData(Arrays.asList(
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("customer.global-customer-id")
+ .relationshipValue("Demonstration").build(),
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-subscription.service-type")
+ .relationshipValue("BBS-CFS").build(),
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-instance.service-instance-id")
+ .relationshipValue(hsiCfsServiceInstanceId).build())
+ )
+ .relatedToProperties(Collections.singletonList(
+ ImmutablePropertyAaiObject.builder()
+ .propertyKey("service-instance.service-instance-name")
+ .propertyValue("bbs-instance").build())
+ )
+ .build();
+
+ RelationshipListAaiObject.RelationshipEntryAaiObject secondRelationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("logical-link")
+ .relatedLink("/network/logical-links/logical-link/" + attachmentPoint)
+ .relationshipData(Collections.singletonList(ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("logical-link.link-name")
+ .relationshipValue(attachmentPoint).build()))
+ .build();
+
+ RelationshipListAaiObject relationshipListAaiObject = ImmutableRelationshipListAaiObject.builder()
+ .relationshipEntries(Arrays.asList(firstRelationshipEntry, secondRelationshipEntry))
+ .build();
+
+ // Finally construct PNF object data
+ return ImmutablePnfAaiObject.builder()
+ .pnfName(pnfName)
+ .isInMaintenance(true)
+ .relationshipListAaiObject(relationshipListAaiObject)
+ .build();
+ }
+
+ private PnfAaiObject constructPnfObjectWithoutLogicalLink(String pnfName, String hsiCfsServiceInstanceId) {
+
+ // Build Relationship Data
+ RelationshipListAaiObject.RelationshipEntryAaiObject relationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("service-instance")
+ .relatedLink("/aai/v14/business/customers/customer/Demonstration/service-subscriptions"
+ + "/service-subscription/BBS-CFS/service-instances"
+ + "/service-instance/" + hsiCfsServiceInstanceId)
+ .relationshipLabel("org.onap.relationships.inventory.ComposedOf")
+ .relationshipData(Arrays.asList(
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("customer.global-customer-id")
+ .relationshipValue("Demonstration").build(),
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-subscription.service-type")
+ .relationshipValue("BBS-CFS").build(),
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-instance.service-instance-id")
+ .relationshipValue(hsiCfsServiceInstanceId).build())
+ )
+ .relatedToProperties(Collections.singletonList(
+ ImmutablePropertyAaiObject.builder()
+ .propertyKey("service-instance.service-instance-name")
+ .propertyValue("bbs-instance").build())
+ )
+ .build();
+
+ RelationshipListAaiObject relationshipListAaiObject = ImmutableRelationshipListAaiObject.builder()
+ .relationshipEntries(Collections.singletonList(relationshipEntry))
+ .build();
+
+ // Finally construct PNF object data
+ return ImmutablePnfAaiObject.builder()
+ .pnfName(pnfName)
+ .isInMaintenance(true)
+ .relationshipListAaiObject(relationshipListAaiObject)
+ .build();
+ }
+
+ private ServiceInstanceAaiObject constructHsiCfsServiceInstanceObject(String hsiCfsServiceInstanceId,
+ String pnfName,
+ String cvlan) {
+ String orchestrationStatus = "active";
+
+ RelationshipListAaiObject.RelationshipEntryAaiObject relationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("pnf")
+ .relatedLink("/pnfs/pnf/" + pnfName)
+ .relationshipData(Collections.singletonList(ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("pnf.pnf-name")
+ .relationshipValue(pnfName).build()))
+ .build();
+
+ RelationshipListAaiObject relationshipListAaiObject = ImmutableRelationshipListAaiObject.builder()
+ .relationshipEntries(Collections.singletonList(relationshipEntry))
+ .build();
+
+ MetadataListAaiObject.MetadataEntryAaiObject metadataEntry =
+ ImmutableMetadataEntryAaiObject.builder()
+ .metaname("cvlan")
+ .metavalue(cvlan)
+ .build();
+
+ MetadataListAaiObject metadataListAaiObject = ImmutableMetadataListAaiObject.builder()
+ .metadataEntries(Collections.singletonList(metadataEntry))
+ .build();
+
+ // Finally construct Service Instance object data
+ return ImmutableServiceInstanceAaiObject.builder()
+ .serviceInstanceId(hsiCfsServiceInstanceId)
+ .orchestrationStatus(orchestrationStatus)
+ .relationshipListAaiObject(relationshipListAaiObject)
+ .metadataListAaiObject(metadataListAaiObject)
+ .build();
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/pipelines/SchedulerTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/pipelines/SchedulerTest.java
new file mode 100644
index 00000000..f721ca7e
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/pipelines/SchedulerTest.java
@@ -0,0 +1,189 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.pipelines;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.concurrent.ScheduledFuture;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.config.ConsulConfigurationGateway;
+import org.springframework.scheduling.TaskScheduler;
+
+// We can safely suppress unchecked assignment warnings for the ScheduledFuture mock
+@SuppressWarnings("unchecked")
+@DisplayName("Application Task Scheduler Unit-Tests")
+class SchedulerTest {
+
+ private Scheduler applicationScheduler;
+ private ApplicationConfiguration configuration;
+ private TaskScheduler taskScheduler;
+
+ SchedulerTest() {
+ configuration = Mockito.mock(ApplicationConfiguration.class);
+ taskScheduler = Mockito.mock(TaskScheduler.class);
+ ReRegistrationPipeline reRegistrationPipeline = Mockito.mock(ReRegistrationPipeline.class);
+ CpeAuthenticationPipeline cpeAuthenticationPipeline = Mockito.mock(CpeAuthenticationPipeline.class);
+ ConsulConfigurationGateway configurationGateway = Mockito.mock(ConsulConfigurationGateway.class);
+ this.applicationScheduler = new Scheduler(configuration, configurationGateway, taskScheduler,
+ reRegistrationPipeline, cpeAuthenticationPipeline);
+ }
+
+ @Test
+ void scheduleTasksWithValidSchedulingPeriod_Succeeds() {
+ when(configuration.getPipelinesPollingIntervalInSeconds()).thenReturn(20);
+ ScheduledFuture scheduledFuture = Mockito.mock(ScheduledFuture.class);
+ when(taskScheduler.scheduleAtFixedRate(any(Runnable.class), any(Instant.class), any(Duration.class)))
+ .thenReturn(scheduledFuture);
+
+ applicationScheduler.setupScheduler();
+ assertAll("Scheduler with valid Scheduling period",
+ () -> assertEquals(2, applicationScheduler.numberOfTotalTasks(), "Total tasks"),
+ () -> assertEquals(2, applicationScheduler.numberOfActiveTasks(), "Active tasks"),
+ () -> assertEquals(0, applicationScheduler.numberOfCancelledTasks(), "Cancelled tasks")
+ );
+ }
+
+ @Test
+ void cancellingRunningTasksSucceeds_tasksAreDeleted() {
+ when(configuration.getPipelinesPollingIntervalInSeconds()).thenReturn(20);
+ ScheduledFuture scheduledFuture1 = Mockito.mock(ScheduledFuture.class);
+ ScheduledFuture scheduledFuture2 = Mockito.mock(ScheduledFuture.class);
+ when(scheduledFuture1.cancel(false)).thenReturn(true);
+ when(scheduledFuture2.cancel(false)).thenReturn(true);
+ when(scheduledFuture1.isCancelled()).thenReturn(true);
+ when(scheduledFuture2.isCancelled()).thenReturn(true);
+ when(taskScheduler.scheduleAtFixedRate(any(Runnable.class), any(Instant.class), any(Duration.class)))
+ .thenReturn(scheduledFuture1).thenReturn(scheduledFuture2);
+
+ applicationScheduler.setupScheduler();
+ boolean result = applicationScheduler.cancelScheduledProcessingTasks();
+ assertAll("Successfully cancelling tasks",
+ () -> assertTrue(result, "Result of cancellation task"),
+ () -> assertEquals(0, applicationScheduler.numberOfTotalTasks(), "Total tasks"),
+ () -> assertEquals(0, applicationScheduler.numberOfActiveTasks(), "Active tasks"),
+ () -> assertEquals(0, applicationScheduler.numberOfCancelledTasks(), "Cancelled tasks")
+ );
+ }
+
+ @Test
+ void cancellingRunningTasksPartiallyFailing_tasksAreNotDeleted() {
+ when(configuration.getPipelinesPollingIntervalInSeconds()).thenReturn(20);
+ ScheduledFuture scheduledFuture1 = Mockito.mock(ScheduledFuture.class);
+ ScheduledFuture scheduledFuture2 = Mockito.mock(ScheduledFuture.class);
+ when(scheduledFuture1.cancel(false)).thenReturn(true);
+ when(scheduledFuture2.cancel(false)).thenReturn(false);
+ when(scheduledFuture1.isCancelled()).thenReturn(true);
+ when(scheduledFuture2.isCancelled()).thenReturn(false);
+ when(taskScheduler.scheduleAtFixedRate(any(Runnable.class), any(Instant.class), any(Duration.class)))
+ .thenReturn(scheduledFuture1).thenReturn(scheduledFuture2);
+
+ applicationScheduler.setupScheduler();
+ boolean result = applicationScheduler.cancelScheduledProcessingTasks();
+ assertAll("Partially cancelling tasks",
+ () -> assertFalse(result, "Result of cancellation task"),
+ () -> assertEquals(1, applicationScheduler.numberOfTotalTasks(), "Total tasks"),
+ () -> assertEquals(1, applicationScheduler.numberOfActiveTasks(), "Active tasks"),
+ () -> assertEquals(0, applicationScheduler.numberOfCancelledTasks(), "Cancelled tasks")
+ );
+ }
+
+ @Test
+ void cancellingRunningTasksFailingForAllOfThem_noTasksAreDeleted() {
+ when(configuration.getPipelinesPollingIntervalInSeconds()).thenReturn(20);
+ ScheduledFuture scheduledFuture1 = Mockito.mock(ScheduledFuture.class);
+ ScheduledFuture scheduledFuture2 = Mockito.mock(ScheduledFuture.class);
+ when(scheduledFuture1.cancel(false)).thenReturn(false);
+ when(scheduledFuture2.cancel(false)).thenReturn(false);
+ when(scheduledFuture1.isCancelled()).thenReturn(false);
+ when(scheduledFuture2.isCancelled()).thenReturn(false);
+ when(taskScheduler.scheduleAtFixedRate(any(Runnable.class), any(Instant.class), any(Duration.class)))
+ .thenReturn(scheduledFuture1).thenReturn(scheduledFuture2);
+
+ applicationScheduler.setupScheduler();
+ boolean result = applicationScheduler.cancelScheduledProcessingTasks();
+ assertAll("Failing in cancelling tasks",
+ () -> assertFalse(result, "Result of cancellation task"),
+ () -> assertEquals(2, applicationScheduler.numberOfTotalTasks(), "Total tasks"),
+ () -> assertEquals(2, applicationScheduler.numberOfActiveTasks(), "Active tasks"),
+ () -> assertEquals(0, applicationScheduler.numberOfCancelledTasks(), "Cancelled tasks")
+ );
+ }
+
+ @Test
+ void reSchedulingWithExistingActiveTasks_Fails() {
+ when(configuration.getPipelinesPollingIntervalInSeconds()).thenReturn(20);
+ ScheduledFuture scheduledFuture1 = Mockito.mock(ScheduledFuture.class);
+ ScheduledFuture scheduledFuture2 = Mockito.mock(ScheduledFuture.class);
+ when(scheduledFuture1.isCancelled()).thenReturn(false);
+ when(scheduledFuture2.isCancelled()).thenReturn(false);
+ when(taskScheduler.scheduleAtFixedRate(any(Runnable.class), any(Instant.class), any(Duration.class)))
+ .thenReturn(scheduledFuture1).thenReturn(scheduledFuture2);
+
+ applicationScheduler.setupScheduler();
+ boolean result = applicationScheduler.reScheduleProcessingTasks();
+ assertAll("Rescheduling with active tasks",
+ () -> assertFalse(result, "Result of re-scheduling"),
+ () -> assertEquals(2, applicationScheduler.numberOfTotalTasks(), "Total tasks"),
+ () -> assertEquals(2, applicationScheduler.numberOfActiveTasks(), "Active tasks"),
+ () -> assertEquals(0, applicationScheduler.numberOfCancelledTasks(), "Cancelled tasks")
+ );
+ }
+
+ @Test
+ void reSchedulingWithExistingCancelledTasks_Succeeds() {
+ when(configuration.getPipelinesPollingIntervalInSeconds()).thenReturn(20);
+ // Initial tasks
+ ScheduledFuture scheduledFuture1 = Mockito.mock(ScheduledFuture.class);
+ ScheduledFuture scheduledFuture2 = Mockito.mock(ScheduledFuture.class);
+ // Re-scheduled tasks
+ ScheduledFuture scheduledFuture3 = Mockito.mock(ScheduledFuture.class);
+ ScheduledFuture scheduledFuture4 = Mockito.mock(ScheduledFuture.class);
+ when(scheduledFuture1.isCancelled()).thenReturn(true);
+ when(scheduledFuture2.isCancelled()).thenReturn(true);
+ when(scheduledFuture3.isCancelled()).thenReturn(false);
+ when(scheduledFuture4.isCancelled()).thenReturn(false);
+ when(taskScheduler.scheduleAtFixedRate(any(Runnable.class), any(Instant.class), any(Duration.class)))
+ .thenReturn(scheduledFuture1)
+ .thenReturn(scheduledFuture2)
+ .thenReturn(scheduledFuture3)
+ .thenReturn(scheduledFuture4);
+
+ applicationScheduler.setupScheduler();
+ boolean result = applicationScheduler.reScheduleProcessingTasks();
+ assertAll("Rescheduling with cancelled tasks",
+ () -> assertTrue(result, "Result of re-scheduling"),
+ () -> assertEquals(2, applicationScheduler.numberOfTotalTasks(), "Total tasks"),
+ () -> assertEquals(2, applicationScheduler.numberOfActiveTasks(), "Active tasks"),
+ () -> assertEquals(0, applicationScheduler.numberOfCancelledTasks(), "Cancelled tasks")
+ );
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/AaiClientTaskImplTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/AaiClientTaskImplTest.java
new file mode 100644
index 00000000..db5f7cb1
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/AaiClientTaskImplTest.java
@@ -0,0 +1,239 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.tasks;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.TypeAdapterFactory;
+
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.ServiceLoader;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.onap.bbs.event.processor.exceptions.AaiTaskException;
+import org.onap.bbs.event.processor.model.ImmutableMetadataEntryAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableMetadataListAaiObject;
+import org.onap.bbs.event.processor.model.ImmutablePnfAaiObject;
+import org.onap.bbs.event.processor.model.ImmutablePropertyAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableRelationshipDataEntryAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableRelationshipEntryAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableRelationshipListAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableServiceInstanceAaiObject;
+import org.onap.bbs.event.processor.model.MetadataListAaiObject;
+import org.onap.bbs.event.processor.model.PnfAaiObject;
+import org.onap.bbs.event.processor.model.RelationshipListAaiObject;
+import org.onap.bbs.event.processor.model.ServiceInstanceAaiObject;
+import org.onap.bbs.event.processor.utilities.AaiReactiveClient;
+
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+class AaiClientTaskImplTest {
+
+ private AaiReactiveClient reactiveClient;
+
+ private AaiClientTask task;
+
+ @BeforeEach
+ void init() {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory);
+ reactiveClient = Mockito.mock(AaiReactiveClient.class);
+ task = new AaiClientTaskImpl(reactiveClient);
+ }
+
+ @Test
+ void passingEmptyPnfObject_NothingHappens() throws AaiTaskException {
+ when(reactiveClient.getPnfObjectDataFor(any(String.class))).thenReturn(Mono.empty());
+ Mono<PnfAaiObject> pnf = task.executePnfRetrieval("Empty PNF task", "some-url");
+
+ verify(reactiveClient).getPnfObjectDataFor("some-url");
+ assertNull(pnf.block(Duration.ofSeconds(5)));
+ }
+
+ @Test
+ void passingEmptyServiceInstanceObject_NothingHappens() throws AaiTaskException {
+ when(reactiveClient.getServiceInstanceObjectDataFor(any(String.class))).thenReturn(Mono.empty());
+ Mono<ServiceInstanceAaiObject> serviceInstance =
+ task.executeServiceInstanceRetrieval("Empty Service Instance task", "some-url");
+
+ verify(reactiveClient).getServiceInstanceObjectDataFor("some-url");
+ assertNull(serviceInstance.block(Duration.ofSeconds(5)));
+ }
+
+ @Test
+ void passingPnfObject_taskSucceeds() throws AaiTaskException {
+
+ String pnfName = "pnf-1";
+ String attachmentPoint = "olt1-1-1";
+
+ // Build Relationship Data
+ RelationshipListAaiObject.RelationshipEntryAaiObject firstRelationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("service-instance")
+ .relatedLink("/aai/v14/business/customers/customer/Demonstration/service-subscriptions"
+ + "/service-subscription/BBS/service-instances"
+ + "/service-instance/84003b26-6b76-4c75-b805-7b14ab4ffaef")
+ .relationshipLabel("org.onap.relationships.inventory.ComposedOf")
+ .relationshipData(Arrays.asList(
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("customer.global-customer-id")
+ .relationshipValue("Demonstration").build(),
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-subscription.service-type")
+ .relationshipValue("BBS").build(),
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-instance.service-instance-id")
+ .relationshipValue("84003b26-6b76-4c75-b805-7b14ab4ffaef").build())
+ )
+ .relatedToProperties(Collections.singletonList(
+ ImmutablePropertyAaiObject.builder()
+ .propertyKey("service-instance.service-instance-name")
+ .propertyValue("bbs-instance").build())
+ )
+ .build();
+
+ RelationshipListAaiObject.RelationshipEntryAaiObject secondRelationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("logical-link")
+ .relatedLink("/network/logical-links/logical-link/" + attachmentPoint)
+ .relationshipData(Collections.singletonList(ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("logical-link.link-name")
+ .relationshipValue(attachmentPoint).build()))
+ .build();
+
+ RelationshipListAaiObject relationshipListAaiObject = ImmutableRelationshipListAaiObject.builder()
+ .relationshipEntries(Arrays.asList(firstRelationshipEntry, secondRelationshipEntry))
+ .build();
+
+ // Finally construct PNF object data
+ PnfAaiObject pnfAaiObject = ImmutablePnfAaiObject.builder()
+ .pnfName(pnfName)
+ .isInMaintenance(true)
+ .relationshipListAaiObject(relationshipListAaiObject)
+ .build();
+
+ when(reactiveClient.getPnfObjectDataFor(any(String.class))).thenReturn(Mono.just(pnfAaiObject));
+ Mono<PnfAaiObject> pnf = task.executePnfRetrieval("Normal PNF retrieval task", "some-url");
+
+ verify(reactiveClient).getPnfObjectDataFor("some-url");
+ assertNotNull(pnf.block(Duration.ofSeconds(5)));
+
+ StepVerifier.create(pnf)
+ .expectSubscription()
+ .consumeNextWith(aPnf -> {
+ Assertions.assertEquals(pnfName, aPnf.getPnfName(), "PNF Name in response does not match");
+ String extractedAttachmentPoint = aPnf.getRelationshipListAaiObject().getRelationshipEntries()
+ .stream()
+ .filter(e -> e.getRelatedTo().equals("logical-link"))
+ .flatMap(e -> e.getRelationshipData().stream())
+ .filter(d -> d.getRelationshipKey().equals("logical-link.link-name"))
+ .map(RelationshipListAaiObject.RelationshipDataEntryAaiObject::getRelationshipValue)
+ .findFirst().orElseThrow(AaiClientTaskTestException::new);
+ Assertions.assertEquals(attachmentPoint, extractedAttachmentPoint,
+ "Attachment point in response does not match");
+ })
+ .verifyComplete();
+ }
+
+ @Test
+ void passingServiceInstanceObject_taskSucceeds() throws AaiTaskException {
+
+ String serviceInstanceId = "84003b26-6b76-4c75-b805-7b14ab4ffaef";
+ String orchestrationStatus = "active";
+
+ // Build Relationship Data
+ RelationshipListAaiObject.RelationshipEntryAaiObject relationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("service-instance")
+ .relatedLink("/aai/v14/business/customers/customer/Demonstration/service-subscriptions"
+ + "/service-subscription/BBS-CFS/service-instances"
+ + "/service-instance/bb374844-44e4-488f-8381-fb5a0e3e6989")
+ .relationshipLabel("org.onap.relationships.inventory.ComposedOf")
+ .relationshipData(Collections.singletonList(ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-instance.service-instance-id")
+ .relationshipValue("bb374844-44e4-488f-8381-fb5a0e3e6989").build()))
+ .build();
+
+ RelationshipListAaiObject relationshipListAaiObject = ImmutableRelationshipListAaiObject.builder()
+ .relationshipEntries(Collections.singletonList(relationshipEntry))
+ .build();
+
+ MetadataListAaiObject.MetadataEntryAaiObject metadataEntry =
+ ImmutableMetadataEntryAaiObject.builder()
+ .metaname("cvlan")
+ .metavalue("1005")
+ .build();
+
+ MetadataListAaiObject metadataListAaiObject = ImmutableMetadataListAaiObject.builder()
+ .metadataEntries(Collections.singletonList(metadataEntry))
+ .build();
+
+ // Finally construct Service Instance object data
+ ServiceInstanceAaiObject serviceInstanceAaiObject = ImmutableServiceInstanceAaiObject.builder()
+ .serviceInstanceId(serviceInstanceId)
+ .orchestrationStatus(orchestrationStatus)
+ .relationshipListAaiObject(relationshipListAaiObject)
+ .metadataListAaiObject(metadataListAaiObject)
+ .build();
+
+ when(reactiveClient.getServiceInstanceObjectDataFor(any(String.class)))
+ .thenReturn(Mono.just(serviceInstanceAaiObject));
+ Mono<ServiceInstanceAaiObject> serviceInstance =
+ task.executeServiceInstanceRetrieval("Normal Service Instance retrieval task",
+ "some-url");
+
+ verify(reactiveClient).getServiceInstanceObjectDataFor("some-url");
+ assertNotNull(serviceInstance.block(Duration.ofSeconds(5)));
+
+ StepVerifier.create(serviceInstance)
+ .expectSubscription()
+ .consumeNextWith(instance -> {
+ Assertions.assertEquals(serviceInstanceId, instance.getServiceInstanceId(),
+ "Service Instance ID in response does not match");
+
+ MetadataListAaiObject extractedMetadataListObject =
+ instance.getMetadataListAaiObject().orElseThrow(AaiClientTaskTestException::new);
+
+ MetadataListAaiObject.MetadataEntryAaiObject extractedMetadataEntry =
+ extractedMetadataListObject.getMetadataEntries()
+ .stream()
+ .filter(m -> m.getMetaname().equals("cvlan"))
+ .findFirst().orElseThrow(AaiClientTaskTestException::new);
+
+ Assertions.assertEquals("1005", extractedMetadataEntry.getMetavalue(),
+ "CVLAN in response does not match");
+ })
+ .verifyComplete();
+ }
+
+ private static class AaiClientTaskTestException extends RuntimeException {}
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/DmaapCpeAuthenticationConsumerTaskImplTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/DmaapCpeAuthenticationConsumerTaskImplTest.java
new file mode 100644
index 00000000..538ff1de
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/DmaapCpeAuthenticationConsumerTaskImplTest.java
@@ -0,0 +1,149 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.tasks;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import javax.net.ssl.SSLException;
+
+import org.junit.Assert;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.exceptions.EmptyDmaapResponseException;
+import org.onap.bbs.event.processor.model.CpeAuthenticationConsumerDmaapModel;
+import org.onap.bbs.event.processor.model.ImmutableCpeAuthenticationConsumerDmaapModel;
+import org.onap.bbs.event.processor.utilities.CpeAuthenticationDmaapConsumerJsonParser;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapConsumerConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapConsumerConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.ConsumerReactiveHttpClientFactory;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.DMaaPConsumerReactiveHttpClient;
+
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+class DmaapCpeAuthenticationConsumerTaskImplTest {
+
+ private static final String CPE_AUTHENTICATION_EVENT_TEMPLATE = "{\"event\": {"
+ + "\"commonEventHeader\": { \"sourceName\":\"%s\"},"
+ + "\"stateChangeFields\": {"
+ + " \"oldState\": \"%s\","
+ + " \"newState\": \"%s\","
+ + " \"stateInterface\": \"%s\","
+ + " \"additionalFields\": {"
+ + " \"macAddress\": \"%s\","
+ + " \"swVersion\": \"%s\""
+ + "}}}}";
+
+ private static DmaapCpeAuthenticationConsumerTask dmaapConsumerTask;
+ private static CpeAuthenticationConsumerDmaapModel cpeAuthenticationConsumerDmaapModel;
+ private static DMaaPConsumerReactiveHttpClient dMaaPConsumerReactiveHttpClient;
+ private static String eventsArray;
+
+ @BeforeAll
+ static void setUp() throws SSLException {
+
+ final String sourceName = "PNF-CorrelationId";
+ final String oldAuthenticationState = "outOfService";
+ final String newAuthenticationState = "inService";
+ final String stateInterface = "stateInterface";
+ final String rgwMacAddress = "00:0a:95:8d:78:16";
+ final String swVersion = "1.2";
+
+ // Mock Re-registration configuration
+ DmaapConsumerConfiguration dmaapConsumerConfiguration = testVersionOfDmaapConsumerConfiguration();
+ ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
+ when(configuration.getDmaapCpeAuthenticationConsumerConfiguration()).thenReturn(dmaapConsumerConfiguration);
+
+ // Mock reactive DMaaP client
+ ConsumerReactiveHttpClientFactory httpClientFactory = mock(ConsumerReactiveHttpClientFactory.class);
+ dMaaPConsumerReactiveHttpClient = mock(DMaaPConsumerReactiveHttpClient.class);
+ doReturn(dMaaPConsumerReactiveHttpClient).when(httpClientFactory).create(dmaapConsumerConfiguration);
+
+ dmaapConsumerTask = new DmaapCpeAuthenticationConsumerTaskImpl(configuration,
+ new CpeAuthenticationDmaapConsumerJsonParser(), httpClientFactory);
+
+ cpeAuthenticationConsumerDmaapModel = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(sourceName)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress)
+ .swVersion(swVersion)
+ .build();
+
+ String event = String.format(CPE_AUTHENTICATION_EVENT_TEMPLATE, sourceName, oldAuthenticationState,
+ newAuthenticationState, stateInterface, rgwMacAddress, swVersion);
+
+ eventsArray = "[" + event + "]";
+ }
+
+ @AfterEach
+ void resetMock() {
+ reset(dMaaPConsumerReactiveHttpClient);
+ }
+
+ @Test
+ void passingEmptyMessage_NothingHappens() throws Exception {
+ when(dMaaPConsumerReactiveHttpClient.getDMaaPConsumerResponse()).thenReturn(Mono.just(""));
+
+ StepVerifier.create(dmaapConsumerTask.execute("Sample input"))
+ .expectSubscription()
+ .expectError(EmptyDmaapResponseException.class);
+ verify(dMaaPConsumerReactiveHttpClient).getDMaaPConsumerResponse();
+ }
+
+ @Test
+ void passingNormalMessage_ResponseSucceeds() throws Exception {
+ when(dMaaPConsumerReactiveHttpClient.getDMaaPConsumerResponse()).thenReturn(Mono.just(eventsArray));
+
+ StepVerifier.create(dmaapConsumerTask.execute("Sample input"))
+ .expectSubscription()
+ .consumeNextWith(e -> Assert.assertEquals(e, cpeAuthenticationConsumerDmaapModel));
+ verify(dMaaPConsumerReactiveHttpClient).getDMaaPConsumerResponse();
+ }
+
+ private static DmaapConsumerConfiguration testVersionOfDmaapConsumerConfiguration() {
+ return new ImmutableDmaapConsumerConfiguration.Builder()
+ .consumerGroup("consumer-group")
+ .consumerId("consumer-id")
+ .dmaapContentType("application/json")
+ .dmaapHostName("message-router.onap.svc.cluster.local")
+ .dmaapPortNumber(3904)
+ .dmaapProtocol("http")
+ .dmaapUserName("admin")
+ .dmaapUserPassword("admin")
+ .trustStorePath("change it")
+ .trustStorePasswordPath("change_it")
+ .keyStorePath("change it")
+ .keyStorePasswordPath("change_it")
+ .enableDmaapCertAuth(false)
+ .dmaapTopicName("/events/unauthenticated.CPE_AUTHENTICATION")
+ .timeoutMs(-1)
+ .messageLimit(-1)
+ .build();
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/DmaapPublisherTaskImplTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/DmaapPublisherTaskImplTest.java
new file mode 100644
index 00000000..199a43ec
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/DmaapPublisherTaskImplTest.java
@@ -0,0 +1,173 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.tasks;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.function.Executable;
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.exceptions.DmaapException;
+import org.onap.bbs.event.processor.model.ControlLoopPublisherDmaapModel;
+import org.onap.bbs.event.processor.model.ImmutableControlLoopPublisherDmaapModel;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapPublisherConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapPublisherConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.producer.DMaaPPublisherReactiveHttpClient;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.producer.PublisherReactiveHttpClientFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+class DmaapPublisherTaskImplTest {
+
+ private static ControlLoopPublisherDmaapModel controlLoopPublisherDmaapModel;
+ private static DmaapPublisherTaskImpl task;
+ private static DMaaPPublisherReactiveHttpClient reactiveHttpClient;
+ private static ApplicationConfiguration configuration;
+ private static DmaapPublisherConfiguration dmaapPublisherConfiguration;
+
+ @BeforeAll
+ static void setUp() {
+ dmaapPublisherConfiguration = testVersionOfDmaapPublisherConfiguration();
+ configuration = mock(ApplicationConfiguration.class);
+
+ final String closedLoopEventClient = "DCAE.BBS_mSInstance";
+ final String policyVersion = "1.0.0.5";
+ final String policyName = "CPE_Authentication";
+ final String policyScope =
+ "service=HSIAService,type=SampleType,"
+ + "closedLoopControlName=CL-CPE_A-d925ed73-8231-4d02-9545-db4e101f88f8";
+ final String targetType = "VM";
+ final long closedLoopAlarmStart = 1484677482204798L;
+ final String closedLoopEventStatus = "ONSET";
+ final String closedLoopControlName = "ControlLoop-CPE_A-2179b738-fd36-4843-a71a-a8c24c70c88b";
+ final String version = "1.0.2";
+ final String target = "vserver.vserver-name";
+ final String requestId = "97964e10-686e-4790-8c45-bdfa61df770f";
+ final String from = "DCAE";
+
+ final Map<String, String> aaiEnrichmentData = new LinkedHashMap<>();
+ aaiEnrichmentData.put("service-information.service-instance-id", "service-instance-id-example");
+ aaiEnrichmentData.put("cvlan-id", "example cvlan-id");
+ aaiEnrichmentData.put("svlan-id", "example svlan-id");
+
+ controlLoopPublisherDmaapModel = ImmutableControlLoopPublisherDmaapModel.builder()
+ .closedLoopEventClient(closedLoopEventClient)
+ .policyVersion(policyVersion)
+ .policyName(policyName)
+ .policyScope(policyScope)
+ .targetType(targetType)
+ .aaiEnrichmentData(aaiEnrichmentData)
+ .closedLoopAlarmStart(closedLoopAlarmStart)
+ .closedLoopEventStatus(closedLoopEventStatus)
+ .closedLoopControlName(closedLoopControlName)
+ .version(version)
+ .target(target)
+ .requestId(requestId)
+ .originator(from)
+ .build();
+
+ when(configuration.getDmaapPublisherConfiguration()).thenReturn(dmaapPublisherConfiguration);
+ }
+
+ @Test
+ void passingNullMessage_ExceptionIsRaised() {
+
+ task = new DmaapPublisherTaskImpl(configuration);
+
+ Executable executableFunction = () -> task.execute(null);
+
+ Assertions.assertThrows(DmaapException.class, executableFunction, "Input message is invalid");
+ }
+
+ @Test
+ void passingNormalMessage_ReactiveClientProcessesIt() throws DmaapException {
+ ResponseEntity<String> responseEntity = setupMocks(HttpStatus.OK.value());
+ when(responseEntity.getStatusCode()).thenReturn(HttpStatus.OK);
+ StepVerifier.create(task.execute(controlLoopPublisherDmaapModel)).expectSubscription()
+ .expectNext(responseEntity).verifyComplete();
+
+ verify(reactiveHttpClient, times(1))
+ .getDMaaPProducerResponse(controlLoopPublisherDmaapModel);
+ verifyNoMoreInteractions(reactiveHttpClient);
+ }
+
+ @Test
+ void passingNormalMessage_IncorrectResponseIsHandled() throws DmaapException {
+ ResponseEntity<String> responseEntity = setupMocks(HttpStatus.UNAUTHORIZED.value());
+ when(responseEntity.getStatusCode()).thenReturn(HttpStatus.UNAUTHORIZED);
+ StepVerifier.create(task.execute(controlLoopPublisherDmaapModel)).expectSubscription()
+ .expectNext(responseEntity).verifyComplete();
+
+ verify(reactiveHttpClient, times(1))
+ .getDMaaPProducerResponse(controlLoopPublisherDmaapModel);
+ verifyNoMoreInteractions(reactiveHttpClient);
+ }
+
+ // We can safely suppress unchecked assignment warning here since it is a mock class
+ @SuppressWarnings("unchecked")
+ private ResponseEntity<String> setupMocks(Integer httpResponseCode) {
+
+ ResponseEntity<String> responseEntity = mock(ResponseEntity.class);
+ when(responseEntity.getStatusCode()).thenReturn(HttpStatus.valueOf(httpResponseCode));
+
+ reactiveHttpClient = mock(DMaaPPublisherReactiveHttpClient.class);
+ when(reactiveHttpClient.getDMaaPProducerResponse(any()))
+ .thenReturn(Mono.just(responseEntity));
+
+ PublisherReactiveHttpClientFactory httpClientFactory = mock(PublisherReactiveHttpClientFactory.class);
+ doReturn(reactiveHttpClient).when(httpClientFactory).create(dmaapPublisherConfiguration);
+
+ task = new DmaapPublisherTaskImpl(configuration, httpClientFactory);
+
+ return responseEntity;
+ }
+
+ private static DmaapPublisherConfiguration testVersionOfDmaapPublisherConfiguration() {
+ return new ImmutableDmaapPublisherConfiguration.Builder()
+ .dmaapContentType("application/json")
+ .dmaapHostName("message-router.onap.svc.cluster.local")
+ .dmaapPortNumber(3904)
+ .dmaapProtocol("http")
+ .dmaapUserName("admin")
+ .dmaapUserPassword("admin")
+ .trustStorePath("/opt/app/bbs/local/org.onap.bbs.trust.jks")
+ .trustStorePasswordPath("change_it")
+ .keyStorePath("/opt/app/bbs/local/org.onap.bbs.p12")
+ .keyStorePasswordPath("change_it")
+ .enableDmaapCertAuth(false)
+ .dmaapTopicName("/events/unauthenticated.DCAE_CL_OUTPUT")
+ .build();
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/DmaapReRegistrationConsumerTaskImplTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/DmaapReRegistrationConsumerTaskImplTest.java
new file mode 100644
index 00000000..c9a461d8
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/tasks/DmaapReRegistrationConsumerTaskImplTest.java
@@ -0,0 +1,147 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.tasks;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import javax.net.ssl.SSLException;
+
+import org.junit.Assert;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.exceptions.EmptyDmaapResponseException;
+import org.onap.bbs.event.processor.model.ImmutableReRegistrationConsumerDmaapModel;
+import org.onap.bbs.event.processor.model.ReRegistrationConsumerDmaapModel;
+import org.onap.bbs.event.processor.utilities.ReRegistrationDmaapConsumerJsonParser;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapConsumerConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapConsumerConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.ConsumerReactiveHttpClientFactory;
+import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.DMaaPConsumerReactiveHttpClient;
+
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+class DmaapReRegistrationConsumerTaskImplTest {
+
+ private static final String RE_REGISTRATION_EVENT_TEMPLATE = "{\"event\": {"
+ + "\"commonEventHeader\": { \"sourceName\":\"%s\"},"
+ + "\"additionalFields\": {"
+ + " \"attachment-point\": \"%s\","
+ + " \"remote-id\": \"%s\","
+ + " \"cvlan\": \"%s\","
+ + " \"svlan\": \"%s\""
+ + "}}}";
+
+ private static DmaapReRegistrationConsumerTaskImpl dmaapConsumerTask;
+ private static ReRegistrationConsumerDmaapModel reRegistrationConsumerDmaapModel;
+ private static DMaaPConsumerReactiveHttpClient dMaaPConsumerReactiveHttpClient;
+ private static String message;
+
+ @BeforeAll
+ static void setUp() throws SSLException {
+
+ final String sourceName = "PNF-CorrelationId";
+ final String attachmentPoint = "olt2/2/2";
+ final String remoteId = "remoteId";
+ final String cvlan = "1005";
+ final String svlan = "100";
+
+ // Mock Re-registration configuration
+ DmaapConsumerConfiguration dmaapConsumerConfiguration = testVersionOfDmaapConsumerConfiguration();
+ ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
+ when(configuration.getDmaapReRegistrationConsumerConfiguration()).thenReturn(dmaapConsumerConfiguration);
+
+ // Mock reactive DMaaP client
+ ConsumerReactiveHttpClientFactory httpClientFactory = mock(ConsumerReactiveHttpClientFactory.class);
+ dMaaPConsumerReactiveHttpClient = mock(DMaaPConsumerReactiveHttpClient.class);
+ doReturn(dMaaPConsumerReactiveHttpClient).when(httpClientFactory).create(dmaapConsumerConfiguration);
+
+ dmaapConsumerTask = new DmaapReRegistrationConsumerTaskImpl(configuration,
+ new ReRegistrationDmaapConsumerJsonParser(), httpClientFactory);
+
+ reRegistrationConsumerDmaapModel = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(sourceName)
+ .attachmentPoint(attachmentPoint)
+ .remoteId(remoteId)
+ .cVlan(cvlan)
+ .sVlan(svlan)
+ .build();
+
+ message = String.format("[" + RE_REGISTRATION_EVENT_TEMPLATE + "]",
+ sourceName,
+ attachmentPoint,
+ remoteId,
+ cvlan,
+ svlan);
+ }
+
+ @AfterEach
+ void resetMock() {
+ reset(dMaaPConsumerReactiveHttpClient);
+ }
+
+ @Test
+ void passingEmptyMessage_NothingHappens() throws Exception {
+ when(dMaaPConsumerReactiveHttpClient.getDMaaPConsumerResponse()).thenReturn(Mono.just(""));
+
+ StepVerifier.create(dmaapConsumerTask.execute("Sample input"))
+ .expectSubscription()
+ .expectError(EmptyDmaapResponseException.class);
+ verify(dMaaPConsumerReactiveHttpClient).getDMaaPConsumerResponse();
+ }
+
+ @Test
+ void passingNormalMessage_ResponseSucceeds() throws Exception {
+ when(dMaaPConsumerReactiveHttpClient.getDMaaPConsumerResponse()).thenReturn(Mono.just(message));
+
+ StepVerifier.create(dmaapConsumerTask.execute("Sample input"))
+ .expectSubscription()
+ .consumeNextWith(e -> Assert.assertEquals(e, reRegistrationConsumerDmaapModel));
+ verify(dMaaPConsumerReactiveHttpClient).getDMaaPConsumerResponse();
+ }
+
+ private static DmaapConsumerConfiguration testVersionOfDmaapConsumerConfiguration() {
+ return new ImmutableDmaapConsumerConfiguration.Builder()
+ .consumerGroup("OpenDCAE-c12")
+ .consumerId("c12")
+ .dmaapContentType("application/json")
+ .dmaapHostName("message-router.onap.svc.cluster.local")
+ .dmaapPortNumber(3904)
+ .dmaapProtocol("http")
+ .dmaapUserName("admin")
+ .dmaapUserPassword("admin")
+ .trustStorePath("/opt/app/bbs/local/org.onap.bbs.trust.jks")
+ .trustStorePasswordPath("change_it")
+ .keyStorePath("/opt/app/bbs/local/org.onap.bbs.p12")
+ .keyStorePasswordPath("change_it")
+ .enableDmaapCertAuth(false)
+ .dmaapTopicName("/events/unauthenticated.PNF_REREGISTRATION")
+ .timeoutMs(-1)
+ .messageLimit(-1)
+ .build();
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/utilities/AaiReactiveClientTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/utilities/AaiReactiveClientTest.java
new file mode 100644
index 00000000..8e3c46ba
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/utilities/AaiReactiveClientTest.java
@@ -0,0 +1,257 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.utilities;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.givenThat;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static org.mockito.Mockito.when;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.TypeAdapterFactory;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.ServiceLoader;
+
+import javax.net.ssl.SSLException;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mockito;
+import org.onap.bbs.event.processor.config.AaiClientConfiguration;
+import org.onap.bbs.event.processor.config.ApplicationConfiguration;
+import org.onap.bbs.event.processor.model.ImmutableMetadataEntryAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableMetadataListAaiObject;
+import org.onap.bbs.event.processor.model.ImmutablePnfAaiObject;
+import org.onap.bbs.event.processor.model.ImmutablePropertyAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableRelationshipDataEntryAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableRelationshipEntryAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableRelationshipListAaiObject;
+import org.onap.bbs.event.processor.model.ImmutableServiceInstanceAaiObject;
+import org.onap.bbs.event.processor.model.MetadataListAaiObject;
+import org.onap.bbs.event.processor.model.PnfAaiObject;
+import org.onap.bbs.event.processor.model.RelationshipListAaiObject;
+import org.onap.bbs.event.processor.model.ServiceInstanceAaiObject;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import reactor.test.StepVerifier;
+
+@ExtendWith(SpringExtension.class)
+class AaiReactiveClientTest {
+
+ private static final int PORT = 9999;
+
+ private static AaiReactiveClient reactiveClient;
+ private static Gson gson;
+ private static WireMockServer wireMockServer;
+
+ @BeforeAll
+ static void init() throws SSLException {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory);
+ gson = gsonBuilder.create();
+
+ ApplicationConfiguration configuration = Mockito.mock(ApplicationConfiguration.class);
+ AaiClientConfiguration aaiClientConfiguration = Mockito.mock(AaiClientConfiguration.class);
+ when(configuration.getAaiClientConfiguration()).thenReturn(aaiClientConfiguration);
+ when(aaiClientConfiguration.aaiUserName()).thenReturn("AAI");
+ when(aaiClientConfiguration.aaiUserPassword()).thenReturn("AAI");
+ when(aaiClientConfiguration.aaiHeaders()).thenReturn(new HashMap<>());
+ when(aaiClientConfiguration.enableAaiCertAuth()).thenReturn(false);
+
+ reactiveClient = new AaiReactiveClient(configuration, gson);
+
+ wireMockServer = new WireMockServer(PORT);
+ WireMock.configureFor("localhost", PORT);
+ }
+
+ @BeforeEach
+ void wireMockSetup() {
+ wireMockServer.start();
+ }
+
+ @AfterEach
+ void wireMockTearDown() {
+ wireMockServer.start();
+ }
+
+ @Test
+ void sendingReactiveRequestForPnf_Succeeds() {
+
+ String pnfName = "pnf-1";
+ String attachmentPoint = "olt1-1-1";
+
+ String pnfUrl = String.format("/aai/v14/network/pnfs/pnf/%s?depth=1", pnfName);
+
+ // Build Relationship Data
+ RelationshipListAaiObject.RelationshipEntryAaiObject firstRelationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("service-instance")
+ .relatedLink("/aai/v14/business/customers/customer/Demonstration/service-subscriptions"
+ + "/service-subscription/BBS/service-instances"
+ + "/service-instance/84003b26-6b76-4c75-b805-7b14ab4ffaef")
+ .relationshipLabel("org.onap.relationships.inventory.ComposedOf")
+ .relationshipData(Arrays.asList(
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("customer.global-customer-id")
+ .relationshipValue("Demonstration").build(),
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-subscription.service-type")
+ .relationshipValue("BBS").build(),
+ ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-instance.service-instance-id")
+ .relationshipValue("84003b26-6b76-4c75-b805-7b14ab4ffaef").build())
+ )
+ .relatedToProperties(Collections.singletonList(
+ ImmutablePropertyAaiObject.builder()
+ .propertyKey("service-instance.service-instance-name")
+ .propertyValue("bbs-instance").build())
+ )
+ .build();
+
+ RelationshipListAaiObject.RelationshipEntryAaiObject secondRelationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("logical-link")
+ .relatedLink("/network/logical-links/logical-link/" + attachmentPoint)
+ .relationshipData(Collections.singletonList(ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("logical-link.link-name")
+ .relationshipValue(attachmentPoint).build()))
+ .build();
+
+ RelationshipListAaiObject relationshipListAaiObject = ImmutableRelationshipListAaiObject.builder()
+ .relationshipEntries(Arrays.asList(firstRelationshipEntry, secondRelationshipEntry))
+ .build();
+
+ // Finally construct PNF object data
+ PnfAaiObject pnfAaiObject = ImmutablePnfAaiObject.builder()
+ .pnfName(pnfName)
+ .isInMaintenance(true)
+ .relationshipListAaiObject(relationshipListAaiObject)
+ .build();
+
+ givenThat(get(urlEqualTo(pnfUrl))
+ .willReturn(aResponse().withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(gson.toJson(pnfAaiObject, ImmutablePnfAaiObject.class))));
+
+ StepVerifier.create(reactiveClient.getPnfObjectDataFor("http://127.0.0.1:" + PORT + pnfUrl))
+ .expectSubscription()
+ .consumeNextWith(pnf -> {
+ Assertions.assertEquals(pnfName, pnf.getPnfName(), "PNF Name in response does not match");
+ String extractedAttachmentPoint = pnf.getRelationshipListAaiObject().getRelationshipEntries()
+ .stream()
+ .filter(e -> e.getRelatedTo().equals("logical-link"))
+ .flatMap(e -> e.getRelationshipData().stream())
+ .filter(d -> d.getRelationshipKey().equals("logical-link.link-name"))
+ .map(RelationshipListAaiObject.RelationshipDataEntryAaiObject::getRelationshipValue)
+ .findFirst().orElseThrow(AaiReactiveClientTestException::new);
+ Assertions.assertEquals(attachmentPoint, extractedAttachmentPoint,
+ "Attachment point in response does not match");
+ })
+ .verifyComplete();
+ }
+
+ @Test
+ void sendingReactiveRequestForServiceInstance_Succeeds() {
+
+ String serviceInstanceId = "84003b26-6b76-4c75-b805-7b14ab4ffaef";
+ String orchestrationStatus = "active";
+
+ String serviceInstanceUrl =
+ String.format("/aai/v14/nodes/service-instances/service-instance/%s?format=resource_and_url",
+ serviceInstanceId);
+
+ // Build Relationship Data
+ RelationshipListAaiObject.RelationshipEntryAaiObject relationshipEntry =
+ ImmutableRelationshipEntryAaiObject.builder()
+ .relatedTo("service-instance")
+ .relatedLink("/aai/v14/business/customers/customer/Demonstration/service-subscriptions"
+ + "/service-subscription/BBS-CFS/service-instances"
+ + "/service-instance/bb374844-44e4-488f-8381-fb5a0e3e6989")
+ .relationshipLabel("org.onap.relationships.inventory.ComposedOf")
+ .relationshipData(Collections.singletonList(ImmutableRelationshipDataEntryAaiObject.builder()
+ .relationshipKey("service-instance.service-instance-id")
+ .relationshipValue("bb374844-44e4-488f-8381-fb5a0e3e6989").build()))
+ .build();
+
+ RelationshipListAaiObject relationshipListAaiObject = ImmutableRelationshipListAaiObject.builder()
+ .relationshipEntries(Collections.singletonList(relationshipEntry))
+ .build();
+
+ MetadataListAaiObject.MetadataEntryAaiObject metadataEntry =
+ ImmutableMetadataEntryAaiObject.builder()
+ .metaname("cvlan")
+ .metavalue("1005")
+ .build();
+
+ MetadataListAaiObject metadataListAaiObject = ImmutableMetadataListAaiObject.builder()
+ .metadataEntries(Collections.singletonList(metadataEntry))
+ .build();
+
+ // Finally construct Service Instance object data
+ ServiceInstanceAaiObject serviceInstanceAaiObject = ImmutableServiceInstanceAaiObject.builder()
+ .serviceInstanceId(serviceInstanceId)
+ .orchestrationStatus(orchestrationStatus)
+ .relationshipListAaiObject(relationshipListAaiObject)
+ .metadataListAaiObject(metadataListAaiObject)
+ .build();
+
+ givenThat(get(urlEqualTo(serviceInstanceUrl))
+ .willReturn(aResponse().withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(gson.toJson(serviceInstanceAaiObject, ImmutableServiceInstanceAaiObject.class))));
+
+ StepVerifier.create(
+ reactiveClient.getServiceInstanceObjectDataFor("http://127.0.0.1:" + PORT + serviceInstanceUrl)
+ )
+ .expectSubscription()
+ .consumeNextWith(serviceInstance -> {
+ Assertions.assertEquals(serviceInstanceId, serviceInstance.getServiceInstanceId(),
+ "Service Instance ID in response does not match");
+
+ MetadataListAaiObject extractedMetadataListObject =
+ serviceInstance.getMetadataListAaiObject().orElseThrow(AaiReactiveClientTestException::new);
+
+ MetadataListAaiObject.MetadataEntryAaiObject extractedMetadataEntry =
+ extractedMetadataListObject.getMetadataEntries()
+ .stream()
+ .filter(m -> m.getMetaname().equals("cvlan"))
+ .findFirst().orElseThrow(AaiReactiveClientTestException::new);
+
+ Assertions.assertEquals("1005", extractedMetadataEntry.getMetavalue(),
+ "CVLAN in response does not match");
+ })
+ .verifyComplete();
+ }
+
+ private static class AaiReactiveClientTestException extends RuntimeException {}
+
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationDmaapConsumerJsonParserTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationDmaapConsumerJsonParserTest.java
new file mode 100644
index 00000000..4ca61f5e
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/utilities/CpeAuthenticationDmaapConsumerJsonParserTest.java
@@ -0,0 +1,311 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.utilities;
+
+import static org.mockito.Mockito.spy;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+
+import java.util.Optional;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.onap.bbs.event.processor.model.CpeAuthenticationConsumerDmaapModel;
+import org.onap.bbs.event.processor.model.ImmutableCpeAuthenticationConsumerDmaapModel;
+
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+class CpeAuthenticationDmaapConsumerJsonParserTest {
+
+ private static JsonParser jsonParser;
+
+ private static final String CPE_AUTHENTICATION_EVENT_TEMPLATE = "{\"event\": {"
+ + "\"commonEventHeader\": { \"sourceName\":\"%s\"},"
+ + "\"stateChangeFields\": {"
+ + " \"oldState\": \"%s\","
+ + " \"newState\": \"%s\","
+ + " \"stateInterface\": \"%s\","
+ + " \"additionalFields\": {"
+ + " \"macAddress\": \"%s\","
+ + " \"swVersion\": \"%s\""
+ + "}}}}";
+
+ private static final String CPE_AUTHENTICATION_EVENT_TEMPLATE_WITH_MISSING_AUTHENTICATION_STATE = "{\"event\": {"
+ + "\"commonEventHeader\": { \"sourceName\":\"%s\"},"
+ + "\"stateChangeFields\": {"
+ + " \"oldState\": \"%s\","
+ + " \"stateInterface\": \"%s\","
+ + " \"additionalFields\": {"
+ + " \"macAddress\": \"%s\","
+ + " \"swVersion\": \"%s\""
+ + "}}}}";
+
+ private static final String CPE_AUTHENTICATION_EVENT_TEMPLATE_WITH_MISSING_SOURCE_NAME = "{\"event\": {"
+ + "\"commonEventHeader\": { },"
+ + "\"stateChangeFields\": {"
+ + " \"oldState\": \"%s\","
+ + " \"newState\": \"%s\","
+ + " \"stateInterface\": \"%s\","
+ + " \"additionalFields\": {"
+ + " \"macAddress\": \"%s\","
+ + " \"swVersion\": \"%s\""
+ + "}}}}";
+
+ private static final String CPE_AUTHENTICATION_EVENT_TEMPLATE_WITH_MISSING_SOURCE_NAME_VALUE = "{\"event\": {"
+ + "\"commonEventHeader\": { \"sourceName\":\"\"},"
+ + "\"stateChangeFields\": {"
+ + " \"oldState\": \"%s\","
+ + " \"newState\": \"%s\","
+ + " \"stateInterface\": \"%s\","
+ + " \"additionalFields\": {"
+ + " \"macAddress\": \"%s\","
+ + " \"swVersion\": \"%s\""
+ + "}}}}";
+
+ private static final String CPE_AUTHENTICATION_EVENT_TEMPLATE_WITH_MISSING_STATE_CHANGE_FIELDS = "{\"event\": {"
+ + "\"commonEventHeader\": { \"sourceName\":\"\"},"
+ + "\"somethingElse\": {"
+ + " \"oldState\": \"%s\","
+ + " \"newState\": \"%s\","
+ + " \"stateInterface\": \"%s\","
+ + " \"additionalFields\": {"
+ + " \"macAddress\": \"%s\","
+ + " \"swVersion\": \"%s\""
+ + "}}}}";
+
+ @BeforeAll
+ static void init() {
+ jsonParser = new JsonParser();
+ }
+
+ @Test
+ void passingNonJson_EmptyFluxIsReturned() {
+
+ CpeAuthenticationDmaapConsumerJsonParser consumerJsonParser =
+ new CpeAuthenticationDmaapConsumerJsonParser();
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just("not JSON")))
+ .expectSubscription()
+ .verifyComplete();
+ }
+
+ @Test
+ void passingNoEvents_EmptyFluxIsReturned() {
+
+ CpeAuthenticationDmaapConsumerJsonParser consumerJsonParser =
+ new CpeAuthenticationDmaapConsumerJsonParser();
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just("[]")))
+ .expectSubscription()
+ .verifyComplete();
+ }
+
+ @Test
+ void passingOneCorrectEvent_validationSucceeds() {
+
+ String sourceName = "PNF-CorrelationId";
+ String oldAuthenticationState = "outOfService";
+ String newAuthenticationState = "inService";
+ String stateInterface = "stateInterface";
+ String rgwMacAddress = "00:0a:95:8d:78:16";
+ String swVersion = "1.2";
+
+ String event = String.format(CPE_AUTHENTICATION_EVENT_TEMPLATE, sourceName, oldAuthenticationState,
+ newAuthenticationState, stateInterface, rgwMacAddress, swVersion);
+
+ CpeAuthenticationDmaapConsumerJsonParser consumerJsonParser =
+ spy(new CpeAuthenticationDmaapConsumerJsonParser());
+ JsonElement jsonElement = jsonParser.parse(event);
+ Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject()))
+ .when(consumerJsonParser).getJsonObjectFromAnArray(jsonElement);
+
+ String eventsArray = "[" + event + "]";
+
+ CpeAuthenticationConsumerDmaapModel expectedEventObject = ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(sourceName)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress)
+ .swVersion(swVersion)
+ .build();
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just(eventsArray)))
+ .expectSubscription()
+ .expectNext(expectedEventObject);
+ }
+
+ @Test
+ void passingTwoCorrectEvents_validationSucceeds() {
+
+ String sourceName1 = "PNF-CorrelationId";
+ String sourceName2 = "PNF-CorrelationId";
+ String oldAuthenticationState = "outOfService";
+ String newAuthenticationState = "inService";
+ String stateInterface = "stateInterface";
+ String rgwMacAddress1 = "00:0a:95:8d:78:16";
+ String rgwMacAddress2 = "00:0a:95:8d:78:17";
+ String swVersion = "1.2";
+
+ String firstEvent = String.format(CPE_AUTHENTICATION_EVENT_TEMPLATE, sourceName1, oldAuthenticationState,
+ newAuthenticationState, stateInterface, rgwMacAddress1, swVersion);
+ String secondEvent = String.format(CPE_AUTHENTICATION_EVENT_TEMPLATE, sourceName2, oldAuthenticationState,
+ newAuthenticationState, stateInterface, rgwMacAddress2, swVersion);
+
+ CpeAuthenticationDmaapConsumerJsonParser consumerJsonParser =
+ spy(new CpeAuthenticationDmaapConsumerJsonParser());
+ JsonElement jsonElement1 = jsonParser.parse(firstEvent);
+ Mockito.doReturn(Optional.of(jsonElement1.getAsJsonObject()))
+ .when(consumerJsonParser).getJsonObjectFromAnArray(jsonElement1);
+ JsonElement jsonElement2 = jsonParser.parse(secondEvent);
+ Mockito.doReturn(Optional.of(jsonElement2.getAsJsonObject()))
+ .when(consumerJsonParser).getJsonObjectFromAnArray(jsonElement2);
+
+ String eventsArray = "[" + firstEvent + secondEvent + "]";
+
+ CpeAuthenticationConsumerDmaapModel expectedFirstEventObject =
+ ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(sourceName1)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress1)
+ .swVersion(swVersion)
+ .build();
+ CpeAuthenticationConsumerDmaapModel expectedSecondEventObject =
+ ImmutableCpeAuthenticationConsumerDmaapModel.builder()
+ .correlationId(sourceName2)
+ .oldAuthenticationState(oldAuthenticationState)
+ .newAuthenticationState(newAuthenticationState)
+ .stateInterface(stateInterface)
+ .rgwMacAddress(rgwMacAddress2)
+ .swVersion(swVersion)
+ .build();
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just(eventsArray)))
+ .expectSubscription()
+ .expectNext(expectedFirstEventObject)
+ .expectNext(expectedSecondEventObject);
+ }
+
+ @Test
+ void passingJsonWithMissingAuthenticationState_validationFails() {
+
+ String sourceName = "PNF-CorrelationId";
+ String oldAuthenticationState = "outOfService";
+ String stateInterface = "stateInterface";
+ String rgwMacAddress = "00:0a:95:8d:78:16";
+ String swVersion = "1.2";
+
+ String event = String.format(CPE_AUTHENTICATION_EVENT_TEMPLATE_WITH_MISSING_AUTHENTICATION_STATE, sourceName,
+ oldAuthenticationState, stateInterface, rgwMacAddress, swVersion);
+
+ CpeAuthenticationDmaapConsumerJsonParser consumerJsonParser =
+ spy(new CpeAuthenticationDmaapConsumerJsonParser());
+ JsonElement jsonElement = jsonParser.parse(event);
+ Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject()))
+ .when(consumerJsonParser).getJsonObjectFromAnArray(jsonElement);
+
+ String eventsArray = "[" + event + "]";
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just(eventsArray)))
+ .expectSubscription()
+ .verifyComplete();
+ }
+
+ @Test
+ void passingJsonWithMissingSourceName_validationFails() {
+
+ String oldAuthenticationState = "outOfService";
+ String newAuthenticationState = "inService";
+ String stateInterface = "stateInterface";
+ String rgwMacAddress = "00:0a:95:8d:78:16";
+ String swVersion = "1.2";
+
+ String event = String.format(CPE_AUTHENTICATION_EVENT_TEMPLATE_WITH_MISSING_SOURCE_NAME,
+ oldAuthenticationState, newAuthenticationState, stateInterface, rgwMacAddress, swVersion);
+
+ CpeAuthenticationDmaapConsumerJsonParser consumerJsonParser =
+ spy(new CpeAuthenticationDmaapConsumerJsonParser());
+ JsonElement jsonElement = jsonParser.parse(event);
+ Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject()))
+ .when(consumerJsonParser).getJsonObjectFromAnArray(jsonElement);
+
+ String eventsArray = "[" + event + "]";
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just(eventsArray)))
+ .expectSubscription()
+ .verifyComplete();
+ }
+
+ @Test
+ void passingJsonWithMissingSourceNameValue_validationFails() {
+
+ String oldAuthenticationState = "outOfService";
+ String newAuthenticationState = "inService";
+ String stateInterface = "stateInterface";
+ String rgwMacAddress = "00:0a:95:8d:78:16";
+ String swVersion = "1.2";
+
+ String event = String.format(CPE_AUTHENTICATION_EVENT_TEMPLATE_WITH_MISSING_SOURCE_NAME_VALUE,
+ oldAuthenticationState, newAuthenticationState, stateInterface, rgwMacAddress, swVersion);
+
+ CpeAuthenticationDmaapConsumerJsonParser consumerJsonParser =
+ spy(new CpeAuthenticationDmaapConsumerJsonParser());
+ JsonElement jsonElement = jsonParser.parse(event);
+ Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject()))
+ .when(consumerJsonParser).getJsonObjectFromAnArray(jsonElement);
+
+ String eventsArray = "[" + event + "]";
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just(eventsArray)))
+ .expectSubscription()
+ .verifyComplete();
+ }
+
+ @Test
+ void passingJsonWithMissingStateChangeFieldsHeader_validationFails() {
+
+ String oldAuthenticationState = "outOfService";
+ String newAuthenticationState = "inService";
+ String stateInterface = "stateInterface";
+ String rgwMacAddress = "00:0a:95:8d:78:16";
+ String swVersion = "1.2";
+
+ String event = String.format(CPE_AUTHENTICATION_EVENT_TEMPLATE_WITH_MISSING_STATE_CHANGE_FIELDS,
+ oldAuthenticationState, newAuthenticationState, stateInterface, rgwMacAddress, swVersion);
+
+ CpeAuthenticationDmaapConsumerJsonParser consumerJsonParser =
+ spy(new CpeAuthenticationDmaapConsumerJsonParser());
+ JsonElement jsonElement = jsonParser.parse(event);
+ Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject()))
+ .when(consumerJsonParser).getJsonObjectFromAnArray(jsonElement);
+
+ String eventsArray = "[" + event + "]";
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just(eventsArray)))
+ .expectSubscription()
+ .verifyComplete();
+ }
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/utilities/ReRegistrationDmaapConsumerJsonParserTest.java b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/utilities/ReRegistrationDmaapConsumerJsonParserTest.java
new file mode 100644
index 00000000..ca448dd0
--- /dev/null
+++ b/components/bbs-event-processor/src/test/java/org/onap/bbs/event/processor/utilities/ReRegistrationDmaapConsumerJsonParserTest.java
@@ -0,0 +1,297 @@
+/*
+ * ============LICENSE_START=======================================================
+ * BBS-RELOCATION-CPE-AUTHENTICATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. 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.bbs.event.processor.utilities;
+
+import static org.mockito.Mockito.spy;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+
+import java.util.Optional;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.onap.bbs.event.processor.model.ImmutableReRegistrationConsumerDmaapModel;
+import org.onap.bbs.event.processor.model.ReRegistrationConsumerDmaapModel;
+
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+class ReRegistrationDmaapConsumerJsonParserTest {
+
+ private static JsonParser jsonParser;
+
+ private static final String RE_REGISTRATION_EVENT_TEMPLATE = "{"
+ + "\"correlationId\":\"%s\","
+ + "\"additionalFields\": {"
+ + " \"attachment-point\": \"%s\","
+ + " \"remote-id\": \"%s\","
+ + " \"cvlan\": \"%s\","
+ + " \"svlan\": \"%s\""
+ + "}}";
+
+ private static final String RE_REGISTRATION_EVENT_TEMPLATE_MISSING_ATTACHMENT_POINT = "{"
+ + "\"correlationId\":\"%s\","
+ + "\"additionalFields\": {"
+ + " \"remote-id\": \"%s\","
+ + " \"cvlan\": \"%s\","
+ + " \"svlan\": \"%s\""
+ + "}}";
+
+ private static final String RE_REGISTRATION_EVENT_TEMPLATE_MISSING_CORRELATION_ID = "{"
+ + "\"additionalFields\": {"
+ + " \"attachment-point\": \"%s\","
+ + " \"remote-id\": \"%s\","
+ + " \"cvlan\": \"%s\","
+ + " \"svlan\": \"%s\""
+ + "}}";
+
+ private static final String RE_REGISTRATION_EVENT_TEMPLATE_MISSING_CORRELATION_ID_VALUE = "{"
+ + "\"correlationId\":\"\","
+ + "\"additionalFields\": {"
+ + " \"attachment-point\": \"%s\","
+ + " \"remote-id\": \"%s\","
+ + " \"cvlan\": \"%s\","
+ + " \"svlan\": \"%s\""
+ + "}}";
+
+ private static final String RE_REGISTRATION_EVENT_TEMPLATE_MISSING_ADDITIONAL_FIELDS = "{"
+ + "\"correlationId\":\"%s\","
+ + "\"somethingElse\": {"
+ + " \"attachment-point\": \"%s\","
+ + " \"remote-id\": \"%s\","
+ + " \"cvlan\": \"%s\","
+ + " \"svlan\": \"%s\""
+ + "}}";
+
+ @BeforeAll
+ static void init() {
+ jsonParser = new JsonParser();
+ }
+
+ @Test
+ void passingNonJson_EmptyFluxIsReturned() {
+
+ ReRegistrationDmaapConsumerJsonParser consumerJsonParser = new ReRegistrationDmaapConsumerJsonParser();
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just("not JSON")))
+ .expectSubscription()
+ .verifyComplete();
+ }
+
+ @Test
+ void passingNoEvents_EmptyFluxIsReturned() {
+
+ ReRegistrationDmaapConsumerJsonParser consumerJsonParser = new ReRegistrationDmaapConsumerJsonParser();
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just("[]")))
+ .expectSubscription()
+ .verifyComplete();
+ }
+
+ @Test
+ void passingOneCorrectEvent_validationSucceeds() {
+
+ String correlationId = "PNF-CorrelationId";
+ String attachmentPoint = "olt1/1/1";
+ String remoteId = "remoteId";
+ String cvlan = "1005";
+ String svlan = "100";
+
+ String event = String.format(RE_REGISTRATION_EVENT_TEMPLATE, correlationId, attachmentPoint,
+ remoteId, cvlan, svlan);
+
+ ReRegistrationDmaapConsumerJsonParser consumerJsonParser = spy(new ReRegistrationDmaapConsumerJsonParser());
+ JsonElement jsonElement = jsonParser.parse(event);
+ Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject()))
+ .when(consumerJsonParser).getJsonObjectFromAnArray(jsonElement);
+
+ String eventsArray = "[" + event + "]";
+
+ ReRegistrationConsumerDmaapModel expectedEventObject = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(correlationId)
+ .attachmentPoint(attachmentPoint)
+ .remoteId(remoteId)
+ .cVlan(cvlan)
+ .sVlan(svlan)
+ .build();
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just(eventsArray)))
+ .expectSubscription()
+ .expectNext(expectedEventObject);
+ }
+
+ @Test
+ void passingTwoCorrectEvents_validationSucceeds() {
+
+ String correlationId1 = "PNF-CorrelationId1";
+ String correlationId2 = "PNF-CorrelationId2";
+ String attachmentPoint1 = "olt1/1/1";
+ String attachmentPoint2 = "olt2/2/2";
+ String remoteId1 = "remoteId1";
+ String remoteId2 = "remoteId2";
+ String cvlan = "1005";
+ String svlan = "100";
+
+ String firstEvent = String.format(RE_REGISTRATION_EVENT_TEMPLATE, correlationId1, attachmentPoint1,
+ remoteId1, cvlan, svlan);
+ String secondEvent = String.format(RE_REGISTRATION_EVENT_TEMPLATE, correlationId1, attachmentPoint1,
+ remoteId1, cvlan, svlan);
+
+ ReRegistrationDmaapConsumerJsonParser consumerJsonParser = spy(new ReRegistrationDmaapConsumerJsonParser());
+ JsonElement jsonElement1 = jsonParser.parse(firstEvent);
+ Mockito.doReturn(Optional.of(jsonElement1.getAsJsonObject()))
+ .when(consumerJsonParser).getJsonObjectFromAnArray(jsonElement1);
+ JsonElement jsonElement2 = jsonParser.parse(secondEvent);
+ Mockito.doReturn(Optional.of(jsonElement2.getAsJsonObject()))
+ .when(consumerJsonParser).getJsonObjectFromAnArray(jsonElement2);
+
+ String eventsArray = "[" + firstEvent + secondEvent + "]";
+
+ ReRegistrationConsumerDmaapModel expectedFirstEventObject = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(correlationId1)
+ .attachmentPoint(attachmentPoint1)
+ .remoteId(remoteId1)
+ .cVlan(cvlan)
+ .sVlan(svlan)
+ .build();
+ ReRegistrationConsumerDmaapModel expectedSecondEventObject = ImmutableReRegistrationConsumerDmaapModel.builder()
+ .correlationId(correlationId2)
+ .attachmentPoint(attachmentPoint2)
+ .remoteId(remoteId2)
+ .cVlan(cvlan)
+ .sVlan(svlan)
+ .build();
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just(eventsArray)))
+ .expectSubscription()
+ .expectNext(expectedFirstEventObject)
+ .expectNext(expectedSecondEventObject);
+ }
+
+ @Test
+ void passingJsonWithMissingAttachmentPoint_validationFails() {
+
+ String correlationId = "PNF-CorrelationId";
+ String remoteId = "remoteId";
+ String cvlan = "1005";
+ String svlan = "100";
+
+ String event = String.format(RE_REGISTRATION_EVENT_TEMPLATE_MISSING_ATTACHMENT_POINT,
+ correlationId,
+ remoteId,
+ cvlan,
+ svlan);
+
+ ReRegistrationDmaapConsumerJsonParser consumerJsonParser = spy(new ReRegistrationDmaapConsumerJsonParser());
+ JsonElement jsonElement = jsonParser.parse(event);
+ Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject()))
+ .when(consumerJsonParser).getJsonObjectFromAnArray(jsonElement);
+
+ String eventsArray = "[" + event + "]";
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just(eventsArray)))
+ .expectSubscription()
+ .verifyComplete();
+ }
+
+ @Test
+ void passingJsonWithMissingCorrelationId_validationFails() {
+
+ String attachmentPoint = "olt1/1/1";
+ String remoteId = "remoteId";
+ String cvlan = "1005";
+ String svlan = "100";
+
+ String event = String.format(RE_REGISTRATION_EVENT_TEMPLATE_MISSING_CORRELATION_ID,
+ attachmentPoint,
+ remoteId,
+ cvlan,
+ svlan);
+
+ ReRegistrationDmaapConsumerJsonParser consumerJsonParser = spy(new ReRegistrationDmaapConsumerJsonParser());
+ JsonElement jsonElement = jsonParser.parse(event);
+ Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject()))
+ .when(consumerJsonParser).getJsonObjectFromAnArray(jsonElement);
+
+ String eventsArray = "[" + event + "]";
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just(eventsArray)))
+ .expectSubscription()
+ .verifyComplete();
+ }
+
+ @Test
+ void passingJsonWithMissingCorrelationIdValue_validationFails() {
+
+ String attachmentPoint = "olt1/1/1";
+ String remoteId = "remoteId";
+ String cvlan = "1005";
+ String svlan = "100";
+
+ String event = String.format(RE_REGISTRATION_EVENT_TEMPLATE_MISSING_CORRELATION_ID_VALUE,
+ attachmentPoint,
+ remoteId,
+ cvlan,
+ svlan);
+
+ ReRegistrationDmaapConsumerJsonParser consumerJsonParser = spy(new ReRegistrationDmaapConsumerJsonParser());
+ JsonElement jsonElement = jsonParser.parse(event);
+ Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject()))
+ .when(consumerJsonParser).getJsonObjectFromAnArray(jsonElement);
+
+ String eventsArray = "[" + event + "]";
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just(eventsArray)))
+ .expectSubscription()
+ .verifyComplete();
+ }
+
+ @Test
+ void passingJsonWithMissingAdditionalFields_validationFails() {
+
+ String correlationId = "PNF-CorrelationId";
+ String attachmentPoint = "olt1/1/1";
+ String remoteId = "remoteId";
+ String cvlan = "1005";
+ String svlan = "100";
+
+ String event = String.format(RE_REGISTRATION_EVENT_TEMPLATE_MISSING_ADDITIONAL_FIELDS,
+ correlationId,
+ attachmentPoint,
+ remoteId,
+ cvlan,
+ svlan);
+
+ ReRegistrationDmaapConsumerJsonParser consumerJsonParser = spy(new ReRegistrationDmaapConsumerJsonParser());
+ JsonElement jsonElement = jsonParser.parse(event);
+ Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject()))
+ .when(consumerJsonParser).getJsonObjectFromAnArray(jsonElement);
+
+ String eventsArray = "[" + event + "]";
+
+ StepVerifier.create(consumerJsonParser.extractModelFromDmaap(Mono.just(eventsArray)))
+ .expectSubscription()
+ .verifyComplete();
+ }
+
+} \ No newline at end of file
diff --git a/components/bbs-event-processor/src/test/resources/logback-test.xml b/components/bbs-event-processor/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..0b93a431
--- /dev/null
+++ b/components/bbs-event-processor/src/test/resources/logback-test.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ ===============================LICENSE_START======================================
+ ~ Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ ~ ================================================================================
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~ ============================LICENSE_END===========================================
+ -->
+<configuration>
+ <include resource="org/springframework/boot/logging/logback/base.xml" />
+ <root level="ERROR"/>
+ <logger name="org.springframework" level="ERROR"/>
+ <logger name="org.onap" level="WARN"/>
+</configuration> \ No newline at end of file
diff --git a/components/bbs-event-processor/version.properties b/components/bbs-event-processor/version.properties
new file mode 100644
index 00000000..2ddebb39
--- /dev/null
+++ b/components/bbs-event-processor/version.properties
@@ -0,0 +1,6 @@
+major=1
+minor=0
+patch=0
+base_version=${major}.${minor}.${patch}
+release_version=${base_version}
+snapshot_version=${base_version}-SNAPSHOT
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 00000000..d564717a
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!--
+============LICENSE_START=======================================================
+org.onap.dcaegen2
+================================================================================
+Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
+================================================================================
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+============LICENSE_END=========================================================
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.oparent</groupId>
+ <artifactId>oparent</artifactId>
+ <version>1.2.3</version>
+ </parent>
+ <groupId>org.onap.dcaegen2</groupId>
+ <artifactId>services</artifactId>
+ <name>dcaegen2-services</name>
+ <version>1.0.0-SNAPSHOT</version>
+ <url>http://maven.apache.org</url>
+ <packaging>pom</packaging>
+ <modules>
+ <module>components</module>
+ </modules>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+</project>
diff --git a/version.properties b/version.properties
new file mode 100644
index 00000000..2ddebb39
--- /dev/null
+++ b/version.properties
@@ -0,0 +1,6 @@
+major=1
+minor=0
+patch=0
+base_version=${major}.${minor}.${patch}
+release_version=${base_version}
+snapshot_version=${base_version}-SNAPSHOT