diff options
author | elinuxhenrik <henrik.b.andersson@est.tech> | 2018-08-17 12:34:58 +0200 |
---|---|---|
committer | elinuxhenrik <henrik.b.andersson@est.tech> | 2018-08-20 10:43:58 +0200 |
commit | d661dbcf431f0f02ecf98f748e3516ba0ab23dff (patch) | |
tree | eae40a0aa43e2f4c0b718ac181d7aec462f00697 | |
parent | 604024401a3f7b142880970b06d91888086feac7 (diff) |
Add seed code.
First version based on PRH micro service.
Change-Id: Iea1673a8a1961006b1ea98ef245e213e3652eb82
Issue-ID: DCAEGEN2-638
Signed-off-by: elinuxhenrik <henrik.b.andersson@est.tech>
87 files changed, 7022 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..37f2c431 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +# Compiled class file +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# Intellij IDE +.idea +*.iml + +# Maven +target +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid*
\ No newline at end of file diff --git a/.gitreview b/.gitreview new file mode 100644 index 00000000..fbd81860 --- /dev/null +++ b/.gitreview @@ -0,0 +1,4 @@ +[gerrit] +host=gerrit.onap.org +port=29418 +project=dcaegen2/collectors/datafile.git
\ No newline at end of file diff --git a/INFO.yaml b/INFO.yaml new file mode 100644 index 00000000..72719384 --- /dev/null +++ b/INFO.yaml @@ -0,0 +1,41 @@ +--- +project: 'dcaegen2-collectors-datafile' +project_creation_date: '2018-01-31' +project_category: '' +lifecycle_state: 'Incubation' +project_lead: &onap_dcaegen2_ptl + name: 'Vijay Venkatesh Kumar' + email: 'vv770d@att.com' + id: 'vv770d' + company: 'ATT' + timezone: 'America/New_York' +primary_contact: *onap_dcaegen2_ptl +issue_tracking: + type: 'jira' + url: 'https://jira.onap.org/projects/DCAEGEN2' + key: 'DCAEGEN2' +mailing_list: + type: 'groups.io' + url: 'lists.onap.org' + tag: '<[sub-project_name]>' +realtime_discussion: '' +meetings: + - type: 'zoom' + agenda: 'https://wiki.onap.org/display/DW/DCAE+Project+Meetings' + url: 'https://wiki.onap.org/pages/viewpage.action?pageId=6593119' + server: 'n/a' + channel: 'n/a' + repeats: 'weekly' + time: '13:00 UTC (DST), 15:30 UTC (post DST)' +repositories: + - 'dcaegen2-collectors-hv-ves' + - 'dcaegen2-collectors-datafile' +committers: + - <<: *onap_dcaegen2_ptl + - name: 'Lusheng Ji' + email: 'lji@research.att.com' + company: 'ATT' + id: 'wrider' + timezone: 'America/New_York' +tsc: + approval: 'https://lists.onap.org/pipermail/onap-tsc' diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..22e7ef85 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,36 @@ +/* +* ============LICENSE_START========================================== +* =================================================================== +* Copyright (c) 2018 NOKIA Intellectual Property. All rights reserved. +* =================================================================== +* +* Unless otherwise specified, all software contained herein is licensed +* under the Apache License, Version 2.0 (the "License"); +* you may not use this software except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* +* +* Unless otherwise specified, all documentation contained herein is licensed +* under the Creative Commons License, Attribution 4.0 Intl. (the "License"); +* you may not use this documentation except in compliance with the License. +* You may obtain a copy of the License at +* +* https://creativecommons.org/licenses/by/4.0/ +* +* Unless required by applicable law or agreed to in writing, documentation +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* ============LICENSE_END============================================ +*/
\ No newline at end of file diff --git a/datafile-aai-client/pom.xml b/datafile-aai-client/pom.xml new file mode 100644 index 00000000..bc496562 --- /dev/null +++ b/datafile-aai-client/pom.xml @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ ============LICENSE_START======================================================= + ~ Datafile Collector Service + ~ ================================================================================ + ~ Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + ~ ================================================================================ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ ============LICENSE_END========================================================= + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <artifactId>datafile</artifactId> + <groupId>org.onap.dcaegen2.collectors</groupId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <artifactId>datafile-aai-client</artifactId> + <groupId>org.onap.dcaegen2.collectors.datafile</groupId> + <packaging>jar</packaging> + + + <properties> + <main.basedir>${project.parent.basedir}</main.basedir> + </properties> + <dependencies> + + <!-- DEVELOPMENT DEPENDENCIES --> + <dependency> + <groupId>org.immutables</groupId> + <artifactId>value</artifactId> + </dependency> + <dependency> + <groupId>org.immutables</groupId> + <artifactId>gson</artifactId> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-webflux</artifactId> + <version>5.0.5.RELEASE</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-beans</artifactId> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-reactor-netty</artifactId> + <version>2.0.4.RELEASE</version> + </dependency> + <dependency> + <groupId>org.onap.dcaegen2.collectors.datafile</groupId> + <artifactId>datafile-commons</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + + <!-- LOGGING DEPENDENCIES--> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jul-to-slf4j</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>log4j-over-slf4j</artifactId> + </dependency> + + <!-- TEST DEPENDENCIES--> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.vintage</groupId> + <artifactId>junit-vintage-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.projectreactor</groupId> + <artifactId>reactor-test</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/config/AaiClientConfiguration.java b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/config/AaiClientConfiguration.java new file mode 100644 index 00000000..ce77599a --- /dev/null +++ b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/config/AaiClientConfiguration.java @@ -0,0 +1,67 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.config; + +import java.io.Serializable; + +import java.util.Map; + +import org.immutables.gson.Gson; +import org.immutables.value.Value; +import org.springframework.stereotype.Component; + + +@Component +@Value.Immutable(prehash = true) +@Value.Style(builder = "new") +@Gson.TypeAdapters +public abstract class AaiClientConfiguration implements Serializable { + + private static final long serialVersionUID = 1L; + + @Value.Parameter + public abstract String aaiHost(); + + @Value.Parameter + public abstract Integer aaiPort(); + + @Value.Parameter + public abstract String aaiProtocol(); + + @Value.Parameter + public abstract String aaiUserName(); + + @Value.Parameter + public abstract String aaiUserPassword(); + + @Value.Parameter + public abstract Boolean aaiIgnoreSslCertificateErrors(); + + @Value.Parameter + public abstract String aaiBasePath(); + + @Value.Parameter + public abstract String aaiPnfPath(); + + @Value.Parameter + public abstract Map<String, String> aaiHeaders(); + +} diff --git a/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/AaiRequestException.java b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/AaiRequestException.java new file mode 100644 index 00000000..a30867a2 --- /dev/null +++ b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/AaiRequestException.java @@ -0,0 +1,28 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.exceptions; + +public class AaiRequestException extends Exception { + + public AaiRequestException(String message) { + super(message); + } +} diff --git a/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiClient.java b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiClient.java new file mode 100644 index 00000000..5ab9b4a6 --- /dev/null +++ b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiClient.java @@ -0,0 +1,29 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service; + +import org.apache.http.impl.client.CloseableHttpClient; + +@FunctionalInterface +public interface AaiClient { + CloseableHttpClient getAaiHttpClient(); +} + diff --git a/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiClientImpl.java b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiClientImpl.java new file mode 100644 index 00000000..8af4a13a --- /dev/null +++ b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiClientImpl.java @@ -0,0 +1,94 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service; + +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; + +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.Credentials; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.ssl.SSLContextBuilder; +import org.apache.http.ssl.TrustStrategy; +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.service.AaiClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class AaiClientImpl implements AaiClient { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private AaiClientConfiguration aaiClientConfig; + + + AaiClientImpl(AaiClientConfiguration aaiClientConfiguration) { + this.aaiClientConfig = aaiClientConfiguration; + } + + @Override + public CloseableHttpClient getAaiHttpClient() { + + final HttpClientBuilder httpClientBuilder = HttpClients.custom().useSystemProperties(); + final boolean aaiIgnoreSslCertificateErrors = aaiClientConfig.aaiIgnoreSslCertificateErrors(); + + TrustStrategy acceptingTrustStrategy = (cert, authType) -> true; + + if (aaiIgnoreSslCertificateErrors) { + try { + logger.info("Setting SSL Context for AAI HTTP Client"); + httpClientBuilder.setSSLContext(new SSLContextBuilder() + .loadTrustMaterial(null, acceptingTrustStrategy) + .build()); + + } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) { + logger.error("Exception while setting SSL Context for AAI HTTP Client: {}", e); + } + + httpClientBuilder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE); + } + + final String aaiUserName = aaiClientConfig.aaiUserName(); + + final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + + if (aaiUserName != null) { + final String aaiHost = aaiClientConfig.aaiHost(); + final Integer aaiHostPortNumber = aaiClientConfig.aaiPort(); + final String aaiUserPassword = aaiClientConfig.aaiUserPassword(); + final AuthScope aaiHostPortAuthScope = new AuthScope(aaiHost, aaiHostPortNumber); + final Credentials aaiCredentials = new UsernamePasswordCredentials(aaiUserName, aaiUserPassword); + credentialsProvider.setCredentials(aaiHostPortAuthScope, aaiCredentials); + } + + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + + return httpClientBuilder.build(); + } +} diff --git a/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiConsumerClient.java b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiConsumerClient.java new file mode 100644 index 00000000..ecc9ed2c --- /dev/null +++ b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiConsumerClient.java @@ -0,0 +1,140 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import org.apache.http.HttpEntity; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.util.EntityUtils; +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.model.utils.HttpUtils; +import org.onap.dcaegen2.collectors.datafile.service.AaiClientImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class AaiConsumerClient { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private final CloseableHttpClient closeableHttpClient; + private final String aaiHost; + private final String aaiProtocol; + private final Integer aaiHostPortNumber; + private final String aaiPath; + private final Map<String, String> aaiHeaders; + + /** + * A{@literal &}AI client for consuming data from A{@literal &}AI. + * + * @param aaiClientConfiguration - A{@literal &}AI client config + */ + public AaiConsumerClient(AaiClientConfiguration aaiClientConfiguration) { + closeableHttpClient = new AaiClientImpl(aaiClientConfiguration).getAaiHttpClient(); + aaiHost = aaiClientConfiguration.aaiHost(); + aaiProtocol = aaiClientConfiguration.aaiProtocol(); + aaiHostPortNumber = aaiClientConfiguration.aaiPort(); + aaiPath = aaiClientConfiguration.aaiBasePath() + aaiClientConfiguration.aaiPnfPath(); + aaiHeaders = aaiClientConfiguration.aaiHeaders(); + } + + /** + * Function which call http client for getting object from A{@literal &}AI. + * + * @param consumerDmaapModel - helper object for uri generation + * @return - status code of operation + * @throws IOException - Apache HTTP client exception + */ + public Optional<String> getHttpResponse(ConsumerDmaapModel consumerDmaapModel) throws IOException { + Optional<HttpRequestBase> request = createRequest(consumerDmaapModel); + try { + return closeableHttpClient.execute(request.get(), aaiResponseHandler()); + } catch (IOException e) { + logger.warn("Exception while executing http client: ", e); + throw new IOException(); + } + } + + private URI createAaiExtendedUri(String pnfName) { + + URI extendedUri = null; + + final URIBuilder uriBuilder = new URIBuilder() + .setScheme(aaiProtocol) + .setHost(aaiHost) + .setPort(aaiHostPortNumber) + .setPath(aaiPath + "/" + pnfName); + + try { + extendedUri = uriBuilder.build(); + logger.trace("Building extended URI: {}", extendedUri); + } catch (URISyntaxException e) { + logger.warn("Exception while building extended URI: {}", e); + } + + return extendedUri; + } + + private ResponseHandler<Optional<String>> aaiResponseHandler() { + return httpResponse -> { + final int responseCode = httpResponse.getStatusLine().getStatusCode(); + logger.info("Status code of operation: {}", responseCode); + final HttpEntity responseEntity = httpResponse.getEntity(); + + if (HttpUtils.isSuccessfulResponseCode(responseCode)) { + logger.trace("HTTP response successful."); + final String aaiResponse = EntityUtils.toString(responseEntity); + return Optional.of(aaiResponse); + } else { + String aaiResponse = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; + logger.warn("HTTP response not successful : {}", aaiResponse); + return Optional.of(String.valueOf(responseCode)); + } + }; + } + + private HttpRequestBase createHttpRequest(URI extendedUri) { + return isExtendedUriNotNull(extendedUri) ? new HttpGet(extendedUri) : null; + } + + private Boolean isExtendedUriNotNull(URI extendedUri) { + return extendedUri != null; + } + + private Optional<HttpRequestBase> createRequest(ConsumerDmaapModel consumerDmaapModel) { + final URI extendedUri = createAaiExtendedUri(consumerDmaapModel.getPnfName()); + HttpRequestBase request = createHttpRequest(extendedUri); + aaiHeaders.forEach(Objects.requireNonNull(request)::addHeader); + Objects.requireNonNull(request).addHeader("Content-Type", "application/json"); + return Optional.of(request); + } +} diff --git a/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiExtendedHttpClient.java b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiExtendedHttpClient.java new file mode 100644 index 00000000..3c85b68e --- /dev/null +++ b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiExtendedHttpClient.java @@ -0,0 +1,33 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service; + +import java.net.URISyntaxException; +import java.util.Optional; + +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; + + +@FunctionalInterface +public interface AaiExtendedHttpClient { + + Optional<Integer> getHttpResponse(ConsumerDmaapModel consumerDmaapModel) throws URISyntaxException; +} diff --git a/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiReactiveWebClient.java b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiReactiveWebClient.java new file mode 100644 index 00000000..9a9ff27e --- /dev/null +++ b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/AaiReactiveWebClient.java @@ -0,0 +1,85 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service; + +import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication; + +import java.util.Map; + +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.service.AaiReactiveWebClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + + +public class AaiReactiveWebClient { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + private String aaiUserName; + private String aaiUserPassword; + private Map<String, String> aaiHeaders; + + /** + * Creating AaiReactiveWebClient. + * @param configuration - configuration object + * @return AaiReactiveWebClient + */ + public AaiReactiveWebClient fromConfiguration(AaiClientConfiguration configuration) { + this.aaiUserName = configuration.aaiUserName(); + this.aaiUserPassword = configuration.aaiUserPassword(); + this.aaiHeaders = configuration.aaiHeaders(); + return this; + } + + /** + * Construct Reactive WebClient with appropriate settings. + * + * @return WebClient + */ + public WebClient build() { + return WebClient.builder() + .defaultHeaders(httpHeaders -> httpHeaders.setAll(aaiHeaders)) + .filter(basicAuthentication(aaiUserName, aaiUserPassword)) + .filter(logRequest()) + .filter(logResponse()) + .build(); + } + + private ExchangeFilterFunction logRequest() { + return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> { + logger.info("Request: {} {}", clientRequest.method(), clientRequest.url()); + clientRequest.headers() + .forEach((name, values) -> values.forEach(value -> logger.info("{}={}",name, value))); + return Mono.just(clientRequest); + }); + } + + private ExchangeFilterFunction logResponse() { + return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { + logger.info("Response Status {}", clientResponse.statusCode()); + return Mono.just(clientResponse); + }); + } +} diff --git a/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/producer/AaiProducerReactiveHttpClient.java b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/producer/AaiProducerReactiveHttpClient.java new file mode 100644 index 00000000..65ae40b8 --- /dev/null +++ b/datafile-aai-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/producer/AaiProducerReactiveHttpClient.java @@ -0,0 +1,99 @@ +/*- + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service.producer; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.http.client.utils.URIBuilder; +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.exceptions.AaiRequestException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.producer.AaiProducerReactiveHttpClient; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + + +public class AaiProducerReactiveHttpClient { + + private WebClient webClient; + private final String aaiHost; + private final String aaiProtocol; + private final Integer aaiHostPortNumber; + private final String aaiBasePath; + + + /** + * Constructor of AaiProducerReactiveHttpClient. + * + * @param configuration - AAI producer configuration object + */ + public AaiProducerReactiveHttpClient(AaiClientConfiguration configuration) { + this.aaiHost = configuration.aaiHost(); + this.aaiProtocol = configuration.aaiProtocol(); + this.aaiHostPortNumber = configuration.aaiPort(); + this.aaiBasePath = configuration.aaiBasePath(); + } + + /** + * Function for calling AAI Http producer - patch request to AAI database. + * + * @param consumerDmaapModelMono - object which will be sent to AAI database + * @return status code of operation + */ + public Mono<Integer> getAaiProducerResponse(Mono<ConsumerDmaapModel> consumerDmaapModelMono) { + return consumerDmaapModelMono.flatMap(this::patchAaiRequest); + } + + public AaiProducerReactiveHttpClient createAaiWebClient(WebClient webClient) { + this.webClient = webClient; + return this; + } + + private Mono<Integer> patchAaiRequest(ConsumerDmaapModel dmaapModel) { + try { + return webClient.patch() + .uri(getUri(dmaapModel.getPnfName())) + .body(BodyInserters.fromObject(dmaapModel)) + .retrieve() + .onStatus( + HttpStatus::is4xxClientError, + clientResponse -> Mono.error(new AaiRequestException("HTTP 400")) + ) + .onStatus(HttpStatus::is5xxServerError, + clientResponse -> Mono.error(new AaiRequestException("HTTP 500"))) + .bodyToMono(Integer.class); + } catch (URISyntaxException e) { + return Mono.error(e); + } + } + + URI getUri(String pnfName) throws URISyntaxException { + return new URIBuilder() + .setScheme(aaiProtocol) + .setHost(aaiHost) + .setPort(aaiHostPortNumber) + .setPath(aaiBasePath + "/" + pnfName) + .build(); + } +} diff --git a/datafile-aai-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/AaiConsumerClientTest.java b/datafile-aai-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/AaiConsumerClientTest.java new file mode 100644 index 00000000..719418fb --- /dev/null +++ b/datafile-aai-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/AaiConsumerClientTest.java @@ -0,0 +1,95 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.AaiConsumerClient; + +class AaiConsumerClientTest { + + private static AaiConsumerClient testedObject; + private static AaiClientConfiguration aaiHttpClientConfigurationMock = mock(AaiClientConfiguration.class); + private static CloseableHttpClient closeableHttpClientMock = mock(CloseableHttpClient.class); + private static final String JSON_MESSAGE = "{ \"pnf-id\": \"example-pnf-id-val-22343\", " + + "\"regional-resource-zone\":null, \"ipaddress-v4-oam\": \"11.22.33.44\" }"; + private static ConsumerDmaapModel consumerDmaapModelMock = mock(ConsumerDmaapModel.class); + private static final String PNF_NAME = "nokia-pnf-nhfsadhff"; + + @BeforeAll + static void setup() throws NoSuchFieldException, IllegalAccessException { + + Map<String, String> aaiHeaders = new HashMap<>(); + aaiHeaders.put("X-FromAppId", "datafile"); + aaiHeaders.put("X-TransactionId", "9999"); + aaiHeaders.put("Accept", "application/json"); + aaiHeaders.put("Authorization", "Basic QUFJOkFBSQ=="); + aaiHeaders.put("Real-Time", "true"); + aaiHeaders.put("Content-Type", "application/json"); + + when(aaiHttpClientConfigurationMock.aaiHost()).thenReturn("54.45.33.2"); + when(aaiHttpClientConfigurationMock.aaiProtocol()).thenReturn("https"); + when(aaiHttpClientConfigurationMock.aaiPort()).thenReturn(1234); + when(aaiHttpClientConfigurationMock.aaiUserName()).thenReturn("Datafile"); + when(aaiHttpClientConfigurationMock.aaiUserPassword()).thenReturn("Datafile"); + when(aaiHttpClientConfigurationMock.aaiBasePath()).thenReturn("/aai/v11"); + when(aaiHttpClientConfigurationMock.aaiPnfPath()).thenReturn("/network/pnfs/pnf"); + when(aaiHttpClientConfigurationMock.aaiHeaders()).thenReturn(aaiHeaders); + + when(consumerDmaapModelMock.getPnfName()).thenReturn(PNF_NAME); + + testedObject = new AaiConsumerClient(aaiHttpClientConfigurationMock); + setField(); + } + + + @Test + void getExtendedDetails_returnsSuccess() throws IOException { + + when(closeableHttpClientMock.execute(any(HttpGet.class), any(ResponseHandler.class))) + .thenReturn(Optional.of(JSON_MESSAGE)); + Optional<String> actualResult = testedObject.getHttpResponse(consumerDmaapModelMock); + Assertions.assertEquals(Optional.of(JSON_MESSAGE), actualResult); + } + + + private static void setField() throws NoSuchFieldException, IllegalAccessException { + Field field = testedObject.getClass().getDeclaredField("closeableHttpClient"); + field.setAccessible(true); + field.set(testedObject, closeableHttpClientMock); + } +} diff --git a/datafile-aai-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/AaiHttpClientImplTest.java b/datafile-aai-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/AaiHttpClientImplTest.java new file mode 100644 index 00000000..dcf29549 --- /dev/null +++ b/datafile-aai-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/AaiHttpClientImplTest.java @@ -0,0 +1,55 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.service.AaiClientImpl; + +class AaiHttpClientImplTest { + + private static AaiClientImpl testedObject; + + + @BeforeAll + public static void setup() { + AaiClientConfiguration aaiHttpClientConfigurationMock = mock(AaiClientConfiguration.class); + when(aaiHttpClientConfigurationMock.aaiHost()).thenReturn("54.45.33.2"); + when(aaiHttpClientConfigurationMock.aaiProtocol()).thenReturn("https"); + when(aaiHttpClientConfigurationMock.aaiPort()).thenReturn(1234); + when(aaiHttpClientConfigurationMock.aaiUserName()).thenReturn("PNF"); + when(aaiHttpClientConfigurationMock.aaiUserPassword()).thenReturn("PNF"); + when(aaiHttpClientConfigurationMock.aaiIgnoreSslCertificateErrors()).thenReturn(true); + + testedObject = new AaiClientImpl(aaiHttpClientConfigurationMock); + } + + @Test + public void getAaiHttpClientObject_shouldNotBeNull() { + assertNotNull(testedObject.getAaiHttpClient()); + } +} + diff --git a/datafile-aai-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/producer/AaiProducerReactiveHttpClientTest.java b/datafile-aai-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/producer/AaiProducerReactiveHttpClientTest.java new file mode 100644 index 00000000..65f13553 --- /dev/null +++ b/datafile-aai-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/producer/AaiProducerReactiveHttpClientTest.java @@ -0,0 +1,142 @@ +/*- + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service.producer; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; +import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModelForUnitTest; +import org.onap.dcaegen2.collectors.datafile.service.producer.AaiProducerReactiveHttpClient; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClient.ResponseSpec; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + + +class AaiProducerReactiveHttpClientTest { + + private static AaiProducerReactiveHttpClient aaiProducerReactiveHttpClient; + + private static final Integer SUCCESS_RESPONSE = 200; + + private static AaiClientConfiguration aaiConfigurationMock = mock(AaiClientConfiguration.class); + private static WebClient webClient = mock(WebClient.class); + + private static ConsumerDmaapModel dmaapModel = new ConsumerDmaapModelForUnitTest(); + private static WebClient.RequestBodyUriSpec requestBodyUriSpec; + private static ResponseSpec responseSpec; + + private static Map<String, String> aaiHeaders; + + @BeforeAll + static void setUp() { + setupHeaders(); + + when(aaiConfigurationMock.aaiHost()).thenReturn("54.45.33.2"); + when(aaiConfigurationMock.aaiProtocol()).thenReturn("https"); + when(aaiConfigurationMock.aaiPort()).thenReturn(1234); + when(aaiConfigurationMock.aaiUserName()).thenReturn("Datafile"); + when(aaiConfigurationMock.aaiUserPassword()).thenReturn("Datafile"); + when(aaiConfigurationMock.aaiBasePath()).thenReturn("/aai/v11"); + when(aaiConfigurationMock.aaiPnfPath()).thenReturn("/network/pnfs/pnf"); + when(aaiConfigurationMock.aaiHeaders()).thenReturn(aaiHeaders); + + aaiProducerReactiveHttpClient = new AaiProducerReactiveHttpClient(aaiConfigurationMock); + + webClient = spy(WebClient.builder() + .defaultHeaders(httpHeaders -> httpHeaders.setAll(aaiHeaders)) + .filter(basicAuthentication(aaiConfigurationMock.aaiUserName(), aaiConfigurationMock.aaiUserPassword())) + .build()); + + requestBodyUriSpec = mock(WebClient.RequestBodyUriSpec.class); + responseSpec = mock(ResponseSpec.class); + } + + + @Test + void getAaiProducerResponse_shouldReturn200() { + //given + Mono<Integer> expectedResult = Mono.just(SUCCESS_RESPONSE); + + //when + mockWebClientDependantObject(); + doReturn(expectedResult).when(responseSpec).bodyToMono(Integer.class); + aaiProducerReactiveHttpClient.createAaiWebClient(webClient); + Mono<Integer> response = aaiProducerReactiveHttpClient.getAaiProducerResponse(Mono.just(dmaapModel)); + + //then + StepVerifier.create(response).expectSubscription() + .expectNextMatches(results -> { + Assertions.assertEquals(results, expectedResult.block()); + return true; + }).verifyComplete(); + } + + @Test + void getHttpResponse_whenUriSyntaxExceptionHasBeenThrown() throws URISyntaxException { + ///given + aaiProducerReactiveHttpClient = spy(aaiProducerReactiveHttpClient); + //when + when(webClient.patch()).thenReturn(requestBodyUriSpec); + aaiProducerReactiveHttpClient.createAaiWebClient(webClient); + when(aaiProducerReactiveHttpClient.getUri("pnfName")).thenThrow(URISyntaxException.class); + + //then + StepVerifier.create( + aaiProducerReactiveHttpClient.getAaiProducerResponse( + Mono.just(dmaapModel) + )).expectSubscription().expectError(Exception.class).verify(); + } + + + private void mockWebClientDependantObject() { + WebClient.RequestHeadersSpec requestHeadersSpec = mock(WebClient.RequestHeadersSpec.class); + when(webClient.patch()).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.uri((URI) any())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.body(any())).thenReturn(requestHeadersSpec); + doReturn(responseSpec).when(requestHeadersSpec).retrieve(); + doReturn(responseSpec).when(responseSpec).onStatus(any(), any()); + } + + private static void setupHeaders() { + aaiHeaders = new HashMap<>(); + aaiHeaders.put("X-FromAppId", "Datafile"); + aaiHeaders.put("X-TransactionId", "vv-temp"); + aaiHeaders.put("Accept", "application/json"); + aaiHeaders.put("Real-Time", "true"); + aaiHeaders.put("Content-Type", "application/merge-patch+json"); + } + +} + diff --git a/datafile-app-server/config/application.yaml b/datafile-app-server/config/application.yaml new file mode 100644 index 00000000..6a792346 --- /dev/null +++ b/datafile-app-server/config/application.yaml @@ -0,0 +1,22 @@ +spring: + profiles: + active: prod + main: + web-application-type: none +server: + port: 8433 + ssl: + key-store-type: PKCS12 + key-store-password: nokiapnf + key-store: classpath:keystore.jks + key-password: nokiapnf + keyAlias: tomcat-localhost +logging: + level: + ROOT: ERROR + org.springframework: ERROR + org.springframework.data: ERROR + org.onap.dcaegen2.collectors.datafile: INFO + file: opt/log/application.log +app: + filepath: config/datafile_endpoints.json diff --git a/datafile-app-server/config/keystore b/datafile-app-server/config/keystore Binary files differnew file mode 100644 index 00000000..26a16f75 --- /dev/null +++ b/datafile-app-server/config/keystore diff --git a/datafile-app-server/config/prh_endpoints.json b/datafile-app-server/config/prh_endpoints.json new file mode 100644 index 00000000..772d9708 --- /dev/null +++ b/datafile-app-server/config/prh_endpoints.json @@ -0,0 +1,47 @@ +{ + "configs": { + "dmaap": { + "dmaapConsumerConfiguration": { + "dmaapHostName": "localhost", + "dmaapPortNumber": 2222, + "dmaapTopicName": "/events/unauthenticated.SEC_OTHER_OUTPUT", + "dmaapProtocol": "http", + "dmaapUserName": "admin", + "dmaapUserPassword": "admin", + "dmaapContentType": "application/json", + "consumerId": "c12", + "consumerGroup": "OpenDcae-c12", + "timeoutMS": -1, + "messageLimit": 1 + }, + "dmaapProducerConfiguration": { + "dmaapHostName": "localhost", + "dmaapPortNumber": 2223, + "dmaapTopicName": "/events/unauthenticated.PNF_READY", + "dmaapProtocol": "http", + "dmaapUserName": "admin", + "dmaapUserPassword": "admin", + "dmaapContentType": "application/json" + } + }, + "aai": { + "aaiClientConfiguration": { + "aaiHost": "localhost", + "aaiPort": 8080, + "aaiProtocol": "https", + "aaiUserName": "AAI", + "aaiUserPassword": "AAI", + "aaiIgnoreSSLCertificateErrors": true, + "aaiBasePath": "/aai/v12", + "aaiPnfPath": "/network/pnfs/pnf", + "aaiHeaders": { + "X-FromAppId": "datafile", + "X-TransactionId": "9999", + "Accept": "application/json", + "Real-Time": "true", + "Content-Type":"application/merge-patch+json" + } + } + } + } +}
\ No newline at end of file diff --git a/datafile-app-server/pom.xml b/datafile-app-server/pom.xml new file mode 100644 index 00000000..84c9539b --- /dev/null +++ b/datafile-app-server/pom.xml @@ -0,0 +1,291 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ ============LICENSE_START======================================================= + ~ Datafile Collector Service + ~ ================================================================================ + ~ Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + ~ ================================================================================ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ ============LICENSE_END========================================================= + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>datafile</artifactId> + <groupId>org.onap.dcaegen2.collectors</groupId> + <version>1.0.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>datafile-app-server</artifactId> + <groupId>org.onap.dcaegen2.collectors.datafile</groupId> + <packaging>jar</packaging> + <properties> + <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format> + <project.fatJar.finalName>datafile-app-server</project.fatJar.finalName> + <nexusproxy>https://nexus.onap.org</nexusproxy> + <snapshots.path>content/repositories/snapshots/</snapshots.path> + <releases.path>content/repositories/releases/</releases.path> + <docker.repo.url>${onap.nexus.dockerregistry.daily}</docker.repo.url> + <nexus.staging>false</nexus.staging> + </properties> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <executions> + <execution> + <id>custom-resources</id> + <phase>process-resources</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>${project.build.directory}/config</outputDirectory> + <resources> + <resource> + <directory>${project.basedir}/config</directory> + <filtering>true</filtering> + </resource> + </resources> + <encoding>UTF-8</encoding> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>repackage</goal> + </goals> + </execution> + </executions> + <configuration> + <finalName>${project.fatJar.finalName}</finalName> + <mainClass>org.onap.dcaegen2.collectors.datafile.MainApp</mainClass> + </configuration> + </plugin> + <!-- This plugin may go away in favor of a custom Dockerfile provided by Carsten and co. --> + <plugin> + <groupId>com.spotify</groupId> + <artifactId>docker-maven-plugin</artifactId> + <configuration> + <skipDockerBuild>false</skipDockerBuild> + <imageName> + ${docker.repo.url}/onap/${project.groupId}.${project.artifactId} + </imageName> + <baseImage>openjdk:8-jre-alpine</baseImage> + <entryPoint>["java", "-jar", "/opt/${project.fatJar.finalName}.jar"]</entryPoint> + <resources> + <resource> + <targetPath>/opt</targetPath> + <directory>${project.build.directory}</directory> + <include>${project.fatJar.finalName}.jar</include> + </resource> + <resource> + <targetPath>/config</targetPath> + <directory>${project.build.directory}/config</directory> + <include>*</include> + </resource> + </resources> + <exposes> + <expose>8100</expose> + <expose>8433</expose> + </exposes> + <imageTags> + <imageTag>${project.version}-SNAPSHOT-${maven.build.timestamp}Z</imageTag> + <imageTag>${project.version}</imageTag> + <imageTag>latest</imageTag> + </imageTags> + <serverId>${docker.repo.url}</serverId> + </configuration> + </plugin> + <plugin> + <groupId>org.sonatype.plugins</groupId> + <artifactId>nexus-staging-maven-plugin</artifactId> + <version>1.6.7</version> + <extensions>true</extensions> + <configuration> + <serverId>ecomp-staging</serverId> + <nexusUrl>${nexusproxy}</nexusUrl> + <stagingProfileId>176c31dfe190a</stagingProfileId> + <skipNexusStagingDeployMojo>${nexus.staging}</skipNexusStagingDeployMojo> + </configuration> + </plugin> + </plugins> + </build> + <dependencies> + + <!--DEVELOPMENT DEPENDENCIES--> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-webflux</artifactId> + </dependency> + <dependency> + <groupId>com.spotify</groupId> + <artifactId>docker-maven-plugin</artifactId> + <exclusions> + <exclusion> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>io.projectreactor</groupId> + <artifactId>reactor-core</artifactId> + </dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk15on</artifactId> + </dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcpkix-jdk15on</artifactId> + </dependency> + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-utils</artifactId> + </dependency> + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-core</artifactId> + </dependency> + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-el</artifactId> + </dependency> + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-websocket</artifactId> + </dependency> + <dependency> + <groupId>org.immutables</groupId> + <artifactId>value</artifactId> + </dependency> + <dependency> + <groupId>org.immutables</groupId> + <artifactId>gson</artifactId> + </dependency> + <dependency> + <groupId>org.onap.dcaegen2.collectors.datafile</groupId> + <artifactId>datafile-commons</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + + + <!-- LOGGING DEPENDENCIES--> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jul-to-slf4j</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>log4j-over-slf4j</artifactId> + </dependency> + + <!--TESTS DEPENDENCIES --> + <dependency> + <groupId>io.projectreactor</groupId> + <artifactId>reactor-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.vintage</groupId> + <artifactId>junit-vintage-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-launcher</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.connectors</groupId> + <artifactId>jersey-apache-connector</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + </dependency> + <dependency> + <groupId>org.onap.dcaegen2.collectors.datafile</groupId> + <artifactId>datafile-aai-client</artifactId> + <version>${project.parent.version}</version> + </dependency> + <dependency> + <groupId>org.onap.dcaegen2.collectors.datafile</groupId> + <artifactId>datafile-dmaap-client</artifactId> + <version>${project.parent.version}</version> + </dependency> + + <!--REQUIRED TO GENERATE DOCUMENTATION --> + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger2</artifactId> + </dependency> + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger-ui</artifactId> + </dependency> + </dependencies> + <dependencyManagement> + <dependencies> + <dependency> + <!-- IMPORT DEPENDENCY MANAGEMENT FROM SPRING BOOT --> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-dependencies</artifactId> + <version>2.0.1.RELEASE</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> +</project> diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/MainApp.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/MainApp.java new file mode 100644 index 00000000..63fbccb0 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/MainApp.java @@ -0,0 +1,52 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/23/18 + */ +@SpringBootApplication +@Configuration +@ComponentScan +@EnableAutoConfiguration(exclude = {JacksonAutoConfiguration.class}) +@EnableScheduling +public class MainApp { + + public static void main(String[] args) { + SpringApplication.run(MainApp.class, args); + } + + @Bean + TaskScheduler taskScheduler() { + return new ConcurrentTaskScheduler(); + } +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/AppConfig.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/AppConfig.java new file mode 100644 index 00000000..1fd50c94 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/AppConfig.java @@ -0,0 +1,212 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.configuration; + +import java.util.Optional; + +import java.util.function.Predicate; + +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.config.DmaapConsumerConfiguration; +import org.onap.dcaegen2.collectors.datafile.config.DmaapPublisherConfiguration; +import org.onap.dcaegen2.collectors.datafile.config.ImmutableAaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.config.ImmutableDmaapConsumerConfiguration; +import org.onap.dcaegen2.collectors.datafile.config.ImmutableDmaapPublisherConfiguration; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/9/18 + */ + +@Component +@Configuration +public class AppConfig extends DatafileAppConfig { + + private static Predicate<String> isEmpty = String::isEmpty; + @Value("${dmaap.dmaapConsumerConfiguration.dmaapHostName:}") + public String consumerDmaapHostName; + + @Value("${dmaap.dmaapConsumerConfiguration.dmaapPortNumber:}") + public Integer consumerDmaapPortNumber; + + @Value("${dmaap.dmaapConsumerConfiguration.dmaapTopicName:}") + public String consumerDmaapTopicName; + + @Value("${dmaap.dmaapConsumerConfiguration.dmaapProtocol:}") + public String consumerDmaapProtocol; + + @Value("${dmaap.dmaapConsumerConfiguration.dmaapUserName:}") + public String consumerDmaapUserName; + + @Value("${dmaap.dmaapConsumerConfiguration.dmaapUserPassword:}") + public String consumerDmaapUserPassword; + + @Value("${dmaap.dmaapConsumerConfiguration.dmaapContentType:}") + public String consumerDmaapContentType; + + @Value("${dmaap.dmaapConsumerConfiguration.consumerId:}") + public String consumerId; + + @Value("${dmaap.dmaapConsumerConfiguration.consumerGroup:}") + public String consumerGroup; + + @Value("${dmaap.dmaapConsumerConfiguration.timeoutMs:}") + public Integer consumerTimeoutMs; + + @Value("${dmaap.dmaapConsumerConfiguration.message-limit:}") + public Integer consumerMessageLimit; + + @Value("${dmaap.dmaapProducerConfiguration.dmaapHostName:}") + public String producerDmaapHostName; + + @Value("${dmaap.dmaapProducerConfiguration.dmaapPortNumber:}") + public Integer producerDmaapPortNumber; + + @Value("${dmaap.dmaapProducerConfiguration.dmaapTopicName:}") + public String producerDmaapTopicName; + + @Value("${dmaap.dmaapProducerConfiguration.dmaapProtocol:}") + public String producerDmaapProtocol; + + @Value("${dmaap.dmaapProducerConfiguration.dmaapUserName:}") + public String producerDmaapUserName; + + @Value("${dmaap.dmaapProducerConfiguration.dmaapUserPassword:}") + public String producerDmaapUserPassword; + + @Value("${dmaap.dmaapProducerConfiguration.dmaapContentType:}") + public String producerDmaapContentType; + + @Value("${aai.aaiClientConfiguration.aaiHost:}") + public String aaiHost; + + @Value("${aai.aaiClientConfiguration.aaiHostPortNumber:}") + public Integer aaiPort; + + @Value("${aai.aaiClientConfiguration.aaiProtocol:}") + public String aaiProtocol; + + @Value("${aai.aaiClientConfiguration.aaiUserName:}") + public String aaiUserName; + + @Value("${aai.aaiClientConfiguration.aaiUserPassword:}") + public String aaiUserPassword; + + @Value("${aai.aaiClientConfiguration.aaiIgnoreSslCertificateErrors:}") + public Boolean aaiIgnoreSslCertificateErrors; + + @Value("${aai.aaiClientConfiguration.aaiBasePath:}") + public String aaiBasePath; + + @Value("${aai.aaiClientConfiguration.aaiPnfPath:}") + public String aaiPnfPath; + + @Override + public DmaapConsumerConfiguration getDmaapConsumerConfiguration() { + return new ImmutableDmaapConsumerConfiguration.Builder() + .dmaapUserPassword( + Optional.ofNullable(consumerDmaapUserPassword).filter(isEmpty.negate()) + .orElse(dmaapConsumerConfiguration.dmaapUserPassword())) + .dmaapUserName( + Optional.ofNullable(consumerDmaapUserName).filter(isEmpty.negate()) + .orElse(dmaapConsumerConfiguration.dmaapUserName())) + .dmaapHostName( + Optional.ofNullable(consumerDmaapHostName).filter(isEmpty.negate()) + .orElse(dmaapConsumerConfiguration.dmaapHostName())) + .dmaapPortNumber( + Optional.ofNullable(consumerDmaapPortNumber).filter(p -> !p.toString().isEmpty()) + .orElse(dmaapConsumerConfiguration.dmaapPortNumber())) + .dmaapProtocol( + Optional.ofNullable(consumerDmaapProtocol).filter(isEmpty.negate()) + .orElse(dmaapConsumerConfiguration.dmaapProtocol())) + .dmaapContentType( + Optional.ofNullable(consumerDmaapContentType).filter(isEmpty.negate()) + .orElse(dmaapConsumerConfiguration.dmaapContentType())) + .dmaapTopicName( + Optional.ofNullable(consumerDmaapTopicName).filter(isEmpty.negate()) + .orElse(dmaapConsumerConfiguration.dmaapTopicName())) + .messageLimit( + Optional.ofNullable(consumerMessageLimit).filter(p -> !p.toString().isEmpty()) + .orElse(dmaapConsumerConfiguration.messageLimit())) + .timeoutMs(Optional.ofNullable(consumerTimeoutMs).filter(p -> !p.toString().isEmpty()) + .orElse(dmaapConsumerConfiguration.timeoutMs())) + .consumerGroup(Optional.ofNullable(consumerGroup).filter(isEmpty.negate()) + .orElse(dmaapConsumerConfiguration.consumerGroup())) + .consumerId(Optional.ofNullable(consumerId).filter(isEmpty.negate()) + .orElse(dmaapConsumerConfiguration.consumerId())) + .build(); + } + + @Override + public AaiClientConfiguration getAaiClientConfiguration() { + return new ImmutableAaiClientConfiguration.Builder() + .aaiHost(Optional.ofNullable(aaiHost).filter(isEmpty.negate()).orElse(aaiClientConfiguration.aaiHost())) + .aaiPort( + Optional.ofNullable(aaiPort).filter(p -> !p.toString().isEmpty()) + .orElse(aaiClientConfiguration.aaiPort())) + .aaiIgnoreSslCertificateErrors( + Optional.ofNullable(aaiIgnoreSslCertificateErrors).filter(p -> !p.toString().isEmpty()) + .orElse(aaiClientConfiguration.aaiIgnoreSslCertificateErrors())) + .aaiProtocol( + Optional.ofNullable(aaiProtocol).filter(isEmpty.negate()).orElse(aaiClientConfiguration.aaiProtocol())) + .aaiUserName( + Optional.ofNullable(aaiUserName).filter(isEmpty.negate()).orElse(aaiClientConfiguration.aaiUserName())) + .aaiUserPassword(Optional.ofNullable(aaiUserPassword).filter(isEmpty.negate()) + .orElse(aaiClientConfiguration.aaiUserPassword())) + .aaiBasePath(Optional.ofNullable(aaiBasePath).filter(isEmpty.negate()) + .orElse(aaiClientConfiguration.aaiBasePath())) + .aaiPnfPath( + Optional.ofNullable(aaiPnfPath).filter(isEmpty.negate()).orElse(aaiClientConfiguration.aaiPnfPath())) + .aaiHeaders(aaiClientConfiguration.aaiHeaders()) + .build(); + } + + @Override + public DmaapPublisherConfiguration getDmaapPublisherConfiguration() { + return new ImmutableDmaapPublisherConfiguration.Builder() + .dmaapContentType( + Optional.ofNullable(producerDmaapContentType).filter(isEmpty.negate()) + .orElse(dmaapPublisherConfiguration.dmaapContentType())) + .dmaapHostName( + Optional.ofNullable(producerDmaapHostName).filter(isEmpty.negate()) + .orElse(dmaapPublisherConfiguration.dmaapHostName())) + .dmaapPortNumber( + Optional.ofNullable(producerDmaapPortNumber).filter(p -> !p.toString().isEmpty()) + .orElse(dmaapPublisherConfiguration.dmaapPortNumber())) + .dmaapProtocol( + Optional.ofNullable(producerDmaapProtocol).filter(isEmpty.negate()) + .orElse(dmaapPublisherConfiguration.dmaapProtocol())) + .dmaapTopicName( + Optional.ofNullable(producerDmaapTopicName).filter(isEmpty.negate()) + .orElse(dmaapPublisherConfiguration.dmaapTopicName())) + .dmaapUserName( + Optional.ofNullable(producerDmaapUserName).filter(isEmpty.negate()) + .orElse(dmaapPublisherConfiguration.dmaapUserName())) + .dmaapUserPassword( + Optional.ofNullable(producerDmaapUserPassword).filter(isEmpty.negate()) + .orElse(dmaapPublisherConfiguration.dmaapUserPassword())) + .build(); + } + +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/Config.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/Config.java new file mode 100644 index 00000000..5c6f1512 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/Config.java @@ -0,0 +1,39 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.configuration; + +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.config.DmaapConsumerConfiguration; +import org.onap.dcaegen2.collectors.datafile.config.DmaapPublisherConfiguration; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/25/18 + */ +public interface Config { + + DmaapConsumerConfiguration getDmaapConsumerConfiguration(); + + AaiClientConfiguration getAaiClientConfiguration(); + + DmaapPublisherConfiguration getDmaapPublisherConfiguration(); + + void initFileStreamReader(); +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/DatafileAppConfig.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/DatafileAppConfig.java new file mode 100644 index 00000000..169bf8ed --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/DatafileAppConfig.java @@ -0,0 +1,143 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.configuration; + +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapterFactory; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import java.nio.charset.StandardCharsets; +import java.util.ServiceLoader; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.config.DmaapConsumerConfiguration; +import org.onap.dcaegen2.collectors.datafile.config.DmaapPublisherConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/9/18 + */ +@Configuration +@EnableConfigurationProperties +@ConfigurationProperties("app") +public abstract class DatafileAppConfig implements Config { + + private static final String CONFIG = "configs"; + private static final String AAI = "aai"; + private static final String DMAAP = "dmaap"; + private static final String AAI_CONFIG = "aaiClientConfiguration"; + private static final String DMAAP_PRODUCER = "dmaapProducerConfiguration"; + private static final String DMAAP_CONSUMER = "dmaapConsumerConfiguration"; + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + AaiClientConfiguration aaiClientConfiguration; + + DmaapConsumerConfiguration dmaapConsumerConfiguration; + + DmaapPublisherConfiguration dmaapPublisherConfiguration; + + @NotEmpty + private String filepath; + + + @Override + public DmaapConsumerConfiguration getDmaapConsumerConfiguration() { + return dmaapConsumerConfiguration; + } + + @Override + public AaiClientConfiguration getAaiClientConfiguration() { + return aaiClientConfiguration; + } + + @Override + public DmaapPublisherConfiguration getDmaapPublisherConfiguration() { + return dmaapPublisherConfiguration; + } + + @Override + public void initFileStreamReader() { + + GsonBuilder gsonBuilder = new GsonBuilder(); + ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory); + JsonParser parser = new JsonParser(); + JsonObject jsonObject; + try (InputStream inputStream = getInputStream(filepath)) { + JsonElement rootElement = getJsonElement(parser, inputStream); + if (rootElement.isJsonObject()) { + jsonObject = rootElement.getAsJsonObject(); + aaiClientConfiguration = deserializeType(gsonBuilder, + jsonObject.getAsJsonObject(CONFIG).getAsJsonObject(AAI).getAsJsonObject(AAI_CONFIG), + AaiClientConfiguration.class); + + dmaapConsumerConfiguration = deserializeType(gsonBuilder, + jsonObject.getAsJsonObject(CONFIG).getAsJsonObject(DMAAP).getAsJsonObject(DMAAP_CONSUMER), + DmaapConsumerConfiguration.class); + + dmaapPublisherConfiguration = deserializeType(gsonBuilder, + jsonObject.getAsJsonObject(CONFIG).getAsJsonObject(DMAAP).getAsJsonObject(DMAAP_PRODUCER), + DmaapPublisherConfiguration.class); + } + } catch (IOException e) { + logger.warn("Problem with file loading, file: {}", filepath, e); + } catch (JsonSyntaxException e) { + logger.warn("Problem with Json deserialization", e); + } + } + + JsonElement getJsonElement(JsonParser parser, InputStream inputStream) { + return parser.parse(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); + } + + private <T> T deserializeType(@NotNull GsonBuilder gsonBuilder, @NotNull JsonObject jsonObject, + @NotNull Class<T> type) { + return gsonBuilder.create().fromJson(jsonObject, type); + } + + InputStream getInputStream(@NotNull String filepath) throws IOException { + return new BufferedInputStream(new FileInputStream(filepath)); + } + + String getFilepath() { + return this.filepath; + } + + public void setFilepath(String filepath) { + this.filepath = filepath; + } + +}
\ No newline at end of file diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/SchedulerConfig.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/SchedulerConfig.java new file mode 100644 index 00000000..823fe732 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/SchedulerConfig.java @@ -0,0 +1,88 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.configuration; + +import io.swagger.annotations.ApiOperation; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ScheduledFuture; +import javax.annotation.PostConstruct; + +import org.onap.dcaegen2.collectors.datafile.tasks.ScheduledTasks; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.annotation.EnableScheduling; +import reactor.core.publisher.Mono; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 6/13/18 + */ +@Configuration +@EnableScheduling +public class SchedulerConfig extends DatafileAppConfig { + + private static final int SCHEDULING_DELAY = 2000; + private static volatile List<ScheduledFuture> scheduledFutureList = new ArrayList<>(); + + private final TaskScheduler taskScheduler; + private final ScheduledTasks scheduledTask; + + @Autowired + public SchedulerConfig(TaskScheduler taskScheduler, ScheduledTasks scheduledTask) { + this.taskScheduler = taskScheduler; + this.scheduledTask = scheduledTask; + } + + /** + * Function which have to stop tasks execution. + * + * @return response entity about status of cancellation operation + */ + @ApiOperation(value = "Get response on stopping task execution") + public synchronized Mono<ResponseEntity<String>> getResponseFromCancellationOfTasks() { + scheduledFutureList.forEach(x -> x.cancel(false)); + scheduledFutureList.clear(); + return Mono.defer(() -> + Mono.just(new ResponseEntity<>("Datafile Service has already been stopped!", HttpStatus.CREATED)) + ); + } + + /** + * Function for starting scheduling Datafile workflow. + * + * @return status of operation execution: true - started, false - not started + */ + @PostConstruct + @ApiOperation(value = "Start task if possible") + public synchronized boolean tryToStartTask() { + if (scheduledFutureList.isEmpty()) { + scheduledFutureList.add(taskScheduler + .scheduleWithFixedDelay(scheduledTask::scheduleMainDatafileEventTask, SCHEDULING_DELAY)); + return true; + } else { + return false; + } + + } +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/SwaggerConfig.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/SwaggerConfig.java new file mode 100644 index 00000000..c45b136a --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/SwaggerConfig.java @@ -0,0 +1,82 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + + +@EnableSwagger2 +@Configuration +@Profile("prod") +public class SwaggerConfig extends WebMvcConfigurationSupport { + + private static final String PACKAGE_PATH = "org.onap.dcaegen2.collectors.datafile"; + private static final String API_TITLE = "Datafile app server"; + private static final String DESCRIPTION = "This page lists all the rest apis for Datafile app server."; + private static final String VERSION = "1.0"; + private static final String RESOURCES_PATH = "classpath:/META-INF/resources/"; + private static final String WEBJARS_PATH = RESOURCES_PATH + "webjars/"; + private static final String SWAGGER_UI = "swagger-ui.html"; + private static final String WEBJARS = "/webjars/**"; + + /** + * Swagger configuration function for hosting it next to spring http website. + * @return Docket + */ + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.basePackage(PACKAGE_PATH)) + .paths(PathSelectors.any()) + .build(); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title(API_TITLE) + .description(DESCRIPTION) + .version(VERSION) + .build(); + } + + + @Override + protected void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler(SWAGGER_UI) + .addResourceLocations(RESOURCES_PATH); + + registry.addResourceHandler(WEBJARS) + .addResourceLocations(WEBJARS_PATH); + } +}
\ No newline at end of file diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/TomcatHttpConfig.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/TomcatHttpConfig.java new file mode 100644 index 00000000..b6231418 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/configuration/TomcatHttpConfig.java @@ -0,0 +1,55 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.configuration; + +import org.apache.catalina.connector.Connector; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/18/18 + */ +@Configuration +public class TomcatHttpConfig { + + /** + * Class for setting up hosting Datafile on http/https. + * + * @return ServletWebServerFactory + */ + @Bean + public ServletWebServerFactory servletContainer() { + TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); + tomcat.addAdditionalTomcatConnectors(getHttpConnector()); + return tomcat; + } + + private Connector getHttpConnector() { + Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL); + connector.setScheme("http"); + connector.setPort(8100); + connector.setSecure(false); + return connector; + } + +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/controllers/HeartbeatController.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/controllers/HeartbeatController.java new file mode 100644 index 00000000..070fe591 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/controllers/HeartbeatController.java @@ -0,0 +1,65 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.controllers; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/19/18 + */ +@RestController +@Api(value = "HeartbeatController", description = "Check liveness of Datafile service") +public class HeartbeatController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + /** + * Endpoint for checking that Datafile is alive. + * + * @return HTTP Status Code + */ + @RequestMapping(value = "heartbeat", method = RequestMethod.GET) + @ApiOperation(value = "Returns liveness of Datafile service") + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Datafile sevice is living"), + @ApiResponse(code = 401, message = "You are not authorized to view the resource"), + @ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"), + @ApiResponse(code = 404, message = "The resource you were trying to reach is not found") + } + ) + public Mono<ResponseEntity<String>> heartbeat() { + logger.trace("Receiving heartbeat request"); + return Mono.defer(() -> + Mono.just(new ResponseEntity<>("alive", HttpStatus.OK)) + ); + } +}
\ No newline at end of file diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/controllers/ScheduleController.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/controllers/ScheduleController.java new file mode 100644 index 00000000..f3cf354f --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/controllers/ScheduleController.java @@ -0,0 +1,75 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.controllers; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import org.onap.dcaegen2.collectors.datafile.configuration.SchedulerConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/5/18 + */ +@RestController +@Api(value = "ScheduleController", description = "Schedule Controller") +public class ScheduleController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private final SchedulerConfig schedulerConfig; + + @Autowired + public ScheduleController(SchedulerConfig schedulerConfig) { + this.schedulerConfig = schedulerConfig; + } + + @RequestMapping(value = "start", method = RequestMethod.GET) + @ApiOperation(value = "Start scheduling worker request") + public Mono<ResponseEntity<String>> startTasks() { + logger.trace("Receiving start scheduling worker request"); + return Mono.fromSupplier(schedulerConfig::tryToStartTask).map(this::createStartTaskResponse); + } + + @RequestMapping(value = "stopDatafile", method = RequestMethod.GET) + @ApiOperation(value = "Receiving stop scheduling worker request") + public Mono<ResponseEntity<String>> stopTask() { + logger.trace("Receiving stop scheduling worker request"); + return schedulerConfig.getResponseFromCancellationOfTasks(); + } + + @ApiOperation(value = "Sends success or error response on starting task execution") + private ResponseEntity<String> createStartTaskResponse(boolean wasScheduled) { + if (wasScheduled) { + return new ResponseEntity<>("Datafile Service has been started!", HttpStatus.CREATED); + } else { + return new ResponseEntity<>("Datafile Service is still running!", HttpStatus.NOT_ACCEPTABLE); + } + } +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/AaiNotFoundException.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/AaiNotFoundException.java new file mode 100644 index 00000000..a83b5bd6 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/AaiNotFoundException.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.exceptions; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/23/18 + */ +public class AaiNotFoundException extends DatafileTaskException { + + public AaiNotFoundException(String message) { + super(message); + } +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DatafileTaskException.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DatafileTaskException.java new file mode 100644 index 00000000..41f77332 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DatafileTaskException.java @@ -0,0 +1,35 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.exceptions; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/13/18 + */ +public class DatafileTaskException extends Exception { + + public DatafileTaskException() { + super(); + } + + public DatafileTaskException(String message) { + super(message); + } +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DmaapEmptyResponseException.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DmaapEmptyResponseException.java new file mode 100644 index 00000000..d9f6f873 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DmaapEmptyResponseException.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.exceptions; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 6/13/18 + */ +public class DmaapEmptyResponseException extends DatafileTaskException { + + public DmaapEmptyResponseException() { + super(); + } +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DmaapNotFoundException.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DmaapNotFoundException.java new file mode 100644 index 00000000..ebff8ae3 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/exceptions/DmaapNotFoundException.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.exceptions; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/13/18 + */ +public class DmaapNotFoundException extends DatafileTaskException { + + public DmaapNotFoundException(String message) { + super(message); + } +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/service/DmaapConsumerJsonParser.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/service/DmaapConsumerJsonParser.java new file mode 100644 index 00000000..aeaf0da1 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/service/DmaapConsumerJsonParser.java @@ -0,0 +1,130 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.util.Optional; +import java.util.stream.StreamSupport; + +import org.onap.dcaegen2.collectors.datafile.exceptions.DmaapEmptyResponseException; +import org.onap.dcaegen2.collectors.datafile.exceptions.DmaapNotFoundException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.model.ImmutableConsumerDmaapModel; +import org.springframework.util.StringUtils; +import reactor.core.publisher.Mono; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 5/8/18 + */ +public class DmaapConsumerJsonParser { + + private static final String EVENT = "event"; + private static final String OTHER_FIELDS = "otherFields"; + private static final String PNF_OAM_IPV_4_ADDRESS = "pnfOamIpv4Address"; + private static final String PNF_OAM_IPV_6_ADDRESS = "pnfOamIpv6Address"; + private static final String PNF_VENDOR_NAME = "pnfVendorName"; + private static final String PNF_SERIAL_NUMBER = "pnfSerialNumber"; + + /** + * Extract info from string and create @see {@link org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel}. + * + * @param monoMessage - results from DMaaP + * @return reactive DMaaPModel + */ + public Mono<ConsumerDmaapModel> getJsonObject(Mono<String> monoMessage) { + return monoMessage + .flatMap(this::getJsonParserMessage) + .flatMap(this::createJsonConsumerModel); + } + + private Mono<JsonElement> getJsonParserMessage(String message) { + return StringUtils.isEmpty(message) ? Mono.error(new DmaapEmptyResponseException()) + : Mono.fromSupplier(() -> new JsonParser().parse(message)); + } + + private Mono<ConsumerDmaapModel> createJsonConsumerModel(JsonElement jsonElement) { + return jsonElement.isJsonObject() + ? create(Mono.fromSupplier(jsonElement::getAsJsonObject)) + : getConsumerDmaapModelFromJsonArray(jsonElement); + } + + private Mono<ConsumerDmaapModel> getConsumerDmaapModelFromJsonArray(JsonElement jsonElement) { + return create( + Mono.fromCallable(() -> StreamSupport.stream(jsonElement.getAsJsonArray().spliterator(), false).findFirst() + .flatMap(this::getJsonObjectFromAnArray) + .orElseThrow(DmaapEmptyResponseException::new))); + } + + public Optional<JsonObject> getJsonObjectFromAnArray(JsonElement element) { + return Optional.of(new JsonParser().parse(element.getAsString()).getAsJsonObject()); + } + + private Mono<ConsumerDmaapModel> create(Mono<JsonObject> jsonObject) { + return jsonObject.flatMap(monoJsonP -> + !containsHeader(monoJsonP) ? Mono.error(new DmaapNotFoundException("Incorrect JsonObject - missing header")) + : transform(monoJsonP)); + } + + private Mono<ConsumerDmaapModel> transform(JsonObject monoJsonP) { + monoJsonP = monoJsonP.getAsJsonObject(EVENT).getAsJsonObject(OTHER_FIELDS); + String pnfVendorName = getValueFromJson(monoJsonP, PNF_VENDOR_NAME); + String pnfSerialNumber = getValueFromJson(monoJsonP, PNF_SERIAL_NUMBER); + String pnfOamIpv4Address = getValueFromJson(monoJsonP, PNF_OAM_IPV_4_ADDRESS); + String pnfOamIpv6Address = getValueFromJson(monoJsonP, PNF_OAM_IPV_6_ADDRESS); + return + (!vendorAndSerialNotEmpty(pnfSerialNumber, pnfVendorName) || !ipPropertiesNotEmpty(pnfOamIpv4Address, + pnfOamIpv6Address)) + ? Mono.error(new DmaapNotFoundException("Incorrect json, consumerDmaapModel can not be created: " + + printMessage(pnfVendorName, pnfSerialNumber, pnfOamIpv4Address, pnfOamIpv6Address))) : + Mono.just(ImmutableConsumerDmaapModel.builder() + .pnfName(pnfVendorName.substring(0, Math.min(pnfVendorName.length(), 3)).toUpperCase() + .concat(pnfSerialNumber)).ipv4(pnfOamIpv4Address) + .ipv6(pnfOamIpv6Address).build()); + } + + private String getValueFromJson(JsonObject jsonObject, String jsonKey) { + return jsonObject.has(jsonKey) ? jsonObject.get(jsonKey).getAsString() : ""; + } + + private boolean vendorAndSerialNotEmpty(String pnfSerialNumber, String pnfVendorName) { + return (!StringUtils.isEmpty(pnfSerialNumber) && !StringUtils.isEmpty(pnfVendorName)); + } + + private boolean ipPropertiesNotEmpty(String ipv4, String ipv6) { + return (!StringUtils.isEmpty(ipv4)) || !(StringUtils.isEmpty(ipv6)); + } + + private boolean containsHeader(JsonObject jsonObject) { + return jsonObject.has(EVENT) && jsonObject.getAsJsonObject(EVENT).has(OTHER_FIELDS); + } + + private String printMessage(String pnfVendorName, String pnfSerialNumber, String pnfOamIpv4Address, + String pnfOamIpv6Address) { + return String.format("%n{" + + "\"pnfVendorName\" : \"%s\"," + + "\"pnfSerialNumber\": \"%s\"," + + "\"pnfOamIpv4Address\": \"%s\"," + + "\"pnfOamIpv6Address\": \"%s\"" + + "%n}", pnfVendorName, pnfSerialNumber, pnfOamIpv4Address, pnfOamIpv6Address); + } +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiConsumerTask.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiConsumerTask.java new file mode 100644 index 00000000..8083a255 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiConsumerTask.java @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import java.util.Optional; + +import org.onap.dcaegen2.collectors.datafile.exceptions.AaiNotFoundException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.AaiConsumerClient; + +public abstract class AaiConsumerTask { + + abstract Optional<String> consume(ConsumerDmaapModel message) throws AaiNotFoundException; + + abstract AaiConsumerClient resolveClient(); + + protected abstract String execute(ConsumerDmaapModel consumerDmaapModel) throws AaiNotFoundException; +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiConsumerTaskImpl.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiConsumerTaskImpl.java new file mode 100644 index 00000000..d487b6b2 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiConsumerTaskImpl.java @@ -0,0 +1,78 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import java.io.IOException; +import java.util.Optional; + +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.configuration.Config; +import org.onap.dcaegen2.collectors.datafile.exceptions.AaiNotFoundException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.AaiConsumerClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class AaiConsumerTaskImpl extends AaiConsumerTask { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private final Config datafileAppConfig; + private AaiConsumerClient aaiConsumerClient; + + @Autowired + public AaiConsumerTaskImpl(AppConfig datafileAppConfig) { + this.datafileAppConfig = datafileAppConfig; + } + + @Override + Optional<String> consume(ConsumerDmaapModel consumerDmaapModel) throws AaiNotFoundException { + logger.trace("Method called with arg {}", consumerDmaapModel); + try { + return aaiConsumerClient.getHttpResponse(consumerDmaapModel); + } catch (IOException e) { + logger.warn("Get request not successful", e); + throw new AaiNotFoundException("Get request not successful"); + } + } + + @Override + public String execute(ConsumerDmaapModel consumerDmaapModel) throws AaiNotFoundException { + consumerDmaapModel = Optional.ofNullable(consumerDmaapModel) + .orElseThrow(() -> new AaiNotFoundException("Invoked null object to AAI task")); + logger.trace("Method called with arg {}", consumerDmaapModel); + aaiConsumerClient = resolveClient(); + return consume(consumerDmaapModel).orElseThrow(() -> new AaiNotFoundException("Null response code")); + } + + protected AaiClientConfiguration resolveConfiguration() { + return datafileAppConfig.getAaiClientConfiguration(); + } + + @Override + AaiConsumerClient resolveClient() { + return Optional.ofNullable(aaiConsumerClient).orElseGet(() -> new AaiConsumerClient(resolveConfiguration())); + } +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiProducerTask.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiProducerTask.java new file mode 100644 index 00000000..ca2d03da --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiProducerTask.java @@ -0,0 +1,49 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.exceptions.AaiNotFoundException; +import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.AaiReactiveWebClient; +import org.onap.dcaegen2.collectors.datafile.service.producer.AaiProducerReactiveHttpClient; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/13/18 + */ +public abstract class AaiProducerTask { + + abstract Mono<ConsumerDmaapModel> publish(Mono<ConsumerDmaapModel> message) throws AaiNotFoundException; + + abstract AaiProducerReactiveHttpClient resolveClient(); + + protected abstract AaiClientConfiguration resolveConfiguration(); + + protected abstract Mono<ConsumerDmaapModel> execute(Mono<ConsumerDmaapModel> consumerDmaapModel) + throws DatafileTaskException; + + WebClient buildWebClient() { + return new AaiReactiveWebClient().fromConfiguration(resolveConfiguration()).build(); + } +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiProducerTaskImpl.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiProducerTaskImpl.java new file mode 100644 index 00000000..9d888aa7 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiProducerTaskImpl.java @@ -0,0 +1,89 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.configuration.Config; +import org.onap.dcaegen2.collectors.datafile.exceptions.AaiNotFoundException; +import org.onap.dcaegen2.collectors.datafile.exceptions.DmaapNotFoundException; +import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.model.utils.HttpUtils; +import org.onap.dcaegen2.collectors.datafile.service.producer.AaiProducerReactiveHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/13/18 + */ +@Component +public class AaiProducerTaskImpl extends + AaiProducerTask { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private final Config datafileAppConfig; + private AaiProducerReactiveHttpClient aaiProducerReactiveHttpClient; + + @Autowired + public AaiProducerTaskImpl(AppConfig datafileAppConfig) { + this.datafileAppConfig = datafileAppConfig; + } + + @Override + Mono<ConsumerDmaapModel> publish(Mono<ConsumerDmaapModel> consumerDmaapModel) { + logger.info("Sending PNF model to AAI {}", consumerDmaapModel); + return aaiProducerReactiveHttpClient.getAaiProducerResponse(consumerDmaapModel) + .flatMap(response -> { + if (HttpUtils.isSuccessfulResponseCode(response)) { + return consumerDmaapModel; + } + return Mono + .error(new AaiNotFoundException("Incorrect response code for continuation of tasks workflow")); + }); + } + + @Override + AaiProducerReactiveHttpClient resolveClient() { + return aaiProducerReactiveHttpClient == null ? new AaiProducerReactiveHttpClient(resolveConfiguration()) + .createAaiWebClient(buildWebClient()) : aaiProducerReactiveHttpClient; + } + + @Override + protected AaiClientConfiguration resolveConfiguration() { + return datafileAppConfig.getAaiClientConfiguration(); + } + + @Override + protected Mono<ConsumerDmaapModel> execute(Mono<ConsumerDmaapModel> consumerDmaapModel) throws DatafileTaskException { + if (consumerDmaapModel == null) { + throw new DmaapNotFoundException("Invoked null object to DMaaP task"); + } + aaiProducerReactiveHttpClient = resolveClient(); + logger.trace("Method called with arg {}", consumerDmaapModel); + return publish(consumerDmaapModel); + + } +}
\ No newline at end of file diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTask.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTask.java new file mode 100644 index 00000000..a5764704 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTask.java @@ -0,0 +1,49 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import org.onap.dcaegen2.collectors.datafile.config.DmaapConsumerConfiguration; +import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.DMaaPReactiveWebClient; +import org.onap.dcaegen2.collectors.datafile.service.consumer.DMaaPConsumerReactiveHttpClient; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/13/18 + */ +abstract class DmaapConsumerTask { + + abstract Mono<ConsumerDmaapModel> consume(Mono<String> message) throws DatafileTaskException; + + abstract DMaaPConsumerReactiveHttpClient resolveClient(); + + abstract void initConfigs(); + + protected abstract DmaapConsumerConfiguration resolveConfiguration(); + + protected abstract Mono<ConsumerDmaapModel> execute(String object) throws DatafileTaskException; + + WebClient buildWebClient() { + return new DMaaPReactiveWebClient().fromConfiguration(resolveConfiguration()).build(); + } +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTaskImpl.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTaskImpl.java new file mode 100644 index 00000000..8d45a7fd --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTaskImpl.java @@ -0,0 +1,86 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import org.onap.dcaegen2.collectors.datafile.config.DmaapConsumerConfiguration; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.configuration.Config; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.DmaapConsumerJsonParser; +import org.onap.dcaegen2.collectors.datafile.service.consumer.DMaaPConsumerReactiveHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/23/18 + */ +@Component +public class DmaapConsumerTaskImpl extends DmaapConsumerTask { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final Config datafileAppConfig; + private DmaapConsumerJsonParser dmaapConsumerJsonParser; + private DMaaPConsumerReactiveHttpClient dmaaPConsumerReactiveHttpClient; + + @Autowired + public DmaapConsumerTaskImpl(AppConfig datafileAppConfig) { + this.datafileAppConfig = datafileAppConfig; + this.dmaapConsumerJsonParser = new DmaapConsumerJsonParser(); + } + + DmaapConsumerTaskImpl(AppConfig datafileAppConfig, DmaapConsumerJsonParser dmaapConsumerJsonParser) { + this.datafileAppConfig = datafileAppConfig; + this.dmaapConsumerJsonParser = dmaapConsumerJsonParser; + } + + @Override + Mono<ConsumerDmaapModel> consume(Mono<String> message) { + logger.info("Consumed model from DMaaP: {}", message); + return dmaapConsumerJsonParser.getJsonObject(message); + } + + @Override + public Mono<ConsumerDmaapModel> execute(String object) { + dmaaPConsumerReactiveHttpClient = resolveClient(); + logger.trace("Method called with arg {}", object); + return consume((dmaaPConsumerReactiveHttpClient.getDMaaPConsumerResponse())); + } + + @Override + void initConfigs() { + datafileAppConfig.initFileStreamReader(); + } + + @Override + protected DmaapConsumerConfiguration resolveConfiguration() { + return datafileAppConfig.getDmaapConsumerConfiguration(); + } + + @Override + DMaaPConsumerReactiveHttpClient resolveClient() { + return dmaaPConsumerReactiveHttpClient == null + ? new DMaaPConsumerReactiveHttpClient(resolveConfiguration()).createDMaaPWebClient(buildWebClient()) + : dmaaPConsumerReactiveHttpClient; + } +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapPublisherTask.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapPublisherTask.java new file mode 100644 index 00000000..467eee0b --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapPublisherTask.java @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import org.onap.dcaegen2.collectors.datafile.config.DmaapPublisherConfiguration; +import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.DMaaPReactiveWebClient; +import org.onap.dcaegen2.collectors.datafile.service.producer.DMaaPProducerReactiveHttpClient; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/23/18 + */ +abstract class DmaapPublisherTask { + + abstract Mono<String> publish(Mono<ConsumerDmaapModel> consumerDmaapModel) throws DatafileTaskException; + + abstract DMaaPProducerReactiveHttpClient resolveClient(); + + protected abstract DmaapPublisherConfiguration resolveConfiguration(); + + protected abstract Mono<String> execute(Mono<ConsumerDmaapModel> consumerDmaapModel) throws DatafileTaskException; + + WebClient buildWebClient() { + return new DMaaPReactiveWebClient().fromConfiguration(resolveConfiguration()).build(); + } +} diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapPublisherTaskImpl.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapPublisherTaskImpl.java new file mode 100644 index 00000000..4d435a4f --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapPublisherTaskImpl.java @@ -0,0 +1,78 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import org.onap.dcaegen2.collectors.datafile.config.DmaapPublisherConfiguration; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.configuration.Config; +import org.onap.dcaegen2.collectors.datafile.exceptions.DmaapNotFoundException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.producer.DMaaPProducerReactiveHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/13/18 + */ +@Component +public class DmaapPublisherTaskImpl extends DmaapPublisherTask { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final Config datafileAppConfig; + private DMaaPProducerReactiveHttpClient dmaapProducerReactiveHttpClient; + + @Autowired + public DmaapPublisherTaskImpl(AppConfig datafileAppConfig) { + this.datafileAppConfig = datafileAppConfig; + } + + @Override + Mono<String> publish(Mono<ConsumerDmaapModel> consumerDmaapModel) { + logger.info("Publishing on DMaaP topic {} object {}", resolveConfiguration().dmaapTopicName(), + consumerDmaapModel); + return dmaapProducerReactiveHttpClient.getDMaaPProducerResponse(consumerDmaapModel); + } + + @Override + public Mono<String> execute(Mono<ConsumerDmaapModel> consumerDmaapModel) throws DmaapNotFoundException { + if (consumerDmaapModel == null) { + throw new DmaapNotFoundException("Invoked null object to DMaaP task"); + } + dmaapProducerReactiveHttpClient = resolveClient(); + logger.trace("Method called with arg {}", consumerDmaapModel); + return publish(consumerDmaapModel); + } + + @Override + protected DmaapPublisherConfiguration resolveConfiguration() { + return datafileAppConfig.getDmaapPublisherConfiguration(); + } + + @Override + DMaaPProducerReactiveHttpClient resolveClient() { + return dmaapProducerReactiveHttpClient == null + ? new DMaaPProducerReactiveHttpClient(resolveConfiguration()).createDMaaPWebClient(buildWebClient()) + : dmaapProducerReactiveHttpClient; + } +}
\ No newline at end of file diff --git a/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/ScheduledTasks.java b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/ScheduledTasks.java new file mode 100644 index 00000000..2600b563 --- /dev/null +++ b/datafile-app-server/src/main/java/org/onap/dcaegen2/collectors/datafile/tasks/ScheduledTasks.java @@ -0,0 +1,113 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import java.util.concurrent.Callable; + +import org.onap.dcaegen2.collectors.datafile.exceptions.DmaapEmptyResponseException; +import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/23/18 + */ +@Component +public class ScheduledTasks { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private final DmaapConsumerTask dmaapConsumerTask; + private final DmaapPublisherTask dmaapProducerTask; + private final AaiProducerTask aaiProducerTask; + + /** + * Constructor for tasks registration in DatafileWorkflow. + * + * @param dmaapConsumerTask - fist task + * @param dmaapPublisherTask - third task + * @param aaiPublisherTask - second task + */ + @Autowired + public ScheduledTasks(DmaapConsumerTask dmaapConsumerTask, DmaapPublisherTask dmaapPublisherTask, + AaiProducerTask aaiPublisherTask) { + this.dmaapConsumerTask = dmaapConsumerTask; + this.dmaapProducerTask = dmaapPublisherTask; + this.aaiProducerTask = aaiPublisherTask; + } + + /** + * Main function for scheduling datafileWorkflow. + */ + public void scheduleMainDatafileEventTask() { + logger.trace("Execution of tasks was registered"); + + Mono<String> dmaapProducerResponse = Mono.fromCallable(consumeFromDMaaPMessage()) + .doOnError(DmaapEmptyResponseException.class, error -> logger.warn("Nothing to consume from DMaaP")) + .map(this::publishToAaiConfiguration) + .flatMap(this::publishToDmaapConfiguration) + .subscribeOn(Schedulers.elastic()); + + dmaapProducerResponse.subscribe(this::onSuccess, this::onError, this::onComplete); + } + + private void onComplete() { + logger.info("Datafile tasks have been completed"); + } + + private void onSuccess(String responseCode) { + logger.info("Datafile consumed tasks. HTTP Response code {}", responseCode); + } + + private void onError(Throwable throwable) { + if (!(throwable instanceof DmaapEmptyResponseException)) { + logger.warn("Chain of tasks have been aborted due to errors in Datafile workflow", throwable); + } + } + + private Callable<Mono<ConsumerDmaapModel>> consumeFromDMaaPMessage() { + return () -> { + dmaapConsumerTask.initConfigs(); + return dmaapConsumerTask.execute(""); + }; + } + + private Mono<ConsumerDmaapModel> publishToAaiConfiguration(Mono<ConsumerDmaapModel> monoDMaaPModel) { + try { + return aaiProducerTask.execute(monoDMaaPModel); + } catch (DatafileTaskException e) { + return Mono.error(e); + } + } + + private Mono<String> publishToDmaapConfiguration(Mono<ConsumerDmaapModel> monoAaiModel) { + try { + return dmaapProducerTask.execute(monoAaiModel); + } catch (DatafileTaskException e) { + return Mono.error(e); + } + } +} diff --git a/datafile-app-server/src/main/resources/application.properties b/datafile-app-server/src/main/resources/application.properties new file mode 100644 index 00000000..205b6caa --- /dev/null +++ b/datafile-app-server/src/main/resources/application.properties @@ -0,0 +1,14 @@ +spring.profiles.active=prod +spring.main.web-application-type=none +server.port=8433 +server.ssl.key-store-type=PKCS12 +server.ssl.key-store-password=nokiapnf +server.ssl.key-store=classpath:keystore.jks +server.ssl.key-password=nokiapnf +server.ssl.key-alias=tomcat-localhost +logging.level.root=ERROR +logging.level.org.springframework=ERROR +logging.level.org.springframework.data=ERROR +logging.level.org.onap.dcaegen2.collectors.datafile=INFO +logging.file=logs/log/application.log +app.filepath=config/datafile_endpoints.json diff --git a/datafile-app-server/src/main/resources/keystore.jks b/datafile-app-server/src/main/resources/keystore.jks Binary files differnew file mode 100644 index 00000000..cd27cc01 --- /dev/null +++ b/datafile-app-server/src/main/resources/keystore.jks diff --git a/datafile-app-server/src/main/resources/keystore.jks.old b/datafile-app-server/src/main/resources/keystore.jks.old Binary files differnew file mode 100644 index 00000000..8a2b4f99 --- /dev/null +++ b/datafile-app-server/src/main/resources/keystore.jks.old diff --git a/datafile-app-server/src/main/resources/logback-spring.xml b/datafile-app-server/src/main/resources/logback-spring.xml new file mode 100644 index 00000000..925b38cc --- /dev/null +++ b/datafile-app-server/src/main/resources/logback-spring.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + <include resource="org/springframework/boot/logging/logback/defaults.xml"/> + <property name="LOG_FILE" + value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/> + + <springProfile name="dev"> + <include resource="org/springframework/boot/logging/logback/console-appender.xml"/> + <appender name="ROLLING-FILE" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <encoder> + <pattern>${FILE_LOG_PATTERN}</pattern> + </encoder> + <file>${LOG_FILE}</file> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> + <maxFileSize>50MB</maxFileSize> + <maxHistory>30</maxHistory> + <totalSizeCap>10GB</totalSizeCap> + </rollingPolicy> + </appender> + <root level="ERROR"> + <appender-ref ref="CONSOLE"/> + <appender-ref ref="ROLLING-FILE"/> + </root> + </springProfile> + + <springProfile name="prod"> + <appender name="ROLLING-FILE" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <encoder> + <pattern>${FILE_LOG_PATTERN}</pattern> + </encoder> + <file>${LOG_FILE}</file> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz</fileNamePattern> + <maxFileSize>50MB</maxFileSize> + <maxHistory>30</maxHistory> + <totalSizeCap>10GB</totalSizeCap> + </rollingPolicy> + </appender> + + <root level="ERROR"> + <appender-ref ref="ROLLING-FILE"/> + </root> + </springProfile> +</configuration>
\ No newline at end of file diff --git a/datafile-app-server/src/main/resources/scheduled-context.xml b/datafile-app-server/src/main/resources/scheduled-context.xml new file mode 100644 index 00000000..369d2c7b --- /dev/null +++ b/datafile-app-server/src/main/resources/scheduled-context.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:task="http://www.springframework.org/schema/task" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> + + <context:component-scan + base-package="org.onap.dcaegen2.collectors.datafile"/> + <task:scheduled-tasks> + <task:scheduled ref="scheduleController" method="startTasks" + fixed-rate="1000"/> + </task:scheduled-tasks> +</beans> diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/DatafileAppConfigTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/DatafileAppConfigTest.java new file mode 100644 index 00000000..7d54b4d5 --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/configuration/DatafileAppConfigTest.java @@ -0,0 +1,212 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.configuration; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.configuration.DatafileAppConfig; +import org.onap.dcaegen2.collectors.datafile.integration.junit5.mockito.MockitoExtension; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/9/18 + */ +@ExtendWith({MockitoExtension.class}) +class DatafileAppConfigTest { + + private static final String DATAFILE_ENDPOINTS = "datafile_endpoints.json"; + private static final String jsonString = "{\"configs\":{\"aai\":{\"aaiClientConfiguration\":{\"aaiHost\":" + + "\"localhost\",\"aaiPort\":8080,\"aaiIgnoreSslCertificateErrors\":true,\"aaiProtocol\":" + + "\"https\",\"aaiUserName\":\"admin\",\"aaiUserPassword\":\"admin\",\"aaiBasePath\":\"/aai/v11\"," + + "\"aaiPnfPath\":\"/network/pnfs/pnf\",\"aaiHeaders\":{\"X-FromAppId\":\"datafile\",\"X-TransactionId\":\"9999\"," + + "\"Accept\":\"application/json\",\"Real-Time\":\"true\",\"Content-Type\":\"application/merge-patch+json\"," + + "\"Authorization\":\"Basic QUFJOkFBSQ==\"}}}," + + "\"dmaap\":{\"dmaapConsumerConfiguration\":{\"consumerGroup\":\"other\",\"consumerId\":\"1\"," + + "\"dmaapContentType\":\"application/json\",\"dmaapHostName\":\"localhost\",\"dmaapPortNumber\":2222," + + "\"dmaapProtocol\":\"http\",\"dmaapTopicName\":\"temp\",\"dmaapUserName\":\"admin\",\"dmaapUserPassword\"" + + ":\"admin\",\"messageLimit\":1000,\"timeoutMs\":1000},\"dmaapProducerConfiguration\":{\"dmaapContentType\":" + + "\"application/json\",\"dmaapHostName\":\"localhost\",\"dmaapPortNumber\":2223,\"dmaapProtocol\":\"http\"," + + "\"dmaapTopicName\":\"temp\",\"dmaapUserName\":\"admin\",\"dmaapUserPassword\":\"admin\"}}}}"; + + private static final String incorrectJsonString = "{\"configs\":{\"aai\":{\"aaiClientConfiguration\":{\"aaiHost\":" + + "\"localhost\",\"aaiPort\":8080,\"aaiIgnoreSslCertificateErrors\":true,\"aaiProtocol\":\"https\"," + + "\"aaiUserName\":\"admin\",\"aaiUserPassword\":\"admin\",\"aaiBasePath\":\"/aai/v11\",\"aaiPnfPath\":" + + "\"/network/pnfs/pnf\",\"aaiHeaders\":{\"X-FromAppId\":\"datafile\",\"X-TransactionId\":\"9999\",\"Accept\":" + + "\"application/json\",\"Real-Time\":\"true\",\"Content-Type\":\"application/merge-patch+json\"," + + "\"Authorization\":\"Basic QUFJOkFBSQ==\"}}},\"dmaap\"" + + ":{\"dmaapConsumerConfiguration\":{\"consumerGroup\":\"other\",\"consumerId\":\"1\",\"dmaapContentType\"" + + ":\"application/json\",\"dmaapHostName\":\"localhost\",\"dmaapPortNumber\":2222,\"dmaapProtocol\":\"http\"" + + ",\"dmaapTopicName\":\"temp\",\"dmaapUserName\":\"admin\",\"dmaapUserPassword\":\"admin\",\"messageLimit\"" + + ":1000,\"timeoutMs\":1000},\"dmaapProducerConfiguration\":{\"dmaapContentType\":\"application/json\"," + + "\"dmaapHostName\":\"localhost\",\"dmaapPortNumber\":2223,\"dmaapProtocol\":\"http\",\"dmaaptopicName\"" + + ":\"temp\",\"dmaapuserName\":\"admin\",\"dmaapuserPassword\":\"admin\"}}}}"; + + private static DatafileAppConfig datafileAppConfig; + private static AppConfig appConfig; + + private static String filePath = Objects + .requireNonNull(DatafileAppConfigTest.class.getClassLoader().getResource(DATAFILE_ENDPOINTS)).getFile(); + + @BeforeEach + void setUp() { + datafileAppConfig = spy(DatafileAppConfig.class); + appConfig = spy(new AppConfig()); + } + + @Test + void whenApplicationWasStarted_FilePathIsSet() { + // + // When + // + datafileAppConfig.setFilepath(filePath); + // + // Then + // + verify(datafileAppConfig, times(1)).setFilepath(anyString()); + verify(datafileAppConfig, times(0)).initFileStreamReader(); + Assertions.assertEquals(filePath, datafileAppConfig.getFilepath()); + } + + @Test + void whenTheConfigurationFits_GetAaiAndDmaapObjectRepresentationConfiguration() + throws IOException { + // + // Given + // + InputStream inputStream = new ByteArrayInputStream((jsonString.getBytes( + StandardCharsets.UTF_8))); + // + // When + // + datafileAppConfig.setFilepath(filePath); + doReturn(inputStream).when(datafileAppConfig).getInputStream(any()); + datafileAppConfig.initFileStreamReader(); + appConfig.dmaapConsumerConfiguration = datafileAppConfig.getDmaapConsumerConfiguration(); + appConfig.dmaapPublisherConfiguration = datafileAppConfig.getDmaapPublisherConfiguration(); + appConfig.aaiClientConfiguration = datafileAppConfig.getAaiClientConfiguration(); + // + // Then + // + verify(datafileAppConfig, times(1)).setFilepath(anyString()); + verify(datafileAppConfig, times(1)).initFileStreamReader(); + Assertions.assertNotNull(datafileAppConfig.getAaiClientConfiguration()); + Assertions.assertNotNull(datafileAppConfig.getDmaapConsumerConfiguration()); + Assertions.assertNotNull(datafileAppConfig.getDmaapPublisherConfiguration()); + Assertions + .assertEquals(appConfig.getDmaapPublisherConfiguration(), datafileAppConfig.getDmaapPublisherConfiguration()); + Assertions + .assertEquals(appConfig.getDmaapConsumerConfiguration(), datafileAppConfig.getDmaapConsumerConfiguration()); + Assertions + .assertEquals(appConfig.getAaiClientConfiguration(), datafileAppConfig.getAaiClientConfiguration()); + + } + + @Test + void whenFileIsNotExist_ThrowIoException() { + // + // Given + // + filePath = "/temp.json"; + datafileAppConfig.setFilepath(filePath); + // + // When + // + datafileAppConfig.initFileStreamReader(); + // + // Then + // + verify(datafileAppConfig, times(1)).setFilepath(anyString()); + verify(datafileAppConfig, times(1)).initFileStreamReader(); + Assertions.assertNull(datafileAppConfig.getAaiClientConfiguration()); + Assertions.assertNull(datafileAppConfig.getDmaapConsumerConfiguration()); + Assertions.assertNull(datafileAppConfig.getDmaapPublisherConfiguration()); + + } + + @Test + void whenFileIsExistsButJsonIsIncorrect() throws IOException { + // + // Given + // + InputStream inputStream = new ByteArrayInputStream((incorrectJsonString.getBytes( + StandardCharsets.UTF_8))); + // + // When + // + datafileAppConfig.setFilepath(filePath); + doReturn(inputStream).when(datafileAppConfig).getInputStream(any()); + datafileAppConfig.initFileStreamReader(); + + // + // Then + // + verify(datafileAppConfig, times(1)).setFilepath(anyString()); + verify(datafileAppConfig, times(1)).initFileStreamReader(); + Assertions.assertNotNull(datafileAppConfig.getAaiClientConfiguration()); + Assertions.assertNotNull(datafileAppConfig.getDmaapConsumerConfiguration()); + Assertions.assertNull(datafileAppConfig.getDmaapPublisherConfiguration()); + + } + + + @Test + void whenTheConfigurationFits_ButRootElementIsNotAJsonObject() + throws IOException { + // Given + InputStream inputStream = new ByteArrayInputStream((jsonString.getBytes( + StandardCharsets.UTF_8))); + // When + datafileAppConfig.setFilepath(filePath); + doReturn(inputStream).when(datafileAppConfig).getInputStream(any()); + JsonElement jsonElement = mock(JsonElement.class); + when(jsonElement.isJsonObject()).thenReturn(false); + doReturn(jsonElement).when(datafileAppConfig).getJsonElement(any(JsonParser.class), any(InputStream.class)); + datafileAppConfig.initFileStreamReader(); + appConfig.dmaapConsumerConfiguration = datafileAppConfig.getDmaapConsumerConfiguration(); + appConfig.dmaapPublisherConfiguration = datafileAppConfig.getDmaapPublisherConfiguration(); + appConfig.aaiClientConfiguration = datafileAppConfig.getAaiClientConfiguration(); + + // Then + verify(datafileAppConfig, times(1)).setFilepath(anyString()); + verify(datafileAppConfig, times(1)).initFileStreamReader(); + Assertions.assertNull(datafileAppConfig.getAaiClientConfiguration()); + Assertions.assertNull(datafileAppConfig.getDmaapConsumerConfiguration()); + Assertions.assertNull(datafileAppConfig.getDmaapPublisherConfiguration()); + } +}
\ No newline at end of file diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/integration/ScheduledXmlContextITest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/integration/ScheduledXmlContextITest.java new file mode 100644 index 00000000..b9aa2f78 --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/integration/ScheduledXmlContextITest.java @@ -0,0 +1,66 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.integration; + +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.verify; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.onap.dcaegen2.collectors.datafile.integration.junit5.mockito.MockitoExtension; +import org.onap.dcaegen2.collectors.datafile.tasks.ScheduledTasks; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/27/18 + */ + +@Configuration +@ComponentScan +@ExtendWith({MockitoExtension.class, SpringExtension.class}) +@ContextConfiguration(locations = {"classpath:scheduled-context.xml"}) +class ScheduledXmlContextITest extends AbstractTestNGSpringContextTests { + + private static final int WAIT_FOR_SCHEDULING = 1; + + @Autowired + private ScheduledTasks scheduledTask; + + @Test + void testScheduling() { + final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + executorService.scheduleWithFixedDelay(this::verifyDmaapConsumerTask, 0, WAIT_FOR_SCHEDULING, TimeUnit.SECONDS); + } + + private void verifyDmaapConsumerTask() { + verify(scheduledTask, atLeast(1)).scheduleMainDatafileEventTask(); + } +} + + diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/integration/ServiceMockProvider.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/integration/ServiceMockProvider.java new file mode 100644 index 00000000..47107588 --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/integration/ServiceMockProvider.java @@ -0,0 +1,45 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.integration; + +import static org.mockito.Mockito.mock; + +import org.onap.dcaegen2.collectors.datafile.configuration.DatafileAppConfig; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 7/10/18 + */ +@Configuration +class ServiceMockProvider { + + @Bean + public DatafileAppConfig getDatafileAppConfig() { + return mock(DatafileAppConfig.class); + } + + @Bean + public ConsumerDmaapModel getRequestDetails() { + return mock(ConsumerDmaapModel.class); + } +} diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/integration/junit5/mockito/MockitoExtension.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/integration/junit5/mockito/MockitoExtension.java new file mode 100644 index 00000000..df167425 --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/integration/junit5/mockito/MockitoExtension.java @@ -0,0 +1,83 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.integration.junit5.mockito; + +import static org.mockito.Mockito.mock; + +import java.lang.reflect.Parameter; + +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; +import org.junit.jupiter.api.extension.ExtensionContext.Store; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolver; +import org.junit.jupiter.api.extension.TestInstancePostProcessor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/27/18 + * + * {@code MockitoExtension } showcases the {@link TestInstancePostProcessor} and {@link ParameterResolver} extension + * APIs of JUnit 5 by providing dependency injection support at the field level and at the method parameter level + * viaMockito 2.x's {@link Mock @Mock} annotation. + */ +public class MockitoExtension implements TestInstancePostProcessor, ParameterResolver { + + @Override + public void postProcessTestInstance(Object testInstance, ExtensionContext context) { + MockitoAnnotations.initMocks(testInstance); + } + + @Override + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { + return parameterContext.getParameter().isAnnotationPresent(Mock.class); + } + + @Override + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { + return getMock(parameterContext.getParameter(), extensionContext); + } + + private Object getMock(Parameter parameter, ExtensionContext extensionContext) { + Class<?> mockType = parameter.getType(); + Store mocks = extensionContext.getStore(Namespace.create(MockitoExtension.class, mockType)); + String mockName = getMockName(parameter); + + if (mockName != null) { + return mocks.getOrComputeIfAbsent(mockName, key -> mock(mockType, mockName)); + } else { + return mocks.getOrComputeIfAbsent(mockType.getCanonicalName(), key -> mock(mockType)); + } + } + + private String getMockName(Parameter parameter) { + String explicitMockName = parameter.getAnnotation(Mock.class).name().trim(); + if (!explicitMockName.isEmpty()) { + return explicitMockName; + } else if (parameter.isNamePresent()) { + return parameter.getName(); + } + return null; + } + + +} diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/service/DmaapConsumerJsonParserTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/service/DmaapConsumerJsonParserTest.java new file mode 100644 index 00000000..d7ceee82 --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/service/DmaapConsumerJsonParserTest.java @@ -0,0 +1,273 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service; + +import static org.mockito.Mockito.spy; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import java.util.Optional; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.onap.dcaegen2.collectors.datafile.exceptions.DmaapNotFoundException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.DmaapConsumerJsonParser; +import org.onap.dcaegen2.collectors.datafile.model.ImmutableConsumerDmaapModel; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 5/8/18 + */ +class DmaapConsumerJsonParserTest { + + @Test + void whenPassingCorrectJson_validationNotThrowingAnException() { + //given + String message = + "[{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":\"<<SerialNumber>>-reg\"," + + "\"eventName\":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"internalHeaderFields\"" + + ":{},\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\",\"nfcNamingCode\":\"5DU\"," + + "\"priority\":\"Normal\",\"reportingEntityName\":\"5GRAN_DU\",\"sequence\":0,\"sourceId\":" + + "\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",\"startEpochMicrosec\":1519837825682,\"version\":" + + "3},\"otherFields\":{\"otherFieldsVersion\":1,\"pnfFamily\":\"BBU\",\"pnfLastServiceDate\":1517206400" + + ",\"pnfManufactureDate\":1516406400,\"pnfModelNumber\":\"AJ02\",\"pnfOamIpv4Address\":" + + "\"10.16.123.234\",\"pnfOamIpv6Address\":\"0:0:0:0:0:FFFF:0A10:7BEA\",\"pnfSerialNumber\":" + + "\"QTFCOC540002E\",\"pnfSoftwareVersion\":\"v4.5.0.1\",\"pnfType\":\"AirScale\",\"pnfVendorName\":" + + "\"Nokia\"}}}]"; + + String parsed = + "{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":\"<<SerialNumber>>-reg\",\"eventName\"" + + ":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"internalHeaderFields\":{}," + + "\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\",\"nfcNamingCode\":\"5DU\"," + + "\"priority\":\"Normal\",\"reportingEntityName\":\"5GRAN_DU\",\"sequence\":0,\"sourceId\":" + + "\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",\"startEpochMicrosec\":1519837825682,\"version\":" + + "3},\"otherFields\":{\"otherFieldsVersion\":1,\"pnfFamily\":\"BBU\",\"pnfLastServiceDate\":" + + "1517206400,\"pnfManufactureDate\":1516406400,\"pnfModelNumber\":\"AJ02\",\"pnfOamIpv4Address\":" + + "\"10.16.123.234\",\"pnfOamIpv6Address\":\"0:0:0:0:0:FFFF:0A10:7BEA\",\"pnfSerialNumber\":" + + "\"QTFCOC540002E\",\"pnfSoftwareVersion\":\"v4.5.0.1\",\"pnfType\":\"AirScale\",\"pnfVendorName\":" + + "\"Nokia\"}}}"; + ConsumerDmaapModel expectedObject = ImmutableConsumerDmaapModel.builder().ipv4("10.16.123.234") + .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") + .pnfName("NOKQTFCOC540002E").build(); + //when + DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); + JsonElement jsonElement = new JsonParser().parse(parsed); + Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) + .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); + ConsumerDmaapModel consumerDmaapModel = dmaapConsumerJsonParser + .getJsonObject(Mono.just((message))).block(); + //then + Assertions.assertNotNull(consumerDmaapModel); + Assertions.assertEquals(expectedObject, consumerDmaapModel); + } + + @Test + void whenPassingCorrectJsonWithoutIpv4_validationNotThrowingAnException() { + //given + String message = + "[{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":\"<<SerialNumber>>-reg\"," + + "\"eventName\":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"internalHeaderFields\":" + + "{},\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\",\"nfcNamingCode\":\"5DU\"," + + "\"priority\":\"Normal\",\"reportingEntityName\":\"5GRAN_DU\",\"sequence\":0,\"sourceId\":" + + "\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",\"startEpochMicrosec\":1519837825682,\"version\":3}" + + ",\"otherFields\":{\"otherFieldsVersion\":1,\"pnfFamily\":\"BBU\",\"pnfLastServiceDate\":1517206400," + + "\"pnfManufactureDate\":1516406400,\"pnfModelNumber\":\"AJ02\",\"pnfOamIpv6Address\":" + + "\"0:0:0:0:0:FFFF:0A10:7BEA\",\"pnfSerialNumber\":\"QTFCOC540002E\",\"pnfSoftwareVersion\"" + + ":\"v4.5.0.1\",\"pnfType\":\"AirScale\",\"pnfVendorName\":\"Nokia\"}}}]"; + + String parsed = + "{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":\"<<SerialNumber>>-reg\",\"eventName\"" + + ":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"internalHeaderFields\":{}," + + "\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\",\"nfcNamingCode\":\"5DU\"," + + "\"priority\":\"Normal\",\"reportingEntityName\":\"5GRAN_DU\",\"sequence\":0,\"sourceId\":" + + "\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",\"startEpochMicrosec\":1519837825682,\"version\":3}" + + ",\"otherFields\":{\"otherFieldsVersion\":1,\"pnfFamily\":\"BBU\",\"pnfLastServiceDate\":1517206400," + + "\"pnfManufactureDate\":1516406400,\"pnfModelNumber\":\"AJ02\",\"pnfOamIpv6Address\":" + + "\"0:0:0:0:0:FFFF:0A10:7BEA\",\"pnfSerialNumber\":\"QTFCOC540002E\",\"pnfSoftwareVersion\"" + + ":\"v4.5.0.1\",\"pnfType\":\"AirScale\",\"pnfVendorName\":\"Nokia\"}}}"; + + //when + DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); + JsonElement jsonElement = new JsonParser().parse(parsed); + Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) + .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); + dmaapConsumerJsonParser.getJsonObject(Mono.just((message))); + ConsumerDmaapModel consumerDmaapModel = dmaapConsumerJsonParser.getJsonObject(Mono.just((message))) + .block(); + //then + ConsumerDmaapModel expectedObject = ImmutableConsumerDmaapModel.builder().ipv4("") + .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") + .pnfName("NOKQTFCOC540002E").build(); + Assertions.assertNotNull(consumerDmaapModel); + Assertions.assertEquals(expectedObject, consumerDmaapModel); + } + + @Test + void whenPassingCorrectJsonWihoutIpv6_validationNotThrowingAnException() { + //given + String message = + "[{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":\"<<SerialNumber>>-reg\"," + + "\"eventName\":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"internalHeaderFields\":" + + "{},\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\",\"nfcNamingCode\":\"5DU\"," + + "\"priority\":\"Normal\",\"reportingEntityName\":\"5GRAN_DU\",\"sequence\":0,\"sourceId\":" + + "\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",\"startEpochMicrosec\":1519837825682," + + "\"version\":3},\"otherFields\":{\"otherFieldsVersion\":1,\"pnfFamily\":\"BBU\",\"pnfLastServiceDate" + + "\":1517206400,\"pnfManufactureDate\":1516406400,\"pnfModelNumber\":\"AJ02\",\"pnfOamIpv4Address" + + "\":\"10.16.123.234\",\"pnfSerialNumber\":\"QTFCOC540002E\",\"pnfSoftwareVersion\":\"v4.5.0.1\"," + + "\"pnfType\":\"AirScale\",\"pnfVendorName\":\"Nokia\"}}}]"; + String parsed = + "{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":\"<<SerialNumber>>-reg\",\"eventName\"" + + ":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"internalHeaderFields\":{}," + + "\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\",\"nfcNamingCode\":\"5DU\"," + + "\"priority\":\"Normal\",\"reportingEntityName\":\"5GRAN_DU\",\"sequence\":0,\"sourceId\":" + + "\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",\"startEpochMicrosec\":1519837825682," + + "\"version\":3},\"otherFields\":{\"otherFieldsVersion\":1,\"pnfFamily\":\"BBU\",\"pnfLastServiceDate" + + "\":1517206400,\"pnfManufactureDate\":1516406400,\"pnfModelNumber\":\"AJ02\",\"pnfOamIpv4Address" + + "\":\"10.16.123.234\",\"pnfSerialNumber\":\"QTFCOC540002E\",\"pnfSoftwareVersion\":\"v4.5.0.1\"," + + "\"pnfType\":\"AirScale\",\"pnfVendorName\":\"Nokia\"}}}"; + + ConsumerDmaapModel expectedObject = ImmutableConsumerDmaapModel.builder().ipv4("10.16.123.234").ipv6("") + .pnfName("NOKQTFCOC540002E").build(); + //when + DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); + JsonElement jsonElement = new JsonParser().parse(parsed); + Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) + .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); + ConsumerDmaapModel consumerDmaapModel = dmaapConsumerJsonParser.getJsonObject(Mono.just((message))) + .block(); + //then + Assertions.assertNotNull(consumerDmaapModel); + Assertions.assertEquals(expectedObject, consumerDmaapModel); + } + + @Test + void whenPassingCorrectJsonWihoutIpv4andIpv6_validationThrowingAnException() { + String message = + "[{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":\"<<SerialNumber>>-reg\"," + + "\"eventName\":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"internalHeaderFields\":" + + "{},\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\",\"nfcNamingCode\":\"5DU\"," + + "\"priority\":\"Normal\",\"reportingEntityName\":\"5GRAN_DU\",\"sequence\":0,\"sourceId\":" + + "\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",\"startEpochMicrosec\":1519837825682,\"version\"" + + ":3},\"otherFields\":{\"otherFieldsVersion\":1,\"pnfFamily\":\"BBU\",\"pnfLastServiceDate\"" + + ":1517206400,\"pnfManufactureDate\":1516406400,\"pnfModelNumber\":\"AJ02\",\"pnfSoftwareVersion\":" + + "\"v4.5.0.1\",\"pnfType\":\"AirScale\",\"pnfVendorName\":\"Nokia\"}}}]"; + String parsed = + "{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":\"<<SerialNumber>>-reg\",\"eventName\"" + + ":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"internalHeaderFields\":{}," + + "\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\",\"nfcNamingCode\":\"5DU\"," + + "\"priority\":\"Normal\",\"reportingEntityName\":\"5GRAN_DU\",\"sequence\":0,\"sourceId\":" + + "\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",\"startEpochMicrosec\":1519837825682,\"version\"" + + ":3},\"otherFields\":{\"otherFieldsVersion\":1,\"pnfFamily\":\"BBU\",\"pnfLastServiceDate\"" + + ":1517206400,\"pnfManufactureDate\":1516406400,\"pnfModelNumber\":\"AJ02\",\"pnfSoftwareVersion\":" + + "\"v4.5.0.1\",\"pnfType\":\"AirScale\",\"pnfVendorName\":\"Nokia\"}}}"; + DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); + JsonElement jsonElement = new JsonParser().parse(parsed); + Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) + .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); + StepVerifier.create(dmaapConsumerJsonParser.getJsonObject(Mono.just(message))) + .expectSubscription().expectError(DmaapNotFoundException.class).verify(); + + } + + @Test + void whenPassingJsonWithoutMandatoryHeaderInformation_validationThrowingAnException() { + String parsed = "{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":\"<<SerialNumber>>-reg\"" + + ",\"eventName\":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"internalHeaderFields\":{}," + + "\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\",\"nfcNamingCode\":\"5DU\",\"priority\"" + + ":\"Normal\",\"reportingEntityName\":\"5GRAN_DU\",\"sequence\":0,\"sourceId\":\"<<SerialNumber>>\"," + + "\"sourceName\":\"5GRAN_DU\",\"startEpochMicrosec\":1519837825682,\"version\":3}}}"; + DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); + JsonElement jsonElement = new JsonParser().parse(parsed); + Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) + .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); + String incorrectMessage = + "[{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":\"<<SerialNumber>>-reg\"" + + ",\"eventName\":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"internalHeaderFields\":" + + "{},\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\",\"nfcNamingCode\":\"5DU\"," + + "\"priority\":\"Normal\",\"reportingEntityName\":\"5GRAN_DU\",\"sequence\":0,\"sourceId\":" + + "\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",\"startEpochMicrosec\":1519837825682,\"version\":3" + + "}}}]"; + StepVerifier.create(dmaapConsumerJsonParser.getJsonObject(Mono.just(incorrectMessage))) + .expectSubscription().expectError(DmaapNotFoundException.class).verify(); + } + + @Test + void whenPassingJsonWithoutPnfSerialNumberOrPnfVendorName_validationThrowingAnException() { + String parsed = "{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":" + + "\"<<SerialNumber>>-reg\",\"eventName\":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"" + + "internalHeaderFields\":{},\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\"," + + "\"nfcNamingCode\":\"5DU\",\"priority\":\"Normal\",reportingEntityName\":\"5GRAN_DU\",\"sequence\":0," + + "\"sourceId\":\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",startEpochMicrosec\":1519837825682,\"" + + "version\":3},\"otherFields\":{\"otherFieldsVersion\":1,\"pnfFamily\":\"BBU\",\"pnfLastServiceDate\"" + + ":1517206400,\"pnfManufactureDate\":1516406400,\"pnfModelNumber\":\"AJ02\",\"pnfOamIpv4Address\":" + + "\"10.16.123.234\",\"pnfOamIpv6Address\":\"0:0:0:0:0:FFFF:0A10:7BEA\",\"pnfSoftwareVersion\":" + + "\"v4.5.0.1\",\"pnfType\":\"AirScale\"}}}"; + DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); + JsonElement jsonElement = new JsonParser().parse(parsed); + Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) + .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); + String jsonWithoutPnfVendorAndSerialNumber = + "[{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":" + + "\"<<SerialNumber>>-reg\",\"eventName\":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"" + + "internalHeaderFields\":{},\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\"," + + "\"nfcNamingCode\":\"5DU\",\"priority\":\"Normal\",reportingEntityName\":\"5GRAN_DU\",\"sequence\":0," + + "\"sourceId\":\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",startEpochMicrosec\":1519837825682," + + "\"version\":3},\"otherFields\":{\"otherFieldsVersion\":1,\"pnfFamily\":\"BBU\"," + + "\"pnfLastServiceDate\":1517206400,\"pnfManufactureDate\":1516406400,\"pnfModelNumber\":\"AJ02\"," + + "\"pnfOamIpv4Address\":\"10.16.123.234\",\"pnfOamIpv6Address\":\"0:0:0:0:0:FFFF:0A10:7BEA\"," + + "\"pnfSoftwareVersion\":\"v4.5.0.1\",\"pnfType\":\"AirScale\"}}}]"; + StepVerifier + .create(dmaapConsumerJsonParser.getJsonObject(Mono.just(jsonWithoutPnfVendorAndSerialNumber))) + .expectSubscription().expectError(DmaapNotFoundException.class).verify(); + } + + @Test + void whenPassingJsonWithoutIpInformation_validationThrowingAnException() { + String parsed = + "{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":\"<<SerialNumber>>-reg\"," + + "\"eventName\":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"internalHeaderFields\"" + + ":{},\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\",\"nfcNamingCode\":\"5DU\"," + + "\"priority\":\"Normal\",\"reportingEntityName\":\"5GRAN_DU\",\"sequence\":0,\"sourceId\":" + + "\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",\"startEpochMicrosec\":1519837825682,\"version\"" + + ":3},\"otherFields\":{\"otherFieldsVersion\":1,\"pnfFamily\":\"BBU\",\"pnfLastServiceDate\":" + + "1517206400,\"pnfManufactureDate\":1516406400,\"pnfModelNumber\":" + + "\"AJ02\",\"pnfSerialNumber\":\"QTFCOC540002E\",\"pnfSoftwareVersion\":\"v4.5.0.1\",\"pnfType\":" + + "\"AirScale\"," + "\"pnfVendorName\":\"Nokia\"}}}"; + DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); + JsonElement jsonElement = new JsonParser().parse(parsed); + Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) + .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); + String jsonWithoutIpInformation = + "[{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":\"<<SerialNumber>>-reg\"," + + "\"eventName\":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"internalHeaderFields\"" + + ":{},\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\",\"nfcNamingCode\":\"5DU\"," + + "\"priority\":\"Normal\",\"reportingEntityName\":\"5GRAN_DU\",\"sequence\":0,\"sourceId\":" + + "\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",\"startEpochMicrosec\":1519837825682,\"version\"" + + ":3},\"otherFields\":{\"otherFieldsVersion\":1,\"pnfFamily\":\"BBU\",\"pnfLastServiceDate\"" + + ":1517206400,\"pnfManufactureDate\":1516406400,\"pnfModelNumber\":\"AJ02\",\"pnfSerialNumber\"" + + ":\"QTFCOC540002E\",\"pnfSoftwareVersion\":\"v4.5.0.1\",\"pnfType\":\"AirScale\"," + + "\"pnfVendorName\":\"Nokia\"}}}]"; + StepVerifier.create(dmaapConsumerJsonParser.getJsonObject(Mono.just(jsonWithoutIpInformation))) + .expectSubscription().expectError(DmaapNotFoundException.class).verify(); + } +} diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiConsumerTaskImplTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiConsumerTaskImplTest.java new file mode 100644 index 00000000..05a99b43 --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiConsumerTaskImplTest.java @@ -0,0 +1,149 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.Optional; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.function.Executable; +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.exceptions.AaiNotFoundException; +import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.AaiConsumerClient; +import org.onap.dcaegen2.collectors.datafile.tasks.AaiConsumerTaskImpl; +import org.onap.dcaegen2.collectors.datafile.config.ImmutableAaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.model.ImmutableConsumerDmaapModel; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 5/17/18 + */ +class AaiConsumerTaskImplTest { + + private static ConsumerDmaapModel consumerDmaapModel; + private static AaiConsumerTaskImpl aaiConsumerTask; + + private static final String AAI_HOST = "/aai/v12/network/pnfs/pnf/NOKQTFCOC540002E"; + private static final Integer PORT = 1234; + private static final String PROTOCOL = "https"; + private static final String USER_NAME_PASSWORD = "Datafile"; + private static final String BASE_PATH = "/aai/v12"; + private static final String PNF_PATH = "/network/pnfs/pnf"; + + private static AaiClientConfiguration aaiClientConfiguration; + private static AaiConsumerClient aaiConsumerClient; + private static AppConfig appConfig; + + @BeforeAll + static void setUp() { + aaiClientConfiguration = new ImmutableAaiClientConfiguration.Builder() + .aaiHost(AAI_HOST) + .aaiPort(PORT) + .aaiProtocol(PROTOCOL) + .aaiUserName(USER_NAME_PASSWORD) + .aaiUserPassword(USER_NAME_PASSWORD) + .aaiIgnoreSslCertificateErrors(true) + .aaiBasePath(BASE_PATH) + .aaiPnfPath(PNF_PATH) + .build(); + consumerDmaapModel = ImmutableConsumerDmaapModel.builder().ipv4("10.16.123.234") + .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") + .pnfName("NOKQTFCOC540002E").build(); + appConfig = mock(AppConfig.class); + + } + + @Test + void whenPassedObjectDoesntFit_ThrowsDatafileTaskException() { + //given/when + when(appConfig.getAaiClientConfiguration()).thenReturn(aaiClientConfiguration); + aaiConsumerTask = new AaiConsumerTaskImpl(appConfig); + Executable executableCode = () -> aaiConsumerTask.execute(null); + //then + Assertions + .assertThrows(DatafileTaskException.class, executableCode, "Passing wrong object type to execute function"); + + } + + @Test + void whenPassedObjectFits_ReturnsCorrectStatus() throws DatafileTaskException, IOException { + //given/when + getAaiConsumerTask_WhenMockingHttpResponseCode("200", false); + String response = aaiConsumerTask.execute(consumerDmaapModel); + + //then + verify(aaiConsumerClient, times(1)).getHttpResponse(any(ConsumerDmaapModel.class)); + verifyNoMoreInteractions(aaiConsumerClient); + Assertions.assertEquals("200", response); + } + + @Test + void whenPassedObjectFits_butIncorrectResponseReturns() throws IOException, AaiNotFoundException { + //given/when + getAaiConsumerTask_WhenMockingHttpResponseCode("400", false); + String response = aaiConsumerTask.execute(consumerDmaapModel); + + //then + verify(aaiConsumerClient, times(1)).getHttpResponse(any(ConsumerDmaapModel.class)); + verifyNoMoreInteractions(aaiConsumerClient); + Assertions.assertEquals("400", response); + } + + @Test + void whenPassedObjectFits_ThrowsIoExceptionAndHandleIt() throws IOException { + //given/when + getAaiConsumerTask_WhenMockingHttpResponseCode(null, true); + Executable executableCode = () -> aaiConsumerTask.execute(any(ConsumerDmaapModel.class)); + Assertions + .assertThrows(DatafileTaskException.class, executableCode, "HttpClient throws IOException"); + + //then + verifyNoMoreInteractions(aaiConsumerClient); + } + + + private static void getAaiConsumerTask_WhenMockingHttpResponseCode(String httpResponseCode, boolean throwsException) + throws IOException { + aaiConsumerClient = mock(AaiConsumerClient.class); + if (throwsException) { + when(aaiConsumerClient.getHttpResponse(consumerDmaapModel)).thenThrow(IOException.class); + } else { + when(aaiConsumerClient.getHttpResponse(consumerDmaapModel)).thenReturn(Optional.of(httpResponseCode)); + } + when(appConfig.getAaiClientConfiguration()).thenReturn(aaiClientConfiguration); + aaiConsumerTask = spy(new AaiConsumerTaskImpl(appConfig)); + when(aaiConsumerTask.resolveConfiguration()).thenReturn(aaiClientConfiguration); + doReturn(aaiConsumerClient).when(aaiConsumerTask).resolveClient(); + } + +}
\ No newline at end of file diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiConsumerTaskSpy.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiConsumerTaskSpy.java new file mode 100644 index 00000000..9e1842b0 --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiConsumerTaskSpy.java @@ -0,0 +1,50 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.tasks.AaiConsumerTask; +import org.onap.dcaegen2.collectors.datafile.tasks.AaiConsumerTaskImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +@Configuration +public class AaiConsumerTaskSpy { + + /** + * Mocking bean for tests. + * + * @return A&AI ConsumerTask spy + */ + @Bean + @Primary + public AaiConsumerTask registerSimpleAaiPublisherTask() { + AppConfig appConfig = mock(AppConfig.class); + when(appConfig.getAaiClientConfiguration()).thenReturn(mock(AaiClientConfiguration.class)); + return spy(new AaiConsumerTaskImpl(appConfig)); + } +}
\ No newline at end of file diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiProducerTaskImplTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiProducerTaskImplTest.java new file mode 100644 index 00000000..f33fc931 --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiProducerTaskImplTest.java @@ -0,0 +1,133 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.function.Executable; +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.producer.AaiProducerReactiveHttpClient; +import org.onap.dcaegen2.collectors.datafile.tasks.AaiProducerTaskImpl; +import org.onap.dcaegen2.collectors.datafile.config.ImmutableAaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.model.ImmutableConsumerDmaapModel; + +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 5/14/18 + */ +class AaiProducerTaskImplTest { + + + private static final String AAI_HOST = "/aai/v11/network/pnfs/pnf/NOKQTFCOC540002E"; + private static final Integer PORT = 1234; + private static final String PROTOCOL = "https"; + private static final String USER_NAME_PASSWORD = "Datafile"; + private static final String BASE_PATH = "/aai/v11"; + private static final String PNF_PATH = "/network/pnfs/pnf"; + + private static ConsumerDmaapModel consumerDmaapModel; + private static AaiProducerTaskImpl aaiProducerTask; + private static AaiClientConfiguration aaiClientConfiguration; + private static AaiProducerReactiveHttpClient aaiProducerReactiveHttpClient; + private static AppConfig appConfig; + + @BeforeAll + static void setUp() { + aaiClientConfiguration = new ImmutableAaiClientConfiguration.Builder() + .aaiHost(AAI_HOST) + .aaiPort(PORT) + .aaiProtocol(PROTOCOL) + .aaiUserName(USER_NAME_PASSWORD) + .aaiUserPassword(USER_NAME_PASSWORD) + .aaiIgnoreSslCertificateErrors(true) + .aaiBasePath(BASE_PATH) + .aaiPnfPath(PNF_PATH) + .build(); + consumerDmaapModel = ImmutableConsumerDmaapModel.builder().ipv4("10.16.123.234") + .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") + .pnfName("NOKQTFCOC540002E").build(); + appConfig = mock(AppConfig.class); + + } + + @Test + void whenPassedObjectDoesntFit_ThrowsDatafileTaskException() { + //given/when/ + when(appConfig.getAaiClientConfiguration()).thenReturn(aaiClientConfiguration); + aaiProducerTask = new AaiProducerTaskImpl(appConfig); + Executable executableCode = () -> aaiProducerTask.execute(null); + + //then + Assertions + .assertThrows(DatafileTaskException.class, executableCode, "Passing wrong object type to execute function"); + } + + @Test + void whenPassedObjectFits_ReturnsCorrectStatus() throws DatafileTaskException { + //given/when + getAaiProducerTask_whenMockingResponseObject(200); + Mono<ConsumerDmaapModel> response = aaiProducerTask.execute(Mono.just(consumerDmaapModel)); + + //then + verify(aaiProducerReactiveHttpClient, times(1)).getAaiProducerResponse(any()); + verifyNoMoreInteractions(aaiProducerReactiveHttpClient); + Assertions.assertEquals(consumerDmaapModel, response.block()); + + } + + + @Test + void whenPassedObjectFits_butIncorrectResponseReturns() throws DatafileTaskException { + //given/when + getAaiProducerTask_whenMockingResponseObject(400); + StepVerifier.create(aaiProducerTask.execute(Mono.just(consumerDmaapModel))).expectSubscription() + .expectError(DatafileTaskException.class).verify(); + //then + verify(aaiProducerReactiveHttpClient, times(1)).getAaiProducerResponse(any()); + verifyNoMoreInteractions(aaiProducerReactiveHttpClient); + } + + private static void getAaiProducerTask_whenMockingResponseObject(Integer statusCode) { + //given + aaiProducerReactiveHttpClient = mock(AaiProducerReactiveHttpClient.class); + when(aaiProducerReactiveHttpClient.getAaiProducerResponse(any())) + .thenReturn(Mono.just(statusCode)); + when(appConfig.getAaiClientConfiguration()).thenReturn(aaiClientConfiguration); + aaiProducerTask = spy(new AaiProducerTaskImpl(appConfig)); + when(aaiProducerTask.resolveConfiguration()).thenReturn(aaiClientConfiguration); + doReturn(aaiProducerReactiveHttpClient).when(aaiProducerTask).resolveClient(); + } +}
\ No newline at end of file diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiPublisherTaskSpy.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiPublisherTaskSpy.java new file mode 100644 index 00000000..3beda94b --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/AaiPublisherTaskSpy.java @@ -0,0 +1,58 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; + +import org.onap.dcaegen2.collectors.datafile.config.AaiClientConfiguration; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.service.producer.AaiProducerReactiveHttpClient; +import org.onap.dcaegen2.collectors.datafile.tasks.AaiProducerTask; +import org.onap.dcaegen2.collectors.datafile.tasks.AaiProducerTaskImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/13/18 + */ +@Configuration +public class AaiPublisherTaskSpy { + + /** + * Mocking bean for tests. + * + * @return A&AI ProducerTask spy + */ + @Bean + @Primary + public AaiProducerTask registerSimpleAaiPublisherTask() { + AppConfig appConfig = spy(AppConfig.class); + doReturn(mock(AaiClientConfiguration.class)).when(appConfig).getAaiClientConfiguration(); + AaiProducerTaskImpl aaiProducerTask = spy(new AaiProducerTaskImpl(appConfig)); + AaiProducerReactiveHttpClient aaiProducerReactiveHttpClient = mock(AaiProducerReactiveHttpClient.class); + doReturn(mock(AaiClientConfiguration.class)).when(aaiProducerTask).resolveConfiguration(); + doReturn(aaiProducerReactiveHttpClient).when(aaiProducerTask).resolveClient(); + return aaiProducerTask; + } +} diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTaskImplTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTaskImplTest.java new file mode 100644 index 00000000..19ab1ab9 --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTaskImplTest.java @@ -0,0 +1,136 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import java.util.Optional; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.onap.dcaegen2.collectors.datafile.config.DmaapConsumerConfiguration; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.exceptions.DmaapEmptyResponseException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.DmaapConsumerJsonParser; +import org.onap.dcaegen2.collectors.datafile.service.consumer.DMaaPConsumerReactiveHttpClient; +import org.onap.dcaegen2.collectors.datafile.tasks.DmaapConsumerTaskImpl; +import org.onap.dcaegen2.collectors.datafile.config.ImmutableDmaapConsumerConfiguration; +import org.onap.dcaegen2.collectors.datafile.model.ImmutableConsumerDmaapModel; + +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 5/17/18 + */ +class DmaapConsumerTaskImplTest { + + private static ConsumerDmaapModel consumerDmaapModel; + private static DmaapConsumerTaskImpl dmaapConsumerTask; + private static DMaaPConsumerReactiveHttpClient dMaaPConsumerReactiveHttpClient; + private static AppConfig appConfig; + private static DmaapConsumerConfiguration dmaapConsumerConfiguration; + private static String message; + private static String parsed; + + @BeforeAll + static void setUp() { + dmaapConsumerConfiguration = new ImmutableDmaapConsumerConfiguration.Builder().consumerGroup("OpenDCAE-c12") + .consumerId("c12").dmaapContentType("application/json").dmaapHostName("54.45.33.2").dmaapPortNumber(1234) + .dmaapProtocol("https").dmaapUserName("Datafile").dmaapUserPassword("Datafile") + .dmaapTopicName("unauthenticated.SEC_OTHER_OUTPUT").timeoutMs(-1).messageLimit(-1).build(); + + consumerDmaapModel = ImmutableConsumerDmaapModel.builder().ipv4("10.16.123.234") + .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") + .pnfName("NOKQTFCOC540002E").build(); + appConfig = mock(AppConfig.class); + message = + "[{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":\"<<SerialNumber>>-reg\"," + + "\"eventName\":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"internalHeaderFields\"" + + ":{},\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\",\"nfcNamingCode\":\"5DU\"," + + "\"priority\":\"Normal\",\"reportingEntityName\":\"5GRAN_DU\",\"sequence\":0,\"sourceId\":" + + "\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",\"startEpochMicrosec\":1519837825682,\"version\"" + + ":3},\"otherFields\":{\"otherFieldsVersion\":1,\"pnfFamily\":\"BBU\",\"pnfLastServiceDate\":" + + "1517206400,\"pnfManufactureDate\":1516406400,\"pnfModelNumber\":\"AJ02\",\"pnfOamIpv4Address\":" + + "\"10.16.123.234\",\"pnfOamIpv6Address\":\"0:0:0:0:0:FFFF:0A10:7BEA\",\"pnfSerialNumber\":" + + "\"QTFCOC540002E\",\"pnfSoftwareVersion\":\"v4.5.0.1\",\"pnfType\":\"AirScale\",\"pnfVendorName\":" + + "\"Nokia\"}}}]"; + parsed = + "{\"event\":{\"commonEventHeader\":{\"domain\":\"other\",\"eventId\":\"<<SerialNumber>>-reg\",\"eventName\"" + + ":\"pnfRegistration_5GDU\",\"eventType\":\"pnfRegistration\",\"internalHeaderFields\":{}," + + "\"lastEpochMicrosec\":1519837825682,\"nfNamingCode\":\"5GRAN\",\"nfcNamingCode\":\"5DU\"," + + "\"priority\":\"Normal\",\"reportingEntityName\":\"5GRAN_DU\",\"sequence\":0,\"sourceId\":" + + "\"<<SerialNumber>>\",\"sourceName\":\"5GRAN_DU\",\"startEpochMicrosec\":1519837825682," + + "\"version\":3},\"otherFields\":{\"otherFieldsVersion\":1,\"pnfFamily\":\"BBU\"," + + "\"pnfLastServiceDate\":1517206400,\"pnfManufactureDate\":1516406400,\"pnfModelNumber\":\"AJ02\"," + + "\"pnfOamIpv4Address\":\"10.16.123.234\",\"pnfOamIpv6Address\":\"0:0:0:0:0:FFFF:0A10:7BEA\"," + + "\"pnfSerialNumber\":\"QTFCOC540002E\",\"pnfSoftwareVersion\":\"v4.5.0.1\",\"pnfType\":\"AirScale\"," + + "\"pnfVendorName\":\"Nokia\"}}}"; + } + + @Test + void whenPassedObjectDoesntFit_DoesNotThrowDatafileTaskException() { + //given + prepareMocksForDmaapConsumer(Optional.empty()); + + //then + StepVerifier.create(dmaapConsumerTask.execute("Sample input")).expectSubscription() + .expectError(DmaapEmptyResponseException.class).verify(); + + verify(dMaaPConsumerReactiveHttpClient, times(1)).getDMaaPConsumerResponse(); + } + + @Test + void whenPassedObjectFits_ReturnsCorrectResponse() { + //given + prepareMocksForDmaapConsumer(Optional.of(message)); + //when + Mono<ConsumerDmaapModel> response = dmaapConsumerTask.execute("Sample input"); + + //then + verify(dMaaPConsumerReactiveHttpClient, times(1)).getDMaaPConsumerResponse(); + assertEquals(consumerDmaapModel, response.block()); + + + } + + private void prepareMocksForDmaapConsumer(Optional<String> message) { + DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); + JsonElement jsonElement = new JsonParser().parse(parsed); + Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) + .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); + dMaaPConsumerReactiveHttpClient = mock(DMaaPConsumerReactiveHttpClient.class); + when(dMaaPConsumerReactiveHttpClient.getDMaaPConsumerResponse()).thenReturn(Mono.just(message.orElse(""))); + when(appConfig.getDmaapConsumerConfiguration()).thenReturn(dmaapConsumerConfiguration); + dmaapConsumerTask = spy(new DmaapConsumerTaskImpl(appConfig, dmaapConsumerJsonParser)); + when(dmaapConsumerTask.resolveConfiguration()).thenReturn(dmaapConsumerConfiguration); + doReturn(dMaaPConsumerReactiveHttpClient).when(dmaapConsumerTask).resolveClient(); + } +}
\ No newline at end of file diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTaskSpy.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTaskSpy.java new file mode 100644 index 00000000..de5c8535 --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapConsumerTaskSpy.java @@ -0,0 +1,59 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; + +import org.onap.dcaegen2.collectors.datafile.config.DmaapConsumerConfiguration; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.service.consumer.DMaaPConsumerReactiveHttpClient; +import org.onap.dcaegen2.collectors.datafile.tasks.DmaapConsumerTask; +import org.onap.dcaegen2.collectors.datafile.tasks.DmaapConsumerTaskImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/27/18 + */ +@Configuration +public class DmaapConsumerTaskSpy { + + /** + * Mocking bean for tests. + * + * @return DMaaP ConsumerTask spy + */ + @Bean + @Primary + public DmaapConsumerTask registerSimpleDmaapConsumerTask() { + AppConfig appConfig = spy(AppConfig.class); + doReturn(mock(DmaapConsumerConfiguration.class)).when(appConfig).getDmaapConsumerConfiguration(); + DmaapConsumerTaskImpl dmaapConsumerTask = spy(new DmaapConsumerTaskImpl(appConfig)); + DMaaPConsumerReactiveHttpClient dmaapConsumerReactiveHttpClient = mock( + DMaaPConsumerReactiveHttpClient.class); + doReturn(mock(DmaapConsumerConfiguration.class)).when(dmaapConsumerTask).resolveConfiguration(); + doReturn(dmaapConsumerReactiveHttpClient).when(dmaapConsumerTask).resolveClient(); + return dmaapConsumerTask; + } +} diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapProducerTaskSpy.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapProducerTaskSpy.java new file mode 100644 index 00000000..870c712e --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapProducerTaskSpy.java @@ -0,0 +1,59 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; + +import org.onap.dcaegen2.collectors.datafile.config.DmaapPublisherConfiguration; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.service.producer.DMaaPProducerReactiveHttpClient; +import org.onap.dcaegen2.collectors.datafile.tasks.DmaapPublisherTask; +import org.onap.dcaegen2.collectors.datafile.tasks.DmaapPublisherTaskImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/13/18 + */ +@Configuration +public class DmaapProducerTaskSpy { + + /** + * Mocking bean for tests. + * + * @return DMaaP PublisherTask spy + */ + @Bean + @Primary + public DmaapPublisherTask registerSimpleDmaapPublisherTask() { + AppConfig appConfig = spy(AppConfig.class); + doReturn(mock(DmaapPublisherConfiguration.class)).when(appConfig).getDmaapPublisherConfiguration(); + DmaapPublisherTaskImpl dmaapPublisherTask = spy(new DmaapPublisherTaskImpl(appConfig)); + DMaaPProducerReactiveHttpClient extendedDmaapProducerHttpClient = mock( + DMaaPProducerReactiveHttpClient.class); + doReturn(mock(DmaapPublisherConfiguration.class)).when(dmaapPublisherTask).resolveConfiguration(); + doReturn(extendedDmaapProducerHttpClient).when(dmaapPublisherTask).resolveClient(); + return dmaapPublisherTask; + } +} diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapPublisherTaskImplTest.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapPublisherTaskImplTest.java new file mode 100644 index 00000000..2b79bc40 --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/DmaapPublisherTaskImplTest.java @@ -0,0 +1,124 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.function.Executable; +import org.onap.dcaegen2.collectors.datafile.config.DmaapPublisherConfiguration; +import org.onap.dcaegen2.collectors.datafile.configuration.AppConfig; +import org.onap.dcaegen2.collectors.datafile.exceptions.DmaapNotFoundException; +import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.producer.DMaaPProducerReactiveHttpClient; +import org.onap.dcaegen2.collectors.datafile.tasks.DmaapPublisherTaskImpl; +import org.onap.dcaegen2.collectors.datafile.config.ImmutableDmaapPublisherConfiguration; +import org.onap.dcaegen2.collectors.datafile.model.ImmutableConsumerDmaapModel; +import org.springframework.http.HttpStatus; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 5/17/18 + */ +class DmaapPublisherTaskImplTest { + + private static ConsumerDmaapModel consumerDmaapModel; + private static DmaapPublisherTaskImpl dmaapPublisherTask; + private static DMaaPProducerReactiveHttpClient dMaaPProducerReactiveHttpClient; + private static AppConfig appConfig; + private static DmaapPublisherConfiguration dmaapPublisherConfiguration; + + @BeforeAll + static void setUp() { + dmaapPublisherConfiguration = new ImmutableDmaapPublisherConfiguration.Builder() + .dmaapContentType("application/json").dmaapHostName("54.45.33.2").dmaapPortNumber(1234) + .dmaapProtocol("https").dmaapUserName("Datafile").dmaapUserPassword("Datafile") + .dmaapTopicName("unauthenticated.SEC_OTHER_OUTPUT").build(); + consumerDmaapModel = ImmutableConsumerDmaapModel.builder().ipv4("10.16.123.234") + .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") + .pnfName("NOKQTFCOC540002E").build(); + appConfig = mock(AppConfig.class); + } + + @Test + void whenPassedObjectDoesntFit_ThrowsDatafileTaskException() { + //given + when(appConfig.getDmaapPublisherConfiguration()).thenReturn(dmaapPublisherConfiguration); + dmaapPublisherTask = new DmaapPublisherTaskImpl(appConfig); + + //when + Executable executableFunction = () -> dmaapPublisherTask.execute(null); + + //then + assertThrows(DatafileTaskException.class, executableFunction, "The specified parameter is incorrect"); + } + + @Test + void whenPassedObjectFits_ReturnsCorrectStatus() throws DatafileTaskException { + //given + prepareMocksForTests(HttpStatus.OK.value()); + + //when + StepVerifier.create(dmaapPublisherTask.execute(Mono.just(consumerDmaapModel))).expectSubscription() + .expectNext(HttpStatus.OK.toString()).verifyComplete(); + + //then + verify(dMaaPProducerReactiveHttpClient, times(1)) + .getDMaaPProducerResponse(any(Mono.class)); + verifyNoMoreInteractions(dMaaPProducerReactiveHttpClient); + } + + + @Test + void whenPassedObjectFits_butIncorrectResponseReturns() throws DmaapNotFoundException { + //given + prepareMocksForTests(HttpStatus.UNAUTHORIZED.value()); + + //when + StepVerifier.create(dmaapPublisherTask.execute(Mono.just(consumerDmaapModel))).expectSubscription() + .expectNext(String.valueOf(HttpStatus.UNAUTHORIZED.value())).verifyComplete(); + + //then + verify(dMaaPProducerReactiveHttpClient, times(1)).getDMaaPProducerResponse(any(Mono.class)); + verifyNoMoreInteractions(dMaaPProducerReactiveHttpClient); + } + + + private void prepareMocksForTests(Integer httpResponseCode) { + dMaaPProducerReactiveHttpClient = mock(DMaaPProducerReactiveHttpClient.class); + when(dMaaPProducerReactiveHttpClient.getDMaaPProducerResponse(any(Mono.class))) + .thenReturn(Mono.just(httpResponseCode.toString())); + dmaapPublisherTask = spy(new DmaapPublisherTaskImpl(appConfig)); + when(dmaapPublisherTask.resolveConfiguration()).thenReturn(dmaapPublisherConfiguration); + doReturn(dMaaPProducerReactiveHttpClient).when(dmaapPublisherTask).resolveClient(); + } +}
\ No newline at end of file diff --git a/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/ScheduleControllerSpy.java b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/ScheduleControllerSpy.java new file mode 100644 index 00000000..d47d31d1 --- /dev/null +++ b/datafile-app-server/src/test/java/org/onap/dcaegen2/collectors/datafile/tasks/ScheduleControllerSpy.java @@ -0,0 +1,54 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.tasks; + +import static org.mockito.Mockito.spy; + +import org.onap.dcaegen2.collectors.datafile.tasks.AaiProducerTask; +import org.onap.dcaegen2.collectors.datafile.tasks.DmaapConsumerTask; +import org.onap.dcaegen2.collectors.datafile.tasks.DmaapPublisherTask; +import org.onap.dcaegen2.collectors.datafile.tasks.ScheduledTasks; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/5/18 + */ +@Configuration +public class ScheduleControllerSpy { + + @Autowired + private DmaapConsumerTask dmaapConsumerTaskImplSpy; + + @Autowired + private DmaapPublisherTask dmaapPublisherTaskImplSpy; + + @Autowired + private AaiProducerTask aaiPublisherTaskImplSpy; + + @Bean + @Primary + public ScheduledTasks registerSimpleScheduledTask() { + return spy(new ScheduledTasks(dmaapConsumerTaskImplSpy, dmaapPublisherTaskImplSpy, aaiPublisherTaskImplSpy)); + } +} diff --git a/datafile-app-server/src/test/resources/datafile_endpoints.json b/datafile-app-server/src/test/resources/datafile_endpoints.json new file mode 100644 index 00000000..599315b6 --- /dev/null +++ b/datafile-app-server/src/test/resources/datafile_endpoints.json @@ -0,0 +1,47 @@ +{ + "configs": { + "aai": { + "aaiClientConfiguration": { + "aaiHost": "localhost", + "aaiPort": 8080, + "aaiIgnoreSSLCertificateErrors": true, + "aaiProtocol": "https", + "aaiUserName": "AAI", + "aaiUserPassword": "AAI", + "aaiBasePath": "/aai/v11", + "aaiPnfPath": "/network/pnfs/pnf", + "aaiHeaders": { + "X-FromAppId": "datafile", + "X-TransactionId": "9999", + "Accept": "application/json", + "Real-Time": "true", + "Content-Type":"application/merge-patch+json" + } + } + }, + "dmaap": { + "dmaapConsumerConfiguration": { + "consumerGroup": "other", + "consumerId": "1", + "dmaapContentType": "application/json", + "dmaapHostName": "localhost", + "dmaapPortNumber": 2222, + "dmaapProtocol": "http", + "dmaapTopicName": "/events/pnfReady", + "dmaapUserName": "admin", + "dmaapUserPassword": "admin", + "messageLimit": 1000, + "timeoutMS": 1000 + }, + "dmaapProducerConfiguration": { + "dmaapContentType": "application/json", + "dmaapHostName": "localhost", + "dmaapPortNumber": 2223, + "dmaapProtocol": "http", + "dmaapTopicName": "/events/pnfReady", + "dmaapUserName": "admin", + "dmaapUserPassword": "admin" + } + } + } +}
\ No newline at end of file diff --git a/datafile-app-server/src/test/resources/logback-test.xml b/datafile-app-server/src/test/resources/logback-test.xml new file mode 100644 index 00000000..3ff015e7 --- /dev/null +++ b/datafile-app-server/src/test/resources/logback-test.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ ===============================LICENSE_START====================================== + ~ Copyright © 2017 AT&T Intellectual Property. All rights reserved. + ~ ================================================================================ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ ============================LICENSE_END=========================================== + --> +<configuration debug="false"> + <include resource="org/springframework/boot/logging/logback/base.xml"/> + <logger name="org.onap.dcaegen2.collectors.datafile" level="DEBUG"/> + <appender name="Console" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>%d{ISO8601} - %-5p [%t:%C{1}@%L] - %m%n</pattern> + </encoder> + </appender> + + <root level="ERROR"> + <appender-ref ref="Console"/> + </root> + + +</configuration> diff --git a/datafile-commons/pom.xml b/datafile-commons/pom.xml new file mode 100644 index 00000000..1af046b9 --- /dev/null +++ b/datafile-commons/pom.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <artifactId>datafile</artifactId> + <groupId>org.onap.dcaegen2.collectors</groupId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <artifactId>datafile-commons</artifactId> + <groupId>org.onap.dcaegen2.collectors.datafile</groupId> + <version>1.0.0-SNAPSHOT</version> + <packaging>jar</packaging> + + <properties> + <main.basedir>${project.parent.basedir}</main.basedir> + </properties> + <dependencies> + <dependency> + <groupId>org.immutables</groupId> + <artifactId>value</artifactId> + </dependency> + <dependency> + <groupId>org.immutables</groupId> + <artifactId>gson</artifactId> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + + <!-- TEST DEPENDENCIES--> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + + <!-- LOGGING DEPENDENCIES--> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jul-to-slf4j</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>log4j-over-slf4j</artifactId> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/datafile-commons/src/main/java/org/onap/dcaegen2/collectors/datafile/model/CommonFunctions.java b/datafile-commons/src/main/java/org/onap/dcaegen2/collectors/datafile/model/CommonFunctions.java new file mode 100644 index 00000000..cc46ab80 --- /dev/null +++ b/datafile-commons/src/main/java/org/onap/dcaegen2/collectors/datafile/model/CommonFunctions.java @@ -0,0 +1,48 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.model; + +import com.google.gson.GsonBuilder; +import com.google.gson.TypeAdapterFactory; +import java.util.ServiceLoader; + +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.model.ImmutableConsumerDmaapModel; + + +public class CommonFunctions { + + private CommonFunctions() { + } + + /** + * Method for serialization object by GSON. + * + * @param consumerDmaapModel - object which will be serialized + * @return string from serialization + */ + public static String createJsonBody(ConsumerDmaapModel consumerDmaapModel) { + GsonBuilder gsonBuilder = new GsonBuilder(); + ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory); + return gsonBuilder.create().toJson(ImmutableConsumerDmaapModel.builder().ipv4(consumerDmaapModel.getIpv4()) + .ipv6(consumerDmaapModel.getIpv6()).pnfName(consumerDmaapModel.getPnfName()).build()); + } +} diff --git a/datafile-commons/src/main/java/org/onap/dcaegen2/collectors/datafile/model/ConsumerDmaapModel.java b/datafile-commons/src/main/java/org/onap/dcaegen2/collectors/datafile/model/ConsumerDmaapModel.java new file mode 100644 index 00000000..3da08d7c --- /dev/null +++ b/datafile-commons/src/main/java/org/onap/dcaegen2/collectors/datafile/model/ConsumerDmaapModel.java @@ -0,0 +1,43 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.model; + +import com.google.gson.annotations.SerializedName; +import org.immutables.gson.Gson; +import org.immutables.value.Value; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 5/8/18 + */ + +@Value.Immutable +@Gson.TypeAdapters(fieldNamingStrategy = true) +public interface ConsumerDmaapModel { + + @SerializedName(value = "pnf-name", alternate = "pnf-name") + String getPnfName(); + + @SerializedName(value = "ipaddress-v4-oam", alternate = "ipaddress-v4-oam") + String getIpv4(); + + @SerializedName(value = "ipaddress-v6-oam", alternate = "ipaddress-v6-oam") + String getIpv6(); +} diff --git a/datafile-commons/src/main/java/org/onap/dcaegen2/collectors/datafile/model/ConsumerDmaapModelForUnitTest.java b/datafile-commons/src/main/java/org/onap/dcaegen2/collectors/datafile/model/ConsumerDmaapModelForUnitTest.java new file mode 100644 index 00000000..ad7bbd8e --- /dev/null +++ b/datafile-commons/src/main/java/org/onap/dcaegen2/collectors/datafile/model/ConsumerDmaapModelForUnitTest.java @@ -0,0 +1,53 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.model; + +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; + +public class ConsumerDmaapModelForUnitTest implements ConsumerDmaapModel { + + private final String pnfName; + private final String ipv4; + private final String ipv6; + + /** + * Class for testing serialization of ConsumerDmaapModel. + */ + public ConsumerDmaapModelForUnitTest() { + this.pnfName = "NOKnhfsadhff"; + this.ipv4 = "256.22.33.155"; + this.ipv6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; + + } + + public String getPnfName() { + return pnfName; + } + + public String getIpv4() { + return ipv4; + } + + public String getIpv6() { + return ipv6; + } + +} diff --git a/datafile-commons/src/main/java/org/onap/dcaegen2/collectors/datafile/model/utils/HttpUtils.java b/datafile-commons/src/main/java/org/onap/dcaegen2/collectors/datafile/model/utils/HttpUtils.java new file mode 100644 index 00000000..0b351ae6 --- /dev/null +++ b/datafile-commons/src/main/java/org/onap/dcaegen2/collectors/datafile/model/utils/HttpUtils.java @@ -0,0 +1,32 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.model.utils; + +import org.apache.http.HttpStatus; + +public final class HttpUtils implements HttpStatus { + + private HttpUtils() {} + + public static boolean isSuccessfulResponseCode(Integer statusCode) { + return statusCode >= 200 && statusCode < 300; + } +} diff --git a/datafile-commons/src/test/java/org/onap/dcaegen2/collectors/datafile/model/CommonFunctionsTest.java b/datafile-commons/src/test/java/org/onap/dcaegen2/collectors/datafile/model/CommonFunctionsTest.java new file mode 100644 index 00000000..d3a0fb18 --- /dev/null +++ b/datafile-commons/src/test/java/org/onap/dcaegen2/collectors/datafile/model/CommonFunctionsTest.java @@ -0,0 +1,57 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.collectors.datafile.model.CommonFunctions; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModelForUnitTest; + +class CommonFunctionsTest { + + // Given + private ConsumerDmaapModel model = new ConsumerDmaapModelForUnitTest(); + + private static final HttpResponse httpResponseMock = mock(HttpResponse.class); + private static final HttpEntity httpEntityMock = mock(HttpEntity.class); + private static final StatusLine statusLineMock = mock(StatusLine.class); + + @BeforeAll + static void setup() { + when(httpResponseMock.getEntity()).thenReturn(httpEntityMock); + when(httpResponseMock.getStatusLine()).thenReturn(statusLineMock); + } + + @Test + void createJsonBody_shouldReturnJsonInString() { + String expectedResult = "{\"pnf-name\":\"NOKnhfsadhff\",\"ipaddress-v4-oam\":\"256.22.33.155\"" + + ",\"ipaddress-v6-oam\":\"2001:0db8:85a3:0000:0000:8a2e:0370:7334\"}"; + assertEquals(expectedResult, CommonFunctions.createJsonBody(model)); + } +} diff --git a/datafile-commons/src/test/java/org/onap/dcaegen2/collectors/datafile/model/ConsumerDmaapModelTest.java b/datafile-commons/src/test/java/org/onap/dcaegen2/collectors/datafile/model/ConsumerDmaapModelTest.java new file mode 100644 index 00000000..50eb434b --- /dev/null +++ b/datafile-commons/src/test/java/org/onap/dcaegen2/collectors/datafile/model/ConsumerDmaapModelTest.java @@ -0,0 +1,50 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.model; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.model.ImmutableConsumerDmaapModel; + +class ConsumerDmaapModelTest { + + @Test + void consumerDmaapModelBuilder_shouldBuildAnObject() { + + // When + // Given + String pnfName = "NOKnhfsadhff"; + String ipv4 = "11.22.33.155"; + String ipv6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; + ConsumerDmaapModel consumerDmaapModel = ImmutableConsumerDmaapModel.builder() + .pnfName(pnfName) + .ipv4(ipv4) + .ipv6(ipv6) + .build(); + + // Then + Assertions.assertNotNull(consumerDmaapModel); + Assertions.assertEquals(pnfName, consumerDmaapModel.getPnfName()); + Assertions.assertEquals(ipv4, consumerDmaapModel.getIpv4()); + Assertions.assertEquals(ipv6, consumerDmaapModel.getIpv6()); + } +} diff --git a/datafile-commons/src/test/java/org/onap/dcaegen2/collectors/datafile/model/utils/HttpUtilsTest.java b/datafile-commons/src/test/java/org/onap/dcaegen2/collectors/datafile/model/utils/HttpUtilsTest.java new file mode 100644 index 00000000..544470a4 --- /dev/null +++ b/datafile-commons/src/test/java/org/onap/dcaegen2/collectors/datafile/model/utils/HttpUtilsTest.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.model.utils; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.apache.http.HttpStatus; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.collectors.datafile.model.utils.HttpUtils; + +class HttpUtilsTest { + + @Test + void isSuccessfulResponseCode_shouldReturnTrue() { + assertTrue(HttpUtils.isSuccessfulResponseCode(HttpUtils.SC_ACCEPTED)); + } + + @Test + void isSuccessfulResponseCode_shouldReturnFalse() { + assertFalse(HttpUtils.isSuccessfulResponseCode(HttpStatus.SC_BAD_GATEWAY)); + } +}
\ No newline at end of file diff --git a/datafile-dmaap-client/pom.xml b/datafile-dmaap-client/pom.xml new file mode 100644 index 00000000..86e41c38 --- /dev/null +++ b/datafile-dmaap-client/pom.xml @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ ============LICENSE_START======================================================= + ~ Datafile Collector Service + ~ ================================================================================ + ~ Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + ~ ================================================================================ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ ============LICENSE_END========================================================= + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>datafile</artifactId> + <groupId>org.onap.dcaegen2.collectors</groupId> + <version>1.0.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>datafile-dmaap-client</artifactId> + <groupId>org.onap.dcaegen2.collectors.datafile</groupId> + <packaging>jar</packaging> + + + <properties> + <main.basedir>${project.parent.basedir}</main.basedir> + </properties> + <dependencies> + + <!-- DEVELOPMENT DEPENDENCIES --> + <dependency> + <groupId>org.immutables</groupId> + <artifactId>value</artifactId> + </dependency> + <dependency> + <groupId>org.immutables</groupId> + <artifactId>gson</artifactId> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-webflux</artifactId> + <version>5.0.5.RELEASE</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-reactor-netty</artifactId> + <version>2.0.4.RELEASE</version> + </dependency> + <dependency> + <groupId>org.onap.dcaegen2.collectors.datafile</groupId> + <artifactId>datafile-commons</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + + + <!-- LOGGING DEPENDENCIES --> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jul-to-slf4j</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>log4j-over-slf4j</artifactId> + </dependency> + + + <!-- TEST DEPENDENCIES--> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.vintage</groupId> + <artifactId>junit-vintage-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.projectreactor</groupId> + <artifactId>reactor-test</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/config/DmaapConsumerConfiguration.java b/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/config/DmaapConsumerConfiguration.java new file mode 100644 index 00000000..57b11127 --- /dev/null +++ b/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/config/DmaapConsumerConfiguration.java @@ -0,0 +1,68 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.config; + +import org.immutables.gson.Gson; +import org.immutables.value.Value; +import org.onap.dcaegen2.collectors.datafile.config.ImmutableDmaapConsumerConfiguration; +import org.springframework.stereotype.Component; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/23/18 + */ +@Component +@Value.Immutable(prehash = true) +@Value.Style(builder = "new") +@Gson.TypeAdapters +public abstract class DmaapConsumerConfiguration implements DmaapCustomConfig { + + private static final long serialVersionUID = 1L; + + @Value.Parameter + public abstract String consumerId(); + + @Value.Parameter + public abstract String consumerGroup(); + + @Value.Parameter + public abstract Integer timeoutMs(); + + @Value.Parameter + public abstract Integer messageLimit(); + + + public interface Builder extends + DmaapCustomConfig.Builder<DmaapConsumerConfiguration, DmaapConsumerConfiguration.Builder> { + + Builder consumerId(String consumerId); + + Builder consumerGroup(String consumerGroup); + + Builder timeoutMs(Integer timeoutMs); + + Builder messageLimit(Integer messageLimit); + } + + public static DmaapConsumerConfiguration.Builder builder() { + return ImmutableDmaapConsumerConfiguration.builder(); + } + +}
\ No newline at end of file diff --git a/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/config/DmaapCustomConfig.java b/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/config/DmaapCustomConfig.java new file mode 100644 index 00000000..31bbfc0e --- /dev/null +++ b/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/config/DmaapCustomConfig.java @@ -0,0 +1,72 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.config; + +import java.io.Serializable; + +import org.immutables.value.Value; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/28/18 + */ +public interface DmaapCustomConfig extends Serializable { + + @Value.Parameter + String dmaapHostName(); + + @Value.Parameter + Integer dmaapPortNumber(); + + @Value.Parameter + String dmaapTopicName(); + + @Value.Parameter + String dmaapProtocol(); + + @Value.Parameter + String dmaapUserName(); + + @Value.Parameter + String dmaapUserPassword(); + + @Value.Parameter + String dmaapContentType(); + + + interface Builder<T extends DmaapCustomConfig, B extends Builder<T, B>> { + + B dmaapHostName(String dmaapHostName); + + B dmaapPortNumber(Integer dmaapPortNumber); + + B dmaapTopicName(String dmaapTopicName); + + B dmaapProtocol(String dmaapProtocol); + + B dmaapUserName(String dmaapUserName); + + B dmaapUserPassword(String dmaapUserPassword); + + B dmaapContentType(String dmaapContentType); + + T build(); + } +} diff --git a/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/config/DmaapPublisherConfiguration.java b/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/config/DmaapPublisherConfiguration.java new file mode 100644 index 00000000..cd520569 --- /dev/null +++ b/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/config/DmaapPublisherConfiguration.java @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.config; + +import org.immutables.gson.Gson; +import org.immutables.value.Value; +import org.onap.dcaegen2.collectors.datafile.config.DmaapCustomConfig; +import org.onap.dcaegen2.collectors.datafile.config.DmaapPublisherConfiguration; +import org.onap.dcaegen2.collectors.datafile.config.ImmutableDmaapPublisherConfiguration; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/23/18 + */ +@Value.Immutable(prehash = true) +@Value.Style(builder = "new") +@Gson.TypeAdapters +public abstract class DmaapPublisherConfiguration implements DmaapCustomConfig { + + private static final long serialVersionUID = 1L; + + interface Builder extends + DmaapCustomConfig.Builder<DmaapPublisherConfiguration, DmaapPublisherConfiguration.Builder> { + + } + + public static DmaapPublisherConfiguration.Builder builder() { + return ImmutableDmaapPublisherConfiguration.builder(); + } +} diff --git a/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/DMaaPReactiveWebClient.java b/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/DMaaPReactiveWebClient.java new file mode 100644 index 00000000..b4cbfeea --- /dev/null +++ b/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/DMaaPReactiveWebClient.java @@ -0,0 +1,88 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service; + +import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication; + +import org.onap.dcaegen2.collectors.datafile.config.DmaapCustomConfig; +import org.onap.dcaegen2.collectors.datafile.service.DMaaPReactiveWebClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 7/4/18 + */ +public class DMaaPReactiveWebClient { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private String dmaaPContentType; + private String dmaaPUserName; + private String dmaaPUserPassword; + + /** + * Creating DMaaPReactiveWebClient passing to them basic DMaaPConfig. + * + * @param dmaapCustomConfig - configuration object + * @return DMaaPReactiveWebClient + */ + public DMaaPReactiveWebClient fromConfiguration(DmaapCustomConfig dmaapCustomConfig) { + this.dmaaPUserName = dmaapCustomConfig.dmaapUserName(); + this.dmaaPUserPassword = dmaapCustomConfig.dmaapUserPassword(); + this.dmaaPContentType = dmaapCustomConfig.dmaapContentType(); + return this; + } + + /** + * Construct Reactive WebClient with appropriate settings. + * + * @return WebClient + */ + public WebClient build() { + return WebClient.builder() + .defaultHeader(HttpHeaders.CONTENT_TYPE, dmaaPContentType) + .filter(basicAuthentication(dmaaPUserName, dmaaPUserPassword)) + .filter(logRequest()) + .filter(logResponse()) + .build(); + } + + private ExchangeFilterFunction logResponse() { + return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { + logger.info("Response Status {}", clientResponse.statusCode()); + return Mono.just(clientResponse); + }); + } + + private ExchangeFilterFunction logRequest() { + return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> { + logger.info("Request: {} {}", clientRequest.method(), clientRequest.url()); + clientRequest.headers() + .forEach((name, values) -> values.forEach(value -> logger.info("{}={}", name, value))); + return Mono.just(clientRequest); + }); + } + +} diff --git a/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/consumer/DMaaPConsumerReactiveHttpClient.java b/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/consumer/DMaaPConsumerReactiveHttpClient.java new file mode 100644 index 00000000..1fcebeac --- /dev/null +++ b/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/consumer/DMaaPConsumerReactiveHttpClient.java @@ -0,0 +1,99 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service.consumer; + +import java.net.URI; +import java.net.URISyntaxException; +import org.apache.http.client.utils.URIBuilder; +import org.onap.dcaegen2.collectors.datafile.config.DmaapConsumerConfiguration; +import org.onap.dcaegen2.collectors.datafile.service.consumer.DMaaPConsumerReactiveHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 6/26/18 + */ +public class DMaaPConsumerReactiveHttpClient { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private WebClient webClient; + private final String dmaapHostName; + private final String dmaapProtocol; + private final Integer dmaapPortNumber; + private final String dmaapTopicName; + private final String consumerGroup; + private final String consumerId; + + /** + * Constructor of DMaaPConsumerReactiveHttpClient. + * + * @param consumerConfiguration - DMaaP consumer configuration object + */ + public DMaaPConsumerReactiveHttpClient(DmaapConsumerConfiguration consumerConfiguration) { + this.dmaapHostName = consumerConfiguration.dmaapHostName(); + this.dmaapProtocol = consumerConfiguration.dmaapProtocol(); + this.dmaapPortNumber = consumerConfiguration.dmaapPortNumber(); + this.dmaapTopicName = consumerConfiguration.dmaapTopicName(); + this.consumerGroup = consumerConfiguration.consumerGroup(); + this.consumerId = consumerConfiguration.consumerId(); + } + + /** + * Function for calling DMaaP HTTP consumer - consuming messages from Kafka/DMaaP from topic. + * + * @return reactive response from DMaaP in string format + */ + public Mono<String> getDMaaPConsumerResponse() { + try { + return webClient + .get() + .uri(getUri()) + .retrieve() + .onStatus(HttpStatus::is4xxClientError, clientResponse -> + Mono.error(new Exception("HTTP 400")) + ) + .onStatus(HttpStatus::is5xxServerError, clientResponse -> + Mono.error(new Exception("HTTP 500"))) + .bodyToMono(String.class); + } catch (URISyntaxException e) { + logger.warn("Exception while evaluating URI "); + return Mono.error(e); + } + } + + private String createRequestPath() { + return dmaapTopicName + "/" + consumerGroup + "/" + consumerId; + } + + public DMaaPConsumerReactiveHttpClient createDMaaPWebClient(WebClient webClient) { + this.webClient = webClient; + return this; + } + + URI getUri() throws URISyntaxException { + return new URIBuilder().setScheme(dmaapProtocol).setHost(dmaapHostName).setPort(dmaapPortNumber) + .setPath(createRequestPath()).build(); + } +} diff --git a/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/producer/DMaaPProducerReactiveHttpClient.java b/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/producer/DMaaPProducerReactiveHttpClient.java new file mode 100644 index 00000000..c6889df4 --- /dev/null +++ b/datafile-dmaap-client/src/main/java/org/onap/dcaegen2/collectors/datafile/service/producer/DMaaPProducerReactiveHttpClient.java @@ -0,0 +1,96 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service.producer; + +import java.net.URI; +import java.net.URISyntaxException; +import org.apache.http.client.utils.URIBuilder; +import org.onap.dcaegen2.collectors.datafile.config.DmaapPublisherConfiguration; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.service.producer.DMaaPProducerReactiveHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 7/4/18 + */ +public class DMaaPProducerReactiveHttpClient { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private WebClient webClient; + private final String dmaapHostName; + private final Integer dmaapPortNumber; + private final String dmaapProtocol; + private final String dmaapTopicName; + + /** + * Constructor DMaaPProducerReactiveHttpClient. + * + * @param dmaapPublisherConfiguration - DMaaP producer configuration object + */ + public DMaaPProducerReactiveHttpClient(DmaapPublisherConfiguration dmaapPublisherConfiguration) { + this.dmaapHostName = dmaapPublisherConfiguration.dmaapHostName(); + this.dmaapProtocol = dmaapPublisherConfiguration.dmaapProtocol(); + this.dmaapPortNumber = dmaapPublisherConfiguration.dmaapPortNumber(); + this.dmaapTopicName = dmaapPublisherConfiguration.dmaapTopicName(); + } + + /** + * Function for calling DMaaP HTTP producer - post request to DMaaP. + * + * @param consumerDmaapModelMono - object which will be sent to DMaaP + * @return status code of operation + */ + public Mono<String> getDMaaPProducerResponse(Mono<ConsumerDmaapModel> consumerDmaapModelMono) { + try { + return webClient + .post() + .uri(getUri()) + .body(BodyInserters.fromObject(consumerDmaapModelMono)) + .retrieve() + .onStatus(HttpStatus::is4xxClientError, clientResponse -> + Mono.error(new Exception("HTTP 400")) + ) + .onStatus(HttpStatus::is5xxServerError, clientResponse -> + Mono.error(new Exception("HTTP 500"))) + .bodyToMono(String.class); + } catch (URISyntaxException e) { + logger.warn("Exception while evaluating URI"); + return Mono.error(e); + } + } + + public DMaaPProducerReactiveHttpClient createDMaaPWebClient(WebClient webClient) { + this.webClient = webClient; + return this; + } + + URI getUri() throws URISyntaxException { + return new URIBuilder().setScheme(dmaapProtocol).setHost(dmaapHostName).setPort(dmaapPortNumber) + .setPath(dmaapTopicName).build(); + } + +} diff --git a/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/DMaaPReactiveWebClientTest.java b/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/DMaaPReactiveWebClientTest.java new file mode 100644 index 00000000..dea22340 --- /dev/null +++ b/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/DMaaPReactiveWebClientTest.java @@ -0,0 +1,58 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.collectors.datafile.config.DmaapConsumerConfiguration; +import org.onap.dcaegen2.collectors.datafile.service.DMaaPReactiveWebClient; +import org.springframework.web.reactive.function.client.WebClient; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 7/5/18 + */ +class DMaaPReactiveWebClientTest { + + + @Test + void builder_shouldBuildDMaaPReactiveWebClient() { + //given + DmaapConsumerConfiguration dmaapConsumerConfiguration = mock(DmaapConsumerConfiguration.class); + String dmaaPContentType = "*/*"; + String dmaaPUserName = "DMaaP"; + String dmaaPUserPassword = "DMaaP"; + + //when + when(dmaapConsumerConfiguration.dmaapContentType()).thenReturn(dmaaPContentType); + when(dmaapConsumerConfiguration.dmaapUserName()).thenReturn(dmaaPUserName); + when(dmaapConsumerConfiguration.dmaapUserPassword()).thenReturn(dmaaPUserPassword); + WebClient dmaapreactiveWebClient = new DMaaPReactiveWebClient() + .fromConfiguration(dmaapConsumerConfiguration) + .build(); + + //then + Assertions.assertNotNull(dmaapreactiveWebClient); + + } +}
\ No newline at end of file diff --git a/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/config/DmaapConsumerConfigurationTest.java b/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/config/DmaapConsumerConfigurationTest.java new file mode 100644 index 00000000..d0943709 --- /dev/null +++ b/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/config/DmaapConsumerConfigurationTest.java @@ -0,0 +1,75 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service.config; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.collectors.datafile.config.DmaapConsumerConfiguration; +import org.onap.dcaegen2.collectors.datafile.config.ImmutableDmaapConsumerConfiguration; + +class DmaapConsumerConfigurationTest { + + @Test + void builder_shouldBuildConfigurationObject() { + + // Given + DmaapConsumerConfiguration configuration; + String consumerId = "1"; + String dmaapHostName = "localhost"; + Integer dmaapPortNumber = 2222; + String dmaapTopicName = "temp"; + String dmaapProtocol = "http"; + String dmaapUserName = "admin"; + String dmaapUserPassword = "admin"; + String dmaapContentType = "application/json"; + String consumerGroup = "other"; + Integer timeoutMs = 1000; + Integer messageLimit = 1000; + + // When + configuration = new ImmutableDmaapConsumerConfiguration.Builder() + .consumerId(consumerId) + .dmaapHostName(dmaapHostName) + .dmaapPortNumber(dmaapPortNumber) + .dmaapTopicName(dmaapTopicName) + .dmaapProtocol(dmaapProtocol) + .dmaapUserName(dmaapUserName) + .dmaapUserPassword(dmaapUserPassword) + .dmaapContentType(dmaapContentType) + .consumerGroup(consumerGroup) + .timeoutMs(timeoutMs) + .messageLimit(messageLimit) + .build(); + + // Then + Assertions.assertNotNull(configuration); + Assertions.assertEquals(consumerId, configuration.consumerId()); + Assertions.assertEquals(dmaapHostName, configuration.dmaapHostName()); + Assertions.assertEquals(dmaapPortNumber, configuration.dmaapPortNumber()); + Assertions.assertEquals(dmaapTopicName, configuration.dmaapTopicName()); + Assertions.assertEquals(dmaapProtocol, configuration.dmaapProtocol()); + Assertions.assertEquals(dmaapUserName, configuration.dmaapUserName()); + Assertions.assertEquals(dmaapUserPassword, configuration.dmaapUserPassword()); + Assertions.assertEquals(consumerGroup, configuration.consumerGroup()); + Assertions.assertEquals(timeoutMs, configuration.timeoutMs()); + Assertions.assertEquals(messageLimit, configuration.messageLimit()); + } +} diff --git a/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/config/DmaapPublisherConfigurationTest.java b/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/config/DmaapPublisherConfigurationTest.java new file mode 100644 index 00000000..a188921c --- /dev/null +++ b/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/config/DmaapPublisherConfigurationTest.java @@ -0,0 +1,64 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service.config; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.collectors.datafile.config.DmaapPublisherConfiguration; +import org.onap.dcaegen2.collectors.datafile.config.ImmutableDmaapPublisherConfiguration; + +class DmaapPublisherConfigurationTest { + + + @Test + void builder_shouldBuildConfigurationObject() { + + // Given + DmaapPublisherConfiguration configuration; + String dmaapHostName = "localhost"; + Integer dmaapPortNumber = 2222; + String dmaapTopicName = "temp"; + String dmaapProtocol = "http"; + String dmaapUserName = "admin"; + String dmaapUserPassword = "admin"; + String dmaapContentType = "application/json"; + + // When + configuration = new ImmutableDmaapPublisherConfiguration.Builder() + .dmaapHostName(dmaapHostName) + .dmaapPortNumber(dmaapPortNumber) + .dmaapTopicName(dmaapTopicName) + .dmaapProtocol(dmaapProtocol) + .dmaapUserName(dmaapUserName) + .dmaapUserPassword(dmaapUserPassword) + .dmaapContentType(dmaapContentType) + .build(); + + // Then + Assertions.assertNotNull(configuration); + Assertions.assertEquals(dmaapHostName, configuration.dmaapHostName()); + Assertions.assertEquals(dmaapPortNumber, configuration.dmaapPortNumber()); + Assertions.assertEquals(dmaapTopicName, configuration.dmaapTopicName()); + Assertions.assertEquals(dmaapProtocol, configuration.dmaapProtocol()); + Assertions.assertEquals(dmaapUserName, configuration.dmaapUserName()); + Assertions.assertEquals(dmaapUserPassword, configuration.dmaapUserPassword()); + } +} diff --git a/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/consumer/DMaaPConsumerReactiveHttpClientTest.java b/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/consumer/DMaaPConsumerReactiveHttpClientTest.java new file mode 100644 index 00000000..abac3cd5 --- /dev/null +++ b/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/consumer/DMaaPConsumerReactiveHttpClientTest.java @@ -0,0 +1,122 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service.consumer; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; +import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication; + +import java.net.URI; +import java.net.URISyntaxException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.collectors.datafile.config.DmaapConsumerConfiguration; +import org.onap.dcaegen2.collectors.datafile.service.consumer.DMaaPConsumerReactiveHttpClient; +import org.springframework.http.HttpHeaders; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClient.RequestHeadersUriSpec; +import org.springframework.web.reactive.function.client.WebClient.ResponseSpec; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 6/27/18 + */ +class DMaaPConsumerReactiveHttpClientTest { + + private DMaaPConsumerReactiveHttpClient dmaapConsumerReactiveHttpClient; + + private DmaapConsumerConfiguration consumerConfigurationMock = mock(DmaapConsumerConfiguration.class); + private static final String JSON_MESSAGE = "{ \"responseFromDmaap\": \"Success\"}"; + private Mono<String> expectedResult = Mono.empty(); + private WebClient webClient; + private RequestHeadersUriSpec requestHeadersSpec; + private ResponseSpec responseSpec; + + + @BeforeEach + void setUp() { + when(consumerConfigurationMock.dmaapHostName()).thenReturn("54.45.33.2"); + when(consumerConfigurationMock.dmaapProtocol()).thenReturn("https"); + when(consumerConfigurationMock.dmaapPortNumber()).thenReturn(1234); + when(consumerConfigurationMock.dmaapUserName()).thenReturn("Datafile"); + when(consumerConfigurationMock.dmaapUserPassword()).thenReturn("Datafile"); + when(consumerConfigurationMock.dmaapContentType()).thenReturn("application/json"); + when(consumerConfigurationMock.dmaapTopicName()).thenReturn("unauthenticated.SEC_OTHER_OUTPUT"); + when(consumerConfigurationMock.consumerGroup()).thenReturn("OpenDCAE-c12"); + when(consumerConfigurationMock.consumerId()).thenReturn("c12"); + + dmaapConsumerReactiveHttpClient = new DMaaPConsumerReactiveHttpClient(consumerConfigurationMock); + webClient = spy(WebClient.builder() + .defaultHeader(HttpHeaders.CONTENT_TYPE, consumerConfigurationMock.dmaapContentType()) + .filter(basicAuthentication(consumerConfigurationMock.dmaapUserName(), + consumerConfigurationMock.dmaapUserPassword())) + .build()); + requestHeadersSpec = mock(RequestHeadersUriSpec.class); + responseSpec = mock(ResponseSpec.class); + } + + + @Test + void getHttpResponse_Success() { + //given + expectedResult = Mono.just(JSON_MESSAGE); + + //when + mockDependantObjects(); + doReturn(expectedResult).when(responseSpec).bodyToMono(String.class); + dmaapConsumerReactiveHttpClient.createDMaaPWebClient(webClient); + Mono<String> response = dmaapConsumerReactiveHttpClient.getDMaaPConsumerResponse(); + + //then + StepVerifier.create(response).expectSubscription() + .expectNextMatches(results -> { + Assertions.assertEquals(results, expectedResult.block()); + return true; + }).verifyComplete(); + } + + @Test + void getHttpResponse_whenUriSyntaxExceptionHasBeenThrown() throws URISyntaxException { + //given + dmaapConsumerReactiveHttpClient = spy(dmaapConsumerReactiveHttpClient); + //when + when(webClient.get()).thenReturn(requestHeadersSpec); + dmaapConsumerReactiveHttpClient.createDMaaPWebClient(webClient); + when(dmaapConsumerReactiveHttpClient.getUri()).thenThrow(URISyntaxException.class); + + //then + StepVerifier.create(dmaapConsumerReactiveHttpClient.getDMaaPConsumerResponse()).expectSubscription() + .expectError(Exception.class).verify(); + } + + private void mockDependantObjects() { + when(webClient.get()).thenReturn(requestHeadersSpec); + when(requestHeadersSpec.uri((URI) any())).thenReturn(requestHeadersSpec); + when(requestHeadersSpec.retrieve()).thenReturn(responseSpec); + doReturn(responseSpec).when(responseSpec).onStatus(any(), any()); + } + +}
\ No newline at end of file diff --git a/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/producer/DMaaPProducerReactiveHttpClientTest.java b/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/producer/DMaaPProducerReactiveHttpClientTest.java new file mode 100644 index 00000000..bb1ce19d --- /dev/null +++ b/datafile-dmaap-client/src/test/java/org/onap/dcaegen2/collectors/datafile/service/producer/DMaaPProducerReactiveHttpClientTest.java @@ -0,0 +1,121 @@ +/* + * ============LICENSE_START======================================================= + * Datafile Collector Service + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.collectors.datafile.service.producer; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; +import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication; + +import java.net.URI; +import java.net.URISyntaxException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.collectors.datafile.config.DmaapPublisherConfiguration; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModel; +import org.onap.dcaegen2.collectors.datafile.model.ConsumerDmaapModelForUnitTest; +import org.onap.dcaegen2.collectors.datafile.service.producer.DMaaPProducerReactiveHttpClient; +import org.springframework.http.HttpHeaders; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClient.RequestBodyUriSpec; +import org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec; +import org.springframework.web.reactive.function.client.WebClient.ResponseSpec; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 7/4/18 + */ +class DMaaPProducerReactiveHttpClientTest { + + private DMaaPProducerReactiveHttpClient dmaapProducerReactiveHttpClient; + + private DmaapPublisherConfiguration dmaapPublisherConfigurationMock = mock( + DmaapPublisherConfiguration.class); + private ConsumerDmaapModel consumerDmaapModel = new ConsumerDmaapModelForUnitTest(); + private WebClient webClient = mock(WebClient.class); + private RequestBodyUriSpec requestBodyUriSpec; + private ResponseSpec responseSpec; + + + @BeforeEach + void setUp() { + when(dmaapPublisherConfigurationMock.dmaapHostName()).thenReturn("54.45.33.2"); + when(dmaapPublisherConfigurationMock.dmaapProtocol()).thenReturn("https"); + when(dmaapPublisherConfigurationMock.dmaapPortNumber()).thenReturn(1234); + when(dmaapPublisherConfigurationMock.dmaapUserName()).thenReturn("Datafile"); + when(dmaapPublisherConfigurationMock.dmaapUserPassword()).thenReturn("Datafile"); + when(dmaapPublisherConfigurationMock.dmaapContentType()).thenReturn("application/json"); + when(dmaapPublisherConfigurationMock.dmaapTopicName()).thenReturn("pnfReady"); + + dmaapProducerReactiveHttpClient = new DMaaPProducerReactiveHttpClient(dmaapPublisherConfigurationMock); + + webClient = spy(WebClient.builder() + .defaultHeader(HttpHeaders.CONTENT_TYPE, dmaapPublisherConfigurationMock.dmaapContentType()) + .filter(basicAuthentication(dmaapPublisherConfigurationMock.dmaapUserName(), + dmaapPublisherConfigurationMock.dmaapUserPassword())) + .build()); + requestBodyUriSpec = mock(RequestBodyUriSpec.class); + responseSpec = mock(ResponseSpec.class); + } + + @Test + void getHttpResponse_Success() { + //given + Integer responseSuccess = 200; + Mono<Integer> expectedResult = Mono.just(responseSuccess); + + //when + mockWebClientDependantObject(); + doReturn(expectedResult).when(responseSpec).bodyToMono(String.class); + dmaapProducerReactiveHttpClient.createDMaaPWebClient(webClient); + Mono<String> response = dmaapProducerReactiveHttpClient.getDMaaPProducerResponse(Mono.just(consumerDmaapModel)); + + //then + Assertions.assertEquals(response.block(), expectedResult.block()); + } + + @Test + void getHttpResponse_whenUriSyntaxExceptionHasBeenThrown() throws URISyntaxException { + //given + dmaapProducerReactiveHttpClient = spy(dmaapProducerReactiveHttpClient); + //when + when(webClient.post()).thenReturn(requestBodyUriSpec); + dmaapProducerReactiveHttpClient.createDMaaPWebClient(webClient); + when(dmaapProducerReactiveHttpClient.getUri()).thenThrow(URISyntaxException.class); + + //then + StepVerifier.create(dmaapProducerReactiveHttpClient.getDMaaPProducerResponse(any())).expectSubscription() + .expectError(Exception.class).verify(); + } + + private void mockWebClientDependantObject() { + RequestHeadersSpec requestHeadersSpec = mock(RequestHeadersSpec.class); + when(webClient.post()).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.uri((URI) any())).thenReturn(requestBodyUriSpec); + when(requestBodyUriSpec.body(any())).thenReturn(requestHeadersSpec); + doReturn(responseSpec).when(requestHeadersSpec).retrieve(); + doReturn(responseSpec).when(responseSpec).onStatus(any(), any()); + } +}
\ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..7feaa6b9 --- /dev/null +++ b/pom.xml @@ -0,0 +1,684 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ ============LICENSE_START======================================================= + ~ Datafile Collector Service + ~ ================================================================================ + ~ Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + ~ ================================================================================ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ ============LICENSE_END========================================================= + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.onap.oparent</groupId> + <artifactId>oparent</artifactId> + <version>0.1.1</version> + <relativePath/> + </parent> + <groupId>org.onap.dcaegen2.collectors</groupId> + <artifactId>datafile</artifactId> + <version>1.0.0-SNAPSHOT</version> + <name>dcaegen2-collectors-datafile</name> + <description>Datafile Collector Service</description> + <packaging>pom</packaging> + + <licenses> + <license> + <name>The Apache Software License, Version 2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> + </license> + </licenses> + + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + + <!-- JAVA VERSION--> + <java.version>8</java.version> + <compiler.plugin.version>3.7.0</compiler.plugin.version> + <tomcat.version>8.5.28</tomcat.version> + <docker.maven.version>1.0.0</docker.maven.version> + <resource.maven.plugin.version>3.1.0</resource.maven.plugin.version> + <!-- DEVELOPMENT SETTINGS --> + <immutable.version>2.5.6</immutable.version> + + <!-- LOGGING SETTINGS --> + <slf4j.version>1.7.25</slf4j.version> + <logback.version>1.2.3</logback.version> + + <!--TEST SETTINGS --> + <surefire.redirectTestOutputToFile>true</surefire.redirectTestOutputToFile> + <junit.version>4.12</junit.version> + <junit.jupiter.version>5.1.0</junit.jupiter.version> + <junit.vintage.version>5.1.0</junit.vintage.version> + <junit.platform.version>1.1.0</junit.platform.version> + + <!--PLUGIN SETTINGS --> + <nexusproxy>https://nexus.onap.org</nexusproxy> + <snapshots.path>content/repositories/snapshots/</snapshots.path> + <releases.path>content/repositories/releases/</releases.path> + <site.path> + content/sites/site/org/onap/dcaegen2/collectors/datafile/${project.artifactId}/${project.version} + </site.path> + </properties> + + <pluginRepositories> + + + <pluginRepository> + <id>40_openecomp-release</id> + <name>40_openecomp-release</name> + <url>https://nexus.onap.org/content/repositories/releases/</url> + <releases> + <enabled>true</enabled> + <updatePolicy>daily</updatePolicy> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </pluginRepository> + + <!-- Black Duck plugin dependencies --> + <pluginRepository> + <id>JCenter</id> + <name>JCenter Repository</name> + <url>http://jcenter.bintray.com</url> + </pluginRepository> + <pluginRepository> + <id>Restlet</id> + <name>Restlet Repository</name> + <url>http://maven.restlet.com</url> + </pluginRepository> + </pluginRepositories> + + + <repositories> + <repository> + <id>external-repository</id> + <url>https://oss.sonatype.org/content/repositories</url> + </repository> + <repository> + <id>40_openecomp-release</id> + <name>40_openecomp-release</name> + <url>https://nexus.onap.org/content/repositories/releases/</url> + <releases> + <enabled>true</enabled> + <updatePolicy>daily</updatePolicy> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + </repositories> + + <build> + + <extensions> + <extension> + <groupId>org.apache.maven.wagon</groupId> + <artifactId>wagon-webdav-jackrabbit</artifactId> + <version>3.0.0</version> + </extension> + </extensions> + + <pluginManagement> + <plugins> + + <!-- COMPILER PLUGIN --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>${compiler.plugin.version}</version> + <configuration> + <source>${java.version}</source> + <target>${java.version}</target> + <showWarnings>true</showWarnings> + <showDeprecation>true</showDeprecation> + </configuration> + </plugin> + + <!-- MAVEN SOURCE PLUGIN --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <version>3.0.1</version> + <configuration> + <excludeResources>true</excludeResources> + </configuration> + <executions> + <execution> + <id>attach-sources</id> + <phase>verify</phase> + <goals> + <goal>jar-no-fork</goal> + </goals> + </execution> + </executions> + </plugin> + + <!-- MAVEN JAVADOC PLUGIN --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>3.0.0</version> + <configuration> + <!-- minimize console output messages --> + <quiet>true</quiet> + <verbose>false</verbose> + <useStandardDocletOptions>false</useStandardDocletOptions> + </configuration> + <executions> + <execution> + <id>aggregate</id> + <phase>site</phase> + <goals> + <goal>aggregate</goal> + </goals> + </execution> + <execution> + <id>attach-javadoc</id> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + </plugin> + + <!-- MAVEN BUNDLE PLUGIN --> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <version>3.5.0</version> + <extensions>true</extensions> + <configuration> + <instructions> + <Embed-Dependency>*;inline=false;scope=compile</Embed-Dependency> + <Embed-Transitive>true</Embed-Transitive> + <Embed-Directory>lib</Embed-Directory> + </instructions> + </configuration> + <executions> + <execution> + <id>Bundling Datafile Jar</id> + <phase>package</phase> + <goals> + <goal>bundle</goal> + </goals> + </execution> + </executions> + </plugin> + + <!-- maven-surefire-plugin which is used during the test phase of build lifecycle --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.19.1</version> + <configuration> + <argLine>-Xmx2048m -Djava.awt.headless=true -XX:+UseConcMarkSweepGC + -XX:OnOutOfMemoryError="kill -9 %p" -XX:+HeapDumpOnOutOfMemoryError + </argLine> + <redirectTestOutputToFile>${surefire.redirectTestOutputToFile} + </redirectTestOutputToFile> + <parallel>methods</parallel> + <threadCount>8</threadCount> + <forkCount>8</forkCount> + <reuseForks>true</reuseForks> + <reportFormat>xml</reportFormat> + <trimStackTrace>false</trimStackTrace> + <systemPropertyVariables> + <java.io.tmpdir>${project.build.directory}</java.io.tmpdir> + <logback.configurationFile> + ${basedir}/src/test/resources/logback-test.xml + </logback.configurationFile> + <HADOOP_HOME>${project.build.directory}</HADOOP_HOME> + </systemPropertyVariables> + <includes> + <include>**/*Test.java</include> + </includes> + <excludes> + <exclude>**/*IT.java</exclude> + </excludes> + <!-- Sets the VM argument line used when unit tests are run. --> + <argLine>${argLine}</argLine> + </configuration> + <dependencies> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-surefire-provider</artifactId> + <version>${junit.platform.version}</version> + </dependency> + </dependencies> + </plugin> + + <!-- FIND BUGS (STATIC CODE ANALYSIS) PLUGIN --> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>findbugs-maven-plugin</artifactId> + <version>${findbugs.plugin.version}</version> + <configuration> + <effort>Max</effort> + <threshold>Low</threshold> + <xmlOutput>true</xmlOutput> + <!-- BUILD FAIL ON FINDBUGS ERRORS --> + <failOnError>true</failOnError> + <excludeFilterFile>${project.basedir}/findbugs-exclude.xml</excludeFilterFile> + <outputDirectory>${project.reporting.outputDirectory}/findbugs</outputDirectory> + <findbugsXmlOutputDirectory>${project.reporting.outputDirectory}/findbugs + </findbugsXmlOutputDirectory> + </configuration> + <executions> + <execution> + <id>analyze-compile</id> + <phase>compile</phase> + <goals> + <goal>check</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>3.0.2</version> + <configuration> + <archive> + <manifest> + <addDefaultImplementationEntries>true</addDefaultImplementationEntries> + </manifest> + <manifestEntries> + <Implementation-Build-Version>${project.version}</Implementation-Build-Version> + </manifestEntries> + </archive> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-site-plugin</artifactId> + <version>3.6</version> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jxr-plugin</artifactId> + <version>2.5</version> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-project-info-reports-plugin</artifactId> + <version>2.9</version> + <configuration> + <dependencyDetailsEnabled>false</dependencyDetailsEnabled> + <dependencyLocationsEnabled>false</dependencyLocationsEnabled> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-report-plugin</artifactId> + <version>2.21.0</version> + </plugin> + + <plugin> + <groupId>com.spotify</groupId> + <artifactId>docker-maven-plugin</artifactId> + <version>${docker.maven.version}</version> + <configuration> + <skipDockerBuild>true</skipDockerBuild> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <version>${resource.maven.plugin.version}</version> + </plugin> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <configuration> + <excludes> + <exclude>**/Immutable*</exclude> + <exclude>**/GsonAdapters*</exclude> + <exclude>**/*ForUnitTest*</exclude> + </excludes> + </configuration> + <executions> + <execution> + <id>default-prepare-agent</id> + <goals> + <goal>prepare-agent</goal> + </goals> + </execution> + <execution> + <id>report</id> + <phase>prepare-package</phase> + <goals> + <goal>report</goal> + </goals> + </execution> + <execution> + <id>check</id> + <goals> + <goal>check</goal> + </goals> + <configuration> + <excludes> + <exclude>**/Immutable*</exclude> + <exclude>**/GsonAdapters*</exclude> + <exclude>**/*ForUnitTest*</exclude> + <exclude>**/AAIConsumer*</exclude> + </excludes> + <rules> + <rule> + <element>CLASS</element> + <limits> + <limit> + <value>COVEREDRATIO</value> + <!--<minimum>0.70</minimum>--> + </limit> + <limit> + <counter>BRANCH</counter> + <value>COVEREDRATIO</value> + <!--<minimum>0.70</minimum>--> + </limit> + </limits> + </rule> + </rules> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-deploy-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + </plugins> + </pluginManagement> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + </plugin> + + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + </plugin> + </plugins> + </build> + + <reporting> + <plugins> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-site-plugin</artifactId> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jxr-plugin</artifactId> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-project-info-reports-plugin</artifactId> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-report-plugin</artifactId> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>2.10.4</version> + <configuration> + <failOnError>false</failOnError> + <doclet>org.umlgraph.doclet.UmlGraphDoc</doclet> + <docletArtifact> + <groupId>org.umlgraph</groupId> + <artifactId>umlgraph</artifactId> + <version>5.6</version> + </docletArtifact> + <additionalparam>-views</additionalparam> + <useStandardDocletOptions>true</useStandardDocletOptions> + </configuration> + </plugin> + </plugins> + </reporting> + + <dependencyManagement> + <dependencies> + + <!-- DEVELOPMENT TOOLS DEPENDENCIES --> + <dependency> + <groupId>org.immutables</groupId> + <artifactId>value</artifactId> + <version>${immutable.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.immutables</groupId> + <artifactId>gson</artifactId> + <version>${immutable.version}</version> + </dependency> + <dependency> + <groupId>io.projectreactor</groupId> + <artifactId>reactor-bom</artifactId> + <version>Bismuth-RELEASE</version> + <type>pom</type> + <scope>import</scope> + </dependency> + <dependency> + <groupId>com.spotify</groupId> + <artifactId>docker-maven-plugin</artifactId> + <version>${docker.maven.version}</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <version>${resource.maven.plugin.version}</version> + </dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk15on</artifactId> + <version>1.59</version> + </dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcpkix-jdk15on</artifactId> + <version>1.59</version> + </dependency> + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-utils</artifactId> + <version>3.1.0</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.5.4</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.6</version> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-beans</artifactId> + <version>5.0.5.RELEASE</version> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + <version>5.0.5.RELEASE</version> + </dependency> + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-core</artifactId> + <version>${tomcat.version}</version> + </dependency> + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-el</artifactId> + <version>${tomcat.version}</version> + </dependency> + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-websocket</artifactId> + <version>${tomcat.version}</version> + </dependency> + + <!-- LOGGING dependencies> --> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + <version>${logback.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jul-to-slf4j</artifactId> + <version>1.7.25</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>log4j-over-slf4j</artifactId> + <version>1.7.25</version> + </dependency> + + <!-- TESTING TOOLS DEPENDENCIES --> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <version>${junit.jupiter.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <version>${junit.jupiter.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.vintage</groupId> + <artifactId>junit-vintage-engine</artifactId> + <version>${junit.vintage.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <version>5.0.4.RELEASE</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>2.16.0</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + <version>6.14.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.connectors</groupId> + <artifactId>jersey-apache-connector</artifactId> + <version>2.25.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <version>2.0.1.RELEASE</version> + <scope>test</scope> + </dependency> + + <!--REQUIRED TO GENERATE DOCUMENTATION --> + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger2</artifactId> + <version>2.8.0</version> + </dependency> + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger-ui</artifactId> + <version>2.8.0</version> + </dependency> + + <!-- ONLY REQUIRED TO RUN TESTS IN AN IDE THAT BUNDLES AN OLDER VERSION --> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-launcher</artifactId> + <version>${junit.platform.version}</version> + <scope>test</scope> + </dependency> + + </dependencies> + </dependencyManagement> + + <modules> + <module>datafile-app-server</module> + <module>datafile-aai-client</module> + <module>datafile-dmaap-client</module> + <module>datafile-commons</module> + </modules> +</project> + diff --git a/swagger.yaml b/swagger.yaml new file mode 100644 index 00000000..b0430487 --- /dev/null +++ b/swagger.yaml @@ -0,0 +1,76 @@ +--- +swagger: '2.0' +info: + description: This page lists all the rest apis for Datafile app server. + version: '1.0' + title: Datafile app server +host: localhost:8100 +basePath: "/" +tags: +- name: heartbeat-controller + description: Check liveness of Datafile service +- name: schedule-controller + description: Schedule Controller +paths: + "/heartbeat": + get: + tags: + - heartbeat-controller + summary: Returns liveness of Datafile service + operationId: heartbeatUsingGET + produces: + - "*/*" + responses: + '200': + description: Datafile sevice is living + schema: + "$ref": "#/definitions/Mono«ResponseEntity«string»»" + '401': + description: You are not authorized to view the resource + '403': + description: Accessing the resource you were trying to reach is forbidden + '404': + description: The resource you were trying to reach is not found + "/start": + get: + tags: + - schedule-controller + summary: Start scheduling worker request + operationId: startTasksUsingGET + produces: + - "*/*" + responses: + '200': + description: OK + schema: + "$ref": "#/definitions/Mono«ResponseEntity«string»»" + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found + "/stopDatafile": + get: + tags: + - schedule-controller + summary: Stop scheduling worker request + operationId: stopTaskUsingGET + produces: + - "*/*" + responses: + '200': + description: OK + schema: + "$ref": "#/definitions/Mono«ResponseEntity«string»»" + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: Not Found +definitions: + Mono«ResponseEntity«string»»: + type: object + title: Mono«ResponseEntity«string»» + diff --git a/version.properties b/version.properties new file mode 100644 index 00000000..2ddebb39 --- /dev/null +++ b/version.properties @@ -0,0 +1,6 @@ +major=1 +minor=0 +patch=0 +base_version=${major}.${minor}.${patch} +release_version=${base_version} +snapshot_version=${base_version}-SNAPSHOT |