From 4751cb9d3db83a1e54d078c9b3416d6f3fb76494 Mon Sep 17 00:00:00 2001 From: emartin Date: Tue, 29 Jan 2019 12:21:51 +0000 Subject: Fetch mapper config from configbinding service Change-Id: I69e654719969f2d0ef6e7c8adb4806aac9c1e898 Issue-ID: DCAEGEN2-1081 Signed-off-by: emartin --- .gitignore | 4 + pom.xml | 24 ++- .../org/onap/dcaegen2/services/pmmapper/App.java | 19 +- .../pmmapper/config/BusControllerConfig.java | 40 ----- .../services/pmmapper/config/ConfigHandler.java | 133 ++++++++++++++ .../pmmapper/datarouter/DataRouterSubscriber.java | 3 +- .../pmmapper/exceptions/CBSConfigException.java | 26 +++ .../pmmapper/exceptions/CBSServerError.java | 26 +++ .../pmmapper/exceptions/ConsulServerError.java | 26 +++ .../exceptions/EnvironmentConfigException.java | 26 +++ .../pmmapper/exceptions/MapperConfigException.java | 26 +++ .../pmmapper/model/BusControllerConfig.java | 40 +++++ .../services/pmmapper/model/CBSConfig.java | 46 +++++ .../services/pmmapper/model/EnvironmentConfig.java | 54 ++++++ .../services/pmmapper/model/MapperConfig.java | 37 ++++ .../services/pmmapper/utils/RequestSender.java | 77 +++++++++ .../pmmapper/config/ConfigHandlerTests.java | 192 +++++++++++++++++++++ .../pmmapper/config/util/RequestSenderTests.java | 116 +++++++++++++ .../datarouter/DataRouterSubscriberTest.java | 2 +- src/test/resources/incomplete_mapper_config.json | 24 +++ src/test/resources/valid_cbs_config.json | 23 +++ src/test/resources/valid_mapper_config.json | 20 +++ 22 files changed, 933 insertions(+), 51 deletions(-) create mode 100644 .gitignore delete mode 100644 src/main/java/org/onap/dcaegen2/services/pmmapper/config/BusControllerConfig.java create mode 100644 src/main/java/org/onap/dcaegen2/services/pmmapper/config/ConfigHandler.java create mode 100644 src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/CBSConfigException.java create mode 100644 src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/CBSServerError.java create mode 100644 src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/ConsulServerError.java create mode 100644 src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/EnvironmentConfigException.java create mode 100644 src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/MapperConfigException.java create mode 100644 src/main/java/org/onap/dcaegen2/services/pmmapper/model/BusControllerConfig.java create mode 100644 src/main/java/org/onap/dcaegen2/services/pmmapper/model/CBSConfig.java create mode 100644 src/main/java/org/onap/dcaegen2/services/pmmapper/model/EnvironmentConfig.java create mode 100644 src/main/java/org/onap/dcaegen2/services/pmmapper/model/MapperConfig.java create mode 100644 src/main/java/org/onap/dcaegen2/services/pmmapper/utils/RequestSender.java create mode 100644 src/test/java/org/onap/dcaegen2/pmmapper/config/ConfigHandlerTests.java create mode 100644 src/test/java/org/onap/dcaegen2/pmmapper/config/util/RequestSenderTests.java create mode 100644 src/test/resources/incomplete_mapper_config.json create mode 100644 src/test/resources/valid_cbs_config.json create mode 100644 src/test/resources/valid_mapper_config.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a2e0ad8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +**/.settings +*.classpath +*.project +**/target \ No newline at end of file diff --git a/pom.xml b/pom.xml index 4edcd0f..bcad6b6 100644 --- a/pom.xml +++ b/pom.xml @@ -20,8 +20,8 @@ --> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.onap.dcaegen2.services @@ -47,6 +47,7 @@ 2.23.4 2.23.4 2.0.0 + 3.10.8 4.12 3.2.0 @@ -135,6 +136,18 @@ ${powermock.version} test + + org.mock-server + mockserver-netty + ${mockserver.version} + test + + + org.mock-server + mockserver-client-java + ${mockserver.version} + test + @@ -156,7 +169,9 @@ org.apache.maven.plugins maven-surefire-plugin ${surefire.version} - + + false + org.apache.maven.plugins @@ -176,7 +191,8 @@ true jar-with-dependencies - + ${shade.main} diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/App.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/App.java index 2b93d03..1c837e4 100644 --- a/src/main/java/org/onap/dcaegen2/services/pmmapper/App.java +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/App.java @@ -23,24 +23,33 @@ package org.onap.dcaegen2.services.pmmapper; import io.undertow.Handlers; import io.undertow.Undertow; import io.undertow.util.StatusCodes; -import org.onap.dcaegen2.services.pmmapper.config.BusControllerConfig; + +import org.onap.dcaegen2.services.pmmapper.config.ConfigHandler; import org.onap.dcaegen2.services.pmmapper.datarouter.DataRouterSubscriber; +import org.onap.dcaegen2.services.pmmapper.exceptions.CBSConfigException; +import org.onap.dcaegen2.services.pmmapper.exceptions.CBSServerError; +import org.onap.dcaegen2.services.pmmapper.exceptions.ConsulServerError; +import org.onap.dcaegen2.services.pmmapper.exceptions.EnvironmentConfigException; +import org.onap.dcaegen2.services.pmmapper.exceptions.MapperConfigException; import org.onap.dcaegen2.services.pmmapper.exceptions.TooManyTriesException; +import org.onap.dcaegen2.services.pmmapper.model.BusControllerConfig; +import org.onap.dcaegen2.services.pmmapper.model.MapperConfig; import java.net.MalformedURLException; import java.net.URL; public class App { - public static void main(String[] args) throws MalformedURLException, InterruptedException, TooManyTriesException { + public static void main(String[] args) throws MalformedURLException, InterruptedException, TooManyTriesException, CBSConfigException, ConsulServerError, EnvironmentConfigException, CBSServerError, MapperConfigException { DataRouterSubscriber dataRouterSubscriber = new DataRouterSubscriber(event -> { event.getHttpServerExchange().unDispatch(); event.getHttpServerExchange().getResponseSender().send(StatusCodes.OK_STRING); System.out.println(event.getMetadata().getProductName()); }); - BusControllerConfig config = new BusControllerConfig(); - config.setDataRouterSubscribeEndpoint(new URL("http://" + System.getenv("DMAAP_BC_SERVICE_HOST") + ":" + System.getenv("DMAAP_BC_SERVICE_PORT") + "/webapi/dr_subs")); - dataRouterSubscriber.start(config); + MapperConfig mapperConfig = new ConfigHandler().getMapperConfig(); + BusControllerConfig busConfig = mapperConfig.getBusControllerConfig(); + busConfig.setDataRouterSubscribeEndpoint(new URL("http://" + System.getenv("DMAAP_BC_SERVICE_HOST") + ":" + System.getenv("DMAAP_BC_SERVICE_PORT") + "/webapi/dr_subs")); + dataRouterSubscriber.start(busConfig); Undertow.builder() .addHttpListener(8081, "0.0.0.0") diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/config/BusControllerConfig.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/config/BusControllerConfig.java deleted file mode 100644 index 63b2a32..0000000 --- a/src/main/java/org/onap/dcaegen2/services/pmmapper/config/BusControllerConfig.java +++ /dev/null @@ -1,40 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2019 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.onap.dcaegen2.services.pmmapper.config; - -import lombok.Data; - -import java.net.URL; - -/** - * Stub for BusControllerConfiguration object. - */ -@Data -public class BusControllerConfig { - - private String dcaeLocation = "dcaeLocation"; - private String deliveryURL = "deliveryURL"; - private int feedId = 2; - private String lastMod = "lastMod"; - private String username = "username"; - private String password = "password"; - private URL dataRouterSubscribeEndpoint; - -} diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/config/ConfigHandler.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/config/ConfigHandler.java new file mode 100644 index 0000000..847fff2 --- /dev/null +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/config/ConfigHandler.java @@ -0,0 +1,133 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.services.pmmapper.config; + +import java.util.Arrays; +import org.onap.dcaegen2.services.pmmapper.exceptions.CBSConfigException; +import org.onap.dcaegen2.services.pmmapper.exceptions.CBSServerError; +import org.onap.dcaegen2.services.pmmapper.exceptions.ConsulServerError; +import org.onap.dcaegen2.services.pmmapper.exceptions.EnvironmentConfigException; +import org.onap.dcaegen2.services.pmmapper.exceptions.MapperConfigException; +import org.onap.dcaegen2.services.pmmapper.model.CBSConfig; +import org.onap.dcaegen2.services.pmmapper.model.EnvironmentConfig; +import org.onap.dcaegen2.services.pmmapper.model.MapperConfig; +import org.onap.dcaegen2.services.pmmapper.utils.RequestSender; +import org.onap.dcaegen2.services.pmmapper.utils.RequiredFieldDeserializer; +import com.google.gson.GsonBuilder; +import lombok.extern.slf4j.Slf4j; + +/** + * Handles the retrieval of the component spec-based PM-Mapper Configuration + * from DCAE. + */ +@Slf4j +public class ConfigHandler { + private RequestSender sender; + + /** + * Creates a ConfigHandler. + */ + public ConfigHandler() { + this(new RequestSender()); + } + + /** + * @see ConfigHandler#ConfigHandler() + * @param sender A RequestSender + */ + public ConfigHandler(RequestSender sender) { + this.sender = sender; + } + + /** + * Retrieves PM-Mapper Configuration from DCAE's ConfigBinding Service. + * + * @throws EnvironmentConfigException + * @throws ConsulServerError + * @throws CBSConfigException + * @throws CBSServerError + * @throws MapperConfigException + */ + public MapperConfig getMapperConfig() throws CBSConfigException, ConsulServerError, EnvironmentConfigException, + CBSServerError, MapperConfigException { + CBSConfig cbsConfig = convertCBSConfigToObject(getCBSConfigFromConsul()); + String cbsSocketAddress = cbsConfig.getServiceAddress() + ":" + cbsConfig.getServicePort(); + String requestURL = "http://" + cbsSocketAddress + "/service_component/" + cbsConfig.getServiceName(); + String mapperConfigJson = ""; + log.debug("Fetching mapper configuration from CBS: " + requestURL); + try { + mapperConfigJson = sender.send(requestURL); + } catch (Exception exception) { + throw new CBSServerError("Error connecting to Configbinding Service: ", exception); + } + + return convertMapperConfigToObject(mapperConfigJson); + } + + private String getCBSConfigFromConsul() throws ConsulServerError, EnvironmentConfigException { + String cbsParams; + String consulURL = "http://" + EnvironmentConfig.getConsulHost() + ":" + EnvironmentConfig.getConsultPort() + + "/v1/catalog/service/" + EnvironmentConfig.getCbsName(); + log.debug(consulURL); + try { + cbsParams = sender.send(consulURL); + } catch (Exception exception) { + throw new ConsulServerError("Error connecting to Consul: ", exception); + } + + log.debug("cbsConfig: " + cbsParams); + return cbsParams; + } + + private MapperConfig convertMapperConfigToObject(String mapperConfigJson) throws MapperConfigException { + log.debug("mapperConfigJson:" + mapperConfigJson); + MapperConfig mapperConfig; + try { + mapperConfig = new GsonBuilder() + .registerTypeAdapter(MapperConfig.class, new RequiredFieldDeserializer()) + .create() + .fromJson(mapperConfigJson, MapperConfig.class); + } catch (Exception exception) { + throw new MapperConfigException("Error parsing mapper configuration: " + mapperConfigJson, exception); + } + + log.debug("\n" + mapperConfig.toString()); + return mapperConfig; + } + + private CBSConfig convertCBSConfigToObject(String cbsParameters) throws CBSConfigException { + CBSConfig cbsConfig; + try { + cbsConfig = Arrays + .asList(new GsonBuilder() + .registerTypeAdapter(CBSConfig.class, new RequiredFieldDeserializer()) + .create() + .fromJson(cbsParameters, CBSConfig[].class)) + .get(0); + log.debug("\n\nReceived ConfigBinding Service Configurations: " + cbsConfig); + } catch (Exception exception) { + throw new CBSConfigException( + "Error mapping the received ConfigBinding service configuration parameters: " + cbsParameters, + exception); + } + return cbsConfig; + } + +} diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriber.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriber.java index 1d27d3b..f063a23 100644 --- a/src/main/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriber.java +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriber.java @@ -27,10 +27,11 @@ import com.google.gson.JsonParseException; import io.undertow.util.HeaderValues; import lombok.Data; import lombok.NonNull; -import org.onap.dcaegen2.services.pmmapper.config.BusControllerConfig; + import org.onap.dcaegen2.services.pmmapper.exceptions.NoMetadataException; import org.onap.dcaegen2.services.pmmapper.exceptions.TooManyTriesException; import org.onap.dcaegen2.services.pmmapper.model.EventMetadata; +import org.onap.dcaegen2.services.pmmapper.model.BusControllerConfig; import org.onap.dcaegen2.services.pmmapper.model.Event; import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/CBSConfigException.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/CBSConfigException.java new file mode 100644 index 0000000..99bb8a7 --- /dev/null +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/CBSConfigException.java @@ -0,0 +1,26 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.services.pmmapper.exceptions; + +public class CBSConfigException extends Exception { + public CBSConfigException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/CBSServerError.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/CBSServerError.java new file mode 100644 index 0000000..787d21f --- /dev/null +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/CBSServerError.java @@ -0,0 +1,26 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.services.pmmapper.exceptions; + +public class CBSServerError extends Exception { + public CBSServerError(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/ConsulServerError.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/ConsulServerError.java new file mode 100644 index 0000000..4c2adab --- /dev/null +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/ConsulServerError.java @@ -0,0 +1,26 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.services.pmmapper.exceptions; + +public class ConsulServerError extends Exception { + public ConsulServerError(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/EnvironmentConfigException.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/EnvironmentConfigException.java new file mode 100644 index 0000000..1a0d321 --- /dev/null +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/EnvironmentConfigException.java @@ -0,0 +1,26 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.services.pmmapper.exceptions; + +public class EnvironmentConfigException extends Exception { + public EnvironmentConfigException(String message) { + super(message); + } +} diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/MapperConfigException.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/MapperConfigException.java new file mode 100644 index 0000000..e78da98 --- /dev/null +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/MapperConfigException.java @@ -0,0 +1,26 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.services.pmmapper.exceptions; + +public class MapperConfigException extends Exception { + public MapperConfigException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/model/BusControllerConfig.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/model/BusControllerConfig.java new file mode 100644 index 0000000..3727099 --- /dev/null +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/model/BusControllerConfig.java @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.services.pmmapper.model; + +import lombok.Data; + +import java.net.URL; + +/** + * Stub for BusControllerConfiguration object. + */ +@Data +public class BusControllerConfig { + + private String dcaeLocation = "dcaeLocation"; + private String deliveryURL = "deliveryURL"; + private int feedId = 2; + private String lastMod = "lastMod"; + private String username = "username"; + private String password = "password"; + private URL dataRouterSubscribeEndpoint; + +} diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/model/CBSConfig.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/model/CBSConfig.java new file mode 100644 index 0000000..66fbed4 --- /dev/null +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/model/CBSConfig.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.services.pmmapper.model; + +import org.onap.dcaegen2.services.pmmapper.utils.GSONRequired; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +@Data +public class CBSConfig { + + @GSONRequired + @SerializedName("ServiceID") + private String serviceID; + + @GSONRequired + @SerializedName("ServiceName") + private String serviceName; + + @GSONRequired + @SerializedName("ServiceAddress") + private String serviceAddress; + + @GSONRequired + @SerializedName("ServicePort") + private String servicePort; + +} diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/model/EnvironmentConfig.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/model/EnvironmentConfig.java new file mode 100644 index 0000000..f9dd178 --- /dev/null +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/model/EnvironmentConfig.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.services.pmmapper.model; + +import java.util.Optional; + +import org.onap.dcaegen2.services.pmmapper.exceptions.EnvironmentConfigException; + +public class EnvironmentConfig { + + private static Integer consulPort = 8500; + + public static String getConsulHost() throws EnvironmentConfigException { + return Optional.ofNullable(System.getProperty("CONSUL_HOST")) + .orElseThrow(() -> new EnvironmentConfigException( + "$CONSUL_HOST environment variable must be defined prior to pm-mapper initialization")); + } + + public static Integer getConsultPort() throws EnvironmentConfigException { + Integer port = consulPort; + try { + port = Optional.ofNullable(System.getProperty("CONSUL_PORT")) + .map(Integer::valueOf) + .orElse(consulPort); + } catch (NumberFormatException e) { + throw new EnvironmentConfigException("CONSUL_PORT must be valid: " + port); + } + return port; + + } + + public static String getCbsName() throws EnvironmentConfigException { + return Optional.ofNullable(System.getProperty("CONFIG_BINDING_SERVICE")) + .orElseThrow(() -> new EnvironmentConfigException( + "$CONFIG_BINDING_SERVICE environment variable must be defined prior to pm-mapper initialization.")); + } +} diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/model/MapperConfig.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/model/MapperConfig.java new file mode 100644 index 0000000..f8e428f --- /dev/null +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/model/MapperConfig.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.services.pmmapper.model; + +import org.onap.dcaegen2.services.pmmapper.utils.GSONRequired; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class MapperConfig { + + @GSONRequired + @SerializedName("streams_subscribes.pm_mapper_handle_out.message_router_topic") + private String messageRouterTopicName; + + BusControllerConfig busControllerConfig; + +} \ No newline at end of file diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/utils/RequestSender.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/utils/RequestSender.java new file mode 100644 index 0000000..1b9cdc6 --- /dev/null +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/utils/RequestSender.java @@ -0,0 +1,77 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.services.pmmapper.utils; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class RequestSender { + private static final int MAX_RETRIES = 5; + private static final int RETRY_INTERVAL = 1000; + public static final String SERVER_ERROR_MESSAGE = "Error on Server"; + public static final int ERROR_START_RANGE = 300; + + /** + * Sends an Http GET request to a given endpoint. + * + * @return http response body + * @throws Exception + * @throws InterruptedException + */ + public String send(final String url) throws Exception { + log.debug("RequestSender::send: " + url); + String result = ""; + for (int i = 1; i <= MAX_RETRIES; i++) { + URL obj = new URL(url); + HttpURLConnection connection = (HttpURLConnection) obj.openConnection(); + try (InputStream is = connection.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(is))) { + result = reader.lines() + .collect(Collectors.joining("\n")); + int responseCode = connection.getResponseCode(); + if (!(isWithinErrorRange(responseCode))) { + break; + } + + } catch (Exception e) { + if (retryLimitReached(i)) { + throw new Exception(SERVER_ERROR_MESSAGE + ": " + connection.getResponseMessage(), e); + } + } + + Thread.sleep(RETRY_INTERVAL); + } + return result; + } + + private boolean retryLimitReached(final int retryCount) { + return retryCount >= MAX_RETRIES; + } + + private boolean isWithinErrorRange(final int responseCode) { + return responseCode >= ERROR_START_RANGE; + } +} diff --git a/src/test/java/org/onap/dcaegen2/pmmapper/config/ConfigHandlerTests.java b/src/test/java/org/onap/dcaegen2/pmmapper/config/ConfigHandlerTests.java new file mode 100644 index 0000000..0c3fb84 --- /dev/null +++ b/src/test/java/org/onap/dcaegen2/pmmapper/config/ConfigHandlerTests.java @@ -0,0 +1,192 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.pmmapper.config; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.when; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.UnknownHostException; + +import static org.mockito.Mockito.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.dcaegen2.services.pmmapper.config.ConfigHandler; +import org.onap.dcaegen2.services.pmmapper.exceptions.CBSConfigException; +import org.onap.dcaegen2.services.pmmapper.exceptions.CBSServerError; +import org.onap.dcaegen2.services.pmmapper.exceptions.ConsulServerError; +import org.onap.dcaegen2.services.pmmapper.exceptions.EnvironmentConfigException; +import org.onap.dcaegen2.services.pmmapper.exceptions.MapperConfigException; +import org.onap.dcaegen2.services.pmmapper.model.MapperConfig; +import org.onap.dcaegen2.services.pmmapper.utils.RequestSender; + +import com.google.gson.Gson; + +@ExtendWith(MockitoExtension.class) +public class ConfigHandlerTests { + private static String cbsConfig; + private static String validMapperConfig; + private String consulURL = "http://my_consult_host:8500/v1/catalog/service/config-binding-service"; + private String cbsURL = "http://config-binding-service:10000/service_component/pm-mapper-service-name"; + private Gson gson = new Gson(); + @Mock + private RequestSender sender; + + @BeforeAll() + public static void beforeAll() throws IOException { + validMapperConfig = getFileContents("valid_mapper_config.json"); + cbsConfig = getFileContents("valid_cbs_config.json"); + } + + @BeforeEach + public void beforeEach() throws Exception { + System.setProperty("CONSUL_HOST", "my_consult_host"); + System.setProperty("CONSUL_PORT", "8500"); + System.setProperty("CONFIG_BINDING_SERVICE", "config-binding-service"); + System.setProperty("HOSTNAME", "hotstname"); + } + + @Test + public void environmentConfig_missing_consulHost() throws EnvironmentConfigException { + System.clearProperty("CONSUL_HOST"); + System.clearProperty("CONFIG_BINDING_SERVICE"); + + Exception exception = assertThrows(EnvironmentConfigException.class, () -> { + ConfigHandler configHandler = new ConfigHandler(sender); + configHandler.getMapperConfig(); + }); + + assertTrue(exception.getMessage() + .contains("$CONSUL_HOST environment variable must be defined")); + } + + @Test + public void getMapperConfig_success() throws Exception { + when(sender.send(anyString())).then(invocation -> { + String url = (String) invocation.getArguments()[0]; + return url.equals(consulURL) ? cbsConfig : validMapperConfig; + }); + + MapperConfig actualConfig = getMapperConfig(); + MapperConfig expectedConfig = gson.fromJson(validMapperConfig, MapperConfig.class); + + assertEquals(expectedConfig, actualConfig); + } + + @Test + public void configbinding_config_format_error() throws Exception { + when(sender.send(consulURL)).then((invocationMock) -> { + return "some string that is not cbs config"; + }); + + assertThrows(CBSConfigException.class, this::getMapperConfig); + } + + @Test + public void consul_host_is_unknown() throws Exception { + when(sender.send(consulURL)).thenThrow(new UnknownHostException()); + assertThrows(ConsulServerError.class, this::getMapperConfig); + } + + @Test + public void configbinding_host_is_unknown() throws Exception { + when(sender.send(anyString())).then(invocation -> { + boolean isCBS = invocation.getArguments()[0].equals(cbsURL); + if (isCBS) { + throw new UnknownHostException("unknown cbs"); + } + return cbsConfig; + }); + + assertThrows(CBSServerError.class, this::getMapperConfig); + } + + @Test + public void consul_port_invalid() throws Exception { + System.setProperty("CONSUL_PORT", "19d93hjuji"); + assertThrows(EnvironmentConfigException.class, this::getMapperConfig); + } + + @Test + public void consul_server_error() throws Exception { + when(sender.send(consulURL)).thenThrow(new ConsulServerError("consul server error", new Throwable())); + assertThrows(ConsulServerError.class, this::getMapperConfig); + } + + @Test + public void configbinding_server_error() throws Exception { + when(sender.send(anyString())).then(invocation -> { + boolean isCBS = invocation.getArguments()[0].equals(cbsURL); + if (isCBS) { + throw new CBSServerError("unknown cbs", new Throwable()); + } + return cbsConfig; + }); + + assertThrows(CBSServerError.class, this::getMapperConfig); + } + + @Test + public void mapper_parse_invalid_json() throws Exception { + when(sender.send(anyString())).then(invocation -> { + String url = (String) invocation.getArguments()[0]; + return url.equals(consulURL) ? cbsConfig : "mapper config with incorrect format"; + }); + + assertThrows(MapperConfigException.class, this::getMapperConfig); + } + + @Test + public void mapper_parse_valid_json_missing_attributes() throws Exception { + when(sender.send(anyString())).then(invocation -> { + String incompleteConfig = getFileContents("incomplete_mapper_config.json"); + String url = (String) invocation.getArguments()[0]; + return url.equals(consulURL) ? cbsConfig : incompleteConfig; + }); + + assertThrows(MapperConfigException.class, this::getMapperConfig); + } + + private MapperConfig getMapperConfig() + throws UnknownHostException, EnvironmentConfigException, CBSConfigException, Exception { + return new ConfigHandler(sender).getMapperConfig(); + } + + private static String getFileContents(String fileName) throws IOException { + ClassLoader classLoader = ConfigHandlerTests.class.getClassLoader(); + String fileAsString = ""; + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(classLoader.getResourceAsStream(fileName)))) { + String line; + while ((line = reader.readLine()) != null) { + fileAsString += line; + } + } + return fileAsString; + } + +} diff --git a/src/test/java/org/onap/dcaegen2/pmmapper/config/util/RequestSenderTests.java b/src/test/java/org/onap/dcaegen2/pmmapper/config/util/RequestSenderTests.java new file mode 100644 index 0000000..470f146 --- /dev/null +++ b/src/test/java/org/onap/dcaegen2/pmmapper/config/util/RequestSenderTests.java @@ -0,0 +1,116 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.pmmapper.config.util; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockserver.integration.ClientAndServer.startClientAndServer; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.UnknownHostException; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Matchers; +import org.mockserver.client.server.MockServerClient; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.HttpStatusCode; +import org.mockserver.verify.VerificationTimes; +import org.onap.dcaegen2.services.pmmapper.utils.RequestSender; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(RequestSender.class) + +public class RequestSenderTests { + private static ClientAndServer mockServer; + private MockServerClient client = mockClient(); + + @BeforeClass + public static void setup() { + mockServer = startClientAndServer(1080); + } + + @AfterClass + public static void teardown() { + mockServer.stop(); + } + + @BeforeClass + public static void setEnvironmentVariable() { + System.setProperty("CONSUL_HOST", "my_consult_host"); + System.setProperty("CONFIG_BINDING_SERVICE", "config-binding-service"); + System.setProperty("HOSTNAME", "hostname"); + } + + @Test + public void send_success() throws Exception { + + client.when(request()) + .respond(response().withStatusCode(HttpStatusCode.OK_200.code())); + + new RequestSender().send("http://127.0.0.1:1080/once"); + + client.verify(request(), VerificationTimes.exactly(1)); + client.clear(request()); + } + + @Test + public void host_unavailable_retry_mechanism() throws Exception { + PowerMockito.mockStatic(Thread.class); + + client.when(request()) + .respond(response().withStatusCode(HttpStatusCode.SERVICE_UNAVAILABLE_503.code())); + + assertThrows(Exception.class, () -> { + new RequestSender().send("http://127.0.0.1:1080/anypath"); + }); + + client.verify(request(), VerificationTimes.exactly(5)); + client.clear(request()); + } + + @Test + public void host_unknown() throws IOException { + PowerMockito.mockStatic(Thread.class); + URL url = PowerMockito.mock(URL.class); + PowerMockito.when(url.openConnection()) + .thenThrow(UnknownHostException.class); + + assertThrows(Exception.class, () -> { + new RequestSender().send("http://127.0.0.1:1080/host-is-unknown"); + }); + + client.verify(request(), VerificationTimes.exactly(5)); + client.clear(request()); + } + + private MockServerClient mockClient() { + return new MockServerClient("127.0.0.1", 1080); + } + +} diff --git a/src/test/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriberTest.java b/src/test/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriberTest.java index 25fb8ae..645d1be 100644 --- a/src/test/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriberTest.java +++ b/src/test/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriberTest.java @@ -49,8 +49,8 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import org.onap.dcaegen2.services.pmmapper.config.BusControllerConfig; import org.onap.dcaegen2.services.pmmapper.exceptions.TooManyTriesException; +import org.onap.dcaegen2.services.pmmapper.model.BusControllerConfig; import org.onap.dcaegen2.services.pmmapper.model.Event; import org.onap.dcaegen2.services.pmmapper.model.EventMetadata; import org.powermock.api.mockito.PowerMockito; diff --git a/src/test/resources/incomplete_mapper_config.json b/src/test/resources/incomplete_mapper_config.json new file mode 100644 index 0000000..aec0aca --- /dev/null +++ b/src/test/resources/incomplete_mapper_config.json @@ -0,0 +1,24 @@ +{ + "_comment": "This mapper config is missing the messagerouter feed name", + "pm-mapper-filter": { + "filters": "{[]}" + }, + "3GPP.schema.file": "{\"3GPP_Schema\":\"./etc/3GPP_relaxed_schema.xsd\"}", + "streams_subscribes": {}, + "streams_publishes": { + "pm_mapper_handle_out": { + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "topic_url": "https://we-are-message-router.us:3905/events/some-topic", + "client_role": null, + "location": null, + "client_id": null + }, + "aaf_username": null + } + }, + "some parameter": "unauthenticated.PM_VES_OUTPUT", + "some field": "1", + "services_calls": {} +} \ No newline at end of file diff --git a/src/test/resources/valid_cbs_config.json b/src/test/resources/valid_cbs_config.json new file mode 100644 index 0000000..e2fc650 --- /dev/null +++ b/src/test/resources/valid_cbs_config.json @@ -0,0 +1,23 @@ +[ + { + "ID": "6e331b82-6563-3bf7-4acc-d02d1e042c9b", + "Node": "dcae-bootstrap", + "Address": "10.42.249.191", + "Datacenter": "dc1", + "TaggedAddresses": { + "lan": "10.42.249.191", + "wan": "10.42.249.191" + }, + "NodeMeta": { + "consul-network-segment": "" + }, + "ServiceID": "dcae-cbs0", + "ServiceName": "pm-mapper-service-name", + "ServiceTags": [], + "ServiceAddress": "config-binding-service", + "ServicePort": 10000, + "ServiceEnableTagOverride": false, + "CreateIndex": 124, + "ModifyIndex": 124 + } +] \ No newline at end of file diff --git a/src/test/resources/valid_mapper_config.json b/src/test/resources/valid_mapper_config.json new file mode 100644 index 0000000..7106141 --- /dev/null +++ b/src/test/resources/valid_mapper_config.json @@ -0,0 +1,20 @@ +{ + "pm-mapper-filter": "{ \"filters\":[]}", + "3GPP.schema.file": "{\"3GPP_Schema\":\"./etc/3GPP_relaxed_schema.xsd\"}", + "streams_subscribes": {}, + "streams_publishes": { + "pm_mapper_handle_out": { + "type": "message_router", + "aaf_password": null, + "dmaap_info": { + "topic_url": "https://we-are-message-router.us:3905/events/some-topic", + "client_role": null, + "location": null, + "client_id": null + }, + "aaf_username": null + } + }, + "streams_subscribes.pm_mapper_handle_out.message_router_topic": "unauthenticated.PM_VES_OUTPUT", + "services_calls": {} +} \ No newline at end of file -- cgit