From be11dee889f5a740d584458b62804e5fd4296e53 Mon Sep 17 00:00:00 2001 From: s00370346 Date: Thu, 14 Mar 2019 15:06:40 +0530 Subject: Issue-ID: DCAEGEN2-1055 Generic RestConfCollector Change-Id: I1800affa2b34cbb7487c0d8411e078adec5a0c48 Signed-off-by: s00370346 --- src/assembly/dep.xml | 39 +- .../java/org/onap/dcae/ApplicationException.java | 44 ++ .../java/org/onap/dcae/ApplicationSettings.java | 208 +++++++++ src/main/java/org/onap/dcae/CLIUtils.java | 55 +++ src/main/java/org/onap/dcae/RestConfCollector.java | 189 ++++++++ .../restconf/common/AdditionalHeaderWebTarget.java | 159 ------- .../dcae/collectors/restconf/common/AnyNode.java | 132 ------ .../dcae/collectors/restconf/common/AuthType.java | 43 -- .../dcae/collectors/restconf/common/Constants.java | 44 -- .../restconf/common/DataChangeEventListener.java | 51 --- .../collectors/restconf/common/EventProcessor.java | 88 ---- .../dcae/collectors/restconf/common/Format.java | 38 -- .../collectors/restconf/common/HttpMethod.java | 47 -- .../collectors/restconf/common/HttpResponse.java | 30 -- .../collectors/restconf/common/JsonParser.java | 92 ---- .../collectors/restconf/common/Parameters.java | 52 --- .../restconf/common/RestConfCollector.java | 72 --- .../restconf/common/RestConfContext.java | 51 --- .../collectors/restconf/common/RestConfProc.java | 336 -------------- .../restconf/common/RestapiCallNode.java | 510 --------------------- .../restconf/common/RestapiCallNodeUtil.java | 178 ------- .../collectors/restconf/common/RetryException.java | 27 -- .../collectors/restconf/common/RetryPolicy.java | 58 --- .../restconf/common/RetryPolicyStore.java | 53 --- .../collectors/restconf/common/XmlJsonUtil.java | 412 ----------------- .../dcae/collectors/restconf/common/XmlParser.java | 178 ------- .../event/publishing/DMaaPConfigurationParser.java | 107 ----- .../event/publishing/DMaaPEventPublisher.java | 75 --- .../event/publishing/DMaaPPublishersBuilder.java | 63 --- .../event/publishing/DMaaPPublishersCache.java | 110 ----- .../common/event/publishing/EventPublisher.java | 35 -- .../common/event/publishing/PublisherConfig.java | 95 ---- .../common/event/publishing/VavrUtils.java | 48 -- .../dcae/common/AdditionalHeaderWebTarget.java | 159 +++++++ src/main/java/org/onap/dcae/common/AnyNode.java | 89 ++++ src/main/java/org/onap/dcae/common/AuthType.java | 43 ++ src/main/java/org/onap/dcae/common/Constants.java | 48 ++ .../onap/dcae/common/DataChangeEventListener.java | 86 ++++ .../org/onap/dcae/common/EventConnectionState.java | 43 ++ src/main/java/org/onap/dcae/common/EventData.java | 42 ++ .../java/org/onap/dcae/common/EventProcessor.java | 103 +++++ src/main/java/org/onap/dcae/common/Format.java | 38 ++ src/main/java/org/onap/dcae/common/HttpMethod.java | 47 ++ .../java/org/onap/dcae/common/HttpResponse.java | 30 ++ src/main/java/org/onap/dcae/common/JsonParser.java | 92 ++++ src/main/java/org/onap/dcae/common/Parameters.java | 52 +++ .../java/org/onap/dcae/common/RestConfContext.java | 51 +++ .../java/org/onap/dcae/common/RestapiCallNode.java | 467 +++++++++++++++++++ .../org/onap/dcae/common/RestapiCallNodeUtil.java | 194 ++++++++ .../org/onap/dcae/common/SSLContextCreator.java | 83 ++++ .../java/org/onap/dcae/common/XmlJsonUtil.java | 412 +++++++++++++++++ src/main/java/org/onap/dcae/common/XmlParser.java | 178 +++++++ .../publishing/DMaaPConfigurationParser.java | 113 +++++ .../common/publishing/DMaaPEventPublisher.java | 87 ++++ .../common/publishing/DMaaPPublishersBuilder.java | 62 +++ .../common/publishing/DMaaPPublishersCache.java | 123 +++++ .../dcae/common/publishing/EventPublisher.java | 39 ++ .../dcae/common/publishing/PublisherConfig.java | 100 ++++ .../org/onap/dcae/common/publishing/VavrUtils.java | 62 +++ .../org/onap/dcae/controller/AccessController.java | 243 ++++++++++ .../onap/dcae/controller/ConfigFilesFacade.java | 131 ++++++ .../org/onap/dcae/controller/ConfigLoader.java | 147 ++++++ .../org/onap/dcae/controller/ConfigParsing.java | 59 +++ .../org/onap/dcae/controller/ConfigSource.java | 90 ++++ .../onap/dcae/controller/ControllerConfigInfo.java | 88 ++++ .../java/org/onap/dcae/controller/Conversions.java | 54 +++ .../onap/dcae/controller/EnvPropertiesReader.java | 95 ++++ .../java/org/onap/dcae/controller/EnvProps.java | 74 +++ .../dcae/controller/PersistentEventConnection.java | 207 +++++++++ .../org/onap/dcae/restapi/ApiAuthInterceptor.java | 77 ++++ .../org/onap/dcae/restapi/ApiConfiguration.java | 48 ++ .../java/org/onap/dcae/restapi/ApiException.java | 66 +++ .../org/onap/dcae/restapi/RccRestController.java | 41 ++ .../java/org/onap/dcae/restapi/ServletConfig.java | 108 +++++ .../java/org/onap/dcae/restapi/SwaggerConfig.java | 44 ++ .../java/org/onap/dcae/restapi/WebMvcConfig.java | 57 +++ src/main/resources/banner.txt | 7 + src/main/scripts/docker_entry.sh | 19 + src/main/scripts/restConfCollector.sh | 21 +- .../java/org/onap/dcae/AccessControllerTest.java | 114 +++++ src/test/java/org/onap/dcae/AnyNodeTest.java | 64 +++ .../org/onap/dcae/ApplicationSettingsTest.java | 337 ++++++++++++++ src/test/java/org/onap/dcae/CLIUtilsTest.java | 58 +++ src/test/java/org/onap/dcae/TLSTest.java | 94 ++++ src/test/java/org/onap/dcae/TLSTestBase.java | 154 +++++++ src/test/java/org/onap/dcae/TestingUtilities.java | 141 ++++++ src/test/java/org/onap/dcae/WiremockBasedTest.java | 68 +++ .../collectors/restconf/common/AuthTypeTest.java | 42 -- .../collectors/restconf/common/FormatTest.java | 40 -- .../restconf/common/RestConfContextTest.java | 52 --- .../restconf/common/RetryPolicyStoreTest.java | 63 --- .../restconf/common/RetryPolicyTest.java | 57 --- .../publishing/DMaaPConfigurationParserTest.java | 111 ----- .../event/publishing/DMaaPEventPublisherTest.java | 78 ---- .../event/publishing/DMaaPPublishersCacheTest.java | 93 ---- .../common/event/publishing/JsonParserTest.java | 38 -- .../restconf/restconftest/AnyNodeTest.java | 62 --- .../restconf/restconftest/RestConfProcTest.java | 79 ---- .../restconf/restconftest/SseResource.java | 69 --- .../restconftest/TestRestConfCollector.java | 66 --- .../org/onap/dcae/common/ApiExceptionTest.java | 54 +++ .../java/org/onap/dcae/common/AuthTypeTest.java | 42 ++ .../dcae/common/DataChangeEventListnerTest.java | 69 +++ .../onap/dcae/common/EventConnectionStateTest.java | 40 ++ .../org/onap/dcae/common/EventProcessorTest.java | 104 +++++ src/test/java/org/onap/dcae/common/FormatTest.java | 40 ++ .../org/onap/dcae/common/RestConfContextTest.java | 52 +++ .../java/org/onap/dcae/common/XmlJsonUtilTest.java | 81 ++++ .../java/org/onap/dcae/common/XmlParserTest.java | 46 ++ .../common/publishing/DMaaPEventPublisherTest.java | 79 ++++ .../publishing/DMaaPPublishersCacheTest.java | 127 +++++ .../dcae/common/publishing/JsonParserTest.java | 38 ++ .../onap/dcae/controller/ConfigCBSSourceTest.java | 151 ++++++ .../dcae/controller/ConfigFilesFacadeTest.java | 140 ++++++ .../controller/ConfigLoaderIntegrationE2ETest.java | 98 ++++ .../onap/dcae/controller/ConfigParsingTest.java | 79 ++++ .../dcae/controller/EnvPropertiesReaderTest.java | 69 +++ .../org/onap/dcae/controller/EnvPropsTest.java | 41 ++ .../onap/dcae/restapi/ApiAuthInterceptionTest.java | 177 +++++++ src/test/resources/RestConfEvent.json | 26 -- src/test/resources/controller-config_dmaap_ip.json | 238 ++++++++++ .../resources/controller-config_singleline_ip.json | 128 ++++++ src/test/resources/keystore | Bin 0 -> 3717 bytes src/test/resources/passwordfile | 1 + src/test/resources/rcc_passwordfile | 1 + src/test/resources/sdnc.p12 | Bin 0 -> 1713 bytes src/test/resources/testDmaapConfig_ip.json | 12 + src/test/resources/testFullDmaapConfig_gen2.json | 24 + .../resources/testParseDMaaPCredentialsGen2.json | 6 +- .../testParseDMaaPCredentialsGen2Temp.json | 9 + .../resources/testParseDMaaPCredentialsLegacy.json | 6 +- src/test/resources/testParseDMaaPGen2.json | 4 +- src/test/resources/testParseDMaaPLegacy.json | 6 +- src/test/resources/test_anynode_class.json | 9 + src/test/resources/testcollector.properties | 10 + src/test/resources/trustpasswordfile | 1 + src/test/resources/truststore | Bin 0 -> 5145 bytes 137 files changed, 8053 insertions(+), 4073 deletions(-) create mode 100644 src/main/java/org/onap/dcae/ApplicationException.java create mode 100644 src/main/java/org/onap/dcae/ApplicationSettings.java create mode 100644 src/main/java/org/onap/dcae/CLIUtils.java create mode 100644 src/main/java/org/onap/dcae/RestConfCollector.java delete mode 100644 src/main/java/org/onap/dcae/collectors/restconf/common/AdditionalHeaderWebTarget.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/AnyNode.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/AuthType.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/Constants.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/DataChangeEventListener.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/EventProcessor.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/Format.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/HttpMethod.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/HttpResponse.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/JsonParser.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/Parameters.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/RestConfCollector.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/RestConfContext.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/RestConfProc.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/RestapiCallNode.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/RestapiCallNodeUtil.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/RetryException.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/RetryPolicy.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/RetryPolicyStore.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/XmlJsonUtil.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/XmlParser.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPConfigurationParser.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPEventPublisher.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPPublishersBuilder.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPPublishersCache.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/EventPublisher.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/PublisherConfig.java delete mode 100755 src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/VavrUtils.java create mode 100644 src/main/java/org/onap/dcae/common/AdditionalHeaderWebTarget.java create mode 100644 src/main/java/org/onap/dcae/common/AnyNode.java create mode 100755 src/main/java/org/onap/dcae/common/AuthType.java create mode 100755 src/main/java/org/onap/dcae/common/Constants.java create mode 100755 src/main/java/org/onap/dcae/common/DataChangeEventListener.java create mode 100644 src/main/java/org/onap/dcae/common/EventConnectionState.java create mode 100644 src/main/java/org/onap/dcae/common/EventData.java create mode 100644 src/main/java/org/onap/dcae/common/EventProcessor.java create mode 100755 src/main/java/org/onap/dcae/common/Format.java create mode 100755 src/main/java/org/onap/dcae/common/HttpMethod.java create mode 100755 src/main/java/org/onap/dcae/common/HttpResponse.java create mode 100755 src/main/java/org/onap/dcae/common/JsonParser.java create mode 100755 src/main/java/org/onap/dcae/common/Parameters.java create mode 100755 src/main/java/org/onap/dcae/common/RestConfContext.java create mode 100755 src/main/java/org/onap/dcae/common/RestapiCallNode.java create mode 100755 src/main/java/org/onap/dcae/common/RestapiCallNodeUtil.java create mode 100644 src/main/java/org/onap/dcae/common/SSLContextCreator.java create mode 100755 src/main/java/org/onap/dcae/common/XmlJsonUtil.java create mode 100755 src/main/java/org/onap/dcae/common/XmlParser.java create mode 100644 src/main/java/org/onap/dcae/common/publishing/DMaaPConfigurationParser.java create mode 100644 src/main/java/org/onap/dcae/common/publishing/DMaaPEventPublisher.java create mode 100644 src/main/java/org/onap/dcae/common/publishing/DMaaPPublishersBuilder.java create mode 100644 src/main/java/org/onap/dcae/common/publishing/DMaaPPublishersCache.java create mode 100644 src/main/java/org/onap/dcae/common/publishing/EventPublisher.java create mode 100644 src/main/java/org/onap/dcae/common/publishing/PublisherConfig.java create mode 100644 src/main/java/org/onap/dcae/common/publishing/VavrUtils.java create mode 100644 src/main/java/org/onap/dcae/controller/AccessController.java create mode 100644 src/main/java/org/onap/dcae/controller/ConfigFilesFacade.java create mode 100644 src/main/java/org/onap/dcae/controller/ConfigLoader.java create mode 100644 src/main/java/org/onap/dcae/controller/ConfigParsing.java create mode 100644 src/main/java/org/onap/dcae/controller/ConfigSource.java create mode 100644 src/main/java/org/onap/dcae/controller/ControllerConfigInfo.java create mode 100644 src/main/java/org/onap/dcae/controller/Conversions.java create mode 100644 src/main/java/org/onap/dcae/controller/EnvPropertiesReader.java create mode 100644 src/main/java/org/onap/dcae/controller/EnvProps.java create mode 100644 src/main/java/org/onap/dcae/controller/PersistentEventConnection.java create mode 100644 src/main/java/org/onap/dcae/restapi/ApiAuthInterceptor.java create mode 100644 src/main/java/org/onap/dcae/restapi/ApiConfiguration.java create mode 100644 src/main/java/org/onap/dcae/restapi/ApiException.java create mode 100644 src/main/java/org/onap/dcae/restapi/RccRestController.java create mode 100644 src/main/java/org/onap/dcae/restapi/ServletConfig.java create mode 100644 src/main/java/org/onap/dcae/restapi/SwaggerConfig.java create mode 100644 src/main/java/org/onap/dcae/restapi/WebMvcConfig.java create mode 100644 src/main/resources/banner.txt create mode 100644 src/test/java/org/onap/dcae/AccessControllerTest.java create mode 100644 src/test/java/org/onap/dcae/AnyNodeTest.java create mode 100644 src/test/java/org/onap/dcae/ApplicationSettingsTest.java create mode 100644 src/test/java/org/onap/dcae/CLIUtilsTest.java create mode 100644 src/test/java/org/onap/dcae/TLSTest.java create mode 100644 src/test/java/org/onap/dcae/TLSTestBase.java create mode 100644 src/test/java/org/onap/dcae/TestingUtilities.java create mode 100644 src/test/java/org/onap/dcae/WiremockBasedTest.java delete mode 100644 src/test/java/org/onap/dcae/collectors/restconf/common/AuthTypeTest.java delete mode 100644 src/test/java/org/onap/dcae/collectors/restconf/common/FormatTest.java delete mode 100644 src/test/java/org/onap/dcae/collectors/restconf/common/RestConfContextTest.java delete mode 100644 src/test/java/org/onap/dcae/collectors/restconf/common/RetryPolicyStoreTest.java delete mode 100644 src/test/java/org/onap/dcae/collectors/restconf/common/RetryPolicyTest.java delete mode 100755 src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPConfigurationParserTest.java delete mode 100755 src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPEventPublisherTest.java delete mode 100755 src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPPublishersCacheTest.java delete mode 100644 src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/JsonParserTest.java delete mode 100755 src/test/java/org/onap/dcae/collectors/restconf/restconftest/AnyNodeTest.java delete mode 100755 src/test/java/org/onap/dcae/collectors/restconf/restconftest/RestConfProcTest.java delete mode 100755 src/test/java/org/onap/dcae/collectors/restconf/restconftest/SseResource.java delete mode 100755 src/test/java/org/onap/dcae/collectors/restconf/restconftest/TestRestConfCollector.java create mode 100644 src/test/java/org/onap/dcae/common/ApiExceptionTest.java create mode 100644 src/test/java/org/onap/dcae/common/AuthTypeTest.java create mode 100644 src/test/java/org/onap/dcae/common/DataChangeEventListnerTest.java create mode 100644 src/test/java/org/onap/dcae/common/EventConnectionStateTest.java create mode 100644 src/test/java/org/onap/dcae/common/EventProcessorTest.java create mode 100644 src/test/java/org/onap/dcae/common/FormatTest.java create mode 100644 src/test/java/org/onap/dcae/common/RestConfContextTest.java create mode 100644 src/test/java/org/onap/dcae/common/XmlJsonUtilTest.java create mode 100644 src/test/java/org/onap/dcae/common/XmlParserTest.java create mode 100644 src/test/java/org/onap/dcae/common/publishing/DMaaPEventPublisherTest.java create mode 100644 src/test/java/org/onap/dcae/common/publishing/DMaaPPublishersCacheTest.java create mode 100644 src/test/java/org/onap/dcae/common/publishing/JsonParserTest.java create mode 100644 src/test/java/org/onap/dcae/controller/ConfigCBSSourceTest.java create mode 100644 src/test/java/org/onap/dcae/controller/ConfigFilesFacadeTest.java create mode 100644 src/test/java/org/onap/dcae/controller/ConfigLoaderIntegrationE2ETest.java create mode 100644 src/test/java/org/onap/dcae/controller/ConfigParsingTest.java create mode 100644 src/test/java/org/onap/dcae/controller/EnvPropertiesReaderTest.java create mode 100644 src/test/java/org/onap/dcae/controller/EnvPropsTest.java create mode 100644 src/test/java/org/onap/dcae/restapi/ApiAuthInterceptionTest.java delete mode 100755 src/test/resources/RestConfEvent.json create mode 100755 src/test/resources/controller-config_dmaap_ip.json create mode 100755 src/test/resources/controller-config_singleline_ip.json create mode 100755 src/test/resources/keystore create mode 100755 src/test/resources/passwordfile create mode 100755 src/test/resources/rcc_passwordfile create mode 100755 src/test/resources/sdnc.p12 create mode 100755 src/test/resources/testDmaapConfig_ip.json create mode 100755 src/test/resources/testFullDmaapConfig_gen2.json create mode 100755 src/test/resources/testParseDMaaPCredentialsGen2Temp.json create mode 100755 src/test/resources/test_anynode_class.json create mode 100755 src/test/resources/testcollector.properties create mode 100755 src/test/resources/trustpasswordfile create mode 100755 src/test/resources/truststore (limited to 'src') diff --git a/src/assembly/dep.xml b/src/assembly/dep.xml index 472d966..484c924 100755 --- a/src/assembly/dep.xml +++ b/src/assembly/dep.xml @@ -1,3 +1,23 @@ + + @@ -13,15 +33,17 @@ src/main/scripts bin - **/*.* + **/*.sh 0755 unix + etc etc + src/main/resources @@ -30,6 +52,21 @@ etc + + dpo/data-formats + + **/*.json + + specs + + + + dpo/spec + + **/*.json + + specs + diff --git a/src/main/java/org/onap/dcae/ApplicationException.java b/src/main/java/org/onap/dcae/ApplicationException.java new file mode 100644 index 0000000..60624da --- /dev/null +++ b/src/main/java/org/onap/dcae/ApplicationException.java @@ -0,0 +1,44 @@ +/* + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae; + +import org.apache.commons.configuration.ConfigurationException; + +public class ApplicationException extends RuntimeException { + + public ApplicationException(ConfigurationException ex) { + super(ex); + } + + public ApplicationException(String message, Exception ex) { + super(message, ex); + } + + public ApplicationException(Exception ex) { + super(ex); + } + + public ApplicationException(String message) { + super(message); + } +} diff --git a/src/main/java/org/onap/dcae/ApplicationSettings.java b/src/main/java/org/onap/dcae/ApplicationSettings.java new file mode 100644 index 0000000..c7e42c5 --- /dev/null +++ b/src/main/java/org/onap/dcae/ApplicationSettings.java @@ -0,0 +1,208 @@ +/* + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae; + +import com.google.common.annotations.VisibleForTesting; +import io.vavr.Function1; +import io.vavr.collection.HashMap; +import io.vavr.collection.List; +import io.vavr.collection.Map; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Iterator; + +/** + * Abstraction over application configuration. + * Its job is to provide easily discoverable (by method names lookup) and type safe access to configuration properties. + */ +public class ApplicationSettings { + + private static final Logger log = LoggerFactory.getLogger(ApplicationSettings.class); + + private final String appInvocationDir; + private final String configurationFileLocation; + private final PropertiesConfiguration properties = new PropertiesConfiguration(); + + + public ApplicationSettings(String[] args, Function1> argsParser) { + this(args, argsParser, System.getProperty("user.dir")); + } + + public ApplicationSettings(String[] args, Function1> argsParser, String appInvocationDir) { + log.info("New ApplicationSettings........"); + this.appInvocationDir = appInvocationDir; + properties.setDelimiterParsingDisabled(true); + Map parsedArgs = argsParser.apply(args); + configurationFileLocation = findOutConfigurationFileLocation(parsedArgs); + loadPropertiesFromFile(); + parsedArgs.filterKeys(k -> !"c".equals(k)).forEach(this::addOrUpdate); + } + + + public void reloadProperties() { + try { + log.info("Reloading Properties ...."); + properties.load(configurationFileLocation); + properties.refresh(); + } catch (ConfigurationException ex) { + log.error("Cannot load properties cause:", ex); + throw new ApplicationException(ex); + } + } + + public void loadPropertiesFromFile() { + try { + properties.load(configurationFileLocation); + Iterator itr = properties.getKeys(); + while (itr.hasNext()) { + String key = itr.next(); + log.info(" Key " + key + " value" + properties.getString(key)); + } + } catch (ConfigurationException ex) { + log.error("Cannot load properties cause:", ex); + throw new ApplicationException(ex); + } + } + + + public boolean authorizationEnabled() { + return properties.getInt("collector.header.authflag", 0) > 0; + } + + private String findOutConfigurationFileLocation(Map parsedArgs) { + return prependWithUserDirOnRelative(parsedArgs.get("c").getOrElse("etc/collector.properties")); + } + + public Path configurationFileLocation() { + return Paths.get(configurationFileLocation); + } + + public int maximumAllowedQueuedEvents() { + return properties.getInt("collector.rcc.inputQueue.maxPending", 1024 * 4); + } + + public int httpPort() { + return properties.getInt("collector.rcc.service.port", 8686); + } + + public int httpsPort() { + return properties.getInt("collector.rcc.service.secure.port", 8687); + } + + + public boolean httpsEnabled() { + return httpsPort() > 0; + } + + public String rcc_keystorePasswordFileLocation() { + return prependWithUserDirOnRelative(properties.getString("collector.keystore.passwordfile", "etc/rcc_passwordfile")); + } + + public String rcc_keystoreFileLocation() { + return prependWithUserDirOnRelative(properties.getString("collector.keystore.file.location", "etc/keystore")); + } + + public String keystorePasswordFileLocation() { + return prependWithUserDirOnRelative(properties.getString("collector.rcc.keystore.passwordfile", "etc/passwordfile")); + } + + public String keystoreFileLocation() { + return prependWithUserDirOnRelative(properties.getString("collector.rcc.keystore.file.location", "etc/sdnc.p12")); + } + + public boolean clientTlsAuthenticationEnabled() { + return httpsEnabled() && properties.getInt("collector.rcc.service.secure.clientauth", 0) > 0; + } + + public Map validAuthorizationCredentials() { + return prepareUsersMap(properties.getString("collector.header.authlist", null)); + } + + private Map prepareUsersMap(@Nullable String allowedUsers) { + return allowedUsers == null ? HashMap.empty() + : List.of(allowedUsers.split("\\|")) + .map(t -> t.split(",")) + .toMap(t -> t[0].trim(), t -> t[1].trim()); + } + + public String keystoreAlias() { + return properties.getString("collector.rcc.keystore.alias", "tomcat"); + } + + public String truststorePasswordFileLocation() { + return prependWithUserDirOnRelative(properties.getString("collector.rcc.truststore.passwordfile", "etc/trustpasswordfile")); + } + + public String truststoreFileLocation() { + return prependWithUserDirOnRelative(properties.getString("collector.rcc.truststore.file.location", "etc/truststore.onap.client.jks")); + } + + public String rcc_policy() { + return properties.getString("rcc_policy", ""); + } + + public String dMaaPConfigurationFileLocation() { + return prependWithUserDirOnRelative(properties.getString("collector.dmaapfile", "etc/DmaapConfig.json")); + } + + public String dMaaPStreamsMapping() { + return properties.getString("collector.rcc.dmaap.streamid", null); + } + + private void updateProperty(String key, String value) { + if (properties.containsKey(key)) { + properties.setProperty(key, value); + log.info("Retrives property: " + key + "Value " + value); + } else { + properties.addProperty(key, value); + } + } + + public void addOrUpdate(String key, String value) { + if (properties.containsKey(key)) { + properties.setProperty(key, value); + } else { + properties.addProperty(key, value); + } + } + + + private String prependWithUserDirOnRelative(String filePath) { + if (!Paths.get(filePath).isAbsolute()) { + filePath = Paths.get(appInvocationDir, filePath).toString(); + } + return filePath; + } + + @VisibleForTesting + String getStringDirectly(String key) { + return properties.getString(key); + } +} + diff --git a/src/main/java/org/onap/dcae/CLIUtils.java b/src/main/java/org/onap/dcae/CLIUtils.java new file mode 100644 index 0000000..eeab465 --- /dev/null +++ b/src/main/java/org/onap/dcae/CLIUtils.java @@ -0,0 +1,55 @@ +/* + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae; + +import io.vavr.collection.Map; + +import java.util.HashMap; + +public class CLIUtils { + + public static Map processCmdLine(String[] args) { + final java.util.Map map = new HashMap<>(); + + String argumentName = null; + + for (String arg : args) { + if (isArgumentName(arg)) { + argumentName = resolveArgumentName(arg); + map.put(argumentName, ""); + } else { + map.put(argumentName, arg); + } + } + + return io.vavr.collection.HashMap.ofAll(map); + } + + private static String resolveArgumentName(String arg) { + return arg.substring(1); + } + + private static boolean isArgumentName(String arg) { + return arg.startsWith("-"); + } +} diff --git a/src/main/java/org/onap/dcae/RestConfCollector.java b/src/main/java/org/onap/dcae/RestConfCollector.java new file mode 100644 index 0000000..1812d23 --- /dev/null +++ b/src/main/java/org/onap/dcae/RestConfCollector.java @@ -0,0 +1,189 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae; + +import io.vavr.collection.Map; +import org.json.JSONArray; +import org.json.JSONObject; +import org.onap.dcae.common.EventData; +import org.onap.dcae.common.EventProcessor; +import org.onap.dcae.common.publishing.DMaaPConfigurationParser; +import org.onap.dcae.common.publishing.EventPublisher; +import org.onap.dcae.common.publishing.PublisherConfig; +import org.onap.dcae.controller.AccessController; +import org.onap.dcae.controller.ConfigLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Lazy; + +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.concurrent.*; + +@SpringBootApplication(exclude = {GsonAutoConfiguration.class, SecurityAutoConfiguration.class}) +public class RestConfCollector { + private static final Logger oplog = LoggerFactory.getLogger("org.onap.dcae.common.output"); + private static final int MAX_THREADS = 20; + private static Logger log = LoggerFactory.getLogger(RestConfCollector.class); + public static LinkedBlockingQueue fProcessingInputQueue; + private static ApplicationSettings properties; + private static ConfigurableApplicationContext context; + private static ConfigLoader configLoader; + private static SpringApplication app; + private static ScheduledFuture scheduleFeatures; + private static ExecutorService executor; + private static ScheduledThreadPoolExecutor scheduledThreadPoolExecutor; + private static EventPublisher eventPublisher; + private static EventProcessor eventProcessor; + + /* List of Controllers */ + private static java.util.Map controllerStore = new ConcurrentHashMap<>(); + + + public static void main(String[] args) { + oplog.info("RestconfController starting"); + app = new SpringApplication(RestConfCollector.class); + properties = new ApplicationSettings(args, CLIUtils::processCmdLine); + scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1); + init(); + app.setAddCommandLineProperties(true); + context = app.run(); + configLoader.updateConfig(); + controllerConfig(properties); + oplog.info("RestConfController running ....."); + } + + + public static void restartApplication() { + Thread thread = new Thread(() -> { + controllerConfigCleanup(); + context.close(); + properties.reloadProperties(); + scheduleFeatures.cancel(true); + init(); + controllerConfig(properties); + context = SpringApplication.run(RestConfCollector.class); + }); + thread.setDaemon(false); + thread.start(); + } + + + private static void init() { + fProcessingInputQueue = new LinkedBlockingQueue<>(properties.maximumAllowedQueuedEvents()); + createConfigLoader(); + createSchedulePoolExecutor(); + createExecutors(); + } + + private static Map getDmapConfig() { + return DMaaPConfigurationParser. + parseToDomainMapping(Paths.get(properties.dMaaPConfigurationFileLocation())).get(); + } + + @Bean + @Lazy + public ApplicationSettings applicationSettings() { + return properties; + } + + @Bean + public LinkedBlockingQueue inputQueue() { + return fProcessingInputQueue; + } + + public static java.util.Map parseStreamIdToStreamHashMapping(String streamId) { + + java.util.Map streamidHash = new HashMap<>(); + String[] list = streamId.split("\\|"); + for (String aList : list) { + String domain = aList.split("=")[0]; + String[] streamIdList = aList.substring(aList.indexOf('=') + 1).split(","); + streamidHash.put(domain, streamIdList); + oplog.info("adding domain " + domain + " count" + streamIdList.length); + } + return streamidHash; + } + + private static void controllerConfig(ApplicationSettings properties) { + oplog.info("Policy received " + properties.rcc_policy()); + if (!properties.rcc_policy().equals("")) { + JSONArray contollers = new JSONArray(properties.rcc_policy()); + for (int i = 0; i < contollers.length(); i++) { + JSONObject controller = contollers.getJSONObject(i); + oplog.info(" object " + controller.toString()); + AccessController acClr = new AccessController(controller, + properties); + controllerStore.put(controller.get("controller_name").toString(), acClr); + oplog.info("Activating controller " + acClr.getCfgInfo().getController_name()); + acClr.activate(); + } + } + } + + private static void controllerConfigCleanup() { + controllerStore.clear(); + } + + public static void handleEvents(EventData ev) throws Exception { + if (!fProcessingInputQueue.offer(ev)) { + throw new Exception(); + } + log.info("RestConfCollector.handleEvents:EVENTS has been published successfully!"); + } + + private static void createConfigLoader() { + log.info("dMaaPConfigurationFileLocation " + properties.dMaaPConfigurationFileLocation() + " " + properties.configurationFileLocation()); + + configLoader = ConfigLoader.create(getEventPublisher()::reconfigure, + Paths.get(properties.dMaaPConfigurationFileLocation()), + properties.configurationFileLocation()); + } + + private static EventPublisher getEventPublisher() { + return EventPublisher.createPublisher(oplog, getDmapConfig()); + } + + private static void createSchedulePoolExecutor() { + scheduleFeatures = scheduledThreadPoolExecutor.scheduleAtFixedRate(configLoader::updateConfig, + 10, + 10, + TimeUnit.MINUTES); + } + + private static void createExecutors() { + eventPublisher = EventPublisher.createPublisher(oplog, getDmapConfig()); + eventProcessor = new EventProcessor(eventPublisher, + parseStreamIdToStreamHashMapping(properties.dMaaPStreamsMapping())); + + executor = Executors.newFixedThreadPool(MAX_THREADS); + for (int i = 0; i < MAX_THREADS; ++i) { + executor.execute(eventProcessor); + } + } +} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/AdditionalHeaderWebTarget.java b/src/main/java/org/onap/dcae/collectors/restconf/common/AdditionalHeaderWebTarget.java deleted file mode 100644 index e814778..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/AdditionalHeaderWebTarget.java +++ /dev/null @@ -1,159 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import javax.ws.rs.client.Invocation; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.Configuration; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.UriBuilder; -import java.net.URI; -import java.util.Map; - -class AdditionalHeaderWebTarget implements WebTarget { - private WebTarget base; - private String token; - private String headerName; - - public AdditionalHeaderWebTarget(WebTarget target, String token, String headerName) { - base = target; - this.token = token; - this.headerName = headerName; - } - - @Override - public Invocation.Builder request() { - return base.request().header(headerName, token); - } - - @Override - public Invocation.Builder request(String... acceptedResponseTypes) { - return base.request().header(headerName, token); - } - - @Override - public Invocation.Builder request(MediaType... acceptedResponseTypes) { - return base.request().header(headerName, token); - } - - @Override - public Configuration getConfiguration() { - return base.getConfiguration(); - } - - @Override - public URI getUri() { - return base.getUri(); - } - - @Override - public UriBuilder getUriBuilder() { - return base.getUriBuilder(); - } - - @Override - public WebTarget path(String path) { - return base.path(path); - } - - @Override - public WebTarget resolveTemplate(String name, Object value) { - return base.resolveTemplate(name, value); - } - - @Override - public WebTarget resolveTemplate(String name, Object value, boolean encodeSlashInPath) { - return base.resolveTemplate(name, value, encodeSlashInPath); - } - - @Override - public WebTarget resolveTemplateFromEncoded(String name, Object value) { - return base.resolveTemplateFromEncoded(name, value); - } - - @Override - public WebTarget resolveTemplates(Map templateValues) { - return base.resolveTemplates(templateValues); - } - - @Override - public WebTarget resolveTemplates(Map templateValues, boolean encodeSlashInPath) { - return base.resolveTemplates(templateValues, encodeSlashInPath); - } - - @Override - public WebTarget resolveTemplatesFromEncoded(Map templateValues) { - return base.resolveTemplatesFromEncoded(templateValues); - } - - @Override - public WebTarget matrixParam(String name, Object... values) { - return base.matrixParam(name, values); - } - - @Override - public WebTarget queryParam(String name, Object... values) { - return base.queryParam(name, values); - } - - @Override - public WebTarget property(String name, Object value) { - return base.property(name, value); - } - - @Override - public WebTarget register(Class componentClass) { - return base.register(componentClass); - } - - @Override - public WebTarget register(Class componentClass, int priority) { - return base.register(componentClass, priority); - } - - @Override - public WebTarget register(Class componentClass, Class... contracts) { - return base.register(componentClass, contracts); - } - - @Override - public WebTarget register(Class componentClass, Map, Integer> contracts) { - return base.register(componentClass, contracts); - } - - @Override - public WebTarget register(Object component) { - return base.register(component); - } - - @Override - public WebTarget register(Object component, int priority) { - return base.register(component, priority); - } - - @Override - public WebTarget register(Object component, Class... contracts) { - return base.register(component, contracts); - } - - @Override - public WebTarget register(Object component, Map, Integer> contracts) { - return base.register(component, contracts); - } -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/AnyNode.java b/src/main/java/org/onap/dcae/collectors/restconf/common/AnyNode.java deleted file mode 100755 index 860fecc..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/AnyNode.java +++ /dev/null @@ -1,132 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import io.vavr.collection.List; -import io.vavr.collection.Set; -import io.vavr.control.Option; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.stream.StreamSupport; - -import static io.vavr.API.Set; - -public class AnyNode { - private static final Logger log = LoggerFactory.getLogger(AnyNode.class); - - private Object obj; - - private AnyNode(Object object) { - this.obj = object; - } - - public static AnyNode fromString(String content) { - return new AnyNode(new JSONObject(content)); - } - - /** - * Returns key set of underlying object. It is assumed that underlying object is of type org.json.JSONObject. - * - * @return key set of underlying objects - */ - public Set keys() { - return Set(asJsonObject().keySet().toArray(new String[]{})); - } - - /** - * Returns value associated with specified key wrapped with AnyValue object. It is assumed that this is of type - * org.json.JSONObject. - * - * @param key for querying value from jsonobject - * @return value associated with specified key - */ - public AnyNode get(String key) { - return new AnyNode(asJsonObject().get(key)); - } - - /** - * Returns string representation of this. If it happens to have null, the value is treated as - * org.json.JSONObject.NULL and "null" string is returned then. - * - * @return string representation of this - */ - public String toString() { - return this.obj.toString(); - } - - /** - * Returns optional of object under specified key, wrapped with AnyNode object. - * If underlying object is not of type org.json.JSONObject - * or underlying object has no given key - * or given key is null - * then Optional.empty will be returned. - * - * @param key for querying value from AnyNode object - * @return optional of object under specified key - */ - public Option getAsOption(String key) { - try { - AnyNode value = get(key); - if ("null".equals(value.toString())) { - return Option.none(); - } - return Option.some(value); - } catch (JSONException ex) { - log.error(ex.getMessage(), ex); - return Option.none(); - } - } - - /** - * Converts underlying object to map representation with map values wrapped with AnyNode object. It is assumed that - * underlying object is of type org.json.JSONObject. - * - * @return converts underlying object to map representation - */ - public List toList() { - return List.ofAll(StreamSupport.stream(((JSONArray) this.obj).spliterator(), false).map(AnyNode::new)); - } - - /** - * Checks if specified key is present in this. It is assumed that this is of type JSONObject. - * - * @param key is used to check presence in anynode object - * @return true if specified key is present in this - */ - public boolean has(String key) { - return !getAsOption(key).isEmpty(); - } - - /** - * Returns as JSONObject. - * - * @return jsonobject - */ - private JSONObject asJsonObject() { - return (JSONObject) this.obj; - } - - -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/AuthType.java b/src/main/java/org/onap/dcae/collectors/restconf/common/AuthType.java deleted file mode 100755 index 2072631..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/AuthType.java +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.dcae.collectors.restconf.common; - -public enum AuthType { - NONE, BASIC, DIGEST, OAUTH, Unspecified; - - public static AuthType fromString(String s) { - if ("basic".equalsIgnoreCase(s)) { - return BASIC; - } - if ("digest".equalsIgnoreCase(s)) { - return DIGEST; - } - if ("oauth".equalsIgnoreCase(s)) { - return OAUTH; - } - if ("none".equalsIgnoreCase(s)) { - return NONE; - } - if ("unspecified".equalsIgnoreCase(s)) { - return Unspecified; - } - throw new IllegalArgumentException("Invalid value for format: " + s); - } -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/Constants.java b/src/main/java/org/onap/dcae/collectors/restconf/common/Constants.java deleted file mode 100755 index 5f8925d..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/Constants.java +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -public class Constants { - public static final String KDEFAULT_TEMP_FILENAME = "templateFileName"; - public static final String KSETTING_REST_API_URL = "restapiUrl"; - public static final String KSETTING_HTTP_METHOD = "httpMethod"; - public static final String KSETTING_RESP_PREFIX = "responsePrefix"; - public static final String KSETTING_SKIP_SENDING = "skipSending"; - public static final String KSETTING_FORMAT = "format"; - public static final String KSETTING_DMAAPCONFIGS = "collector.dmaapfile"; - public static final String[] KDEFAULT_DMAAPCONFIGS = new String[]{"./etc/DmaapConfig.json"}; - public static final String KSETTING_SSE_CONNECT_URL = "sseConnectURL"; - public static final int KDEFAULT_MAXQUEUEDEVENTS = 1024 * 4; - public static final String RESPONSE_CODE = "restapi-result.response-code"; - public static final String OUTPUT_IDENTIFIER = "restapi-result.ietf-subscribed-notifications:output.identifier"; - public static final String RESPONSE_CODE_200 = "200"; - public static final String KCONFIG = "c"; - public static final String KSETTING_UNAME = "restapiUser"; - public static final String KSETTING_PASSWORD = "restapiPassword"; - public static final String KSETTING_TRUST_STORE_FILENAME = "trustStoreFileName"; - public static final String KSETTING_TRUST_STORE_PASSWORD = "trustStorePassword"; - public static final String KSETTING_KEY_STORE_FILENAME = "keyStoreFileName"; - public static final String KSETTING_KEY_STORE_PASSWORD = "keyStorePassword"; -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/DataChangeEventListener.java b/src/main/java/org/onap/dcae/collectors/restconf/common/DataChangeEventListener.java deleted file mode 100755 index 98bb74a..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/DataChangeEventListener.java +++ /dev/null @@ -1,51 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import org.glassfish.jersey.media.sse.EventListener; -import org.glassfish.jersey.media.sse.InboundEvent; -import org.json.JSONArray; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DataChangeEventListener implements EventListener { - private static final Logger log = LoggerFactory.getLogger(DataChangeEventListener.class); - private RestConfContext ctx; - - public DataChangeEventListener(RestConfContext ctx) { - this.ctx = ctx; - } - - @Override - public void onEvent(InboundEvent event) { - JSONArray jsonArrayMod; - log.info("On SSE Event is received"); - String s = event.readData(); - JSONObject jsonObj = new JSONObject(s); - jsonArrayMod = new JSONArray().put(jsonObj); - try { - RestConfProc.handleEvents(jsonArrayMod); - } catch (Exception e) { - log.error("Error in DataChangeEventListener ", e.getMessage()); - } - } -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/EventProcessor.java b/src/main/java/org/onap/dcae/collectors/restconf/common/EventProcessor.java deleted file mode 100755 index 763cece..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/EventProcessor.java +++ /dev/null @@ -1,88 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - - -import org.json.JSONObject; -import org.onap.dcae.collectors.restconf.common.event.publishing.EventPublisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -public class EventProcessor implements Runnable { - private static final Logger log = LoggerFactory.getLogger(EventProcessor.class); - - static Map streamidHash = new HashMap<>(); - public JSONObject event; - private EventPublisher eventPublisher; - - public EventProcessor(EventPublisher eventPublisher) { - this.eventPublisher = eventPublisher; - streamidHash = parseStreamIdToStreamHashMapping(new RestConfProc().streamID); - } - - private Map parseStreamIdToStreamHashMapping(String streamId) { - Map streamidHash = new HashMap<>(); - String[] list = streamId.split("\\|"); - for (String aList : list) { - String domain = aList.split("=")[0]; - String[] streamIdList = aList.substring(aList.indexOf('=') + 1).split(","); - streamidHash.put(domain, streamIdList); - } - return streamidHash; - } - - @Override - public void run() { - try { - - while (true) { - event = RestConfProc.fProcessingInputQueue.take(); - // As long as the producer is running we remove elements from - // the queue. - log.info("QueueSize:" + RestConfProc.fProcessingInputQueue.size() + "\tEventProcessor\tRemoving element: " + - event); - String[] streamIdList = streamidHash.get("route"); - log.debug("streamIdList:" + Arrays.toString(streamIdList)); - - if (streamIdList.length == 0) { - log.error("No StreamID defined for publish - Message dropped" + event); - } else { - sendEventsToStreams(streamIdList); - } - log.debug("Event published" + event); - } - } catch (Exception e) { - log.error("EventProcessor InterruptedException" + e.getMessage()); - Thread.currentThread().interrupt(); - } - } - - private void sendEventsToStreams(String[] streamIdList) { - for (String aStreamIdList : streamIdList) { - log.info("Invoking publisher for streamId:" + aStreamIdList); - eventPublisher.sendEvent(event, aStreamIdList); - } - } -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/Format.java b/src/main/java/org/onap/dcae/collectors/restconf/common/Format.java deleted file mode 100755 index 710a576..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/Format.java +++ /dev/null @@ -1,38 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -public enum Format { - JSON, XML, NONE; - - public static Format fromString(String s) { - if ("json".equalsIgnoreCase(s)) { - return JSON; - } - if ("xml".equalsIgnoreCase(s)) { - return XML; - } - if ("none".equalsIgnoreCase(s)) { - return NONE; - } - throw new IllegalArgumentException("Invalid value for format: " + s); - } -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/HttpMethod.java b/src/main/java/org/onap/dcae/collectors/restconf/common/HttpMethod.java deleted file mode 100755 index b5c8e71..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/HttpMethod.java +++ /dev/null @@ -1,47 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -public enum HttpMethod { - GET, POST, PUT, DELETE, PATCH; - - public static HttpMethod fromString(String s) { - if (s == null) { - return null; - } - if ("get".equalsIgnoreCase(s)) { - return GET; - } - if ("post".equalsIgnoreCase(s)) { - return POST; - } - if ("put".equalsIgnoreCase(s)) { - return PUT; - } - if ("delete".equalsIgnoreCase(s)) { - return DELETE; - } - if ("patch".equalsIgnoreCase(s)) { - return PATCH; - } - throw new IllegalArgumentException("Invalid value for HTTP Method: " + s); - } -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/HttpResponse.java b/src/main/java/org/onap/dcae/collectors/restconf/common/HttpResponse.java deleted file mode 100755 index 01505c3..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/HttpResponse.java +++ /dev/null @@ -1,30 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import javax.ws.rs.core.MultivaluedMap; - -public class HttpResponse { - public int code; - public String message; - public String body; - public MultivaluedMap headers; -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/JsonParser.java b/src/main/java/org/onap/dcae/collectors/restconf/common/JsonParser.java deleted file mode 100755 index 16a5b7d..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/JsonParser.java +++ /dev/null @@ -1,92 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import org.codehaus.jettison.json.JSONArray; -import org.codehaus.jettison.json.JSONException; -import org.codehaus.jettison.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import static com.google.common.base.Preconditions.checkNotNull; - -public class JsonParser { - - private static final Logger log = LoggerFactory.getLogger(JsonParser.class); - - private JsonParser() { - // Preventing instantiation of the same. - } - - @SuppressWarnings("unchecked") - public static Map convertToProperties(String s) - throws Exception { - - checkNotNull(s, "Input should not be null."); - - try { - JSONObject json = new JSONObject(s); - Map wm = new HashMap<>(); - Iterator ii = json.keys(); - while (ii.hasNext()) { - String key1 = ii.next(); - wm.put(key1, json.get(key1)); - } - - Map mm = new HashMap<>(); - - while (!wm.isEmpty()) - for (String key : new ArrayList<>(wm.keySet())) { - Object o = wm.get(key); - wm.remove(key); - - if (o instanceof Boolean || o instanceof Number || o instanceof String) { - mm.put(key, o.toString()); - - log.info("Added property: {} : {}", key, o.toString()); - } else if (o instanceof JSONObject) { - JSONObject jo = (JSONObject) o; - Iterator i = jo.keys(); - while (i.hasNext()) { - String key1 = i.next(); - wm.put(key + "." + key1, jo.get(key1)); - } - } else if (o instanceof JSONArray) { - JSONArray ja = (JSONArray) o; - mm.put(key + "_length", String.valueOf(ja.length())); - - log.info("Added property: {}_length: {}", key, String.valueOf(ja.length())); - - for (int i = 0; i < ja.length(); i++) - wm.put(key + '[' + i + ']', ja.get(i)); - } - } - return mm; - } catch (JSONException e) { - throw new Exception("Unable to convert JSON to properties" + e.getLocalizedMessage(), e); - } - } -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/Parameters.java b/src/main/java/org/onap/dcae/collectors/restconf/common/Parameters.java deleted file mode 100755 index b0f7dfc..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/Parameters.java +++ /dev/null @@ -1,52 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import java.util.Set; - -public class Parameters { - public String templateFileName; - public String restapiUrl; - public String restapiUser; - public String restapiPassword; - public Format format; - public String contentType; - public HttpMethod httpMethod; - public String responsePrefix; - public Set listNameList; - public boolean skipSending; - public boolean convertResponse; - public String keyStoreFileName; - public String keyStorePassword; - public String trustStoreFileName; - public String trustStorePassword; - public boolean ssl; - public String customHttpHeaders; - public String partner; - public Boolean dumpHeaders; - public String requestBody; - public String oAuthConsumerKey; - public String oAuthConsumerSecret; - public String oAuthSignatureMethod; - public String oAuthVersion; - public AuthType authtype; - public Boolean returnRequestPayload; -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/RestConfCollector.java b/src/main/java/org/onap/dcae/collectors/restconf/common/RestConfCollector.java deleted file mode 100755 index 508cf66..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/RestConfCollector.java +++ /dev/null @@ -1,72 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import com.att.nsa.cmdLine.NsaCommandLineUtil; -import com.att.nsa.drumlin.service.framework.DrumlinServlet; -import com.att.nsa.drumlin.till.nv.impl.nvPropertiesFile; -import com.att.nsa.drumlin.till.nv.impl.nvReadableStack; -import com.att.nsa.drumlin.till.nv.impl.nvReadableTable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.URL; -import java.util.Map; - -public class RestConfCollector { - - public static final Logger eplog = LoggerFactory.getLogger("org.onap.restconf.common.error"); - - public static void main(String[] args) { - try { - final Map argMap = NsaCommandLineUtil.processCmdLine(args, true); - final String config = NsaCommandLineUtil.getSetting(argMap, Constants.KCONFIG, "collector.properties"); - final URL settingStream = DrumlinServlet.findStream(config, RestConfCollector.class); - - final nvReadableStack settings = new nvReadableStack(); - settings.push(new nvPropertiesFile(settingStream)); - settings.push(new nvReadableTable(argMap)); - - RestConfProc restConfProc = new RestConfProc(settings); - Map paraMap = restConfProc.getParaMap(); - String restApiURL = paraMap.get(Constants.KSETTING_REST_API_URL); - String sseEventsURL = paraMap.get(Constants.KSETTING_SSE_CONNECT_URL); - String trustStoreFileName = paraMap.get(Constants.KSETTING_TRUST_STORE_FILENAME); - String keyStoreFileName = paraMap.get(Constants.KSETTING_KEY_STORE_FILENAME); - String[] listRestApiURL = restApiURL.split(";"); - String[] listSseEventsURL = sseEventsURL.split(";"); - String[] listTrustStoreFileName = trustStoreFileName.split(";"); - String[] listKeyStoreFileName = keyStoreFileName.split(";"); - for (int i = 0; i < listRestApiURL.length; i++) { - paraMap.put(Constants.KSETTING_REST_API_URL, "https://" + listRestApiURL[i] + - "/restconf/operations/ietf-subscribed-notifications:establish-subscription"); - paraMap.put(Constants.KSETTING_SSE_CONNECT_URL, listSseEventsURL[i]); - paraMap.put(Constants.KSETTING_TRUST_STORE_FILENAME, listTrustStoreFileName[i]); - paraMap.put(Constants.KSETTING_KEY_STORE_FILENAME, listKeyStoreFileName[i]); - restConfProc.establishSubscription(paraMap, restConfProc.getCtx(), listRestApiURL[i]); - } - - } catch (Exception e) { - RestConfCollector.eplog.error("Fatal error during application startup", e); - throw new RuntimeException(e); - } - } -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/RestConfContext.java b/src/main/java/org/onap/dcae/collectors/restconf/common/RestConfContext.java deleted file mode 100755 index e1ea001..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/RestConfContext.java +++ /dev/null @@ -1,51 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import java.util.HashMap; -import java.util.Set; - -public class RestConfContext { - private HashMap attributes; - - public RestConfContext() { - attributes = new HashMap<>(); - } - - public String getAttribute(String name) { - return attributes.getOrDefault(name, null); - } - - public void setAttribute(String name, String value) { - if (value == null) { - if (attributes.containsKey(name)) { - attributes.remove(name); - } - } else { - attributes.put(name, value); - } - } - - public Set getAttributeKeySet() { - return attributes.keySet(); - } - -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/RestConfProc.java b/src/main/java/org/onap/dcae/collectors/restconf/common/RestConfProc.java deleted file mode 100755 index cfebe3b..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/RestConfProc.java +++ /dev/null @@ -1,336 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import com.att.nsa.drumlin.till.nv.rrNvReadable; -import org.glassfish.jersey.media.sse.EventSource; -import org.glassfish.jersey.media.sse.SseFeature; -import org.json.JSONArray; -import org.json.JSONObject; -import org.onap.dcae.collectors.restconf.common.event.publishing.DMaaPConfigurationParser; -import org.onap.dcae.collectors.restconf.common.event.publishing.EventPublisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.HttpHeaders; -import java.nio.file.Paths; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.Base64; - -import static org.onap.dcae.collectors.restconf.common.RestapiCallNodeUtil.getParameters; -import static org.onap.dcae.collectors.restconf.common.RestapiCallNodeUtil.addAuthType; - -public class RestConfProc { - - private static final Logger log = LoggerFactory.getLogger(RestConfProc.class); - - public static String format; - - private static RestConfContext ctx = new RestConfContext(); - - private static final Logger oplog = LoggerFactory.getLogger("org.onap.restconf.common.output"); - - private Map runnableInfo = new ConcurrentHashMap<>(); - - private final Map paraMap = new HashMap<>(); - private static String cambriaConfigFile; - - public static LinkedBlockingQueue fProcessingInputQueue; - - public static String streamID; - private ExecutorService executor = Executors.newCachedThreadPool(); - - public RestConfProc() { - } - - private void parseInputParameters(rrNvReadable settings) { - String tempFileName; - String restApiUrl; - String httpMetthod; - String respPrefix; - String skipSending; - String sseConnectUrl; - String restapiUser; - String restapiPassword; - String trustStoreFileName; - String trustStorePassword; - String keyStoreFileName; - String keyStorePassword; - String[] currentConfigFile; - - currentConfigFile = settings.getStrings(Constants.KSETTING_DMAAPCONFIGS, Constants.KDEFAULT_DMAAPCONFIGS); - cambriaConfigFile = currentConfigFile[0]; - - tempFileName = settings.getString(Constants.KDEFAULT_TEMP_FILENAME, null); - restApiUrl = settings.getString(Constants.KSETTING_REST_API_URL, null); - httpMetthod = settings.getString(Constants.KSETTING_HTTP_METHOD, null); - respPrefix = settings.getString(Constants.KSETTING_RESP_PREFIX, null); - skipSending = settings.getString(Constants.KSETTING_SKIP_SENDING, null); - sseConnectUrl = settings.getString(Constants.KSETTING_SSE_CONNECT_URL, null); - restapiUser = settings.getString(Constants.KSETTING_UNAME, null); - restapiPassword = settings.getString(Constants.KSETTING_PASSWORD, null); - trustStoreFileName = settings.getString(Constants.KSETTING_TRUST_STORE_FILENAME, null); - trustStorePassword = settings.getString(Constants.KSETTING_TRUST_STORE_PASSWORD, null); - keyStoreFileName = settings.getString(Constants.KSETTING_KEY_STORE_FILENAME, null); - keyStorePassword = settings.getString(Constants.KSETTING_KEY_STORE_PASSWORD, null); - format = settings.getString(Constants.KSETTING_FORMAT, null); - streamID = "route=route_failure"; - - paraMap.put(Constants.KDEFAULT_TEMP_FILENAME, tempFileName); - paraMap.put(Constants.KSETTING_REST_API_URL, restApiUrl); - paraMap.put(Constants.KSETTING_HTTP_METHOD, httpMetthod); - paraMap.put(Constants.KSETTING_RESP_PREFIX, respPrefix); - paraMap.put(Constants.KSETTING_SKIP_SENDING, skipSending); - paraMap.put(Constants.KSETTING_SSE_CONNECT_URL, sseConnectUrl); - paraMap.put(Constants.KSETTING_FORMAT, format); - paraMap.put(Constants.KSETTING_UNAME, restapiUser); - paraMap.put(Constants.KSETTING_PASSWORD, restapiPassword); - paraMap.put(Constants.KSETTING_TRUST_STORE_FILENAME, trustStoreFileName); - paraMap.put(Constants.KSETTING_TRUST_STORE_PASSWORD, trustStorePassword); - paraMap.put(Constants.KSETTING_KEY_STORE_FILENAME, keyStoreFileName); - paraMap.put(Constants.KSETTING_KEY_STORE_PASSWORD, keyStorePassword); - - ctx.setAttribute("prop.encoding-json", "encoding-json"); - ctx.setAttribute("restapi-result.response-code", "200"); - ctx.setAttribute("restapi-result.ietf-subscribed-notifications:output.identifier", "100"); - } - - public RestConfProc(rrNvReadable settings) { - - parseInputParameters(settings); - - fProcessingInputQueue = new LinkedBlockingQueue<>(Constants.KDEFAULT_MAXQUEUEDEVENTS); - - EventProcessor ep = new EventProcessor(EventPublisher.createPublisher(oplog, - DMaaPConfigurationParser - .parseToDomainMapping(Paths.get(cambriaConfigFile)) - .get())); - ExecutorService executor = Executors.newFixedThreadPool(20); - for (int i = 0; i < 20; ++i) { - executor.execute(ep); - } - } - - /** - * To establish a subscription with controller by sending HTTP request - * - * @param paramMap holds the input configuration - * @param ctx restconf context - * @param url url to send subscription request - * @throws Exception exception - */ - public void establishSubscription(Map paramMap, - RestConfContext ctx, - String url) throws Exception { - - RestapiCallNode restApiCallNode = new RestapiCallNode(); - - Map params = new HashMap<>(); - params.put("restapiUrl", "https://" + url + "/controller/v2/tokens"); - params.put("httpMethod", "post"); - params.put("templateFileName", "./etc/access-token.json"); - params.put("skipSending", "false"); - params.put("format", "json"); - params.put("restapiUser", "test123"); - params.put("restapiPassword", "Changeme_123"); - params.put(Constants.KSETTING_TRUST_STORE_FILENAME, - paramMap.get(Constants.KSETTING_TRUST_STORE_FILENAME)); - params.put(Constants.KSETTING_TRUST_STORE_PASSWORD, "adminadmin"); - params.put(Constants.KSETTING_KEY_STORE_FILENAME, - paramMap.get(Constants.KSETTING_KEY_STORE_FILENAME)); - params.put(Constants.KSETTING_KEY_STORE_PASSWORD, "adminadmin"); - - String httpResponse = null; - try { - restApiCallNode.sendRequest(params, ctx, null); - httpResponse = ctx.getAttribute("httpResponse"); - JSONObject jsonObj = new JSONObject(httpResponse); - JSONObject data = jsonObj.getJSONObject("data"); - String tokenId = data.get("token_id").toString(); - paramMap.put("customHttpHeaders", "X-ACCESS-TOKEN=" + tokenId); - paramMap.put("TokenId", tokenId); - } catch (Exception e) { - log.info("Access token is not supported" + e.getMessage()); - log.info("http response" + httpResponse); - } - - restApiCallNode.sendRequest(paramMap, ctx, null); - - establishPersistentConnection(paramMap, ctx); - } - - /** - * To establish persistent connection after receiving successful subscription response from controller - * - * @param paramMap holds the input configuration - * @param ctx restconf context - */ - public void establishPersistentConnection(Map paramMap, RestConfContext ctx) { - - // check whether response is ok - if (ctx.getAttribute(Constants.RESPONSE_CODE).equals(Constants.RESPONSE_CODE_200)) { - - String id = ctx.getAttribute(Constants.OUTPUT_IDENTIFIER); - - String url = paramMap.get(Constants.KSETTING_SSE_CONNECT_URL); - - PersistentConnection connection = new PersistentConnection(url, ctx, paramMap); - runnableInfo.put(id, connection); - executor.execute(connection); - } else { - // error response is already updated in ctx - log.info("Failed to subscribe"); - } - } - - /** - * Get input parameter map - * - * @return input parameters map - */ - public Map getParaMap() { - return paraMap; - } - - - /** - * Get restConf context which has information about message encoding type - * - * @return restconf context - */ - public RestConfContext getCtx() { - return ctx; - } - - public class PersistentConnection implements Runnable { - private String url; - private RestConfContext ctx; - private Map paramMap; - private volatile boolean running = true; - - public PersistentConnection(String url, RestConfContext ctx, Map paramMap) { - this.url = url; - this.ctx = ctx; - this.paramMap = paramMap; - } - - @Override - public void run() { - Parameters p = null; - try { - p = getParameters(paramMap); - } catch (Exception e) { - log.error("Exception occured!", e); - Thread.currentThread().interrupt(); - } - - Client client = ignoreSslClient().register(SseFeature.class); - WebTarget target = addAuthType(client, p).target(url); - String token = paramMap.get("TokenId"); - String headerName = "X-ACCESS-TOKEN"; - if (token == null) { - headerName = HttpHeaders.AUTHORIZATION; - if(null!=p) { - token = getAuthorizationToken(p.restapiUser, p.restapiPassword); - } - } - AdditionalHeaderWebTarget newTarget = new AdditionalHeaderWebTarget(target, token, headerName); - EventSource eventSource = EventSource.target(newTarget).build(); - eventSource.register(new DataChangeEventListener(ctx)); - eventSource.open(); - log.debug("Connected to SSE source"); - while (running) { - try { - log.debug("SSE state " + eventSource.isOpen()); - Thread.sleep(5000); - } catch (InterruptedException ie) { - log.debug("Exception: " + ie.getMessage()); - Thread.currentThread().interrupt(); - } - } - eventSource.close(); - log.info("Closed connection to SSE source"); - } - } - - private String getAuthorizationToken(String userName, String password) { - return "Basic " + Base64.getEncoder().encodeToString(( - userName + ":" + password).getBytes()); - } - - /** - * To process the array of events which are received from controller - * - * @param a JSONArray - * @throws Exception exception - */ - public static void handleEvents(JSONArray a) throws Exception { - for (int i = 0; i < a.length(); i++) { - if (!fProcessingInputQueue.offer(a.getJSONObject(i))) { - throw new Exception(); - } - } - log.debug("RestConfCollector.handleEvents:EVENTS has been published successfully!"); - } - - private Client ignoreSslClient() { - SSLContext sslcontext = null; - - try { - sslcontext = SSLContext.getInstance("TLS"); - sslcontext.init(null, new TrustManager[]{new X509TrustManager() { - @Override - public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { - } - - @Override - public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - } }, new java.security.SecureRandom()); - } catch (NoSuchAlgorithmException | KeyManagementException e) { - throw new IllegalStateException(e); - } - - return ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier((s1, s2) -> true).build(); - } -} - - diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/RestapiCallNode.java b/src/main/java/org/onap/dcae/collectors/restconf/common/RestapiCallNode.java deleted file mode 100755 index 33abca9..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/RestapiCallNode.java +++ /dev/null @@ -1,510 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientHandlerException; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.UniformInterfaceException; -import com.sun.jersey.api.client.WebResource; -import com.sun.jersey.api.client.config.ClientConfig; -import com.sun.jersey.api.client.config.DefaultClientConfig; -import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; -import com.sun.jersey.api.client.filter.HTTPDigestAuthFilter; -import com.sun.jersey.client.urlconnection.HTTPSProperties; -import com.sun.jersey.oauth.client.OAuthClientFilter; -import com.sun.jersey.oauth.signature.OAuthParameters; -import com.sun.jersey.oauth.signature.OAuthSecrets; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.ws.rs.core.EntityTag; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.UriBuilder; -import java.io.FileInputStream; -import java.io.IOException; -import java.net.SocketException; -import java.net.URI; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.KeyStore; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.onap.dcae.collectors.restconf.common.RestapiCallNodeUtil.getParameters; -import static org.onap.dcae.collectors.restconf.common.RestapiCallNodeUtil.parseParam; - -public class RestapiCallNode { - private static final Logger log = LoggerFactory.getLogger(RestapiCallNode.class); - - public void sendRequest(Map paramMap, RestConfContext ctx, Integer retryCount) throws Exception { - RetryPolicy retryPolicy = null; - HttpResponse r = new HttpResponse(); - try { - Parameters p = getParameters(paramMap); - String pp = p.responsePrefix != null ? p.responsePrefix + '.' : ""; - String req = null; - if (p.templateFileName != null) { - String reqTemplate = readFile(p.templateFileName); - req = buildXmlJsonRequest(ctx, reqTemplate, p.format); - } else if (p.requestBody != null) { - req = p.requestBody; - } - - r = sendHttpRequest(req, p); - setResponseStatus(ctx, p.responsePrefix, r); - - if (p.dumpHeaders && r.headers != null) { - for (Map.Entry> a : r.headers.entrySet()) { - ctx.setAttribute(pp + "header." + a.getKey(), StringUtils.join(a.getValue(), ",")); - } - } - - if (p.returnRequestPayload && req != null) { - ctx.setAttribute(pp + "httpRequest", req); - } - - if (r.body != null && r.body.trim().length() > 0) { - ctx.setAttribute(pp + "httpResponse", r.body); - - if (p.convertResponse) { - Map mm = null; - if (p.format == Format.XML) { - mm = XmlParser.convertToProperties(r.body, p.listNameList); - } else if (p.format == Format.JSON) { - mm = JsonParser.convertToProperties(r.body); - } - - if (mm != null) { - for (Map.Entry entry : mm.entrySet()) - ctx.setAttribute(pp + entry.getKey(), entry.getValue()); - } - } - } - } catch (Exception e) { - boolean shouldRetry = false; - if (e.getCause().getCause() instanceof SocketException) { - shouldRetry = true; - } - - log.error("Error sending the request: " + e.getMessage(), e); - String prefix = parseParam(paramMap, "responsePrefix", false, null); - if (null == retryPolicy || !shouldRetry) { - setFailureResponseStatus(ctx, prefix, e.getMessage(), r); - } else { - if (retryCount == null) { - retryCount = 0; - } - String retryMessage = retryCount + " attempts were made out of " + retryPolicy.getMaximumRetries() + - " maximum retries."; - log.debug(retryMessage); - try { - retryCount = retryCount + 1; - if (retryCount < retryPolicy.getMaximumRetries() + 1) { - URI uri = new URI(paramMap.get("restapiUrl")); - String hostname = uri.getHost(); - String retryString = retryPolicy.getNextHostName(uri.toString()); - URI uriTwo = new URI(retryString); - URI retryUri = UriBuilder.fromUri(uri).host(uriTwo.getHost()).port(uriTwo.getPort()).scheme( - uriTwo.getScheme()).build(); - paramMap.put("restapiUrl", retryUri.toString()); - log.debug("URL was set to {}", retryUri.toString()); - log.debug("Failed to communicate with host {}. Request will be re-attempted using the host {}.", - hostname, retryString); - log.debug("This is retry attempt {} out of {}", retryCount, retryPolicy.getMaximumRetries()); - sendRequest(paramMap, ctx, retryCount); - } else { - log.debug("Maximum retries reached, calling setFailureResponseStatus."); - setFailureResponseStatus(ctx, prefix, e.getMessage(), r); - } - } catch (Exception ex) { - log.error("Could not attempt retry.", ex); - String retryErrorMessage = - "Retry attempt has failed. No further retry shall be attempted, calling " + - "setFailureResponseStatus."; - setFailureResponseStatus(ctx, prefix, retryErrorMessage, r); - } - } - } - - if (r != null && r.code >= 300) { - throw new Exception(String.valueOf(r.code) + ": " + r.message); - } - } - - protected String buildXmlJsonRequest(RestConfContext ctx, String template, Format format) throws Exception { - log.info("Building {} started", format); - long t1 = System.currentTimeMillis(); - - template = expandRepeats(ctx, template, 1); - - Map mm = new HashMap<>(); - for (String s : ctx.getAttributeKeySet()) - mm.put(s, ctx.getAttribute(s)); - StringBuilder ss = new StringBuilder(); - int i = 0; - while (i < template.length()) { - int i1 = template.indexOf("${", i); - if (i1 < 0) { - ss.append(template.substring(i)); - break; - } - - int i2 = template.indexOf('}', i1 + 2); - if (i2 < 0) { - throw new Exception("Template error: Matching } not found"); - } - - String var1 = template.substring(i1 + 2, i2); - String value1 = format == Format.XML ? XmlJsonUtil.getXml(mm, var1) : XmlJsonUtil.getJson(mm, var1); - if (value1 == null || value1.trim().length() == 0) { - // delete the whole element (line) - int i3 = template.lastIndexOf('\n', i1); - if (i3 < 0) { - i3 = 0; - } - int i4 = template.indexOf('\n', i1); - if (i4 < 0) { - i4 = template.length(); - } - - if (i < i3) { - ss.append(template.substring(i, i3)); - } - i = i4; - } else { - ss.append(template.substring(i, i1)).append(value1); - i = i2 + 1; - } - } - - String req = format == Format.XML - ? XmlJsonUtil.removeEmptyStructXml(ss.toString()) : XmlJsonUtil.removeEmptyStructJson(ss.toString()); - - if (format == Format.JSON) { - req = XmlJsonUtil.removeLastCommaJson(req); - } - - long t2 = System.currentTimeMillis(); - log.info("Building {} completed. Time: {}", format, (t2 - t1)); - - return req; - } - - protected String expandRepeats(RestConfContext ctx, String template, int level) throws Exception { - StringBuilder newTemplate = new StringBuilder(); - int k = 0; - while (k < template.length()) { - int i1 = template.indexOf("${repeat:", k); - if (i1 < 0) { - newTemplate.append(template.substring(k)); - break; - } - - int i2 = template.indexOf(':', i1 + 9); - if (i2 < 0) { - throw new Exception( - "Template error: Context variable name followed by : is required after repeat"); - } - - // Find the closing }, store in i3 - int nn = 1; - int i3 = -1; - int i = i2; - while (nn > 0 && i < template.length()) { - i3 = template.indexOf('}', i); - if (i3 < 0) { - throw new Exception("Template error: Matching } not found"); - } - int i32 = template.indexOf('{', i); - if (i32 >= 0 && i32 < i3) { - nn++; - i = i32 + 1; - } else { - nn--; - i = i3 + 1; - } - } - - String var1 = template.substring(i1 + 9, i2); - String value1 = ctx.getAttribute(var1); - log.info(" {}:{}", var1, value1); - int n = 0; - try { - n = Integer.parseInt(value1); - } catch (NumberFormatException e) { - log.info("value1 not set or not a number, n will remain set at zero"); - } - - newTemplate.append(template.substring(k, i1)); - - String rpt = template.substring(i2 + 1, i3); - - for (int ii = 0; ii < n; ii++) { - String ss = rpt.replaceAll("\\[\\$\\{" + level + "\\}\\]", "[" + ii + "]"); - if (ii == n - 1 && ss.trim().endsWith(",")) { - int i4 = ss.lastIndexOf(','); - if (i4 > 0) { - ss = ss.substring(0, i4) + ss.substring(i4 + 1); - } - } - newTemplate.append(ss); - } - - k = i3 + 1; - } - - if (k == 0) { - return newTemplate.toString(); - } - - return expandRepeats(ctx, newTemplate.toString(), level + 1); - } - - protected String readFile(String fileName) throws Exception { - try { - byte[] encoded = Files.readAllBytes(Paths.get(fileName)); - return new String(encoded, "UTF-8"); - } catch (IOException | SecurityException e) { - throw new Exception("Unable to read file " + fileName + e.getLocalizedMessage(), e); - } - } - - protected Client addAuthType(Client client, Parameters p) throws Exception { - if (p.authtype == AuthType.Unspecified) { - if (p.restapiUser != null && p.restapiPassword != null) { - client.addFilter(new HTTPBasicAuthFilter(p.restapiUser, p.restapiPassword)); - } else if (p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null - && p.oAuthSignatureMethod != null) { - OAuthParameters params = new OAuthParameters() - .signatureMethod(p.oAuthSignatureMethod) - .consumerKey(p.oAuthConsumerKey) - .version(p.oAuthVersion); - - OAuthSecrets secrets = new OAuthSecrets() - .consumerSecret(p.oAuthConsumerSecret); - client.addFilter(new OAuthClientFilter(client.getProviders(), params, secrets)); - } - } else { - if (p.authtype == AuthType.DIGEST) { - if (p.restapiUser != null && p.restapiPassword != null) { - client.addFilter(new HTTPDigestAuthFilter(p.restapiUser, p.restapiPassword)); - } else { - throw new Exception("oAUTH authentication type selected but all restapiUser and restapiPassword " + - "parameters doesn't exist", new Throwable()); - } - } else if (p.authtype == AuthType.BASIC) { - if (p.restapiUser != null && p.restapiPassword != null) { - client.addFilter(new HTTPBasicAuthFilter(p.restapiUser, p.restapiPassword)); - } else { - throw new Exception("oAUTH authentication type selected but all restapiUser and restapiPassword " + - "parameters doesn't exist", new Throwable()); - } - } else if (p.authtype == AuthType.OAUTH) { - if (p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null && p.oAuthSignatureMethod != null) { - OAuthParameters params = new OAuthParameters() - .signatureMethod(p.oAuthSignatureMethod) - .consumerKey(p.oAuthConsumerKey) - .version(p.oAuthVersion); - - OAuthSecrets secrets = new OAuthSecrets() - .consumerSecret(p.oAuthConsumerSecret); - client.addFilter(new OAuthClientFilter(client.getProviders(), params, secrets)); - } else { - throw new Exception("oAUTH authentication type selected but all oAuthConsumerKey, oAuthConsumerSecret " + - "and oAuthSignatureMethod parameters doesn't exist", new Throwable()); - } - } - } - return client; - } - - protected HttpResponse sendHttpRequest(String request, Parameters p) throws Exception { - - ClientConfig config = new DefaultClientConfig(); - SSLContext ssl = null; - if (p.ssl && p.restapiUrl.startsWith("https")) { - ssl = createSSLContext(p); - } - if (ssl != null) { - HostnameVerifier hostnameVerifier = (hostname, session) -> true; - - config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, - new HTTPSProperties(hostnameVerifier, ssl)); - } - - logProperties(config.getProperties()); - - Client client = Client.create(config); - client.setConnectTimeout(5000); - WebResource webResource = addAuthType(client, p).resource(p.restapiUrl); - - log.info("Sending request:"); - log.info(request); - long t1 = System.currentTimeMillis(); - - HttpResponse r = new HttpResponse(); - r.code = 200; - - if (!p.skipSending) { - String tt = p.format == Format.XML ? "application/xml" : "application/json"; - String tt1 = tt + ";charset=UTF-8"; - if (p.contentType != null) { - tt = p.contentType; - tt1 = p.contentType; - } - - WebResource.Builder webResourceBuilder = webResource.accept(tt).type(tt1); - if (p.format == Format.NONE) { - webResourceBuilder = webResource.header("", ""); - } - - if (p.customHttpHeaders != null && p.customHttpHeaders.length() > 0) { - String[] keyValuePairs = p.customHttpHeaders.split(","); - for (String singlePair : keyValuePairs) { - int equalPosition = singlePair.indexOf('='); - webResourceBuilder.header(singlePair.substring(0, equalPosition), - singlePair.substring(equalPosition + 1, singlePair.length())); - } - } - - webResourceBuilder.header("X-ECOMP-RequestID", org.slf4j.MDC.get("X-ECOMP-RequestID")); - - ClientResponse response; - - try { - response = webResourceBuilder.method(p.httpMethod.toString(), ClientResponse.class, request); - } catch (UniformInterfaceException | ClientHandlerException e) { - throw new Exception("Exception while sending http request to client " - + e.getLocalizedMessage(), e); - } - - r.code = response.getStatus(); - r.headers = response.getHeaders(); - EntityTag etag = response.getEntityTag(); - if (etag != null) { - r.message = etag.getValue(); - } - if (response.hasEntity() && r.code != 204) { - r.body = response.getEntity(String.class); - } - } - - long t2 = System.currentTimeMillis(); - log.info("Response received. Time: {}", (t2 - t1)); - log.info("HTTP response code: {}", r.code); - log.info("HTTP response message: {}", r.message); - logHeaders(r.headers); - log.info("HTTP response: {}", r.body); - - return r; - } - - protected void setFailureResponseStatus(RestConfContext ctx, String prefix, String errorMessage, - HttpResponse resp) { - resp.code = 500; - resp.message = errorMessage; - String pp = prefix != null ? prefix + '.' : ""; - ctx.setAttribute(pp + "response-code", String.valueOf(resp.code)); - ctx.setAttribute(pp + "response-message", resp.message); - } - - protected void setResponseStatus(RestConfContext ctx, String prefix, HttpResponse r) { - String pp = prefix != null ? prefix + '.' : ""; - ctx.setAttribute(pp + "response-code", String.valueOf(r.code)); - ctx.setAttribute(pp + "response-message", r.message); - } - - protected SSLContext createSSLContext(Parameters p) { - try (FileInputStream in = new FileInputStream(p.keyStoreFileName)) { - System.setProperty("jsse.enableSNIExtension", "false"); - System.setProperty("javax.net.ssl.trustStore", p.trustStoreFileName); - System.setProperty("javax.net.ssl.trustStorePassword", p.trustStorePassword); - - HttpsURLConnection.setDefaultHostnameVerifier((string, ssls) -> true); - - KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - KeyStore ks = KeyStore.getInstance("PKCS12"); - char[] pwd = p.keyStorePassword.toCharArray(); - ks.load(in, pwd); - kmf.init(ks, pwd); - - SSLContext ctx = SSLContext.getInstance("TLS"); - ctx.init(kmf.getKeyManagers(), null, null); - return ctx; - } catch (Exception e) { - log.error("Error creating SSLContext: {}", e.getMessage(), e); - } - return null; - } - - protected void logProperties(Map mm) { - List ll = new ArrayList<>(); - for (Object o : mm.keySet()) - ll.add((String) o); - Collections.sort(ll); - - log.info("Properties:"); - for (String name : ll) - log.info("--- {}:{}", name, String.valueOf(mm.get(name))); - } - - protected void logHeaders(MultivaluedMap mm) { - log.info("HTTP response headers:"); - - if (mm == null) { - return; - } - - List ll = new ArrayList<>(); - for (Object o : mm.keySet()) - ll.add((String) o); - Collections.sort(ll); - - for (String name : ll) - log.info("--- {}:{}", name, String.valueOf(mm.get(name))); - } - - private static class FileParam { - - public String fileName; - public String url; - public String user; - public String password; - public HttpMethod httpMethod; - public String responsePrefix; - public boolean skipSending; - public String oAuthConsumerKey; - public String oAuthConsumerSecret; - public String oAuthSignatureMethod; - public String oAuthVersion; - public AuthType authtype; - } - -} \ No newline at end of file diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/RestapiCallNodeUtil.java b/src/main/java/org/onap/dcae/collectors/restconf/common/RestapiCallNodeUtil.java deleted file mode 100755 index 0e1d03b..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/RestapiCallNodeUtil.java +++ /dev/null @@ -1,178 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; -import org.glassfish.jersey.client.oauth1.ConsumerCredentials; -import org.glassfish.jersey.client.oauth1.OAuth1ClientSupport; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.ws.rs.client.Client; -import javax.ws.rs.core.Feature; -import java.net.URI; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -public class RestapiCallNodeUtil { - - private static final Logger log = LoggerFactory.getLogger(RestapiCallNodeUtil.class); - - private RestapiCallNodeUtil() { - // Preventing instantiation of the same. - } - - public static Parameters getParameters(Map paramMap) throws Exception { - Parameters p = new Parameters(); - p.templateFileName = parseParam(paramMap, "templateFileName", false, null); - p.requestBody = parseParam(paramMap, "requestBody", false, null); - p.restapiUrl = parseParam(paramMap, "restapiUrl", true, null); - validateUrl(p.restapiUrl); - p.restapiUser = parseParam(paramMap, "restapiUser", false, null); - p.restapiPassword = parseParam(paramMap, "restapiPassword", false, null); - p.oAuthConsumerKey = parseParam(paramMap, "oAuthConsumerKey", false, null); - p.oAuthConsumerSecret = parseParam(paramMap, "oAuthConsumerSecret", false, null); - p.oAuthSignatureMethod = parseParam(paramMap, "oAuthSignatureMethod", false, null); - p.oAuthVersion = parseParam(paramMap, "oAuthVersion", false, null); - p.contentType = parseParam(paramMap, "contentType", false, null); - p.format = Format.fromString(parseParam(paramMap, "format", false, "json")); - p.authtype = AuthType.fromString(parseParam(paramMap, "authType", false, "unspecified")); - p.httpMethod = HttpMethod.fromString(parseParam(paramMap, "httpMethod", false, "post")); - p.responsePrefix = parseParam(paramMap, "responsePrefix", false, null); - p.listNameList = getListNameList(paramMap); - String skipSendingStr = paramMap.get("skipSending"); - p.skipSending = "true".equalsIgnoreCase(skipSendingStr); - p.convertResponse = Boolean.valueOf(parseParam(paramMap, "convertResponse", false, "true")); - p.trustStoreFileName = parseParam(paramMap, "trustStoreFileName", false, null); - p.trustStorePassword = parseParam(paramMap, "trustStorePassword", false, null); - p.keyStoreFileName = parseParam(paramMap, "keyStoreFileName", false, null); - p.keyStorePassword = parseParam(paramMap, "keyStorePassword", false, null); - p.ssl = p.trustStoreFileName != null && p.trustStorePassword != null && p.keyStoreFileName != null && - p.keyStorePassword != null; - p.customHttpHeaders = parseParam(paramMap, "customHttpHeaders", false, null); - p.partner = parseParam(paramMap, "partner", false, null); - p.dumpHeaders = Boolean.valueOf(parseParam(paramMap, "dumpHeaders", false, null)); - p.returnRequestPayload = Boolean.valueOf(parseParam(paramMap, "returnRequestPayload", false, null)); - return p; - } - - public static String parseParam(Map paramMap, String name, boolean required, String def) - throws Exception { - String s = paramMap.get(name); - - if (s == null || s.trim().length() == 0) { - if (!required) { - return def; - } - throw new Exception("Parameter " + name + " is required in RestapiCallNode"); - } - - s = s.trim(); - StringBuilder value = new StringBuilder(); - int i = 0; - int i1 = s.indexOf('%'); - while (i1 >= 0) { - int i2 = s.indexOf('%', i1 + 1); - if (i2 < 0) { - break; - } - - String varName = s.substring(i1 + 1, i2); - String varValue = System.getenv(varName); - if (varValue == null) { - varValue = "%" + varName + "%"; - } - - value.append(s.substring(i, i1)); - value.append(varValue); - - i = i2 + 1; - i1 = s.indexOf('%', i); - } - value.append(s.substring(i)); - - log.info("Parameter {}: [{}]", name, value); - return value.toString(); - } - - private static void validateUrl(String restapiUrl) throws Exception { - try { - URI.create(restapiUrl); - } catch (IllegalArgumentException e) { - throw new Exception("Invalid input of url " + e.getLocalizedMessage(), e); - } - } - - private static Set getListNameList(Map paramMap) { - Set ll = new HashSet<>(); - for (Map.Entry entry : paramMap.entrySet()) - if (entry.getKey().startsWith("listName")) { - ll.add(entry.getValue()); - } - return ll; - } - - public static Client addAuthType(Client client, Parameters p) { - if (p.authtype == AuthType.Unspecified) { - if (p.restapiUser != null && p.restapiPassword != null) { - client.register(HttpAuthenticationFeature.basic(p.restapiUser, p.restapiPassword)); - } else if (p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null - && p.oAuthSignatureMethod != null) { - Feature oAuth1Feature = OAuth1ClientSupport - .builder(new ConsumerCredentials(p.oAuthConsumerKey, p.oAuthConsumerSecret)) - .version(p.oAuthVersion).signatureMethod(p.oAuthSignatureMethod).feature().build(); - client.register(oAuth1Feature); - } - } else { - if (p.authtype == AuthType.DIGEST) { - if (p.restapiUser != null && p.restapiPassword != null) { - client.register(HttpAuthenticationFeature.digest(p.restapiUser, p.restapiPassword)); - } else { - throw new IllegalArgumentException( - "oAUTH authentication type selected but all restapiUser and restapiPassword " + - "parameters doesn't exist", new Throwable()); - } - } else if (p.authtype == AuthType.BASIC) { - if (p.restapiUser != null && p.restapiPassword != null) { - client.register(HttpAuthenticationFeature.basic(p.restapiUser, p.restapiPassword)); - } else { - throw new IllegalArgumentException( - "oAUTH authentication type selected but all restapiUser and restapiPassword " + - "parameters doesn't exist", new Throwable()); - } - } else if (p.authtype == AuthType.OAUTH) { - if (p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null && p.oAuthSignatureMethod != null) { - Feature oAuth1Feature = OAuth1ClientSupport - .builder(new ConsumerCredentials(p.oAuthConsumerKey, p.oAuthConsumerSecret)) - .version(p.oAuthVersion).signatureMethod(p.oAuthSignatureMethod).feature().build(); - client.register(oAuth1Feature); - } else { - throw new IllegalArgumentException( - "oAUTH authentication type selected but all oAuthConsumerKey, oAuthConsumerSecret " + - "and oAuthSignatureMethod parameters doesn't exist", new Throwable()); - } - } - } - return client; - } -} - diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/RetryException.java b/src/main/java/org/onap/dcae/collectors/restconf/common/RetryException.java deleted file mode 100755 index aa40c33..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/RetryException.java +++ /dev/null @@ -1,27 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -public class RetryException extends Exception { - public RetryException(String message) { - super(message); - } -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/RetryPolicy.java b/src/main/java/org/onap/dcae/collectors/restconf/common/RetryPolicy.java deleted file mode 100755 index 6c62394..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/RetryPolicy.java +++ /dev/null @@ -1,58 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -public class RetryPolicy { - private String[] hostnames; - private Integer maximumRetries; - - public Integer getMaximumRetries() { - return maximumRetries; - } - - public String getNextHostName(String uri) throws RetryException { - Integer position = null; - - for (int i = 0; i < hostnames.length; i++) { - if (uri.contains(hostnames[i])) { - position = i; - break; - } - } - - if (position == null) { - throw new RetryException("No match found for the provided uri[" + uri + "] " + - "so the next host name could not be retreived"); - } - position++; - - if (position > hostnames.length - 1) { - position = 0; - } - return hostnames[position]; - } - - public RetryPolicy(String[] hostnames, Integer maximumRetries) { - this.hostnames = hostnames; - this.maximumRetries = maximumRetries; - } - -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/RetryPolicyStore.java b/src/main/java/org/onap/dcae/collectors/restconf/common/RetryPolicyStore.java deleted file mode 100755 index 0d1762f..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/RetryPolicyStore.java +++ /dev/null @@ -1,53 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; - -public class RetryPolicyStore { - private static final Logger log = LoggerFactory.getLogger(RetryPolicyStore.class); - - HashMap retryPolicies; - public String proxyServers; - - public String getProxyServers() { - return proxyServers; - } - - public void setProxyServers(String admServers) { - this.proxyServers = admServers; - String[] adminServersArray = admServers.split(","); - RetryPolicy adminPortalRetry = new RetryPolicy(adminServersArray, adminServersArray.length); - retryPolicies.put("dme2proxy", adminPortalRetry); - } - - public RetryPolicyStore() { - retryPolicies = new HashMap<>(); - } - - public RetryPolicy getRetryPolicy(String policyName) { - return (this.retryPolicies.get(policyName)); - } - -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/XmlJsonUtil.java b/src/main/java/org/onap/dcae/collectors/restconf/common/XmlJsonUtil.java deleted file mode 100755 index 6cac728..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/XmlJsonUtil.java +++ /dev/null @@ -1,412 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class XmlJsonUtil { - - private static final Logger log = LoggerFactory.getLogger(XmlJsonUtil.class); - - private XmlJsonUtil() { - // Preventing instantiation of the same. - } - - public static String getXml(Map varmap, String var) { - boolean escape = true; - if (var.startsWith("'")) { - var = var.substring(1); - escape = false; - } - - Object o = createStructure(varmap, var); - return generateXml(o, 0, escape); - } - - public static String getJson(Map varmap, String var) { - boolean escape = true; - if (var.startsWith("'")) { - var = var.substring(1); - escape = false; - } - - boolean quotes = true; - if (var.startsWith("\"")) { - var = var.substring(1); - quotes = false; - } - - Object o = createStructure(varmap, var); - return generateJson(o, escape, quotes); - } - - private static Object createStructure(Map flatmap, String var) { - if (flatmap.containsKey(var)) { - if (var.endsWith("_length") || var.endsWith("].key")) { - return null; - } - return flatmap.get(var); - } - - Map mm = new HashMap<>(); - for (String k : flatmap.keySet()) - if (k.startsWith(var + ".")) { - int i1 = k.indexOf('.', var.length() + 1); - int i2 = k.indexOf('[', var.length() + 1); - int i3 = k.length(); - if (i1 > 0 && i1 < i3) { - i3 = i1; - } - if (i2 > 0 && i2 < i3) { - i3 = i2; - } - String k1 = k.substring(var.length() + 1, i3); - String var1 = k.substring(0, i3); - if (!mm.containsKey(k1)) { - Object str = createStructure(flatmap, var1); - if (str != null && (!(str instanceof String) || ((String) str).trim().length() > 0)) { - mm.put(k1, str); - } - } - } - if (!mm.isEmpty()) { - return mm; - } - - boolean arrayFound = false; - for (String k : flatmap.keySet()) - if (k.startsWith(var + "[")) { - arrayFound = true; - break; - } - - if (arrayFound) { - List ll = new ArrayList<>(); - - int length = Integer.MAX_VALUE; - String lengthStr = flatmap.get(var + "_length"); - if (lengthStr != null) { - try { - length = Integer.parseInt(lengthStr); - } catch (Exception e) { - log.warn("Invalid number for {}_length:{}", var, lengthStr, e); - } - } - - for (int i = 0; i < length; i++) { - Object v = createStructure(flatmap, var + '[' + i + ']'); - if (v == null) { - break; - } - ll.add(v); - } - - if (!ll.isEmpty()) { - return ll; - } - } - - return null; - } - - @SuppressWarnings("unchecked") - private static String generateXml(Object o, int indent, boolean escape) { - if (o == null) { - return null; - } - - if (o instanceof String) { - return escape ? escapeXml((String) o) : (String) o; - } - ; - - if (o instanceof Map) { - StringBuilder ss = new StringBuilder(); - Map mm = (Map) o; - for (Map.Entry entry : mm.entrySet()) { - Object v = entry.getValue(); - String key = entry.getKey(); - if (v instanceof String) { - String s = escape ? escapeXml((String) v) : (String) v; - ss.append(pad(indent)).append('<').append(key).append('>'); - ss.append(s); - ss.append("').append('\n'); - } else if (v instanceof Map) { - ss.append(pad(indent)).append('<').append(key).append('>').append('\n'); - ss.append(generateXml(v, indent + 1, escape)); - ss.append(pad(indent)).append("').append('\n'); - } else if (v instanceof List) { - List ll = (List) v; - for (Object o1 : ll) { - ss.append(pad(indent)).append('<').append(key).append('>').append('\n'); - ss.append(generateXml(o1, indent + 1, escape)); - ss.append(pad(indent)).append("').append('\n'); - } - } - } - return ss.toString(); - } - - return null; - } - - private static String generateJson(Object o, boolean escape, boolean quotes) { - if (o == null) { - return null; - } - - StringBuilder ss = new StringBuilder(); - generateJson(ss, o, 0, false, escape, quotes); - return ss.toString(); - } - - @SuppressWarnings("unchecked") - private static void generateJson(StringBuilder ss, Object o, int indent, boolean padFirst, boolean escape, boolean quotes) { - if (o instanceof String) { - String s = escape ? escapeJson((String) o) : (String) o; - if (padFirst) { - ss.append(pad(indent)); - } - if (quotes) { - ss.append('"').append(s).append('"'); - } else { - ss.append(s); - } - return; - } - - if (o instanceof Map) { - Map mm = (Map) o; - - if (padFirst) { - ss.append(pad(indent)); - } - ss.append("{\n"); - - boolean first = true; - for (Map.Entry entry : mm.entrySet()) { - if (!first) { - ss.append(",\n"); - } - first = false; - Object v = entry.getValue(); - String key = entry.getKey(); - ss.append(pad(indent + 1)).append('"').append(key).append("\": "); - generateJson(ss, v, indent + 1, false, escape, true); - } - - ss.append("\n"); - ss.append(pad(indent)).append('}'); - - return; - } - - if (o instanceof List) { - List ll = (List) o; - - if (padFirst) { - ss.append(pad(indent)); - } - ss.append("[\n"); - - boolean first = true; - for (Object o1 : ll) { - if (!first) { - ss.append(",\n"); - } - first = false; - - generateJson(ss, o1, indent + 1, true, escape, quotes); - } - - ss.append("\n"); - ss.append(pad(indent)).append(']'); - } - } - - public static String removeLastCommaJson(String s) { - StringBuilder sb = new StringBuilder(); - int k = 0; - int start = 0; - while (k < s.length()) { - int i11 = s.indexOf('}', k); - int i12 = s.indexOf(']', k); - int i1 = -1; - if (i11 < 0) { - i1 = i12; - } else if (i12 < 0) { - i1 = i11; - } else { - i1 = i11 < i12 ? i11 : i12; - } - if (i1 < 0) { - break; - } - - int i2 = s.lastIndexOf(',', i1); - if (i2 < 0) { - k = i1 + 1; - continue; - } - - String between = s.substring(i2 + 1, i1); - if (between.trim().length() > 0) { - k = i1 + 1; - continue; - } - - sb.append(s.substring(start, i2)); - start = i2 + 1; - k = i1 + 1; - } - - sb.append(s.substring(start, s.length())); - - return sb.toString(); - } - - public static String removeEmptyStructJson(String s) { - int k = 0; - while (k < s.length()) { - boolean curly = true; - int i11 = s.indexOf('{', k); - int i12 = s.indexOf('[', k); - int i1 = -1; - if (i11 < 0) { - i1 = i12; - curly = false; - } else if (i12 < 0) { - i1 = i11; - } else if (i11 < i12) { - i1 = i11; - } else { - i1 = i12; - curly = false; - } - - if (i1 >= 0) { - int i2 = curly ? s.indexOf('}', i1) : s.indexOf(']', i1); - if (i2 > 0) { - String value = s.substring(i1 + 1, i2); - if (value.trim().length() == 0) { - int i4 = s.lastIndexOf('\n', i1); - if (i4 < 0) { - i4 = 0; - } - int i5 = s.indexOf('\n', i2); - if (i5 < 0) { - i5 = s.length(); - } - - s = s.substring(0, i4) + s.substring(i5); - k = 0; - } else { - k = i1 + 1; - } - } else { - break; - } - } else { - break; - } - } - - return s; - } - - public static String removeEmptyStructXml(String s) { - int k = 0; - while (k < s.length()) { - int i1 = s.indexOf('<', k); - if (i1 < 0 || i1 == s.length() - 1) { - break; - } - - char c1 = s.charAt(i1 + 1); - if (c1 == '?' || c1 == '!') { - k = i1 + 2; - continue; - } - - int i2 = s.indexOf('>', i1); - if (i2 < 0) { - k = i1 + 1; - continue; - } - - String closingTag = " 0) { - k = i2 + 1; - continue; - } - - int i4 = s.lastIndexOf('\n', i1); - if (i4 < 0) { - i4 = 0; - } - int i5 = s.indexOf('\n', i3); - if (i5 < 0) { - i5 = s.length(); - } - - s = s.substring(0, i4) + s.substring(i5); - k = 0; - } - - return s; - } - - private static String escapeXml(String v) { - String s = v.replaceAll("&", "&"); - s = s.replaceAll("<", "<"); - s = s.replaceAll("'", "'"); - s = s.replaceAll("\"", """); - s = s.replaceAll(">", ">"); - return s; - } - - private static String escapeJson(String v) { - String s = v.replaceAll("\\\\", "\\\\\\\\"); - s = s.replaceAll("\"", "\\\\\""); - return s; - } - - private static String pad(int n) { - StringBuilder s = new StringBuilder(); - for (int i = 0; i < n; i++) - s.append(Character.toString('\t')); - return s.toString(); - } -} - diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/XmlParser.java b/src/main/java/org/onap/dcae/collectors/restconf/common/XmlParser.java deleted file mode 100755 index 80bf2fc..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/XmlParser.java +++ /dev/null @@ -1,178 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import static com.google.common.base.Preconditions.checkNotNull; - -public class XmlParser { - - private static final Logger log = LoggerFactory.getLogger(XmlParser.class); - - private XmlParser() { - // Preventing instantiation of the same. - } - - public static Map convertToProperties(String s, Set listNameList) - throws Exception { - - checkNotNull(s, "Input should not be null."); - - Handler handler = new Handler(listNameList); - try { - SAXParserFactory factory = SAXParserFactory.newInstance(); - SAXParser saxParser = factory.newSAXParser(); - InputStream in = new ByteArrayInputStream(s.getBytes()); - saxParser.parse(in, handler); - } catch (ParserConfigurationException | IOException | SAXException | NumberFormatException e) { - throw new Exception("Unable to convert XML to properties" + e.getLocalizedMessage(), e); - } - return handler.getProperties(); - } - - private static class Handler extends DefaultHandler { - - private Set listNameList; - - private Map properties = new HashMap<>(); - - public Map getProperties() { - return properties; - } - - public Handler(Set listNameList) { - super(); - this.listNameList = listNameList; - if (this.listNameList == null) { - this.listNameList = new HashSet<>(); - } - } - - StringBuilder currentName = new StringBuilder(); - StringBuilder currentValue = new StringBuilder(); - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) - throws SAXException { - super.startElement(uri, localName, qName, attributes); - - String name = localName; - if (name == null || name.trim().length() == 0) { - name = qName; - } - int i2 = name.indexOf(':'); - if (i2 >= 0) { - name = name.substring(i2 + 1); - } - - if (currentName.length() > 0) { - currentName.append(Character.toString('.')); - } - currentName.append(name); - - String listName = removeIndexes(currentName.toString()); - - if (listNameList.contains(listName)) { - String n = currentName.toString() + "_length"; - int len = getInt(properties, n); - properties.put(n, String.valueOf(len + 1)); - currentName.append("[").append(len).append("]"); - } - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - super.endElement(uri, localName, qName); - - String name = localName; - if (name == null || name.trim().length() == 0) { - name = qName; - } - int i2 = name.indexOf(':'); - if (i2 >= 0) { - name = name.substring(i2 + 1); - } - - String s = currentValue.toString().trim(); - if (s.length() > 0) { - properties.put(currentName.toString(), s); - - log.info("Added property: {} : {}", currentName, s); - currentValue = new StringBuilder(); - } - - int i1 = currentName.lastIndexOf("." + name); - if (i1 <= 0) { - currentName = new StringBuilder(); - } else { - currentName = new StringBuilder(currentName.substring(0, i1)); - } - } - - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - super.characters(ch, start, length); - - String value = new String(ch, start, length); - currentValue.append(value); - } - - private static int getInt(Map mm, String name) { - String s = mm.get(name); - if (s == null) { - return 0; - } - return Integer.parseInt(s); - } - - private String removeIndexes(String currentName) { - StringBuilder b = new StringBuilder(); - boolean add = true; - for (int i = 0; i < currentName.length(); i++) { - char c = currentName.charAt(i); - if (c == '[') { - add = false; - } else if (c == ']') { - add = true; - } else if (add) { - b.append(Character.toString(c)); - } - } - return b.toString(); - } - } -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPConfigurationParser.java b/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPConfigurationParser.java deleted file mode 100755 index 7e65d34..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPConfigurationParser.java +++ /dev/null @@ -1,107 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common.event.publishing; - -import io.vavr.collection.List; -import io.vavr.collection.Map; -import io.vavr.control.Option; -import io.vavr.control.Try; -import org.onap.dcae.collectors.restconf.common.AnyNode; - -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; - -import static io.vavr.API.List; -import static io.vavr.API.Try; -import static io.vavr.API.Tuple; -import static io.vavr.API.unchecked; -import static org.onap.dcae.collectors.restconf.common.event.publishing.VavrUtils.enhanceError; -import static org.onap.dcae.collectors.restconf.common.event.publishing.VavrUtils.f; - -public class DMaaPConfigurationParser { - - public static Try> parseToDomainMapping(Path configLocation) { - return readFromFile(configLocation) - .flatMap(DMaaPConfigurationParser::toJSON) - .flatMap(DMaaPConfigurationParser::toConfigMap); - } - - private static Try readFromFile(Path configLocation) { - return Try(() -> new String(Files.readAllBytes(configLocation))) - .mapFailure(enhanceError(f("Could not read DMaaP configuration from location: '%s'", configLocation))); - } - - private static Try toJSON(String config) { - return Try(() -> AnyNode.fromString(config)) - .mapFailure(enhanceError(f("DMaaP configuration '%s' is not a valid JSON document", config))); - } - - private static Try> toConfigMap(AnyNode config) { - return Try(() -> usesLegacyFormat(config) ? parseLegacyFormat(config) : parseNewFormat(config)) - .mapFailure(enhanceError( - f("Parsing DMaaP configuration: '%s' failed, probably it is in unexpected format", config))); - } - - private static boolean usesLegacyFormat(AnyNode dMaaPConfig) { - return dMaaPConfig.has("channels"); - } - - private static Map parseLegacyFormat(AnyNode root) { - return root.get("channels").toList().toMap( - channel -> channel.get("name").toString(), - channel -> { - String destinationsStr = channel.getAsOption("cambria.url") - .getOrElse(channel.getAsOption("cambria.hosts").get()) - .toString(); - String topic = channel.get("cambria.topic").toString(); - Option maybeUser = channel.getAsOption("basicAuthUsername").map(AnyNode::toString); - Option maybePassword = channel.getAsOption("basicAuthPassword").map(AnyNode::toString); - List destinations = List(destinationsStr.split(",")); - return buildBasedOnAuth(maybeUser, maybePassword, topic, destinations); - }); - } - - private static Map parseNewFormat(AnyNode root) { - return root.keys().toMap( - channelName -> channelName, - channelName -> { - AnyNode channelConfig = root.get(channelName); - Option maybeUser = channelConfig.getAsOption("aaf_username").map(AnyNode::toString); - Option maybePassword = channelConfig.getAsOption("aaf_password").map(AnyNode::toString); - URL topicURL = unchecked( - () -> new URL(channelConfig.get("dmaap_info").get("topic_url").toString())).apply(); - String[] pathSegments = topicURL.getPath().substring(1).split("/"); - String topic = pathSegments[1]; - String destination = "events".equals(pathSegments[0]) ? topicURL.getAuthority() : topicURL.getHost(); - List destinations = List(destination); - return buildBasedOnAuth(maybeUser, maybePassword, topic, destinations); - }); - } - - private static PublisherConfig buildBasedOnAuth(Option maybeUser, Option maybePassword, - String topic, List destinations) { - return maybeUser.flatMap(user -> maybePassword.map(password -> Tuple(user, password))) - .map(credentials -> new PublisherConfig(destinations, topic, credentials._1, credentials._2)) - .getOrElse(new PublisherConfig(destinations, topic)); - } - -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPEventPublisher.java b/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPEventPublisher.java deleted file mode 100755 index 4c14275..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPEventPublisher.java +++ /dev/null @@ -1,75 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common.event.publishing; - -import com.att.nsa.cambria.client.CambriaBatchingPublisher; -import io.vavr.control.Try; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; - -public class DMaaPEventPublisher implements EventPublisher { - - private static final int PENDING_MESSAGE_LOG_THRESHOLD = 100; - private static final Logger log = LoggerFactory.getLogger(DMaaPEventPublisher.class); - private final DMaaPPublishersCache publishersCache; - private final Logger outputLogger; - - DMaaPEventPublisher(DMaaPPublishersCache DMaaPPublishersCache, - Logger outputLogger) { - this.publishersCache = DMaaPPublishersCache; - this.outputLogger = outputLogger; - } - - @Override - public void sendEvent(JSONObject event, String domain) { - publishersCache.getPublisher(domain) - .onEmpty(() -> - log.warn(VavrUtils.f("Could not find event publisher for domain: '%s', dropping message: '%s'", domain, event))) - .forEach(publisher -> sendEvent(event, domain, publisher)); - } - - private void sendEvent(JSONObject event, String domain, CambriaBatchingPublisher publisher) { - Try.run(() -> uncheckedSendEvent(event, domain, publisher)) - .onFailure(exc -> closePublisher(event, domain, exc)); - } - - private void uncheckedSendEvent(JSONObject event, String domain, CambriaBatchingPublisher publisher) - throws IOException { - System.out.println("printing publisher information" + publisher); - int pendingMsgs = publisher.send("MyPartitionKey", event.toString()); - if (pendingMsgs > PENDING_MESSAGE_LOG_THRESHOLD) { - log.info("Pending messages count: " + pendingMsgs); - } - String infoMsg = VavrUtils.f("Event: '%s' scheduled to be send asynchronously on domain: '%s'", event, domain); - log.info(infoMsg); - outputLogger.info(infoMsg); - } - - private void closePublisher(JSONObject event, String domain, Throwable e) { - log.error(VavrUtils.f("Unable to schedule event: '%s' on domain: '%s'. Closing publisher and dropping message.", - event, domain), e); - publishersCache.closePublisherFor(domain); - } - -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPPublishersBuilder.java b/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPPublishersBuilder.java deleted file mode 100755 index e6c7600..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPPublishersBuilder.java +++ /dev/null @@ -1,63 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common.event.publishing; - -import com.att.nsa.cambria.client.CambriaBatchingPublisher; -import com.att.nsa.cambria.client.CambriaClientBuilders; -import com.att.nsa.cambria.client.CambriaClientBuilders.PublisherBuilder; -import io.vavr.control.Try; - -import static io.vavr.API.Try; -import static org.onap.dcae.collectors.restconf.common.event.publishing.VavrUtils.enhanceError; -import static org.onap.dcae.collectors.restconf.common.event.publishing.VavrUtils.f; - -/** - * @author Pawel Szalapski (pawel.szalapski@nokia.com) - */ -final class DMaaPPublishersBuilder { - - @SuppressWarnings("mapFailure takes a generic varargs, unchecked because of Javas type system limitation, actually safe to do") - static Try buildPublisher(PublisherConfig config) { - return Try(() -> builder(config).build()) - .mapFailure(enhanceError(f("DMaaP client builder throws exception for this configuration: '%s'", config))); - } - - private static PublisherBuilder builder(PublisherConfig config) { - if (config.isSecured()) { - return authenticatedBuilder(config); - } else { - return unAuthenticatedBuilder(config); - } - } - - private static PublisherBuilder authenticatedBuilder(PublisherConfig config) { - return unAuthenticatedBuilder(config) - .usingHttps() - .authenticatedByHttp(config.userName().get(), config.password().get()); - } - - private static PublisherBuilder unAuthenticatedBuilder(PublisherConfig config) { - return new CambriaClientBuilders.PublisherBuilder() - .usingHosts(config.destinations().mkString(",")) - .onTopic(config.topic()) - .logSendFailuresAfter(5); - } -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPPublishersCache.java b/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPPublishersCache.java deleted file mode 100755 index 6974bc9..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPPublishersCache.java +++ /dev/null @@ -1,110 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common.event.publishing; - -import com.att.nsa.cambria.client.CambriaBatchingPublisher; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.cache.RemovalListener; -import com.google.common.cache.RemovalNotification; -import io.vavr.collection.Map; -import io.vavr.control.Option; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nonnull; -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import static io.vavr.API.Option; -import static org.onap.dcae.collectors.restconf.common.event.publishing.VavrUtils.f; - -public class DMaaPPublishersCache { - - private static final Logger log = LoggerFactory.getLogger(DMaaPPublishersCache.class); - private final LoadingCache publishersCache; - private AtomicReference> dMaaPConfiguration; - - DMaaPPublishersCache(Map dMaaPConfiguration) { - this.dMaaPConfiguration = new AtomicReference<>(dMaaPConfiguration); - this.publishersCache = CacheBuilder.newBuilder() - .removalListener(new OnPublisherRemovalListener()) - .build(new CambriaPublishersCacheLoader()); - } - - DMaaPPublishersCache(CambriaPublishersCacheLoader dMaaPPublishersCacheLoader, - OnPublisherRemovalListener onPublisherRemovalListener, - Map dMaaPConfiguration) { - this.dMaaPConfiguration = new AtomicReference<>(dMaaPConfiguration); - this.publishersCache = CacheBuilder.newBuilder() - .removalListener(onPublisherRemovalListener) - .build(dMaaPPublishersCacheLoader); - } - - Option getPublisher(String streamID) { - try { - return Option(publishersCache.getUnchecked(streamID)); - } catch (Exception e) { - log.warn("Could not create / load Cambria Publisher for streamID", e); - return Option.none(); - } - } - - void closePublisherFor(String streamId) { - publishersCache.invalidate(streamId); - } - - static class OnPublisherRemovalListener implements RemovalListener { - - @Override - public void onRemoval(@Nonnull RemovalNotification notification) { - CambriaBatchingPublisher publisher = notification.getValue(); - if (publisher != null) { // The value might get Garbage Collected at this moment, regardless of @Nonnull - try { - int timeout = 20; - TimeUnit unit = TimeUnit.SECONDS; - java.util.List stuck = publisher.close(timeout, unit); - if (!stuck.isEmpty()) { - log.error(f("Publisher got stuck and did not manage to close in '%s' '%s', " - + "%s messages were dropped", stuck.size(), timeout, unit)); - } - } catch (InterruptedException | IOException e) { - log.error("Could not close Cambria publisher, some messages might have been dropped", e); - } - } - } - } - - class CambriaPublishersCacheLoader extends CacheLoader { - - @Override - public CambriaBatchingPublisher load(@Nonnull String domain) { - return dMaaPConfiguration.get() - .get(domain) - .toTry(() -> new RuntimeException( - f("DMaaP configuration contains no configuration for domain: '%s'", domain))) - .flatMap(DMaaPPublishersBuilder::buildPublisher) - .get(); - } - } -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/EventPublisher.java b/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/EventPublisher.java deleted file mode 100755 index 28aace8..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/EventPublisher.java +++ /dev/null @@ -1,35 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.dcae.collectors.restconf.common.event.publishing; - - -import io.vavr.collection.Map; -import org.json.JSONObject; -import org.slf4j.Logger; - -public interface EventPublisher { - - static EventPublisher createPublisher(Logger outputLogger, Map dMaaPConfig) { - return new DMaaPEventPublisher(new DMaaPPublishersCache(dMaaPConfig), outputLogger); - } - - void sendEvent(JSONObject event, String domain); - -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/PublisherConfig.java b/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/PublisherConfig.java deleted file mode 100755 index 0e14a42..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/PublisherConfig.java +++ /dev/null @@ -1,95 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.dcae.collectors.restconf.common.event.publishing; - -import io.vavr.collection.List; -import io.vavr.control.Option; - -import java.util.Objects; - -public class PublisherConfig { - private final List destinations; - private final String topic; - private String userName; - private String password; - - PublisherConfig(List destinations, String topic) { - this.destinations = destinations; - this.topic = topic; - } - - PublisherConfig(List destinations, String topic, String userName, String password) { - this.destinations = destinations; - this.topic = topic; - this.userName = userName; - this.password = password; - } - - List destinations() { - return destinations; - } - - String topic() { - return topic; - } - - Option userName() { - return Option.of(userName); - } - - Option password() { - return Option.of(password); - } - - boolean isSecured() { - return userName().isDefined() && password().isDefined(); - } - - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - PublisherConfig that = (PublisherConfig) o; - return Objects.equals(destinations, that.destinations) && - Objects.equals(topic, that.topic) && - Objects.equals(userName, that.userName) && - Objects.equals(password, that.password); - } - - @Override - public int hashCode() { - return Objects.hash(destinations, topic, userName, password); - } - - @Override - public String toString() { - return "PublisherConfig{" + - "destinations=" + destinations + - ", topic='" + topic + '\'' + - ", userName='" + userName + '\'' + - ", password='" + password + '\'' + - '}'; - } -} diff --git a/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/VavrUtils.java b/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/VavrUtils.java deleted file mode 100755 index 4a82bed..0000000 --- a/src/main/java/org/onap/dcae/collectors/restconf/common/event/publishing/VavrUtils.java +++ /dev/null @@ -1,48 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common.event.publishing; - -import io.vavr.API; -import io.vavr.API.Match.Case; - -import static io.vavr.API.$; - - -public class VavrUtils { - private VavrUtils() { - // utils aggregator - } - - /** - * Shortcut for 'string interpolation' - */ - static String f(String msg, Object... args) { - return String.format(msg, args); - } - - /** - * Wrap failure with a more descriptive message of what has failed and chain original cause. Used to provide a - * context for errors instead of raw exception. - */ - static Case enhanceError(String msg) { - return API.Case($(), e -> new RuntimeException(msg, e)); - } -} diff --git a/src/main/java/org/onap/dcae/common/AdditionalHeaderWebTarget.java b/src/main/java/org/onap/dcae/common/AdditionalHeaderWebTarget.java new file mode 100644 index 0000000..fe61155 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/AdditionalHeaderWebTarget.java @@ -0,0 +1,159 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Configuration; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriBuilder; +import java.net.URI; +import java.util.Map; + +public class AdditionalHeaderWebTarget implements WebTarget { + private WebTarget base; + private String token; + private String headerName; + + public AdditionalHeaderWebTarget(WebTarget target, String token, String headerName) { + base = target; + this.token = token; + this.headerName = headerName; + } + + @Override + public Invocation.Builder request() { + return base.request().header(headerName, token); + } + + @Override + public Invocation.Builder request(String... acceptedResponseTypes) { + return base.request().header(headerName, token); + } + + @Override + public Invocation.Builder request(MediaType... acceptedResponseTypes) { + return base.request().header(headerName, token); + } + + @Override + public Configuration getConfiguration() { + return base.getConfiguration(); + } + + @Override + public URI getUri() { + return base.getUri(); + } + + @Override + public UriBuilder getUriBuilder() { + return base.getUriBuilder(); + } + + @Override + public WebTarget path(String path) { + return base.path(path); + } + + @Override + public WebTarget resolveTemplate(String name, Object value) { + return base.resolveTemplate(name, value); + } + + @Override + public WebTarget resolveTemplate(String name, Object value, boolean encodeSlashInPath) { + return base.resolveTemplate(name, value, encodeSlashInPath); + } + + @Override + public WebTarget resolveTemplateFromEncoded(String name, Object value) { + return base.resolveTemplateFromEncoded(name, value); + } + + @Override + public WebTarget resolveTemplates(Map templateValues) { + return base.resolveTemplates(templateValues); + } + + @Override + public WebTarget resolveTemplates(Map templateValues, boolean encodeSlashInPath) { + return base.resolveTemplates(templateValues, encodeSlashInPath); + } + + @Override + public WebTarget resolveTemplatesFromEncoded(Map templateValues) { + return base.resolveTemplatesFromEncoded(templateValues); + } + + @Override + public WebTarget matrixParam(String name, Object... values) { + return base.matrixParam(name, values); + } + + @Override + public WebTarget queryParam(String name, Object... values) { + return base.queryParam(name, values); + } + + @Override + public WebTarget property(String name, Object value) { + return base.property(name, value); + } + + @Override + public WebTarget register(Class componentClass) { + return base.register(componentClass); + } + + @Override + public WebTarget register(Class componentClass, int priority) { + return base.register(componentClass, priority); + } + + @Override + public WebTarget register(Class componentClass, Class... contracts) { + return base.register(componentClass, contracts); + } + + @Override + public WebTarget register(Class componentClass, Map, Integer> contracts) { + return base.register(componentClass, contracts); + } + + @Override + public WebTarget register(Object component) { + return base.register(component); + } + + @Override + public WebTarget register(Object component, int priority) { + return base.register(component, priority); + } + + @Override + public WebTarget register(Object component, Class... contracts) { + return base.register(component, contracts); + } + + @Override + public WebTarget register(Object component, Map, Integer> contracts) { + return base.register(component, contracts); + } +} diff --git a/src/main/java/org/onap/dcae/common/AnyNode.java b/src/main/java/org/onap/dcae/common/AnyNode.java new file mode 100644 index 0000000..8980f1b --- /dev/null +++ b/src/main/java/org/onap/dcae/common/AnyNode.java @@ -0,0 +1,89 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia Networks Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common; + +import io.vavr.collection.List; +import io.vavr.collection.Set; +import io.vavr.control.Option; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.stream.StreamSupport; + +import static io.vavr.API.Set; + +/** + * This class is a wrapper for 2 most used entities of org.json lib: JSONArray and JSONObject and comprises utility + * methods for fast access of json structures without need to explicitly coerce between them. While using this, bear in + * mind it does not contain exception handling - it is assumed that when using, the parsed json structure is known. + * + * @author koblosz + */ +public class AnyNode { + + private Object obj; + + private AnyNode(Object object) { + this.obj = object; + } + + public static AnyNode fromString(String content) { + return new AnyNode(new JSONObject(content)); + } + + public Set keys() { + return Set(asJsonObject().keySet().toArray(new String[]{})); + } + + public AnyNode get(String key) { + return new AnyNode(asJsonObject().get(key)); + } + + public String toString() { + return this.obj.toString(); + } + + public Option getAsOption(String key) { + try { + AnyNode value = get(key); + if ("null".equals(value.toString())) { + return Option.none(); + } + return Option.some(value); + } catch (JSONException ex) { + return Option.none(); + } + } + + public List toList() { + return List.ofAll(StreamSupport.stream(((JSONArray) this.obj).spliterator(), false).map(AnyNode::new)); + } + + public boolean has(String key) { + return !getAsOption(key).isEmpty(); + } + + private JSONObject asJsonObject() { + return (JSONObject) this.obj; + } + +} diff --git a/src/main/java/org/onap/dcae/common/AuthType.java b/src/main/java/org/onap/dcae/common/AuthType.java new file mode 100755 index 0000000..d87321e --- /dev/null +++ b/src/main/java/org/onap/dcae/common/AuthType.java @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common; + +public enum AuthType { + NONE, BASIC, DIGEST, OAUTH, Unspecified; + + public static AuthType fromString(String s) { + if ("basic".equalsIgnoreCase(s)) { + return BASIC; + } + if ("digest".equalsIgnoreCase(s)) { + return DIGEST; + } + if ("oauth".equalsIgnoreCase(s)) { + return OAUTH; + } + if ("none".equalsIgnoreCase(s)) { + return NONE; + } + if ("unspecified".equalsIgnoreCase(s)) { + return Unspecified; + } + throw new IllegalArgumentException("Invalid value for format: " + s); + } +} diff --git a/src/main/java/org/onap/dcae/common/Constants.java b/src/main/java/org/onap/dcae/common/Constants.java new file mode 100755 index 0000000..1fe5624 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/Constants.java @@ -0,0 +1,48 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +public class Constants { + public static final String KDEFAULT_TEMP_FILENAME = "templateFileName"; + public static final String KDEFAULT_REQUESTBODY = "requestBody"; + public static final String KSETTING_REST_API_URL = "restapiUrl"; + public static final String KSETTING_REST_UNAME = "restapiUser"; + public static final String KSETTING_REST_PASSWORD = "restapiPassword"; + public static final String KSETTING_HTTP_METHOD = "httpMethod"; + public static final String KSETTING_RESP_PREFIX = "responsePrefix"; + public static final String KSETTING_SKIP_SENDING = "skipSending"; + public static final String KSETTING_FORMAT = "format"; + public static final String KSETTING_SSE_CONNECT_URL = "sseConnectURL"; + public static final String KSETTING_AUTH_TYPE = "authType"; + public static final String KSETTING_CONTENT_TYPE = "contentType"; + public static final String KSETTING_OAUTH_CONSUMER_KEY = "oAuthConsumerKey"; + public static final String KSETTING_OAUTH_CONSUMER_SECRET = "oAuthConsumerSecret"; + public static final String KSETTING_OAUTH_SIGNATURE_METHOD = "oAuthSignatureMethod"; + public static final String KSETTING_OAUTH_VERSION = "oAuthVersion"; + public static final String KSETTING_TOKENID = "tokenId"; + public static final String KSETTING_CUSTOMHTTP_HEADER = "customHttpHeaders"; + public static final String KSETTING_DUMP_HEADER = "dumpHeaders"; + public static final String KSETTING_RETURN_REQUEST_PAYLOAD = "returnRequestPayload"; + public static final String KSETTING_TRUST_STORE_FILENAME = "trustStoreFileName"; + public static final String KSETTING_TRUST_STORE_PASSWORD = "trustStorePassword"; + public static final String KSETTING_KEY_STORE_FILENAME = "keyStoreFileName"; + public static final String KSETTING_KEY_STORE_PASSWORD = "keyStorePassword"; +} diff --git a/src/main/java/org/onap/dcae/common/DataChangeEventListener.java b/src/main/java/org/onap/dcae/common/DataChangeEventListener.java new file mode 100755 index 0000000..6e13f73 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/DataChangeEventListener.java @@ -0,0 +1,86 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import org.glassfish.jersey.media.sse.EventListener; +import org.glassfish.jersey.media.sse.InboundEvent; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.onap.dcae.RestConfCollector; +import org.onap.dcae.controller.PersistentEventConnection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DataChangeEventListener implements EventListener { + private static final Logger log = LoggerFactory.getLogger(DataChangeEventListener.class); + private PersistentEventConnection conn; + + public DataChangeEventListener(PersistentEventConnection conn) { + this.conn = conn; + } + + @Override + public void onEvent(InboundEvent event) { + try { + log.info("SSE Event is received"); + String s = event.readData(); + jsonType type = isJSONValid(s); + if (type == jsonType.OBJECT) { + JSONObject jsonObj = new JSONObject(s); + EventData ev = new EventData(this.conn, jsonObj); + log.info("SSE Event in json " + jsonObj.toString()); + RestConfCollector.handleEvents(ev); + } else if (type == jsonType.ARRAY) { + JSONArray jsonArr = new JSONArray(s); + for (int j = 0; j < jsonArr.length(); j++) { + JSONObject jsonObj = jsonArr.getJSONObject(j); + EventData ev = new EventData(this.conn, jsonObj); + log.info("SSE Event in json " + jsonObj.toString()); + RestConfCollector.handleEvents(ev); + } + } else { + log.info("Received heart beat "); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private enum jsonType { + OBJECT, ARRAY, NONE; + } + + public jsonType isJSONValid(String test) { + try { + new JSONObject(test); + log.info("Received a Json object"); + } catch (JSONException ex) { + try { + new JSONArray(test); + return jsonType.ARRAY; + } catch (JSONException ex1) { + return jsonType.NONE; + } + } + return jsonType.OBJECT; + } +} diff --git a/src/main/java/org/onap/dcae/common/EventConnectionState.java b/src/main/java/org/onap/dcae/common/EventConnectionState.java new file mode 100644 index 0000000..3e53247 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/EventConnectionState.java @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +public enum EventConnectionState { + + INIT, SUBSCRIBED, UNSUBSCRIBED, Unspecified; + + public static EventConnectionState fromString(String s) { + if ("init".equalsIgnoreCase(s)) { + return INIT; + } + if ("subscribed".equalsIgnoreCase(s)) { + return SUBSCRIBED; + } + if ("unsubscribed".equalsIgnoreCase(s)) { + return UNSUBSCRIBED; + } + if ("unspecified".equalsIgnoreCase(s)) { + return Unspecified; + } + throw new IllegalArgumentException("Invalid value for format: " + s); + } + +} diff --git a/src/main/java/org/onap/dcae/common/EventData.java b/src/main/java/org/onap/dcae/common/EventData.java new file mode 100644 index 0000000..b97d8e4 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/EventData.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common; + +import org.json.JSONObject; +import org.onap.dcae.controller.PersistentEventConnection; + +public class EventData { + private PersistentEventConnection conn; + private JSONObject eventObj; + + + public EventData(PersistentEventConnection conn, JSONObject eventObj) { + this.conn = conn; + this.eventObj = eventObj; + } + + public PersistentEventConnection getConn() { + return conn; + } + + public JSONObject getEventObj() { + return eventObj; + } +} diff --git a/src/main/java/org/onap/dcae/common/EventProcessor.java b/src/main/java/org/onap/dcae/common/EventProcessor.java new file mode 100644 index 0000000..bb0f095 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/EventProcessor.java @@ -0,0 +1,103 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + + +import org.json.JSONException; +import org.json.JSONObject; +import org.onap.dcae.RestConfCollector; +import org.onap.dcae.common.publishing.EventPublisher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public class EventProcessor implements Runnable { + private static final Logger log = LoggerFactory.getLogger(EventProcessor.class); + + private Map streamidHash = new HashMap<>(); + public EventData ev; + private EventPublisher eventPublisher; + + public EventProcessor(EventPublisher eventPublisher, Map streamidHash) { + this.eventPublisher = eventPublisher; + this.streamidHash.putAll(streamidHash); + } + + + @Override + public void run() { + try { + + while (true) { + ev = RestConfCollector.fProcessingInputQueue.take(); + + // As long as the producer is running we remove elements from + // the queue. + log.info("QueueSize:" + RestConfCollector.fProcessingInputQueue.size() + "\tEventProcessor\tRemoving element: " + + ev.getEventObj()); + /*@TODO: Right now all event publish to single domain and consume by VES collector. Later maybe send to specific domain */ + String[] streamIdList = streamidHash.get("notification"); + log.info("streamIdList:" + Arrays.toString(streamIdList)); + + if (streamIdList.length == 0) { + log.error("No StreamID defined for publish - Message dropped" + ev.getEventObj()); + } else { + sendEventsToStreams(streamIdList, ev); + } + log.info("Event published" + ev.getEventObj()); + } + } catch (Exception e) { + log.error("EventProcessor InterruptedException" + e.getMessage()); + Thread.currentThread().interrupt(); + } + } + + private void sendEventsToStreams(String[] streamIdList, EventData ev) { + for (String aStreamIdList : streamIdList) { + log.info("Invoking publisher for streamId:" + aStreamIdList); + if (!ev.getConn().getEvent_ruleId().equals("")) { + JSONObject customHeader = new JSONObject(); + customHeader.put("rule-id", ev.getConn().getEvent_ruleId()); + eventPublisher.sendEvent(overrideEvent(customHeader, ev.getEventObj()), aStreamIdList); + } else { + eventPublisher.sendEvent(ev.getEventObj(), aStreamIdList); + } + } + } + + private static JSONObject overrideEvent(JSONObject json1, JSONObject json2) { + JSONObject mergedJSON; + try { + mergedJSON = new JSONObject(json1, JSONObject.getNames(json1)); + for (String key : JSONObject.getNames(json2)) { + mergedJSON.put(key, json2.get(key)); + } + + } catch (JSONException e) { + throw new RuntimeException("JSON Exception" + e); + } + log.info("Merged json " + mergedJSON); + return mergedJSON; + } +} diff --git a/src/main/java/org/onap/dcae/common/Format.java b/src/main/java/org/onap/dcae/common/Format.java new file mode 100755 index 0000000..3539684 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/Format.java @@ -0,0 +1,38 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +public enum Format { + JSON, XML, NONE; + + public static Format fromString(String s) { + if ("json".equalsIgnoreCase(s)) { + return JSON; + } + if ("xml".equalsIgnoreCase(s)) { + return XML; + } + if ("none".equalsIgnoreCase(s)) { + return NONE; + } + throw new IllegalArgumentException("Invalid value for format: " + s); + } +} diff --git a/src/main/java/org/onap/dcae/common/HttpMethod.java b/src/main/java/org/onap/dcae/common/HttpMethod.java new file mode 100755 index 0000000..730ff2d --- /dev/null +++ b/src/main/java/org/onap/dcae/common/HttpMethod.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +public enum HttpMethod { + GET, POST, PUT, DELETE, PATCH; + + public static HttpMethod fromString(String s) { + if (s == null) { + return null; + } + if ("get".equalsIgnoreCase(s)) { + return GET; + } + if ("post".equalsIgnoreCase(s)) { + return POST; + } + if ("put".equalsIgnoreCase(s)) { + return PUT; + } + if ("delete".equalsIgnoreCase(s)) { + return DELETE; + } + if ("patch".equalsIgnoreCase(s)) { + return PATCH; + } + throw new IllegalArgumentException("Invalid value for HTTP Method: " + s); + } +} diff --git a/src/main/java/org/onap/dcae/common/HttpResponse.java b/src/main/java/org/onap/dcae/common/HttpResponse.java new file mode 100755 index 0000000..3d69ec8 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/HttpResponse.java @@ -0,0 +1,30 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import javax.ws.rs.core.MultivaluedMap; + +public class HttpResponse { + public int code; + public String message; + public String body; + public MultivaluedMap headers; +} diff --git a/src/main/java/org/onap/dcae/common/JsonParser.java b/src/main/java/org/onap/dcae/common/JsonParser.java new file mode 100755 index 0000000..6ce02f2 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/JsonParser.java @@ -0,0 +1,92 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkNotNull; + +public class JsonParser { + + private static final Logger log = LoggerFactory.getLogger(JsonParser.class); + + private JsonParser() { + // Preventing instantiation of the same. + } + + @SuppressWarnings("unchecked") + public static Map convertToProperties(String s) + throws Exception { + + checkNotNull(s, "Input should not be null."); + + try { + JSONObject json = new JSONObject(s); + Map wm = new HashMap<>(); + Iterator ii = json.keys(); + while (ii.hasNext()) { + String key1 = ii.next(); + wm.put(key1, json.get(key1)); + } + + Map mm = new HashMap<>(); + + while (!wm.isEmpty()) + for (String key : new ArrayList<>(wm.keySet())) { + Object o = wm.get(key); + wm.remove(key); + + if (o instanceof Boolean || o instanceof Number || o instanceof String) { + mm.put(key, o.toString()); + + log.info("Added property: {} : {}", key, o.toString()); + } else if (o instanceof JSONObject) { + JSONObject jo = (JSONObject) o; + Iterator i = jo.keys(); + while (i.hasNext()) { + String key1 = i.next(); + wm.put(key + "." + key1, jo.get(key1)); + } + } else if (o instanceof JSONArray) { + JSONArray ja = (JSONArray) o; + mm.put(key + "_length", String.valueOf(ja.length())); + + log.info("Added property: {}_length: {}", key, String.valueOf(ja.length())); + + for (int i = 0; i < ja.length(); i++) + wm.put(key + '[' + i + ']', ja.get(i)); + } + } + return mm; + } catch (JSONException e) { + throw new Exception("Unable to convert JSON to properties" + e.getLocalizedMessage(), e); + } + } +} diff --git a/src/main/java/org/onap/dcae/common/Parameters.java b/src/main/java/org/onap/dcae/common/Parameters.java new file mode 100755 index 0000000..5bc85a5 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/Parameters.java @@ -0,0 +1,52 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import java.util.Set; + +public class Parameters { + public String templateFileName; + public String restapiUrl; + public String restapiUser; + public String restapiPassword; + public Format format; + public String contentType; + public HttpMethod httpMethod; + public String responsePrefix; + public Set listNameList; + public boolean skipSending; + public boolean convertResponse; + public String keyStoreFileName; + public String keyStorePassword; + public String trustStoreFileName; + public String trustStorePassword; + public boolean ssl; + public String customHttpHeaders; + public String partner; + public Boolean dumpHeaders; + public String requestBody; + public String oAuthConsumerKey; + public String oAuthConsumerSecret; + public String oAuthSignatureMethod; + public String oAuthVersion; + public AuthType authtype; + public Boolean returnRequestPayload; +} diff --git a/src/main/java/org/onap/dcae/common/RestConfContext.java b/src/main/java/org/onap/dcae/common/RestConfContext.java new file mode 100755 index 0000000..0f95151 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/RestConfContext.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import java.util.HashMap; +import java.util.Set; + +public class RestConfContext { + private HashMap attributes; + + public RestConfContext() { + attributes = new HashMap<>(); + } + + public String getAttribute(String name) { + return attributes.getOrDefault(name, null); + } + + public void setAttribute(String name, String value) { + if (value == null) { + if (attributes.containsKey(name)) { + attributes.remove(name); + } + } else { + attributes.put(name, value); + } + } + + public Set getAttributeKeySet() { + return attributes.keySet(); + } + +} diff --git a/src/main/java/org/onap/dcae/common/RestapiCallNode.java b/src/main/java/org/onap/dcae/common/RestapiCallNode.java new file mode 100755 index 0000000..af0245d --- /dev/null +++ b/src/main/java/org/onap/dcae/common/RestapiCallNode.java @@ -0,0 +1,467 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import com.sun.jersey.api.client.*; +import com.sun.jersey.api.client.config.ClientConfig; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; +import com.sun.jersey.api.client.filter.HTTPDigestAuthFilter; +import com.sun.jersey.api.client.filter.LoggingFilter; +import com.sun.jersey.client.urlconnection.HTTPSProperties; +import com.sun.jersey.oauth.client.OAuthClientFilter; +import com.sun.jersey.oauth.signature.OAuthParameters; +import com.sun.jersey.oauth.signature.OAuthSecrets; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.ws.rs.core.EntityTag; +import javax.ws.rs.core.MultivaluedMap; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.SocketException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyStore; +import java.util.*; + +import static org.onap.dcae.common.RestapiCallNodeUtil.getParameters; +import static org.onap.dcae.common.RestapiCallNodeUtil.parseParam; + +public class RestapiCallNode { + private static final Logger log = LoggerFactory.getLogger(RestapiCallNode.class); + + public void sendRequest(Map paramMap, RestConfContext ctx, Integer retryCount) throws Exception { + HttpResponse r = new HttpResponse(); + try { + Parameters p = getParameters(paramMap); + String pp = p.responsePrefix != null ? p.responsePrefix + '.' : ""; + String req = null; + if (p.templateFileName != null) { + log.info("p.templateFileName " + p.templateFileName); + String reqTemplate = readFile(p.templateFileName); + req = buildXmlJsonRequest(ctx, reqTemplate, p.format); + } else if (p.requestBody != null) { + req = p.requestBody; + } + + r = sendHttpRequest(req, p); + setResponseStatus(ctx, p.responsePrefix, r); + + if (p.dumpHeaders && r.headers != null) { + for (Map.Entry> a : r.headers.entrySet()) { + ctx.setAttribute(pp + "header." + a.getKey(), StringUtils.join(a.getValue(), ",")); + } + } + + if (p.returnRequestPayload && req != null) { + ctx.setAttribute(pp + "httpRequest", req); + } + + if (r.body != null && r.body.trim().length() > 0) { + ctx.setAttribute(pp + "httpResponse", r.body); + + if (p.convertResponse) { + Map mm = null; + if (p.format == Format.XML) { + mm = XmlParser.convertToProperties(r.body, p.listNameList); + } else if (p.format == Format.JSON) { + mm = JsonParser.convertToProperties(r.body); + } + + if (mm != null) { + for (Map.Entry entry : mm.entrySet()) { + ctx.setAttribute(pp + entry.getKey(), entry.getValue()); + log.info("ctx.setAttribute :=> {} value {} ", pp + entry.getKey(), entry.getValue()); + } + } + } + } + } catch (Exception e) { + boolean shouldRetry = false; + if (e.getCause().getCause() instanceof SocketException) { + shouldRetry = true; + } + + log.error("Error sending the request: " + e.getMessage(), e); + String prefix = parseParam(paramMap, "responsePrefix", false, null); + if (!shouldRetry || (retryCount == null) || (retryCount == 0)) { + setFailureResponseStatus(ctx, prefix, e.getMessage(), r); + } else { + try { + retryCount = retryCount - 1; + log.debug("This is retry attempt {} ", retryCount); + sendRequest(paramMap, ctx, retryCount); + } catch (Exception ex) { + log.error("Could not attempt retry.", ex); + String retryErrorMessage = + "Retry attempt has failed. No further retry shall be attempted, calling " + + "setFailureResponseStatus."; + setFailureResponseStatus(ctx, prefix, retryErrorMessage, r); + } + } + } + + if (r != null && r.code >= 300) { + throw new Exception(String.valueOf(r.code) + ": " + r.message); + } + } + + protected String buildXmlJsonRequest(RestConfContext ctx, String template, Format format) throws Exception { + log.info("Building {} started", format); + long t1 = System.currentTimeMillis(); + + template = expandRepeats(ctx, template, 1); + + Map mm = new HashMap<>(); + for (String s : ctx.getAttributeKeySet()) { + mm.put(s, ctx.getAttribute(s)); + } + StringBuilder ss = new StringBuilder(); + int i = 0; + while (i < template.length()) { + int i1 = template.indexOf("${", i); + if (i1 < 0) { + ss.append(template.substring(i)); + break; + } + + int i2 = template.indexOf('}', i1 + 2); + if (i2 < 0) { + throw new Exception("Template error: Matching } not found"); + } + + String var1 = template.substring(i1 + 2, i2); + String value1 = format == Format.XML ? XmlJsonUtil.getXml(mm, var1) : XmlJsonUtil.getJson(mm, var1); + if (value1 == null || value1.trim().length() == 0) { + // delete the whole element (line) + int i3 = template.lastIndexOf('\n', i1); + if (i3 < 0) { + i3 = 0; + } + int i4 = template.indexOf('\n', i1); + if (i4 < 0) { + i4 = template.length(); + } + + if (i < i3) { + ss.append(template.substring(i, i3)); + } + i = i4; + } else { + ss.append(template.substring(i, i1)).append(value1); + i = i2 + 1; + } + } + + String req = format == Format.XML + ? XmlJsonUtil.removeEmptyStructXml(ss.toString()) : XmlJsonUtil.removeEmptyStructJson(ss.toString()); + + if (format == Format.JSON) { + req = XmlJsonUtil.removeLastCommaJson(req); + } + + long t2 = System.currentTimeMillis(); + log.info("Building {} completed. Time: {}", format, (t2 - t1)); + + return req; + } + + protected String expandRepeats(RestConfContext ctx, String template, int level) throws Exception { + StringBuilder newTemplate = new StringBuilder(); + int k = 0; + while (k < template.length()) { + int i1 = template.indexOf("${repeat:", k); + if (i1 < 0) { + newTemplate.append(template.substring(k)); + break; + } + + int i2 = template.indexOf(':', i1 + 9); + if (i2 < 0) { + throw new Exception( + "Template error: Context variable name followed by : is required after repeat"); + } + + // Find the closing }, store in i3 + int nn = 1; + int i3 = -1; + int i = i2; + while (nn > 0 && i < template.length()) { + i3 = template.indexOf('}', i); + if (i3 < 0) { + throw new Exception("Template error: Matching } not found"); + } + int i32 = template.indexOf('{', i); + if (i32 >= 0 && i32 < i3) { + nn++; + i = i32 + 1; + } else { + nn--; + i = i3 + 1; + } + } + + String var1 = template.substring(i1 + 9, i2); + String value1 = ctx.getAttribute(var1); + log.info(" {}:{}", var1, value1); + int n = 0; + try { + n = Integer.parseInt(value1); + } catch (NumberFormatException e) { + log.info("value1 not set or not a number, n will remain set at zero"); + } + + newTemplate.append(template.substring(k, i1)); + + String rpt = template.substring(i2 + 1, i3); + + for (int ii = 0; ii < n; ii++) { + String ss = rpt.replaceAll("\\[\\$\\{" + level + "\\}\\]", "[" + ii + "]"); + if (ii == n - 1 && ss.trim().endsWith(",")) { + int i4 = ss.lastIndexOf(','); + if (i4 > 0) { + ss = ss.substring(0, i4) + ss.substring(i4 + 1); + } + } + newTemplate.append(ss); + } + + k = i3 + 1; + } + + if (k == 0) { + return newTemplate.toString(); + } + + return expandRepeats(ctx, newTemplate.toString(), level + 1); + } + + protected String readFile(String fileName) throws Exception { + try { + byte[] encoded = Files.readAllBytes(Paths.get(fileName)); + return new String(encoded, "UTF-8"); + } catch (IOException | SecurityException e) { + throw new Exception("Unable to read file " + fileName + e.getLocalizedMessage(), e); + } + } + + protected Client addAuthType(Client client, Parameters p) throws Exception { + if (p.authtype == AuthType.Unspecified) { + if (p.restapiUser != null && p.restapiPassword != null) { + client.addFilter(new HTTPBasicAuthFilter(p.restapiUser, p.restapiPassword)); + } else if (p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null + && p.oAuthSignatureMethod != null) { + OAuthParameters params = new OAuthParameters() + .signatureMethod(p.oAuthSignatureMethod) + .consumerKey(p.oAuthConsumerKey) + .version(p.oAuthVersion); + + OAuthSecrets secrets = new OAuthSecrets() + .consumerSecret(p.oAuthConsumerSecret); + client.addFilter(new OAuthClientFilter(client.getProviders(), params, secrets)); + } + } else { + if (p.authtype == AuthType.DIGEST) { + if (p.restapiUser != null && p.restapiPassword != null) { + client.addFilter(new HTTPDigestAuthFilter(p.restapiUser, p.restapiPassword)); + } else { + throw new Exception("oAUTH authentication type selected but all restapiUser and restapiPassword " + + "parameters doesn't exist", new Throwable()); + } + } else if (p.authtype == AuthType.BASIC) { + if (p.restapiUser != null && p.restapiPassword != null) { + client.addFilter(new HTTPBasicAuthFilter(p.restapiUser, p.restapiPassword)); + } else { + throw new Exception("oAUTH authentication type selected but all restapiUser and restapiPassword " + + "parameters doesn't exist", new Throwable()); + } + } else if (p.authtype == AuthType.OAUTH) { + if (p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null && p.oAuthSignatureMethod != null) { + OAuthParameters params = new OAuthParameters() + .signatureMethod(p.oAuthSignatureMethod) + .consumerKey(p.oAuthConsumerKey) + .version(p.oAuthVersion); + + OAuthSecrets secrets = new OAuthSecrets() + .consumerSecret(p.oAuthConsumerSecret); + client.addFilter(new OAuthClientFilter(client.getProviders(), params, secrets)); + } else { + throw new Exception("oAUTH authentication type selected but all oAuthConsumerKey, voAuthConsumerSecret " + + "and oAuthSignatureMethod parameters doesn't exist", new Throwable()); + } + } + } + return client; + } + + protected HttpResponse sendHttpRequest(String request, Parameters p) throws Exception { + ClientConfig config = new DefaultClientConfig(); + SSLContext ssl = null; + if (p.ssl && p.restapiUrl.startsWith("https")) { + ssl = createSSLContext(p); + } + if (ssl != null) { + HostnameVerifier hostnameVerifier = (hostname, session) -> true; + + config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, + new HTTPSProperties(hostnameVerifier, ssl)); + } + + logProperties(config.getProperties()); + + Client client = Client.create(config); + client.setConnectTimeout(5000); + client.addFilter(new LoggingFilter()); + WebResource webResource = addAuthType(client, p).resource(p.restapiUrl); + + log.info("Sending request:"); + log.info(request); + log.info("URL: " + p.restapiUrl + " method " + p.httpMethod.toString() + " Custome headr " + p.customHttpHeaders); + + long t1 = System.currentTimeMillis(); + + HttpResponse r = new HttpResponse(); + r.code = 200; + + if (!p.skipSending) { + String tt = p.format == Format.XML ? "application/xml" : "application/json"; + String tt1 = tt + ";charset=UTF-8"; + if (p.contentType != null) { + tt = p.contentType; + tt1 = p.contentType; + } + + WebResource.Builder webResourceBuilder = webResource.accept(tt).type(tt1); + if (p.format == Format.NONE) { + webResourceBuilder = webResource.header("", ""); + } + + if (p.customHttpHeaders != null && p.customHttpHeaders.length() > 0) { + String[] keyValuePairs = p.customHttpHeaders.split(","); + for (String singlePair : keyValuePairs) { + int equalPosition = singlePair.indexOf('='); + webResourceBuilder.header(singlePair.substring(0, equalPosition), + singlePair.substring(equalPosition + 1, singlePair.length())); + } + } + + ClientResponse response; + + try { + response = webResourceBuilder.method(p.httpMethod.toString(), ClientResponse.class, request); + } catch (UniformInterfaceException | ClientHandlerException e) { + throw new Exception("Exception while sending http request to client " + + e.getLocalizedMessage(), e); + } + + r.code = response.getStatus(); + r.headers = response.getHeaders(); + EntityTag etag = response.getEntityTag(); + if (etag != null) { + r.message = etag.getValue(); + } + if (response.hasEntity() && r.code != 204) { + r.body = response.getEntity(String.class); + } + } + + long t2 = System.currentTimeMillis(); + log.info("Response received. Time: {}", (t2 - t1)); + log.info("HTTP response code: {}", r.code); + log.info("HTTP response message: {}", r.message); + logHeaders(r.headers); + log.info("HTTP response: {}", r.body); + + return r; + } + + protected void setFailureResponseStatus(RestConfContext ctx, String prefix, String errorMessage, + HttpResponse resp) { + resp.code = 500; + resp.message = errorMessage; + String pp = prefix != null ? prefix + '.' : ""; + ctx.setAttribute(pp + "response-code", String.valueOf(resp.code)); + ctx.setAttribute(pp + "response-message", resp.message); + } + + protected void setResponseStatus(RestConfContext ctx, String prefix, HttpResponse r) { + String pp = prefix != null ? prefix + '.' : ""; + ctx.setAttribute(pp + "response-code", String.valueOf(r.code)); + ctx.setAttribute(pp + "response-message", r.message); + } + + protected SSLContext createSSLContext(Parameters p) { + try (FileInputStream in = new FileInputStream(p.keyStoreFileName)) { + System.setProperty("jsse.enableSNIExtension", "false"); + System.setProperty("javax.net.ssl.trustStore", p.trustStoreFileName); + System.setProperty("javax.net.ssl.trustStorePassword", p.trustStorePassword); + + HttpsURLConnection.setDefaultHostnameVerifier((string, ssls) -> true); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + KeyStore ks = KeyStore.getInstance("PKCS12"); + char[] pwd = p.keyStorePassword.toCharArray(); + log.info("pwd " + pwd + " " + p.keyStorePassword); + ks.load(in, pwd); + kmf.init(ks, pwd); + + SSLContext ctx = SSLContext.getInstance("TLS"); + ctx.init(kmf.getKeyManagers(), null, null); + return ctx; + } catch (Exception e) { + log.error("Error creating SSLContext: {}", e.getMessage(), e); + } + return null; + } + + protected void logProperties(Map mm) { + List ll = new ArrayList<>(); + for (Object o : mm.keySet()) + ll.add((String) o); + Collections.sort(ll); + + log.info("Properties:"); + for (String name : ll) + log.info("--- {}:{}", name, String.valueOf(mm.get(name))); + } + + protected void logHeaders(MultivaluedMap mm) { + log.info("HTTP response headers:"); + + if (mm == null) { + return; + } + + List ll = new ArrayList<>(); + for (Object o : mm.keySet()) + ll.add((String) o); + Collections.sort(ll); + + for (String name : ll) + log.info("--- {}:{}", name, String.valueOf(mm.get(name))); + } +} \ No newline at end of file diff --git a/src/main/java/org/onap/dcae/common/RestapiCallNodeUtil.java b/src/main/java/org/onap/dcae/common/RestapiCallNodeUtil.java new file mode 100755 index 0000000..1ff00dd --- /dev/null +++ b/src/main/java/org/onap/dcae/common/RestapiCallNodeUtil.java @@ -0,0 +1,194 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; +import org.glassfish.jersey.client.oauth1.ConsumerCredentials; +import org.glassfish.jersey.client.oauth1.OAuth1ClientSupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.client.Client; +import javax.ws.rs.core.Feature; +import java.net.URI; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class RestapiCallNodeUtil { + + private static final Logger log = LoggerFactory.getLogger(RestapiCallNodeUtil.class); + + + private RestapiCallNodeUtil() { + // Preventing instantiation of the same. + } + + public static String getUriMethod(Boolean authEnabled) { + /*@TODO: As per configuration */ +// String uri; +// if (authEnabled) { +// uri = "https://"; +// } else { +// uri = "http://"; +// } + return "https://"; + } + + public static Parameters getParameters(Map paramMap) throws Exception { + Parameters p = new Parameters(); + p.templateFileName = parseParam(paramMap, "templateFileName", false, null); + p.requestBody = parseParam(paramMap, "requestBody", false, null); + p.restapiUrl = parseParam(paramMap, "restapiUrl", true, null); + validateUrl(p.restapiUrl); + p.restapiUser = null;//parseParam(paramMap, "restapiUser", false, null); + p.restapiPassword = null;//parseParam(paramMap, "restapiPassword", false, null); + p.oAuthConsumerKey = parseParam(paramMap, "oAuthConsumerKey", false, null); + p.oAuthConsumerSecret = parseParam(paramMap, "oAuthConsumerSecret", false, null); + p.oAuthSignatureMethod = parseParam(paramMap, "oAuthSignatureMethod", false, null); + p.oAuthVersion = parseParam(paramMap, "oAuthVersion", false, null); + p.contentType = parseParam(paramMap, "contentType", false, null); + p.format = Format.fromString(parseParam(paramMap, "format", false, "json")); + p.authtype = AuthType.fromString(parseParam(paramMap, "authType", false, "unspecified")); + p.httpMethod = HttpMethod.fromString(parseParam(paramMap, "httpMethod", false, "post")); + p.responsePrefix = parseParam(paramMap, "responsePrefix", false, null); + p.listNameList = getListNameList(paramMap); + String skipSendingStr = paramMap.get("skipSending"); + p.skipSending = "true".equalsIgnoreCase(skipSendingStr); + p.convertResponse = Boolean.valueOf(parseParam(paramMap, "convertResponse", false, "true")); + p.trustStoreFileName = parseParam(paramMap, "trustStoreFileName", false, null); + p.trustStorePassword = parseParam(paramMap, "trustStorePassword", false, null); + p.keyStoreFileName = parseParam(paramMap, "keyStoreFileName", false, null); + p.keyStorePassword = parseParam(paramMap, "keyStorePassword", false, null); + p.ssl = p.trustStoreFileName != null && p.trustStorePassword != null && p.keyStoreFileName != null && + p.keyStorePassword != null; + p.customHttpHeaders = parseParam(paramMap, "customHttpHeaders", false, null); + p.partner = parseParam(paramMap, "partner", false, null); + p.dumpHeaders = Boolean.valueOf(parseParam(paramMap, "dumpHeaders", false, null)); + p.returnRequestPayload = Boolean.valueOf(parseParam(paramMap, "returnRequestPayload", false, null)); + log.info(p.toString()); + return p; + } + + + public static String parseParam(Map paramMap, String name, boolean required, String def) + throws Exception { + String s = paramMap.get(name); + + if (s == null || s.trim().length() == 0) { + if (!required) { + return def; + } + throw new Exception("Parameter " + name + " is required in RestapiCallNode"); + } + + s = s.trim(); + StringBuilder value = new StringBuilder(); + int i = 0; + int i1 = s.indexOf('%'); + while (i1 >= 0) { + int i2 = s.indexOf('%', i1 + 1); + if (i2 < 0) { + break; + } + + String varName = s.substring(i1 + 1, i2); + String varValue = System.getenv(varName); + if (varValue == null) { + varValue = "%" + varName + "%"; + } + + value.append(s.substring(i, i1)); + value.append(varValue); + + i = i2 + 1; + i1 = s.indexOf('%', i); + } + value.append(s.substring(i)); + + log.info("Parameter {}: [{}]", name, value); + return value.toString(); + } + + private static void validateUrl(String restapiUrl) throws Exception { + try { + URI.create(restapiUrl); + } catch (IllegalArgumentException e) { + throw new Exception("Invalid input of url " + e.getLocalizedMessage(), e); + } + } + + private static Set getListNameList(Map paramMap) { + Set ll = new HashSet<>(); + for (Map.Entry entry : paramMap.entrySet()) + if (entry.getKey().startsWith("listName")) { + ll.add(entry.getValue()); + } + return ll; + } + + public static Client addAuthType(Client client, Parameters p) { + if (p != null) { + if (p.authtype == AuthType.Unspecified) { + if (p.restapiUser != null && p.restapiPassword != null) { + client.register(HttpAuthenticationFeature.basic(p.restapiUser, p.restapiPassword)); + } else if (p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null + && p.oAuthSignatureMethod != null) { + Feature oAuth1Feature = OAuth1ClientSupport + .builder(new ConsumerCredentials(p.oAuthConsumerKey, p.oAuthConsumerSecret)) + .version(p.oAuthVersion).signatureMethod(p.oAuthSignatureMethod).feature().build(); + client.register(oAuth1Feature); + } + } else { + if (p.authtype == AuthType.DIGEST) { + if (p.restapiUser != null && p.restapiPassword != null) { + client.register(HttpAuthenticationFeature.digest(p.restapiUser, p.restapiPassword)); + } else { + throw new IllegalArgumentException( + "oAUTH authentication type selected but all restapiUser and restapiPassword " + + "parameters doesn't exist", new Throwable()); + } + } else if (p.authtype == AuthType.BASIC) { + if (p.restapiUser != null && p.restapiPassword != null) { + client.register(HttpAuthenticationFeature.basic(p.restapiUser, p.restapiPassword)); + } else { + throw new IllegalArgumentException( + "oAUTH authentication type selected but all restapiUser and restapiPassword " + + "parameters doesn't exist", new Throwable()); + } + } else if (p.authtype == AuthType.OAUTH) { + if (p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null && p.oAuthSignatureMethod != null) { + Feature oAuth1Feature = OAuth1ClientSupport + .builder(new ConsumerCredentials(p.oAuthConsumerKey, p.oAuthConsumerSecret)) + .version(p.oAuthVersion).signatureMethod(p.oAuthSignatureMethod).feature().build(); + client.register(oAuth1Feature); + } else { + throw new IllegalArgumentException( + "oAUTH authentication type selected but all oAuthConsumerKey, oAuthConsumerSecret " + + "and oAuthSignatureMethod parameters doesn't exist", new Throwable()); + } + } + } + } + return client; + } +} + diff --git a/src/main/java/org/onap/dcae/common/SSLContextCreator.java b/src/main/java/org/onap/dcae/common/SSLContextCreator.java new file mode 100644 index 0000000..db3d123 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/SSLContextCreator.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import org.springframework.boot.web.server.Ssl; + +import java.nio.file.Path; + +public class SSLContextCreator { + private final String keyStorePassword; + private final String certAlias; + private final Path keyStoreFile; + + private Path trustStoreFile; + private String trustStorePassword; + private boolean hasTlsClientAuthentication = false; + + public static SSLContextCreator create(final Path keyStoreFile, final String certAlias, final String password) { + return new SSLContextCreator(keyStoreFile, certAlias, password); + } + + private SSLContextCreator(final Path keyStoreFile, final String certAlias, final String password) { + this.certAlias = certAlias; + this.keyStoreFile = keyStoreFile; + this.keyStorePassword = password; + } + + public SSLContextCreator withTlsClientAuthentication(final Path trustStoreFile, final String password) { + hasTlsClientAuthentication = true; + this.trustStoreFile = trustStoreFile; + this.trustStorePassword = password; + + return this; + } + + private void configureKeyStore(final Ssl ssl) { + final String keyStore = keyStoreFile.toAbsolutePath().toString(); + + ssl.setKeyStore(keyStore); + ssl.setKeyPassword(keyStorePassword); + ssl.setKeyAlias(certAlias); + } + + private void configureTrustStore(final Ssl ssl) { + final String trustStore = trustStoreFile.toAbsolutePath().toString(); + + ssl.setTrustStore(trustStore); + ssl.setTrustStorePassword(trustStorePassword); + ssl.setClientAuth(Ssl.ClientAuth.NEED); + } + + public Ssl build() { + final Ssl ssl = new Ssl(); + ssl.setEnabled(true); + + configureKeyStore(ssl); + + if (hasTlsClientAuthentication) { + configureTrustStore(ssl); + } + + return ssl; + } +} \ No newline at end of file diff --git a/src/main/java/org/onap/dcae/common/XmlJsonUtil.java b/src/main/java/org/onap/dcae/common/XmlJsonUtil.java new file mode 100755 index 0000000..877f9e5 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/XmlJsonUtil.java @@ -0,0 +1,412 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class XmlJsonUtil { + + private static final Logger log = LoggerFactory.getLogger(XmlJsonUtil.class); + + private XmlJsonUtil() { + // Preventing instantiation of the same. + } + + public static String getXml(Map varmap, String var) { + boolean escape = true; + if (var.startsWith("'")) { + var = var.substring(1); + escape = false; + } + + Object o = createStructure(varmap, var); + return generateXml(o, 0, escape); + } + + public static String getJson(Map varmap, String var) { + boolean escape = true; + if (var.startsWith("'")) { + var = var.substring(1); + escape = false; + } + + boolean quotes = true; + if (var.startsWith("\"")) { + var = var.substring(1); + quotes = false; + } + + Object o = createStructure(varmap, var); + return generateJson(o, escape, quotes); + } + + private static Object createStructure(Map flatmap, String var) { + if (flatmap.containsKey(var)) { + if (var.endsWith("_length") || var.endsWith("].key")) { + return null; + } + return flatmap.get(var); + } + + Map mm = new HashMap<>(); + for (String k : flatmap.keySet()) + if (k.startsWith(var + ".")) { + int i1 = k.indexOf('.', var.length() + 1); + int i2 = k.indexOf('[', var.length() + 1); + int i3 = k.length(); + if (i1 > 0 && i1 < i3) { + i3 = i1; + } + if (i2 > 0 && i2 < i3) { + i3 = i2; + } + String k1 = k.substring(var.length() + 1, i3); + String var1 = k.substring(0, i3); + if (!mm.containsKey(k1)) { + Object str = createStructure(flatmap, var1); + if (str != null && (!(str instanceof String) || ((String) str).trim().length() > 0)) { + mm.put(k1, str); + } + } + } + if (!mm.isEmpty()) { + return mm; + } + + boolean arrayFound = false; + for (String k : flatmap.keySet()) + if (k.startsWith(var + "[")) { + arrayFound = true; + break; + } + + if (arrayFound) { + List ll = new ArrayList<>(); + + int length = Integer.MAX_VALUE; + String lengthStr = flatmap.get(var + "_length"); + if (lengthStr != null) { + try { + length = Integer.parseInt(lengthStr); + } catch (Exception e) { + log.warn("Invalid number for {}_length:{}", var, lengthStr, e); + } + } + + for (int i = 0; i < length; i++) { + Object v = createStructure(flatmap, var + '[' + i + ']'); + if (v == null) { + break; + } + ll.add(v); + } + + if (!ll.isEmpty()) { + return ll; + } + } + + return null; + } + + @SuppressWarnings("unchecked") + private static String generateXml(Object o, int indent, boolean escape) { + if (o == null) { + return null; + } + + if (o instanceof String) { + return escape ? escapeXml((String) o) : (String) o; + } + ; + + if (o instanceof Map) { + StringBuilder ss = new StringBuilder(); + Map mm = (Map) o; + for (Map.Entry entry : mm.entrySet()) { + Object v = entry.getValue(); + String key = entry.getKey(); + if (v instanceof String) { + String s = escape ? escapeXml((String) v) : (String) v; + ss.append(pad(indent)).append('<').append(key).append('>'); + ss.append(s); + ss.append("').append('\n'); + } else if (v instanceof Map) { + ss.append(pad(indent)).append('<').append(key).append('>').append('\n'); + ss.append(generateXml(v, indent + 1, escape)); + ss.append(pad(indent)).append("').append('\n'); + } else if (v instanceof List) { + List ll = (List) v; + for (Object o1 : ll) { + ss.append(pad(indent)).append('<').append(key).append('>').append('\n'); + ss.append(generateXml(o1, indent + 1, escape)); + ss.append(pad(indent)).append("').append('\n'); + } + } + } + return ss.toString(); + } + + return null; + } + + private static String generateJson(Object o, boolean escape, boolean quotes) { + if (o == null) { + return null; + } + + StringBuilder ss = new StringBuilder(); + generateJson(ss, o, 0, false, escape, quotes); + return ss.toString(); + } + + @SuppressWarnings("unchecked") + private static void generateJson(StringBuilder ss, Object o, int indent, boolean padFirst, boolean escape, boolean quotes) { + if (o instanceof String) { + String s = escape ? escapeJson((String) o) : (String) o; + if (padFirst) { + ss.append(pad(indent)); + } + if (quotes) { + ss.append('"').append(s).append('"'); + } else { + ss.append(s); + } + return; + } + + if (o instanceof Map) { + Map mm = (Map) o; + + if (padFirst) { + ss.append(pad(indent)); + } + ss.append("{\n"); + + boolean first = true; + for (Map.Entry entry : mm.entrySet()) { + if (!first) { + ss.append(",\n"); + } + first = false; + Object v = entry.getValue(); + String key = entry.getKey(); + ss.append(pad(indent + 1)).append('"').append(key).append("\": "); + generateJson(ss, v, indent + 1, false, escape, true); + } + + ss.append("\n"); + ss.append(pad(indent)).append('}'); + + return; + } + + if (o instanceof List) { + List ll = (List) o; + + if (padFirst) { + ss.append(pad(indent)); + } + ss.append("[\n"); + + boolean first = true; + for (Object o1 : ll) { + if (!first) { + ss.append(",\n"); + } + first = false; + + generateJson(ss, o1, indent + 1, true, escape, quotes); + } + + ss.append("\n"); + ss.append(pad(indent)).append(']'); + } + } + + public static String removeLastCommaJson(String s) { + StringBuilder sb = new StringBuilder(); + int k = 0; + int start = 0; + while (k < s.length()) { + int i11 = s.indexOf('}', k); + int i12 = s.indexOf(']', k); + int i1 = -1; + if (i11 < 0) { + i1 = i12; + } else if (i12 < 0) { + i1 = i11; + } else { + i1 = i11 < i12 ? i11 : i12; + } + if (i1 < 0) { + break; + } + + int i2 = s.lastIndexOf(',', i1); + if (i2 < 0) { + k = i1 + 1; + continue; + } + + String between = s.substring(i2 + 1, i1); + if (between.trim().length() > 0) { + k = i1 + 1; + continue; + } + + sb.append(s.substring(start, i2)); + start = i2 + 1; + k = i1 + 1; + } + + sb.append(s.substring(start, s.length())); + + return sb.toString(); + } + + public static String removeEmptyStructJson(String s) { + int k = 0; + while (k < s.length()) { + boolean curly = true; + int i11 = s.indexOf('{', k); + int i12 = s.indexOf('[', k); + int i1 = -1; + if (i11 < 0) { + i1 = i12; + curly = false; + } else if (i12 < 0) { + i1 = i11; + } else if (i11 < i12) { + i1 = i11; + } else { + i1 = i12; + curly = false; + } + + if (i1 >= 0) { + int i2 = curly ? s.indexOf('}', i1) : s.indexOf(']', i1); + if (i2 > 0) { + String value = s.substring(i1 + 1, i2); + if (value.trim().length() == 0) { + int i4 = s.lastIndexOf('\n', i1); + if (i4 < 0) { + i4 = 0; + } + int i5 = s.indexOf('\n', i2); + if (i5 < 0) { + i5 = s.length(); + } + + s = s.substring(0, i4) + s.substring(i5); + k = 0; + } else { + k = i1 + 1; + } + } else { + break; + } + } else { + break; + } + } + + return s; + } + + public static String removeEmptyStructXml(String s) { + int k = 0; + while (k < s.length()) { + int i1 = s.indexOf('<', k); + if (i1 < 0 || i1 == s.length() - 1) { + break; + } + + char c1 = s.charAt(i1 + 1); + if (c1 == '?' || c1 == '!') { + k = i1 + 2; + continue; + } + + int i2 = s.indexOf('>', i1); + if (i2 < 0) { + k = i1 + 1; + continue; + } + + String closingTag = " 0) { + k = i2 + 1; + continue; + } + + int i4 = s.lastIndexOf('\n', i1); + if (i4 < 0) { + i4 = 0; + } + int i5 = s.indexOf('\n', i3); + if (i5 < 0) { + i5 = s.length(); + } + + s = s.substring(0, i4) + s.substring(i5); + k = 0; + } + + return s; + } + + private static String escapeXml(String v) { + String s = v.replaceAll("&", "&"); + s = s.replaceAll("<", "<"); + s = s.replaceAll("'", "'"); + s = s.replaceAll("\"", """); + s = s.replaceAll(">", ">"); + return s; + } + + private static String escapeJson(String v) { + String s = v.replaceAll("\\\\", "\\\\\\\\"); + s = s.replaceAll("\"", "\\\\\""); + return s; + } + + private static String pad(int n) { + StringBuilder s = new StringBuilder(); + for (int i = 0; i < n; i++) + s.append(Character.toString('\t')); + return s.toString(); + } +} + diff --git a/src/main/java/org/onap/dcae/common/XmlParser.java b/src/main/java/org/onap/dcae/common/XmlParser.java new file mode 100755 index 0000000..06a4a66 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/XmlParser.java @@ -0,0 +1,178 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkNotNull; + +public class XmlParser { + + private static final Logger log = LoggerFactory.getLogger(XmlParser.class); + + private XmlParser() { + // Preventing instantiation of the same. + } + + public static Map convertToProperties(String s, Set listNameList) + throws Exception { + + checkNotNull(s, "Input should not be null."); + + Handler handler = new Handler(listNameList); + try { + SAXParserFactory factory = SAXParserFactory.newInstance(); + SAXParser saxParser = factory.newSAXParser(); + InputStream in = new ByteArrayInputStream(s.getBytes()); + saxParser.parse(in, handler); + } catch (ParserConfigurationException | IOException | SAXException | NumberFormatException e) { + throw new Exception("Unable to convert XML to properties" + e.getLocalizedMessage(), e); + } + return handler.getProperties(); + } + + private static class Handler extends DefaultHandler { + + private Set listNameList; + + private Map properties = new HashMap<>(); + + public Map getProperties() { + return properties; + } + + public Handler(Set listNameList) { + super(); + this.listNameList = listNameList; + if (this.listNameList == null) { + this.listNameList = new HashSet<>(); + } + } + + StringBuilder currentName = new StringBuilder(); + StringBuilder currentValue = new StringBuilder(); + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { + super.startElement(uri, localName, qName, attributes); + + String name = localName; + if (name == null || name.trim().length() == 0) { + name = qName; + } + int i2 = name.indexOf(':'); + if (i2 >= 0) { + name = name.substring(i2 + 1); + } + + if (currentName.length() > 0) { + currentName.append(Character.toString('.')); + } + currentName.append(name); + + String listName = removeIndexes(currentName.toString()); + + if (listNameList.contains(listName)) { + String n = currentName.toString() + "_length"; + int len = getInt(properties, n); + properties.put(n, String.valueOf(len + 1)); + currentName.append("[").append(len).append("]"); + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + super.endElement(uri, localName, qName); + + String name = localName; + if (name == null || name.trim().length() == 0) { + name = qName; + } + int i2 = name.indexOf(':'); + if (i2 >= 0) { + name = name.substring(i2 + 1); + } + + String s = currentValue.toString().trim(); + if (s.length() > 0) { + properties.put(currentName.toString(), s); + + log.info("Added property: {} : {}", currentName, s); + currentValue = new StringBuilder(); + } + + int i1 = currentName.lastIndexOf("." + name); + if (i1 <= 0) { + currentName = new StringBuilder(); + } else { + currentName = new StringBuilder(currentName.substring(0, i1)); + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + super.characters(ch, start, length); + + String value = new String(ch, start, length); + currentValue.append(value); + } + + private static int getInt(Map mm, String name) { + String s = mm.get(name); + if (s == null) { + return 0; + } + return Integer.parseInt(s); + } + + private String removeIndexes(String currentName) { + StringBuilder b = new StringBuilder(); + boolean add = true; + for (int i = 0; i < currentName.length(); i++) { + char c = currentName.charAt(i); + if (c == '[') { + add = false; + } else if (c == ']') { + add = true; + } else if (add) { + b.append(Character.toString(c)); + } + } + return b.toString(); + } + } +} diff --git a/src/main/java/org/onap/dcae/common/publishing/DMaaPConfigurationParser.java b/src/main/java/org/onap/dcae/common/publishing/DMaaPConfigurationParser.java new file mode 100644 index 0000000..dada578 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/publishing/DMaaPConfigurationParser.java @@ -0,0 +1,113 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common.publishing; + +import io.vavr.collection.List; +import io.vavr.collection.Map; +import io.vavr.control.Option; +import io.vavr.control.Try; +import org.onap.dcae.common.AnyNode; + +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.json.JSONObject; + +import static io.vavr.API.*; +import static org.onap.dcae.common.publishing.VavrUtils.enhanceError; +import static org.onap.dcae.common.publishing.VavrUtils.f; + +/** + * @author Pawel Szalapski (pawel.szalapski@nokia.com) + */ +@SuppressWarnings("mapFailure takes a generic varargs, unchecked because of Javas type system limitation, actually safe to do") +public final class DMaaPConfigurationParser { + + public static Try> parseToDomainMapping(Path configLocation) { + return readFromFile(configLocation) + .flatMap(DMaaPConfigurationParser::toJSON) + .flatMap(DMaaPConfigurationParser::toConfigMap); + } + + public static Try> parseToDomainMapping(JSONObject config) { + return toJSON(config.toString()) + .flatMap(DMaaPConfigurationParser::toConfigMap); + } + + private static Try readFromFile(Path configLocation) { + return Try(() -> new String(Files.readAllBytes(configLocation))) + .mapFailure(enhanceError(f("Could not read DMaaP configuration from location: '%s'", configLocation))); + } + + private static Try toJSON(String config) { + return Try(() -> AnyNode.fromString(config)) + .mapFailure(enhanceError(f("DMaaP configuration '%s' is not a valid JSON document", config))); + } + + private static Try> toConfigMap(AnyNode config) { + return Try(() -> usesLegacyFormat(config) ? parseLegacyFormat(config) : parseNewFormat(config)) + .mapFailure(enhanceError(f("Parsing DMaaP configuration: '%s' failed, probably it is in unexpected format", config))); + } + + private static boolean usesLegacyFormat(AnyNode dMaaPConfig) { + return dMaaPConfig.has("channels"); + } + + private static Map parseLegacyFormat(AnyNode root) { + return root.get("channels").toList().toMap( + channel -> channel.get("name").toString(), + channel -> { + String destinationsStr = channel.getAsOption("cambria.url") + .getOrElse(channel.getAsOption("cambria.hosts").get()) + .toString(); + String topic = channel.get("cambria.topic").toString(); + Option maybeUser = channel.getAsOption("basicAuthUsername").map(AnyNode::toString); + Option maybePassword = channel.getAsOption("basicAuthPassword").map(AnyNode::toString); + List destinations = List(destinationsStr.split(",")); + return buildBasedOnAuth(maybeUser, maybePassword, topic, destinations); + }); + } + + private static Map parseNewFormat(AnyNode root) { + return root.keys().toMap( + channelName -> channelName, + channelName -> { + AnyNode channelConfig = root.get(channelName); + Option maybeUser = channelConfig.getAsOption("aaf_username").map(AnyNode::toString); + Option maybePassword = channelConfig.getAsOption("aaf_password").map(AnyNode::toString); + URL topicURL = unchecked( + () -> new URL(channelConfig.get("dmaap_info").get("topic_url").toString())).apply(); + String[] pathSegments = topicURL.getPath().substring(1).split("/"); + String topic = pathSegments[1]; + String destination = "events".equals(pathSegments[0]) ? topicURL.getAuthority() : topicURL.getHost(); + List destinations = List(destination); + return buildBasedOnAuth(maybeUser, maybePassword, topic, destinations); + }); + } + + private static PublisherConfig buildBasedOnAuth(Option maybeUser, Option maybePassword, + String topic, List destinations) { + return maybeUser.flatMap(user -> maybePassword.map(password -> Tuple(user, password))) + .map(credentials -> new PublisherConfig(destinations, topic, credentials._1, credentials._2)) + .getOrElse(new PublisherConfig(destinations, topic)); + } +} diff --git a/src/main/java/org/onap/dcae/common/publishing/DMaaPEventPublisher.java b/src/main/java/org/onap/dcae/common/publishing/DMaaPEventPublisher.java new file mode 100644 index 0000000..1209b38 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/publishing/DMaaPEventPublisher.java @@ -0,0 +1,87 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common.publishing; + +import com.att.nsa.cambria.client.CambriaBatchingPublisher; +import io.vavr.collection.Map; +import io.vavr.control.Try; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +import static org.onap.dcae.common.publishing.VavrUtils.f; + +/** + * @author Pawel Szalapski (pawel.szalapski@nokia.com) + */ +class DMaaPEventPublisher implements EventPublisher { + private static final int PENDING_MESSAGE_LOG_THRESHOLD = 100; + private static final Logger log = LoggerFactory.getLogger(DMaaPEventPublisher.class); + private final DMaaPPublishersCache publishersCache; + private final Logger outputLogger; + + DMaaPEventPublisher(DMaaPPublishersCache publishersCache, + Logger outputLogger) { + this.publishersCache = publishersCache; + this.outputLogger = outputLogger; + } + + @Override + public void sendEvent(JSONObject event, String domain) { + + publishersCache.getPublisher(domain) + .onEmpty(() -> + log.warn(f("Could not find event publisher for domain: '%s', dropping message: '%s'", domain, event))) + .forEach(publisher -> sendEvent(event, domain, publisher)); + } + + @Override + public void reconfigure(Map dMaaPConfig) { + log.info("reconfigure "); + publishersCache.reconfigure(dMaaPConfig); + } + + private void sendEvent(JSONObject event, String domain, CambriaBatchingPublisher publisher) { + Try.run(() -> uncheckedSendEvent(event, domain, publisher)) + .onFailure(exc -> closePublisher(event, domain, exc)); + } + + private void uncheckedSendEvent(JSONObject event, String domain, CambriaBatchingPublisher publisher) + throws IOException { + int pendingMsgs = publisher.send("MyPartitionKey", event.toString()); + if (pendingMsgs > PENDING_MESSAGE_LOG_THRESHOLD) { + log.info("Pending messages count: " + pendingMsgs); + } + String infoMsg = f("Event: '%s' scheduled to be send asynchronously on domain: '%s'", event, domain); + log.info(infoMsg); + outputLogger.info(infoMsg); + } + + private void closePublisher(JSONObject event, String domain, Throwable e) { + log.error(f("Unable to schedule event: '%s' on domain: '%s'. Closing publisher and dropping message.", + event, domain), e); + publishersCache.closePublisherFor(domain); + } +} diff --git a/src/main/java/org/onap/dcae/common/publishing/DMaaPPublishersBuilder.java b/src/main/java/org/onap/dcae/common/publishing/DMaaPPublishersBuilder.java new file mode 100644 index 0000000..8020b60 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/publishing/DMaaPPublishersBuilder.java @@ -0,0 +1,62 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common.publishing; + +import com.att.nsa.cambria.client.CambriaBatchingPublisher; +import com.att.nsa.cambria.client.CambriaClientBuilders; +import com.att.nsa.cambria.client.CambriaClientBuilders.PublisherBuilder; +import io.vavr.control.Try; + +import static io.vavr.API.Try; +import static org.onap.dcae.common.publishing.VavrUtils.enhanceError; +import static org.onap.dcae.common.publishing.VavrUtils.f; + +/** + * @author Pawel Szalapski (pawel.szalapski@nokia.com) + */ +final class DMaaPPublishersBuilder { + + static Try buildPublisher(PublisherConfig config) { + return Try(() -> builder(config).build()) + .mapFailure(enhanceError(f("DMaaP client builder throws exception for this configuration: '%s'", config))); + } + + private static PublisherBuilder builder(PublisherConfig config) { + if (config.isSecured()) { + return authenticatedBuilder(config); + } else { + return unAuthenticatedBuilder(config); + } + } + + private static PublisherBuilder authenticatedBuilder(PublisherConfig config) { + return unAuthenticatedBuilder(config) + .usingHttps() + .authenticatedByHttp(config.userName().get(), config.password().get()); + } + + private static PublisherBuilder unAuthenticatedBuilder(PublisherConfig config) { + return new CambriaClientBuilders.PublisherBuilder() + .usingHosts(config.destinations().mkString(",")) + .onTopic(config.topic()) + .logSendFailuresAfter(5); + } +} diff --git a/src/main/java/org/onap/dcae/common/publishing/DMaaPPublishersCache.java b/src/main/java/org/onap/dcae/common/publishing/DMaaPPublishersCache.java new file mode 100644 index 0000000..8f4c761 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/publishing/DMaaPPublishersCache.java @@ -0,0 +1,123 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common.publishing; + +import com.att.nsa.cambria.client.CambriaBatchingPublisher; +import com.google.common.cache.*; +import io.vavr.collection.Map; +import io.vavr.control.Option; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import static io.vavr.API.Option; +import static org.onap.dcae.common.publishing.VavrUtils.f; + +/** + * @author Pawel Szalapski (pawel.szalapski@nokia.com) + */ +class DMaaPPublishersCache { + + private static final Logger log = LoggerFactory.getLogger(DMaaPPublishersCache.class); + private final LoadingCache publishersCache; + private AtomicReference> dMaaPConfiguration; + + DMaaPPublishersCache(Map dMaaPConfiguration) { + this.dMaaPConfiguration = new AtomicReference<>(dMaaPConfiguration); + this.publishersCache = CacheBuilder.newBuilder() + .removalListener(new OnPublisherRemovalListener()) + .build(new CambriaPublishersCacheLoader()); + } + + DMaaPPublishersCache(CambriaPublishersCacheLoader dMaaPPublishersCacheLoader, + OnPublisherRemovalListener onPublisherRemovalListener, + Map dMaaPConfiguration) { + this.dMaaPConfiguration = new AtomicReference<>(dMaaPConfiguration); + this.publishersCache = CacheBuilder.newBuilder() + .removalListener(onPublisherRemovalListener) + .build(dMaaPPublishersCacheLoader); + } + + Option getPublisher(String streamID) { + try { + return Option(publishersCache.getUnchecked(streamID)); + } catch (Exception e) { + log.warn("Could not create / load Cambria Publisher for streamID", e); + return Option.none(); + } + } + + void closePublisherFor(String streamId) { + publishersCache.invalidate(streamId); + } + + synchronized void reconfigure(Map newConfig) { + log.info("reconfigure in DMaaPPublishersCache"); + Map currentConfig = dMaaPConfiguration.get(); + Map removedConfigurations = currentConfig + .filterKeys(domain -> !newConfig.containsKey(domain)); + Map changedConfigurations = newConfig + .filterKeys(e -> currentConfig.containsKey(e) && !currentConfig.get(e).equals(newConfig.get(e))); + dMaaPConfiguration.set(newConfig); + removedConfigurations.merge(changedConfigurations).forEach(e -> publishersCache.invalidate(e._1)); + } + + static class OnPublisherRemovalListener implements RemovalListener { + + @Override + public void onRemoval(@Nonnull RemovalNotification notification) { + CambriaBatchingPublisher publisher = notification.getValue(); + if (publisher != null) { // The value might get Garbage Collected at this moment, regardless of @Nonnull + try { + int timeout = 20; + TimeUnit unit = TimeUnit.SECONDS; + java.util.List stuck = publisher.close(timeout, unit); + if (!stuck.isEmpty()) { + log.error(f("Publisher got stuck and did not manage to close in '%s' '%s', " + + "%s messages were dropped", stuck.size(), timeout, unit)); + } + } catch (InterruptedException | IOException e) { + log.error("Could not close Cambria publisher, some messages might have been dropped", e); + Thread.currentThread().interrupt(); + } + } + } + } + + class CambriaPublishersCacheLoader extends CacheLoader { + + @Override + public CambriaBatchingPublisher load(@Nonnull String domain) { + return dMaaPConfiguration.get() + .get(domain) + .toTry(() -> new RuntimeException( + f("DMaaP configuration contains no configuration for domain: '%s'", domain))) + .flatMap(DMaaPPublishersBuilder::buildPublisher) + .get(); + } + } + +} diff --git a/src/main/java/org/onap/dcae/common/publishing/EventPublisher.java b/src/main/java/org/onap/dcae/common/publishing/EventPublisher.java new file mode 100644 index 0000000..91736ec --- /dev/null +++ b/src/main/java/org/onap/dcae/common/publishing/EventPublisher.java @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common.publishing; + +import io.vavr.collection.Map; +import org.json.JSONObject; +import org.slf4j.Logger; + +/** + * @author Pawel Szalapski (pawel.szalapski@nokia.com) + */ +public interface EventPublisher { + + static EventPublisher createPublisher(Logger outputLogger, Map dMaaPConfig) { + return new DMaaPEventPublisher(new DMaaPPublishersCache(dMaaPConfig), outputLogger); + } + + void sendEvent(JSONObject event, String domain); + + void reconfigure(Map dMaaPConfig); +} diff --git a/src/main/java/org/onap/dcae/common/publishing/PublisherConfig.java b/src/main/java/org/onap/dcae/common/publishing/PublisherConfig.java new file mode 100644 index 0000000..67aca1d --- /dev/null +++ b/src/main/java/org/onap/dcae/common/publishing/PublisherConfig.java @@ -0,0 +1,100 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common.publishing; + +import io.vavr.collection.List; +import io.vavr.control.Option; + +import java.util.Objects; + +/** + * @author Pawel Szalapski (pawel.szalapski@nokia.com) + */ +public final class PublisherConfig { + + private final List destinations; + private final String topic; + private String userName; + private String password; + + PublisherConfig(List destinations, String topic) { + this.destinations = destinations; + this.topic = topic; + } + + PublisherConfig(List destinations, String topic, String userName, String password) { + this.destinations = destinations; + this.topic = topic; + this.userName = userName; + this.password = password; + } + + List destinations() { + return destinations; + } + + String topic() { + return topic; + } + + Option userName() { + return Option.of(userName); + } + + Option password() { + return Option.of(password); + } + + boolean isSecured() { + return userName().isDefined() && password().isDefined(); + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PublisherConfig that = (PublisherConfig) o; + return Objects.equals(destinations, that.destinations) && + Objects.equals(topic, that.topic) && + Objects.equals(userName, that.userName) && + Objects.equals(password, that.password); + } + + @Override + public int hashCode() { + return Objects.hash(destinations, topic, userName, password); + } + + @Override + public String toString() { + return "PublisherConfig{" + + "destinations=" + destinations + + ", topic='" + topic + '\'' + + ", userName='" + userName + '\'' + + ", password='" + password + '\'' + + '}'; + } +} diff --git a/src/main/java/org/onap/dcae/common/publishing/VavrUtils.java b/src/main/java/org/onap/dcae/common/publishing/VavrUtils.java new file mode 100644 index 0000000..1db4e18 --- /dev/null +++ b/src/main/java/org/onap/dcae/common/publishing/VavrUtils.java @@ -0,0 +1,62 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common.publishing; + +import io.vavr.API; +import io.vavr.API.Match.Case; +import java.util.function.Consumer; +import org.slf4j.Logger; + +import static io.vavr.API.$; + +/** + * @author Pawel Szalapski (pawel.szalapski@nokia.com) + */ +public final class VavrUtils { + + private VavrUtils() { + // utils aggregator + } + + /** + * Shortcut for 'string interpolation' + */ + public static String f(String msg, Object... args) { + return String.format(msg, args); + } + + /** + * Wrap failure with a more descriptive message of what has failed and chain original cause. Used to provide a + * context for errors instead of raw exception. + */ + public static Case enhanceError(String msg) { + return API.Case($(), e -> new RuntimeException(msg, e)); + } + + public static Case enhanceError(String pattern, Object... arguments) { + return API.Case($(), e -> new RuntimeException(f(pattern, arguments), e)); + } + + public static Consumer logError(Logger withLogger) { + return e -> withLogger.error(e.getMessage(), e); + } + + +} diff --git a/src/main/java/org/onap/dcae/controller/AccessController.java b/src/main/java/org/onap/dcae/controller/AccessController.java new file mode 100644 index 0000000..83673b8 --- /dev/null +++ b/src/main/java/org/onap/dcae/controller/AccessController.java @@ -0,0 +1,243 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.controller; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.onap.dcae.ApplicationException; +import org.onap.dcae.ApplicationSettings; +import org.onap.dcae.common.Constants; +import org.onap.dcae.common.RestConfContext; +import org.onap.dcae.common.RestapiCallNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static java.nio.file.Files.readAllBytes; +import static org.onap.dcae.common.RestapiCallNodeUtil.getUriMethod; + +public class AccessController { + private static final Logger log = LoggerFactory.getLogger(AccessController.class); + /* Collector properties */ + private ApplicationSettings properties; + + /* Controller specific information */ + private ControllerConfigInfo cfgInfo; + private RestConfContext ctx; + RestapiCallNode restApiCallNode; + + /* Maps of Events */ + private Map eventList = new ConcurrentHashMap<>(); + private ExecutorService executor = Executors.newCachedThreadPool(); + private Map paraMap; + + public AccessController(JSONObject controller, + ApplicationSettings properties) { + this.cfgInfo = new ControllerConfigInfo(controller.get("controller_name").toString(), + controller.get("controller_restapiUrl").toString(), + controller.get("controller_restapiUser").toString(), + controller.get("controller_restapiPassword").toString(), + controller.get("controller_accessTokenUrl").toString(), + controller.get("controller_accessTokenFile").toString(), + controller.get("controller_subscriptionUrl").toString(), + controller.get("controller_accessTokenMethod").toString(), + controller.get("controller_subsMethod").toString()); + this.properties = properties; + this.ctx = new RestConfContext(); + this.restApiCallNode = new RestapiCallNode(); + this.paraMap = new HashMap<>(); + + prepareControllerParamMap(); + + log.info("AccesController Created {} {} {} {} {} {}", + this.cfgInfo.getController_name(), + this.cfgInfo.getController_restapiUrl(), + this.cfgInfo.getController_restapiPassword(), + this.cfgInfo.getController_restapiUser(), + this.cfgInfo.getController_accessTokenUrl(), + this.cfgInfo.getController_accessTokenFile()); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AccessController)) return false; + AccessController that = (AccessController) o; + return that.cfgInfo.getController_name().equals(that.cfgInfo.getController_name()); + } + + @Override + public int hashCode() { + return Objects.hash(this.cfgInfo.getController_name()); + } + + public RestapiCallNode getRestApiCallNode() { + return restApiCallNode; + } + + private void fetch_TokenId() { + + + modifyControllerParamMap(Constants.KSETTING_REST_API_URL, getUriMethod(this.properties.authorizationEnabled()) + cfgInfo.getController_restapiUrl() + cfgInfo.getController_accessTokenUrl()); + modifyControllerParamMap(Constants.KDEFAULT_TEMP_FILENAME, cfgInfo.getController_accessTokenFile()); + modifyControllerParamMap(Constants.KSETTING_REST_UNAME, cfgInfo.getController_restapiUser()); + modifyControllerParamMap(Constants.KSETTING_REST_PASSWORD, cfgInfo.getController_restapiPassword()); + modifyControllerParamMap(Constants.KSETTING_HTTP_METHOD, cfgInfo.getController_accessTokenMethod()); + + String httpResponse = null; + try { + + restApiCallNode.sendRequest(this.paraMap, ctx, null); + String key = getControllerParamMapValue(Constants.KSETTING_RESP_PREFIX).concat(".").concat("httpResponse"); + httpResponse = ctx.getAttribute(key); + log.info("httpResponse ", httpResponse + " key " + key); + JSONObject jsonObj = new JSONObject(httpResponse); + log.info("jsonObj ", jsonObj.toString()); + //JSONObject data = jsonObj.getJSONObject("data"); + //String tokenId = data.get("accessSession").toString(); + //@TODO: Make return field dynamic + String tokenId = jsonObj.get("accessSession").toString(); + log.info("token 1" + tokenId); + modifyControllerParamMap(Constants.KSETTING_TOKENID, tokenId); + modifyControllerParamMap(Constants.KSETTING_CUSTOMHTTP_HEADER, "X-ACCESS-TOKEN=" + tokenId); + } catch (Exception e) { + log.info("Access token is not supported" + e.getMessage()); + log.info("http response " + httpResponse); + } + } + + public void activate() { + fetch_TokenId(); + printControllerParamMap(); + /* Create eventlist from properties */ + JSONArray contollers = new JSONArray(properties.rcc_policy()); + for (int i = 0; i < contollers.length(); i++) { + JSONObject controller = contollers.getJSONObject(i); + if (controller.get("controller_name").equals(this.getCfgInfo().getController_name())) { + JSONArray eventlists = controller.getJSONArray("event_details"); + for (int j = 0; j < eventlists.length(); j++) { + JSONObject event = eventlists.getJSONObject(j); + String name = event.get("event_name").toString(); + PersistentEventConnection conn = new PersistentEventConnection(name, + event.get("event_description").toString(), + Boolean.parseBoolean(event.get("event_sseventUrlEmbed").toString()), + event.get("event_sseventsField").toString(), + event.get("event_sseventsUrl").toString(), + event.get("event_subscriptionTemplate").toString(), + event.get("event_unSubscriptionTemplate").toString(), + event.get("event_ruleId").toString(), + this); + + eventList.put(name, conn); + executor.execute(conn); + } + } + } + } + + public RestConfContext getCtx() { + return ctx; + } + + public ApplicationSettings getProperties() { + return properties; + } + + public ControllerConfigInfo getCfgInfo() { + return cfgInfo; + } + + public Map getParaMap() { + return this.paraMap; + } + + private void prepareControllerParamMap() { + /* Adding the fields in ParaMap */ + paraMap.put(Constants.KDEFAULT_TEMP_FILENAME, null); + paraMap.put(Constants.KSETTING_REST_API_URL, null); + paraMap.put(Constants.KSETTING_HTTP_METHOD, "post"); + paraMap.put(Constants.KSETTING_RESP_PREFIX, "responsePrefix"); + paraMap.put(Constants.KSETTING_SKIP_SENDING, "false"); + paraMap.put(Constants.KSETTING_SSE_CONNECT_URL, null); + paraMap.put(Constants.KSETTING_FORMAT, "json"); + + paraMap.put(Constants.KSETTING_REST_UNAME, null); + paraMap.put(Constants.KSETTING_REST_PASSWORD, null); + paraMap.put(Constants.KDEFAULT_REQUESTBODY, null); + + paraMap.put(Constants.KSETTING_AUTH_TYPE, "unspecified"); + paraMap.put(Constants.KSETTING_CONTENT_TYPE, "application/json"); + paraMap.put(Constants.KSETTING_OAUTH_CONSUMER_KEY, null); + paraMap.put(Constants.KSETTING_OAUTH_CONSUMER_SECRET, null); + paraMap.put(Constants.KSETTING_OAUTH_SIGNATURE_METHOD, null); + paraMap.put(Constants.KSETTING_OAUTH_VERSION, null); + + paraMap.put(Constants.KSETTING_CUSTOMHTTP_HEADER, null); + paraMap.put(Constants.KSETTING_TOKENID, null); + paraMap.put(Constants.KSETTING_DUMP_HEADER, "false"); + paraMap.put(Constants.KSETTING_RETURN_REQUEST_PAYLOAD, "false"); + + paraMap.put(Constants.KSETTING_TRUST_STORE_FILENAME, this.getProperties().truststoreFileLocation()); + String trustPassword = getKeyStorePassword(toAbsolutePath(this.getProperties().truststorePasswordFileLocation())); + paraMap.put(Constants.KSETTING_TRUST_STORE_PASSWORD, trustPassword); + paraMap.put(Constants.KSETTING_KEY_STORE_FILENAME, this.getProperties().keystoreFileLocation()); + String KeyPassword = getKeyStorePassword(toAbsolutePath(this.getProperties().keystorePasswordFileLocation())); + paraMap.put(Constants.KSETTING_KEY_STORE_PASSWORD, KeyPassword); + + } + + private Path toAbsolutePath(final String path) { + return Paths.get(path).toAbsolutePath(); + } + + private String getKeyStorePassword(final Path location) { + try { + return new String(readAllBytes(location)); + } catch (Exception e) { + log.error("Could not read password from: '" + location + "'.", e); + throw new ApplicationException(e); + } + } + + public void modifyControllerParamMap(String fieldName, String value) { + paraMap.put(fieldName, value); + } + + public String getControllerParamMapValue(String fieldName) { + return paraMap.get(fieldName); + } + + public void printControllerParamMap() { + log.info("----------------Controller Param Map-------------------"); + for (String name : paraMap.keySet()) { + String value = paraMap.get(name); + log.info(name + " : " + value); + } + } +} diff --git a/src/main/java/org/onap/dcae/controller/ConfigFilesFacade.java b/src/main/java/org/onap/dcae/controller/ConfigFilesFacade.java new file mode 100644 index 0000000..4542fb5 --- /dev/null +++ b/src/main/java/org/onap/dcae/controller/ConfigFilesFacade.java @@ -0,0 +1,131 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.controller; + +import io.vavr.CheckedRunnable; +import io.vavr.Tuple2; +import io.vavr.collection.Map; +import io.vavr.control.Try; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.FileNotFoundException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; + +import static io.vavr.API.Try; +import static org.onap.dcae.common.publishing.VavrUtils.*; +import static org.onap.dcae.controller.Conversions.toList; + +class ConfigFilesFacade { + + private static Logger log = LoggerFactory.getLogger(ConfigFilesFacade.class); + + private final Path dMaaPConfigPath; + private final Path propertiesPath; + + public ConfigFilesFacade(Path dMaaPConfigPath, Path propertiesPath) { + this.dMaaPConfigPath = dMaaPConfigPath; + this.propertiesPath = propertiesPath; + } + + Try> readCollectorProperties() { + log.info(f("Reading collector properties from path: '%s'", propertiesPath)); + return Try(this::readProperties) + .map(prop -> toList(prop.getKeys()).toMap(k -> k, k -> (String) prop.getProperty(k))) + .mapFailure(enhanceError("Unable to read properties configuration from path '%s'", propertiesPath)) + .onFailure(logError(log)) + .peek(props -> log.info(f("Read following collector properties: '%s'", props))); + } + + Try readDMaaPConfiguration() { + log.info(f("Reading DMaaP configuration from file: '%s'", dMaaPConfigPath)); + return readFile(dMaaPConfigPath) + .recover(FileNotFoundException.class, __ -> "{}") + .mapFailure(enhanceError("Unable to read DMaaP configuration from file '%s'", dMaaPConfigPath)) + .flatMap(Conversions::toJson) + .onFailure(logError(log)) + .peek(props -> log.info(f("Read following DMaaP properties: '%s'", props))); + } + + Try writeDMaaPConfiguration(JSONObject dMaaPConfiguration) { + log.info(f("Writing DMaaP configuration '%s' into file '%s'", dMaaPConfiguration, dMaaPConfigPath)); + return writeFile(dMaaPConfigPath, indentConfiguration(dMaaPConfiguration.toString())) + .mapFailure(enhanceError("Could not save new DMaaP configuration to path '%s'", dMaaPConfigPath)) + .onFailure(logError(log)) + .peek(__ -> log.info("Written successfully")); + } + + + Try writeProperties(Map properties) { + log.info(f("Writing properties configuration '%s' into file '%s'", properties, propertiesPath)); + return Try.run(saveProperties(properties)) + .mapFailure(enhanceError("Could not save properties to path '%s'", properties)) + .onFailure(logError(log)) + .peek(__ -> log.info("Written successfully")); + } + + private Try readFile(Path path) { + return Try(() -> new String(Files.readAllBytes(path), StandardCharsets.UTF_8)) + .mapFailure(enhanceError("Could not read content from path: '%s'", path)); + } + + private Try writeFile(Path path, String content) { + return Try.run(() -> Files.write(path, content.getBytes())) + .mapFailure(enhanceError("Could not write content to path: '%s'", path)); + } + + private PropertiesConfiguration readProperties() throws ConfigurationException { + PropertiesConfiguration propertiesConfiguration = new PropertiesConfiguration(); + propertiesConfiguration.setDelimiterParsingDisabled(true); + propertiesConfiguration.load(propertiesPath.toFile()); + return propertiesConfiguration; + } + + private CheckedRunnable saveProperties(Map properties) { + return () -> { + PropertiesConfiguration propertiesConfiguration = new PropertiesConfiguration(propertiesPath.toFile()); + propertiesConfiguration.setEncoding(null); + for (Tuple2 property : properties) { + updateProperty(propertiesConfiguration, property); + } + propertiesConfiguration.save(); + }; + } + + private void updateProperty(PropertiesConfiguration propertiesConfiguration, Tuple2 property) { + if (propertiesConfiguration.containsKey(property._1)) { + propertiesConfiguration.setProperty(property._1, property._2); + } else { + propertiesConfiguration.addProperty(property._1, property._2); + } + } + + private String indentConfiguration(String configuration) { + return new JSONObject(configuration).toString(4); + } + +} diff --git a/src/main/java/org/onap/dcae/controller/ConfigLoader.java b/src/main/java/org/onap/dcae/controller/ConfigLoader.java new file mode 100644 index 0000000..1b7e60b --- /dev/null +++ b/src/main/java/org/onap/dcae/controller/ConfigLoader.java @@ -0,0 +1,147 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.controller; + +import io.vavr.Function0; +import io.vavr.Function1; +import io.vavr.collection.HashMap; +import io.vavr.collection.Map; +import io.vavr.control.Try; +import org.json.JSONObject; +import org.onap.dcae.RestConfCollector; +import org.onap.dcae.common.publishing.PublisherConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.file.Path; +import java.util.function.Consumer; + +import static org.onap.dcae.common.publishing.DMaaPConfigurationParser.parseToDomainMapping; +import static org.onap.dcae.controller.ConfigParsing.getDMaaPConfig; +import static org.onap.dcae.controller.ConfigParsing.getProperties; +import static org.onap.dcae.controller.EnvPropertiesReader.readEnvProps; + +public class ConfigLoader { + + private static final String SKIP_MSG = "Skipping dynamic configuration update"; + private static Logger log = LoggerFactory.getLogger(ConfigLoader.class); + private final Consumer> eventPublisherReconfigurer; + private final ConfigFilesFacade configFilesFacade; + private final Function1> configurationSource; + private final Function0> envVariablesSupplier; + private boolean toRestart = false; + + ConfigLoader(Consumer> eventPublisherReconfigurer, + ConfigFilesFacade configFilesFacade, + Function1> configurationSource, + Function0> envVariablesSupplier) { + this.eventPublisherReconfigurer = eventPublisherReconfigurer; + this.configFilesFacade = configFilesFacade; + this.configurationSource = configurationSource; + this.envVariablesSupplier = envVariablesSupplier; + } + + public static ConfigLoader create(Consumer> eventPublisherReconfigurer, + Path dMaaPConfigFile, Path propertiesConfigFile) { + log.info("ConfigLoader create ...."); + return new ConfigLoader(eventPublisherReconfigurer, + new ConfigFilesFacade(dMaaPConfigFile, propertiesConfigFile), + ConfigSource::getAppConfig, + () -> HashMap.ofAll(System.getenv())); + } + + public void updateConfig() { + log.info("Trying to dynamically update config from Config Binding Service"); + readEnvProps(envVariablesSupplier.get()) + .onEmpty(() -> log.warn(SKIP_MSG)) + .forEach(this::updateConfig); + } + + private void updateConfig(EnvProps props) { + configurationSource.apply(props) + .onFailure(logSkip()) + .onSuccess(newConf -> { + updateConfigurationProperties(newConf); + updateDMaaPProperties(newConf); + reloadApplication(); + } + ); + } + + private void reloadApplication() { + if (toRestart) { + log.info("New app config - Application will be restarted"); + RestConfCollector.restartApplication(); + } + } + + private void updateDMaaPProperties(JSONObject newConf) { + configFilesFacade.readDMaaPConfiguration() + .onFailure(logSkip()) + .onSuccess(oldDMaaPConf -> getDMaaPConfig(newConf) + .onEmpty(() -> log.warn(SKIP_MSG)) + .forEach(newDMaaPConf -> compareAndOverwriteDMaaPConfig(oldDMaaPConf, newDMaaPConf))); + } + + + private void updateConfigurationProperties(JSONObject newConf) { + configFilesFacade.readCollectorProperties() + .onFailure(logSkip()) + .onSuccess(oldProps -> compareAndOverwritePropertiesConfig(newConf, oldProps)); + } + + private void compareAndOverwritePropertiesConfig(JSONObject newConf, Map oldProps) { + Map newProperties = getProperties(newConf); + Map result = oldProps.filterKeys((s) -> newProperties.keySet().contains(s)); + if (!result.equals(newProperties)) { + configFilesFacade.writeProperties(newProperties) + .onSuccess(__ -> { + toRestart = true; + log.info("New properties configuration written to file"); + }) + .onFailure(logSkip()); + } else { + log.info("Collector properties from CBS are the same as currently used ones. " + SKIP_MSG); + } + } + + private void compareAndOverwriteDMaaPConfig(JSONObject oldDMaaPConf, JSONObject newDMaaPConf) { + if (!oldDMaaPConf.toString().equals(newDMaaPConf.toString())) { + parseToDomainMapping(newDMaaPConf) + .onFailure(exc -> log.error(SKIP_MSG, exc)) + .onSuccess(eventPublisherReconfigurer) + .onSuccess(parsedConfig -> + configFilesFacade.writeDMaaPConfiguration(newDMaaPConf) + .onFailure(logSkip()) + .onSuccess(__ -> { + toRestart = true; + log.info("New dMaaP configuration written to file"); + })); + } else { + log.info("DMaaP config from CBS is the same as currently used one. " + SKIP_MSG); + } + } + + private Consumer logSkip() { + return __ -> log.error(SKIP_MSG); + } +} diff --git a/src/main/java/org/onap/dcae/controller/ConfigParsing.java b/src/main/java/org/onap/dcae/controller/ConfigParsing.java new file mode 100644 index 0000000..fea3451 --- /dev/null +++ b/src/main/java/org/onap/dcae/controller/ConfigParsing.java @@ -0,0 +1,59 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.controller; + +import io.vavr.collection.Map; +import io.vavr.control.Option; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static io.vavr.API.Try; +import static io.vavr.API.Tuple; +import static org.onap.dcae.common.publishing.VavrUtils.f; +import static org.onap.dcae.controller.Conversions.toList; + +interface ConfigParsing { + + Logger log = LoggerFactory.getLogger(ConfigParsing.class); + + static Option getDMaaPConfig(JSONObject configuration) { + log.info(f("Getting DMaaP configuration from app configuration: '%s'", configuration)); + return toList(configuration.toMap().entrySet().iterator()) + .filter(t -> t.getKey().startsWith("streams_publishes")) + .headOption() + .flatMap(e -> Try(() -> configuration.getJSONObject(e.getKey())).toOption()) + .onEmpty(() -> log.warn(f("App configuration '%s' is missing DMaaP configuration ('streams_publishes' key) " + + "or DMaaP configuration is not a valid json document", configuration))) + .peek(dMaaPConf -> log.info(f("Found following DMaaP configuration: '%s'", dMaaPConf))); + } + + static Map getProperties(JSONObject configuration) { + log.info(f("Getting properties configuration from app configuration: '%s'", configuration)); + Map confEntries = toList(configuration.toMap().entrySet().iterator()) + .toMap(e -> Tuple(e.getKey(), String.valueOf(e.getValue()))) + .filterKeys(e -> !e.startsWith("streams_publishes")); + log.info(f("Found following app properties: '%s'", confEntries)); + return confEntries; + } + +} diff --git a/src/main/java/org/onap/dcae/controller/ConfigSource.java b/src/main/java/org/onap/dcae/controller/ConfigSource.java new file mode 100644 index 0000000..78cb147 --- /dev/null +++ b/src/main/java/org/onap/dcae/controller/ConfigSource.java @@ -0,0 +1,90 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.controller; + +import com.mashape.unirest.http.HttpResponse; +import com.mashape.unirest.http.Unirest; +import io.vavr.control.Try; +import org.json.JSONArray; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static io.vavr.API.Try; +import static org.onap.dcae.common.publishing.VavrUtils.enhanceError; +import static org.onap.dcae.common.publishing.VavrUtils.f; + +final class ConfigSource { + + private static final Logger log = LoggerFactory.getLogger(ConfigSource.class); + + static Try getAppConfig(EnvProps envProps) { + log.info("Fetching app configuration from CBS"); + return callConsulForCBSConfiguration(envProps) + .peek(strBody -> log.info(f("Received following CBS configuration from Consul '%s'", strBody))) + .flatMap(Conversions::toJsonArray) + .flatMap(ConfigSource::withdrawCatalog) + .flatMap(json -> constructFullCBSUrl(envProps, json)) + .flatMap(cbsUrl -> callCBSForAppConfig(envProps, cbsUrl)) + .flatMap(Conversions::toJson) + .peek(jsonNode -> log.info(f("Received app configuration: '%s'", jsonNode))) + .onFailure(exc -> log.error("Could not fetch application config", exc)); + } + + private static Try callConsulForCBSConfiguration(EnvProps envProps) { + return executeGet(envProps.consulProtocol + "://" + envProps.consulHost + ":" + + envProps.consulPort + "/v1/catalog/service/" + envProps.cbsName) + .mapFailure(enhanceError("Unable to retrieve CBS configuration from Consul")); + } + + private static Try constructFullCBSUrl(EnvProps envProps, JSONObject json) { + return Try(() -> envProps.cbsProtocol + "://" + json.get("ServiceAddress").toString() + ":" + + json.get("ServicePort").toString()) + .mapFailure(enhanceError("ServiceAddress / ServicePort missing from CBS conf: '%s'", json)); + } + + private static Try withdrawCatalog(JSONArray json) { + return Try(() -> new JSONObject(json.get(0).toString())) + .mapFailure(enhanceError("CBS response '%s' is in invalid format," + + " most probably is it not a list of configuration objects", json)); + } + + private static Try callCBSForAppConfig(EnvProps envProps, String cbsUrl) { + log.info("Calling CBS for application config"); + return executeGet(cbsUrl + "/service_component/" + envProps.appName) + .mapFailure(enhanceError("Unable to fetch configuration from CBS")); + } + + + private static Try executeGet(String url) { + log.info(f("Calling HTTP GET on url: '%s'", url)); + return Try(() -> Unirest.get(url).asString()) + .mapFailure(enhanceError("Http call (GET '%s') failed.", url)) + .filter( + res -> res.getStatus() == 200, + res -> new RuntimeException(f("HTTP call (GET '%s') failed with status %s and body '%s'", + url, res.getStatus(), res.getBody()))) + .map(HttpResponse::getBody) + .peek(body -> log.info(f("HTTP GET on '%s' returned body '%s'", url, body))); + } + +} diff --git a/src/main/java/org/onap/dcae/controller/ControllerConfigInfo.java b/src/main/java/org/onap/dcae/controller/ControllerConfigInfo.java new file mode 100644 index 0000000..2941b9b --- /dev/null +++ b/src/main/java/org/onap/dcae/controller/ControllerConfigInfo.java @@ -0,0 +1,88 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.controller; + +public class ControllerConfigInfo { + private String controller_name; + private String controller_restapiUrl; + private String controller_restapiUser; + private String controller_restapiPassword; + private String controller_accessTokenUrl; + private String controller_accessTokenFile; + private String controller_subscriptionUrl; + private String controller_accessTokenMethod; + private String controller_subsMethod; + + public ControllerConfigInfo(String controller_name, + String controller_restapiUrl, + String controller_restapiUser, + String controller_restapiPassword, + String controller_accessTokenUrl, + String controller_accessTokenFile, + String controller_subscriptionUrl, + String controller_accessTokenMethod, + String controller_subsMethod) { + this.controller_name = controller_name; + this.controller_restapiUrl = controller_restapiUrl; + this.controller_restapiUser = controller_restapiUser; + this.controller_restapiPassword = controller_restapiPassword; + this.controller_accessTokenUrl = controller_accessTokenUrl; + this.controller_accessTokenFile = controller_accessTokenFile; + this.controller_subscriptionUrl = controller_subscriptionUrl; + this.controller_accessTokenMethod = controller_accessTokenMethod; + this.controller_subsMethod = controller_subsMethod; + } + + public String getController_name() { + return controller_name; + } + + public String getController_restapiUrl() { + return controller_restapiUrl; + } + + public String getController_restapiUser() { + return controller_restapiUser; + } + + public String getController_restapiPassword() { + return controller_restapiPassword; + } + + public String getController_accessTokenUrl() { + return controller_accessTokenUrl; + } + + public String getController_accessTokenFile() { + return controller_accessTokenFile; + } + + public String getController_accessTokenMethod() { + return controller_accessTokenMethod; + } + + public String getController_subsMethod() { + return controller_subsMethod; + } + + public String getController_subscriptionUrl() { + return controller_subscriptionUrl; + } +} \ No newline at end of file diff --git a/src/main/java/org/onap/dcae/controller/Conversions.java b/src/main/java/org/onap/dcae/controller/Conversions.java new file mode 100644 index 0000000..0a3e7c7 --- /dev/null +++ b/src/main/java/org/onap/dcae/controller/Conversions.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.controller; + +import static org.onap.dcae.common.publishing.VavrUtils.enhanceError; + +import io.vavr.API; +import io.vavr.collection.List; +import io.vavr.control.Try; +import java.util.Iterator; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.StreamSupport; +import org.json.JSONArray; +import org.json.JSONObject; + +/** + * @author Pawel Szalapski (pawel.szalapski@nokia.com) + */ +interface Conversions { + + static Try toJson(String strBody) { + return API.Try(() -> new JSONObject(strBody)) + .mapFailure(enhanceError("Value '%s' is not a valid JSON document", strBody)); + } + + static Try toJsonArray(String strBody) { + return API.Try(() -> new JSONArray(strBody)) + .mapFailure(enhanceError("Value '%s' is not a valid JSON array", strBody)); + } + + static List toList(Iterator iterator) { + return List.ofAll(StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false)); + } + +} diff --git a/src/main/java/org/onap/dcae/controller/EnvPropertiesReader.java b/src/main/java/org/onap/dcae/controller/EnvPropertiesReader.java new file mode 100644 index 0000000..3feeacc --- /dev/null +++ b/src/main/java/org/onap/dcae/controller/EnvPropertiesReader.java @@ -0,0 +1,95 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.controller; + +import io.vavr.collection.Map; +import io.vavr.control.Option; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static io.vavr.API.List; +import static io.vavr.API.Try; +import static org.onap.dcae.common.publishing.VavrUtils.f; + +final class EnvPropertiesReader { + + private final static Logger log = LoggerFactory.getLogger(EnvPropertiesReader.class); + + static Option readEnvProps(Map environmentVariables) { + log.info("Loading necessary environment variables for dynamic configuration update"); + int consulPort = getConsulPort(environmentVariables); + String consulProtocol = getConsulProtocol(environmentVariables); + String cbsProtocol = getCbsProtocol(environmentVariables); + Option consulHost = getConsulHost(environmentVariables); + Option cbsServiceName = getCBSName(environmentVariables); + Option collectorAppName = getAppName(environmentVariables); + return Option.sequence(List(consulHost, cbsServiceName, collectorAppName)) + .map(e -> new EnvProps(consulProtocol, e.get(0), consulPort, cbsProtocol, e.get(1), e.get(2))) + .onEmpty(() -> log.warn("Some required environment variables are missing")) + .peek(props -> log.info(f("Discovered following environment variables: '%s'", props))); + } + + private static Option getAppName(Map environmentVariables) { + return environmentVariables.get("HOSTNAME") + .orElse(environmentVariables.get("SERVICE_NAME")) + .onEmpty(() -> log.warn("App service name (as registered in CBS) (env var: 'HOSTNAME' / 'SERVICE_NAME') " + + "is missing error environment variables.")); + } + + private static Option getCBSName(Map environmentVariables) { + return environmentVariables.get("CONFIG_BINDING_SERVICE") + .onEmpty(() -> log.warn("Name of CBS Service (as registered in Consul) (env var: 'CONFIG_BINDING_SERVICE') " + + "is missing from environment variables.")); + } + + private static Integer getConsulPort(Map environmentVariables) { + return environmentVariables.get("CONSUL_PORT") + .flatMap(str -> Try(() -> Integer.valueOf(str)) + .onFailure(exc -> log.warn("Consul port is not an integer value", exc)) + .toOption()) + .onEmpty(() -> log.warn("Consul port (env var: 'CONSUL_PORT') is missing from environment variables. " + + "Using default value of 8500")) + .getOrElse(8500); + } + + private static Option getConsulHost(Map environmentVariables) { + return environmentVariables.get("CONSUL_HOST") + .onEmpty(() -> log.warn("Consul host (env var: 'CONSUL_HOST') (without port) " + + "is missing from environment variables.")); + } + + private static String getConsulProtocol(Map environmentVariables) { + return getProtocolFrom("CONSUL_PROTOCOL", environmentVariables); + } + + private static String getCbsProtocol(Map environmentVariables) { + return getProtocolFrom("CBS_PROTOCOL", environmentVariables); + } + + private static String getProtocolFrom(String variableName, Map environmentVariables) { + return environmentVariables.get(variableName) + .onEmpty(() -> log.warn("Consul protocol (env var: '" + variableName + "') is missing " + + "from environment variables.")) + .getOrElse("http"); + } + +} diff --git a/src/main/java/org/onap/dcae/controller/EnvProps.java b/src/main/java/org/onap/dcae/controller/EnvProps.java new file mode 100644 index 0000000..a2d381d --- /dev/null +++ b/src/main/java/org/onap/dcae/controller/EnvProps.java @@ -0,0 +1,74 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.controller; + +import java.util.Objects; + +/** + * @author Pawel Szalapski (pawel.szalapski@nokia.com) + */ +final class EnvProps { + + final String consulProtocol; + final String consulHost; + final int consulPort; + final String cbsName; + final String cbsProtocol; + final String appName; + + EnvProps(String consulProtocol, String consulHost, int consulPort, String cbsProtocol, String cbsName, String appName) { + this.consulProtocol = consulProtocol; + this.consulHost = consulHost; + this.consulPort = consulPort; + this.cbsProtocol = cbsProtocol; + this.cbsName = cbsName; + this.appName = appName; + } + + @Override + public String toString() { + return "EnvProps{" + + "consulProtocol='" + consulProtocol + '\'' + + ", consulHost='" + consulHost + '\'' + + ", consulPort=" + consulPort + + ", cbsProtocol='" + cbsProtocol + '\'' + + ", cbsName='" + cbsName + '\'' + + ", appName='" + appName + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + EnvProps envProps = (EnvProps) o; + return consulPort == envProps.consulPort && + Objects.equals(consulProtocol, envProps.consulProtocol) && + Objects.equals(consulHost, envProps.consulHost) && + Objects.equals(cbsProtocol, envProps.cbsProtocol) && + Objects.equals(cbsName, envProps.cbsName) && + Objects.equals(appName, envProps.appName); + } +} \ No newline at end of file diff --git a/src/main/java/org/onap/dcae/controller/PersistentEventConnection.java b/src/main/java/org/onap/dcae/controller/PersistentEventConnection.java new file mode 100644 index 0000000..1c0d85b --- /dev/null +++ b/src/main/java/org/onap/dcae/controller/PersistentEventConnection.java @@ -0,0 +1,207 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.restconf + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.controller; + +import org.glassfish.jersey.media.sse.EventSource; +import org.glassfish.jersey.media.sse.SseFeature; +import org.onap.dcae.common.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.HttpHeaders; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; + +import static org.onap.dcae.common.RestapiCallNodeUtil.*; + +public class PersistentEventConnection implements Runnable { + public String event_name; + private String event_description; + private boolean event_sseventUrlEmbed; + private String event_sseventsField; + private String event_sseventsUrl; + private String event_subscriptionTemplate; + private String event_unSubscriptionTemplate; + private String event_ruleId; + private EventConnectionState state; + private volatile boolean running = true; + private static final Logger log = LoggerFactory.getLogger(PersistentEventConnection.class); + + + private RestConfContext ctx; + private AccessController parentCtrllr; + private Map eventParaMap; + + public PersistentEventConnection(String event_name, + String event_description, + boolean event_sseventUrlEmbed, + String event_sseventsField, + String event_sseventsUrl, + String event_subscriptionTemplate, + String event_unSubscriptionTemplate, + String event_ruleId, + AccessController parentCtrllr) { + this.event_name = event_name; + this.event_description = event_description; + this.event_sseventUrlEmbed = event_sseventUrlEmbed; + this.event_sseventsField = event_sseventsField; + this.event_sseventsUrl = event_sseventsUrl; + this.event_subscriptionTemplate = event_subscriptionTemplate; + this.event_unSubscriptionTemplate = event_unSubscriptionTemplate; + this.event_ruleId = event_ruleId; + this.state = EventConnectionState.INIT; + + this.ctx = new RestConfContext(); + for (String s : parentCtrllr.getCtx().getAttributeKeySet()) { + this.ctx.setAttribute(s, ctx.getAttribute(s)); + } + this.parentCtrllr = parentCtrllr; + this.eventParaMap = new HashMap<>(); + this.eventParaMap.putAll(parentCtrllr.getParaMap()); + printEventParamMap(); + log.info("New persistent connection created " + event_name); + } + + @Override + public void run() { + Parameters p = null; + try { + modifyEventParamMap(Constants.KSETTING_REST_API_URL, getUriMethod(parentCtrllr.getProperties().authorizationEnabled()) + + parentCtrllr.getCfgInfo().getController_restapiUrl() + + parentCtrllr.getCfgInfo().getController_subscriptionUrl()); + modifyEventParamMap(Constants.KDEFAULT_TEMP_FILENAME, event_subscriptionTemplate); + modifyEventParamMap(Constants.KSETTING_REST_UNAME, parentCtrllr.getCfgInfo().getController_restapiUser()); + modifyEventParamMap(Constants.KSETTING_REST_PASSWORD, parentCtrllr.getCfgInfo().getController_restapiPassword()); + modifyEventParamMap(Constants.KSETTING_HTTP_METHOD, parentCtrllr.getCfgInfo().getController_subsMethod()); + + parentCtrllr.getRestApiCallNode().sendRequest(eventParaMap, ctx, null); + } catch (Exception e) { + log.error("Exception occured!", e); + Thread.currentThread().interrupt(); + } + + /* Retrieve url from result and construct SSE url */ + if (event_sseventUrlEmbed) { + String key = getEventParamMapValue(Constants.KSETTING_RESP_PREFIX).concat(".").concat(event_sseventsField); + log.info("key " + key); + this.event_sseventsUrl = ctx.getAttribute(key); + } + + log.info("SSE received url " + event_sseventsUrl); + try { + p = getParameters(eventParaMap); + } catch (Exception e) { + log.error("Exception occured!", e); + Thread.currentThread().interrupt(); + } + printEventParamMap(); + String url = getUriMethod(parentCtrllr.getProperties().authorizationEnabled()) + + parentCtrllr.getCfgInfo().getController_restapiUrl() + event_sseventsUrl; + Client client = ignoreSslClient().register(SseFeature.class); + WebTarget target = addAuthType(client, p).target(url); + String tokenId = getEventParamMapValue(Constants.KSETTING_TOKENID); + String headerName = "X-ACCESS-TOKEN"; + if (tokenId == null) { + headerName = HttpHeaders.AUTHORIZATION; + tokenId = getAuthorizationToken(parentCtrllr.getCfgInfo().getController_restapiUser(), + parentCtrllr.getCfgInfo().getController_restapiPassword()); + } + AdditionalHeaderWebTarget newTarget = new AdditionalHeaderWebTarget(target, tokenId, headerName); + EventSource eventSource = EventSource.target(newTarget).build(); + eventSource.register(new DataChangeEventListener(this)); + eventSource.open(); + log.info("Connected to SSE source"); + while (running) { + try { + log.info("SSE state " + eventSource.isOpen()); + Thread.sleep(5000); + } catch (InterruptedException ie) { + log.info("Exception: " + ie.getMessage()); + Thread.currentThread().interrupt(); + running = false; + } + } + eventSource.close(); + log.info("Closed connection to SSE source"); + } + + private String getAuthorizationToken(String userName, String password) { + return "Basic " + Base64.getEncoder().encodeToString(( + userName + ":" + password).getBytes()); + } + + private Client ignoreSslClient() { + SSLContext sslcontext = null; + + try { + sslcontext = SSLContext.getInstance("TLS"); + sslcontext.init(null, new TrustManager[]{new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + } + + @Override + public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + }}, new java.security.SecureRandom()); + } catch (NoSuchAlgorithmException | KeyManagementException e) { + throw new IllegalStateException(e); + } + + return ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier((s1, s2) -> true).build(); + } + + public String getEvent_ruleId() { + return event_ruleId; + } + + public void modifyEventParamMap(String fieldName, String value) { + eventParaMap.put(fieldName, value); + } + + public String getEventParamMapValue(String fieldName) { + return eventParaMap.get(fieldName); + } + + public void printEventParamMap() { + log.info("----------------Event Param Map-------------------"); + for (String name : eventParaMap.keySet()) { + String value = eventParaMap.get(name); + log.info(name + " : " + value); + } + } +} diff --git a/src/main/java/org/onap/dcae/restapi/ApiAuthInterceptor.java b/src/main/java/org/onap/dcae/restapi/ApiAuthInterceptor.java new file mode 100644 index 0000000..654ad20 --- /dev/null +++ b/src/main/java/org/onap/dcae/restapi/ApiAuthInterceptor.java @@ -0,0 +1,77 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.restapi; + +import io.vavr.control.Option; +import java.io.IOException; +import java.util.Base64; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.onap.dcae.ApplicationSettings; +import org.onap.dcaegen2.services.sdk.security.CryptPassword; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +final class ApiAuthInterceptor extends HandlerInterceptorAdapter { + + private static final Logger LOG = LoggerFactory.getLogger(ApiAuthInterceptor.class); + private final CryptPassword cryptPassword = new CryptPassword(); + private final ApplicationSettings applicationSettings; + + + + ApiAuthInterceptor(ApplicationSettings applicationSettings) { + this.applicationSettings = applicationSettings; + + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws IOException { + if (applicationSettings.authorizationEnabled()) { + String authorizationHeader = request.getHeader("Authorization"); + if (authorizationHeader == null || !isAuthorized(authorizationHeader)) { + response.setStatus(400); + + response.getWriter().write(ApiException.UNAUTHORIZED_USER.toJSON().toString()); + return false; + } + } + return true; + } + + private boolean isAuthorized(String authorizationHeader) { + try { + String encodedData = authorizationHeader.split(" ")[1]; + String decodedData = new String(Base64.getDecoder().decode(encodedData)); + String providedUser = decodedData.split(":")[0].trim(); + String providedPassword = decodedData.split(":")[1].trim(); + Option maybeSavedPassword = applicationSettings.validAuthorizationCredentials().get(providedUser); + boolean userRegistered = maybeSavedPassword.isDefined(); + return userRegistered && cryptPassword.matches(providedPassword,maybeSavedPassword.get()); + } catch (Exception e) { + LOG.warn(String.format("Could not check if user is authorized (header: '%s')), probably malformed header.", + authorizationHeader), e); + return false; + } + } +} \ No newline at end of file diff --git a/src/main/java/org/onap/dcae/restapi/ApiConfiguration.java b/src/main/java/org/onap/dcae/restapi/ApiConfiguration.java new file mode 100644 index 0000000..28a61bc --- /dev/null +++ b/src/main/java/org/onap/dcae/restapi/ApiConfiguration.java @@ -0,0 +1,48 @@ +/* + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.restapi; + +import org.onap.dcae.ApplicationSettings; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@EnableWebMvc +@Configuration +public class ApiConfiguration implements WebMvcConfigurer { + + private final ApplicationSettings applicationSettings; + + + @Autowired + ApiConfiguration(ApplicationSettings applicationSettings) { + this.applicationSettings = applicationSettings; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new ApiAuthInterceptor(applicationSettings)); + } +} diff --git a/src/main/java/org/onap/dcae/restapi/ApiException.java b/src/main/java/org/onap/dcae/restapi/ApiException.java new file mode 100644 index 0000000..d8c21b1 --- /dev/null +++ b/src/main/java/org/onap/dcae/restapi/ApiException.java @@ -0,0 +1,66 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.restapi; + +import com.google.common.base.CaseFormat; +import org.json.JSONObject; + +/** + * @author Pawel Szalapski (pawel.szalapski@nokia.com) + */ +public enum ApiException { + UNAUTHORIZED_USER(ExceptionType.POLICY_EXCEPTION, "POL2000", "Unauthorized user", 401); + + public final int httpStatusCode; + private final ExceptionType type; + private final String code; + private final String details; + + ApiException(ExceptionType type, String code, String details, int httpStatusCode) { + this.type = type; + this.code = code; + this.details = details; + this.httpStatusCode = httpStatusCode; + } + + public JSONObject toJSON() { + JSONObject exceptionTypeNode = new JSONObject(); + exceptionTypeNode.put("messageId", code); + exceptionTypeNode.put("text", details); + + JSONObject requestErrorNode = new JSONObject(); + requestErrorNode.put(type.toString(), exceptionTypeNode); + + JSONObject rootNode = new JSONObject(); + rootNode.put("requestError", requestErrorNode); + return rootNode; + } + + public enum ExceptionType { + POLICY_EXCEPTION; + + @Override + public String toString() { + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, this.name()); + } + } + +} diff --git a/src/main/java/org/onap/dcae/restapi/RccRestController.java b/src/main/java/org/onap/dcae/restapi/RccRestController.java new file mode 100644 index 0000000..75cfa15 --- /dev/null +++ b/src/main/java/org/onap/dcae/restapi/RccRestController.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.restapi; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class RccRestController { + private static final Logger log = LoggerFactory.getLogger(RccRestController.class); + + @GetMapping("/") + String mainPage() { + return "Welcome to RestConfCollector"; + } + + @GetMapping("/healthcheck") + public String healthy() { + return "hello"; + } +} \ No newline at end of file diff --git a/src/main/java/org/onap/dcae/restapi/ServletConfig.java b/src/main/java/org/onap/dcae/restapi/ServletConfig.java new file mode 100644 index 0000000..6a6a761 --- /dev/null +++ b/src/main/java/org/onap/dcae/restapi/ServletConfig.java @@ -0,0 +1,108 @@ +/* + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.restapi; + +import org.onap.dcae.ApplicationException; +import org.onap.dcae.ApplicationSettings; +import org.onap.dcae.common.SSLContextCreator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.server.Ssl; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static java.nio.file.Files.readAllBytes; + +@Component +public class ServletConfig implements WebServerFactoryCustomizer { + + private static final Logger log = LoggerFactory.getLogger(ServletConfig.class); + + @Autowired + private ApplicationSettings properties; + + @Override + public void customize(ConfigurableServletWebServerFactory container) { + final boolean hasClientTlsAuthentication = properties.clientTlsAuthenticationEnabled(); + log.info("WebServerFactoryCustomizer initializing........"); + if (hasClientTlsAuthentication || properties.authorizationEnabled()) { + container.setSsl(hasClientTlsAuthentication ? httpsContextWithTlsAuthentication() : simpleHttpsContext()); + container.setPort(properties.httpsPort()); + } else { + container.setPort(properties.httpPort()); + } + } + + private SSLContextCreator simpleHttpsContextBuilder() { + log.info("Enabling SSL"); + + final Path keyStore = toAbsolutePath(properties.rcc_keystoreFileLocation()); + log.info("Using keyStore path: " + keyStore); + + final Path keyStorePasswordLocation = toAbsolutePath(properties.rcc_keystorePasswordFileLocation()); + final String keyStorePassword = getKeyStorePassword(keyStorePasswordLocation); + log.info("Using keyStore password from: " + keyStorePasswordLocation); + + final String alias = properties.keystoreAlias(); + + return SSLContextCreator.create(keyStore, alias, keyStorePassword); + } + + private Ssl simpleHttpsContext() { + return simpleHttpsContextBuilder().build(); + } + + private Ssl httpsContextWithTlsAuthentication() { + final SSLContextCreator sslContextCreator = simpleHttpsContextBuilder(); + + log.info("Enabling TLS client authorization"); + + final Path trustStore = toAbsolutePath(properties.truststoreFileLocation()); + log.info("Using trustStore path: " + trustStore); + + final Path trustPasswordFileLocation = toAbsolutePath(properties.truststorePasswordFileLocation()); + final String trustStorePassword = getKeyStorePassword(trustPasswordFileLocation); + log.info("Using trustStore password from: " + trustPasswordFileLocation); + + return sslContextCreator.withTlsClientAuthentication(trustStore, trustStorePassword).build(); + } + + private Path toAbsolutePath(final String path) { + return Paths.get(path).toAbsolutePath(); + } + + private String getKeyStorePassword(final Path location) { + try { + return new String(readAllBytes(location)); + } catch (IOException e) { + log.error("Could not read keystore password from: '" + location + "'.", e); + throw new ApplicationException(e); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/onap/dcae/restapi/SwaggerConfig.java b/src/main/java/org/onap/dcae/restapi/SwaggerConfig.java new file mode 100644 index 0000000..fc47ba8 --- /dev/null +++ b/src/main/java/org/onap/dcae/restapi/SwaggerConfig.java @@ -0,0 +1,44 @@ +/* + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.restapi; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@Configuration +@EnableSwagger2 +public class SwaggerConfig { + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.any()) + .build(); + } + +} diff --git a/src/main/java/org/onap/dcae/restapi/WebMvcConfig.java b/src/main/java/org/onap/dcae/restapi/WebMvcConfig.java new file mode 100644 index 0000000..d015b45 --- /dev/null +++ b/src/main/java/org/onap/dcae/restapi/WebMvcConfig.java @@ -0,0 +1,57 @@ +/* + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.restapi; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; +import org.springframework.web.servlet.view.InternalResourceViewResolver; + +@Configuration +public class WebMvcConfig extends WebMvcConfigurationSupport { + + @Override + protected void addResourceHandlers(ResourceHandlerRegistry registry) { + registry + .addResourceHandler("swagger-ui.html") + .addResourceLocations("classpath:/META-INF/resources/"); + + registry + .addResourceHandler("/webjars/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/"); + + registry + .addResourceHandler("**") + .addResourceLocations("classpath:/templates/"); + } + + @Bean + public InternalResourceViewResolver jspViewResolver() { + InternalResourceViewResolver resolver = new InternalResourceViewResolver(); + resolver.setPrefix("/"); + resolver.setSuffix(".html"); + return resolver; + } + +} diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt new file mode 100644 index 0000000..9f2d466 --- /dev/null +++ b/src/main/resources/banner.txt @@ -0,0 +1,7 @@ + _____ _ _____ __ _____ _ _ _ +| __ \ | | / ____| / _| / ____| | || | | | +| |__) | ___ ___ | |_ | | ___ _ __ | |_ | | ___ | || | ___ ___ | |_ ___ _ __ +| _ / / _ \/ __|| __|| | / _ \ | '_ \ | _| | | / _ \ | || | / _ \ / __|| __|/ _ \ | '__| +| | \ \| __/\__ \| |_ | |____| (_) || | | || | | |____| (_) || || || __/| (__ | |_| (_) || | +|_| \_\\___||___/ \__| \_____|\___/ |_| |_||_| \_____|\___/ |_||_| \___| \___| \__|\___/ |_| + diff --git a/src/main/scripts/docker_entry.sh b/src/main/scripts/docker_entry.sh index 78b83f6..c51bc84 100755 --- a/src/main/scripts/docker_entry.sh +++ b/src/main/scripts/docker_entry.sh @@ -1,4 +1,23 @@ #!/bin/sh +### +# ============LICENSE_START======================================================= +# org.onap.dcaegen2.restconfcollector +# ================================================================================ +# Copyright (C) 2018-2019 Huawei. 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========================================================= +### echo "INFO: USING RESTCONF CONTROLLER" diff --git a/src/main/scripts/restConfCollector.sh b/src/main/scripts/restConfCollector.sh index 88893c0..9a211fd 100755 --- a/src/main/scripts/restConfCollector.sh +++ b/src/main/scripts/restConfCollector.sh @@ -1,4 +1,23 @@ #!/bin/sh +### +# ============LICENSE_START======================================================= +# org.onap.dcaegen2.restconfcollector +# ================================================================================ +# Copyright (C) 2018-2019 Huawei. 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========================================================= +### usage() { echo "restConfCollector.sh " @@ -47,7 +66,7 @@ else JAVA=$JAVA_HOME fi -MAINCLASS=org.onap.dcae.collectors.restconf.common.RestConfCollector +MAINCLASS=org.onap.dcae.RestConfCollector # determine a path separator that works for this platform PATHSEP=":" diff --git a/src/test/java/org/onap/dcae/AccessControllerTest.java b/src/test/java/org/onap/dcae/AccessControllerTest.java new file mode 100644 index 0000000..74d3da1 --- /dev/null +++ b/src/test/java/org/onap/dcae/AccessControllerTest.java @@ -0,0 +1,114 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae; + +import io.vavr.collection.Map; +import org.json.JSONArray; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.onap.dcae.common.RestConfContext; +import org.onap.dcae.common.RestapiCallNode; +import org.onap.dcae.controller.AccessController; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.json.JSONObject; + +import static java.nio.file.Files.readAllBytes; +import static java.util.Collections.singletonList; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; +import static org.onap.dcae.CLIUtils.processCmdLine; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class AccessControllerTest { + @Mock + private ApplicationSettings properties; + + @Mock + private RestConfContext ctx; + + @Mock + private RestapiCallNode restApiCallNode; + + protected static final Path RESOURCES = Paths.get("src", "test", "resources"); + protected static final Path KEYSTORE = Paths.get(RESOURCES.toString(), "keystore"); + protected static final Path KEYSTORE_PASSWORD_FILE = Paths.get(RESOURCES.toString(), "passwordfile"); + protected static final Path TRUSTSTORE = Paths.get(RESOURCES.toString(), "truststore"); + protected static final Path TRUSTSTORE_PASSWORD_FILE = Paths.get(RESOURCES.toString(), "trustpasswordfile"); + protected static final Path RCC_KEYSTORE_PASSWORD_FILE = Paths.get(RESOURCES.toString(), "rcc_passwordfile"); + protected static final Path RCC_KEYSTORE = Paths.get(RESOURCES.toString(), "sdnc.p12"); + + @Test + public void createAndGetAccessControler() { + when(properties.truststoreFileLocation()).thenReturn(TRUSTSTORE.toString()); + when(properties.truststorePasswordFileLocation()).thenReturn(TRUSTSTORE_PASSWORD_FILE.toString()); + when(properties.keystoreFileLocation()).thenReturn(KEYSTORE.toString()); + when(properties.keystorePasswordFileLocation()).thenReturn(KEYSTORE_PASSWORD_FILE.toString()); + when(properties.rcc_keystoreFileLocation()).thenReturn(RCC_KEYSTORE.toString()); + when(properties.rcc_keystorePasswordFileLocation()).thenReturn(RCC_KEYSTORE_PASSWORD_FILE.toString()); + try { + when(readAllBytes(null)).thenReturn("colletor".getBytes()); + } catch (Exception e){} + JSONObject controller = new JSONObject("{\"controller_name\":\"AccessM&C\",\"controller_restapiUrl\":\"10.118.191.43:26335\",\"controller_restapiUser\":\"access\",\"controller_restapiPassword\":\"Huawei@123\",\"controller_accessTokenUrl\":\"/rest/plat/smapp/v1/oauth/token\",\"controller_accessTokenFile\":\"./etc/access-token.json\",\"controller_accessTokenMethod\":\"put\",\"controller_subsMethod\":\"post\",\"controller_subscriptionUrl\":\"/restconf/v1/operations/huawei-nce-notification-action:establish-subscription\",\"event_details\":[{\"event_name\":\"ONT_registration\",\"event_description\":\"ONTregistartionevent\",\"event_sseventUrlEmbed\":\"true\",\"event_sseventsField\":\"output.url\",\"event_sseventsUrl\":\"null\",\"event_subscriptionTemplate\":\"./etc/ont_registartion_subscription_template.json\",\"event_unSubscriptionTemplate\":\"./etc/ont_registartion_unsubscription_template.json\",\"event_ruleId\":\"777777777\"}]}"); + try { + AccessController acClr = new AccessController(controller, + properties); + + // then + assertEquals(acClr.getCfgInfo().getController_name(), "AccessM&C"); + assertEquals(acClr.getCfgInfo().getController_accessTokenMethod(), "put"); + assertEquals(acClr.getCfgInfo().getController_subsMethod(), "post"); + assertEquals(acClr.getCfgInfo().getController_subscriptionUrl(), "/restconf/v1/operations/huawei-nce-notification-action:establish-subscription"); + } catch (Exception e){} + } + + @Test + public void accessControllerSuccessfullyActivated() { + when(properties.truststoreFileLocation()).thenReturn(TRUSTSTORE.toString()); + when(properties.truststorePasswordFileLocation()).thenReturn(TRUSTSTORE_PASSWORD_FILE.toString()); + when(properties.keystoreFileLocation()).thenReturn(KEYSTORE.toString()); + when(properties.keystorePasswordFileLocation()).thenReturn(KEYSTORE_PASSWORD_FILE.toString()); + when(properties.rcc_keystoreFileLocation()).thenReturn(RCC_KEYSTORE.toString()); + when(properties.rcc_keystorePasswordFileLocation()).thenReturn(RCC_KEYSTORE_PASSWORD_FILE.toString()); + when(properties.rcc_policy()).thenReturn("[{\"controller_name\":\"AccessM&C\",\"controller_restapiUrl\":\"10.118.191.43:26335\",\"controller_restapiUser\":\"access\",\"controller_restapiPassword\":\"Huawei@123\",\"controller_accessTokenUrl\":\"/rest/plat/smapp/v1/oauth/token\",\"controller_accessTokenFile\":\"./etc/access-token.json\",\"controller_accessTokenMethod\":\"put\",\"controller_subsMethod\":\"post\",\"controller_subscriptionUrl\":\"/restconf/v1/operations/huawei-nce-notification-action:establish-subscription\",\"event_details\":[{\"event_name\":\"ONT_registration\",\"event_description\":\"ONTregistartionevent\",\"event_sseventUrlEmbed\":\"true\",\"event_sseventsField\":\"output.url\",\"event_sseventsUrl\":\"null\",\"event_subscriptionTemplate\":\"./etc/ont_registartion_subscription_template.json\",\"event_unSubscriptionTemplate\":\"./etc/ont_registartion_unsubscription_template.json\",\"event_ruleId\":\"777777777\"}]}]"); + when(ctx.getAttribute("responsePrefix.httpResponse")).thenReturn("{\"accessSession\" : \"1234567890\",\"result\" : \"Ok\"}"); + try { + doThrow(new Exception()).when(restApiCallNode).sendRequest(null, null, 0); + } catch (Exception e){} + try { + when(readAllBytes(null)).thenReturn("colletor".getBytes()); + } catch (Exception e){} + + JSONObject controller = new JSONObject("{\"controller_name\":\"AccessM&C\",\"controller_restapiUrl\":\"10.118.191.43:26335\",\"controller_restapiUser\":\"access\",\"controller_restapiPassword\":\"Huawei@123\",\"controller_accessTokenUrl\":\"/rest/plat/smapp/v1/oauth/token\",\"controller_accessTokenFile\":\"./etc/access-token.json\",\"controller_accessTokenMethod\":\"put\",\"controller_subsMethod\":\"post\",\"controller_subscriptionUrl\":\"/restconf/v1/operations/huawei-nce-notification-action:establish-subscription\",\"event_details\":[{\"event_name\":\"ONT_registration\",\"event_description\":\"ONTregistartionevent\",\"event_sseventUrlEmbed\":\"true\",\"event_sseventsField\":\"output.url\",\"event_sseventsUrl\":\"null\",\"event_subscriptionTemplate\":\"./etc/ont_registartion_subscription_template.json\",\"event_unSubscriptionTemplate\":\"./etc/ont_registartion_unsubscription_template.json\",\"event_ruleId\":\"777777777\"}]}"); + try { + AccessController acClr = new AccessController(controller, + properties); + acClr.activate(); + } catch (Exception e){} + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/AnyNodeTest.java b/src/test/java/org/onap/dcae/AnyNodeTest.java new file mode 100644 index 0000000..20fbf35 --- /dev/null +++ b/src/test/java/org/onap/dcae/AnyNodeTest.java @@ -0,0 +1,64 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.common.collect.Sets; +import java.util.Set; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.dcae.common.AnyNode; + +/** + * Created by koblosz on 07.06.18. + */ +public class AnyNodeTest { + + private static final String SAMPLE_JSON_FILEPATH = "{\n" + + " \"channels\": [{\n" + + " \"one\": \"number1\", \"two\": \"number2\", \"three\": \"number3\"}],\n" + + " \"sampleStrList\": [\"1\", \"2\", \"3\", \"4\", \"5\"],\n" + + " \"sampleNestedObject\": {\"a\": 1, \"b\": 2},\n" + + " \"sampleInt\": 1,\n" + + " \"sampleString\": \"str\",\n" + + " \"sampleNull\": null\n" + + "}\n"; + private static final Set EXPECTED_JSON_KEYS = Sets + .newHashSet("channels", "sampleStrList", "sampleNestedObject", "sampleInt", "sampleString", "sampleNull"); + private static AnyNode node; + + + @BeforeClass + public static void setUpClass() { + node = AnyNode.fromString(SAMPLE_JSON_FILEPATH); + } + + @Test + public void testShouldReturnJsonObjectKeySet() { + assertThat(node.keys()).containsOnlyElementsOf(EXPECTED_JSON_KEYS); + } + + @Test(expected = ClassCastException.class) + public void whenInvokedOnJsonObjInsteadOfJsonArrShouldRaiseRuntimeEx() { + node.toList(); + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/ApplicationSettingsTest.java b/src/test/java/org/onap/dcae/ApplicationSettingsTest.java new file mode 100644 index 0000000..1e1a115 --- /dev/null +++ b/src/test/java/org/onap/dcae/ApplicationSettingsTest.java @@ -0,0 +1,337 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae; + +import static java.util.Collections.singletonList; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import static org.junit.Assert.assertTrue; +import static org.onap.dcae.CLIUtils.processCmdLine; + +import io.vavr.collection.HashMap; +import io.vavr.collection.Map; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Objects; +import org.junit.Test; + +public class ApplicationSettingsTest { + + @Test + public void shouldMakeApplicationSettingsOutOfCLIArguments() { + // given + String[] cliArguments = {"-param1", "param1value", "-param2", "param2value"}; + + // when + ApplicationSettings configurationAccessor = new ApplicationSettings(cliArguments, CLIUtils::processCmdLine); + String param1value = configurationAccessor.getStringDirectly("param1"); + String param2value = configurationAccessor.getStringDirectly("param2"); + + // then + assertEquals("param1value", param1value); + assertEquals("param2value", param2value); + } + + @Test + public void shouldMakeApplicationSettingsOutOfCLIArgumentsAndAConfigurationFile() + throws IOException { + // given + File tempConfFile = File.createTempFile("doesNotMatter", "doesNotMatter"); + Files.write(tempConfFile.toPath(), Arrays.asList("section.subSection1=abc", "section.subSection2=zxc")); + tempConfFile.deleteOnExit(); + String[] cliArguments = {"-param1", "param1value", "-param2", "param2value", "-c", tempConfFile.toString()}; + + // when + ApplicationSettings configurationAccessor = new ApplicationSettings(cliArguments, CLIUtils::processCmdLine); + String param1value = configurationAccessor.getStringDirectly("param1"); + String param2value = configurationAccessor.getStringDirectly("param2"); + String fromFileParam1Value = configurationAccessor.getStringDirectly("section.subSection1"); + String fromFileParam2Value = configurationAccessor.getStringDirectly("section.subSection2"); + + // then + assertEquals("param1value", param1value); + assertEquals("param2value", param2value); + assertEquals("abc", fromFileParam1Value); + assertEquals("zxc", fromFileParam2Value); + } + + @Test + public void shouldCLIArgumentsOverrideConfigFileParameters() throws IOException { + // given + String[] cliArguments = {"-section.subSection1", "abc"}; + File tempConfFile = File.createTempFile("doesNotMatter", "doesNotMatter"); + Files.write(tempConfFile.toPath(), singletonList("section.subSection1=zxc")); + tempConfFile.deleteOnExit(); + + // when + ApplicationSettings configurationAccessor = new ApplicationSettings(cliArguments, CLIUtils::processCmdLine); + String actuallyOverridenByCLIParam = configurationAccessor.getStringDirectly("section.subSection1"); + + // then + assertEquals("abc", actuallyOverridenByCLIParam); + } + + @Test + public void shouldReturnHTTPPort() throws IOException { + // when + int applicationPort = fromTemporaryConfiguration("collector.rcc.service.port=8090") + .httpPort(); + + // then + assertEquals(8090, applicationPort); + } + + @Test + public void shouldReturnDefaultHTTPPort() throws IOException { + // when + int applicationPort = fromTemporaryConfiguration().httpPort(); + + // then + assertEquals(8686, applicationPort); + } + + @Test + public void shouldReturnIfHTTPSIsEnabled() throws IOException { + // when + boolean httpsEnabled = fromTemporaryConfiguration("collector.rcc.service.secure.port=8687") + .httpsEnabled(); + + // then + assertTrue(httpsEnabled); + } + + @Test + public void shouldReturnIfHTTPIsEnabled() throws IOException { + // when + boolean httpsEnabled = fromTemporaryConfiguration("collector.service.port=8686").httpsEnabled(); + // then + assertTrue(httpsEnabled); + } + + @Test + public void shouldByDefaultHTTPSBeDisabled() throws IOException { + // when + boolean httpsEnabled = fromTemporaryConfiguration().httpsEnabled(); + + // then + assertTrue(httpsEnabled); + } + + @Test + public void shouldReturnHTTPSPort() throws IOException { + // when + int httpsPort = fromTemporaryConfiguration("collector.service.secure.port=8687") + .httpsPort(); + + // then + assertEquals(8687, httpsPort); + } + + + @Test + public void shouldReturnLocationOfThePasswordFile() throws IOException { + // when + String passwordFileLocation = fromTemporaryConfiguration("collector.rcc.keystore.passwordfile=/somewhere/password") + .keystorePasswordFileLocation(); + + // then + assertEquals(sanitizePath("/somewhere/password"), passwordFileLocation); + } + + @Test + public void shouldReturnDefaultLocationOfThePasswordFile() throws IOException { + // when + String passwordFileLocation = fromTemporaryConfiguration().keystorePasswordFileLocation(); + + // then + assertEquals(sanitizePath("etc/passwordfile"), passwordFileLocation); + } + + @Test + public void shouldReturnLocationOfTheKeystoreFile() throws IOException { + // when + String keystoreFileLocation = fromTemporaryConfiguration("collector.rcc.keystore.file.location=/somewhere/keystore") + .keystoreFileLocation(); + + // then + assertEquals(sanitizePath("/somewhere/keystore"), keystoreFileLocation); + } + + @Test + public void shouldReturnLocationOfTheDefaultKeystoreFile() throws IOException { + // when + String keystoreFileLocation = fromTemporaryConfiguration().keystoreFileLocation(); + + // then + assertEquals(sanitizePath("etc/sdnc.p12"), keystoreFileLocation); + } + + @Test + public void shouldReturnDMAAPConfigFileLocation() throws IOException { + // when + String dmaapConfigFileLocation = fromTemporaryConfiguration("collector.dmaapfile=/somewhere/dmaapFile") + .dMaaPConfigurationFileLocation(); + + // then + assertEquals(sanitizePath("/somewhere/dmaapFile"), dmaapConfigFileLocation); + } + + @Test + public void shouldReturnDefaultDMAAPConfigFileLocation() throws IOException { + // when + String dmaapConfigFileLocation = fromTemporaryConfiguration().dMaaPConfigurationFileLocation(); + + // then + assertEquals(sanitizePath("etc/DmaapConfig.json"), dmaapConfigFileLocation); + } + + @Test + public void shouldReturnMaximumAllowedQueuedEvents() throws IOException { + // when + int maximumAllowedQueuedEvents = fromTemporaryConfiguration("collector.rcc.inputQueue.maxPending=10000") + .maximumAllowedQueuedEvents(); + + // then + assertEquals(10000, maximumAllowedQueuedEvents); + } + + @Test + public void shouldReturnDefaultMaximumAllowedQueuedEvents() throws IOException { + // when + int maximumAllowedQueuedEvents = fromTemporaryConfiguration().maximumAllowedQueuedEvents(); + + // then + assertEquals(1024 * 4, maximumAllowedQueuedEvents); + } + + + + +// @Test +// public void shouldReturnDMAAPStreamId() throws IOException { +// // given +// Map expected = HashMap.of( +// "s", new String[]{"something", "something2"}, +// "s2", new String[]{"something3"} +// ); +// +// // when +// Map dmaapStreamID = fromTemporaryConfiguration( +// "collector.dmaap.streamid=s=something,something2|s2=something3") +// .dMaaPStreamsMapping(); +// +// // then +// assertArrayEquals(expected.get("s").get(), Objects.requireNonNull(dmaapStreamID).get("s").get()); +// assertArrayEquals(expected.get("s2").get(), Objects.requireNonNull(dmaapStreamID).get("s2").get()); +// assertEquals(expected.keySet(), dmaapStreamID.keySet()); +// } +// +// @Test +// public void shouldReturnDefaultDMAAPStreamId() throws IOException { +// // when +// Map dmaapStreamID = fromTemporaryConfiguration().dMaaPStreamsMapping(); +// +// // then +// assertEquals(dmaapStreamID, HashMap.empty()); +// } + + @Test + public void shouldReturnIfAuthorizationIsEnabled() throws IOException { + // when + boolean authorizationEnabled = fromTemporaryConfiguration("collector.header.authflag=1") + .authorizationEnabled(); + + // then + assertTrue(authorizationEnabled); + } + + @Test + public void shouldAuthorizationBeDisabledByDefault() throws IOException { + // when + boolean authorizationEnabled = fromTemporaryConfiguration().authorizationEnabled(); + + // then + assertFalse(authorizationEnabled); + } + + @Test + public void shouldReturnValidCredentials() throws IOException { + // when + Map allowedUsers = fromTemporaryConfiguration( + "collector.header.authlist=pasza,c2ltcGxlcGFzc3dvcmQNCg==|someoneelse,c2ltcGxlcGFzc3dvcmQNCg==" + ).validAuthorizationCredentials(); + + // then + assertEquals(allowedUsers.get("pasza").get(), "c2ltcGxlcGFzc3dvcmQNCg=="); + assertEquals(allowedUsers.get("someoneelse").get(), "c2ltcGxlcGFzc3dvcmQNCg=="); + } + + @Test + public void shouldbyDefaultThereShouldBeNoValidCredentials() throws IOException { + // when + Map userToBase64PasswordDelimitedByCommaSeparatedByPipes = fromTemporaryConfiguration(). + validAuthorizationCredentials(); + + // then + assertTrue(userToBase64PasswordDelimitedByCommaSeparatedByPipes.isEmpty()); + } + + + @Test + public void shouldReturnCambriaConfigurationFileLocation() throws IOException { + // when + String cambriaConfigurationFileLocation = fromTemporaryConfiguration( + "collector.dmaapfile=/somewhere/dmaapConfig") + .dMaaPConfigurationFileLocation(); + + // then + assertEquals(sanitizePath("/somewhere/dmaapConfig"), cambriaConfigurationFileLocation); + } + + @Test + public void shouldReturnDefaultCambriaConfigurationFileLocation() throws IOException { + // when + String cambriaConfigurationFileLocation = fromTemporaryConfiguration() + .dMaaPConfigurationFileLocation(); + + // then + assertEquals(sanitizePath("etc/DmaapConfig.json"), cambriaConfigurationFileLocation); + } + + private static ApplicationSettings fromTemporaryConfiguration(String... fileLines) + throws IOException { + File tempConfFile = File.createTempFile("doesNotMatter", "doesNotMatter"); + Files.write(tempConfFile.toPath(), Arrays.asList(fileLines)); + tempConfFile.deleteOnExit(); + return new ApplicationSettings(new String[]{"-c", tempConfFile.toString()}, args -> processCmdLine(args), ""); + } + + private String sanitizePath(String path) { + return Paths.get(path).toString(); + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/CLIUtilsTest.java b/src/test/java/org/onap/dcae/CLIUtilsTest.java new file mode 100644 index 0000000..caf88ac --- /dev/null +++ b/src/test/java/org/onap/dcae/CLIUtilsTest.java @@ -0,0 +1,58 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae; + +import io.vavr.collection.Map; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CLIUtilsTest { + + @Test + public void shouldConvertArgsToPropertiesMap() { + // given + String[] args = {"-withOutValue", "-collector.service.port", "8000", "-collector.service.secure.port", "8687"}; + + //when + Map properties = CLIUtils.processCmdLine(args); + + //then + assertThat(properties.get("collector.service.port").get()).isEqualTo("8000"); + assertThat(properties.get("collector.service.secure.port").get()).isEqualTo("8687"); + assertThat(properties.get("withOutValue").get()).isEqualTo(""); + } + + @Test + public void shouldReturnEmptyMapIfThereIsNoArgs() { + //given + String[] args = {}; + + //when + Map properties = CLIUtils.processCmdLine(args); + + //then + assertThat(properties).isEmpty(); + } + +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/TLSTest.java b/src/test/java/org/onap/dcae/TLSTest.java new file mode 100644 index 0000000..ddb39ee --- /dev/null +++ b/src/test/java/org/onap/dcae/TLSTest.java @@ -0,0 +1,94 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae; + +import io.vavr.collection.HashMap; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpStatus; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.when; +import static org.onap.dcae.TLSTest.HttpsConfiguration.USERNAME; +import static org.onap.dcae.TLSTest.HttpsConfiguration.PASSWORD; + +public class TLSTest extends TLSTestBase { + + @Nested + @Import(HttpConfiguration.class) + class HttpTest extends TestClassBase { + + @Test + public void shouldHttpRequestSucceed() { + assertEquals(HttpStatus.OK, makeHttpRequest().getStatusCode()); + } + + @Test + public void shouldHttpsRequestFail() { + assertThrows(Exception.class, this::makeHttpsRequest); + } + } + + + static class HttpConfiguration extends TLSTestBase.ConfigurationBase { + @Override + protected void configureSettings(ApplicationSettings settings) { + } + } + + static class HttpsConfiguration extends TLSTestBase.ConfigurationBase { + public static final String USERNAME = "TestUser"; + public static final String PASSWORD = "TestPassword"; + + @Override + protected void configureSettings(ApplicationSettings settings) { + when(settings.keystoreFileLocation()).thenReturn(KEYSTORE.toString()); + when(settings.keystorePasswordFileLocation()).thenReturn(KEYSTORE_PASSWORD_FILE.toString()); + when(settings.rcc_keystoreFileLocation()).thenReturn(RCC_KEYSTORE.toString()); + when(settings.rcc_keystorePasswordFileLocation()).thenReturn(RCC_KEYSTORE_PASSWORD_FILE.toString()); + when(settings.authorizationEnabled()).thenReturn(true); + when(settings.validAuthorizationCredentials()).thenReturn(HashMap.of(USERNAME, "$2a$10$51tDgG2VNLde5E173Ay/YO.Fq.aD.LR2Rp8pY3QAKriOSPswvGviy")); + } + } + + static class HttpsConfigurationWithTLSAuthentication extends HttpsConfiguration { + @Override + protected void configureSettings(ApplicationSettings settings) { + super.configureSettings(settings); + when(settings.authorizationEnabled()).thenReturn(false); + when(settings.clientTlsAuthenticationEnabled()).thenReturn(true); + when(settings.truststoreFileLocation()).thenReturn(TRUSTSTORE.toString()); + when(settings.truststorePasswordFileLocation()).thenReturn(TRUSTSTORE_PASSWORD_FILE.toString()); + } + } + + static class HttpsConfigurationWithTLSAuthenticationAndBasicAuth extends HttpsConfigurationWithTLSAuthentication { + @Override + protected void configureSettings(ApplicationSettings settings) { + super.configureSettings(settings); + when(settings.authorizationEnabled()).thenReturn(true); + } + } +} diff --git a/src/test/java/org/onap/dcae/TLSTestBase.java b/src/test/java/org/onap/dcae/TLSTestBase.java new file mode 100644 index 0000000..fdcc6e6 --- /dev/null +++ b/src/test/java/org/onap/dcae/TLSTestBase.java @@ -0,0 +1,154 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae; + +import org.json.JSONObject; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.support.BasicAuthenticationInterceptor; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.web.client.RestTemplate; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.LinkedBlockingQueue; + +import static org.onap.dcae.TestingUtilities.*; + +@Configuration +@ExtendWith(SpringExtension.class) +public class TLSTestBase { + protected static final String KEYSTORE_ALIAS = "tomcat"; + protected static final Path RESOURCES = Paths.get("src", "test", "resources"); + protected static final Path KEYSTORE = Paths.get(RESOURCES.toString(), "keystore"); + protected static final Path KEYSTORE_PASSWORD_FILE = Paths.get(RESOURCES.toString(), "passwordfile"); + protected static final Path TRUSTSTORE = Paths.get(RESOURCES.toString(), "truststore"); + protected static final Path TRUSTSTORE_PASSWORD_FILE = Paths.get(RESOURCES.toString(), "trustpasswordfile"); + protected static final Path RCC_KEYSTORE_PASSWORD_FILE = Paths.get(RESOURCES.toString(), "rcc_passwordfile"); + protected static final Path RCC_KEYSTORE = Paths.get(RESOURCES.toString(), "sdnc.p12"); + + protected static abstract class ConfigurationBase { + protected final ApplicationSettings settings = Mockito.mock(ApplicationSettings.class); + + @Bean + @Primary + public ApplicationSettings settings() { + configureSettings(settings); + return settings; + } + + protected abstract void configureSettings(final ApplicationSettings settings); + } + + @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) + protected abstract class TestClassBase { + @MockBean + @Qualifier("inputQueue") + protected LinkedBlockingQueue queue; + + @LocalServerPort + private int port; + + private final String keyStorePassword; + private final String trustStorePassword; + + public TestClassBase() { + keyStorePassword = readFile(RCC_KEYSTORE_PASSWORD_FILE); + trustStorePassword = readFile(TRUSTSTORE_PASSWORD_FILE); + } + + private String getURL(final String protocol, final String uri) { + return protocol + "://localhost:" + port + uri; + } + + private RestTemplate addBasicAuth(final RestTemplate template, final String username, final String password) { + template.getInterceptors() + .add(new BasicAuthenticationInterceptor(username, password)); + + return template; + } + + public String createHttpURL(String uri) { + return getURL("http", uri); + } + + public String createHttpsURL(String uri) { + return getURL("https", uri); + } + + public RestTemplate createHttpRestTemplate() { + return new RestTemplate(); + } + + public RestTemplate createHttpsRestTemplate() { + return rethrow(() -> + createRestTemplateWithSsl( + sslBuilderWithTrustStore(KEYSTORE, keyStorePassword).build() + )); + } + + public RestTemplate createHttpsRestTemplateWithKeyStore() { + return rethrow(() -> + createRestTemplateWithSsl( + configureKeyStore( + sslBuilderWithTrustStore(RCC_KEYSTORE, keyStorePassword), + TRUSTSTORE, + trustStorePassword + ).build()) + ); + } + + public ResponseEntity makeHttpRequest() { + return createHttpRestTemplate().getForEntity(createHttpURL("/"), String.class); + } + + public ResponseEntity makeHttpsRequest() { + return createHttpsRestTemplate().getForEntity(createHttpsURL("/"), String.class); + } + + + public ResponseEntity makeHttpsRequestWithBasicAuth(final String username, final String password) { + return addBasicAuth(createHttpsRestTemplate(), username, password) + .getForEntity(createHttpsURL("/"), String.class); + + } + + public ResponseEntity makeHttpsRequestWithClientCert() { + return createHttpsRestTemplateWithKeyStore().getForEntity(createHttpsURL("/"), String.class); + } + + public ResponseEntity makeHttpsRequestWithClientCertAndBasicAuth( + final String username, + final String password) { + return addBasicAuth(createHttpsRestTemplateWithKeyStore(), username, password) + .getForEntity(createHttpsURL("/"), String.class); + } + } +} diff --git a/src/test/java/org/onap/dcae/TestingUtilities.java b/src/test/java/org/onap/dcae/TestingUtilities.java new file mode 100644 index 0000000..5ae238a --- /dev/null +++ b/src/test/java/org/onap/dcae/TestingUtilities.java @@ -0,0 +1,141 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae; + +import static java.nio.file.Files.readAllBytes; +import static org.assertj.core.api.Assertions.assertThat; + +import io.vavr.control.Try; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; + +import org.apache.http.client.HttpClient; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.ssl.SSLContextBuilder; +import org.assertj.core.api.AbstractThrowableAssert; +import org.assertj.core.api.Java6Assertions; +import org.json.JSONObject; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +import javax.net.ssl.SSLContext; + +public final class TestingUtilities { + + private TestingUtilities() { + // utility class, no objects allowed + } + + public static void assertJSONObjectsEqual(JSONObject o1, JSONObject o2) { + assertThat(o1.toString()).isEqualTo(o2.toString()); + } + + public static JSONObject readJSONFromFile(Path path) { + return rethrow(() -> new JSONObject(readFile(path))); + } + + public static String readFile(Path path) { + return rethrow(() -> new String(readAllBytes(path))); + } + + public static Path createTemporaryFile(String content) { + return rethrow(() -> { + File temp = File.createTempFile("restconf-collector-tests-created-this-file", ".tmp"); + temp.deleteOnExit(); + Path filePath = Paths.get(temp.toString()); + Files.write(filePath, content.getBytes()); + return filePath; + }); + } + + /** + * Exception in test case usually means there is something wrong, it should never be catched, but rather thrown to + * be handled by JUnit framework. + */ + public static T rethrow(CheckedSupplier supplier) { + try { + return supplier.get(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @FunctionalInterface + interface CheckedSupplier { + + T get() throws Exception; + } + + public static void assertFailureHasInfo(Try any, String... msgPart) { + Java6Assertions.assertThat(any.isFailure()).isTrue(); + AbstractThrowableAssert o = Java6Assertions.assertThat(any.getCause()) + .hasCauseInstanceOf(Exception.class); + for (String s : msgPart) { + o.hasStackTraceContaining(s); + } + } + + public static SSLContextBuilder sslBuilderWithTrustStore(final Path trustStore, final String pass) { + return rethrow(() -> + new SSLContextBuilder() + .loadTrustMaterial(trustStore.toFile(), pass.toCharArray()) + ); + } + + public static SSLContextBuilder configureKeyStore( + final SSLContextBuilder builder, + final Path keyStore, + final String pass) { + return rethrow(() -> { + KeyStore cks = KeyStore.getInstance(KeyStore.getDefaultType()); + cks.load(new FileInputStream(keyStore.toFile()), pass.toCharArray()); + + builder.loadKeyMaterial(cks, pass.toCharArray()); + + return builder; + }); + } + + public static RestTemplate createRestTemplateWithSsl(final SSLContext context) { + final SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(context); + final HttpClient httpClient = HttpClients + .custom() + .setSSLSocketFactory(socketFactory) + .build(); + + final HttpComponentsClientHttpRequestFactory factory = + new HttpComponentsClientHttpRequestFactory(httpClient); + + return new RestTemplate(factory); + } +} diff --git a/src/test/java/org/onap/dcae/WiremockBasedTest.java b/src/test/java/org/onap/dcae/WiremockBasedTest.java new file mode 100644 index 0000000..2144e99 --- /dev/null +++ b/src/test/java/org/onap/dcae/WiremockBasedTest.java @@ -0,0 +1,68 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae; + +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.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; +import static io.vavr.API.Map; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import io.vavr.collection.Map; +import org.junit.Rule; + +public class WiremockBasedTest { + + @Rule + public WireMockRule wireMockRule = new WireMockRule( + wireMockConfig().dynamicPort().dynamicHttpsPort().keystorePath(null)); + + protected void stubConsulToReturnLocalAddressOfCBS() { + stubFor(get(urlEqualTo("/v1/catalog/service/CBSName")) + .willReturn(aResponse().withBody(validLocalCBSConf()))); + } + + protected void stubCBSToReturnAppConfig(String sampleConfigForVES) { + stubFor(get(urlEqualTo("/service_component/restconfcollector")) + .willReturn(aResponse().withBody(sampleConfigForVES))); + } + + protected Map wiremockBasedEnvProps() { + return Map( + "CONSUL_HOST", "localhost", + "CONSUL_PORT", "" + wireMockRule.port(), + "HOSTNAME", "restconfcollector", + "CONFIG_BINDING_SERVICE", "CBSName" + ); + } + + protected String validLocalCBSConf() { + return "" + + "[{ " + + "\"ServiceAddress\": \"localhost\"," + + "\"ServicePort\":" + wireMockRule.port() + + "}]"; + } +} diff --git a/src/test/java/org/onap/dcae/collectors/restconf/common/AuthTypeTest.java b/src/test/java/org/onap/dcae/collectors/restconf/common/AuthTypeTest.java deleted file mode 100644 index 8eaee6f..0000000 --- a/src/test/java/org/onap/dcae/collectors/restconf/common/AuthTypeTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2019 IBM. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import org.junit.Test; - -import static org.junit.Assert.*; - -public class AuthTypeTest { - - @Test - public void fromString() { - assertEquals(AuthType.BASIC, AuthType.fromString("basic")); - assertEquals(AuthType.DIGEST, AuthType.fromString("digest")); - assertEquals(AuthType.OAUTH, AuthType.fromString("oauth")); - assertEquals(AuthType.NONE, AuthType.fromString("none")); - assertEquals(AuthType.Unspecified, AuthType.fromString("unspecified")); - } - - @Test(expected = IllegalArgumentException.class) - public void fromStringWithException() { - AuthType.fromString("test"); - } -} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/collectors/restconf/common/FormatTest.java b/src/test/java/org/onap/dcae/collectors/restconf/common/FormatTest.java deleted file mode 100644 index dd4159b..0000000 --- a/src/test/java/org/onap/dcae/collectors/restconf/common/FormatTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2019 IBM. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class FormatTest { - - @Test - public void fromString() { - assertEquals(Format.JSON, Format.fromString("json")); - assertEquals(Format.XML, Format.fromString("xml")); - assertEquals(Format.NONE, Format.fromString("none")); - } - - @Test(expected = IllegalArgumentException.class) - public void fromStringWithException() { - Format.fromString("test"); - } -} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/collectors/restconf/common/RestConfContextTest.java b/src/test/java/org/onap/dcae/collectors/restconf/common/RestConfContextTest.java deleted file mode 100644 index 696c254..0000000 --- a/src/test/java/org/onap/dcae/collectors/restconf/common/RestConfContextTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2019 IBM. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - - -package org.onap.dcae.collectors.restconf.common; - -import org.junit.Test; - -import static org.junit.Assert.*; - -public class RestConfContextTest { - - @Test - public void setAttribute() { - String key = "key"; - String value = "value"; - RestConfContext restConfContext = new RestConfContext(); - restConfContext.setAttribute(key, value); - assertEquals(value, restConfContext.getAttribute(key)); - restConfContext.setAttribute(key, null); - assertFalse(restConfContext.getAttributeKeySet().contains(key)); - } - - @Test - public void getAttributeKeySet() { - String key = "key"; - String value = "value"; - String key1 = "key1"; - String value1 = "value1"; - RestConfContext restConfContext = new RestConfContext(); - restConfContext.setAttribute(key,value); - restConfContext.setAttribute(key1,value1); - assertTrue(restConfContext.getAttributeKeySet().contains(key) && restConfContext.getAttributeKeySet().contains(key1)); - } -} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/collectors/restconf/common/RetryPolicyStoreTest.java b/src/test/java/org/onap/dcae/collectors/restconf/common/RetryPolicyStoreTest.java deleted file mode 100644 index 9508b1a..0000000 --- a/src/test/java/org/onap/dcae/collectors/restconf/common/RetryPolicyStoreTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2019 IBM. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - - -package org.onap.dcae.collectors.restconf.common; - -import org.junit.Before; -import org.junit.Test; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.*; - -public class RetryPolicyStoreTest { - - RetryPolicyStore retryPolicyStore; - String proxyServers; - - @Before - public void setUp() throws Exception { - retryPolicyStore = new RetryPolicyStore(); - proxyServers = "3.3.3.3,4.4.4.4,5.5.5.5"; - } - - @Test - public void getProxyServers() { - retryPolicyStore.setProxyServers(proxyServers); - assertThat(retryPolicyStore.getProxyServers(), is(proxyServers)); - } - - @Test - public void setProxyServers() throws RetryException { - retryPolicyStore.setProxyServers(proxyServers); - RetryPolicy actual = retryPolicyStore.getRetryPolicy("dme2proxy"); - assertThat(3, is(actual.getMaximumRetries())); - assertThat("4.4.4.4", is(actual.getNextHostName("3.3.3.3"))); - assertThat("5.5.5.5", is(actual.getNextHostName("4.4.4.4"))); - } - - @Test - public void getRetryPolicy() { - String[] adminServersArray = {"3.3.3.3","4.4.4.4","5.5.5.5"}; - RetryPolicy retryPolicy = new RetryPolicy(adminServersArray, adminServersArray.length); - retryPolicyStore.retryPolicies.put("dme2proxy", retryPolicy); - assertThat(retryPolicyStore.getRetryPolicy("dme2proxy"), is(retryPolicy)); - } -} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/collectors/restconf/common/RetryPolicyTest.java b/src/test/java/org/onap/dcae/collectors/restconf/common/RetryPolicyTest.java deleted file mode 100644 index 1b8cfcb..0000000 --- a/src/test/java/org/onap/dcae/collectors/restconf/common/RetryPolicyTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2019 IBM. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common; - -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class RetryPolicyTest { - - String[] hostnames; - Integer maximumRetries; - RetryPolicy retryPolicy; - - @Before - public void setUp() throws Exception { - hostnames = "test1.com,test2.com,test3.com,4.4.4.4".split(","); - maximumRetries = 3; - retryPolicy = new RetryPolicy(this.hostnames, this.maximumRetries); - } - - @Test - public void testGetMaximumRetries() { - assertEquals(maximumRetries, retryPolicy.getMaximumRetries()); - } - - @Test - public void testGetNextHostName() throws RetryException { - assertEquals(hostnames[2], retryPolicy.getNextHostName("http://" + hostnames[1] + "/endpoint")); - assertEquals(hostnames[0], retryPolicy.getNextHostName("http://" + hostnames[3] + "/endpoint")); - } - - @Test(expected = RetryException.class) - public void testGetNextHostNameWithException() throws RetryException { - retryPolicy.getNextHostName("abc"); - } -} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPConfigurationParserTest.java b/src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPConfigurationParserTest.java deleted file mode 100755 index 730d257..0000000 --- a/src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPConfigurationParserTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common.event.publishing; - -import io.vavr.collection.Map; -import io.vavr.control.Try; -import org.junit.Test; - -import java.nio.file.Path; -import java.nio.file.Paths; - -import static io.vavr.API.List; -import static org.assertj.core.api.Assertions.assertThat; -import static org.onap.dcae.collectors.restconf.common.event.publishing.DMaaPConfigurationParser.parseToDomainMapping; - -public class DMaaPConfigurationParserTest { - @Test - public void testParseCredentialsForGen2() { - Path path = Paths.get("src/test/resources/testParseDMaaPCredentialsGen2.json"); - Try> publisherConfigs = parseToDomainMapping(path); - - PublisherConfig authCredentialsNulls = publisherConfigs.get().get("auth-credentials-null").getOrNull(); - assertThat(authCredentialsNulls.userName().isEmpty()).isTrue(); - assertThat(authCredentialsNulls.password().isEmpty()).isTrue(); - assertThat(authCredentialsNulls.isSecured()).isFalse(); - - PublisherConfig authCredentialsPresent = publisherConfigs.get().get("auth-credentials-present").getOrNull(); - assertThat(authCredentialsPresent.userName().getOrNull()).isEqualTo("sampleUser"); - assertThat(authCredentialsPresent.password().getOrNull()).isEqualTo("samplePassword"); - assertThat(authCredentialsPresent.isSecured()).isTrue(); - - PublisherConfig authCredentialsKeysMissing = publisherConfigs.get().get("auth-credentials-missing").getOrNull(); - assertThat(authCredentialsKeysMissing.userName().isEmpty()).isTrue(); - assertThat(authCredentialsKeysMissing.password().isEmpty()).isTrue(); - assertThat(authCredentialsKeysMissing.isSecured()).isFalse(); - } - - - @Test - public void testParseCredentialsForLegacy() { - Path path = Paths.get("src/test/resources/testParseDMaaPCredentialsLegacy.json"); - Try> publisherConfigs = parseToDomainMapping(path); - - PublisherConfig authCredentialsNull = publisherConfigs.get().get("auth-credentials-null").getOrNull(); - assertThat(authCredentialsNull.userName().isEmpty()).isTrue(); - assertThat(authCredentialsNull.password().isEmpty()).isTrue(); - assertThat(authCredentialsNull.isSecured()).isFalse(); - - PublisherConfig authCredentialsPresent = publisherConfigs.get().get("auth-credentials-present").getOrNull(); - assertThat(authCredentialsPresent.userName().getOrNull()).isEqualTo("sampleUser"); - assertThat(authCredentialsPresent.password().getOrNull()).isEqualTo("samplePassword"); - assertThat(authCredentialsPresent.isSecured()).isTrue(); - - PublisherConfig authCredentialsMissing = publisherConfigs.get().get("auth-credentials-missing").getOrNull(); - assertThat(authCredentialsMissing.userName().isEmpty()).isTrue(); - assertThat(authCredentialsMissing.password().isEmpty()).isTrue(); - assertThat(authCredentialsMissing.isSecured()).isFalse(); - } - - - @Test - public void testParseGen2() { - Path path = Paths.get("src/test/resources/testParseDMaaPGen2.json"); - Try> publisherConfigs = parseToDomainMapping(path); - - PublisherConfig withEventsSegment = publisherConfigs.get().get("event-segments-with-port").getOrNull(); - assertThat(withEventsSegment.destinations()).isEqualTo(List("UEBHOST:3904")); - assertThat(withEventsSegment.topic()).isEqualTo("DCAE-RESTCONF-COLLECTOR-EVENTS-DEV"); - - PublisherConfig withOtherSegment = publisherConfigs.get().get("other-segments-without-ports").getOrNull(); - assertThat(withOtherSegment.destinations()).isEqualTo(List("UEBHOST")); - assertThat(withOtherSegment.topic()).isEqualTo("DCAE-RESTCONF-COLLECTOR-EVENTS-DEV"); - } - - @Test - public void testParseLegacy() { - Path exemplaryConfig = Paths.get("src/test/resources/testParseDMaaPLegacy.json"); - Try> publisherConfigs = - parseToDomainMapping(exemplaryConfig); - - PublisherConfig urlFirstThenHosts = publisherConfigs.get().get("url-precedes-hosts").getOrNull(); - assertThat(urlFirstThenHosts.destinations()).isEqualTo(List("127.0.0.1:3904")); - assertThat(urlFirstThenHosts.topic()).isEqualTo("DCAE-RESTCONF-COLLECTOR-EVENTS-DEV"); - - PublisherConfig urlKeyMissing = publisherConfigs.get().get("url-key-missing").getOrNull(); - assertThat(urlKeyMissing.destinations()).isEqualTo(List("h1.att.com", "h2.att.com")); - assertThat(urlKeyMissing.topic()).isEqualTo("DCAE-RESTCONF-COLLECTOR-EVENTS-DEV"); - - PublisherConfig urlIsMissing = publisherConfigs.get().get("url-is-null").getOrNull(); - assertThat(urlIsMissing.destinations()).isEqualTo(List("h1.att.com", "h2.att.com")); - assertThat(urlIsMissing.topic()).isEqualTo("DCAE-RESTCONF-COLLECTOR-EVENTS-DEV"); - } -} diff --git a/src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPEventPublisherTest.java b/src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPEventPublisherTest.java deleted file mode 100755 index 3e1095d..0000000 --- a/src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPEventPublisherTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common.event.publishing; - -import com.att.nsa.cambria.client.CambriaBatchingPublisher; -import org.json.JSONObject; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Logger; - -import java.io.IOException; - -import static io.vavr.API.Option; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class DMaaPEventPublisherTest { - - private static final String STREAM_ID = "sampleStreamId"; - - private DMaaPEventPublisher eventPublisher; - private CambriaBatchingPublisher cambriaPublisher; - private DMaaPPublishersCache DMaaPPublishersCache; - - @Before - public void setUp() { - cambriaPublisher = mock(CambriaBatchingPublisher.class); - DMaaPPublishersCache = mock(DMaaPPublishersCache.class); - when(DMaaPPublishersCache.getPublisher(anyString())).thenReturn(Option(cambriaPublisher)); - eventPublisher = new DMaaPEventPublisher(DMaaPPublishersCache, mock(Logger.class)); - } - - @Test - public void shouldSendEventToTopic() throws Exception { - // given - JSONObject event = new JSONObject("{}"); - - // when - eventPublisher.sendEvent(event, STREAM_ID); - - // then - verify(cambriaPublisher).send("MyPartitionKey", event.toString()); - } - - @Test - public void shouldCloseConnectionWhenExceptionOccurred() throws Exception { - // given - JSONObject event = new JSONObject("{}"); - given(cambriaPublisher.send(anyString(), anyString())).willThrow(new IOException("epic fail")); - - // when - eventPublisher.sendEvent(event, STREAM_ID); - - // then - verify(DMaaPPublishersCache).closePublisherFor(STREAM_ID); - } -} diff --git a/src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPPublishersCacheTest.java b/src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPPublishersCacheTest.java deleted file mode 100755 index 6ebf273..0000000 --- a/src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/DMaaPPublishersCacheTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common.event.publishing; - -import com.att.nsa.cambria.client.CambriaBatchingPublisher; -import io.vavr.collection.Map; -import io.vavr.control.Option; -import org.junit.Before; -import org.junit.Test; -import org.onap.dcae.collectors.restconf.common.event.publishing.DMaaPPublishersCache.OnPublisherRemovalListener; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -import static io.vavr.API.List; -import static io.vavr.API.Map; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class DMaaPPublishersCacheTest { - - private String streamId1; - private Map dMaaPConfigs; - - @Before - public void setUp() { - streamId1 = "sampleStream1"; - dMaaPConfigs = Map("sampleStream1", new PublisherConfig(List("destination1"), "topic1")); - } - - @Test - public void shouldReturnTheSameCachedInstanceOnConsecutiveRetrievals() { - // given - DMaaPPublishersCache dMaaPPublishersCache = new DMaaPPublishersCache(dMaaPConfigs); - - // when - Option firstPublisher = dMaaPPublishersCache.getPublisher(streamId1); - Option secondPublisher = dMaaPPublishersCache.getPublisher(streamId1); - - // then - assertSame("should return same instance", firstPublisher.get(), secondPublisher.get()); - } - - @Test - public void shouldCloseCambriaPublisherOnCacheInvalidate() throws IOException, InterruptedException { - // given - CambriaBatchingPublisher cambriaPublisherMock1 = mock(CambriaBatchingPublisher.class); - DMaaPPublishersCache.CambriaPublishersCacheLoader cacheLoaderMock = mock(DMaaPPublishersCache.CambriaPublishersCacheLoader.class); - DMaaPPublishersCache dMaaPPublishersCache = new DMaaPPublishersCache(cacheLoaderMock, - new OnPublisherRemovalListener(), - dMaaPConfigs); - when(cacheLoaderMock.load(streamId1)).thenReturn(cambriaPublisherMock1); - - // when - dMaaPPublishersCache.getPublisher(streamId1); - dMaaPPublishersCache.closePublisherFor(streamId1); - - // then - verify(cambriaPublisherMock1).close(20, TimeUnit.SECONDS); - - } - - @Test - public void shouldReturnNoneIfThereIsNoDMaaPConfigurationForGivenStreamID() { - // given - DMaaPPublishersCache dMaaPPublishersCache = new DMaaPPublishersCache(dMaaPConfigs); - - // then - assertTrue("should not exist", dMaaPPublishersCache.getPublisher("non-existing").isEmpty()); - } - -} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/JsonParserTest.java b/src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/JsonParserTest.java deleted file mode 100644 index a5609f9..0000000 --- a/src/test/java/org/onap/dcae/collectors/restconf/common/event/publishing/JsonParserTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2019 IBM. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.common.event.publishing; - -import java.util.Map; - -import org.junit.Test; -import org.onap.dcae.collectors.restconf.common.JsonParser; - -import junit.framework.Assert; - -public class JsonParserTest { - - @Test - public void convertToPropertiesTest() throws Exception { - String testJson="{\"prop2\"=\"value\", \"prop1\"=\"value\"}"; - Map response=JsonParser.convertToProperties(testJson); - Assert.assertEquals("value", response.get("prop2")); - } -} diff --git a/src/test/java/org/onap/dcae/collectors/restconf/restconftest/AnyNodeTest.java b/src/test/java/org/onap/dcae/collectors/restconf/restconftest/AnyNodeTest.java deleted file mode 100755 index 301f148..0000000 --- a/src/test/java/org/onap/dcae/collectors/restconf/restconftest/AnyNodeTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.restconftest; - -import com.google.common.collect.Sets; -import org.junit.BeforeClass; -import org.junit.Test; -import org.onap.dcae.collectors.restconf.common.AnyNode; - -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; - -public class AnyNodeTest { - - private static final String SAMPLE_JSON_FILEPATH = "{\n" - + " \"channels\": [{\n" - + " \"one\": \"number1\", \"two\": \"number2\", \"three\": \"number3\"}],\n" - + " \"sampleStrList\": [\"1\", \"2\", \"3\", \"4\", \"5\"],\n" - + " \"sampleNestedObject\": {\"a\": 1, \"b\": 2},\n" - + " \"sampleInt\": 1,\n" - + " \"sampleString\": \"str\",\n" - + " \"sampleNull\": null\n" - + "}\n"; - private static final Set EXPECTED_JSON_KEYS = Sets - .newHashSet("channels", "sampleStrList", "sampleNestedObject", "sampleInt", "sampleString", "sampleNull"); - private static AnyNode node; - - - @BeforeClass - public static void setUpClass() { - node = AnyNode.fromString(SAMPLE_JSON_FILEPATH); - } - - @Test - public void testShouldReturnJsonObjectKeySet() { - assertThat(node.keys()).containsOnlyElementsOf(EXPECTED_JSON_KEYS); - } - - @Test(expected = ClassCastException.class) - public void whenInvokedOnJsonObjInsteadOfJsonArrShouldRaiseRuntimeEx() { - node.toList(); - } -} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/collectors/restconf/restconftest/RestConfProcTest.java b/src/test/java/org/onap/dcae/collectors/restconf/restconftest/RestConfProcTest.java deleted file mode 100755 index 3c55618..0000000 --- a/src/test/java/org/onap/dcae/collectors/restconf/restconftest/RestConfProcTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.restconftest; - -import com.att.nsa.cmdLine.NsaCommandLineUtil; -import com.att.nsa.drumlin.service.framework.DrumlinServlet; -import com.att.nsa.drumlin.till.nv.impl.nvPropertiesFile; -import com.att.nsa.drumlin.till.nv.impl.nvReadableStack; -import com.att.nsa.drumlin.till.nv.impl.nvReadableTable; -import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; -import org.glassfish.jersey.media.sse.SseFeature; -import org.glassfish.jersey.server.ResourceConfig; -import org.junit.Test; -import org.onap.dcae.collectors.restconf.common.Constants; -import org.onap.dcae.collectors.restconf.common.RestConfCollector; -import org.onap.dcae.collectors.restconf.common.RestConfContext; -import org.onap.dcae.collectors.restconf.common.RestConfProc; - -import java.net.URI; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; - -public class RestConfProcTest { - - private static final URI CONTEXT = URI.create("http://localhost:8080/"); - - @Test - public void testEstablishPersistentConnection() throws Exception { - - final Map argMap = new HashMap<>(); - final String config = NsaCommandLineUtil.getSetting(argMap, Constants.KCONFIG, "collector.properties"); - final URL settingStream = DrumlinServlet.findStream(config, RestConfCollector.class); - - final nvReadableStack settings = new nvReadableStack(); - - settings.push(new nvPropertiesFile(settingStream)); - settings.push(new nvReadableTable(argMap)); - - RestConfProc restConfProc = new RestConfProc(settings); - - final ResourceConfig resourceConfig = new ResourceConfig(SseResource.class, SseFeature.class); - GrizzlyHttpServerFactory.createHttpServer(CONTEXT, resourceConfig); - RestConfContext ctx = new RestConfContext(); - ctx.setAttribute("prop.encoding-json", "encoding-json"); - ctx.setAttribute("restapi-result.response-code", "200"); - ctx.setAttribute("restapi-result.ietf-subscribed-notifications:output.identifier", "100"); - - Map p = new HashMap<>(); - p.put("sseConnectURL", "http://localhost:8080/ssevents"); - p.put("subscriberId", "networkId"); - p.put("responsePrefix", "restapi-result"); - p.put("restapiUrl", "https://localhost:8080/restconf/operations/" + - "ietf-subscribed-notifications:establish-subscription"); - p.put("restapiUser", "access"); - p.put("restapiPassword", "abc@123"); - - restConfProc.establishPersistentConnection(p, ctx); - Thread.sleep(1000); - } -} diff --git a/src/test/java/org/onap/dcae/collectors/restconf/restconftest/SseResource.java b/src/test/java/org/onap/dcae/collectors/restconf/restconftest/SseResource.java deleted file mode 100755 index 558cba8..0000000 --- a/src/test/java/org/onap/dcae/collectors/restconf/restconftest/SseResource.java +++ /dev/null @@ -1,69 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.restconftest; - -import org.glassfish.jersey.media.sse.EventOutput; -import org.glassfish.jersey.media.sse.OutboundEvent; -import org.glassfish.jersey.media.sse.SseFeature; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import java.io.IOException; - -@Path("ssevents") -public class SseResource { - - @GET - @Produces(SseFeature.SERVER_SENT_EVENTS) - public EventOutput getServerSentEvents() throws IOException { - String data = "{" - + "\"ietf-notification:notification\" : {" - + " \"eventTime\" : \"2017-10-25T08:22:33.44Z\"," - + " \"ietf-yang-push:push-change-update\": {" - + "\"subscription-id\":\"89\"," - + "\"datastore-changes\": {" - + "\"ietf-yang-patch:yang-patch\":{" - + "\"patch-id\":\"1\"," - + "\"edit\":[{" - + "\"edit-id\":\"edit1\"," - + "\"operation\":\"merge\"," - + "\"target\":\"/ietf-interfaces:interfaces-state\"," - + "\"value\": {" - + "\"ietf-interfaces:interfaces-state\":{" - + "\"interface\": {" - + "\"name\":\"eth0\"," - + "\"oper-status\":\"down\"," - + "}" - + "}" - + "}" - + "}]" - + "}" - + "}" - + "}" - + "}" - + "}"; - final EventOutput result = new EventOutput(); - result.write(new OutboundEvent.Builder().data(String.class, data).build()); - result.close(); - return result; - } -} diff --git a/src/test/java/org/onap/dcae/collectors/restconf/restconftest/TestRestConfCollector.java b/src/test/java/org/onap/dcae/collectors/restconf/restconftest/TestRestConfCollector.java deleted file mode 100755 index 59e6e72..0000000 --- a/src/test/java/org/onap/dcae/collectors/restconf/restconftest/TestRestConfCollector.java +++ /dev/null @@ -1,66 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * org.onap.dcaegen2.collectors.restconf - * ================================================================================ - * Copyright (C) 2018 Huawei. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.collectors.restconf.restconftest; - -import com.att.nsa.cmdLine.NsaCommandLineUtil; -import com.att.nsa.drumlin.till.nv.impl.nvReadableStack; -import com.att.nsa.drumlin.till.nv.impl.nvReadableTable; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import org.json.JSONArray; -import org.json.JSONObject; -import org.junit.Test; -import org.onap.dcae.collectors.restconf.common.Constants; -import org.onap.dcae.collectors.restconf.common.RestConfProc; - -import java.io.FileReader; -import java.util.Map; -import java.util.concurrent.LinkedBlockingQueue; - -import static org.junit.Assert.assertEquals; - -public class TestRestConfCollector { - @Test - public void testParseCLIArguments() { - // given - String args[] = {"-a", "aa"}; - Map argMap = NsaCommandLineUtil.processCmdLine(args, true); - // when - nvReadableStack settings = new nvReadableStack(); - settings.push(new nvReadableTable(argMap)); - - // then - assertEquals(settings.getString("a", "default"), "aa"); - } - - @Test - public void shouldPutValidRestConfEventOnProcessingQueueWithoutExceptions() throws Exception { - // given - RestConfProc.fProcessingInputQueue = new LinkedBlockingQueue<>( - Constants.KDEFAULT_MAXQUEUEDEVENTS); - JsonElement restConfEvent = new JsonParser().parse(new FileReader("src/test/resources/RestConfEvent.json")); - JSONObject validRestConfEvent = new JSONObject(restConfEvent.toString()); - JSONArray jsonArrayMod = new JSONArray().put(validRestConfEvent); - - // then - RestConfProc.handleEvents(jsonArrayMod); - } -} diff --git a/src/test/java/org/onap/dcae/common/ApiExceptionTest.java b/src/test/java/org/onap/dcae/common/ApiExceptionTest.java new file mode 100644 index 0000000..58cf9e4 --- /dev/null +++ b/src/test/java/org/onap/dcae/common/ApiExceptionTest.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import static org.junit.Assert.assertEquals; + +import org.json.JSONObject; +import org.junit.Test; +import org.onap.dcae.restapi.ApiException; +import org.onap.dcae.restapi.ApiException.ExceptionType; + +public class ApiExceptionTest { + + + @Test + public void shouldStringifyPolicyExceptionTypeAccordingToSpecification() { + assertEquals(ExceptionType.POLICY_EXCEPTION.toString(), "PolicyException"); + } + + @Test + public void shouldConvertExceptionToBackwardCompatibleFormat() { + JSONObject responseBody = ApiException.UNAUTHORIZED_USER.toJSON(); + assertEquals(responseBody.toString(), new JSONObject("" + + "{ " + + " 'requestError': { " + + " 'PolicyException': { " + + " 'messageId': 'POL2000', " + + " 'text': 'Unauthorized user' " + + " } " + + " } " + + "} " + .replace("'", "\"") + ).toString()); + } +} diff --git a/src/test/java/org/onap/dcae/common/AuthTypeTest.java b/src/test/java/org/onap/dcae/common/AuthTypeTest.java new file mode 100644 index 0000000..a8a8729 --- /dev/null +++ b/src/test/java/org/onap/dcae/common/AuthTypeTest.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common; + +import org.junit.Test; +import org.onap.dcae.common.AuthType; + +import static org.junit.Assert.*; + +public class AuthTypeTest { + + @Test + public void fromString() { + assertEquals(AuthType.BASIC, AuthType.fromString("basic")); + assertEquals(AuthType.DIGEST, AuthType.fromString("digest")); + assertEquals(AuthType.OAUTH, AuthType.fromString("oauth")); + assertEquals(AuthType.NONE, AuthType.fromString("none")); + assertEquals(AuthType.Unspecified, AuthType.fromString("unspecified")); + } + + @Test(expected = IllegalArgumentException.class) + public void fromStringWithException() { + AuthType.fromString("test"); + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/common/DataChangeEventListnerTest.java b/src/test/java/org/onap/dcae/common/DataChangeEventListnerTest.java new file mode 100644 index 0000000..95c8012 --- /dev/null +++ b/src/test/java/org/onap/dcae/common/DataChangeEventListnerTest.java @@ -0,0 +1,69 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common; + + +import org.glassfish.jersey.media.sse.EventInput; +import org.glassfish.jersey.media.sse.InboundEvent; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import static org.mockito.Mockito.*; + +import org.onap.dcae.RestConfCollector; +import org.onap.dcae.common.publishing.DMaaPConfigurationParser; +import org.onap.dcae.common.publishing.EventPublisher; + + +import org.slf4j.LoggerFactory; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.LinkedBlockingQueue; + +@RunWith(MockitoJUnitRunner.class) +public class DataChangeEventListnerTest { + @Mock + InboundEvent event; + + @Test + public void testDataChangeEventListenerString() { + when(event.readData()).thenReturn(""); + DataChangeEventListener listner = new DataChangeEventListener(null); + listner.onEvent(event); + } + + @Test + public void testDataChangeEventListenerJsonObject() { + when(event.readData()).thenReturn("{\"name\":\"john\",\"age\":22,\"class\":\"mca\"}"); + RestConfCollector.fProcessingInputQueue = new LinkedBlockingQueue<>(4); + DataChangeEventListener listner = new DataChangeEventListener(null); + listner.onEvent(event); + } + @Test + public void testDataChangeEventListenerJsonArray() { + when(event.readData()).thenReturn("[{ \"name\":\"Ford\", \"models\":[ \"Fiesta\",\"Focus\", \"Mustang\" ] },{\"name\":\"BMW\", \"models\":[ \"320\", \"X3\",\"X5\" ] },{\"name\":\"Fiat\",\"models\":[ \"500\", \"Panda\" ]}]"); + RestConfCollector.fProcessingInputQueue = new LinkedBlockingQueue<>(4); + DataChangeEventListener listner = new DataChangeEventListener(null); + listner.onEvent(event); + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/common/EventConnectionStateTest.java b/src/test/java/org/onap/dcae/common/EventConnectionStateTest.java new file mode 100644 index 0000000..c6327bc --- /dev/null +++ b/src/test/java/org/onap/dcae/common/EventConnectionStateTest.java @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class EventConnectionStateTest { + + @Test + public void fromString() { + assertEquals(EventConnectionState.INIT, EventConnectionState.fromString("init")); + assertEquals(EventConnectionState.SUBSCRIBED, EventConnectionState.fromString("subscribed")); + assertEquals(EventConnectionState.UNSUBSCRIBED, EventConnectionState.fromString("unsubscribed")); + assertEquals(EventConnectionState.Unspecified, EventConnectionState.fromString("unspecified")); + } + + @Test(expected = IllegalArgumentException.class) + public void fromStringWithException() { + EventConnectionState.fromString("test"); + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/common/EventProcessorTest.java b/src/test/java/org/onap/dcae/common/EventProcessorTest.java new file mode 100644 index 0000000..f32cc2e --- /dev/null +++ b/src/test/java/org/onap/dcae/common/EventProcessorTest.java @@ -0,0 +1,104 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common; + + + +import org.json.JSONObject; +import org.junit.Before; + + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.onap.dcae.ApplicationSettings; +import org.onap.dcae.RestConfCollector; +import org.onap.dcae.common.publishing.DMaaPConfigurationParser; +import org.onap.dcae.common.publishing.EventPublisher; +import org.onap.dcae.common.publishing.PublisherConfig; +import org.onap.dcae.controller.AccessController; +import org.onap.dcae.controller.PersistentEventConnection; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.mock.mockito.MockBean; + + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.LinkedBlockingQueue; + + + +import static io.vavr.API.Map; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.when; +import static org.onap.dcae.common.publishing.DMaaPConfigurationParser.parseToDomainMapping; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class EventProcessorTest { + + + + @Mock + private ApplicationSettings properties; + + private EventPublisher eventPublisher; + + Path path = Paths.get("src/test/resources/testParseDMaaPCredentialsLegacy.json"); + java.util.Map streamMap; + protected static final Path RESOURCES = Paths.get("src", "test", "resources"); + protected static final Path KEYSTORE = Paths.get(RESOURCES.toString(), "keystore"); + protected static final Path KEYSTORE_PASSWORD_FILE = Paths.get(RESOURCES.toString(), "passwordfile"); + protected static final Path TRUSTSTORE = Paths.get(RESOURCES.toString(), "truststore"); + protected static final Path TRUSTSTORE_PASSWORD_FILE = Paths.get(RESOURCES.toString(), "trustpasswordfile"); + protected static final Path RCC_KEYSTORE_PASSWORD_FILE = Paths.get(RESOURCES.toString(), "rcc_passwordfile"); + protected static final Path RCC_KEYSTORE = Paths.get(RESOURCES.toString(), "sdnc.p12"); + + @Before + public void setUp() { + eventPublisher = EventPublisher.createPublisher(LoggerFactory.getLogger("some_log"), DMaaPConfigurationParser. + parseToDomainMapping(path).get()); + streamMap = RestConfCollector.parseStreamIdToStreamHashMapping("notification=device-registration"); + + } + + @Test + public void testEventProcessorRunException() { + when(properties.truststoreFileLocation()).thenReturn(TRUSTSTORE.toString()); + when(properties.truststorePasswordFileLocation()).thenReturn(TRUSTSTORE_PASSWORD_FILE.toString()); + when(properties.keystoreFileLocation()).thenReturn(KEYSTORE.toString()); + when(properties.keystorePasswordFileLocation()).thenReturn(KEYSTORE_PASSWORD_FILE.toString()); + when(properties.rcc_keystoreFileLocation()).thenReturn(RCC_KEYSTORE.toString()); + when(properties.rcc_keystorePasswordFileLocation()).thenReturn(RCC_KEYSTORE_PASSWORD_FILE.toString()); + JSONObject controller = new JSONObject("{\"controller_name\":\"AccessM&C\",\"controller_restapiUrl\":\"10.118.191.43:26335\",\"controller_restapiUser\":\"access\",\"controller_restapiPassword\":\"Huawei@123\",\"controller_accessTokenUrl\":\"/rest/plat/smapp/v1/oauth/token\",\"controller_accessTokenFile\":\"./etc/access-token.json\",\"controller_accessTokenMethod\":\"put\",\"controller_subsMethod\":\"post\",\"controller_subscriptionUrl\":\"/restconf/v1/operations/huawei-nce-notification-action:establish-subscription\",\"event_details\":[{\"event_name\":\"ONT_registration\",\"event_description\":\"ONTregistartionevent\",\"event_sseventUrlEmbed\":\"true\",\"event_sseventsField\":\"output.url\",\"event_sseventsUrl\":\"null\",\"event_subscriptionTemplate\":\"./etc/ont_registartion_subscription_template.json\",\"event_unSubscriptionTemplate\":\"./etc/ont_registartion_unsubscription_template.json\",\"event_ruleId\":\"777777777\"}]}"); + AccessController acClr = new AccessController(controller, + properties); + + PersistentEventConnection p = new PersistentEventConnection("","",true, "", + "","","","1234646346", acClr); + RestConfCollector.fProcessingInputQueue = new LinkedBlockingQueue<>(4); + RestConfCollector.fProcessingInputQueue.offer(new EventData(p, new JSONObject("{}"))); + RestConfCollector.fProcessingInputQueue.offer(new EventData(null, null)); + EventProcessor ev = new EventProcessor(eventPublisher, streamMap); + ev.run(); + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/common/FormatTest.java b/src/test/java/org/onap/dcae/common/FormatTest.java new file mode 100644 index 0000000..e54dd9b --- /dev/null +++ b/src/test/java/org/onap/dcae/common/FormatTest.java @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common; + +import org.junit.Test; +import org.onap.dcae.common.Format; + +import static org.junit.Assert.assertEquals; + +public class FormatTest { + + @Test + public void fromString() { + assertEquals(Format.JSON, Format.fromString("json")); + assertEquals(Format.XML, Format.fromString("xml")); + assertEquals(Format.NONE, Format.fromString("none")); + } + + @Test(expected = IllegalArgumentException.class) + public void fromStringWithException() { + Format.fromString("test"); + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/common/RestConfContextTest.java b/src/test/java/org/onap/dcae/common/RestConfContextTest.java new file mode 100644 index 0000000..00b07f8 --- /dev/null +++ b/src/test/java/org/onap/dcae/common/RestConfContextTest.java @@ -0,0 +1,52 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import org.junit.Test; +import org.onap.dcae.common.RestConfContext; + +import static org.junit.Assert.*; + +public class RestConfContextTest { + + @Test + public void setAttribute() { + String key = "key"; + String value = "value"; + RestConfContext restConfContext = new RestConfContext(); + restConfContext.setAttribute(key, value); + assertEquals(value, restConfContext.getAttribute(key)); + restConfContext.setAttribute(key, null); + assertFalse(restConfContext.getAttributeKeySet().contains(key)); + } + + @Test + public void getAttributeKeySet() { + String key = "key"; + String value = "value"; + String key1 = "key1"; + String value1 = "value1"; + RestConfContext restConfContext = new RestConfContext(); + restConfContext.setAttribute(key,value); + restConfContext.setAttribute(key1,value1); + assertTrue(restConfContext.getAttributeKeySet().contains(key) && restConfContext.getAttributeKeySet().contains(key1)); + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/common/XmlJsonUtilTest.java b/src/test/java/org/onap/dcae/common/XmlJsonUtilTest.java new file mode 100644 index 0000000..3cf065e --- /dev/null +++ b/src/test/java/org/onap/dcae/common/XmlJsonUtilTest.java @@ -0,0 +1,81 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import org.json.XML; +import org.junit.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertEquals; + +public class XmlJsonUtilTest { + + @Test + public void getJsonOrXmlTest() { + String var = "result"; + Map mm = new HashMap<>(); + + + mm.put("result.time", "2018 12:04"); + mm.put("result.status", "200"); + mm.put("result.output", "xml2json"); + mm.put("result.[", "start"); + mm.put("result.]", "end"); + try { + String str = XmlJsonUtil.getXml(mm, var); + assertEquals(str.startsWith("<"), true); + String str2 = XmlJsonUtil.getJson(mm, var); + assertEquals(str2.startsWith("{"), true); + }catch (Exception e) {} + } + + @Test + public void removeEmptystructFromXml() { + String var = "\n" + + "t2\n" + + "bad\n" + + "200"; + Map mm = new HashMap<>(); + try { + String str = XmlJsonUtil.removeEmptyStructXml(var); + + }catch (Exception e) {} + } + + @Test + public void removeEmptystructFromJson() { + String var = "{\n" + + "\t\"output\": \"xml2json\",\n" + + "\t\"time\": \"2018 12:04\",\n" + + "\t\"\": \"end\",\n" + + "\t\"status\": \"200\"\n" + + "}"; + Map mm = new HashMap<>(); + + try { + String str = XmlJsonUtil.removeEmptyStructJson(var); + }catch (Exception e) {} + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/common/XmlParserTest.java b/src/test/java/org/onap/dcae/common/XmlParserTest.java new file mode 100644 index 0000000..b005c89 --- /dev/null +++ b/src/test/java/org/onap/dcae/common/XmlParserTest.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.common; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.*; + +public class XmlParserTest { + + @Test + public void setAttribute() { + String convert = "\n" + + "t2\n" + + "200"; + Set listNameList = new HashSet<>(); + listNameList.add("result"); + Map propMap; + try { + propMap = XmlParser.convertToProperties(convert, listNameList); + System.out.println(propMap); + }catch (Exception e) {} + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/common/publishing/DMaaPEventPublisherTest.java b/src/test/java/org/onap/dcae/common/publishing/DMaaPEventPublisherTest.java new file mode 100644 index 0000000..2865b75 --- /dev/null +++ b/src/test/java/org/onap/dcae/common/publishing/DMaaPEventPublisherTest.java @@ -0,0 +1,79 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common.publishing; + +import static io.vavr.API.Option; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.att.nsa.cambria.client.CambriaBatchingPublisher; +import java.io.IOException; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; + +public class DMaaPEventPublisherTest { + + private static final String STREAM_ID = "sampleStreamId"; + + private DMaaPEventPublisher eventPublisher; + private CambriaBatchingPublisher cambriaPublisher; + private DMaaPPublishersCache DMaaPPublishersCache; + + @Before + public void setUp() { + cambriaPublisher = mock(CambriaBatchingPublisher.class); + DMaaPPublishersCache = mock(DMaaPPublishersCache.class); + when(DMaaPPublishersCache.getPublisher(anyString())).thenReturn(Option(cambriaPublisher)); + eventPublisher = new DMaaPEventPublisher(DMaaPPublishersCache, mock(Logger.class)); + } + + @Test + public void shouldSendEventToTopic() throws Exception { + // given + JSONObject event = new JSONObject("{}"); + + // when + eventPublisher.sendEvent(event, STREAM_ID); + + // then + verify(cambriaPublisher).send("MyPartitionKey", event.toString()); + } + + + + @Test + public void shouldCloseConnectionWhenExceptionOccurred() throws Exception { + // given + JSONObject event = new JSONObject("{}"); + given(cambriaPublisher.send(anyString(), anyString())).willThrow(new IOException("epic fail")); + + // when + eventPublisher.sendEvent(event, STREAM_ID); + + // then + verify(DMaaPPublishersCache).closePublisherFor(STREAM_ID); + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/common/publishing/DMaaPPublishersCacheTest.java b/src/test/java/org/onap/dcae/common/publishing/DMaaPPublishersCacheTest.java new file mode 100644 index 0000000..2884e44 --- /dev/null +++ b/src/test/java/org/onap/dcae/common/publishing/DMaaPPublishersCacheTest.java @@ -0,0 +1,127 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common.publishing; + +import static io.vavr.API.List; +import static io.vavr.API.Map; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +import com.att.nsa.cambria.client.CambriaBatchingPublisher; +import io.vavr.collection.Map; +import io.vavr.control.Option; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import org.junit.Before; +import org.junit.Test; +import org.onap.dcae.common.publishing.DMaaPPublishersCache.CambriaPublishersCacheLoader; +import org.onap.dcae.common.publishing.DMaaPPublishersCache.OnPublisherRemovalListener; + + +public class DMaaPPublishersCacheTest { + + private String streamId1; + private Map dMaaPConfigs; + + @Before + public void setUp() { + streamId1 = "sampleStream1"; + dMaaPConfigs = Map("sampleStream1", new PublisherConfig(List("destination1"), "topic1")); + } + + @Test + public void shouldReturnTheSameCachedInstanceOnConsecutiveRetrievals() { + // given + DMaaPPublishersCache dMaaPPublishersCache = new DMaaPPublishersCache(dMaaPConfigs); + + // when + Option firstPublisher = dMaaPPublishersCache.getPublisher(streamId1); + Option secondPublisher = dMaaPPublishersCache.getPublisher(streamId1); + + // then + assertSame("should return same instance", firstPublisher.get(), secondPublisher.get()); + } + + @Test + public void shouldCloseCambriaPublisherOnCacheInvalidate() throws IOException, InterruptedException { + // given + CambriaBatchingPublisher cambriaPublisherMock1 = mock(CambriaBatchingPublisher.class); + CambriaPublishersCacheLoader cacheLoaderMock = mock(CambriaPublishersCacheLoader.class); + DMaaPPublishersCache dMaaPPublishersCache = new DMaaPPublishersCache(cacheLoaderMock, + new OnPublisherRemovalListener(), + dMaaPConfigs); + when(cacheLoaderMock.load(streamId1)).thenReturn(cambriaPublisherMock1); + + // when + dMaaPPublishersCache.getPublisher(streamId1); + dMaaPPublishersCache.closePublisherFor(streamId1); + + // then + verify(cambriaPublisherMock1).close(20, TimeUnit.SECONDS); + + } + + @Test + public void shouldReturnNoneIfThereIsNoDMaaPConfigurationForGivenStreamID() { + // given + DMaaPPublishersCache dMaaPPublishersCache = new DMaaPPublishersCache(dMaaPConfigs); + + // then + assertTrue("should not exist", dMaaPPublishersCache.getPublisher("non-existing").isEmpty()); + } + + + @Test + public void shouldCloseOnlyChangedPublishers() throws IOException, InterruptedException { + // given + CambriaBatchingPublisher cambriaPublisherMock1 = mock(CambriaBatchingPublisher.class); + CambriaBatchingPublisher cambriaPublisherMock2 = mock(CambriaBatchingPublisher.class); + CambriaPublishersCacheLoader cacheLoaderMock = mock(CambriaPublishersCacheLoader.class); + String firstDomain = "domain1"; + String secondDomain = "domain2"; + Map oldConfig = Map(firstDomain, + new PublisherConfig(List("destination1"), "topic1"), + secondDomain, + new PublisherConfig(List("destination2"), "topic2", + "user", "pass")); + Map newConfig = Map(firstDomain, new PublisherConfig(List("destination1"), "topic1"), + secondDomain, new PublisherConfig(List("destination2"), "topic2")); + DMaaPPublishersCache dMaaPPublishersCache = new DMaaPPublishersCache(cacheLoaderMock, + new OnPublisherRemovalListener(), + oldConfig); + when(cacheLoaderMock.load(firstDomain)).thenReturn(cambriaPublisherMock1); + when(cacheLoaderMock.load(secondDomain)).thenReturn(cambriaPublisherMock2); + + dMaaPPublishersCache.getPublisher(firstDomain); + dMaaPPublishersCache.getPublisher(secondDomain); + + // when + dMaaPPublishersCache.reconfigure(newConfig); + + // then + verify(cambriaPublisherMock2).close(20, TimeUnit.SECONDS); + verifyZeroInteractions(cambriaPublisherMock1); + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/common/publishing/JsonParserTest.java b/src/test/java/org/onap/dcae/common/publishing/JsonParserTest.java new file mode 100644 index 0000000..f00df2c --- /dev/null +++ b/src/test/java/org/onap/dcae/common/publishing/JsonParserTest.java @@ -0,0 +1,38 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.common.publishing; + +import java.util.Map; + +import org.junit.Test; +import org.onap.dcae.common.JsonParser; + +import junit.framework.Assert; + + +public class JsonParserTest { + + @Test + public void convertToPropertiesTest() throws Exception { + String testJson="{\"prop2\"=\"value\", \"prop1\"=\"value\"}"; + Map response= JsonParser.convertToProperties(testJson); + Assert.assertEquals("value", response.get("prop2")); + } +} diff --git a/src/test/java/org/onap/dcae/controller/ConfigCBSSourceTest.java b/src/test/java/org/onap/dcae/controller/ConfigCBSSourceTest.java new file mode 100644 index 0000000..5c8593e --- /dev/null +++ b/src/test/java/org/onap/dcae/controller/ConfigCBSSourceTest.java @@ -0,0 +1,151 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.controller; + +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.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static org.assertj.core.api.Java6Assertions.assertThat; +import static org.onap.dcae.TestingUtilities.assertFailureHasInfo; +import static org.onap.dcae.controller.ConfigSource.getAppConfig; + +import io.vavr.control.Try; +import org.json.JSONObject; +import org.junit.Test; +import org.onap.dcae.WiremockBasedTest; + + +public class ConfigCBSSourceTest extends WiremockBasedTest { + + @Test + public void shouldReturnValidAppConfiguration() { + // given + String sampleConfigForVES = "{\"collector.rcc.service.port\": 8686}"; + + stubConsulToReturnLocalAddressOfCBS(); + stubCBSToReturnAppConfig(sampleConfigForVES); + + // when + Try actual = tryToGetConfig(); + + // then + assertThat(actual.get().toString()).isEqualTo(new JSONObject(sampleConfigForVES).toString()); + } + + @Test + public void shouldReturnFailureOnFailureToCommunicateWithConsul() { + // given + stubFor(get(urlEqualTo("/v1/catalog/service/CBSName")) + .willReturn(aResponse().withStatus(400))); + + // when + Try actual = tryToGetConfig(); + + // then + assertFailureHasInfo(actual, "HTTP", "Consul", "400", + "http://localhost:" + wireMockRule.port() + "/v1/catalog/service/CBSName"); + } + + @Test + public void shouldReturnFailureOnBadJsonFromConsul() { + // given + stubFor(get(urlEqualTo("/v1/catalog/service/CBSName")) + .willReturn(aResponse().withStatus(200).withBody("[{"))); + + // when + Try actual = tryToGetConfig(); + + // then + assertFailureHasInfo(actual, "JSON", "array", "[{"); + } + + @Test + public void shouldReturnFailureOnInvalidCatalogFormat() { + // given + String notAListCatalog = "" + + "{" + + "\"ServiceAddress\":\"localhost\"," + + "\"ServicePort\":" + wireMockRule.port() + + "}"; + + stubFor(get(urlEqualTo("/v1/catalog/service/CBSName")) + .willReturn(aResponse().withStatus(200).withBody(notAListCatalog))); + + // when + Try actual = tryToGetConfig(); + + // then + assertFailureHasInfo(actual, "JSON", "array", notAListCatalog); + } + + + @Test + public void shouldReturnFailureIfConfigIsMissingRequiredProperties() { + // given + String actualConf = "{\"ServicePort\":" + wireMockRule.port() + "}"; + String asCatalog = "[" + actualConf + "]"; + + stubFor(get(urlEqualTo("/v1/catalog/service/CBSName")) + .willReturn(aResponse().withStatus(200).withBody(asCatalog))); + + // when + Try actual = tryToGetConfig(); + + // then + assertFailureHasInfo(actual, "ServiceAddress", "ServicePort", "missing", actualConf); + } + + + @Test + public void shouldReturnFailureOnFailureToCommunicateWithCBS() { + // given + stubFor(get(urlEqualTo("/v1/catalog/service/CBSName")) + .willReturn(aResponse().withStatus(200).withBody(validLocalCBSConf()))); + stubFor(get(urlEqualTo("/service_component/restconfcollector")) + .willReturn(aResponse().withStatus(400))); + + // when + Try actual = tryToGetConfig(); + + // then + assertFailureHasInfo(actual, "HTTP", "CBS", "400", + "http://localhost:" + wireMockRule.port() + "/service_component/restconfcollector"); + } + + @Test + public void shouldReturnFailureIfAppIsInvalidJsonDocument() { + // given + String invalidAppConf = "[$"; + stubConsulToReturnLocalAddressOfCBS(); + stubCBSToReturnAppConfig(invalidAppConf); + + // when + Try actual = tryToGetConfig(); + + // then + assertFailureHasInfo(actual, "JSON", "document", invalidAppConf); + } + + private Try tryToGetConfig() { + return getAppConfig(new EnvProps("http", "localhost", wireMockRule.port(), "http", "CBSName", "restconfcollector")); + } +} + diff --git a/src/test/java/org/onap/dcae/controller/ConfigFilesFacadeTest.java b/src/test/java/org/onap/dcae/controller/ConfigFilesFacadeTest.java new file mode 100644 index 0000000..4130ceb --- /dev/null +++ b/src/test/java/org/onap/dcae/controller/ConfigFilesFacadeTest.java @@ -0,0 +1,140 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.controller; + +import static io.vavr.API.Map; +import static io.vavr.API.Some; +import static org.assertj.core.api.Assertions.assertThat; +import static org.onap.dcae.TestingUtilities.assertFailureHasInfo; +import static org.onap.dcae.TestingUtilities.assertJSONObjectsEqual; +import static org.onap.dcae.TestingUtilities.createTemporaryFile; +import static org.onap.dcae.TestingUtilities.readFile; +import static org.onap.dcae.TestingUtilities.readJSONFromFile; + +import io.vavr.collection.Map; +import io.vavr.control.Try; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.json.JSONObject; +import org.junit.Test; + +public class ConfigFilesFacadeTest { + + private static final Path NON_EXISTENT = Paths.get("/non-existent"); + private static final ConfigFilesFacade TO_NON_EXISTENT_POINTING_FACADE = new ConfigFilesFacade(NON_EXISTENT, + NON_EXISTENT); + + @Test + public void shouldReadPropertyFile() { + // given + Path temporaryFile = createTemporaryFile("some.property=10"); + + // when + ConfigFilesFacade configFilesFacade = new ConfigFilesFacade(temporaryFile, temporaryFile); + + Try> propertiesConfigurations = configFilesFacade.readCollectorProperties(); + + // then + assertThat(propertiesConfigurations.isSuccess()).isTrue(); + assertThat(propertiesConfigurations.get().containsKey("some.property")).isTrue(); + assertThat(propertiesConfigurations.get().get("some.property")).isEqualTo(Some("10")); + } + + + @Test + public void shouldReadDMaaPFile() { + // given + Path temporaryFile = createTemporaryFile("{}"); + + // when + ConfigFilesFacade configFilesFacade = new ConfigFilesFacade(temporaryFile, temporaryFile); + + Try dMaaPConfiguration = configFilesFacade.readDMaaPConfiguration(); + + // then + assertThat(dMaaPConfiguration.isSuccess()).isTrue(); + assertThat(dMaaPConfiguration.get().toString()).isEqualTo("{}"); + } + + @Test + public void shouldWriteDMaaPConf() { + // given + Path temporaryFile = createTemporaryFile("{}"); + JSONObject desiredConf = new JSONObject("{\"key\": 1}"); + + // when + ConfigFilesFacade configFilesFacade = new ConfigFilesFacade(temporaryFile, temporaryFile); + + Try propertiesConfigurations = configFilesFacade.writeDMaaPConfiguration(desiredConf); + + // then + assertThat(propertiesConfigurations.isSuccess()).isTrue(); + assertJSONObjectsEqual(readJSONFromFile(temporaryFile), desiredConf); + } + + + @Test + public void shouldWriteProperties() { + // given + Path temporaryFile = createTemporaryFile("{}"); + + // when + ConfigFilesFacade configFilesFacade = new ConfigFilesFacade(temporaryFile, temporaryFile); + Try propertiesConfigurations = configFilesFacade.writeProperties(Map("prop1", "hi")); + + // then + assertThat(propertiesConfigurations.isSuccess()).isTrue(); + assertThat(readFile(temporaryFile).trim()).isEqualTo("prop1 = hi"); + } + + @Test + public void shouldContainPropertiesPathInCaseOfFailures() { + Try> result = TO_NON_EXISTENT_POINTING_FACADE.readCollectorProperties(); + assertThat(result.isFailure()).isTrue(); + assertFailureHasInfo(result, NON_EXISTENT.toString()); + } + + @Test + public void shouldContainDMaaPPathPathInCaseOfFailures() { + Try result = TO_NON_EXISTENT_POINTING_FACADE.readDMaaPConfiguration(); + assertThat(result.isFailure()).isTrue(); + assertFailureHasInfo(result, NON_EXISTENT.toString()); + } + + @Test + public void shouldContainPropertiesPathPathInCaseOfFailuresOnWrite() { + // given + Try result = TO_NON_EXISTENT_POINTING_FACADE.writeProperties(Map("any", "any")); + assertThat(result.isFailure()).isTrue(); + assertFailureHasInfo(result, NON_EXISTENT.toString()); + } + + @Test + public void shouldContainDMaaPPathPathInCaseOfFailuresOnWrite() { + // given + Try result = TO_NON_EXISTENT_POINTING_FACADE.writeDMaaPConfiguration(new JSONObject()); + assertThat(result.isFailure()).isTrue(); + assertFailureHasInfo(result, NON_EXISTENT.toString()); + } + +} + diff --git a/src/test/java/org/onap/dcae/controller/ConfigLoaderIntegrationE2ETest.java b/src/test/java/org/onap/dcae/controller/ConfigLoaderIntegrationE2ETest.java new file mode 100644 index 0000000..730a98d --- /dev/null +++ b/src/test/java/org/onap/dcae/controller/ConfigLoaderIntegrationE2ETest.java @@ -0,0 +1,98 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.controller; + +import static io.vavr.API.Map; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import static org.onap.dcae.TestingUtilities.createTemporaryFile; +import static org.onap.dcae.TestingUtilities.readFile; +import static org.onap.dcae.TestingUtilities.readJSONFromFile; +import static org.onap.dcae.common.publishing.VavrUtils.f; + +import java.nio.file.Path; +import java.nio.file.Paths; +import org.json.JSONObject; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.onap.dcae.ApplicationSettings; +import org.onap.dcae.RestConfCollector; +import org.onap.dcae.WiremockBasedTest; +import org.onap.dcae.common.publishing.DMaaPConfigurationParser; +import org.onap.dcae.common.publishing.EventPublisher; + +public class ConfigLoaderIntegrationE2ETest extends WiremockBasedTest { + + @Test + public void testSuccessfulE2EFlow() { + // given +// Path dMaaPConfigFile = createTemporaryFile("{}"); +// Path collectorPropertiesFile = createTemporaryFile(""); +// Path dMaaPConfigSource = Paths.get("src/test/resources/testParseDMaaPCredentialsGen2.json"); +// JSONObject dMaaPConf = readJSONFromFile(dMaaPConfigSource); +// stubConsulToReturnLocalAddressOfCBS(); +// stubCBSToReturnAppConfig(f("{\"collector.port\": 8686, \"streams_publishes\": %s}}", dMaaPConf)); +// +// EventPublisher eventPublisherMock = mock(EventPublisher.class); +// +// Mockito.mock(RestConfCollector.class); +// ConfigFilesFacade configFilesFacade = new ConfigFilesFacade(dMaaPConfigFile, collectorPropertiesFile); +// ConfigLoader configLoader = new ConfigLoader(eventPublisherMock::reconfigure, configFilesFacade, ConfigSource::getAppConfig, () -> wiremockBasedEnvProps()); +// configLoader.updateConfig(); +// +// // then +// assertThat(readJSONFromFile(dMaaPConfigSource).toString()).isEqualTo(dMaaPConf.toString()); +// assertThat(readFile(collectorPropertiesFile).trim()).isEqualTo("collector.port = 8686"); +// verify(eventPublisherMock, times(1)).reconfigure( +// DMaaPConfigurationParser.parseToDomainMapping(dMaaPConf).get() +// ); + } + + @Test + public void shouldNotReconfigureNotOverwriteIfConfigurationHasNotChanged() { + // given + Path dMaaPConfigFile = createTemporaryFile("{}"); + Path collectorPropertiesFile = createTemporaryFile(""); + JSONObject dMaaPConf = readJSONFromFile(Paths.get("src/test/resources/testParseDMaaPCredentialsGen2.json")); + stubConsulToReturnLocalAddressOfCBS(); + stubCBSToReturnAppConfig(f("{\"collector.port\": 8686, \"streams_publishes\": %s}}", dMaaPConf)); + EventPublisher eventPublisherMock = mock(EventPublisher.class); + ConfigFilesFacade configFilesFacade = new ConfigFilesFacade(dMaaPConfigFile, collectorPropertiesFile); + configFilesFacade.writeProperties(Map("collector.port", "8686")); + configFilesFacade.writeDMaaPConfiguration(dMaaPConf); + + // when + ConfigLoader configLoader = new ConfigLoader(eventPublisherMock::reconfigure, configFilesFacade, ConfigSource::getAppConfig, () -> wiremockBasedEnvProps()); + configLoader.updateConfig(); + + // then + verifyZeroInteractions(eventPublisherMock); + } + +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/controller/ConfigParsingTest.java b/src/test/java/org/onap/dcae/controller/ConfigParsingTest.java new file mode 100644 index 0000000..7792b71 --- /dev/null +++ b/src/test/java/org/onap/dcae/controller/ConfigParsingTest.java @@ -0,0 +1,79 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.controller; + + +import static io.vavr.API.Map; +import static org.assertj.core.api.Assertions.assertThat; +import static org.onap.dcae.TestingUtilities.assertJSONObjectsEqual; +import static org.onap.dcae.TestingUtilities.readJSONFromFile; + +import io.vavr.collection.Map; +import io.vavr.control.Option; + +import java.nio.file.Path; +import java.nio.file.Paths; +import org.json.JSONObject; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class ConfigParsingTest { + + @Test + public void shouldReturnDMaaPConfig() { + JSONObject dMaaPConf = new JSONObject("{\"auth-credentials-present\": {\"aaf_username\": \"sampleUser\",\"dmaap_info\": {\"topic_url\": \"http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV\",},\"aaf_password\": \"samplePassword\"}}"); + JSONObject root = new JSONObject(); + root.put("key1", "someProperty"); + root.put("key2", "someProperty"); + root.put("streams_publishes", dMaaPConf); + + Option dMaaPConfig = ConfigParsing.getDMaaPConfig(root); + + assertThat(dMaaPConfig.isEmpty()).isFalse(); + assertJSONObjectsEqual(dMaaPConfig.get(), dMaaPConf); + } + + @Test + public void shouldReturnEmptyIfDMaaPConfigIsInvalid() { + JSONObject root = new JSONObject(); + root.put("streams_publishes", 1); + + Option dMaaPConfig = ConfigParsing.getDMaaPConfig(root); + + assertThat(dMaaPConfig.isEmpty()).isTrue(); + } + + @Test + public void getProperties() { + JSONObject dMaaPConf = new JSONObject("{\"auth-credentials-present\": {\"aaf_username\": \"sampleUser\",\"dmaap_info\": {\"topic_url\": \"http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV\",},\"aaf_password\": \"samplePassword\"}}"); + JSONObject root = new JSONObject(); + root.put("key1", "someProperty"); + root.put("key2", "someProperty"); + root.put("streams_publishes", dMaaPConf); + + Map properties = ConfigParsing.getProperties(root); + assertThat(properties).isEqualTo(Map("key1", "someProperty", "key2", "someProperty")); + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/controller/EnvPropertiesReaderTest.java b/src/test/java/org/onap/dcae/controller/EnvPropertiesReaderTest.java new file mode 100644 index 0000000..2e215a7 --- /dev/null +++ b/src/test/java/org/onap/dcae/controller/EnvPropertiesReaderTest.java @@ -0,0 +1,69 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.controller; + +import static io.vavr.API.Map; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.onap.dcae.controller.EnvPropertiesReader.readEnvProps; + +import io.vavr.collection.Map; +import org.junit.Test; + + +public class EnvPropertiesReaderTest { + + @Test + public void shouldReturnEmptyOnMissingConsulHost() { + Map envs = Map( + "CONFIG_BINDING_SERVICE", "doesNotMatter", + "HOSTNAME", "doesNotMatter"); + assertTrue(readEnvProps(envs).isEmpty()); + } + + @Test + public void shouldReturnEmptyOnMissingCBSName() { + Map envs = Map( + "CONSUL_HOST", "doesNotMatter", + "HOSTNAME", "doesNotMatter"); + assertTrue(readEnvProps(envs).isEmpty()); + } + + @Test + public void shouldReturnEmptyOnMissingVESAppName() { + Map envs = Map( + "CONSUL_HOST", "doesNotMatter", + "CONFIG_BINDING_SERVICE", "doesNotMatter"); + assertTrue(readEnvProps(envs).isEmpty()); + } + + @Test + public void shouldReturnSomeOfAllProperties() { + Map envs = Map( + "CONSUL_HOST", "doesNotMatter", + "HOSTNAME", "doesNotMatter", + "CONFIG_BINDING_SERVICE", "doesNotMatter"); + assertFalse(readEnvProps(envs).isEmpty()); + } + +} + diff --git a/src/test/java/org/onap/dcae/controller/EnvPropsTest.java b/src/test/java/org/onap/dcae/controller/EnvPropsTest.java new file mode 100644 index 0000000..e9c194e --- /dev/null +++ b/src/test/java/org/onap/dcae/controller/EnvPropsTest.java @@ -0,0 +1,41 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.controller; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import junit.framework.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.onap.dcae.common.Format; + + +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; +import static org.junit.Assert.assertEquals; + +public class EnvPropsTest { + @Rule + public WireMockRule wireMockRule = new WireMockRule( + wireMockConfig().dynamicPort().dynamicHttpsPort().keystorePath(null)); + @Test + public void fromString() { + Assert.assertEquals(new EnvProps("http", "localhost", wireMockRule.port(), "http", "CBSName", "restconfcollector").equals(new EnvProps("http", "localhost", wireMockRule.port(), "http", "CBSName", "restconfcollector")), true); + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/dcae/restapi/ApiAuthInterceptionTest.java b/src/test/java/org/onap/dcae/restapi/ApiAuthInterceptionTest.java new file mode 100644 index 0000000..1427438 --- /dev/null +++ b/src/test/java/org/onap/dcae/restapi/ApiAuthInterceptionTest.java @@ -0,0 +1,177 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.restconfcollector + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * Copyright (C) 2018-2019 Huawei. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcae.restapi; + +import io.vavr.collection.HashMap; +import io.vavr.collection.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.onap.dcae.ApplicationSettings; +import org.slf4j.Logger; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class ApiAuthInterceptionTest { + private static final String USERNAME = "Foo"; + private static final String PASSWORD = "Bar"; + private static final Map CREDENTIALS = HashMap.of(USERNAME, PASSWORD); + + @Mock + private Logger log; + + @Mock + private ApplicationSettings settings; + + @Mock + private HttpServletResponse response; + + @Mock + private Object obj; + + @Mock + private PrintWriter writer; + + @InjectMocks + private ApiAuthInterceptor sut; + + + private HttpServletRequest createEmptyRequest() { + return MockMvcRequestBuilders + .post("") + .buildRequest(null); + } + + private HttpServletRequest createRequestWithAuthorizationHeader() { + return SecurityMockMvcRequestPostProcessors + .httpBasic(USERNAME, PASSWORD) + .postProcessRequest( + MockMvcRequestBuilders + .post("") + .buildRequest(null)); + } + + @Test + public void shouldSucceedWhenAuthorizationIsDisabled() throws IOException { + // given + final HttpServletRequest request = createEmptyRequest(); + + when(settings.authorizationEnabled()).thenReturn(false); + + // when + final boolean isAuthorized = sut.preHandle(request, response, obj); + + // then + assertTrue(isAuthorized); + } + + @Test + public void shouldFailDueToEmptyBasicAuthorizationHeader() throws IOException { + // given + final HttpServletRequest request = createEmptyRequest(); + + when(settings.authorizationEnabled()).thenReturn(true); + when(response.getWriter()).thenReturn(writer); + + // when + final boolean isAuthorized = sut.preHandle(request, response, obj); + + + // then + assertFalse(isAuthorized); + + verify(response).setStatus(HttpStatus.BAD_REQUEST.value()); + verify(writer).write(ApiException.UNAUTHORIZED_USER.toJSON().toString()); + } + + @Test + public void shouldFailDueToBasicAuthenticationUserMissingFromSettings() throws IOException { + // given + final HttpServletRequest request = createRequestWithAuthorizationHeader(); + + when(settings.authorizationEnabled()).thenReturn(true); + when(response.getWriter()).thenReturn(writer); + + // when + final boolean isAuthorized = sut.preHandle(request, response, obj); + + // then + assertFalse(isAuthorized); + + verify(response).setStatus(HttpStatus.BAD_REQUEST.value()); + verify(writer).write(ApiException.UNAUTHORIZED_USER.toJSON().toString()); + } + + @Test + public void shouldSucceed() throws IOException { + // given + final HttpServletRequest request = createRequestWithAuthorizationHeader(); + when(settings.authorizationEnabled()).thenReturn(true); + when(settings.validAuthorizationCredentials()).thenReturn( + HashMap.of(USERNAME, "$2a$10$BsZkEynNm/93wbAeeZuxJeu6IHRyQl4XReqDg2BtYOFDhUsz20.3G")); + when(response.getWriter()).thenReturn(writer); + + // when + final boolean isAuthorized = sut.preHandle(request, response, obj); + + // then + assertTrue(isAuthorized); + } + + @Test + public void shouldFailDueToInvalidBasicAuthorizationHeaderValue() throws IOException { + // given + final HttpServletRequest request = + MockMvcRequestBuilders + .post("") + .header(HttpHeaders.AUTHORIZATION, "FooBar") + .buildRequest(null); + + when(settings.authorizationEnabled()).thenReturn(true); + when(settings.validAuthorizationCredentials()).thenReturn(CREDENTIALS); + when(response.getWriter()).thenReturn(writer); + + // when + final boolean isAuthorized = sut.preHandle(request, response, obj); + + // then + assertFalse(isAuthorized); + + verify(response).setStatus(HttpStatus.BAD_REQUEST.value()); + verify(writer).write(ApiException.UNAUTHORIZED_USER.toJSON().toString()); + } +} diff --git a/src/test/resources/RestConfEvent.json b/src/test/resources/RestConfEvent.json deleted file mode 100755 index 93d0b64..0000000 --- a/src/test/resources/RestConfEvent.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "ietf-notification:notification" : { - "eventTime" : "eventtime", - "ietf-yang-push:push-change-update": { - "subscription-id":"100", - "datastore-changes": { - "ietf-yang-patch:yang-patch":{ - "patch-id":"patch-id", - "edit":[{ - "edit-id":"edit-id", - "operation":"create", - "target":"target", - "value": { - "ietf-interfaces:interfaces-state":{ - "interface": { - "name":"eth0", - "oper-status":"up" - } - } - } - }] - } - } - } - } -} \ No newline at end of file diff --git a/src/test/resources/controller-config_dmaap_ip.json b/src/test/resources/controller-config_dmaap_ip.json new file mode 100755 index 0000000..060c51e --- /dev/null +++ b/src/test/resources/controller-config_dmaap_ip.json @@ -0,0 +1,238 @@ +{ + "header.authflag": 1, + "collector.inputQueue.maxPending": 8096, + "collector.schema.checkflag": 1, + "collector.keystore.file.location": "/opt/app/dcae-certificate/keystore.jks", + "tomcat.maxthreads": "200", + "collector.keystore.passwordfile": "/opt/app/dcae-certificate/.password", + "collector.service.secure.port": 8687, + "collector.schema.file": "{\"v1\":\"./etc/CommonEventFormat_27.2.json\",\"v2\":\"./etc/CommonEventFormat_27.2.json\",\"v3\":\"./etc/CommonEventFormat_27.2.json\",\"v4\":\"./etc/CommonEventFormat_27.2.json\",\"v5\":\"./etc/CommonEventFormat_28.4.json\"}", + "collector.dmaap.streamid": "fault=ves-fault,ves-fault-secondary|syslog=ves-syslog,ves-syslog-secondary|heartbeat=ves-heartbeat,ves-heartbeat-secondary|measurementsForVfScaling=ves-measurement,ves-measurement-secondary|mobileFlow=ves-mobileflow,ves-mobileflow-secondary|other=ves-other,ves-other-secondary|stateChange=ves-statechange,ves-statechange-secondary|thresholdCrossingAlert=ves-thresholdCrossingAlert,ves-thresholdCrossingAlert-secondary|voiceQuality=ves-voicequality,ves-voicequality-secondary|sipSignaling=ves-sipsignaling,ves-sipsignaling-secondary", + "streams_subscribes": {}, + "collector.service.port": -1, + "services_calls": {}, + "streams_publishes": { + "ves-other": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-fault": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-syslog": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-other-secondary": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-syslog-secondary": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-thresholdCrossingAlert-secondary": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-voicequality": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-sipsignaling-secondary": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-heartbeat": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-mobileflow-secondary": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-heartbeat-secondary": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-measurement-secondary": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-measurement": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-sipsignaling": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-statechange-secondary": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-voicequality-secondary": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-fault-secondary": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-statechange": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-mobileflow": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + }, + "ves-thresholdCrossingAlert": { + "aaf_username": null, + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "client_id": null, + "location": "mtl5", + "client_role": null, + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV" + } + } + }, + "event.transform.flag": 1, + "header.authlist": "sample1,$2a$10$pgjaxDzSuc6XVFEeqvxQ5u90DKJnM/u7TJTcinAlFJVaavXMWf/Zi|userid1,$2a$10$61gNubgJJl9lh3nvQvY9X.x4e5ETWJJ7ao7ZhJEvmfJigov26Z6uq|userid2,$2a$10$G52y/3uhuhWAMy.bx9Se8uzWinmbJa.dlm1LW6bYPdPkkywLDPLiy" +} diff --git a/src/test/resources/controller-config_singleline_ip.json b/src/test/resources/controller-config_singleline_ip.json new file mode 100755 index 0000000..752a64f --- /dev/null +++ b/src/test/resources/controller-config_singleline_ip.json @@ -0,0 +1,128 @@ +{ + "header.authflag": "1", + "collector.schema.file": "{\"v1\": \"./etc/CommonEventFormat_27.2.json\", \"v2\": \"./etc/CommonEventFormat_27.2.json\", \"v3\": \"./etc/CommonEventFormat_27.2.json\", \"v4\": \"./etc/CommonEventFormat_27.2.json\", \"v5\": \"./etc/CommonEventFormat_28.4.json\"}", + "collector.keystore.passwordfile": "/opt/app/dcae-certificate/.password", + "tomcat.maxthreads": "200", + "collector.dmaap.streamid": "fault=ves-fault|syslog=ves-syslog|heartbeat=ves-heartbeat|measurementsForVfScaling=ves-measurement|mobileFlow=ves-mobileflow|other=ves-other|stateChange=ves-statechange|thresholdCrossingAlert=ves-thresholdCrossingAlert|voiceQuality=ves-voicequality|sipSignaling=ves-sipsignaling", + "streams_subscribes": {}, + "collector.inputQueue.maxPending": "8096", + "streams_publishes": { + "ves-mobileflow": { + "type": "message_router", + "dmaap_info": { + "client_id": "1517590629043", + "client_role": "com.att.secCollector.member", + "location": "rdm5bdcc2", + "topic_url": "https://DMAAPHOST:3905/events/com.att.dcae.dmaap.FTL.24256-SEC-MOBILEFLOW-OUTPUT-v1" + }, + "aaf_username": "userid@namespace", + "aaf_password": "authpwd" + }, + "ves-measurement": { + "type": "message_router", + "dmaap_info": { + "client_id": "1517590433916", + "client_role": "com.att.secCollector.member", + "location": "rdm5bdcc2", + "topic_url": "https://DMAAPHOST:3905/events/com.att.dcae.dmaap.FTL.24256-ENC-MEASUREMENT-OUTPUT-v1" + }, + "aaf_username": "userid@namespace", + "aaf_password": "authpwd" + }, + "ves-voicequality": { + "type": "message_router", + "dmaap_info": { + "client_id": "1517590778397", + "client_role": "com.att.secCollector.member", + "location": "rdm5bdcc2", + "topic_url": "https://DMAAPHOST:3905/events/com.att.dcae.dmaap.FTL.24256-VES-VOICEQUALITY-OUTPUT-v1" + }, + "aaf_username": "userid@namespace", + "aaf_password": "authpwd" + }, + "ves-thresholdCrossingAlert": { + "type": "message_router", + "dmaap_info": { + "client_id": "1517590728150", + "client_role": "com.att.secCollector.member", + "location": "rdm5bdcc2", + "topic_url": "https://DMAAPHOST:3905/events/com.att.dcae.dmaap.FTL.24256-SEC-TCA-OUTPUT-v1" + }, + "aaf_username": "userid@namespace", + "aaf_password": "authpwd" + }, + "ves-fault": { + "type": "message_router", + "dmaap_info": { + "client_id": "1517590384670", + "client_role": "com.att.secCollector.member", + "location": "rdm5bdcc2", + "topic_url": "https://DMAAPHOST:3905/events/com.att.dcae.dmaap.FTL.24256-SEC-FAULT-OUTPUT-v1" + }, + "aaf_username": "userid@namespace", + "aaf_password": "authpwd" + }, + "ves-heartbeat": { + "type": "message_router", + "dmaap_info": { + "client_id": "1517590530041", + "client_role": "com.att.secCollector.member", + "location": "rdm5bdcc2", + "topic_url": "https://DMAAPHOST:3905/events/com.att.dcae.dmaap.FTL.24256-SEC-HEARTBEAT-OUTPUT-v1" + }, + "aaf_username": "userid@namespace", + "aaf_password": "authpwd" + }, + "ves-sipsignaling": { + "type": "message_router", + "dmaap_info": { + "client_id": "1517590828736", + "client_role": "com.att.secCollector.member", + "location": "rdm5bdcc2", + "topic_url": "https://DMAAPHOST:3905/events/com.att.dcae.dmaap.FTL.24256-VES-SIPSIGNALING-OUTPUT-v1" + }, + "aaf_username": "userid@namespace", + "aaf_password": "authpwd" + }, + "ves-syslog": { + "type": "message_router", + "dmaap_info": { + "client_id": "1517590482019", + "client_role": "com.att.secCollector.member", + "location": "rdm5bdcc2", + "topic_url": "https://DMAAPHOST:3905/events/com.att.dcae.dmaap.FTL.24256-SEC-SYSLOG-OUTPUT-v1" + }, + "aaf_username": "userid@namespace", + "aaf_password": "authpwd" + }, + "ves-other": { + "type": "message_router", + "dmaap_info": { + "client_id": "1517590581045", + "client_role": "com.att.secCollector.member", + "location": "rdm5bdcc2", + "topic_url": "https://DMAAPHOST:3905/events/com.att.dcae.dmaap.FTL.24256-SEC-OTHER-OUTPUT-v1" + }, + "aaf_username": "userid@namespace", + "aaf_password": "authpwd" + }, + "ves-statechange": { + "type": "message_router", + "dmaap_info": { + "client_id": "1517590677649", + "client_role": "com.att.secCollector.member", + "location": "rdm5bdcc2", + "topic_url": "https://DMAAPHOST:3905/events/com.att.dcae.dmaap.FTL.24256-SEC-STATECHANGE-OUTPUT-v1" + }, + "aaf_username": "userid@namespace", + "aaf_password": "authpwd" + } + }, + "collector.schema.checkflag": "1", + "services_calls": {}, + "event.transform.flag": "1", + "collector.keystore.file.location": "/opt/app/dcae-certificate/keystore.jks", + "collector.header.authlist": "sample1,$2a$10$pgjaxDzSuc6XVFEeqvxQ5u90DKJnM/u7TJTcinAlFJVaavXMWf/Zi|userid1,$2a$10$61gNubgJJl9lh3nvQvY9X.x4e5ETWJJ7ao7ZhJEvmfJigov26Z6uq|userid2,$2a$10$G52y/3uhuhWAMy.bx9Se8uzWinmbJa.dlm1LW6bYPdPkkywLDPLiy", + "collector.rcc.service.secure.port": "8687", + "collector.rcc.service.port": "-1" +} \ No newline at end of file diff --git a/src/test/resources/keystore b/src/test/resources/keystore new file mode 100755 index 0000000..f0822cb Binary files /dev/null and b/src/test/resources/keystore differ diff --git a/src/test/resources/passwordfile b/src/test/resources/passwordfile new file mode 100755 index 0000000..11e1e24 --- /dev/null +++ b/src/test/resources/passwordfile @@ -0,0 +1 @@ +vestest \ No newline at end of file diff --git a/src/test/resources/rcc_passwordfile b/src/test/resources/rcc_passwordfile new file mode 100755 index 0000000..25acfbf --- /dev/null +++ b/src/test/resources/rcc_passwordfile @@ -0,0 +1 @@ +collector \ No newline at end of file diff --git a/src/test/resources/sdnc.p12 b/src/test/resources/sdnc.p12 new file mode 100755 index 0000000..15c8893 Binary files /dev/null and b/src/test/resources/sdnc.p12 differ diff --git a/src/test/resources/testDmaapConfig_ip.json b/src/test/resources/testDmaapConfig_ip.json new file mode 100755 index 0000000..247db78 --- /dev/null +++ b/src/test/resources/testDmaapConfig_ip.json @@ -0,0 +1,12 @@ +{ + + "channels": [{ + "name": "sec_fault_ueb", + "type": "out", + "class": "HpCambriaOutputStream", + "cambria.hosts": "uebsb91kcdc.it.att.com,uebsb92kcdc.it.att.com,uebsb93kcdc.it.att.com", + "cambria.topic": "DCAE-SE-COLLECTOR-EVENTS-DEV", + "stripHpId": "true" + } + ] +} diff --git a/src/test/resources/testFullDmaapConfig_gen2.json b/src/test/resources/testFullDmaapConfig_gen2.json new file mode 100755 index 0000000..6880466 --- /dev/null +++ b/src/test/resources/testFullDmaapConfig_gen2.json @@ -0,0 +1,24 @@ +{ + "ves-fault-secondary": { + "aaf_username": "sampleUsername", + "dmaap_info": { + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV", + "location": "mtl5", + "client_id": null, + "client_role": null + }, + "type": "message_router", + "aaf_password": "SamplePasswd" + }, + "ves-thresholdCrossingAlert-secondary": { + "aaf_username": "sampleUsername2", + "dmaap_info": { + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV", + "location": "mtl5", + "client_id": null, + "client_role": null + }, + "type": "message_router", + "aaf_password": "SamplePassWD2" + } +} \ No newline at end of file diff --git a/src/test/resources/testParseDMaaPCredentialsGen2.json b/src/test/resources/testParseDMaaPCredentialsGen2.json index 23230c1..953cb6e 100755 --- a/src/test/resources/testParseDMaaPCredentialsGen2.json +++ b/src/test/resources/testParseDMaaPCredentialsGen2.json @@ -2,20 +2,20 @@ "auth-credentials-null": { "aaf_username": null, "dmaap_info": { - "topic_url": "http://UEBHOST:3904/events/DCAE-RESTCONF-COLLECTOR-EVENTS-DEV" + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV", }, "aaf_password": null }, "auth-credentials-present": { "aaf_username": "sampleUser", "dmaap_info": { - "topic_url": "http://UEBHOST:3904/events/DCAE-RESTCONF-COLLECTOR-EVENTS-DEV" + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV", }, "aaf_password": "samplePassword" }, "auth-credentials-missing": { "dmaap_info": { - "topic_url": "http://UEBHOST:3904/events/DCAE-RESTCONF-COLLECTOR-EVENTS-DEV" + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV", } } } \ No newline at end of file diff --git a/src/test/resources/testParseDMaaPCredentialsGen2Temp.json b/src/test/resources/testParseDMaaPCredentialsGen2Temp.json new file mode 100755 index 0000000..fef7a8b --- /dev/null +++ b/src/test/resources/testParseDMaaPCredentialsGen2Temp.json @@ -0,0 +1,9 @@ +{ + "auth-credentials-present": { + "aaf_username": "sampleUser", + "dmaap_info": { + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV", + }, + "aaf_password": "samplePassword" + } +} \ No newline at end of file diff --git a/src/test/resources/testParseDMaaPCredentialsLegacy.json b/src/test/resources/testParseDMaaPCredentialsLegacy.json index ee215e2..9f19b2c 100755 --- a/src/test/resources/testParseDMaaPCredentialsLegacy.json +++ b/src/test/resources/testParseDMaaPCredentialsLegacy.json @@ -4,7 +4,7 @@ "name": "auth-credentials-null", "cambria.url": "127.0.0.1:3904", "cambria.hosts": "uebsb91kcdc.it.att.com,uebsb92kcdc.it.att.com,uebsb93kcdc.it.att.com", - "cambria.topic": "DCAE-RESTCONF-COLLECTOR-EVENTS-DEV", + "cambria.topic": "DCAE-SE-COLLECTOR-EVENTS-DEV", "basicAuthPassword": null, "basicAuthUsername": null }, @@ -12,7 +12,7 @@ "name": "auth-credentials-present", "cambria.url": "127.0.0.1:3904", "cambria.hosts": "uebsb91kcdc.it.att.com,uebsb92kcdc.it.att.com,uebsb93kcdc.it.att.com", - "cambria.topic": "DCAE-RESTCONF-COLLECTOR-EVENTS-DEV", + "cambria.topic": "DCAE-SE-COLLECTOR-EVENTS-DEV", "basicAuthPassword": "samplePassword", "basicAuthUsername": "sampleUser" }, @@ -20,7 +20,7 @@ "name": "auth-credentials-missing", "cambria.url": "127.0.0.1:3904", "cambria.hosts": "uebsb91kcdc.it.att.com,uebsb92kcdc.it.att.com,uebsb93kcdc.it.att.com", - "cambria.topic": "DCAE-RESTCONF-COLLECTOR-EVENTS-DEV" + "cambria.topic": "DCAE-SE-COLLECTOR-EVENTS-DEV" } ] } \ No newline at end of file diff --git a/src/test/resources/testParseDMaaPGen2.json b/src/test/resources/testParseDMaaPGen2.json index 4ef04a2..5b4fe6a 100755 --- a/src/test/resources/testParseDMaaPGen2.json +++ b/src/test/resources/testParseDMaaPGen2.json @@ -1,12 +1,12 @@ { "event-segments-with-port": { "dmaap_info": { - "topic_url": "http://UEBHOST:3904/events/DCAE-RESTCONF-COLLECTOR-EVENTS-DEV" + "topic_url": "http://UEBHOST:3904/events/DCAE-SE-COLLECTOR-EVENTS-DEV", } }, "other-segments-without-ports": { "dmaap_info": { - "topic_url": "http://UEBHOST:3904/somethingHere/DCAE-RESTCONF-COLLECTOR-EVENTS-DEV" + "topic_url": "http://UEBHOST:3904/somethingHere/DCAE-SE-COLLECTOR-EVENTS-DEV", } } } \ No newline at end of file diff --git a/src/test/resources/testParseDMaaPLegacy.json b/src/test/resources/testParseDMaaPLegacy.json index fda9c60..9661e30 100755 --- a/src/test/resources/testParseDMaaPLegacy.json +++ b/src/test/resources/testParseDMaaPLegacy.json @@ -4,18 +4,18 @@ "name": "url-precedes-hosts", "cambria.url": "127.0.0.1:3904", "cambria.hosts": "h1.att.com,h2.att.com", - "cambria.topic": "DCAE-RESTCONF-COLLECTOR-EVENTS-DEV" + "cambria.topic": "DCAE-SE-COLLECTOR-EVENTS-DEV", }, { "name": "url-key-missing", "cambria.hosts": "h1.att.com,h2.att.com", - "cambria.topic": "DCAE-RESTCONF-COLLECTOR-EVENTS-DEV" + "cambria.topic": "DCAE-SE-COLLECTOR-EVENTS-DEV", }, { "name": "url-is-null", "cambria.url": null, "cambria.hosts": "h1.att.com,h2.att.com", - "cambria.topic": "DCAE-RESTCONF-COLLECTOR-EVENTS-DEV" + "cambria.topic": "DCAE-SE-COLLECTOR-EVENTS-DEV" } ] } \ No newline at end of file diff --git a/src/test/resources/test_anynode_class.json b/src/test/resources/test_anynode_class.json new file mode 100755 index 0000000..0d34945 --- /dev/null +++ b/src/test/resources/test_anynode_class.json @@ -0,0 +1,9 @@ +{ + "channels": [{ + "one": "number1", "two": "number2", "three": "number3"}], + "sampleStrList": ["1", "2", "3", "4", "5"], + "sampleNestedObject": {"a": 1, "b": 2}, + "sampleInt": 1, + "sampleString": "str", + "sampleNull": null +} diff --git a/src/test/resources/testcollector.properties b/src/test/resources/testcollector.properties new file mode 100755 index 0000000..677e1c8 --- /dev/null +++ b/src/test/resources/testcollector.properties @@ -0,0 +1,10 @@ +collector.rcc.service.port=9999 +collector.rcc.service.secure.port=8687 +collector.rcc.keystore.file.location=../etc/keystore +collector.rcc.keystore.passwordfile=./etc/passwordfile +collector.rcc.dmaap.streamid=fault=sec_fault|syslog=sec_syslog|heartbeat=sec_heartbeat|measurementsForVfScaling=sec_measurement|mobileFlow=sec_mobileflow|other=sec_other|stateChange=sec_statechange|thresholdCrossingAlert=sec_thresholdCrossingAlert|voiceQuality=ves_voicequality|sipSignaling=ves_sipsignaling +collector.dmaapfile=./etc/DmaapConfig.json +collector.header.authflag=1 +collector.header.authlist=sample1,$2a$10$pgjaxDzSuc6XVFEeqvxQ5u90DKJnM/u7TJTcinAlFJVaavXMWf/Zi|userid1,$2a$10$61gNubgJJl9lh3nvQvY9X.x4e5ETWJJ7ao7ZhJEvmfJigov26Z6uq|userid2,$2a$10$G52y/3uhuhWAMy.bx9Se8uzWinmbJa.dlm1LW6bYPdPkkywLDPLiy + + diff --git a/src/test/resources/trustpasswordfile b/src/test/resources/trustpasswordfile new file mode 100755 index 0000000..11e1e24 --- /dev/null +++ b/src/test/resources/trustpasswordfile @@ -0,0 +1 @@ +vestest \ No newline at end of file diff --git a/src/test/resources/truststore b/src/test/resources/truststore new file mode 100755 index 0000000..b0802a7 Binary files /dev/null and b/src/test/resources/truststore differ -- cgit 1.2.3-korg