diff options
author | Patrick Brady <patrick.brady@att.com> | 2019-10-10 15:34:00 -0700 |
---|---|---|
committer | Takamune Cho <takamune.cho@att.com> | 2019-11-08 16:38:47 +0000 |
commit | 6a6d3afd489ea3b8945f1cdd8a8a74afdcc5221a (patch) | |
tree | 1b9b67b9683145d693d831eea7128d36738aa9a4 | |
parent | 7b04a1754482ba02a49d4d6376dc45e4cd6551f4 (diff) |
Dmaap micro service jar
Creating a service running in a standalone jar to handle
the publishing and recieving of dmaap messages for appc.
Dmaap adapter and event listener code is copeid from the
main appc project. It will be moved in a later commit.
Change-Id: I3fa7b5dc60345f0f38f763a243150b8472f985ac
Signed-off-by: Patrick Brady <patrick.brady@att.com>
Issue-ID: APPC-1744
124 files changed, 11629 insertions, 0 deletions
@@ -648,6 +648,7 @@ limitations under the License. <module>appc-metric</module> <module>appc-dg</module> <module>appc-dg-util</module> + <module>services</module> </modules> </profile> </profiles> diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/.gitignore b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/.gitignore new file mode 100644 index 000000000..eacf31a67 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/.gitignore @@ -0,0 +1 @@ +/target-ide/ diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/pom.xml b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/pom.xml new file mode 100644 index 000000000..76401f916 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/pom.xml @@ -0,0 +1,180 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + ONAP : APPC + ================================================================================ + Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + Copyright (C) 2017 Amdocs + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR 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.appc.parent</groupId> + <artifactId>binding-parent</artifactId> + <version>2.6.2</version> + <relativePath /> + </parent> + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>appc-dmaap-adapter-bundle</artifactId> + <packaging>jar</packaging> + <name>DMaaP Adapter - bundle</name> + + <dependencies> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + </dependency> + <dependency> + <groupId>org.onap.appc</groupId> + <artifactId>appc-common-bundle</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>appc-message-adapter-api</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + <version>${logback.version}</version> + </dependency> + <dependency> + <groupId>com.att.eelf</groupId> + <artifactId>eelf-core</artifactId> + <exclusions> + <exclusion> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + </dependency> + + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + </dependency> + + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-core</artifactId> + </dependency> + <dependency> + <groupId>org.objenesis</groupId> + <artifactId>objenesis</artifactId> + <version>2.2</version> + </dependency> + + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-module-junit4</artifactId> + <scope>test</scope> + </dependency> + <!-- <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + </dependency>--> + <dependency> + <groupId>org.onap.ccsdk.sli.core</groupId> + <artifactId>sli-common</artifactId> + <scope>compile</scope> + <!-- Added exclusion to prevent missing dependency issue on dblib --> + <exclusions> + <exclusion> + <groupId>org.onap.ccsdk.sli.core</groupId> + <artifactId>dblib-provider</artifactId> + </exclusion> + <exclusion> + <artifactId>slf4j-simple</artifactId> + <groupId>org.slf4j</groupId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.onap.ccsdk.sli.core</groupId> + <artifactId>sli-provider</artifactId> + <scope>compile</scope> + <!-- Added exclusion to prevent missing dependency issue on dblib --> + <exclusions> + <exclusion> + <groupId>org.onap.ccsdk.sli.core</groupId> + <artifactId>dblib-provider</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> + + <dependency> + <groupId>javax.ws.rs</groupId> + <artifactId>javax.ws.rs-api</artifactId> + </dependency> + </dependencies> + + <version>1.7.0-SNAPSHOT</version> +</project> diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/AppcDmaapAdapterActivator.java b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/AppcDmaapAdapterActivator.java new file mode 100644 index 000000000..828cdb773 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/AppcDmaapAdapterActivator.java @@ -0,0 +1,104 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.messaging.dmaap; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + + + +/** + * This activator is used to initialize and terminate the connection pool to one or more providers. + * <p> + * The CDP abstraction layer supports multiple types of providers, with each provider supporting multiple tenants. The + * "connection" to a specific tenant on a specific provider is represented by a "context" object. These context objects + * are authenticated to a specific tenant on the provider, but can be reused from one request to another. Contexts are + * slow to set up and are resource intensive, so they are cached. However, the contexts for a specific tenant on a + * specific provider must be cached separately. + * </p> + * <p> + * Activation of the bundle creates an empty cache which is organized first by provider type, then by tenant name, with + * the contents being an empty pool of contexts for that provider/tenant combination. The pool is created on first use, + * and retained for as long as the bundle is active. + * </p> + * <p> + * When the bundle is deactivated, the cache is torn down with all contexts being closed. + * </p> + */ +public class AppcDmaapAdapterActivator implements BundleActivator { + + /** + * The logger to be used + */ + private static final EELFLogger LOG = EELFManager.getInstance().getLogger(AppcDmaapAdapterActivator.class); + + /** + * Called when this bundle is started so the Framework can perform the bundle-specific activities necessary to start + * this bundle. This method can be used to register services or to allocate any resources that this bundle needs. + * <p> + * This method must complete and return to its caller in a timely manner. + * </p> + * + * @param bundleContext + * The execution context of the bundle being started. + * @throws java.lang.Exception + * If this method throws an exception, this bundle is marked as stopped and the Framework will remove + * this bundle's listeners, unregister all services registered by this bundle, and release all services + * used by this bundle. + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(final BundleContext bundleContext) throws Exception { + LOG.info("Starting Bundle " + getName()); + } + + /** + * Called when this bundle is stopped so the Framework can perform the bundle-specific activities necessary to stop + * the bundle. In general, this method should undo the work that the BundleActivator.start method started. There + * should be no active threads that were started by this bundle when this bundle returns. A stopped bundle must not + * call any Framework objects. + * <p> + * This method must complete and return to its caller in a timely manner. + * </p> + * + * @param ctx + * The execution context of the bundle being stopped. + * @throws java.lang.Exception + * If this method throws an exception, the bundle is still marked as stopped, and the Framework will + * remove the bundle's listeners, unregister all services registered by the bundle, and release all + * services used by the bundle. * + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext ctx) throws Exception { + LOG.info("Stopped Bundle " + getName()); + } + + public String getName() { + return "DMaaP Adapter"; + } + +} diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/http/AuthenticationException.java b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/http/AuthenticationException.java new file mode 100644 index 000000000..f670d6cdd --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/http/AuthenticationException.java @@ -0,0 +1,28 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.messaging.dmaap.http; + +class AuthenticationException extends Exception { + + public AuthenticationException(String message) { + super(message); + } +} diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/http/CommonHttpClient.java b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/http/CommonHttpClient.java new file mode 100644 index 000000000..7c243d08e --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/http/CommonHttpClient.java @@ -0,0 +1,105 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.messaging.dmaap.http; + +import java.net.URI; + +import org.apache.commons.codec.binary.Base64; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.config.RequestConfig.Builder; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; + +abstract class CommonHttpClient { + + private static final int HTTP_PORT = 3904; + private static final int HTTPS_PORT = 3905; + private static final int TIMEOUT_OFFSET = 5000; + + private String authStr; + + protected void setBasicAuth(String username, String password) { + if (username != null && password != null) { + String plain = String.format("%s:%s", username, password); + authStr = Base64.encodeBase64String(plain.getBytes()); + } else { + authStr = null; + } + } + + protected HttpGet getReq(URI uri, int timeoutMs) throws AuthenticationException { + + HttpGet out = (uri == null) ? new HttpGet() : new HttpGet(uri); + if (authStr != null) { + out.setHeader("Authorization", String.format("Basic %s", authStr)); + } + + out.setConfig(getConfig(timeoutMs)); + return out; + } + + protected HttpPost postReq(String url) throws AuthenticationException { + + HttpPost out = (url == null) ? new HttpPost() : new HttpPost(url); + if (authStr != null) { + out.setHeader("Authorization", String.format("Basic %s", authStr)); + } + out.setConfig(getConfig(0)); + return out; + } + + private RequestConfig getConfig(int timeoutMs) { + Builder builder = RequestConfig.custom(); + builder.setSocketTimeout(timeoutMs + TIMEOUT_OFFSET); + return builder.build(); + } + + protected CloseableHttpClient getClient() { + return HttpClientBuilder.create().build(); + } + + protected String formatHostString(String host) { + return formatHostString(host, host.contains(String.valueOf(HTTPS_PORT))); + } + + private String formatHostString(String host, boolean useHttps) { + // Trim trailing slash + String out = host.endsWith("/") ? host.substring(0, host.length() - 1) : host; + + boolean hasProtocol = out.startsWith("http"); + boolean hasPort = out.contains(":"); + + // Add protocol + if (!hasProtocol) { + out = String.format("%s%s", (useHttps) ? "https://" : "http://", out); + } + // Add port + if (!hasPort) { + out = String.format("%s:%d", out, (useHttps) ? HTTPS_PORT : HTTP_PORT); + } + return out; + } +} diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/http/HttpDmaapConsumerImpl.java b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/http/HttpDmaapConsumerImpl.java new file mode 100644 index 000000000..e2a20ee45 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/http/HttpDmaapConsumerImpl.java @@ -0,0 +1,154 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.messaging.dmaap.http; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.json.JSONArray; +import org.onap.appc.adapter.message.Consumer; + +public class HttpDmaapConsumerImpl extends CommonHttpClient implements Consumer { + + private static final EELFLogger LOG = EELFManager.getInstance().getLogger(HttpDmaapConsumerImpl.class); + + // Default values + private static final int DEFAULT_TIMEOUT_MS = 15000; + private static final int DEFAULT_LIMIT = 1000; + private static final String URL_TEMPLATE = "%s/events/%s/%s/%s"; + + private List<String> urls; + private String filter; + + public HttpDmaapConsumerImpl(Collection<String> hosts, String topicName, String consumerName, String consumerId, + String filter) { + + this(hosts, topicName, consumerName, consumerId, filter, null, null); + } + + public HttpDmaapConsumerImpl(Collection<String> hosts, String topicName, String consumerName, String consumerId, + String filter, String user, String password) { + + urls = new ArrayList<>(); + for (String host : hosts) { + urls.add(String.format(URL_TEMPLATE, formatHostString(host), topicName, consumerName, consumerId)); + } + this.filter = filter; + updateCredentials(user, password); + } + + @Override + public void updateCredentials(String user, String pass) { + LOG.debug(String.format("Setting auth to %s for %s", user, this.toString())); + this.setBasicAuth(user, pass); + } + + @Override + public List<String> fetch(int waitMs, int limit) { + LOG.debug(String.format("Fetching up to %d records with %dms wait on %s", limit, waitMs, this.toString())); + List<String> out = new ArrayList<>(); + try { + List<NameValuePair> urlParams = new ArrayList<>(); + urlParams.add(new BasicNameValuePair("timeout", String.valueOf(waitMs))); + urlParams.add(new BasicNameValuePair("limit", String.valueOf(limit))); + if (filter != null) { + urlParams.add(new BasicNameValuePair("filter", filter)); + } + + URIBuilder builder = new URIBuilder(urls.get(0)); + builder.setParameters(urlParams); + + URI uri = builder.build(); + LOG.info(String.format("GET %s", uri)); + HttpGet request = getReq(uri, waitMs); + CloseableHttpResponse response = getClient().execute(request); + + int httpStatus = response.getStatusLine().getStatusCode(); + HttpEntity entity = response.getEntity(); + String body = (entity != null) ? entityToString(entity) : null; + + LOG.debug(String.format("Request to %s completed with status %d and a body size of %s", uri, httpStatus, + body != null ? body.length() : "null")); + + response.close(); + if (httpStatus == 200 && body != null) { + JSONArray json = new JSONArray(body); + LOG.info(String.format("Got %d messages from DMaaP", json.length())); + for (int i = 0; i < json.length(); i++) { + out.add(json.getString(i)); + } + } else { + LOG.error(String.format("Did not get 200 from DMaaP. Got %d - %s", httpStatus, body)); + sleep(waitMs); + } + } catch (Exception e) { + if (urls.size() > 1) { + String failedUrl = urls.remove(0); + urls.add(failedUrl); + LOG.debug(String.format("Moving host %s to the end of the pool. New primary host is %s", failedUrl, + urls.get(0))); + } + LOG.error(String.format("Got exception while querying DMaaP. Message: %s", e.getMessage()), e); + sleep(waitMs); + } + return out; + } + + @Override + public List<String> fetch() { + return fetch(DEFAULT_TIMEOUT_MS, DEFAULT_LIMIT); + } + + @Override + public String toString() { + String hostStr = (urls == null || urls.isEmpty()) ? "N/A" : urls.get(0); + return String.format("Consumer listening to [%s]", hostStr); + } + + String entityToString(HttpEntity entity) throws IOException { + return EntityUtils.toString(entity); + } + + private void sleep(int ms) { + LOG.info(String.format("Sleeping for %ds after failed request", ms / 1000)); + try { + Thread.sleep(ms); + } catch (InterruptedException e1) { + LOG.error("Interrupted while sleeping", e1); + Thread.currentThread().interrupt(); + } + } + +} diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/http/HttpDmaapProducerImpl.java b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/http/HttpDmaapProducerImpl.java new file mode 100644 index 000000000..84b5a5ff6 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/http/HttpDmaapProducerImpl.java @@ -0,0 +1,140 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.messaging.dmaap.http; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.onap.appc.adapter.message.Producer; + +public class HttpDmaapProducerImpl extends CommonHttpClient implements Producer { + + private static final EELFLogger LOG = EELFManager.getInstance().getLogger(HttpDmaapProducerImpl.class); + + private static final String CONTENT_TYPE = "application/cambria"; + private static final String URL_TEMPLATE = "%s/events/%s"; + + private List<String> hosts; + private Set<String> topics; + + public HttpDmaapProducerImpl() { + //for test purposes + } + + public HttpDmaapProducerImpl(Collection<String> urls, String topicName, String username, String password) { + this(urls, topicName); + updateCredentials(username, password); + } + + public HttpDmaapProducerImpl(Collection<String> urls, String topicName) { + topics = new HashSet<>(); + topics.add(topicName); + + hosts = new ArrayList<>(); + for (String host : urls) { + hosts.add(formatHostString(host)); + } + } + + @Override + public void updateCredentials(String user, String pass) { + LOG.debug(String.format("Setting auth to %s for %s", user, this.toString())); + this.setBasicAuth(user, pass); + } + + @Override + public boolean post(String partition, String data) { + LOG.debug("Entering HttpDmaapProducerImpl::: post "); + long sent = 0; + try { + HttpPost request = postReq(null); + request.setHeader("Content-Type", CONTENT_TYPE); + request.setEntity(new StringEntity(bodyLine(partition, data))); + + LOG.debug("Before sendRequest HttpDmaapProducerImpl::: post "); + sent = topics.stream() + .filter(topic -> sendRequest(request, topic)) + .count(); + + } catch (Exception buildEx) { + LOG.error( + String.format("Failed to build request with string [%s]. Message not sent to any topic. Reason: %s", + data, buildEx.getMessage()), + buildEx); + } + LOG.debug("Exiting HttpDmaapProducerImpl::: post "); + return sent == topics.size(); + } + + private boolean sendRequest(HttpPost request, String topic) { + boolean successful = false; + String uriStr = String.format(URL_TEMPLATE, hosts.get(0), topic); + try { + request.setURI(new URI(uriStr)); + LOG.debug("HttpDmaapProducerImpl::: before sendRequest()"); + CloseableHttpResponse response = getClient().execute(request); + LOG.debug("HttpDmaapProducerImpl::: after sendRequest()"); + if (response.getStatusLine().getStatusCode() == 200) { + successful = true; + } + else { + LOG.debug("HttpDmaapProducerImpl::: did not receive 200 for sendRequest"); + } + response.close(); + } catch (Exception sendEx) { + LOG.error(String.format("Failed to send message to %s. Reason: %s", uriStr, sendEx.getMessage()), + sendEx); + if (hosts.size() > 1) { + String failedUrl = hosts.remove(0); + hosts.add(failedUrl); + LOG.debug(String.format("Moving host %s to the end of the pool. New primary host is %s", + failedUrl, hosts.get(0))); + } + } + return successful; + } + + /** + * Format the body for the application/cambria content type with no partitioning. See + * + * @param message + * The message body to format + * @return A string in the application/cambria content type + */ + private String bodyLine(String partition, String message) { + String prt = (partition == null) ? "" : partition; + String msg = (message == null) ? "" : message; + return String.format("%d.%d.%s%s", prt.length(), msg.length(), prt, msg); + } + + +} diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/utils/DmaapUtil.java b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/utils/DmaapUtil.java new file mode 100644 index 000000000..af20ac7c6 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/java/org/onap/appc/adapter/messaging/dmaap/utils/DmaapUtil.java @@ -0,0 +1,155 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.messaging.dmaap.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.onap.appc.configuration.Configuration; +import org.onap.appc.configuration.ConfigurationFactory; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +public class DmaapUtil { + + private static final char DELIMITER = '_'; + + static final String DMAAP_PROPERTIES_PATH = "org.onap.appc.dmaap.profile.path"; + + private static final EELFLogger log = EELFManager.getInstance().getLogger(DmaapUtil.class); + + private DmaapUtil() { + } + + private static String createPreferredRouteFileIfNotExist(String topic) throws IOException { + String topicPreferredRouteFileName; + topicPreferredRouteFileName = topic + "preferredRoute.properties"; + File fo = new File(topicPreferredRouteFileName); + if (!fo.exists()) { + ClassLoader classLoader = DmaapUtil.class.getClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream("preferredRoute.txt"); + Properties props = new Properties(); + props.load(inputStream); + String fileName = topic != null ? topic + DELIMITER + "MR1" : DELIMITER + "MR1"; + props.setProperty("preferredRouteKey", fileName); + topicPreferredRouteFileName = topic + "preferredRoute.properties"; + props.store(new FileOutputStream(topicPreferredRouteFileName), + "preferredRoute.properties -This file is generated automatically for topic:" + topic + " on:" + + System.currentTimeMillis()); + } + return topicPreferredRouteFileName; + } + + public static String createConsumerPropFile(String topic, Properties props) throws IOException { + String defaultProfFileName = "consumer.properties"; + + log.debug("Creating DMaaP Consumer Property File for topic " + topic); + return createConsumerProducerPropFile(topic, defaultProfFileName, props); + } + + public static String createProducerPropFile(String topic, Properties props) throws IOException { + String defaultProfFileName = "producer.properties"; + + log.debug("Creating DMaaP Producer Property File for topic " + topic); + return createConsumerProducerPropFile(topic, defaultProfFileName, props); + } + + private static String createConsumerProducerPropFile(String topic, String defaultProfFileName, Properties props) + throws IOException { + Properties defaultProps = getDefaultProperties(defaultProfFileName); + + defaultProps.setProperty("topic", topic); + + String preferredRouteFileName = DmaapUtil.createPreferredRouteFileIfNotExist(topic); + if (props != null && !props.isEmpty()) { + defaultProps.putAll(props); + } + defaultProps.setProperty("topic", topic); + defaultProps.setProperty("DME2preferredRouterFilePath", preferredRouteFileName); + String id = defaultProps.getProperty("id"); + String topicConsumerPropFileName = defaultProfFileName; + topicConsumerPropFileName = id != null ? id + DELIMITER + topicConsumerPropFileName + : DELIMITER + topicConsumerPropFileName; + topicConsumerPropFileName = topic != null ? topic + DELIMITER + topicConsumerPropFileName + : DELIMITER + topicConsumerPropFileName; + + defaultProps.store(new FileOutputStream(topicConsumerPropFileName), defaultProfFileName + + " - This file is generated automatically for topic:" + topic + " on:" + System.currentTimeMillis()); + return topicConsumerPropFileName; + } + + private static Properties getDefaultProperties(String profileName) { + Properties props = new Properties(); + + // use appc configuration to get all properties which includes + // appc.properties and system properties + // allowing variable to be set in any location + Configuration config = ConfigurationFactory.getConfiguration(); + String dmaapPropPath = config.getProperty(DMAAP_PROPERTIES_PATH); + + if (dmaapPropPath != null) { + // load from file system + + File profileFile = new File(dmaapPropPath, profileName); + FileInputStream inputStream = null; + + log.info("Loading DMaaP Profile from " + profileFile.getAbsolutePath()); + + if (profileFile.exists()) { + try { + inputStream = new FileInputStream(profileFile); + props.load(inputStream); + } catch (IOException e) { + log.error("Exception loading DMaaP Profile from " + profileFile.getAbsolutePath(), e); + } finally { + try { + if (inputStream != null) { + inputStream.close(); + } + } catch (IOException ex) { + log.warn("Exception closing DMaaP Profile file " + profileFile.getAbsolutePath(), ex); + } + } + } + } + if (props.isEmpty()) { + // load default Profile from class + log.info("Loading Default DMaaP Profile"); + + ClassLoader classLoader = DmaapUtil.class.getClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream(profileName); + try { + props.load(inputStream); + } catch (IOException e) { + log.error("Exception loading Default DMaaP Profile", e); + } + } + + return props; + } +} diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/resources/consumer.properties b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/resources/consumer.properties new file mode 100644 index 000000000..b19a33505 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/resources/consumer.properties @@ -0,0 +1,56 @@ +### +# ============LICENSE_START======================================================= +# ONAP : APPC +# ================================================================================ +# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Copyright (C) 2017 Amdocs +# ============================================================================= +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END========================================================= +### + +#TransportType-Specify which way user want to use. I.e. <HTTPAAF,DME2,HTTPAUTH > +TransportType=HTTPNOAUTH +Latitude =50.000000 +Longitude =-100.000000 +Version =1.0 +ServiceName =dmaap-v1.dev.dmaap.dt.saat.acsi.openecomp.org/events +Environment =TEST +Partner=BOT_R +routeOffer=MR1 +SubContextPath =/ +Protocol =http +MethodType =GET +username =admin +password =admin +contenttype =application/json +authKey=01234567890abcde:01234567890abcdefghijklmn +authDate=2016-02-18T13:57:37-0800 +host=127.0.0.1 +topic=org.onap.appc.UNIT-TEST +group=jmsgrp +id=2 +timeout=15000 +limit=1000 +filter= +AFT_DME2_EXCHANGE_REQUEST_HANDLERS=com.att.nsa.test.PreferredRouteRequestHandler +AFT_DME2_EXCHANGE_REPLY_HANDLERS=com.att.nsa.test.PreferredRouteReplyHandler +AFT_DME2_REQ_TRACE_ON=true +AFT_ENVIRONMENT=AFTUAT +AFT_DME2_EP_CONN_TIMEOUT=15000 +AFT_DME2_ROUNDTRIP_TIMEOUT_MS=240000 +AFT_DME2_EP_READ_TIMEOUT_MS=50000 +sessionstickinessrequired=NO +DME2preferredRouterFilePath=preferredRoute.txt diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/resources/org/onap/appc/default.properties b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/resources/org/onap/appc/default.properties new file mode 100644 index 000000000..218cafe6e --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/resources/org/onap/appc/default.properties @@ -0,0 +1,27 @@ +### +# ============LICENSE_START======================================================= +# ONAP : APPC +# ================================================================================ +# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Copyright (C) 2017 Amdocs +# ============================================================================= +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END========================================================= +### + +# ${user.home} usually goes to /root if instantiation uses the appc-docker approach + +org.onap.appc.bootstrap.file=appc.properties +org.onap.appc.bootstrap.path=/opt/onap/appc/data/properties,${user.home},. diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/resources/preferredRoute.txt b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/resources/preferredRoute.txt new file mode 100644 index 000000000..7e6ed8bdf --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/resources/preferredRoute.txt @@ -0,0 +1,22 @@ +# ============LICENSE_START========================================== +# ONAP : APPC +# =================================================================== +# Copyright (C) 2017-2018 AT&T 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. +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# ============LICENSE_END============================================ +preferredRouteKey=MR1 diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/resources/producer.properties b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/resources/producer.properties new file mode 100644 index 000000000..129ec9c6b --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/main/resources/producer.properties @@ -0,0 +1,54 @@ +### +# ============LICENSE_START======================================================= +# ONAP : APPC +# ================================================================================ +# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Copyright (C) 2017 Amdocs +# ============================================================================= +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END========================================================= +### + +#TransportType-Specify which way user want to use. I.e. <HTTPAAF,DME2,HTTPAUTH > +TransportType=HTTPNOAUTH +Latitude =50.000000 +Longitude =-100.000000 +Version =1.0 +ServiceName =dmaap-v1.dev.dmaap.dt.saat.acsi.openecomp.org/events +Environment =TEST +Partner=BOT_R +SubContextPath =/ +Protocol =http +MethodType =POST +username =admin +password =admin +contenttype = application/json +authKey=01234567890abcde:01234567890abcdefghijklmn +authDate=2016-07-20T11:30:56-0700 +host=127.0.0.1 +topic=org.onap.appc.UNIT-TEST +partition=2 +maxBatchSize=100 +maxAgeMs=250 +AFT_DME2_EXCHANGE_REQUEST_HANDLERS=com.att.nsa.test.PreferredRouteRequestHandler +AFT_DME2_EXCHANGE_REPLY_HANDLERS=com.att.nsa.test.PreferredRouteReplyHandler +AFT_DME2_REQ_TRACE_ON=true +AFT_ENVIRONMENT=AFTUAT +AFT_DME2_EP_CONN_TIMEOUT=15000 +AFT_DME2_ROUNDTRIP_TIMEOUT_MS=240000 +AFT_DME2_EP_READ_TIMEOUT_MS=50000 +sessionstickinessrequired=NO +DME2preferredRouterFilePath=preferredRoute.txt +MessageSentThreadOccurance=50 diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/TestAppcDmaapAdapterActivator.java b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/TestAppcDmaapAdapterActivator.java new file mode 100644 index 000000000..e5ee0680c --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/TestAppcDmaapAdapterActivator.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.messaging.dmaap; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import org.junit.Test; +import org.onap.appc.adapter.messaging.dmaap.AppcDmaapAdapterActivator; + +public class TestAppcDmaapAdapterActivator { + + @Test + public void test_dmaap_activator() { + // This does nothing since the activator does nothing + AppcDmaapAdapterActivator appc = new AppcDmaapAdapterActivator(); + try { + appc.start(null); + appc.stop(null); + } catch (Exception e) { + fail("Got exception when starting stopping. " + e.getMessage()); + } + assertNotNull(appc.getName()); + } +} diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/TestDmaapConsuming.java b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/TestDmaapConsuming.java new file mode 100644 index 000000000..ec9740053 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/TestDmaapConsuming.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.messaging.dmaap; + + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.appc.adapter.message.Consumer; +import org.onap.appc.adapter.messaging.dmaap.http.HttpDmaapConsumerImpl; +import org.onap.appc.configuration.Configuration; +import org.onap.appc.configuration.ConfigurationFactory; +import org.junit.Ignore; + +import java.util.Arrays; +import java.util.List; + +/** + * Must have a DMaaP cluster or simulator up and running + * Update the hostname, topic, client properties in + * resources/org/onap/appc/default.properties + * + */ +public class TestDmaapConsuming { + + private static Consumer httpConsumer; + + @BeforeClass + public static void setUp() { + + Configuration configuration = ConfigurationFactory.getConfiguration(); + + List<String> hosts = Arrays.asList(configuration.getProperty("poolMembers").split(",")); + String topic = configuration.getProperty("topic.read"); + String consumerName = configuration.getProperty("client.name"); + String consumerId = configuration.getProperty("client.name.id"); + String msgFilter = configuration.getProperty("message.filter"); + String user = configuration.getProperty("dmaap.appc.username"); + String password = configuration.getProperty("dmaap.appc.password"); + + httpConsumer = new HttpDmaapConsumerImpl(hosts, topic, consumerName, consumerId, msgFilter); + } + + @Test + @Ignore + public void testHttpFetchMessages() { + testFetchMessages(httpConsumer); + } + + @Test + @Ignore + public void testFetchMessages() { + testFetchMessages(httpConsumer); + } + + private void testFetchMessages(Consumer consumer) { + List<String> messages = consumer.fetch(1000, 100); + Assert.assertNotNull(messages); + Assert.assertFalse(messages.isEmpty()); + } + +} diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/TestDmaapProducing.java b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/TestDmaapProducing.java new file mode 100644 index 000000000..5b2183e37 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/TestDmaapProducing.java @@ -0,0 +1,79 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.messaging.dmaap; + + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.onap.appc.adapter.message.Producer; +import org.onap.appc.adapter.messaging.dmaap.http.HttpDmaapProducerImpl; +import org.onap.appc.configuration.Configuration; +import org.onap.appc.configuration.ConfigurationFactory; + +import java.util.Arrays; +import java.util.List; + +/** + * Must have a DMaaP cluster or simulator up and running + * Update the hostname, topic, client properties in + * resources/org/onap/appc/default.properties + * + */ +public class TestDmaapProducing { + + private static Producer httpProducer; + + @BeforeClass + public static void setUp() { + + Configuration configuration = ConfigurationFactory.getConfiguration(); + + List<String> hosts = Arrays.asList(configuration.getProperty("poolMembers").split(",")); + String topic = configuration.getProperty("topic.write"); + String user = configuration.getProperty("dmaap.appc.username"); + String password = configuration.getProperty("dmaap.appc.password"); + + httpProducer = new HttpDmaapProducerImpl(hosts, topic); + httpProducer.updateCredentials(user,password); + } + + @Test + @Ignore + public void testHttpPostMessage() { + testPostMessage(httpProducer); + } + + @Test + @Ignore + public void testPostMessages() { + testPostMessage(httpProducer); + } + + private void testPostMessage(Producer producer) { + Assert.assertTrue(producer.post("partition", "{\"message\": \"Hello, world!\"}")); + } + +} diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/http/TestAuthenticationException.java b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/http/TestAuthenticationException.java new file mode 100644 index 000000000..448af3022 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/http/TestAuthenticationException.java @@ -0,0 +1,35 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 IBM. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.appc.adapter.messaging.dmaap.http; + +import org.junit.Assert; +import org.junit.Test; + +public class TestAuthenticationException { + + @Test + public void testAuthException() { + AuthenticationException authException = new AuthenticationException("AuthenticationException"); + Assert.assertEquals("AuthenticationException", authException.getMessage()); + } + +} diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/http/TestCommonHttpClient.java b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/http/TestCommonHttpClient.java new file mode 100644 index 000000000..660a6e4bc --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/http/TestCommonHttpClient.java @@ -0,0 +1,118 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.messaging.dmaap.http; + +import static org.junit.Assert.*; + +import java.net.URI; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.junit.Before; +import org.junit.Test; + +public class TestCommonHttpClient { + + private static final String HTTP = "http://"; + private static final String HTTPS = "https://"; + private static final String URL = "example.org/location"; + private static final URI URI = java.net.URI.create(HTTP + URL); + private static final String USERNAME = "username"; + private static final String PASSWORD = "password"; + private static final int TIMEOUT = 15000; + private static final int TIMEOUT_OFFSET = 5000; + private static final int HTTP_PORT = 3904; + private static final int HTTPS_PORT = 3905; + + private CommonHttpClient commonHttpClient; + + @Before + public void setUp() { + commonHttpClient = new CommonHttpClient() {}; + } + + private void setBasicAuth() { + commonHttpClient.setBasicAuth(USERNAME, PASSWORD); + } + + private void noBasicAuth() { + commonHttpClient.setBasicAuth(null, null); + } + + @Test + public void shouldGetHttpRequest_whenSetBasicAuth() throws AuthenticationException { + + setBasicAuth(); + + HttpGet httpGet = commonHttpClient.getReq(URI, TIMEOUT); + + assertNotNull(httpGet); + assertNotNull(httpGet.getFirstHeader("Authorization")); + assertNotNull(httpGet.getConfig()); + assertEquals(httpGet.getConfig().getSocketTimeout(), TIMEOUT + TIMEOUT_OFFSET); + } + + @Test + public void shouldPostHttpRequest_whenSetBasicAuth() throws AuthenticationException { + + setBasicAuth(); + + HttpPost httpPost = commonHttpClient.postReq(URL); + + assertNotNull(httpPost); + assertNotNull(httpPost.getFirstHeader("Authorization")); + assertNotNull(httpPost.getConfig()); + assertEquals(httpPost.getConfig().getSocketTimeout(), TIMEOUT_OFFSET); + } + + @Test + public void shouldGetClient() { + assertNotNull(commonHttpClient.getClient()); + } + + @Test + public void shouldFormatHostString() { + String httpUrl = HTTP + URL + ":" + HTTP_PORT; + String httpsUrl = HTTPS + URL + ":" + HTTPS_PORT; + String outputUrl; + + outputUrl = commonHttpClient.formatHostString(httpUrl); + assertTrue(assertMessage(httpUrl, outputUrl), httpUrl.equals(outputUrl)); + + outputUrl = commonHttpClient.formatHostString(httpsUrl); + assertTrue(assertMessage(httpsUrl, outputUrl), httpsUrl.equals(outputUrl)); + + outputUrl = commonHttpClient.formatHostString(httpsUrl + "/"); + assertTrue(assertMessage(httpsUrl, outputUrl), httpsUrl.equals(outputUrl)); + + outputUrl = commonHttpClient.formatHostString(URL + ":" + HTTP_PORT); + assertTrue(assertMessage(httpUrl, outputUrl), httpUrl.equals(outputUrl)); + + outputUrl = commonHttpClient.formatHostString(URL + ":" + HTTPS_PORT); + assertTrue(assertMessage(httpsUrl, outputUrl), httpsUrl.equals(outputUrl)); + + outputUrl = commonHttpClient.formatHostString(URL); + assertTrue(assertMessage(httpUrl, outputUrl), httpUrl.equals(outputUrl)); + } + + private String assertMessage(String expected, String actual) { + return "Expected: " + expected + " Actual: " + actual; + } +}
\ No newline at end of file diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/http/TestHttpDmaapConsumerImpl.java b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/http/TestHttpDmaapConsumerImpl.java new file mode 100644 index 000000000..ea9a5e921 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/http/TestHttpDmaapConsumerImpl.java @@ -0,0 +1,153 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.messaging.dmaap.http; + +import static javax.ws.rs.core.Response.Status.FORBIDDEN; +import static javax.ws.rs.core.Response.Status.OK; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import org.apache.http.HttpEntity; +import org.apache.http.StatusLine; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; + +public class TestHttpDmaapConsumerImpl { + + private static final Collection<String> URLS = Arrays.asList("test.com", "test.org"); + private static final Collection<String> OUTPUT_MSG = Arrays.asList("FirstMessage", "SecondMessage"); + private static final String TOPIC_NAME = "Topic"; + private static final String CONSUMER_NAME = "Consumer"; + private static final String CONSUMER_ID = "Id"; + private static final String FILTER = "filter"; + private static final String USERNAME = "username"; + private static final String PASSWORD = "password"; + private static final String MESSAGE_BODY = "[FirstMessage, SecondMessage]"; + private static final int TIMEOUT_MS = 1000; + private static final int LIMIT = 1000; + + @Spy + private HttpDmaapConsumerImpl httpDmaapConsumer; + + @Mock + private CloseableHttpClient httpClient; + + @Mock + private CloseableHttpResponse httpResponse; + + @Mock + private StatusLine statusLine; + + @Mock + private HttpEntity entity; + + @Before + public void setUp() throws Exception { + httpDmaapConsumer = new HttpDmaapConsumerImpl(URLS, TOPIC_NAME, CONSUMER_NAME, CONSUMER_ID, FILTER); + httpDmaapConsumer.updateCredentials(USERNAME, PASSWORD); + + MockitoAnnotations.initMocks(this); + doReturn(httpClient).when(httpDmaapConsumer).getClient(); + when(httpClient.execute(any(HttpGet.class))).thenReturn(httpResponse); + when(httpResponse.getStatusLine()).thenReturn(statusLine); + when(httpResponse.getEntity()).thenReturn(entity); + doReturn(MESSAGE_BODY).when(httpDmaapConsumer).entityToString(same(entity)); + } + + @Test + public void shouldGetHttpRequest() throws Exception { + + when(statusLine.getStatusCode()).thenReturn(OK.getStatusCode()); + + List<String> output = httpDmaapConsumer.fetch(); + + assertFalse(output.isEmpty()); + assertTrue(output.containsAll(OUTPUT_MSG)); + verify(httpClient).execute(any(HttpGet.class)); + verify(httpResponse).getStatusLine(); + verify(httpResponse).getEntity(); + verify(httpResponse).close(); + verify(statusLine).getStatusCode(); + verifyNoMoreInteractions(httpClient, httpResponse, statusLine, entity); + } + + @Test + public void shouldNotBeSuccessful_whenHttpResponseIsOtherThanOk() throws Exception { + + when(statusLine.getStatusCode()).thenReturn(FORBIDDEN.getStatusCode()); + + List<String> output = httpDmaapConsumer.fetch(TIMEOUT_MS, LIMIT); + + assertTrue(output.isEmpty()); + verify(httpClient).execute(any(HttpGet.class)); + verify(httpResponse).getStatusLine(); + verify(httpResponse).getEntity(); + verify(httpResponse).close(); + verify(statusLine).getStatusCode(); + verifyNoMoreInteractions(httpClient, httpResponse, statusLine, entity); + } + + @Test + public void shouldNotBeSuccessful_whenRequestToOneOfUrlsCannotBeSent() throws Exception { + + when(httpClient.execute(any(HttpGet.class))).thenThrow(new ClientProtocolException()); + + List<String> output = httpDmaapConsumer.fetch(TIMEOUT_MS, LIMIT); + + assertTrue(output.isEmpty()); + verify(httpClient).execute(any(HttpGet.class)); + verifyNoMoreInteractions(httpClient, httpResponse, statusLine, entity); + + + reset(httpClient); + when(httpClient.execute(any(HttpGet.class))).thenReturn(httpResponse); + when(statusLine.getStatusCode()).thenReturn(OK.getStatusCode()); + + output = httpDmaapConsumer.fetch(TIMEOUT_MS, LIMIT); + + assertFalse(output.isEmpty()); + assertTrue(output.containsAll(OUTPUT_MSG)); + verify(httpClient).execute(any(HttpGet.class)); + verify(httpResponse).getStatusLine(); + verify(httpResponse).getEntity(); + verify(httpResponse).close(); + verify(statusLine).getStatusCode(); + verifyNoMoreInteractions(httpClient, httpResponse, statusLine, entity); + } + +}
\ No newline at end of file diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/http/TestHttpDmaapProducerImpl.java b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/http/TestHttpDmaapProducerImpl.java new file mode 100644 index 000000000..01e41a857 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/http/TestHttpDmaapProducerImpl.java @@ -0,0 +1,135 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.messaging.dmaap.http; + +import static javax.ws.rs.core.Response.Status.FORBIDDEN; +import static javax.ws.rs.core.Response.Status.OK; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collection; +import org.apache.http.StatusLine; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; + +public class TestHttpDmaapProducerImpl { + + private static final Collection<String> URLS = Arrays.asList("test.com", "test.org"); + private static final String TOPIC_NAME = "Topic"; + private static final String USERNAME = "username"; + private static final String PASSWORD = "password"; + private static final String PARTITION = "partition"; + private static final String DATA = "data"; + + + @Spy + private HttpDmaapProducerImpl httpDmaapProducer = new HttpDmaapProducerImpl(); + + @Mock + private CloseableHttpClient httpClient; + + @Mock + private CloseableHttpResponse httpResponse; + + @Mock + private StatusLine statusLine; + + @Before + public void setUp() throws Exception { + httpDmaapProducer = new HttpDmaapProducerImpl(URLS, TOPIC_NAME); + httpDmaapProducer.updateCredentials(USERNAME, PASSWORD); + + MockitoAnnotations.initMocks(this); + doReturn(httpClient).when(httpDmaapProducer).getClient(); + when(httpClient.execute(any(HttpPost.class))).thenReturn(httpResponse); + when(httpResponse.getStatusLine()).thenReturn(statusLine); + } + + @Test + public void shouldPostHttpRequest() throws Exception { + + when(statusLine.getStatusCode()).thenReturn(OK.getStatusCode()); + + boolean successful = httpDmaapProducer.post(PARTITION, DATA); + + assertTrue(successful); + verify(httpClient).execute(any(HttpPost.class)); + verify(httpResponse).getStatusLine(); + verify(httpResponse).close(); + verify(statusLine).getStatusCode(); + verifyNoMoreInteractions(httpClient, httpResponse, statusLine); + } + + @Test + public void shouldNotBeSuccessful_whenHttpResponseIsOtherThanOk() throws Exception { + + when(statusLine.getStatusCode()).thenReturn(FORBIDDEN.getStatusCode()); + + boolean successful = httpDmaapProducer.post(PARTITION, DATA); + + assertFalse(successful); + verify(httpClient).execute(any(HttpPost.class)); + verify(httpResponse).getStatusLine(); + verify(httpResponse).close(); + verify(statusLine).getStatusCode(); + verifyNoMoreInteractions(httpClient, httpResponse, statusLine); + } + + @Test + public void shouldNotBeSuccessful_whenRequestToOneOfUrlsCannotBeSent() throws Exception { + + when(httpClient.execute(any(HttpPost.class))).thenThrow(new ClientProtocolException()); + + boolean successful = httpDmaapProducer.post(PARTITION, DATA); + + assertFalse(successful); + verify(httpClient).execute(any(HttpPost.class)); + verifyNoMoreInteractions(httpClient, httpResponse, statusLine); + + + reset(httpClient); + when(httpClient.execute(any(HttpPost.class))).thenReturn(httpResponse); + when(statusLine.getStatusCode()).thenReturn(OK.getStatusCode()); + + successful = httpDmaapProducer.post(PARTITION, DATA); + + assertTrue(successful); + verify(httpClient).execute(any(HttpPost.class)); + verify(httpResponse).getStatusLine(); + verify(httpResponse).close(); + verify(statusLine).getStatusCode(); + verifyNoMoreInteractions(httpClient, httpResponse, statusLine); + } +}
\ No newline at end of file diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/utils/TestDmaapUtil.java b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/utils/TestDmaapUtil.java new file mode 100644 index 000000000..1567242b5 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/java/org/onap/appc/adapter/messaging/dmaap/utils/TestDmaapUtil.java @@ -0,0 +1,268 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.messaging.dmaap.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.util.Properties; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.appc.configuration.ConfigurationFactory; + +public class TestDmaapUtil { + private static Class<?> configurationFactoryClass; + private static Field configField; + + @Test + public void testCreateConsumerPropFile() { + String topic = "JunitTopicOne"; + Properties junitProps = new Properties(); + junitProps.put("host", "192.168.10.10"); + junitProps.put("group", "junit-client"); + junitProps.put("id", "junit-consumer-one"); + junitProps.put("filter", "none"); + + String junitFile = null; + + // ensure file path property is not set + if (System.getProperty(DmaapUtil.DMAAP_PROPERTIES_PATH) != null) { + System.clearProperty(DmaapUtil.DMAAP_PROPERTIES_PATH); + + // set configuration to null to force reloading of properties + try { + configField.set(null, null); + } catch (IllegalArgumentException | IllegalAccessException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + try { + junitFile = DmaapUtil.createConsumerPropFile(topic, junitProps); + } catch (IOException e) { + e.printStackTrace(); + fail("Exception creating consumer property file"); + } + + assertNotNull(junitFile); + + // open file and verify properties + File testFile = new File(junitFile); + assertTrue(testFile.exists()); + + InputStream is = null; + Properties testProps = new Properties(); + try { + is = new FileInputStream(testFile); + testProps.load(is); + } catch (FileNotFoundException e) { + e.printStackTrace(); + fail("Exception opening consumer property file"); + } catch (IOException e) { + e.printStackTrace(); + fail("Exception opening consumer property file"); + } finally { + try { + if (is != null) { + is.close(); + } + } catch (IOException ex) { + ex.printStackTrace(); + fail("Exception closing consumer property file"); + } + } + + assertFalse(testProps.isEmpty()); + + assertEquals(testProps.get("host"), "192.168.10.10"); + assertEquals(testProps.get("group"), "junit-client"); + assertEquals(testProps.get("id"), "junit-consumer-one"); + assertEquals(testProps.get("filter"), "none"); + assertEquals(testProps.get("TransportType"), "HTTPNOAUTH"); + } + + @Test + public void testCreateConsumerPropFileWithCustomProfile() { + String topic = "JunitTopicOne"; + Properties junitProps = new Properties(); + junitProps.put("host", "192.168.10.10"); + junitProps.put("group", "junit-client"); + junitProps.put("id", "junit-consumer-two"); + junitProps.put("filter", "none"); + + String junitFile = null; + + // set property for DMaaP profile + System.setProperty(DmaapUtil.DMAAP_PROPERTIES_PATH, "src/test/resources/org/onap/appc"); + + // set configuration to null to force reloading of properties + try { + configField.set(null, null); + } catch (IllegalArgumentException | IllegalAccessException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + try { + junitFile = DmaapUtil.createConsumerPropFile(topic, junitProps); + } catch (IOException e) { + e.printStackTrace(); + fail("Exception creating consumer property file"); + } + + assertNotNull(junitFile); + + // open file and verify properties + File testFile = new File(junitFile); + assertTrue(testFile.exists()); + + InputStream is = null; + Properties testProps = new Properties(); + try { + is = new FileInputStream(testFile); + testProps.load(is); + } catch (FileNotFoundException e) { + e.printStackTrace(); + fail("Exception opening consumer property file"); + } catch (IOException e) { + e.printStackTrace(); + fail("Exception opening consumer property file"); + } finally { + try { + if (is != null) { + is.close(); + } + } catch (IOException ex) { + ex.printStackTrace(); + fail("Exception closing consumer property file"); + } + } + + assertFalse(testProps.isEmpty()); + + assertEquals(testProps.get("host"), "192.168.10.10"); + assertEquals(testProps.get("group"), "junit-client"); + assertEquals(testProps.get("id"), "junit-consumer-two"); + assertEquals(testProps.get("filter"), "none"); + assertEquals(testProps.get("TransportType"), "HTTPAAF"); + } + + @Test + public void testCreateProducerPropFile() { + String topic = "JunitTopicOne"; + Properties junitProps = new Properties(); + junitProps.put("host", "192.168.10.10"); + junitProps.put("group", "junit-client"); + junitProps.put("id", "junit-producer-one"); + junitProps.put("filter", "none"); + + String junitFile = null; + + // ensure file path property is not set + if (System.getProperty(DmaapUtil.DMAAP_PROPERTIES_PATH) != null) { + System.clearProperty(DmaapUtil.DMAAP_PROPERTIES_PATH); + + // set configuration to null to force reloading of properties + try { + configField.set(null, null); + } catch (IllegalArgumentException | IllegalAccessException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + + try { + junitFile = DmaapUtil.createProducerPropFile(topic, junitProps); + } catch (IOException e) { + e.printStackTrace(); + fail("Exception creating consumer property file"); + } + + assertNotNull(junitFile); + + // open file and verify properties + File testFile = new File(junitFile); + assertTrue(testFile.exists()); + + InputStream is = null; + Properties testProps = new Properties(); + try { + is = new FileInputStream(testFile); + testProps.load(is); + } catch (FileNotFoundException e) { + e.printStackTrace(); + fail("Exception opening consumer property file"); + } catch (IOException e) { + e.printStackTrace(); + fail("Exception opening consumer property file"); + } finally { + try { + if (is != null) { + is.close(); + } + } catch (IOException ex) { + ex.printStackTrace(); + fail("Exception closing consumer property file"); + } + } + + assertFalse(testProps.isEmpty()); + + assertEquals(testProps.get("host"), "192.168.10.10"); + assertEquals(testProps.get("group"), "junit-client"); + assertEquals(testProps.get("id"), "junit-producer-one"); + assertEquals(testProps.get("filter"), "none"); + assertEquals("HTTPNOAUTH", testProps.get("TransportType")); + } + + /** + * Use reflection to locate fields and methods so that they can be + * manipulated during the test to change the internal state accordingly. + * + * @throws NoSuchFieldException + * if the field(s) dont exist + * @throws SecurityException + * if reflective access is not allowed + * @throws NoSuchMethodException + * If the method(s) dont exist + */ + @SuppressWarnings("nls") + @BeforeClass + public static void once() throws NoSuchFieldException, SecurityException, NoSuchMethodException { + configurationFactoryClass = ConfigurationFactory.class; + + configField = configurationFactoryClass.getDeclaredField("config"); + configField.setAccessible(true); + } +} diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/DCAEResponse.txt b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/DCAEResponse.txt new file mode 100644 index 000000000..884a8525f --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/DCAEResponse.txt @@ -0,0 +1,20 @@ +{ +"requestTime": "0000-00-00 14:31:19.653787", +"policyVersion": "13", +"VMName": "123", +"from": "test", +"msgOid": ".1.3.6.1.4.1.193.183.4.1.3.5.1.4", +"trapID": "1234567", +"requestClient": "test", +"message": "Abnormal condition detected", +"time": "123567890", +"policyName": "RESTART", +"trapIDOID": ".1.3.6.1.4.1.193.183.4.1.3.5.1.3", +"request": "Restart", +"OPS_CL_timer": "15", +"nOID": ".1.3.6.1.4.1.193.183.4.2.0.4", +"AgentAddress": "192.168.1.2", +"vmOID": ".1.3.6.1.4.1.193.183.4.1.2.1", +"AICTenantID": "0123456789abcdef0123456789", +"AICVServerSelfLink": "http://somewhere" +}
\ No newline at end of file diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/org/onap/appc/consumer.properties b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/org/onap/appc/consumer.properties new file mode 100644 index 000000000..709619452 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/org/onap/appc/consumer.properties @@ -0,0 +1,54 @@ +### +# ============LICENSE_START======================================================= +# ONAP : APPC +# ================================================================================ +# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Copyright (C) 2017 Amdocs +# ============================================================================= +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END========================================================= +### + +#TransportType-Specify which way user want to use. I.e. <HTTPAAF,DME2,HTTPAUTH > +TransportType=HTTPAAF +Latitude =50.000000 +Longitude =-100.000000 +Version =1.0 +ServiceName =dmaap-v1.dev.dmaap.dt.saat.acsi.openecomp.org/events +Environment =TEST +Partner=BOT_R +routeOffer=MR1 +SubContextPath =/ +Protocol =http +MethodType =GET +contenttype =application/json +#authKey=01234567890abcde:01234567890abcdefghijklmn +#authDate=2016-02-18T13:57:37-0800 +host=127.0.0.1 +topic=org.onap.appc.UNIT-TEST +group=jmsgrp +id=2 +timeout=15000 +limit=1000 +filter= +AFT_DME2_EXCHANGE_REQUEST_HANDLERS=com.att.nsa.test.PreferredRouteRequestHandler +AFT_DME2_EXCHANGE_REPLY_HANDLERS=com.att.nsa.test.PreferredRouteReplyHandler +AFT_DME2_REQ_TRACE_ON=true +AFT_ENVIRONMENT=AFTUAT +AFT_DME2_EP_CONN_TIMEOUT=15000 +AFT_DME2_ROUNDTRIP_TIMEOUT_MS=240000 +AFT_DME2_EP_READ_TIMEOUT_MS=50000 +sessionstickinessrequired=NO +DME2preferredRouterFilePath=preferredRoute.txt diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/org/onap/appc/default.properties b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/org/onap/appc/default.properties new file mode 100644 index 000000000..8dea0a61d --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/org/onap/appc/default.properties @@ -0,0 +1,38 @@ +### +# ============LICENSE_START======================================================= +# ONAP : APPC +# ================================================================================ +# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Copyright (C) 2017 Amdocs +# ============================================================================= +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END========================================================= +### + +org.onap.appc.bootstrap.file=test.properties +org.onap.appc.bootstrap.path=/opt/onap/appc/data/properties,${user.home},. + +# Properties commented out below are provided in appc.properties +poolMembers=10.0.0.1 +#event.pool.members=<DMAAP_IP>:3904 + +topic.read=APPC-CL +topic.read.timeout=5 +topic.write=APPC-CL +event.topic.write=APPC-CL +client.name=APPC-CLIENT-DMAAP-ADAPTER-TEST +client.name.id=0 + +metric.enabled=false; diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/org/onap/appc/producer.properties b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/org/onap/appc/producer.properties new file mode 100644 index 000000000..9cc7f2e55 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/org/onap/appc/producer.properties @@ -0,0 +1,52 @@ +### +# ============LICENSE_START======================================================= +# ONAP : APPC +# ================================================================================ +# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Copyright (C) 2017 Amdocs +# ============================================================================= +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END========================================================= +### + +#TransportType-Specify which way user want to use. I.e. <HTTPAAF,DME2,HTTPAUTH > +TransportType=HTTPAAF +Latitude =50.000000 +Longitude =-100.000000 +Version =1.0 +ServiceName =dmaap-v1.dev.dmaap.dt.saat.acsi.openecomp.org/events +Environment =TEST +Partner=BOT_R +SubContextPath =/ +Protocol =http +MethodType =POST +contenttype = application/json +authKey=01234567890abcde:01234567890abcdefghijklmn +authDate=2016-07-20T11:30:56-0700 +host=127.0.0.1 +topic=org.onap.appc.UNIT-TEST +partition=2 +maxBatchSize=100 +maxAgeMs=250 +AFT_DME2_EXCHANGE_REQUEST_HANDLERS=com.att.nsa.test.PreferredRouteRequestHandler +AFT_DME2_EXCHANGE_REPLY_HANDLERS=com.att.nsa.test.PreferredRouteReplyHandler +AFT_DME2_REQ_TRACE_ON=true +AFT_ENVIRONMENT=AFTUAT +AFT_DME2_EP_CONN_TIMEOUT=15000 +AFT_DME2_ROUNDTRIP_TIMEOUT_MS=240000 +AFT_DME2_EP_READ_TIMEOUT_MS=50000 +sessionstickinessrequired=NO +DME2preferredRouterFilePath=preferredRoute.txt +MessageSentThreadOccurance=50 diff --git a/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/test.properties b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/test.properties new file mode 100644 index 000000000..a451739bf --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-adapter-bundle/src/test/resources/test.properties @@ -0,0 +1,37 @@ +### +# ============LICENSE_START======================================================= +# ONAP : APPC +# ================================================================================ +# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Copyright (C) 2017 Amdocs +# ============================================================================= +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END========================================================= +### + +# Properties commented out below are provided in appc.properties +#poolMembers=<DMAAP_IP>:3904 +#event.pool.members=<DMAAP_IP>:3904 + +topic.read=APPC-TEST2 +topic.read.timeout=5 +topic.write=APPC-TEST2 +event.topic.write=APPC-TEST2 +client.name=APPC-CLIENT-DMAAP-ADAPTER-TEST +client.name.id=0 +#client.key=fakeKey +#client.secret=fakeSecret +#event.client.key=fakeKey +#event.client.secret=fakeSecret diff --git a/services/appc-dmaap-service/appc-dmaap-event-service/.gitignore b/services/appc-dmaap-service/appc-dmaap-event-service/.gitignore new file mode 100644 index 000000000..b83d22266 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-event-service/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/services/appc-dmaap-service/appc-dmaap-event-service/pom.xml b/services/appc-dmaap-service/appc-dmaap-event-service/pom.xml new file mode 100644 index 000000000..aa94e45a6 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-event-service/pom.xml @@ -0,0 +1,90 @@ +<!-- + ============LICENSE_START======================================================= + ONAP : APPC + ================================================================================ + Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>dmaap-event-service</artifactId> + <packaging>jar</packaging> + <version>1.7.0-SNAPSHOT</version> + <name>dmaapService</name> + <parent> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-parent</artifactId> + <version>2.1.6.RELEASE</version> + </parent> + <dependencies> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-security</artifactId> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.5.2</version> + </dependency> + <dependency> + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>appc-event-listener-bundle</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>appc-message-adapter-factory</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>appc-message-adapter-api</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>appc-dmaap-adapter-bundle</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + </plugin> + </plugins> + </build> +</project> diff --git a/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/App.java b/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/App.java new file mode 100644 index 000000000..afcb3277d --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/App.java @@ -0,0 +1,57 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.services.dmaapService; + +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Properties; +import java.util.Set; +import org.onap.appc.listener.AppcEventListenerActivator; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + + +/** + * Hello world! + * + */ +@SpringBootApplication +public class App +{ + public static void main( String[] args ) + { + + System.out.println("Starting"); + AppcEventListenerActivator event = new AppcEventListenerActivator(); + try { + event.start(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + SpringApplication.run(App.class, args); + } + + +} diff --git a/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/AuthenticationConfig.java b/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/AuthenticationConfig.java new file mode 100644 index 000000000..4031a5144 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/AuthenticationConfig.java @@ -0,0 +1,46 @@ +package org.onap.appc.services.dmaapService; + +import java.util.Properties; + +import org.onap.appc.configuration.ConfigurationFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class AuthenticationConfig extends WebSecurityConfigurerAdapter { + + private final String PROPERTIES_PREFIX = "appc.srvcomm.messaging"; + private final String DEFAULT_USER = "appc"; + private final String DEFAULT_PASSWORD = "onapappc"; + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().httpBasic(); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + org.onap.appc.configuration.Configuration configuration = ConfigurationFactory.getConfiguration(); + Properties props = configuration.getProperties(); + String user = props.getProperty(PROPERTIES_PREFIX + ".user"); + String pass = props.getProperty(PROPERTIES_PREFIX + ".pass"); + if(user == null) { + user = DEFAULT_USER; + } + if(pass == null) { + pass = DEFAULT_PASSWORD; + } + auth.inMemoryAuthentication().withUser(user).password(encoder().encode(pass)).roles("USER"); + } + + @Bean + public PasswordEncoder encoder() { + return new BCryptPasswordEncoder(); + } + +} diff --git a/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/EventServer.java b/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/EventServer.java new file mode 100644 index 000000000..9df67cbf2 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/EventServer.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.services.dmaapService; + +import org.onap.appc.adapter.messaging.dmaap.http.HttpDmaapConsumerImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +@RestController +public class EventServer { + + private static final EELFLogger LOG = EELFManager.getInstance().getLogger(EventServer.class); + + @Autowired + private PublishService publishService; + + @RequestMapping("/publish") + public PublishResponse publish(@RequestBody String body) { + PublishRequest req = PublishRequest.parsePublishRequest(body); + String result = publishService.publishMessage(req.getProps(),req.getPartition(), + req.getTopic(), req.getMessage()); + if(result.equals("Success")) { + return new PublishResponse(result); + } + LOG.error("Error during message publish: " + result); + throw new MessagingException(); + } + +} diff --git a/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/MessagingException.java b/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/MessagingException.java new file mode 100644 index 000000000..3c114a1ed --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/MessagingException.java @@ -0,0 +1,31 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.services.dmaapService; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR, reason="Error Publishing Messsage") +public class MessagingException extends RuntimeException { + + +} diff --git a/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/PublishRequest.java b/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/PublishRequest.java new file mode 100644 index 000000000..c242fdbfd --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/PublishRequest.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.services.dmaapService; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +public class PublishRequest { + + private static final EELFLogger LOG = EELFManager.getInstance().getLogger(PublishRequest.class); + + private String props; + private String partition; + private String message; + private String topic; + + private PublishRequest(String props, String partition, String topic, String message) { + this.props = props; + this.partition = partition; + this.message = message; + this.topic = topic; + } + + public String getProps() { + return props; + } + + public String getPartition() { + return partition; + } + + public String getMessage() { + return message; + } + + public String getTopic() { + return topic; + } + + public static PublishRequest parsePublishRequest(String data) { + //body content: props, partition, topic, message + String[] bodyParameters = new String[4]; + LOG.debug("Parsing message into " + bodyParameters.length + " parts: " + data); + int[] bodyParameterSizes = new int[bodyParameters.length]; + for(int i = 0; i < bodyParameters.length; i ++) { + String[] split = data.split("\\.", 2); + try { + bodyParameterSizes[i] = Integer.parseInt(split[0]); + } catch(NumberFormatException e) { + LOG.error("Could not parse message: " + data); + } + data = split[1]; + } + int cursor = 0; + for(int i = 0; i < bodyParameters.length; i ++) { + if(bodyParameterSizes[i] > 0) { + bodyParameters[i] = data.substring(cursor, cursor + bodyParameterSizes[i]); + cursor = cursor + bodyParameterSizes[i]; + } + } + return new PublishRequest(bodyParameters[0], bodyParameters[1], bodyParameters[2], bodyParameters[3]); + } + +} diff --git a/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/PublishResponse.java b/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/PublishResponse.java new file mode 100644 index 000000000..576c80d80 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/PublishResponse.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.services.dmaapService; + +public class PublishResponse { + + private String status; + + public PublishResponse(String status) { + this.status = status; + } + + public String getName() { + return status; + } + +} diff --git a/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/PublishService.java b/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/PublishService.java new file mode 100644 index 000000000..1e1b9e7f8 --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-event-service/src/main/java/org/onap/appc/services/dmaapService/PublishService.java @@ -0,0 +1,109 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.services.dmaapService; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; + +import org.onap.appc.adapter.factory.DmaapMessageAdapterFactoryImpl; +import org.onap.appc.configuration.Configuration; +import org.onap.appc.configuration.ConfigurationFactory; +import org.springframework.stereotype.Service; +import org.onap.appc.adapter.message.MessageAdapterFactory; +import org.onap.appc.adapter.message.Producer; +import org.onap.appc.adapter.messaging.dmaap.http.HttpDmaapProducerImpl; + +@Service +public class PublishService { + + private Map<String,Producer> producers; + private MessageAdapterFactory factory; + Configuration configuration; + + public PublishService() { + this.factory = new DmaapMessageAdapterFactoryImpl(); + producers = new HashMap<>(); + } + + public PublishService(MessageAdapterFactory factory) { + this.factory = factory; + producers = new HashMap<>(); + } + + public String publishMessage(String key, String partition, String topic, String message) { + Producer producer = getProducer(key, topic); + if(producer == null) { + return "Could not find producer with property prefix: " + key; + } + boolean success = producer.post(partition, message); + if(success) { + return "Success"; + } + return "Failed. See dmaap service jar log."; + } + + private Producer getProducer(String key, String topic) { + String searchKey = key; + if(topic != null) { + searchKey += topic; + } + Producer producer = producers.get(searchKey); + if(producer != null) { + return producer; + } + producer = newProducer(key, topic); + producers.put(searchKey,producer); + return producer; + } + + private Producer newProducer(String key, String topic) { + Configuration configuration; + if(this.configuration != null) { + configuration = this.configuration; + } else { + configuration = ConfigurationFactory.getConfiguration(); + } + Properties props = configuration.getProperties(); + HashSet<String> pool = new HashSet<>(); + if (props != null) { + String writeTopic; + if(topic == null) { + writeTopic = props.getProperty(key + ".topic.write"); + } else { + writeTopic = topic; + } + String apiKey = props.getProperty(key + ".client.key"); + String apiSecret = props.getProperty(key + ".client.secret"); + String hostnames = props.getProperty(key + ".poolMembers"); + if (hostnames != null && !hostnames.isEmpty()) { + for (String name : hostnames.split(",")) { + pool.add(name); + } + } + return factory.createProducer(pool, writeTopic, apiKey, apiSecret); + } + return null; + } + +} diff --git a/services/appc-dmaap-service/appc-dmaap-event-service/src/test/java/org/onap/appc/services/PublishRequestTest.java b/services/appc-dmaap-service/appc-dmaap-event-service/src/test/java/org/onap/appc/services/PublishRequestTest.java new file mode 100644 index 000000000..7cc9bccfd --- /dev/null +++ b/services/appc-dmaap-service/appc-dmaap-event-service/src/test/java/org/onap/appc/services/PublishRequestTest.java @@ -0,0 +1,82 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.services; + +import org.onap.appc.services.dmaapService.PublishRequest; + +import org.junit.Assert; +import org.junit.Test; + +public class PublishRequestTest { + + @Test + public void testParsePublishRequest() { + //props, partition, topic, message + String props = "props.test"; + String partition = "testPartition"; + String topic = "testTopic"; + String message = "sameple message data"; + String data = props.length() + "." + partition.length() + "." + topic.length() + + "." + message.length() + "." + props + partition + topic + message; + PublishRequest publishRequest = PublishRequest.parsePublishRequest(data); + Assert.assertTrue(props.equals(publishRequest.getProps())); + Assert.assertTrue(partition.equals(publishRequest.getPartition())); + Assert.assertTrue(topic.equals(publishRequest.getTopic())); + Assert.assertTrue(message.equals(publishRequest.getMessage())); + + } + + @Test + public void testParsePublishRequest_period_in_message() { + //props, partition, topic, message + String props = "props.test"; + String partition = "testPartition"; + String topic = "testTopic"; + String message = "sameple. message. dat.a"; + String data = props.length() + "." + partition.length() + "." + topic.length() + + "." + message.length() + "." + props + partition + topic + message; + PublishRequest publishRequest = PublishRequest.parsePublishRequest(data); + Assert.assertTrue(props.equals(publishRequest.getProps())); + Assert.assertTrue(partition.equals(publishRequest.getPartition())); + Assert.assertTrue(topic.equals(publishRequest.getTopic())); + Assert.assertTrue(message.equals(publishRequest.getMessage())); + + } + + @Test + public void testParsePublishRequest_with_missing_value() { + //props, partition, topic, message + String props = "props.test"; + String partition = "testPartition"; + String topic = ""; + String message = "sameple message data"; + String data = props.length() + "." + partition.length() + "." + topic.length() + + "." + message.length() + "." + props + partition + topic + message; + PublishRequest publishRequest = PublishRequest.parsePublishRequest(data); + Assert.assertTrue(props.equals(publishRequest.getProps())); + Assert.assertTrue(partition.equals(publishRequest.getPartition())); + Assert.assertTrue(null == publishRequest.getTopic()); + Assert.assertTrue(message.equals(publishRequest.getMessage())); + + } + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/.gitignore b/services/appc-dmaap-service/appc-event-listener-bundle/.gitignore new file mode 100644 index 000000000..8d27d5a75 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/.gitignore @@ -0,0 +1,28 @@ +# ============LICENSE_START========================================== +# ONAP : APPC +# =================================================================== +# Copyright (C) 2017-2018 AT&T 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. +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# ============LICENSE_END============================================ +/bin/* +/target/ +/.settings/ +/bin/ +/target-ide/ +/logs/ +/debug-logs/ diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/pom.xml b/services/appc-dmaap-service/appc-event-listener-bundle/pom.xml new file mode 100644 index 000000000..0d02b2155 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/pom.xml @@ -0,0 +1,141 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + ONAP : APPC + ================================================================================ + Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + Copyright (C) 2017 Amdocs + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR 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.appc.parent</groupId> + <artifactId>binding-parent</artifactId> + <version>2.6.2</version> + <relativePath /> + </parent> + <groupId>org.onap.appc.services.dmaap</groupId> + + <artifactId>appc-event-listener-bundle</artifactId> + <packaging>jar</packaging> + <name>Event Listener - bundle</name> + + <dependencies> +<!-- + <dependency> + <groupId>org.onap.appc</groupId> + <artifactId>appc-rest-bundle</artifactId> + <version>${project.version}</version> + </dependency> +--> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + <version>${logback.version}</version> + </dependency> + <dependency> + <groupId>com.att.eelf</groupId> + <artifactId>eelf-core</artifactId> + <exclusions> + <exclusion> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.onap.appc</groupId> + <artifactId>appc-common-bundle</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>appc-dmaap-adapter-bundle</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>appc-message-adapter-api</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>appc-message-adapter-factory</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> +<!-- + <dependency> + <groupId>org.onap.appc</groupId> + <artifactId>appc-rest-model</artifactId> + <version>${project.version}</version> + </dependency> +--> + + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.5.3</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpcore</artifactId> + <version>${apache.httpcomponents.version}</version> + </dependency> + + <dependency> + <groupId>equinoxSDK381</groupId> + <artifactId>org.eclipse.osgi</artifactId> + </dependency> + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + </dependency> + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + <version>1.2</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <version>1.7.0-SNAPSHOT</version> +</project> diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/AbstractListener.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/AbstractListener.java new file mode 100644 index 000000000..b9e8a6c84 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/AbstractListener.java @@ -0,0 +1,158 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Modifications Copyright (C) 2019 IBM + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener; + +import java.security.SecureRandom; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.commons.lang3.concurrent.BasicThreadFactory; +import org.onap.appc.listener.impl.EventHandlerImpl; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +public abstract class AbstractListener implements Listener { + + private final EELFLogger LOG = EELFManager.getInstance().getLogger(AbstractListener.class); + + protected AtomicBoolean run = new AtomicBoolean(false); + protected int QUEUED_MIN = 1; + protected int QUEUED_MAX = 10; + protected int THREAD_MIN = 4; + protected int THREAD_MAX = THREAD_MIN; // Fixed thread pool + protected int THREAD_SCALE_DOWN_SEC = 10; // Number of seconds to wait until we remove idle threads + protected ThreadPoolExecutor executor; + protected EventHandler dmaap; + protected ListenerProperties props; + + private String listenerId; + + public AbstractListener(ListenerProperties props) { + updateProperties(props); + + dmaap = new EventHandlerImpl(props); + if (dmaap.getClientId().equals("0")) { + dmaap.setClientId(String.valueOf(new SecureRandom().nextInt(1000))); + } + + BlockingQueue<Runnable> threadQueue = new ArrayBlockingQueue<Runnable>(QUEUED_MAX + QUEUED_MIN + 1); + executor = new ThreadPoolExecutor(THREAD_MIN, THREAD_MAX, THREAD_SCALE_DOWN_SEC, TimeUnit.SECONDS, threadQueue, + new JobRejectionHandler()); + + // Custom Named thread factory + BasicThreadFactory threadFactory = new BasicThreadFactory.Builder().namingPattern("DMaaP-Worker-%d").build(); + executor.setThreadFactory(threadFactory); + + run.set(true); + } + + /** + * Starts a loop that will only end after stop() or stopNow() are called. The loop will read messages off the DMaaP + * topic and perform some action on them while writing messages back to DMaaP at critical points in the execution. + * Inherited from Runnable. + * + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + LOG.error("Listener.run() has not been implemented"); + } + + @Override + public void stop() { + run.set(false); + LOG.info(String.format("Stopping with %d messages in queue", executor.getQueue().size())); + executor.shutdown(); + try { + executor.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + LOG.error("Listener graceful stop() failed", e); + Thread.currentThread().interrupt(); + } + + // close DMaaP clients + if (dmaap != null) { + dmaap.closeClients(); + } + LOG.info("Listener Thread Pool Finished"); + } + + @Override + public void stopNow() { + run.set(false); + LOG.info(String.format("StopNow called. Orphaning %d messages in the queue", executor.getQueue().size())); + executor.getQueue().clear(); + stop(); + } + + @Override + public String getBenchmark() { + return String.format("%s - No benchmarking implemented.", getListenerId()); + } + + @Override + public String getListenerId() { + return listenerId; + } + + // Sets the id of the listener in + @Override + public void setListenerId(String id) { + listenerId = id; + } + + private void updateProperties(ListenerProperties properties) { + this.props = properties; + QUEUED_MIN = + Integer.valueOf(props.getProperty(ListenerProperties.KEYS.THREADS_MIN_QUEUE, String.valueOf(QUEUED_MIN))); + QUEUED_MAX = + Integer.valueOf(props.getProperty(ListenerProperties.KEYS.THREADS_MAX_QUEUE, String.valueOf(QUEUED_MAX))); + THREAD_MIN = + Integer.valueOf(props.getProperty(ListenerProperties.KEYS.THREADS_MIN_POOL, String.valueOf(THREAD_MIN))); + THREAD_MAX = + Integer.valueOf(props.getProperty(ListenerProperties.KEYS.THREADS_MAX_POOL, String.valueOf(THREAD_MAX))); + + listenerId = props.getPrefix(); + } + + /** + * This class will be used to handle what happens when we cannot add a job because of a ThreadPool issue. It does + * not get invoked if there is any fault with the job. NOTE: So far, this has only been seen when doing a + * {@link Listener#stopNow} + * + */ + class JobRejectionHandler implements RejectedExecutionHandler { + @Override + public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { + LOG.error(String.format("A job was rejected. [%s]", r)); + } + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/AppcEventListenerActivator.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/AppcEventListenerActivator.java new file mode 100644 index 000000000..5c6fd4c67 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/AppcEventListenerActivator.java @@ -0,0 +1,196 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener; + +import org.onap.appc.configuration.Configuration; +import org.onap.appc.configuration.ConfigurationFactory; +import org.onap.appc.listener.impl.ControllerImpl; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; + +/** + * This activator is used to initialize and terminate the dmaap listener controller and pool(s) + * <p> + * The DMaaP listener is responsible for listening to a topic on the Universal Event Bus and reading in messages that + * conform to the DCAE message format for APPC. These messages will then be parsed and passed along to the APPC Provider + * to take action on. The listener will also send messages out on DMaaP during critical phases. The messages sent out + * will have a status of: + * <ul> + * <li><i>PENDING</i> - The listener has read the message off of DMaaP and has put it in the queue to be processed</li> + * <li><i>ACTIVE</i> - The listener has begun actually processing the request and is waiting on the appc provider to + * complete the request</li> + * <li><i>SUCCESS</i> or <i>FAILURE</i> - The listener has gotten a response back from the appc provider. If it is a + * FAILURE, a message should also be included</li> + * </ul> + * </p> + * <p> + * Activation of the bundle will provision 1 controller that in turn will provision 1 (or in the future more) listener + * to interact with DMaaP. Each listener will have a queue of messages read off of DMaaP and a thread pool of workers to + * process them. This worker is responsible for contacting appc provider to perform the action + * </p> + * <p> + * When the bundle is deactivated, the stopNow() method is called and the thread pool is emptied and all remaining jobs + * are orphaned. Alternatively stop() could be called which would allow all remaining jobs in the queue to complete at + * the cost of longer run time. + * </p> + * + * @since Aug 30, 2015 + * @version $Id$ + */ +public class AppcEventListenerActivator { + + + /** + * The configuration object + */ + private Configuration configuration; + + /** + * The reference to the actual implementation object that implements the services + */ + private Controller adapter; + + /** + * The logger to be used + */ + private final EELFLogger LOG = EELFManager.getInstance().getLogger(AppcEventListenerActivator.class); + + /** + * Called when this bundle is started so the Framework can perform the bundle-specific activities necessary to start + * this bundle. This method can be used to register services or to allocate any resources that this bundle needs. + * <p> + * This method must complete and return to its caller in a timely manner. + * </p> + * + * @param ctx + * The execution context of the bundle being started. + * @throws java.lang.Exception + * If this method throws an exception, this bundle is marked as stopped and the Framework will remove + * this bundle's listeners, unregister all services registered by this bundle, and release all services + * used by this bundle. + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start() throws Exception { + LOG.info("Starting Bundle " + getName()); + + Properties props = getProperties(); + + Set<ListenerProperties> listeners = new HashSet<>(); + + // Configure event listener for the demo use case + ListenerProperties demoProps = new ListenerProperties("appc.demo", props); + // Only add the listener if properties are set + if (!demoProps.getProperties().isEmpty()) { + demoProps.setListenerClass(org.onap.appc.listener.demo.impl.ListenerImpl.class); + listeners.add(demoProps); + } + + + ListenerProperties clLCMProps = new ListenerProperties("appc.LCM", props); + // Only add the listener if properties are set + if (!clLCMProps.getProperties().isEmpty()) { + clLCMProps.setListenerClass(org.onap.appc.listener.LCM.impl.ListenerImpl.class); + listeners.add(clLCMProps); + } + + + // Configure the OAM properties + String oamPropKeyPrefix = "appc.OAM"; + ListenerProperties oamProps = new ListenerProperties(oamPropKeyPrefix, props); + // Only add the listener if properties are set and enabled is true + if (!oamProps.getProperties().isEmpty() && isAppcOamPropsListenerEnabled(oamProps)) { + oamProps.setListenerClass(org.onap.appc.listener.LCM.impl.ListenerImpl.class); + listeners.add(oamProps); + } else { + LOG.warn(String.format("The listener %s is disabled and will not be run", oamPropKeyPrefix)); + } + + adapter = new ControllerImpl(listeners); + adapter.start(); + + LOG.info("DMaaP Listener started successfully"); + } + + /** + * Called when this bundle is stopped so the Framework can perform the bundle-specific activities necessary to stop + * the bundle. In general, this method should undo the work that the BundleActivator.start method started. There + * should be no active threads that were started by this bundle when this bundle returns. A stopped bundle must not + * call any Framework objects. + * <p> + * This method must complete and return to its caller in a timely manner. + * </p> + * + * @param ctx + * The execution context of the bundle being stopped. + * @throws java.lang.Exception + * If this method throws an exception, the bundle is still marked as stopped, and the Framework will + * remove the bundle's listeners, unregister all services registered by the bundle, and release all + * services used by the bundle. * + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop() throws Exception { + boolean stopNow = true; + LOG.info("Stopping DMaaP Listener. StopNow=" + stopNow); + adapter.stop(stopNow); + LOG.info("DMaaP Listener stopped successfully"); + } + + public String getName() { + return "DMaaP Listener"; + } + + /** + * Check if AppcOam props disable listener or not + * + * @param listenerProperties of ListenerProperties objext + * @return false only if AppcOam disabled key is defined and equal to true. Otherwise, return true. + */ + private boolean isAppcOamPropsListenerEnabled(ListenerProperties listenerProperties) { + final Properties appcOamProperties = listenerProperties.getProperties(); + + boolean result; + if (appcOamProperties == null) { + result = true; + } else { + result = !Boolean.parseBoolean(appcOamProperties.getProperty( + ListenerProperties.KEYS.DISABLED.getPropertySuffix())); + } + + return result; + } + + /** + * Get properties from configuration + */ + Properties getProperties() { + configuration = ConfigurationFactory.getConfiguration(); + return configuration.getProperties(); + } + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/Controller.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/Controller.java new file mode 100644 index 000000000..25f4735a2 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/Controller.java @@ -0,0 +1,57 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener; + +import java.util.Map; + +/** + * A controller is responsible for creating a listener for each ListenerProperties object that is passed in to it on + * instantiation. The controller will create a thread pool that will contain all of the listener threads so no listener + * can crash the controller. + * + */ +public interface Controller { + + /** + * Creates a new thread in the thread pool for an implementation of the {@see #Listener} class set in the + * ListenerProperties. This thread is run immediately after it is created. + */ + public void start(); + + /** + * Stops each of the listeners known by this controller. Takes an optional parameter that indicates the the listener + * should stop immediately rather than waiting for all threads to complete. + * + * @param stopNow + * Determines what method the listeners should use to shutdown. If true, listeners will use the stopNow() + * method. Otherwise they will use the stop() method. + */ + public void stop(boolean stopNow); + + /** + * @return A Map of ListenerProperties and the Listener object that is running in the controllers thread pool. + */ + public Map<ListenerProperties, Listener> getListeners(); + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/EventHandler.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/EventHandler.java new file mode 100644 index 000000000..35052a085 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/EventHandler.java @@ -0,0 +1,208 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +/** + * EventHandler defines a class that wraps DMaaP operations (most notably Get Message and Post Message) to make them + * easier to use. + * + */ +public interface EventHandler { + + /** + * Gets a list of messages as Strings on the read topic. + * + * @return A list of String messages. Never returns null. + */ + public List<String> getIncomingEvents(); + + /** + * Gets a list of messages as String on the read topic. + * + * @param limit + * The maximum amount of entries to return + * @return A list of String messages. Never returns null. + */ + public List<String> getIncomingEvents(int limit); + + /** + * Gets a list of messages Mapped to the given Class. If a message cannot be mapped to that class, it is discarded. + * + * @param cls + * The class to map the message to. + * @return A list of objects of the provided class. Never returns null. + */ + public <T> List<T> getIncomingEvents(Class<T> cls); + + /** + * Gets a list of messages Mapped to the given Class. If a message cannot be mapped to that class, it is discarded. + * + * @param cls + * The class to map the message to. + * @param limit + * The maximum amount of entries to return + * @return A list of objects of the provided class. Never returns null. + */ + public <T> List<T> getIncomingEvents(Class<T> cls, int limit); + + /** + * Posts the String message to the write topic(s). + * + * @param event + * The String to post. + */ + public void postStatus(String event); + + /** + * Posts the String message to the write topic(s) on the specified partition. Partitions are only used to guarantee + * ordering and do not impact if data is retreived. + * + * @param partition + * The partition to post to or null if no partition should be used. + * @param event + * The String to post. + */ + public void postStatus(String partition, String event); + + /** + * @return The client/group id used to read messages + */ + public String getClientId(); + + /** + * Set the client/group id used to read messages + * + * @param clientId + * The new clientId to use + */ + public void setClientId(String clientId); + + /** + * @return The client/group name to use. + */ + public String getClientName(); + + /** + * Set the client/group name used to read messages. + * + * @param clientName + * The new clientName to use + */ + public void setClientName(String clientName); + + /** + * @return The name of the topic to read from + */ + public String getReadTopic(); + + /** + * Set the name of the topic to read from. + * + * @param topic + * The new topic to read from + */ + public void setReadTopic(String topic); + + /** + * @return The name of the topic to write to + */ + public String getWriteTopic(); + + /** + * Set the name of the topic to write to + * + * @param topic + * The new topic to write to + */ + public void setWriteTopic(String topic); + + /** + * Adds a DMaaP host to the host pool + * + * @param host + * The host to add to the pool in <host>:<port> format + */ + public void addToPool(String host); + + /** + * Remove the host name from the pool if it exists + * + * @param host + * The host to add to the pool in <host>:<port> format + */ + public void removeFromPool(String host); + + /** + * Get all of the hosts in the DMaaP pool + * + * @return A collection of host in <host>:<port> format + */ + public Collection<String> getPool(); + + /** + * Clear any provided api credentials and make future requests as an unauthenticated user + */ + public void clearCredentials(); + + /** + * Sets Blacklist time for a server with response problem in seconds + */ + void setResponseProblemBlacklistTime(String duration); + + /** + * Sets Blacklist time for a server with server problem in seconds + */ + void setServerProblemBlacklistTime(String duration); + + /** + * Sets Blacklist time for a server with DNS problem in seconds + */ + void setDnsIssueBlacklistTime(String duration); + + /** + * Sets Blacklist time for a server with IO Exception problem in seconds + */ + void setIOExceptionBlacklistTime(String duration); + /** + * Set the api credentials and make future requests as an authenticated user + * + * @param access + * The access portion of the credentials (either user name or api key) + * @param secret + * The secret portion of the credentials (either password or api secret) + */ + + + public void setCredentials(String access, String secret); + + /** + * Close consumer/producer DMaaP clients + */ + public void closeClients(); + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/conv/Converter.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/conv/Converter.java new file mode 100644 index 000000000..8222af13f --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/conv/Converter.java @@ -0,0 +1,139 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.conv; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.SerializationFeature; +import org.apache.commons.lang3.StringUtils; +import org.json.JSONObject; +import org.onap.appc.listener.LCM.model.DmaapMessage; +import org.onap.appc.listener.LCM.model.DmaapOutgoingMessage; +import org.onap.appc.listener.util.Mapper; +import org.onap.ccsdk.sli.core.sli.SvcLogicException; + +public class Converter { + + private Converter() { + } + + public static DmaapOutgoingMessage convertJsonNodeToDmaapOutgoingMessage(DmaapMessage event, JsonNode inObj){ + + if (event == null || inObj == null) { + throw new IllegalArgumentException("One of given arguments is null"); + } + + DmaapOutgoingMessage outObj = new DmaapOutgoingMessage(); + outObj.setBody(inObj); + outObj.setRpcName(event.getRpcName()); + outObj.setVersion(event.getVersion()); + outObj.setType("response"); + outObj.setCorrelationID(event.getCorrelationID()); + return outObj; + } + + public static String convertDmaapOutgoingMessageToJsonString(DmaapMessage inObj) throws JsonProcessingException { + + if (inObj == null) + throw new IllegalArgumentException("Input message is null"); + + + ObjectMapper objectMapper = new ObjectMapper(); + ObjectWriter writer = objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL) + .configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true) + .writer().withFeatures(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS); + return writer.writeValueAsString(inObj); + + } + + public static DmaapOutgoingMessage buildDmaapOutgoingMessageWithUnexpectedError(DmaapMessage event, + Exception inputException) { + + if (event == null || inputException == null) { + throw new IllegalArgumentException("One of given arguments is null"); + } + + DmaapOutgoingMessage dmaapOutgoingMessage; + String errMsg = + StringUtils.isEmpty(inputException.getMessage()) ? inputException.toString() : inputException.getMessage(); + JSONObject commonHeaderJsonObject = Mapper.toJsonObject(event.getBody().get("input").get("common-header")); + JSONObject jsonObjectOutput = new JSONObject().accumulate("common-header", commonHeaderJsonObject) + .accumulate("status", new JSONObject().accumulate("code", 200).accumulate("value", errMsg)); + dmaapOutgoingMessage = new DmaapOutgoingMessage(); + dmaapOutgoingMessage.setRpcName(event.getRpcName()); + dmaapOutgoingMessage.setCorrelationID(event.getCorrelationID()); + dmaapOutgoingMessage.setType("error"); + dmaapOutgoingMessage.setVersion(event.getVersion()); + JSONObject jsonObjectBody = new JSONObject().accumulate("output", jsonObjectOutput); + JsonNode jsonNodeBody = Mapper.toJsonNodeFromJsonString(jsonObjectBody.toString()); + dmaapOutgoingMessage.setBody(jsonNodeBody); + return dmaapOutgoingMessage; + } + + public static String extractRequestIdWithSubId(JsonNode dmaapBody) { + + if (dmaapBody == null) { + throw new IllegalArgumentException("Dmaap body is null"); + } + + JsonNode commonHeaderJsonNode = dmaapBody.get("input").get("common-header"); + String requestId = getValue(commonHeaderJsonNode, "request-id", ""); + String subRequestId = getValue(commonHeaderJsonNode, "sub-request-id", ""); + if (!StringUtils.isEmpty(subRequestId)) { + requestId = requestId + "-" + subRequestId; + } + return requestId; + } + + public static Integer extractStatusCode(JsonNode event) { + + if (event == null){ + throw new IllegalArgumentException("Input event is null"); + } + + Integer statusCode; + statusCode = event.get("output").get("status").get("code").asInt(); + return statusCode; + } + + private static String getValue(JsonNode jsonNode, String name, String defaultValue) { + if (jsonNode == null) { + return defaultValue; + } + JsonNode childJsonNode = jsonNode.get(name); + if (childJsonNode == null) { + return defaultValue; + } + String value = childJsonNode.asText(); + if (value == null) { + return defaultValue; + } + return value; + } + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/impl/ListenerImpl.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/impl/ListenerImpl.java new file mode 100644 index 000000000..761d65231 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/impl/ListenerImpl.java @@ -0,0 +1,156 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.impl; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.att.eelf.i18n.EELFResourceManager; +import com.fasterxml.jackson.databind.JsonNode; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; +import java.util.concurrent.RejectedExecutionException; +import org.apache.commons.lang3.StringUtils; +import org.onap.appc.listener.AbstractListener; +import org.onap.appc.listener.LCM.conv.Converter; +import org.onap.appc.listener.LCM.model.DmaapIncomingMessage; +import org.onap.appc.listener.LCM.operation.ProviderOperations; +import org.onap.appc.listener.ListenerProperties; + +public class ListenerImpl extends AbstractListener { + + private final EELFLogger LOG = EELFManager.getInstance().getLogger(ListenerImpl.class); + + private long startTime = 0; + + private final ProviderOperations providerOperations; + + public ListenerImpl(ListenerProperties props) { + super(props); + + String url = props.getProperty("provider.url"); + String user = props.getProperty("provider.user"); + String pass = props.getProperty("provider.pass"); + providerOperations = new ProviderOperations(url, user, pass); + LOG.info("DMaaP Provider Endpoint: " + url); + } + + @Override + public void run() { + // Some vars for benchmarking + startTime = System.currentTimeMillis(); + + LOG.info("Running DMaaP Listener"); + + while (run.get()) { + // Only update if the queue is low. otherwise we read in more + // messages than we need + try { + if (executor.getQueue().size() <= QUEUED_MIN) { + LOG.debug("DMaaP queue running low. Querying for more jobs"); + + List<DmaapIncomingMessage> messages = dmaap + .getIncomingEvents(DmaapIncomingMessage.class, QUEUED_MAX); + LOG.debug(String.format("Read %d messages from dmaap", messages.size())); + for (DmaapIncomingMessage incoming : messages) { + // Acknowledge that we read the event + if (isValid(incoming)) { + String requestIdWithSubId = getRequestIdWithSubId(incoming.getBody()); + LOG.info("Acknowledging Message: " + requestIdWithSubId); + } + } + for (DmaapIncomingMessage incoming : messages) { + String requestIdWithSubId = getRequestIdWithSubId(incoming.getBody()); + // Add to pool if still running + if (run.get()) { + if (isValid(incoming)) { + LOG.info(String.format("Adding DMaaP message to pool queue [%s]", requestIdWithSubId)); + try { + executor.execute(new WorkerImpl(incoming, dmaap, providerOperations)); + } catch (RejectedExecutionException rejectEx) { + LOG.error("Task Rejected: ", rejectEx); + } + } else { + // Badly formed message + LOG.error("Message was not valid. Rejecting message: " + incoming); + } + } else { + if (isValid(incoming)) { + LOG.info("Run stopped. Orphaning Message: " + requestIdWithSubId); + } else { + // Badly formed message + LOG.error("Message was not valid. Rejecting message: " + incoming); + } + } + } + } + } catch (Exception e) { + LOG.error("Exception " + e.getClass().getSimpleName() + " caught in DMaaP listener"); + LOG.error(EELFResourceManager.format(e)); + LOG.error("DMaaP Listener logging and ignoring the exception, continue..."); + } + } + + LOG.info("Stopping DMaaP Listener thread"); + + // We've told the listener to stop + // TODO - Should we: + // 1) Put a message back on the queue indicating that APP-C never got to + // the message + // or + // 2) Let downstream figure it out after timeout between PENDING and + // ACTIVE messages + } + + private boolean isValid(DmaapIncomingMessage incoming) { + return ((incoming != null) && + incoming.getBody() != null + && !StringUtils.isEmpty(incoming.getRpcName())); + } + + @Override + public String getBenchmark() { + long time = System.currentTimeMillis(); + DateFormat df = new SimpleDateFormat("HH:mm:ss"); + df.setTimeZone(TimeZone.getTimeZone("UTC")); + String runningTime = df.format(new Date(time - startTime)); + + String out = String.format("Running for %s and completed %d jobs using %d threads.", runningTime, + executor.getCompletedTaskCount(), executor.getPoolSize()); + LOG.info("***BENCHMARK*** " + out); + return out; + } + + private String getRequestIdWithSubId(JsonNode event) { + String requestId = ""; + try { + requestId = Converter.extractRequestIdWithSubId(event); + } catch (Exception e) { + LOG.error("failed to parse request-id and sub-request-id. Json not in expected format", e); + } + return requestId; + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/impl/WorkerImpl.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/impl/WorkerImpl.java new file mode 100644 index 000000000..870871da3 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/impl/WorkerImpl.java @@ -0,0 +1,136 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.impl; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import org.onap.appc.exceptions.APPCException; +import org.onap.appc.listener.EventHandler; +import org.onap.appc.listener.LCM.conv.Converter; +import org.onap.appc.listener.LCM.model.DmaapMessage; +import org.onap.appc.listener.LCM.model.DmaapOutgoingMessage; +import org.onap.appc.listener.LCM.operation.ProviderOperations; + +public class WorkerImpl implements Runnable { + + private final EELFLogger LOG = EELFManager.getInstance().getLogger(WorkerImpl.class); + + // Should have all of the data we need for processing + private DmaapMessage event; + + // So we can post messages from inside the worker. + private EventHandler dmaap; + + //so we know were to post the messages + private final ProviderOperations providerOperations; + + + public WorkerImpl(DmaapMessage message, EventHandler dmaap, ProviderOperations providerOperations) { + this.event = message; + this.dmaap = dmaap; + this.providerOperations = providerOperations; + } + + @Override + public void run() { + + if (checkParametersForNull(event, dmaap, providerOperations)) { + throw new IllegalStateException("Cannot run worker. One of its parameters is null"); + } + + String requestIdWithSubId = extractRequestIdWithSubId(event.getBody()); + LOG.debug(String.format("Started working on %s", requestIdWithSubId)); + + // Run the dg in a try catch to handle all exceptions and update the message at the end + try { + + JsonNode outputJsonNode = doDG(event.getRpcName(), event.getBody()); + DmaapOutgoingMessage dmaapOutgoingMessage = Converter + .convertJsonNodeToDmaapOutgoingMessage(event, outputJsonNode); + postMessageToDMaaP(dmaapOutgoingMessage, requestIdWithSubId); + Integer statusCode = extractStatusCode(dmaapOutgoingMessage.getBody()); + if (ProviderOperations.isSucceeded(statusCode)) { + LOG.debug(String.format("Event %s finished successfully", requestIdWithSubId)); + } else { + LOG.warn(String.format("Event %s failed", requestIdWithSubId)); + } + + } catch (Exception e) { + // Unknown exception from DG method. Fail and pass the exception along + String msg = "Exception: " + e.getMessage(); + LOG.error(String.format("Event %s finished with failure. %s", requestIdWithSubId, msg)); + DmaapOutgoingMessage dmaapOutgoingMessage = Converter + .buildDmaapOutgoingMessageWithUnexpectedError(event, e); + postMessageToDMaaP(dmaapOutgoingMessage, requestIdWithSubId); + } + + LOG.debug("Done working on " + requestIdWithSubId); + } + + private boolean checkParametersForNull(DmaapMessage message, EventHandler dmaap, + ProviderOperations providerOperations) { + + return message == null || dmaap == null || providerOperations == null; + } + + private Integer extractStatusCode(JsonNode event) { + Integer statusCode = null; + try { + statusCode = Converter.extractStatusCode(event); + } catch (Exception e) { + LOG.error("failed to parse statusCode. Json not in expected format", e); + } + return statusCode; + } + + + private String extractRequestIdWithSubId(JsonNode event) { + String requestId = ""; + try { + requestId = Converter.extractRequestIdWithSubId(event); + } catch (Exception e) { + LOG.error("failed to parse request-id and sub-request-id. Json not in expected format", e); + } + return requestId; + } + + + private void postMessageToDMaaP(DmaapOutgoingMessage dmaapOutgoingMessage, String requestIdWithSubId) { + String dmaapOutgoingMessageJsonString; + try { + dmaapOutgoingMessageJsonString = Converter.convertDmaapOutgoingMessageToJsonString(dmaapOutgoingMessage); + dmaap.postStatus(dmaapOutgoingMessage.getCambriaPartition(), dmaapOutgoingMessageJsonString); + } catch (JsonProcessingException e) { + LOG.error( + "failed to postMessageToDMaaP requestIdWithSubId: " + requestIdWithSubId + " dmaapOutgoingMessage: " + + dmaapOutgoingMessage, e); + } + } + + private JsonNode doDG(String rpcName, JsonNode msg) throws APPCException { + return providerOperations.topologyDG(rpcName, msg); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/ActionIdentifiers.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/ActionIdentifiers.java new file mode 100644 index 000000000..a7a2795d4 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/ActionIdentifiers.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.io.Serializable; + + +public class ActionIdentifiers implements Serializable { + + @JsonProperty("service-instance-id") + private String serviceInstanceId; + @JsonProperty("vnf-id") + private String vnfID; + @JsonProperty("vnfc-name") + private String vnfcName; + @JsonProperty("vserver-id") + private String vserverId; + + public ActionIdentifiers() { + } + + public ActionIdentifiers(ActionIdentifiers actionIdentifiers) { + this.serviceInstanceId=actionIdentifiers.getServiceInstanceId(); + this.vnfID=actionIdentifiers.getVnfID(); + this.vnfcName=actionIdentifiers.getVnfcName(); + this.vserverId=actionIdentifiers.getVserverId(); + } + + public String getServiceInstanceId() { + return serviceInstanceId; + } + + public void setServiceInstanceId(String serviceInstanceId) { + this.serviceInstanceId = serviceInstanceId; + } + + public String getVnfID() { + return vnfID; + } + + public void setVnfID(String vnfID) { + this.vnfID = vnfID; + } + + public String getVnfcName() { + return vnfcName; + } + + public void setVnfcName(String vnfcName) { + this.vnfcName = vnfcName; + } + + public String getVserverId() { + return vserverId; + } + + public void setVserverId(String vserverId) { + this.vserverId = vserverId; + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/CommonHeader.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/CommonHeader.java new file mode 100644 index 000000000..b7933184c --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/CommonHeader.java @@ -0,0 +1,116 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Modification Copyright (C) 2019 IBM + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.io.Serializable; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Map; + +import org.onap.appc.util.Time; + +public class CommonHeader implements Serializable { + @JsonProperty("timestamp") + private String timeStamp; + @JsonProperty("api-ver") + private String apiVer; + @JsonProperty("originator-id") + private String originatorId; + @JsonProperty("request-id") + private String requestID; + @JsonProperty("sub-request-id") + private String subRequestId; + @JsonProperty("flags") + private Map<String, String> flags; + + private final DateFormat ZULU_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SS'Z'"); + + public CommonHeader() { + } + + public CommonHeader(CommonHeader commonHeader) { + // changed to current system time + timeStamp = ZULU_FORMATTER.format(Time.utcDate()); + + apiVer = commonHeader.getApiVer(); + originatorId = commonHeader.getOriginatorId(); + requestID = commonHeader.getRequestID(); + subRequestId = commonHeader.getSubRequestId(); + flags = commonHeader.getFlags(); + } + + + + public String getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(String timeStamp) { + this.timeStamp = timeStamp; + } + + public String getApiVer() { + return apiVer; + } + + public void setApiVer(String apiVer) { + this.apiVer = apiVer; + } + + public String getRequestID() { + return requestID; + } + + public void setRequestID(String requestID) { + this.requestID = requestID; + } + + public String getOriginatorId() { + return originatorId; + } + + public void setOriginatorId(String originatorId) { + this.originatorId = originatorId; + } + + public String getSubRequestId() { + return subRequestId; + } + + public void setSubRequestId(String subRequestId) { + this.subRequestId = subRequestId; + } + + public Map<String, String> getFlags() { + return flags; + } + + public void setFlags(Map<String, String> flags) { + this.flags = flags; + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/DmaapIncomingMessage.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/DmaapIncomingMessage.java new file mode 100644 index 000000000..3607fd719 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/DmaapIncomingMessage.java @@ -0,0 +1,52 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.json.JSONObject; +import org.onap.appc.listener.util.Mapper; + +/** + * This class represents a message being sent out to DMaaP by APPC to update listeners on the status of a request + * + */ +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class DmaapIncomingMessage extends DmaapMessage{ + private final static String defaultCambriaPartition = "APP-C"; + + public DmaapIncomingMessage() { + super(); + setCambriaPartition(defaultCambriaPartition); + } + + + @Override + public String toString() { + return "DmaapIncomingMessage{"+super.toString()+"}"; + } +} + diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/DmaapMessage.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/DmaapMessage.java new file mode 100644 index 000000000..8703b0d75 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/DmaapMessage.java @@ -0,0 +1,116 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + + +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class DmaapMessage { + + @JsonProperty("version") + private String version; + + @JsonProperty("type") + private String type; + + @JsonProperty("correlation-id") + private String correlationID; + + @JsonProperty("cambria.partition") + private String cambriaPartition; + + @JsonProperty("rpc-name") + private String rpcName; + + @JsonProperty("body") + private JsonNode body; + + public String getVersion() { + return version; + } + + + public String getType() { + return type; + } + + public String getCorrelationID() { + return correlationID; + } + + public String getCambriaPartition() { + return cambriaPartition; + } + + public String getRpcName() { + return rpcName; + } + + public JsonNode getBody() { + return body; + } + + + public void setVersion(String version) { + this.version = version; + } + + public void setType(String type) { + this.type = type; + } + + public void setCorrelationID(String correlationID) { + this.correlationID = correlationID; + } + + public void setCambriaPartition(String cambriaPartition) { + this.cambriaPartition = cambriaPartition; + } + + public void setRpcName(String rpcName) { + this.rpcName = rpcName; + } + + public void setBody(JsonNode body) { + this.body = body; + } + + @Override + public String toString() { + return "DmaapMessage{" + + "version='" + version + '\'' + + ", type='" + type + '\'' + + ", correlationId='" + correlationID + '\'' + + ", cambriaPartition='" + cambriaPartition + '\'' + + ", rpcName='" + rpcName + '\'' + + ", body=" + body + + '}'; + } +} + diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/DmaapOutgoingMessage.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/DmaapOutgoingMessage.java new file mode 100644 index 000000000..b24043971 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/DmaapOutgoingMessage.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.json.JSONObject; +import org.onap.appc.listener.util.Mapper; + +/** + * This class represents a message being sent out to DMaaP by APPC to update listeners on the status of a request + * + */ +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class DmaapOutgoingMessage extends DmaapMessage{ + private final static String defaultCambriaPartition = "MSO"; + + public DmaapOutgoingMessage() { + super(); + setCambriaPartition(defaultCambriaPartition); + } + + + @Override + public String toString() { + return "DmaapOutgoingMessage{"+super.toString()+"}"; + } +} + diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/InputBody.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/InputBody.java new file mode 100644 index 000000000..0c70d643c --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/InputBody.java @@ -0,0 +1,89 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class InputBody { + + @JsonProperty("common-header") + private CommonHeader commonHeader; + + @JsonProperty("action-identifiers") + private ActionIdentifiers actionIdentifiers; + + @JsonProperty("action") + private String action; + + @JsonProperty("payload") + private Object payload; + + + public Object getPayload() { + return payload; + } + + public String getAction() { + return action; + } + + public ActionIdentifiers getActionIdentifiers() { + return actionIdentifiers; + } + + public CommonHeader getCommonHeader() { + return commonHeader; + } + + @JsonIgnore + public void setPayloadAsString(String payload) { + this.payload = payload; + } + + public void setPayload(Object payload) { + this.payload = payload; + } + + public void setAction(String action) { + this.action = action; + } + + public void setActionIdentifiers(ActionIdentifiers actionIdentifiers) { + this.actionIdentifiers = actionIdentifiers; + } + + public void setCommonHeader(CommonHeader commonHeader) { + this.commonHeader = commonHeader; + } + + @JsonIgnore + public boolean isValid() { + return getCommonHeader() != null; + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/OutputBody.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/OutputBody.java new file mode 100644 index 000000000..a42174dc2 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/OutputBody.java @@ -0,0 +1,100 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.json.JSONObject; +import org.onap.appc.listener.util.Mapper; + +/** + * This class represents a message being sent out to DMaaP by APPC to update listeners on the status of a request + */ +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class OutputBody { + + @JsonProperty("common-header") + private CommonHeader header; + + @JsonProperty("status") + private ResponseStatus status; + + @JsonProperty("payload") + private String payload; + + @JsonProperty("locked") + private String locked; + + public OutputBody() { + } + + public OutputBody(InputBody msg) { + this.header = new CommonHeader(msg.getCommonHeader()); + } + + + public JSONObject toResponse() { + return Mapper.toJsonObject(this); + } + + public String getLocked() { + return locked; + } + + public String getPayload() { + return payload; + } + + public CommonHeader getHeader() { + return header; + } + + public ResponseStatus getStatus() { + return status; + } + + public void setStatus(ResponseStatus status) { + this.status = status; + } + + public void setLocked(String locked) { + this.locked = locked; + } + + public void setHeader(CommonHeader header) { + this.header = header; + } + + public void setPayload(String payload) { + this.payload = payload; + } + + @Override + public String toString() { + return String.format("%s - %s(%s)", getHeader().getRequestID(), getStatus().getCode(), getStatus().getValue()); + } +} + diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/ResponseStatus.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/ResponseStatus.java new file mode 100644 index 000000000..6562bf9db --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/model/ResponseStatus.java @@ -0,0 +1,72 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + + +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class ResponseStatus { + + @JsonProperty("code") + private Integer code; + @JsonProperty("message") + private String value; + + public ResponseStatus() { + } + + public ResponseStatus(Integer code, String value) { + this.code = code; + this.value = value; + } + + public Integer getCode() { + return code; + } + + + public String getValue() { + return value; + } + + public void setCode(Integer code) { + this.code = code; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() { + return "ResponseStatus{" + + "code=" + code + + ", value='" + value + '\'' + + '}'; + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/operation/GenericProviderOperationRequestFormatter.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/operation/GenericProviderOperationRequestFormatter.java new file mode 100644 index 000000000..ca0f52ac7 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/operation/GenericProviderOperationRequestFormatter.java @@ -0,0 +1,85 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ================================================================================ + * Modifications Copyright (C) 2019 Ericsson + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.operation; + +import com.fasterxml.jackson.databind.JsonNode; +import org.json.JSONObject; +import org.onap.appc.exceptions.APPCException; +import org.onap.appc.listener.LCM.model.InputBody; +import org.onap.appc.listener.LCM.model.ResponseStatus; +import org.onap.appc.listener.util.Mapper; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import java.net.URL; + +public class GenericProviderOperationRequestFormatter implements ProviderOperationRequestFormatter { + + private final EELFLogger LOG = EELFManager.getInstance().getLogger(GenericProviderOperationRequestFormatter.class); + + //@formatter:off + @SuppressWarnings("nls") + private final static String TEMPLATE = "{\"input\": %s}"; + //@formatter:on + + @Override + public String buildPath(URL url, String rpcName) { + return url.getPath() + ":" + rpcName; + } + + @Override + public String buildRequest(InputBody msg) { + JSONObject jsonObject = Mapper.toJsonObject(msg); + return String.format(TEMPLATE, jsonObject.toString()); + } + + @Override + public ResponseStatus getResponseStatus(JsonNode responseBody)throws APPCException{ + try { + JsonNode status = responseBody.get("output").get("status"); + return new ResponseStatus(status.get("code").asInt(), status.get("message").asText()); + } catch (Exception e) { + LOG.error("Unknown error processing failed response from provider. Json not in expected format", e); + throw new APPCException("APPC has an unknown RPC error"); + } + } + + @Override + public String getLocked(JSONObject responseBody) throws APPCException { + try { + JSONObject outputObject=responseBody.getJSONObject("output"); + if(outputObject.has("locked")){ + return outputObject.getString("locked"); + }else{ + return null; + } + } catch (Exception e) { + LOG.error("Unknown error processing failed response from provider. Json not in expected format", e); + throw new APPCException("APPC has an unknown RPC error"); + } + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/operation/ProviderOperationRequestFormatter.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/operation/ProviderOperationRequestFormatter.java new file mode 100644 index 000000000..e8a6ecbeb --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/operation/ProviderOperationRequestFormatter.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.operation; + +import com.fasterxml.jackson.databind.JsonNode; +import org.json.JSONObject; +import org.onap.appc.exceptions.APPCException; +import org.onap.appc.listener.LCM.model.InputBody; +import org.onap.appc.listener.LCM.model.ResponseStatus; + +import java.net.URL; + + +public interface ProviderOperationRequestFormatter { + + String buildPath(URL url, String rpcName); + + String buildRequest(InputBody msg); + + ResponseStatus getResponseStatus(JsonNode json)throws APPCException; + + String getLocked(JSONObject json)throws APPCException; +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/operation/ProviderOperations.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/operation/ProviderOperations.java new file mode 100644 index 000000000..42206ec2e --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/LCM/operation/ProviderOperations.java @@ -0,0 +1,281 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ================================================================================ + * Modifications Copyright (C) 2019 Ericsson + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.operation; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.fasterxml.jackson.databind.JsonNode; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.Socket; +import java.net.URL; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpHeaders; +import org.apache.http.HttpResponse; +import org.apache.http.HttpVersion; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.scheme.PlainSocketFactory; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.HttpParams; +import org.apache.http.params.HttpProtocolParams; +import org.apache.http.protocol.HTTP; +import org.onap.appc.exceptions.APPCException; +import org.onap.appc.listener.LCM.model.ResponseStatus; +import org.onap.appc.listener.util.Mapper; + +public class ProviderOperations { + + private final EELFLogger LOG = EELFManager.getInstance().getLogger(ProviderOperations.class); + + private URL url; + private String basicAuth; + + private static ProviderOperationRequestFormatter requestFormatter = new GenericProviderOperationRequestFormatter(); + + + public ProviderOperations(String url, String username, String password){ + setAuthentication(username, password); + try { + this.url = new URL(url); + } catch (MalformedURLException e) { + LOG.error("An error occurred while building url", e); + } + } + + /** + * Calls the AppcProvider to run a topology directed graph + * + * @param message The incoming message to be run + * @return True if the result is success. Never returns false and throws an exception instead. + * @throws UnsupportedEncodingException + * @throws Exception if there was a failure processing the request. The exception message is the failure reason. + */ + @SuppressWarnings("nls") + public JsonNode topologyDG(String rpcName, JsonNode message) throws APPCException { + if (message == null) { + throw new APPCException("Provided message was null"); + } + + HttpPost postRequest = buildPostRequest(rpcName, message); + return getJsonNode(message, postRequest); + } + + private HttpPost buildPostRequest(String rpcName, JsonNode message) throws APPCException { + HttpPost post; + try { + + // Concatenate the "action" on the end of the URL + String path = requestFormatter.buildPath(url, rpcName); + URL serviceUrl = new URL(url.getProtocol(), url.getHost(), url.getPort(), path); + + post = new HttpPost(serviceUrl.toExternalForm()); + post.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); + post.setHeader(HttpHeaders.ACCEPT, "application/json"); + + // Set Auth + if (basicAuth != null) { + post.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + basicAuth); + } + + String body = Mapper.toJsonString(message); + StringEntity entity = new StringEntity(body); + entity.setContentType("application/json"); + post.setEntity(entity); + } catch (UnsupportedEncodingException | MalformedURLException e) { + throw new APPCException(e); + } + return post; + } + + private JsonNode getJsonNode(JsonNode message, HttpPost post) throws APPCException { + HttpClient client = getHttpClient(); + + int httpCode; + String respBody; + try { + HttpResponse response = client.execute(post); + httpCode = response.getStatusLine().getStatusCode(); + respBody = IOUtils.toString(response.getEntity().getContent()); + } catch (IOException e) { + throw new APPCException(e); + } + + if (httpCode >= 200 && httpCode < 300 && respBody != null) { + JsonNode json; + try { + json = Mapper.toJsonNodeFromJsonString(respBody); + } catch (Exception e) { + LOG.error("Error processing response from provider. Could not map response to json", e); + throw new APPCException("APPC has an unknown RPC error"); + } + ResponseStatus responseStatus = requestFormatter.getResponseStatus(json); + if (!isSucceeded(responseStatus.getCode())) { + LOG.warn(String.format("Operation failed [%s]", message.toString())); + } + return json; + } + throw new APPCException(String.format("Unexpected response from endpoint: [%d] - %s ", httpCode, respBody)); + } + + /** + * Updates the static var URL and returns the value; + * + * @return The new value of URL + */ + public String getUrl() { + return url.toExternalForm(); + } + + public void setUrl(String newUrl) { + try { + url = new URL(newUrl); + } catch (MalformedURLException e) { + LOG.error("An error occurred while building url", e); + } + } + + /** + * Sets the basic authentication header for the given user and password. If either entry is null then set basic auth + * to null + * + * @param user The user with optional domain name + * @param password The password for the user + * @return The new value of the basic auth string that will be used in the request headers + */ + public String setAuthentication(String user, String password) { + if (user != null && password != null) { + String authStr = user + ":" + password; + basicAuth = new String(Base64.encodeBase64(authStr.getBytes())); + } else { + basicAuth = null; + } + return basicAuth; + } + + @SuppressWarnings("deprecation") + protected HttpClient getHttpClient() throws APPCException { + HttpClient client; + switch (url.getProtocol()) { + case "https": + try { + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + MySSLSocketFactory sf = new MySSLSocketFactory(trustStore); + sf.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + + HttpParams params = new BasicHttpParams(); + HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); + HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); + + SchemeRegistry registry = new SchemeRegistry(); + registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); + registry.register(new Scheme("https", sf, 443)); + registry.register(new Scheme("https", sf, 8443)); + registry.register(new Scheme("http", sf, 8181)); + + ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); + client = new DefaultHttpClient(ccm, params); + } catch (Exception e) { + LOG.error("Error getting HTTP Client", e); + client = new DefaultHttpClient(); + } + break; + case "http": + client = new DefaultHttpClient(); + break; + default: + throw new APPCException( + "The provider.topology.url property is invalid. The url did not start with http[s]"); + } + return client; + } + + @SuppressWarnings("deprecation") + public static class MySSLSocketFactory extends SSLSocketFactory { + private SSLContext sslContext = SSLContext.getInstance("TLS"); + + public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, + KeyStoreException, UnrecoverableKeyException { + super(truststore); + + TrustManager tm = new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + }; + + sslContext.init(null, new TrustManager[]{ + tm + }, null); + } + + @Override + public Socket createSocket(Socket socket, String host, int port, boolean autoClose) + throws IOException { + return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); + } + + @Override + public Socket createSocket() throws IOException { + return sslContext.getSocketFactory().createSocket(); + } + } + + public static boolean isSucceeded(Integer code) { + + //FIXME is it working as intended? + return code != null && ((code == 100) || (code == 400)); + } +}
\ No newline at end of file diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/Listener.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/Listener.java new file mode 100644 index 000000000..f4b87bd25 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/Listener.java @@ -0,0 +1,74 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener; + +/** + * This interface defines a listener that subscribes to a DMaaP topic and continually polls for messages. The + * listener does all operations in the run() method and long running operations should be created in a separate worker + * thread. + * + */ +public interface Listener extends Runnable { + + /** + * Should start a continuous poll to get messages from the message bus only ending when stop() or stopNow() are + * called. + * + * @see java.lang.Runnable#run() + */ + @Override + public void run(); + + /** + * Signals the listener to stop accepting new messages to the queue and to cleanly finish processing all remaining + * messages in the queue. This can take a significant amount of time to complete depending on the thread pool + * characteristics. Similar to {@link #stopNow()} + */ + public void stop(); + + /** + * Signals the listener to stop accepting new messages to the queue and to destroy all remaining messages in the + * queue. This will complete quicker than {@link #stop()} at the cost of discarded requests. Recovery of these + * requests would have to be caught downstream. Similar to {@link #stop()} + */ + public void stopNow(); + + /** + * @return A string that shows various benchmarking data. Can be used by humans to tune the thread pool. + */ + public String getBenchmark(); + + /** + * @return The listener's id when requesting messages from DMaaP. Also known as the group id. + */ + public String getListenerId(); + + /** + * Sets the listener's id to use when requesting messages from DMaaP. Also known as the group id. + * + * @param idString + * The new listener id + */ + public void setListenerId(String idString); +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/ListenerProperties.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/ListenerProperties.java new file mode 100644 index 000000000..74ead9485 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/ListenerProperties.java @@ -0,0 +1,305 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener; + +import java.util.Properties; + +/** + * A class for instantiating Listener objects. It is primarily used to hold properties that start with the given prefix. + * It also holds a class that implements {@see Listener} and will be used by the controller to spawn a new listener + * object. + * + * @since Apr 25, 2016 + * @version $Id$ + */ +public class ListenerProperties { + + private String prefix; + + private Class<? extends Listener> listenerClass; + + private Properties props; + + /** + * Creates a new listener object with the given prefix and properties. Any property starting with the prefix is + * added to the internal properties object with the prefix removed. All other properties are ignored. + * ListenerProperties constructor + * + * @param prefix + * The prefix of the properties to load + * @param allProps + * The properties object to load from. + */ + public ListenerProperties(String prefix, Properties allProps) { + this.prefix = prefix; + props = new Properties(); + + String dottedPrefix = String.format("%s.", prefix); + for (String key : allProps.stringPropertyNames()) { + if (key.startsWith(dottedPrefix) && key.length() > dottedPrefix.length()) { + props.put(key.substring(dottedPrefix.length()), allProps.get(key)); + } + } + } + + /** + * @return The prefix of these properties + */ + public String getPrefix() { + return prefix; + } + + /** + * Sets the listener class. Will be used by {@see Controller} to instantiate the Listener thread for this object + * + * @param cls + * The class to be created. Implements {@see Listener} + */ + public void setListenerClass(Class<? extends Listener> cls) { + this.listenerClass = cls; + } + + /** + * @return The class that will be used by {@see Controller} to instantiate the Listener thread for this object + */ + public Class<? extends Listener> getListenerClass() { + return listenerClass; + } + + /** + * Returns a property matching a given KEYS + * + * @param key + * The KEYS object who's value to return. + * @return The value of the property or null if none exists + */ + public String getProperty(KEYS key) { + return getProperty(key, null); + } + + /** + * Returns a property matching a given string. + * + * @param key + * The key who's value to return. + * @return The value of the property or null if none exists + */ + public String getProperty(String key) { + return getProperty(key, null); + } + + /** + * Returns a property matching a given KEYS + * + * @param key + * The KEYS object who's value to return. + * @param defaultValue + * The value to return if the property is not found + * @return The value of the property or null if none exists + */ + public String getProperty(KEYS key, String defaultValue) { + return getProperty(key.getPropertySuffix(), defaultValue); + } + + /** + * Returns a property matching a given string. + * + * @param key + * The key who's value to return. + * @param defaultValue + * The value to return if the property is not found + * @return The value of the property or null if none exists + */ + public String getProperty(String key, String defaultValue) { + return props.getProperty(key, defaultValue); + } + + /** + * @return The properties object containing all properties + */ + public Properties getProperties() { + return props; + } + + /** + * Reads the <i>prefix</i>.disabled property to determine if the listener is disabled and should not be run by the + * controller. Defaults to false if property not set or value cannot be parsed. + * + * @return true if the listener is disabled and should not be started. false if the listener should be start + * normally (default). + */ + public boolean isDisabled() { + return Boolean.valueOf(getProperty(KEYS.DISABLED, "false")); + } + + @Override + public String toString() { + return String.format("%s", prefix); + } + + + /** + * Set of common properties that will be used by most systems. Primarily relating to DMaaP and ThreadPools + * + * @since Apr 25, 2016 + * @version $Id$ + */ + public enum KEYS { + /** + * Property to determine if the listener should be disabled. If not set, defaults to false + */ + DISABLED("disabled"), + + /** + * Property for the message service type. Should be a lower case string. See MessageService. + */ + MESSAGE_SERVICE("service"), + + /** + * A hostname or comma separated list (no spaces) of hostnames of servers in a cluster. Can have ports included + * as well.<br> + * Examples: + * <ul> + * <li>server1.appc.onap.org</li> + * <li>server1.appc.onap.org:3904</li> + * <li>server1.appc.onap.org,server2.appc.onap.org</li> + * </ul> + */ + HOSTS("poolMembers"), + + /** + * The topic that will be used for DMaaP read operations. Can only support a single topic. + */ + TOPIC_READ("topic.read"), + + /** + * The topic or topics that will be used to write to. If multiple topics are provided, should be in a comma + * seperated list with no spaces.<br> + * Examples: + * <ul> + * <li>TOPIC-1</li> + * <li>TOPIC-1,TOPIC-2,ANOTHER-TOPIC</li> + * </ul> + */ + TOPIC_WRITE("topic.write"), + + /** + * The highland park filter to use on read requests. If you are reading and writing to the same topic this must + * be provided. Filter should be in JSON format (not url escaped). + */ + TOPIC_READ_FILTER("topic.read.filter"), + + /** + * The amount of time in seconds that the DMaaP polling connection should stay open for. Recommended to be set + * high (around 60 seconds) as most clients will return immediately and not wait until the timeout is up to + * return if they have data. + */ + TOPIC_READ_TIMEOUT("topic.read.timeout"), + + /** + * Blacklist time for a server with response problem in seconds + */ + + PROBLEM_WITH_RESPONSE_BLACKLIST_TIME("topic.responseProblem.blacklistTime"), + /** + * Blacklist time for a server with server problem in seconds + */ + + PROBLEM_SERVERSIDE_ERROR_BLACKLIST_TIME("topic.serverError.blacklistTime"), + /** + * Blacklist time for a server with DNS problem in seconds + */ + + PROBLEM_DNS_BLACKLIST_TIME("topic.dnsIssue.blacklistTime"), + /** + * Blacklist time for a server with IO Exception problem in seconds + */ + + PROBLEM_IO_EXCEPTION_BLACKLIST_TIME("topic.ioException.blacklistTime"), + + /** + * The name of the client to use. Should be unique to the application. + */ + CLIENT_NAME("client.name"), + + /** + * The id of the client to use. Should be unique for each instance of the application in an environment. + */ + CLIENT_ID("client.name.id"), + + /** + * The User (DMaaP) to use for authentication. If a user is provided, you must include the + * domain name (e.g. example<b>@example.com</b>). + */ + AUTH_USER_KEY("client.key"), + + /** + * The password (DMaaP) to use for authentication. + */ + AUTH_SECRET_KEY("client.secret"), + + /** + * The minimum amount of size of the queue. A client should request new messages once the queue has dropped + * below this size. + */ + THREADS_MIN_QUEUE("threads.queuesize.min"), + + /** + * The maximum size of the queue. A client will request no new messages once this maximum size has been reached. + */ + THREADS_MAX_QUEUE("threads.queuesize.max"), + + /** + * The minimum size of the worker threads pool. This is the pool each listener will use to launch longer running + * operations. + */ + THREADS_MIN_POOL("threads.poolsize.min"), + + /** + * The maximum size of the worker threads pool. This is the pool each listener will use to launch longer running + * operations. + */ + THREADS_MAX_POOL("threads.poolsize.max"); + + private String suffix; + + private KEYS(String val) { + this.suffix = val; + } + + /** + * @param prefix + * The prefix to prepend + * @return a fully property name that corroponds to what is used in the properties file. Format is PREFIX.KEY + */ + public String getFullProp(String prefix) { + return String.format("%s.%s", prefix, suffix); + } + + public String getPropertySuffix() { + return suffix; + } + } + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/impl/ListenerImpl.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/impl/ListenerImpl.java new file mode 100644 index 000000000..d6909abf3 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/impl/ListenerImpl.java @@ -0,0 +1,131 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.impl; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; +import java.util.concurrent.RejectedExecutionException; + +import org.onap.appc.listener.AbstractListener; +import org.onap.appc.listener.ListenerProperties; +import org.onap.appc.listener.demo.model.IncomingMessage; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.att.eelf.i18n.EELFResourceManager; + +public class ListenerImpl extends AbstractListener { + + private final EELFLogger LOG = EELFManager.getInstance().getLogger(ListenerImpl.class); + + private long startTime = 0; + + public ListenerImpl(ListenerProperties props) { + super(props); + String url = props.getProperty("provider.url"); + LOG.info("DMaaP Provider Endpoint: " + url); + ProviderOperations.setUrl(url); + + // Set Basic Auth + String user = props.getProperty("provider.user"); + String pass = props.getProperty("provider.pass"); + ProviderOperations.setAuthentication(user, pass); + } + + @Override + public void run() { + // Some vars for benchmarking + startTime = System.currentTimeMillis(); + + LOG.info("Running DMaaP Listener"); + + while (run.get()) { + // Only update if the queue is low. otherwise we read in more + // messages than we need + try { + if (executor.getQueue().size() <= QUEUED_MIN) { + LOG.debug("DMaaP queue running low. Querying for more jobs"); + List<IncomingMessage> messages = dmaap.getIncomingEvents(IncomingMessage.class, QUEUED_MAX); + LOG.debug(String.format("Read %d messages from dmaap", messages.size())); + for (IncomingMessage incoming : messages) { + // Acknowledge that we read the event + LOG.info("Acknowledging Message: " + incoming.getHeader().getRequestID()); + + //TODO: Should we post a pending status for 1607 + //dmaap.postStatus(incoming.toOutgoing(Status.PENDING, null).toString()); + } + for (IncomingMessage incoming : messages) { + // Add to pool if still running + if (run.get()) { + LOG.info(String.format("Adding DMaaP message to pool queue [%s]", incoming.getHeader().getRequestID())); + if (incoming.isValid()) { + try { + executor.execute(new WorkerImpl(incoming, dmaap)); + } catch (RejectedExecutionException rejectEx) { + LOG.error("Task Rejected: ", rejectEx); + } + } else { + // Badly formed message + LOG.error("Message was not valid. Rejecting"); + } + } else { + LOG.info("Run stopped. Orphaning Message: " + incoming.getHeader().getRequestID()); + } + } + } + } catch (Exception e) { + LOG.error("Exception " + e.getClass().getSimpleName() + " caught in DMaaP listener"); + LOG.error(EELFResourceManager.format(e)); + LOG.error("DMaaP Listener logging and ignoring the exception, continue..."); + } + } + + LOG.info("Stopping DMaaP Listener thread"); + + // We've told the listener to stop + // TODO - Should we: + // 1) Put a message back on the queue indicating that APP-C never got to + // the message + // or + // 2) Let downstream figure it out after timeout between PENDING and + // ACTIVE messages + } + + @Override + public String getBenchmark() { + long time = System.currentTimeMillis(); + DateFormat df = new SimpleDateFormat("HH:mm:ss"); + df.setTimeZone(TimeZone.getTimeZone("UTC")); + String runningTime = df.format(new Date(time - startTime)); + + String out = String.format("Running for %s and completed %d jobs using %d threads.", runningTime, + executor.getCompletedTaskCount(), executor.getPoolSize()); + LOG.info("***BENCHMARK*** " + out); + return out; + } + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/impl/ProviderOperations.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/impl/ProviderOperations.java new file mode 100644 index 000000000..6cd2f2d76 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/impl/ProviderOperations.java @@ -0,0 +1,195 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Modifications Copyright (C) 2019 Ericsson + * Modifications Copyright (C) 2019 IBM + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.impl; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.json.JSONObject; +import org.onap.appc.exceptions.APPCException; +import org.onap.appc.listener.demo.model.IncomingMessage; +import org.onap.appc.listener.util.HttpClientUtil; +import org.onap.appc.listener.util.Mapper; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +public class ProviderOperations { + + private static final EELFLogger LOG = EELFManager.getInstance().getLogger(ProviderOperations.class); + + private static URL url; + + private static String basic_auth; + + //@formatter:off + @SuppressWarnings("nls") + private final static String TEMPLATE = "{\"input\": {\"common-request-header\": {\"service-request-id\": \"%s\"},\"config-payload\": {\"config-url\": \"%s\",\"config-json\":\"%s\"}}}"; + //@formatter:on + + /** + * Calls the AppcProvider to run a topology directed graph + * + * @param msg + * The incoming message to be run + * @return True if the result is success. Never returns false and throws an exception instead. + * @throws UnsupportedEncodingException + * @throws Exception + * if there was a failure processing the request. The exception message is the failure reason. + */ + @SuppressWarnings("nls") + public static boolean topologyDG(IncomingMessage msg) throws APPCException { + if (msg == null) { + throw new APPCException("Provided message was null"); + } + + HttpPost post = null; + try { + // Concatenate the "action" on the end of the URL + String path = url.getPath() + ":" + msg.getAction().getValue(); + URL serviceUrl = new URL(url.getProtocol(), url.getHost(), url.getPort(), path); + + post = new HttpPost(serviceUrl.toExternalForm()); + post.setHeader("Content-Type", "application/json"); + post.setHeader("Accept", "application/json"); + + // Set Auth + if (basic_auth != null) { + post.setHeader("Authorization", "Basic " + basic_auth); + } + + //String body = buildReqest(msg.getId(), msg.getUrl(), msg.getIdentityUrl()); + String body = buildReqest(msg.getHeader().getRequestID(), msg.getPayload().getGenericVnfId(), msg.getPayload().getStreams()); + StringEntity entity = new StringEntity(body); + entity.setContentType("application/json"); + post.setEntity(new StringEntity(body)); + } catch (UnsupportedEncodingException | MalformedURLException e) { + throw new APPCException(e); + } + + HttpClient client = HttpClientUtil.getHttpClient(url.getProtocol()); + + int httpCode = 0; + String respBody = null; + try { + HttpResponse response = client.execute(post); + httpCode = response.getStatusLine().getStatusCode(); + respBody = IOUtils.toString(response.getEntity().getContent()); + } catch (IOException e) { + throw new APPCException(e); + } + + if (httpCode == 200 && respBody != null) { + JSONObject json; + try { + json = Mapper.toJsonObject(respBody); + } catch (Exception e) { + LOG.error("Error prcoessing response from provider. Could not map response to json", e); + throw new APPCException("APPC has an unknown RPC error"); + } + boolean success; + String reason; + try { + JSONObject header = json.getJSONObject("output").getJSONObject("common-response-header"); + success = header.getBoolean("success"); + reason = header.getString("reason"); + } catch (Exception e) { + LOG.error("Unknown error prcoessing failed response from provider. Json not in expected format", e); + throw new APPCException("APPC has an unknown RPC error"); + } + if (success) { + return true; + } + String reasonStr = reason == null ? "Unknown" : reason; + LOG.warn(String.format("Topology Operation [%s] failed. Reason: %s", msg.getHeader().getRequestID(), reasonStr)); + throw new APPCException(reasonStr); + + } + throw new APPCException(String.format("Unexpected response from endpoint: [%d] - %s ", httpCode, respBody)); + } + + /** + * Updates the static var URL and returns the value; + * + * @return The new value of URL + */ + public static String getUrl() { + return url.toExternalForm(); + } + + public static void setUrl(String newUrl) { + try { + url = new URL(newUrl); + } catch (MalformedURLException e) { + LOG.error("Malformed URL", e); + } + } + + /** + * Sets the basic authentication header for the given user and password. If either entry is null then set basic auth + * to null + * + * @param user + * The user with optional domain name + * @param password + * The password for the user + * @return The new value of the basic auth string that will be used in the request headers + */ + public static String setAuthentication(String user, String password) { + if (user != null && password != null) { + String authStr = user + ":" + password; + basic_auth = new String(org.apache.commons.codec.binary.Base64.encodeBase64(authStr.getBytes())); + } else { + basic_auth = null; + } + return basic_auth; + } + + /** + * Builds the request body for a topology operation + * + * @param id + * The request id + * @param url + * The vm's url + * + * @param pgstreams + * The streams to send to the traffic generator + * + * @return A String containing the request body + */ + private static String buildReqest(String id, String url, String pgstreams) { + + return String.format(TEMPLATE, id, url, pgstreams); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/impl/WorkerImpl.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/impl/WorkerImpl.java new file mode 100644 index 000000000..d9bf6d358 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/impl/WorkerImpl.java @@ -0,0 +1,84 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.impl; + +import org.onap.appc.exceptions.APPCException; +import org.onap.appc.listener.EventHandler; +import org.onap.appc.listener.demo.model.IncomingMessage; +import org.onap.appc.listener.demo.model.Status; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +public class WorkerImpl implements Runnable { + + private final EELFLogger LOG = EELFManager.getInstance().getLogger(WorkerImpl.class); + + // Should have all of the data we need for processing + private IncomingMessage event; + + // So we can post messages from inside the worker. + private EventHandler dmaap; + + public WorkerImpl(IncomingMessage message, EventHandler dmaap) { + this.event = message; + this.dmaap = dmaap; + } + + @Override + public void run() { + LOG.debug(String.format("Started working on %s", event.getHeader().getRequestID())); + + dmaap.postStatus(event.toOutgoing(Status.ACCEPTED)); + // Run the dg in a try catch to handle all exceptions and update the + // message at the end + try { + if (doDG(event)) { + dmaap.postStatus(event.toOutgoing(Status.SUCCESS)); + LOG.debug(String.format("Event %s finished successfully", event.getHeader().getRequestID())); + } else { + // Should never happen. Exception with message should be thrown instead. + LOG.error(String.format( + "We somehow returned false from doDG() instead of throwing exception. Incoming event [%s]", + event.toJson().toString())); + dmaap.postStatus(event.toOutgoing(Status.FAILURE)); + } + + } catch (Exception e) { + // Unknown exception from DG method. Fail and pass the exception + // along + String msg = "Exception: " + e.getMessage(); + LOG.warn(String.format("Event %s finished with failure. %s", event.getHeader().getRequestID(), msg)); + //TODO: should a message be included? there is nothing in the API spec for a msg? + //dmaap.postStatus(event.toOutgoing(Status.FAILURE, msg)); + dmaap.postStatus(event.toOutgoing(Status.FAILURE)); + } + + LOG.debug("Done working on " + event.getHeader().getRequestID()); + } + + private boolean doDG(IncomingMessage msg) throws APPCException { + return ProviderOperations.topologyDG(msg); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/Action.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/Action.java new file mode 100644 index 000000000..6fc8ca0bc --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/Action.java @@ -0,0 +1,57 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.model; + +public enum Action { + Restart("Restart"), Rebuild("Rebuild"), Migrate("Migrate"), Evacuate("Evacuate"), Snapshot("Snapshot"),modifyconfig("ModifyConfig"); + + /** + * Converts the string to an Action + * + * @param value + * The string to try and convert. Is case insensitive + * @return The action matching the string or null if no match was found. + */ + public static Action toAction(String value) { + if (value != null) { + for (Action e : values()) { + if (e.getValue().toUpperCase().equals(value.toUpperCase())) { + return e; + } + } + } + + return null; + } + + private String value; + + private Action(String valueToUse) { + value = valueToUse; + } + + public final String getValue() { + return value; + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/CommonMessage.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/CommonMessage.java new file mode 100644 index 000000000..e0dbbab67 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/CommonMessage.java @@ -0,0 +1,313 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ================================================================================ + * Modifications Copyright (C) 2019 Ericsson + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.model; + +import java.io.Serializable; +import java.util.Collection; + +import org.json.JSONObject; +import org.onap.appc.listener.util.Mapper; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize.Inclusion; + +/** + * This class holds attributes that are common to DMaaP messages both coming in from DCAE and being sent out by APPC + * + */ +@JsonSerialize(include = Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class CommonMessage implements Serializable { + /* + * { "CommonHeader": { "TimeStamp": "0000-00-00T00:00:00.000Z", "APIver": "1.01", "OriginatorID": "policy.pdp01", + * "RequestID": "b74d13c5-bb26-4b04-992c-4679dfc8280e", "SubrequestID": "1" }, "Action": "RESTART", "Payload": { + * "VServerSelfLink": + * "http://192.168.1.2:8774/v2/abcde12345fghijk6789lmnopq123rst/servers/abc12345-1234-5678-890a-abcdefg12345", + * "VNF_NAME": "test", "VMID": "abc12345-1234-5678-890a-abcdefg12345", "TenantID": + * "abcde12345fghijk6789lmnopq123rst", "LOC_ID": "Test", "in-maint": "false", "Identity": + * "http://example.com:5000/v2.0", "Prov_status": "ACTIVE", "OAM_IPV4": "192.168.1.2", + * "is-closed-loop-disabled": "false", "VM_NAME": "basx0001vm034", "OAM_IPV6": "aaaa::bbbb:cccc:dddd:eeee/64" } } + */ + + private static final long serialVersionUID = 1L; + + /* + * The common header + */ + @JsonProperty("CommonHeader") + private CommonHeader header; + + /* + * The payload + */ + @JsonProperty("Payload") + private Payload payload; + + @JsonIgnore + private long startTime = System.currentTimeMillis(); + + /* + * Getters and Setters + */ + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + /** + * @return the header + */ + public CommonHeader getHeader() { + return header; + } + + /** + * @param header + * the header to set + */ + public void setHeader(CommonHeader header) { + this.header = header; + } + + /** + * @return the payload + */ + public Payload getPayload() { + return payload; + } + + /** + * @param payload + * the payload to set + */ + public void setPayload(Payload payload) { + this.payload = payload; + } + + /** + * Convenience method to return a json representation of this object. + * + * @return The json representation of this object + */ + public JSONObject toJson() { + return Mapper.toJsonObject(this); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class CommonHeader { + /* + * "CommonHeader": { "TimeStamp": "2016-05-11T13:53:53.146Z", "APIver": "1.01", "OriginatorID": "policy.pdp01", + * "RequestID": "b74d13c5-bb26-4b04-992c-4679dfc8280e", "SubrequestID": "1" } + */ + + /* + * The timestamp of the message + */ + @JsonProperty("TimeStamp") + private String timeStamp; + + /* + * The API version of the message + */ + @JsonProperty("APIver") + private String apiVer; + + /* + * The Originator ID of the message + */ + @JsonProperty("OriginatorID") + private String originatorId; + + /* + * The Request Id of the message + */ + @JsonProperty("RequestID") + private String requestID; + + /* + * The Subrequest Id of the message + */ + @JsonProperty("SubRequestID") + private String subRequestId; + + /** + * @return the timeStamp + */ + public String getTimeStamp() { + return timeStamp; + } + + /** + * @param timeStamp + * the timeStamp to set + */ + public void setTimeStamp(String timeStamp) { + this.timeStamp = timeStamp; + } + + /** + * @return the apiVer + */ + public String getApiVer() { + return apiVer; + } + + /** + * @param apiVer + * the apiVer to set + */ + public void setApiVer(String apiVer) { + this.apiVer = apiVer; + } + + /** + * @return the originatorId + */ + public String getOriginatorId() { + return originatorId; + } + + /** + * @param originatorId + * the originatorId to set + */ + public void setOriginatorId(String originatorId) { + this.originatorId = originatorId; + } + + /** + * @return the requestID + */ + public String getRequestID() { + return requestID; + } + + /** + * @param requestID + * the requestID to set + */ + public void setRequestID(String requestID) { + this.requestID = requestID; + } + + /** + * @return the subRequestId + */ + public String getSubRequestId() { + return subRequestId; + } + + /** + * @param subRequestId + * the subRequestId to set + */ + public void setSubRequestId(String subRequestId) { + this.subRequestId = subRequestId; + } + }; + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Payload { + /* + * "Payload": { "VServerSelfLink": + * "http://192.168.1.2:8774/v2/abcde12345fghijk6789lmnopq123rst/servers/abc12345-1234-5678-890a-abcdefg12345", + * "VNF_NAME": "test", "VMID": "abc12345-1234-5678-890a-abcdefg12345", "TenantID": + * "abcde12345fghijk6789lmnopq123rst", "LOC_ID": "Test", "in-maint": "false", "Identity": + * "http://example.com:5000/v2.0", "Prov_status": "ACTIVE", "OAM_IPV4": "192.168.1.2", + * "is-closed-loop-disabled": "false", "VM_NAME": "test", "OAM_IPV6": "aaaa::bbbb:cccc:dddd:eeee/64" } + */ + + /* + * The TenantID of the message + */ + @JsonProperty("generic-vnf.vnf-id") + private String genericVnfId; + + /** + * @return the TenantID + */ + public String getGenericVnfId() { + return genericVnfId; + } + + /** + * @param TenantID + * the TenantID to set + */ + public void setGenericVnfId(String genericVnfId) { + this.genericVnfId = genericVnfId; + } + + @JsonProperty("streams") + private Streams streams; + + /** + * @return the TenantID + */ + + public String getStreams() { + String r = "{\\\"streams\\\": {\\\"active-streams\\\": " + streams.getActiveStreams() + + "}}"; + return r; + } + + /** + * @param TenantID + * the TenantID to set + */ + public void setStreams(Streams streams) { + this.streams = streams; + } + + + + + + }; + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Streams { + + @JsonProperty("active-streams") + private int activeStreams; + + public int getActiveStreams() { + return this.activeStreams; + } + + public void setActiveStreams(int activeStreams) { + this.activeStreams = activeStreams; + } + + }; + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/IncomingMessage.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/IncomingMessage.java new file mode 100644 index 000000000..bff1f3bc7 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/IncomingMessage.java @@ -0,0 +1,90 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize.Inclusion; + +/** + * This class represents a message coming in from DCAE. + * + */ +@JsonSerialize(include = Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class IncomingMessage extends CommonMessage { + + private static final long serialVersionUID = 1L; + + /* + * The action being requested. Its presence signals that it is an incoming message and it is not present on outgoing + * messages + */ + //TODO; use enum + @JsonProperty("Action") + private String action; + + + public String getRequest() { + return action; + } + + @JsonIgnore + public Action getAction() { + return Action.toAction(action); + } + + public void setRequest(String request) { + this.action = request; + } + +// @Override +// public String toString() { +// String time = getRequestTime() != null ? getRequestTime() : "N/A"; +// // String req = request != null ? request : "N/A"; +// return String.format("[%s - %s]", time, getId()); +// } + +// public String toOutgoing(Status status) { +// return toOutgoing(status); +// } + + public String toOutgoing(Status status) { + OutgoingMessage out = new OutgoingMessage(this); + out.setResponse(status); + return out.toResponse().toString(); + } + + /** + * Determines if this message should be parsed parsed. Will eventually check that the message is well formed, has + * all required fields, and had not exceeded any timing restrictions. + * + * @return True if the message should be parsed. False otherwise + */ + public boolean isValid() { + return true; + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/OutgoingMessage.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/OutgoingMessage.java new file mode 100644 index 000000000..100d55bf2 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/OutgoingMessage.java @@ -0,0 +1,202 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ================================================================================ + * Modifications Copyright (C) 2019 Ericsson + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.model; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.security.SecureRandom; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + +import org.json.JSONObject; +import org.onap.appc.listener.util.Mapper; +import org.onap.appc.util.Time; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize.Inclusion; + +/** + * This class represents a message being sent out to DMaaP by APPC to update listeners on the status of a request + * + */ +@JsonSerialize(include = Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class OutgoingMessage extends CommonMessage { + + public OutgoingMessage() { + + } + + public OutgoingMessage(IncomingMessage msg) { + setHeader(msg.getHeader()); + setPayload(msg.getPayload()); + // setId(msg.getId()); + // setOriginalRequest(msg.getRequest()); + // setRequestClient(msg.getRequestClient()); + // setRequestTime(msg.getRequestTime()); + // setVmName(msg.getVmName()); + // setFromSystem(generateFrom()); + // setResponse(Status.PENDING); + // setPolicyName(msg.getPolicyName()); + // setPolicyVersion(msg.getPolicyVersion()); + // setStartTime(msg.getStartTime()); + } + + private static final long serialVersionUID = -5447940920271469613L; + /* + * The status of the response + */ + @JsonProperty("Status") + private OutStatus status; + + /** + * @return the status + */ + public OutStatus getStatus() { + return status; + } + + /** + * @param status the status to set + */ + public void setStatus(OutStatus status) { + this.status = status; + } + + public void updateResponseTime() { + SecureRandom rand = new SecureRandom(); + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss.SSS"); + df.setTimeZone(TimeZone.getTimeZone("UTC")); + String date = df.format(new Date(Time.utcTime())); + //this.responseTime = String.format("%s%03d", date, rand.nextInt(1000)); + } + + public String generateFrom() { + String name; + try { + InetAddress iAddress = getLocalHost(); + name = iAddress.getCanonicalHostName(); + } catch (Exception e) { + // Could not get anything from the InetAddress + name = "UnknownHost"; + } + return "appc@" + name; + } + + public JSONObject toResponse() { + updateResponseTime(); + JSONObject json = Mapper.toJsonObject(this); + + if (!json.has("message")) { + // If there is no message, parrot the status (response field) + // TODO - Can this be removed for 1602 making message truely optional? + //json.put("message", this.getResponse().toString()); + } + + // Removed duplication of status from message for 1602 + // json.put("message", String.format("%s: %s", request, json.get("message"))); + + return json; + } + + // @Override + // public String toString() { + // return String.format("%s - %s", getId(), getResponse()); + // } + + public static class OutStatus{ + @JsonProperty("Code") + private String code; + + @JsonProperty("Value") + private String value; + + /** + * @return the code + */ + public String getCode() { + return code; + } + + /** + * @param code the code to set + */ + public void setCode(String code) { + this.code = code; + } + + /** + * @return the value + */ + public String getValue() { + return value; + } + + /** + * @param value the value to set + */ + public void setValue(String value) { + this.value = value; + } + + } + + public void setResponse(Status newStatus) { + if(this.status == null){ + this.status = new OutStatus(); + } + if(newStatus == null) { + return; + } + + switch (newStatus){ + case ACCEPTED: + this.status.setValue(newStatus.getValue()); + this.status.setCode("100"); + break; + + case FAILURE: + this.status.setValue(newStatus.getValue()); + this.status.setCode("500"); + break; + + case SUCCESS: + this.status.setValue(newStatus.getValue()); + this.status.setCode("400"); + break; + default: + break; + + } + } + + protected InetAddress getLocalHost() throws UnknownHostException { + return InetAddress.getLocalHost(); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/Status.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/Status.java new file mode 100644 index 000000000..a4abeac60 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/demo/model/Status.java @@ -0,0 +1,71 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.model; + +public enum Status { + /* + * APP-C acknowledges that it has read the event off of the wire. This is the initial status of an OutgoingEvent + */ + ACCEPTED("ACCEPTED"), + + /* + * APP-C has finished processing the event without errors + */ + SUCCESS("SUCCESS"), + + /* + * APP-C has finished processing the event with errors + */ + FAILURE("FAILURE"); + + /** + * Converts the string to an Status + * + * @param value + * The string to try and convert. Is case insensitive + * @return The status matching the string or null if no match was found. + */ + public static Status toStatus(String value) { + if (value != null) { + for (Status e : values()) { + if (e.getValue().toUpperCase().equals(value.toUpperCase())) { + return e; + } + } + } + + return null; + } + + private String value; + + private Status(String valueToUse) { + value = valueToUse; + } + + public final String getValue() { + return value; + } + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/impl/ControllerImpl.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/impl/ControllerImpl.java new file mode 100644 index 000000000..d1c5d61c2 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/impl/ControllerImpl.java @@ -0,0 +1,146 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ================================================================================ + * Modifications Copyright (C) 2019 Ericsson + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.impl; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang3.concurrent.BasicThreadFactory; +import org.onap.appc.listener.Controller; +import org.onap.appc.listener.Listener; +import org.onap.appc.listener.ListenerProperties; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + + +/** + * A common implementation of a controller. This controller should not need to be modified to implement new listeners + * + */ +public class ControllerImpl implements Controller { + + private final EELFLogger LOG = EELFManager.getInstance().getLogger(ControllerImpl.class); + + private int LISTENER_COUNT = 1; + + private Map<ListenerProperties, Listener> listeners = null; + + private ThreadPoolExecutor executor; + + /** + * Creates a Controller with the set of listener properties which will be used to start listener threads. + * + * @param properties + * A non null Set of ListenerProperties + */ + public ControllerImpl(Set<ListenerProperties> properties) { + listeners = new HashMap<ListenerProperties, Listener>(); + for (ListenerProperties props : properties) { + if (props.getListenerClass() != null) { + listeners.put(props, null); + } else { + LOG.error(String.format( + "The ListenerProperties %s has no Listener class associated with it and will not run.", props)); + properties.remove(props); + } + } + + LISTENER_COUNT = properties.size(); + + // Only create executor if listeners are configured + if (LISTENER_COUNT > 0) { + executor = new ThreadPoolExecutor(LISTENER_COUNT, LISTENER_COUNT, 1, TimeUnit.SECONDS, + new ArrayBlockingQueue<Runnable>(LISTENER_COUNT)); + + // Custom Named thread factory + BasicThreadFactory threadFactory = new BasicThreadFactory.Builder().namingPattern("Appc-Listener-%d").build(); + executor.setThreadFactory(threadFactory); + } + } + + @Override + public void start() { + LOG.info("Starting DMaaP Controller."); + for (ListenerProperties props : listeners.keySet()) { + try { + if (props.isDisabled()) { + LOG.warn(String.format("The listener %s is disabled and will not be run", props.getPrefix())); + } else { + Listener l = props.getListenerClass().getConstructor(ListenerProperties.class).newInstance(props); + l.setListenerId(props.getPrefix()); + listeners.put(props, l); + executor.execute(l); + } + } catch (Exception e) { + LOG.error(String.format("Exception while starting listener %s.", props), e); + } + } + } + + @Override + public void stop(boolean stopNow) { + LOG.info("Stopping DMaaP Controller."); + Iterator<Listener> itr = listeners.values().iterator(); + while (itr.hasNext()) { + Listener l = itr.next(); + if (stopNow && l != null) { + l.stopNow(); + } else if(l != null){ + l.stop(); + } + itr.remove(); + } + // disable new tasks from being submitted + if(executor != null) { + executor.shutdown(); + int timeout = 300; + try { + if (!executor.awaitTermination(timeout, TimeUnit.SECONDS)) { + LOG.error("Not all tasks completed execution after " + timeout + " seconds. " + + "Attempting to stop all actively executing tasks."); + executor.shutdownNow(); + } + if (!executor.awaitTermination(timeout, TimeUnit.SECONDS)) { + LOG.error("Could not terminate all tasks after " + (timeout * 2) + " seconds."); + } + } catch (InterruptedException e) { + executor.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + } + + @Override + public Map<ListenerProperties, Listener> getListeners() { + return listeners; + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/impl/EventHandlerImpl.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/impl/EventHandlerImpl.java new file mode 100644 index 000000000..117901ca1 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/impl/EventHandlerImpl.java @@ -0,0 +1,400 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ================================================================================ + * Modifications Copyright (C) 2019 Ericsson + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.impl; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import org.onap.appc.adapter.factory.MessageService; +import org.onap.appc.adapter.message.Consumer; +import org.onap.appc.adapter.message.Producer; +import org.onap.appc.adapter.messaging.dmaap.http.HttpDmaapConsumerImpl; +import org.onap.appc.adapter.messaging.dmaap.http.HttpDmaapProducerImpl; +import org.onap.appc.listener.EventHandler; +import org.onap.appc.listener.ListenerProperties; +import org.onap.appc.listener.util.Mapper; +import org.onap.appc.logging.LoggingConstants; +import org.slf4j.MDC; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; + +/** + * This class is a wrapper for the DMaaP client provided in appc-dmaap-adapter. Its aim is to ensure + * that only well formed messages are sent and received on DMaaP. + */ +public class EventHandlerImpl implements EventHandler { + + private final EELFLogger LOG = EELFManager.getInstance().getLogger(EventHandlerImpl.class); + + /* + * The amount of time in seconds to keep a connection to a topic open while waiting for data + */ + private int READ_TIMEOUT = 60; + + /* + * The pool of hosts to query against + */ + private Collection<String> pool; + + /* + * The topic to read messages from + */ + private String readTopic; + + /* + * The topic to write messages to + */ + private String writeTopic; + + /* + * The client (group) name to use for reading messages + */ + private String clientName; + + /* + * The id of the client (group) that is reading messages + */ + private String clientId; + + /* + * The api public key to use for authentication + */ + private String apiKey; + + /* + * The api secret key to use for authentication + */ + private String apiSecret; + + /* + * A json object containing filter arguments. + */ + private String filter_json; + + + /* + * Blacklist time for a server with response problem in seconds + */ + private String responseProblemBlacklistTime; + + /* + * Blacklist time for a server with server problem in seconds + */ + private String serverProblemBlacklistTime; + + /* + * Blacklist time for a server with DNS problem in seconds + */ + private String dnsIssueBlacklistTime; + + /* + * Blacklist time for a server with IO Exception problem in seconds + */ + private String ioExceptionBlacklistTime; + + private MessageService messageService; + + private Consumer reader = null; + private Producer producer = null; + + public EventHandlerImpl(ListenerProperties props) { + pool = new HashSet<>(); + + if (props != null) { + readTopic = props.getProperty(ListenerProperties.KEYS.TOPIC_READ); + clientName = props.getProperty(ListenerProperties.KEYS.CLIENT_NAME, "APP-C"); + clientId = props.getProperty(ListenerProperties.KEYS.CLIENT_ID, "0"); + apiKey = props.getProperty(ListenerProperties.KEYS.AUTH_USER_KEY); + apiSecret = props.getProperty(ListenerProperties.KEYS.AUTH_SECRET_KEY); + responseProblemBlacklistTime = props.getProperty(ListenerProperties.KEYS.PROBLEM_WITH_RESPONSE_BLACKLIST_TIME); + serverProblemBlacklistTime = props.getProperty(ListenerProperties.KEYS.PROBLEM_SERVERSIDE_ERROR_BLACKLIST_TIME); + dnsIssueBlacklistTime = props.getProperty(ListenerProperties.KEYS.PROBLEM_DNS_BLACKLIST_TIME); + ioExceptionBlacklistTime = props.getProperty(ListenerProperties.KEYS.PROBLEM_IO_EXCEPTION_BLACKLIST_TIME); + + filter_json = props.getProperty(ListenerProperties.KEYS.TOPIC_READ_FILTER); + + READ_TIMEOUT = Integer + .valueOf(props.getProperty(ListenerProperties.KEYS.TOPIC_READ_TIMEOUT, String.valueOf(READ_TIMEOUT))); + + String hostnames = props.getProperty(ListenerProperties.KEYS.HOSTS); + if (hostnames != null && !hostnames.isEmpty()) { + for (String name : hostnames.split(",")) { + pool.add(name); + } + } + + String writeTopicStr = props.getProperty(ListenerProperties.KEYS.TOPIC_WRITE); + if (writeTopicStr != null) { + for (String topic : writeTopicStr.split(",")) { + writeTopic = topic; + } + } + + messageService = MessageService.parse(props.getProperty(ListenerProperties.KEYS.MESSAGE_SERVICE)); + + LOG.info(String.format( + "Configured to use %s client on host pool [%s]. Reading from [%s] filtered by %s. Writing to [%s]. Authenticated using %s", + messageService, hostnames, readTopic, filter_json, writeTopic, apiKey)); + } + } + + @Override + public List<String> getIncomingEvents() { + return getIncomingEvents(1000); + } + + @Override + public List<String> getIncomingEvents(int limit) { + List<String> out = new ArrayList<>(); + LOG.info(String.format("Getting up to %d incoming events", limit)); + // reuse the consumer object instead of creating a new one every time + if (reader == null) { + LOG.info("Getting Consumer..."); + reader = getConsumer(); + } + if (reader != null) { + List<String> items = reader.fetch(READ_TIMEOUT * 1000, limit); + for (String item : items) { + out.add(item); + } + } + LOG.info(String.format("Read %d messages from %s as %s/%s.", out.size(), readTopic, clientName, clientId)); + return out; + } + + @Override + public <T> List<T> getIncomingEvents(Class<T> cls) { + return getIncomingEvents(cls, 1000); + } + + @Override + public <T> List<T> getIncomingEvents(Class<T> cls, int limit) { + List<String> incomingStrings = getIncomingEvents(limit); + return Mapper.mapList(incomingStrings, cls); + } + + @Override + public void postStatus(String event) { + postStatus(null, event); + } + + @Override + public void postStatus(String partition, String event) { + LOG.debug(String.format("Posting Message [%s]", event)); + if (producer == null) { + LOG.info("Getting Producer..."); + producer = getProducer(); + } + producer.post(partition, event); + } + + /** + * Returns a consumer object for direct access to our Cambria consumer interface + * + * @return An instance of the consumer interface + */ + protected Consumer getConsumer() { + LOG.debug(String.format("Getting Consumer: %s %s/%s/%s", pool, readTopic, clientName, clientId)); + if (filter_json == null && writeTopic.equals(readTopic)) { + LOG.error( + "*****We will be writing and reading to the same topic without a filter. This will cause an infinite loop.*****"); + } + + Consumer out = null; + out = new HttpDmaapConsumerImpl(pool, readTopic, clientName, clientId, filter_json, apiKey, apiSecret); + + if (out != null && responseProblemBlacklistTime != null && responseProblemBlacklistTime.length() > 0) + { + out.setResponseProblemBlacklistTime(responseProblemBlacklistTime); + } + + if (out != null && serverProblemBlacklistTime != null && serverProblemBlacklistTime.length() > 0) + { + out.setServerProblemBlacklistTime(serverProblemBlacklistTime); + } + + if (out != null && dnsIssueBlacklistTime != null && dnsIssueBlacklistTime.length() > 0) + { + out.setDnsIssueBlacklistTime(dnsIssueBlacklistTime); + } + + if (out != null && ioExceptionBlacklistTime != null && ioExceptionBlacklistTime.length() > 0) + { + out.setIOExceptionBlacklistTime(ioExceptionBlacklistTime); + } + if (out != null) { + for (String url : pool) { + if (url.contains("3905") || url.contains("https")) { + out.useHttps(true); + break; + } + } + } + return out; + } + + /** + * Returns a consumer object for direct access to our Cambria producer interface + * + * @return An instance of the producer interface + */ + protected Producer getProducer() { + LOG.debug(String.format("Getting Producer: %s %s", pool, readTopic)); + + Producer out = null; + out = new HttpDmaapProducerImpl(pool, writeTopic, apiKey, apiSecret); + if (out != null && responseProblemBlacklistTime != null && responseProblemBlacklistTime.length() > 0) + { + out.setResponseProblemBlacklistTime(responseProblemBlacklistTime); + } + + if (out != null && serverProblemBlacklistTime != null && serverProblemBlacklistTime.length() > 0) + { + out.setServerProblemBlacklistTime(serverProblemBlacklistTime); + } + + if (out != null && dnsIssueBlacklistTime != null && dnsIssueBlacklistTime.length() > 0) + { + out.setDnsIssueBlacklistTime(dnsIssueBlacklistTime); + } + + if (out != null && ioExceptionBlacklistTime != null && ioExceptionBlacklistTime.length() > 0) + { + out.setIOExceptionBlacklistTime(ioExceptionBlacklistTime); + } + if (out != null) { + for (String url : pool) { + if (url.contains("3905") || url.contains("https")) { + out.useHttps(true); + break; + } + } + } + return out; + } + + @Override + public void closeClients() { + LOG.debug("Closing Consumer and Producer DMaaP clients"); + if (reader != null) { + reader.close(); + } + if (producer != null) { + producer.close(); + } + } + + @Override + public String getClientId() { + return clientId; + } + + @Override + public void setClientId(String clientId) { + this.clientId = clientId; + } + + @Override + public String getClientName() { + return clientName; + } + + @Override + public void setClientName(String clientName) { + this.clientName = clientName; + MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, clientName); + } + + @Override + public void addToPool(String hostname) { + pool.add(hostname); + } + + @Override + public Collection<String> getPool() { + return pool; + } + + @Override + public void removeFromPool(String hostname) { + pool.remove(hostname); + } + + @Override + public String getReadTopic() { + return readTopic; + } + + @Override + public void setReadTopic(String readTopic) { + this.readTopic = readTopic; + } + + @Override + public String getWriteTopic() { + return writeTopic; + } + + @Override + public void setWriteTopic(String writeTopic) { + this.writeTopic = writeTopic; + } + + @Override + public void setResponseProblemBlacklistTime(String duration){ + this.responseProblemBlacklistTime = duration; + } + + @Override + public void setServerProblemBlacklistTime(String duration){ + this.serverProblemBlacklistTime = duration; + } + + @Override + public void setDnsIssueBlacklistTime(String duration){ + this.dnsIssueBlacklistTime = duration; + } + + @Override + public void setIOExceptionBlacklistTime(String duration){ + this.ioExceptionBlacklistTime = duration; + } + + @Override + public void clearCredentials() { + apiKey = null; + apiSecret = null; + } + + @Override + public void setCredentials(String key, String secret) { + apiKey = key; + apiSecret = secret; + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/util/HttpClientUtil.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/util/HttpClientUtil.java new file mode 100644 index 000000000..2b8e887bf --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/util/HttpClientUtil.java @@ -0,0 +1,126 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Ericsson. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + * file except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.util; + +import java.io.IOException; +import java.net.Socket; +import java.net.UnknownHostException; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import org.apache.http.HttpVersion; +import org.apache.http.client.HttpClient; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.scheme.PlainSocketFactory; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.HttpParams; +import org.apache.http.params.HttpProtocolParams; +import org.apache.http.protocol.HTTP; +import org.onap.appc.exceptions.APPCException; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +@SuppressWarnings("deprecation") +public class HttpClientUtil { + + private static final EELFLogger log = EELFManager.getInstance().getLogger(HttpClientUtil.class); + + public static HttpClient getHttpClient(String protocol) throws APPCException { + HttpClient client; + if ("https".equals(protocol)) { + try { + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + MySSLSocketFactory sf = new MySSLSocketFactory(trustStore); + sf.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + + HttpParams params = new BasicHttpParams(); + HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); + HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); + + SchemeRegistry registry = new SchemeRegistry(); + registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); + registry.register(new Scheme("https", sf, 443)); + registry.register(new Scheme("https", sf, 8443)); + registry.register(new Scheme("http", sf, 8181)); + + ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); + client = new DefaultHttpClient(ccm, params); + } catch (Exception e) { + log.info("Creating Default Http Client with no params " + e.getMessage(), e); + client = new DefaultHttpClient(); + } + } else if ("http".equals(protocol)) { + client = new DefaultHttpClient(); + } else { + throw new APPCException( + "The provider.topology.url property is invalid. The url did not start with http[s]"); + } + return client; + } + + private static class MySSLSocketFactory extends SSLSocketFactory { + private SSLContext sslContext = SSLContext.getInstance("TLS"); + + public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, + KeyManagementException, KeyStoreException, UnrecoverableKeyException { + super(truststore); + + TrustManager tm = new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException {} + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException {} + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + }; + + sslContext.init(null, new TrustManager[] {tm}, null); + } + + @Override + public Socket createSocket(Socket socket, String host, int port, boolean autoClose) + throws IOException, UnknownHostException { + return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); + } + + @Override + public Socket createSocket() throws IOException { + return sslContext.getSocketFactory().createSocket(); + } + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/util/Mapper.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/util/Mapper.java new file mode 100644 index 000000000..b9a6a4cc8 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/java/org/onap/appc/listener/util/Mapper.java @@ -0,0 +1,136 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ================================================================================ + * Modifications Copyright (C) 2019 Ericsson + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.util; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.json.JSONObject; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class Mapper { + + private static final EELFLogger LOG = EELFManager.getInstance().getLogger(Mapper.class); + + private static ObjectMapper mapper = new ObjectMapper(); + + /** + * @return The object mapper that we are using. + */ + public static ObjectMapper getMapper() { + return mapper; + } + + /** + * Convert a String to a DcaeMessage + * + * @param data + * The json string to try and parse + * @return A DcaeMessage from the json string or null if it could not + */ + public static <T> T mapOne(String data, Class<T> cls) { + try { + return mapper.readValue(data, cls); + } catch (Exception e) { + LOG.warn(String.format("Could not map [ %s ] to %s", data, cls.getName()), e); + return null; + } + } + + public static <T> List<T> mapList(List<String> data, Class<T> cls) { + List<T> out = new ArrayList<T>(); + for (String s : data) { + T tmp = Mapper.mapOne(s, cls); + if (tmp != null) { + out.add(tmp); + } + } + return out; + } + + /** + * Convenience method to try and convert objects to json String + * + * @param obj + * The object to try and convert + * @return A json string representing the object or null if it could not be converted + */ + public static String toJsonString(Object obj) { + String jsonStr; + try { + if (obj instanceof JSONObject) { + jsonStr = obj.toString(); + }else { + jsonStr = mapper.writeValueAsString(obj); + } + return jsonStr; + } catch (Exception e) { + LOG.warn(String.format("Could not map %s to JSONObject.", obj), e); + return null; + } + } + + public static JSONObject toJsonObject(Object obj) { + String jsonStr; + try { + if (obj.getClass().equals(String.class)) { + jsonStr = (String) obj; + } else { + jsonStr = mapper.writeValueAsString(obj); + } + return new JSONObject(jsonStr); + } catch (Exception e) { + LOG.warn(String.format("Could not map %s to JSONObject.", obj), e); + return null; + } + } + public static JsonNode toJsonNodeFromJsonString(String jsonStr) { + JsonNode jsonNode = null; + if(jsonStr != null) { + try { + jsonNode = mapper.readTree(jsonStr); + } catch (IOException e) { + LOG.warn(String.format("Could not map %s to jsonNode.", jsonStr), e); + } + } + return jsonNode; + } + public static JsonNode toJsonNode(Object obj) { + JsonNode jsonNode = null; + String jsonStr = toJsonString(obj); + if(jsonStr != null) { + try { + jsonNode = mapper.readTree(jsonStr); + } catch (IOException e) { + LOG.warn(String.format("Could not map %s to JSONObject.", obj), e); + } + } + return jsonNode; + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/main/resources/org/onap/appc/default.properties b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/resources/org/onap/appc/default.properties new file mode 100644 index 000000000..ba4c5239a --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/main/resources/org/onap/appc/default.properties @@ -0,0 +1,113 @@ +### +# ============LICENSE_START======================================================= +# ONAP : APPC +# ================================================================================ +# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Copyright (C) 2017 Amdocs +# ============================================================================= +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END========================================================= +### + +# ${user.home} usually goes to /root if instantiation uses the appc-docker approach + +### ### +### ### +###Properties below that are commented out are/need to be provided in appc.properties### +### ### +### ### + + + + +# Define the name and path of any user-provided configuration (bootstrap) file that can be loaded to supply configuration options +org.onap.appc.bootstrap.file=appc.properties +org.onap.appc.bootstrap.path=/opt/onap/appc/data/properties,${user.home},. + + + + + +### ### +###Closed Loop - properties ### +### ### +appc.ClosedLoop.poolMembers=192.168.1.2:3904 +appc.ClosedLoop.topic.read=APPC-TEST2 +appc.ClosedLoop.topic.write=APPC-TEST2 +appc.ClosedLoop.topic.read.filter={"class": "And","filters": [{"class": "Assigned","field": "request"},{"class": "Unassigned","field": "response"}]} +appc.ClosedLoop.client.name=APPC-TEST-CLIENT-EVT-LST-MAIN +appc.ClosedLoop.client.name.id=0 + +# KEY AND SECRET BELOW NEED TO BE MODIFIED TO APPROPRIATE VALUES WHEN THE TOPIC IS API-KEY-BASED AUTH +#dmaap.client.key=random +#dmaap.client.secret=random + +appc.ClosedLoop.threads.queuesize.min=1 +appc.ClosedLoop.threads.queuesize.max=1000 +appc.ClosedLoop.threads.poolsize.min=1 +appc.ClosedLoop.threads.poolsize.max=2 +appc.ClosedLoop.provider.url=http://localhost:8181/restconf/operations/appc-provider +appc.ClosedLoop.provider.url.user=ODL_USER +appc.ClosedLoop.provider.url.pass=ODL_PASS + + + + + +### ### +###Closed Loop - 1607 properties ### +### ### +appc.ClosedLoop1607.poolMembers=192.168.1.2:3904 +appc.ClosedLoop1607.topic.read=MY_DMAAP_TOPIC +appc.ClosedLoop1607.topic.write=MY_DMAAP_TOPIC +appc.ClosedLoop1607.topic.read.filter={"class":"Unassigned","field":"Status"} +appc.ClosedLoop1607.client.name=MY_DMAAP_CLIENT_NAME +appc.ClosedLoop1607.client.name.id=0 +#dmaap.client.key=random +#dmaap.client.secret=random +appc.ClosedLoop1607.threads.queuesize.min=1 +appc.ClosedLoop1607.threads.queuesize.max=1000 +appc.ClosedLoop1607.threads.poolsize.min=1 +appc.ClosedLoop1607.threads.poolsize.max=2 +appc.ClosedLoop.provider.user=ODL_USER +appc.ClosedLoop.provider.pass=ODL_PASS +appc.ClosedLoop1607.provider.url=http://localhost:8181/restconf/operations/appc-provider + + + + + +### ### +### This needs to be changed so that the action can be appended to the end of the URL path ### +### ### +appc.LCM.provider.url=http://localhost:8181/restconf/operations/appc-provider +appc.LCM.poolMembers=127.0.0.1:3001 +appc.LCM.topic.read=DMAAP_TOPIC +appc.LCM.topic.write=DMAAP_TOPIC +appc.LCM.client.name=DMAAP_CLIENT_NAME +appc.LCM.provider.user=ODL_USER +appc.LCM.provider.pass=ODL_URL + +appc.demo.poolMembers=127.0.0.1:3002 +appc.demo.topic.read=APPC-CL +appc.demo.topic.write=APPC-CL +appc.demo.client.name=appcDemoEventListener +appc.demo.threads.queuesize.min=1 +appc.demo.threads.queuesize.max=1000 +appc.demo.threads.poolsize.min=1 +appc.demo.threads.poolsize.max=2 +appc.demo.provider.user=admin +appc.demo.provider.pass=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U +appc.demo.provider.url=http://192.168.55.12:8282/restconf/operations/appc-provider diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/AbstractListenerTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/AbstractListenerTest.java new file mode 100644 index 000000000..a47175c02 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/AbstractListenerTest.java @@ -0,0 +1,152 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Properties; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; + +import java.util.concurrent.TimeUnit; +import org.junit.Before; +import org.junit.Test; +import org.onap.appc.listener.AbstractListener; +import org.onap.appc.listener.ListenerProperties; + +public class AbstractListenerTest { + + private DummyListener listener; + private ListenerProperties props; + + @Before + public void setup() throws Exception { + Properties regularProps = new Properties(); + regularProps.load(getClass().getResourceAsStream("/org/onap/appc/default.properties")); + props = new ListenerProperties("", regularProps); + listener = new DummyListener(props); + } + + @Test + public void stop_should_shutdown_executor() { + + EventHandler mockEventHandler = mock(EventHandler.class); + listener.setEventHandler(mockEventHandler); + + Thread thread = new Thread(listener); + thread.start(); + + assertTrue(thread.isAlive()); + assertTrue(listener.getRun()); + assertFalse(listener.getExecutor().isShutdown()); + assertFalse(listener.getExecutor().isTerminated()); + + listener.stop(); + + assertFalse(listener.getRun()); + assertTrue(listener.getExecutor().isShutdown()); + assertTrue(listener.getExecutor().isTerminated()); + + verify(mockEventHandler).closeClients(); + + } + + @Test + public void stopNow_should_clear_executors_queue_and_call_stop() throws InterruptedException { + EventHandler mockEventHandler = mock(EventHandler.class); + listener.setEventHandler(mockEventHandler); + + ThreadPoolExecutor mockExecutor = mock(ThreadPoolExecutor.class); + BlockingQueue<Runnable> mockBlockingQueue = mock(BlockingQueue.class); + listener.setExecutor(mockExecutor); + when(mockExecutor.getQueue()).thenReturn(mockBlockingQueue); + + Thread thread = new Thread(listener); + thread.start(); + + assertTrue(thread.isAlive()); + assertTrue(listener.getRun()); + + listener.stopNow(); + + assertFalse(listener.getRun()); + verify(mockExecutor).shutdown(); + verify(mockExecutor).awaitTermination(anyLong(), any(TimeUnit.class)); + verify(mockBlockingQueue).clear(); + verify(mockEventHandler).closeClients(); + } + + @Test + public void getBenchmark_result_should_contain_listenerId() { + String out = listener.getBenchmark(); + assertNotNull(out); + assertTrue(out.contains(listener.getListenerId())); + } + + @Test + public void getListenerId_should_return_properties_prefix_by_default() { + assertEquals(props.getPrefix(), listener.getListenerId()); + listener.setListenerId("newId"); + assertEquals("newId", listener.getListenerId()); + } + + + private class DummyListener extends AbstractListener { + + DummyListener(ListenerProperties props) { + super(props); + } + + boolean getRun() { + return run.get(); + } + + public ThreadPoolExecutor getExecutor() { + return executor; + } + + void setEventHandler(EventHandler eventHandler){ + dmaap = eventHandler; + } + + void setExecutor(ThreadPoolExecutor executor){ + this.executor = executor; + } + + @Override + public void run() { + + while (run.get()) { + } + } + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/AppcEventListenerActivatorTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/AppcEventListenerActivatorTest.java new file mode 100644 index 000000000..0dc1d4d3f --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/AppcEventListenerActivatorTest.java @@ -0,0 +1,80 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.junit.Test; +import org.mockito.Mockito; + +import static org.mockito.Mockito.doReturn; + +import org.onap.appc.listener.AppcEventListenerActivator; + +public class AppcEventListenerActivatorTest { + + @Test + public void testStartStopDefaultProperties() { + AppcEventListenerActivator appc = new AppcEventListenerActivator(); + try { + appc.start(); + Thread.sleep(1000); + appc.stop(); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + assertNotNull(appc.getName()); + } + + @Test + public void testStartStopEmptyProperties() { + InputStream input = getClass().getResourceAsStream("/org/onap/appc/empty.properties"); + Properties props = new Properties(); + try { + props.load(input); + } catch (IOException e) { + e.printStackTrace(); + } + + AppcEventListenerActivator appc = new AppcEventListenerActivator(); + AppcEventListenerActivator spyAppc = Mockito.spy(appc); + doReturn(props).when(spyAppc).getProperties(); + + try { + spyAppc.start(); + Thread.sleep(1000); + spyAppc.stop(); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + assertNotNull(spyAppc.getName()); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/conv/ConverterTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/conv/ConverterTest.java new file mode 100644 index 000000000..037f91a6e --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/conv/ConverterTest.java @@ -0,0 +1,143 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.conv; + +import static org.junit.Assert.assertEquals; +import static org.onap.appc.listener.TestUtil.JSON_INPUT_BODY_STR; +import static org.onap.appc.listener.TestUtil.JSON_OUTPUT_BODY_STR; +import static org.onap.appc.listener.TestUtil.buildDmaapIncomingMessage; +import static org.onap.appc.listener.TestUtil.buildDmaapOutgoingMessage; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import org.junit.Test; +import org.onap.appc.listener.LCM.model.DmaapIncomingMessage; +import org.onap.appc.listener.LCM.model.DmaapOutgoingMessage; +import org.onap.appc.listener.util.Mapper; +import org.onap.ccsdk.sli.core.sli.SvcLogicException; + +public class ConverterTest { + + private static final String EXPECTED_DMAAP_OUTGOING_MESSAGE_AS_JSON_STRING = + "{\"body\":{\"output\":{\"common-header\":" + + "{\"timestamp\":\"2016-08-03T08:50:18.97Z\",\"api-ver\":\"1\",\"flags\":{\"force\":\"TRUE\",\"ttl\":\"9900\"}," + + "\"sub-request-id\":\"1\",\"request-id\":\"123\",\"originator-id\":\"1\"},\"locked\":\"test-locked\",\"" + + "status\":{\"message\":\"test message\",\"code\":200}}},\"cambria.partition\":\"MSO\",\"rpc-name\":\"test\"}"; + + @Test(expected = IllegalArgumentException.class) + public void convertJsonNodeToDmaapOutgoingMessage_should_throw_when_given_null_arguments() { + + Converter.convertJsonNodeToDmaapOutgoingMessage(null, null); + } + + @Test + public void convertJsonNodeToDmaapOutgoingMessage_should_convert_to_outgoing_message() { + + DmaapIncomingMessage message = new DmaapIncomingMessage(); + message.setRpcName("test"); + message.setCorrelationID("test-1"); + message.setVersion("v1"); + JsonNode jsonNode = Mapper.toJsonNodeFromJsonString(JSON_INPUT_BODY_STR); + message.setBody(jsonNode); + + DmaapOutgoingMessage result = Converter.convertJsonNodeToDmaapOutgoingMessage(message, jsonNode); + + assertEquals("test", result.getRpcName()); + assertEquals("test-1", result.getCorrelationID()); + assertEquals("v1", result.getVersion()); + assertEquals(jsonNode, result.getBody()); + } + + @Test(expected = IllegalArgumentException.class) + public void convertDmaapOutgoingMessageToJsonString_should_throw_when_given_null_arguments() + throws JsonProcessingException { + + Converter.convertDmaapOutgoingMessageToJsonString(null); + } + + @Test + public void convertDmaapOutgoingMessageToJsonString_should_return_converted_json_string() + throws JsonProcessingException { + + DmaapOutgoingMessage message = new DmaapOutgoingMessage(); + message.setRpcName("test"); + JsonNode jsonNode = Mapper.toJsonNodeFromJsonString(JSON_OUTPUT_BODY_STR); + message.setBody(jsonNode); + + assertEquals(EXPECTED_DMAAP_OUTGOING_MESSAGE_AS_JSON_STRING, + Converter.convertDmaapOutgoingMessageToJsonString(message)); + } + + @Test(expected = IllegalArgumentException.class) + public void buildDmaapOutgoingMessageWithUnexpectedErrorTest_should_throw_given_null_arguments() + throws JsonProcessingException { + + Converter.buildDmaapOutgoingMessageWithUnexpectedError(null, null); + } + + @Test + public void buildDmaapOutgoingMessageWithUnexpectedErrorTest_should_build_valid_outgoing_message() + throws JsonProcessingException { + + DmaapIncomingMessage dmaapIncomingMessage = buildDmaapIncomingMessage(); + String errMsg = "TestException"; + DmaapOutgoingMessage dmaapOutgoingMessage = Converter + .buildDmaapOutgoingMessageWithUnexpectedError(dmaapIncomingMessage, new Exception(errMsg)); + int code = dmaapOutgoingMessage.getBody().get("output").get("status").get("code").asInt(); + String value = dmaapOutgoingMessage.getBody().get("output").get("status").get("value").asText(); + assertEquals(200, code); + assertEquals(errMsg, value); + } + + + @Test(expected = IllegalArgumentException.class) + public void extractRequestIdWithSubId_should_throw_given_null_argument() throws SvcLogicException { + + Converter.extractRequestIdWithSubId(null); + } + + @Test + public void extractRequestIdWithSubIdTest_should_extract_id_with_subDd() throws SvcLogicException { + DmaapIncomingMessage dmaapIncomingMessage = buildDmaapIncomingMessage(); + + String requestIdWithSubId = Converter.extractRequestIdWithSubId(dmaapIncomingMessage.getBody()); + assertEquals("123-1", requestIdWithSubId); + } + + + @Test(expected = IllegalArgumentException.class) + public void extractStatusCode_should_throw_given_null_argument() { + Converter.extractStatusCode(null); + } + + + @Test + public void extractStatusCode_should_extract_valid_status_code() { + DmaapOutgoingMessage dmaapOutgoingMessage = buildDmaapOutgoingMessage(); + Integer statusCode = Converter.extractStatusCode(dmaapOutgoingMessage.getBody()); + assertEquals(200L, statusCode.longValue()); + } + + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/impl/ListenerImplTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/impl/ListenerImplTest.java new file mode 100644 index 000000000..900e9c5fc --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/impl/ListenerImplTest.java @@ -0,0 +1,97 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM.impl; + +import static org.junit.Assert.fail; + +import java.util.Properties; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.onap.appc.listener.Listener; +import org.onap.appc.listener.ListenerProperties; +import org.onap.appc.listener.demo.impl.ListenerImpl; + +@Ignore +public class ListenerImplTest { + + private static final String PROP_FILE = "/org/onap/appc/default.properties"; + + private Listener listener; + private Properties props; + + @Before + public void setup() { + props = new Properties(); + try { + props.load(getClass().getResourceAsStream(PROP_FILE)); + props.setProperty("topic.read", "DCAE-CLOSED-LOOP-EVENTS-DEV1510SIM"); + } catch (Exception e) { + e.printStackTrace(); + fail("Failed to setup test: " + e.getMessage()); + } + listener = new ListenerImpl(new ListenerProperties("appc.ClosedLoop", props)); + } + + @Test + public void testRun() { + try { + Thread t = new Thread(listener); + t.start(); + + Thread.sleep(5000); + + listener.stopNow(); + + System.out.println(listener.getBenchmark()); + + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + @Test + public void printSampleData() { + try { + props.setProperty("threads.queuesize.min", "1"); + props.setProperty("threads.queuesize.max", "1"); + props.setProperty("threads.poolsize.min", "1"); + props.setProperty("threads.poolsize.max", "1"); + + Thread t = new Thread(listener); + t.start(); + + Thread.sleep(2000); + + listener.stop(); + + System.out.println(listener.getBenchmark()); + + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/impl/WorkerImplTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/impl/WorkerImplTest.java new file mode 100644 index 000000000..e6d08fba7 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/impl/WorkerImplTest.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2018 Nokia Solutions and Networks + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ +package org.onap.appc.listener.LCM.impl; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.onap.appc.listener.TestUtil.JSON_OUTPUT_BODY_STR; +import static org.onap.appc.listener.TestUtil.buildDmaapMessage; + +import com.fasterxml.jackson.databind.JsonNode; +import org.junit.Test; +import org.onap.appc.exceptions.APPCException; +import org.onap.appc.listener.EventHandler; +import org.onap.appc.listener.LCM.operation.ProviderOperations; +import org.onap.appc.listener.util.Mapper; + +public class WorkerImplTest { + + private EventHandler mockEventHandler = mock(EventHandler.class); + private ProviderOperations mockProviderOperations = mock(ProviderOperations.class); + + + @Test(expected = IllegalStateException.class) + public void should_throw_when_one_of_worker_fields_is_null() { + + WorkerImpl worker = new WorkerImpl(null, mockEventHandler, mockProviderOperations); + worker.run(); + } + + @Test + public void should_post_error_message_to_dmaap_on_exception() throws APPCException { + + when(mockProviderOperations.topologyDG(anyString(), any(JsonNode.class))) + .thenThrow(new RuntimeException("test exception")); + + WorkerImpl worker = new WorkerImpl(buildDmaapMessage(), mockEventHandler, mockProviderOperations); + worker.run(); + + verify(mockEventHandler).postStatus(anyString(), anyString()); + } + + + @Test + public void should_post_message_to_dmaap_on_successful_run() throws APPCException { + + JsonNode testOutputJsonNode = Mapper.toJsonNodeFromJsonString(JSON_OUTPUT_BODY_STR); + when(mockProviderOperations.topologyDG(anyString(), any(JsonNode.class))) + .thenReturn(testOutputJsonNode); + + WorkerImpl worker = new WorkerImpl(buildDmaapMessage(), mockEventHandler, mockProviderOperations); + worker.run(); + + verify(mockEventHandler).postStatus(anyString(), anyString()); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/ActionIdentifiersTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/ActionIdentifiersTest.java new file mode 100644 index 000000000..4c826b2d2 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/ActionIdentifiersTest.java @@ -0,0 +1,70 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2018 Nokia Solutions and Networks + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ +package org.onap.appc.listener.LCM.model; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +public class ActionIdentifiersTest { + + private ActionIdentifiers actionIdentifiers; + + + @Before + public void setup(){ + actionIdentifiers = new ActionIdentifiers(); + } + + @Test + public void should_set_properties(){ + + actionIdentifiers.setServiceInstanceId("test-instance-id"); + actionIdentifiers.setVnfID("test-vnf-id"); + actionIdentifiers.setVnfcName("test-name"); + actionIdentifiers.setVserverId("test-vserver-id"); + + + assertEquals("test-instance-id", actionIdentifiers.getServiceInstanceId()); + assertEquals("test-vnf-id", actionIdentifiers.getVnfID()); + assertEquals("test-name", actionIdentifiers.getVnfcName()); + assertEquals("test-vserver-id", actionIdentifiers.getVserverId()); + } + + @Test + public void should_initialize_parameters_from_constructor(){ + + actionIdentifiers.setServiceInstanceId("test-instance-id"); + actionIdentifiers.setVnfID("test-vnf-id"); + actionIdentifiers.setVnfcName("test-name"); + actionIdentifiers.setVserverId("test-vserver-id"); + + ActionIdentifiers testObject = new ActionIdentifiers(actionIdentifiers); + + assertEquals("test-instance-id", testObject.getServiceInstanceId()); + assertEquals("test-vnf-id", testObject.getVnfID()); + assertEquals("test-name", testObject.getVnfcName()); + assertEquals("test-vserver-id", testObject.getVserverId()); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/CommonHeaderTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/CommonHeaderTest.java new file mode 100644 index 000000000..7e834b28e --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/CommonHeaderTest.java @@ -0,0 +1,91 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2018 Nokia Solutions and Networks + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ +package org.onap.appc.listener.LCM.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import java.util.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; + +public class CommonHeaderTest { + + private CommonHeader commonHeader; + + @Before + public void setup() { + commonHeader = new CommonHeader(); + } + + @Test + public void should_set_properties() { + + commonHeader.setTimeStamp("test-timestamp"); + commonHeader.setApiVer("test-api-version"); + commonHeader.setOriginatorId("test-originator-id"); + commonHeader.setRequestID("test-request-id"); + commonHeader.setSubRequestId("test-subrequest-id"); + + Map<String, String> flags = new HashMap<>(); + flags.put("key1", "flag1"); + flags.put("key2", "flag2"); + flags.put("key3", "flag3"); + + commonHeader.setFlags(flags); + + assertEquals("test-timestamp", commonHeader.getTimeStamp()); + assertEquals("test-api-version", commonHeader.getApiVer()); + assertEquals("test-originator-id", commonHeader.getOriginatorId()); + assertEquals("test-request-id", commonHeader.getRequestID()); + assertEquals("test-subrequest-id", commonHeader.getSubRequestId()); + assertEquals(flags, commonHeader.getFlags()); + } + + @Test + public void should_initialize_parameters_from_constructor() { + + commonHeader.setTimeStamp("test-timestamp"); + commonHeader.setApiVer("test-api-version"); + commonHeader.setOriginatorId("test-originator-id"); + commonHeader.setRequestID("test-request-id"); + commonHeader.setSubRequestId("test-subrequest-id"); + + Map<String, String> flags = new HashMap<>(); + flags.put("key1", "flag1"); + flags.put("key2", "flag2"); + flags.put("key3", "flag3"); + + commonHeader.setFlags(flags); + + CommonHeader testObject = new CommonHeader(commonHeader); + + assertNotEquals(commonHeader.getTimeStamp(), testObject.getTimeStamp()); + assertEquals(commonHeader.getApiVer(), testObject.getApiVer()); + assertEquals(commonHeader.getOriginatorId(), testObject.getOriginatorId()); + assertEquals(commonHeader.getRequestID(), testObject.getRequestID()); + assertEquals(commonHeader.getSubRequestId(), testObject.getSubRequestId()); + assertEquals(commonHeader.getFlags(), testObject.getFlags()); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/DmaapIncomingMessageTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/DmaapIncomingMessageTest.java new file mode 100644 index 000000000..40b88e5df --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/DmaapIncomingMessageTest.java @@ -0,0 +1,70 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2018 Nokia Solutions and Networks + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ +package org.onap.appc.listener.LCM.model; + +import static org.junit.Assert.assertEquals; +import static org.onap.appc.listener.TestUtil.JSON_INPUT_BODY_STR; + +import com.fasterxml.jackson.databind.JsonNode; +import org.junit.Before; +import org.junit.Test; +import org.onap.appc.listener.util.Mapper; + +public class DmaapIncomingMessageTest { + + private DmaapIncomingMessage dmaapIncomingMessage; + + @Before + public void setup() { + dmaapIncomingMessage = new DmaapIncomingMessage(); + } + + @Test + public void should_set_default_cambria_partition_when_initialized() { + + assertEquals("APP-C", dmaapIncomingMessage.getCambriaPartition()); + } + + @Test + public void toString_should_return_valid_string_representation() { + JsonNode jsonNode = Mapper.toJsonNodeFromJsonString(JSON_INPUT_BODY_STR); + + dmaapIncomingMessage.setVersion("test-version"); + dmaapIncomingMessage.setType("test-type"); + dmaapIncomingMessage.setCorrelationID("test-correlation-id"); + dmaapIncomingMessage.setCambriaPartition("test-cambria-partition"); + dmaapIncomingMessage.setRpcName("test-rpc-name"); + dmaapIncomingMessage.setBody(jsonNode); + + assertEquals("DmaapIncomingMessage{DmaapMessage{" + + "version='" + dmaapIncomingMessage.getVersion() + '\'' + + ", type='" + dmaapIncomingMessage.getType() + '\'' + + ", correlationId='" + dmaapIncomingMessage.getCorrelationID() + '\'' + + ", cambriaPartition='" + dmaapIncomingMessage.getCambriaPartition() + '\'' + + ", rpcName='" + dmaapIncomingMessage.getRpcName() + '\'' + + ", body=" + dmaapIncomingMessage.getBody() + + "}}", dmaapIncomingMessage.toString()); + } + + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/DmaapMessageTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/DmaapMessageTest.java new file mode 100644 index 000000000..0c204df88 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/DmaapMessageTest.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2018 Nokia Solutions and Networks + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ +package org.onap.appc.listener.LCM.model; + +import static org.junit.Assert.assertEquals; +import static org.onap.appc.listener.TestUtil.JSON_INPUT_BODY_STR; + +import com.fasterxml.jackson.databind.JsonNode; +import org.junit.Before; +import org.junit.Test; +import org.onap.appc.listener.util.Mapper; + +public class DmaapMessageTest { + + private DmaapMessage dmaapMessage; + + @Before + public void setup() { + dmaapMessage = new DmaapMessage(); + } + + @Test + public void should_set_properties() { + + JsonNode jsonNode = Mapper.toJsonNodeFromJsonString(JSON_INPUT_BODY_STR); + + dmaapMessage.setVersion("test-version"); + dmaapMessage.setType("test-type"); + dmaapMessage.setCorrelationID("test-correlation-id"); + dmaapMessage.setCambriaPartition("test-cambria-partition"); + dmaapMessage.setRpcName("test-rpc-name"); + dmaapMessage.setBody(jsonNode); + + assertEquals("test-version", dmaapMessage.getVersion()); + assertEquals("test-type", dmaapMessage.getType()); + assertEquals("test-correlation-id", dmaapMessage.getCorrelationID()); + assertEquals("test-cambria-partition", dmaapMessage.getCambriaPartition()); + assertEquals("test-rpc-name", dmaapMessage.getRpcName()); + assertEquals(jsonNode, dmaapMessage.getBody()); + } + + @Test + public void toString_should_return_valid_string_representation() { + JsonNode jsonNode = Mapper.toJsonNodeFromJsonString(JSON_INPUT_BODY_STR); + + dmaapMessage.setVersion("test-version"); + dmaapMessage.setType("test-type"); + dmaapMessage.setCorrelationID("test-correlation-id"); + dmaapMessage.setCambriaPartition("test-cambria-partition"); + dmaapMessage.setRpcName("test-rpc-name"); + dmaapMessage.setBody(jsonNode); + + assertEquals("DmaapMessage{" + + "version='" + dmaapMessage.getVersion() + '\'' + + ", type='" + dmaapMessage.getType() + '\'' + + ", correlationId='" + dmaapMessage.getCorrelationID() + '\'' + + ", cambriaPartition='" + dmaapMessage.getCambriaPartition() + '\'' + + ", rpcName='" + dmaapMessage.getRpcName() + '\'' + + ", body=" + dmaapMessage.getBody() + + '}', dmaapMessage.toString()); + } +} + diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/DmaapOutgoingMessageTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/DmaapOutgoingMessageTest.java new file mode 100644 index 000000000..d3f72ee50 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/DmaapOutgoingMessageTest.java @@ -0,0 +1,68 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2018 Nokia Solutions and Networks + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ +package org.onap.appc.listener.LCM.model; + +import static org.junit.Assert.assertEquals; +import static org.onap.appc.listener.TestUtil.JSON_INPUT_BODY_STR; + +import com.fasterxml.jackson.databind.JsonNode; +import org.junit.Before; +import org.junit.Test; +import org.onap.appc.listener.util.Mapper; + +public class DmaapOutgoingMessageTest { + + private DmaapOutgoingMessage dmaapOutgoingMessage; + + @Before + public void setup() { + dmaapOutgoingMessage = new DmaapOutgoingMessage(); + } + + @Test + public void should_set_default_cambria_partition_when_initialized() { + + assertEquals("MSO", dmaapOutgoingMessage.getCambriaPartition()); + } + + @Test + public void toString_should_return_valid_string_representation() { + JsonNode jsonNode = Mapper.toJsonNodeFromJsonString(JSON_INPUT_BODY_STR); + + dmaapOutgoingMessage.setVersion("test-version"); + dmaapOutgoingMessage.setType("test-type"); + dmaapOutgoingMessage.setCorrelationID("test-correlation-id"); + dmaapOutgoingMessage.setCambriaPartition("test-cambria-partition"); + dmaapOutgoingMessage.setRpcName("test-rpc-name"); + dmaapOutgoingMessage.setBody(jsonNode); + + assertEquals("DmaapOutgoingMessage{DmaapMessage{" + + "version='" + dmaapOutgoingMessage.getVersion() + '\'' + + ", type='" + dmaapOutgoingMessage.getType() + '\'' + + ", correlationId='" + dmaapOutgoingMessage.getCorrelationID() + '\'' + + ", cambriaPartition='" + dmaapOutgoingMessage.getCambriaPartition() + '\'' + + ", rpcName='" + dmaapOutgoingMessage.getRpcName() + '\'' + + ", body=" + dmaapOutgoingMessage.getBody() + + "}}", dmaapOutgoingMessage.toString()); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/InputBodyTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/InputBodyTest.java new file mode 100644 index 000000000..21a95955c --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/InputBodyTest.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2018 Nokia Solutions and Networks + * ============================================================================= + * Modifications Copyright (C) 2019 IBM. + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ +package org.onap.appc.listener.LCM.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.onap.appc.listener.TestUtil.buildActionIdentifiers; +import static org.onap.appc.listener.TestUtil.buildCommonHeader; + +import org.junit.Before; +import org.junit.Test; + +public class InputBodyTest { + + private InputBody inputBody; + + @Before + public void setup() { + inputBody = new InputBody(); + } + + @Test + public void should_set_properties() { + + CommonHeader testCommonHeader = buildCommonHeader(); + ActionIdentifiers testActionIdentifiers = buildActionIdentifiers(); + + inputBody.setCommonHeader(testCommonHeader); + inputBody.setActionIdentifiers(testActionIdentifiers); + inputBody.setAction("test-action"); + inputBody.setPayload("{\"payload\": \"value\""); + + assertEquals(testCommonHeader, inputBody.getCommonHeader()); + assertEquals(testActionIdentifiers, inputBody.getActionIdentifiers()); + assertEquals("test-action", inputBody.getAction()); + assertEquals("{\"payload\": \"value\"", inputBody.getPayload()); + } + + @Test + public void should_verify_if_is_valid() { + + assertFalse(inputBody.isValid()); + inputBody.setCommonHeader(buildCommonHeader()); + assertTrue(inputBody.isValid()); + } + + @Test + public void testPayLoadAsString() + { + inputBody.setPayloadAsString("payload"); + assertEquals("payload", inputBody.getPayload()); + } + + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/OutputBodyTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/OutputBodyTest.java new file mode 100644 index 000000000..27913284b --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/OutputBodyTest.java @@ -0,0 +1,95 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2018 Nokia Solutions and Networks + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ +package org.onap.appc.listener.LCM.model; + +import static junit.framework.TestCase.assertNotNull; +import static org.junit.Assert.assertEquals; +import static org.onap.appc.listener.TestUtil.buildCommonHeader; + +import java.util.HashMap; +import java.util.Map; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; + +public class OutputBodyTest { + + private OutputBody outputBody; + + @Before + public void setup() { + outputBody = new OutputBody(); + } + + @Test + public void should_set_properties() { + + CommonHeader testCommonHeader = buildCommonHeader(); + ResponseStatus testResponseStatus = new ResponseStatus(200, "OK"); + + outputBody.setHeader(testCommonHeader); + outputBody.setStatus(testResponseStatus); + outputBody.setLocked("test-locked"); + outputBody.setPayload("{\"payload\": \"value\""); + + assertEquals(testCommonHeader, outputBody.getHeader()); + assertEquals(testResponseStatus, outputBody.getStatus()); + assertEquals("test-locked", outputBody.getLocked()); + assertEquals("{\"payload\": \"value\"", outputBody.getPayload()); + } + + + @Test + public void should_inherit_input_body_header_when_initialized_from_constructor() { + + InputBody testInputBody = new InputBody(); + CommonHeader testCommonHeader = buildCommonHeader(); + testInputBody.setCommonHeader(testCommonHeader); + + outputBody = new OutputBody(testInputBody); + + assertNotNull(outputBody.getHeader()); + assertEquals(testCommonHeader.getFlags(), outputBody.getHeader().getFlags()); + assertEquals(testCommonHeader.getSubRequestId(), outputBody.getHeader().getSubRequestId()); + assertEquals(testCommonHeader.getRequestID(), outputBody.getHeader().getRequestID()); + assertEquals(testCommonHeader.getOriginatorId(), outputBody.getHeader().getOriginatorId()); + assertEquals(testCommonHeader.getApiVer(), outputBody.getHeader().getApiVer()); + } + + @Test + public void toResponse_should_convert_to_json_object() { + CommonHeader testCommonHeader = buildCommonHeader(); + ResponseStatus testResponseStatus = new ResponseStatus(200, "OK"); + + outputBody.setHeader(testCommonHeader); + outputBody.setStatus(testResponseStatus); + outputBody.setLocked("test-locked"); + outputBody.setPayload("{\"payload\": \"value\""); + + JSONObject response = outputBody.toResponse(); + assertNotNull(response); + + assertEquals("test-locked", response.get("locked")); + assertEquals("{\"payload\": \"value\"", response.get("payload")); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/ResponseStatusTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/ResponseStatusTest.java new file mode 100644 index 000000000..1283643bf --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/model/ResponseStatusTest.java @@ -0,0 +1,56 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2018 Nokia Solutions and Networks + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ +package org.onap.appc.listener.LCM.model; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +public class ResponseStatusTest { + + private ResponseStatus responseStatus; + + @Before + public void setup() { + responseStatus = new ResponseStatus(); + } + + @Test + public void should_set_properties() { + + responseStatus.setCode(200); + responseStatus.setValue("OK"); + + assertEquals(Integer.valueOf(200), responseStatus.getCode()); + assertEquals("OK", responseStatus.getValue()); + } + + @Test + public void should_initialize_parameters_from_constructor() { + responseStatus = new ResponseStatus(200, "OK"); + + assertEquals(Integer.valueOf(200), responseStatus.getCode()); + assertEquals("OK", responseStatus.getValue()); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/operation/GenericProviderOperationsRequestFormatterTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/operation/GenericProviderOperationsRequestFormatterTest.java new file mode 100644 index 000000000..a6d1bb9d1 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/operation/GenericProviderOperationsRequestFormatterTest.java @@ -0,0 +1,93 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2018 Nokia Solutions and Networks + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ +package org.onap.appc.listener.LCM.operation; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.onap.appc.listener.TestUtil.JSON_OUTPUT_BODY_STR; + +import com.fasterxml.jackson.databind.JsonNode; +import java.net.MalformedURLException; +import java.net.URL; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.onap.appc.exceptions.APPCException; +import org.onap.appc.listener.LCM.model.InputBody; +import org.onap.appc.listener.LCM.model.ResponseStatus; +import org.onap.appc.listener.util.Mapper; + +public class GenericProviderOperationsRequestFormatterTest { + + private static final String INVALID_JSON_OUTPUT_BODY_STR = + "{\"output\":{\"common-header\":{\"timestamp\":\"2016-08-03T08:50:18.97Z\"," + + "\"api-ver\":\"1\",\"flags\":{\"force\":\"TRUE\",\"ttl\":\"9900\"},\"sub-request-id\":\"1\"," + + "\"request-id\":\"123\",\"originator-id\":\"1\"}}}"; + + private GenericProviderOperationRequestFormatter requestFormatter; + + + @Before + public void setup() { + requestFormatter = new GenericProviderOperationRequestFormatter(); + } + + @Test + public void should_build_path() throws MalformedURLException { + String result = requestFormatter.buildPath(new URL("http://127.0.0.1/abc/def"), "test"); + assertEquals("/abc/def:test", result); + } + + @Test + public void should_build_request_json() { + InputBody inputBody = new InputBody(); + inputBody.setPayload("\"key1\": \"value1\", \"key2\": \"value2\""); + + assertEquals("{\"input\": {\"payload\":\"\\\"key1\\\": \\\"value1\\\", \\\"key2\\\": \\\"value2\\\"\"}}", + requestFormatter.buildRequest(inputBody)); + } + + @Test(expected = APPCException.class) + public void should_throw_when_invalid_json() throws APPCException { + + JsonNode jsonNode = Mapper.toJsonNodeFromJsonString(INVALID_JSON_OUTPUT_BODY_STR); + requestFormatter.getResponseStatus(jsonNode); + } + + @Test + public void should_extract_response_status() throws APPCException { + + JsonNode jsonNode = Mapper.toJsonNodeFromJsonString(JSON_OUTPUT_BODY_STR); + ResponseStatus status = requestFormatter.getResponseStatus(jsonNode); + + assertEquals("test message", status.getValue()); + assertEquals(Integer.valueOf(200), status.getCode()); + } + + @Test + public void should_return_extract_locked_field() throws APPCException { + + assertNull(requestFormatter.getLocked(new JSONObject(INVALID_JSON_OUTPUT_BODY_STR))); + assertEquals("test-locked", requestFormatter.getLocked(new JSONObject(JSON_OUTPUT_BODY_STR))); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/operation/ProviderOperationsTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/operation/ProviderOperationsTest.java new file mode 100644 index 000000000..fc6c14d16 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM/operation/ProviderOperationsTest.java @@ -0,0 +1,136 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2018 Nokia Solutions and Networks + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ +package org.onap.appc.listener.LCM.operation; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import org.apache.commons.codec.binary.Base64; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.Socket; +import java.net.SocketException; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.client.HttpClient; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.onap.appc.exceptions.APPCException; +import org.onap.appc.listener.LCM.operation.ProviderOperations.MySSLSocketFactory; + +public class ProviderOperationsTest { + + private ProviderOperations providerOperations; + private MySSLSocketFactory socketFactory; + + @Mock + private KeyStore mockKeyStore; + + + @Before + public void setup() + throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException { + + providerOperations = + new ProviderOperations("http://127.0.0.1", "test_user", "test_password"); + socketFactory = new MySSLSocketFactory(mockKeyStore); + } + + @Test + public void setAuthentication_should_return_null_given_null_arguments() { + String newAuthentication = providerOperations.setAuthentication(null, null); + assertNull(newAuthentication); + } + + @Test + public void should_set_properties() { + providerOperations.setUrl("hp://123.1.2.3"); + assertEquals("http://127.0.0.1", providerOperations.getUrl()); + providerOperations.setUrl("http://123.1.2.3"); + assertEquals("http://123.1.2.3", providerOperations.getUrl()); + + String newAuthentication = providerOperations.setAuthentication("new_user", "new_password"); + String authStr = "new_user:new_password"; + assertEquals(new String(Base64.encodeBase64(authStr.getBytes())), newAuthentication); + } + + @Test + public void isSucceeded_should_resolve_status_codes() { + + assertFalse(ProviderOperations.isSucceeded(null)); + assertFalse(ProviderOperations.isSucceeded(200)); + assertTrue(ProviderOperations.isSucceeded(100)); + assertTrue(ProviderOperations.isSucceeded(400)); + } + + @Test(expected = APPCException.class) + public void topologyDG_should_throw_given_null_message() throws APPCException { + + providerOperations.topologyDG("test-rpc-name", null); + } + + @Test(expected = SocketException.class) + public void sslSocketFactory_should_throw_when_socket_not_connected() throws IOException { + Socket socket = socketFactory.createSocket(); + assertNotNull(socket); + + socketFactory.createSocket(socket, "127.0.0.1", 123, true); + } + + //TODO write some test cases for topologyDG method + @Test + public void testBuildPostRequest() throws JsonProcessingException, IOException, APPCException { + String jsonString = "{\"output\":{\"status\":{\"code\":\"200\",\"message\":\"TEST_MESSAGE\"}}}"; + providerOperations = Mockito.spy( + new ProviderOperations("http://127.0.0.1", "test_user", "test_password")); + HttpClient httpClient = Mockito.mock(HttpClient.class); + HttpResponse httpResponse = Mockito.mock(HttpResponse.class); + StatusLine statusLine = Mockito.mock(StatusLine.class); + Mockito.when(statusLine.getStatusCode()).thenReturn(200); + Mockito.when(httpResponse.getStatusLine()).thenReturn(statusLine); + HttpEntity httpEntity = Mockito.mock(HttpEntity.class); + InputStream inputStream = new ByteArrayInputStream(jsonString.getBytes()); + Mockito.when(httpEntity.getContent()).thenReturn(inputStream); + Mockito.when(httpResponse.getEntity()).thenReturn(httpEntity); + Mockito.when(httpClient.execute(Mockito.any())).thenReturn(httpResponse); + Mockito.when(providerOperations.getHttpClient()).thenReturn(httpClient); + ObjectMapper mapper = new ObjectMapper(); + JsonNode jsonNode = mapper.readTree(jsonString); + assertEquals(ObjectNode.class, providerOperations.topologyDG(null, jsonNode).getClass()); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM1607/model/TestJsonGenericMessages.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM1607/model/TestJsonGenericMessages.java new file mode 100644 index 000000000..b17789115 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/LCM1607/model/TestJsonGenericMessages.java @@ -0,0 +1,101 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.LCM1607.model; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Assert; +import org.junit.Test; +import org.onap.appc.listener.util.Mapper; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + + +public class TestJsonGenericMessages {/* + + @Test + public void serializeIncomingMessage() { + + final String expectedJson = "{\"CommonHeader\":{\"TimeStamp\":\"2016-05-02 19:50:37.09\",\"TransactionID\":\"1\",\"APIver\":\"1.01\",\"RequestTrack\":[\"1\",\"4\",\"12\",\"3\"],\"Flags\":null,\"SubrequestID\":null,\"OriginatorID\":\"2\"},\"Payload\":\"{ \\\"command\\\": \\\"start\\\", \\\"target-id\\\": \\\"111\\\", \\\"flag10\\\": {\\\"object-1\\\": {\\\"key-1\\\": \\\"key\\\", \\\"value-1\\\": \\\"value\\\" }} }\",\"Action\":\"CONFIGURE\",\"ObjectID\":\"200\",\"TargetID\":\"100\"}"; + InputBody msg = createIncomingMessage(); + + String json = Mapper.toJsonObject(msg).toString(); + //System.out.println(json); + Assert.assertEquals(expectedJson, json); + } + + @Test + public void deserializeIncomingMessage() throws IOException { + final String originalJson = "{\"CommonHeader\":{\"TimeStamp\":\"2016-05-02 19:50:37.09\",\"TransactionID\":\"1\",\"Flags\":{\"FORCE\":\"Y\",\"TTL\":\"12\"},\"SubrequestID\":\"2345\",\"OriginatorID\":\"2\",\"APIver\":\"1.01\"}, \"Payload\": \" \\\"Graceful\\\" : \\\"Yes\\\" \",\"Action\":\"CONFIGURE\",\"ObjectID\":\"200\",\"TargetID\":\"100\"}"; + + ObjectMapper mapper = new ObjectMapper(); + InputBody msg = mapper.readValue(originalJson, InputBody.class); + + Assert.assertNotNull(msg); + Assert.assertEquals("2016-05-02 19:50:37.09", msg.getCommonHeader().getTimeStamp()); + Assert.assertEquals("1", msg.getCommonHeader().getRequestID()); + Assert.assertEquals("1.01", msg.getCommonHeader().getApiVer()); + Assert.assertEquals("200", msg.getObjectId()); + Assert.assertEquals("100", msg.getTargetId()); + Assert.assertEquals(" \"Graceful\" : \"Yes\" ", msg.getPayload()); + Assert.assertEquals("CONFIGURE", msg.getAction()); + + } + + @Test + public void serializeResponseMessage() { + InputBody imsg = createIncomingMessage(); + OutputBody omsg = new OutputBody(imsg); + omsg.setStatus(new ResponseStatus("200", "OK")); + + String json = Mapper.toJsonObject(omsg).toString(); + System.out.println(json); + //Assert.assertEquals(expectedJson, json); + Assert.assertNotEquals("", json); + + } + + private InputBody createIncomingMessage() { + InputBody msg = new InputBody(); + CommonHeader rh = new CommonHeader(); + rh.setTimeStamp("2016-05-02 19:50:37.09"); + rh.setApiVer("1.01"); + rh.setRequestID("1"); + rh.setOriginatorId("2"); + + + Map<String, String> flags = new HashMap<>(); + flags.put("FORCE", "Y"); + flags.put("TTL", "12"); + + msg.setCommonHeader(rh); + msg.setAction("CONFIGURE"); + msg.setTargetId("100"); + msg.setObjectId("200"); + msg.setPayloadAsString("{ \"command\": \"start\", \"target-id\": \"111\", \"flag10\": {\"object-1\": {\"key-1\": \"key\", \"value-1\": \"value\" }} }"); + return msg; + } +*/ +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/ListenerPropertiesTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/ListenerPropertiesTest.java new file mode 100644 index 000000000..c83555c50 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/ListenerPropertiesTest.java @@ -0,0 +1,156 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Properties; + +import org.junit.Before; +import org.junit.Test; +import org.onap.appc.adapter.factory.MessageService; +import org.onap.appc.listener.AbstractListener; +import org.onap.appc.listener.ListenerProperties; +import org.onap.appc.listener.ListenerProperties.KEYS; + +public class ListenerPropertiesTest { + + private Properties good, bad, both; + private String prefix; + + private ListenerProperties props; + + @Before + public void setup() { + prefix = "test"; + good = new Properties(); + bad = new Properties(); + both = new Properties(); + + good.setProperty(String.format("%s.%s", prefix, "a"), "1"); + good.setProperty(String.format("%s.%s", prefix, "a.b"), "2"); + good.setProperty(String.format("%s.%s", prefix, "a.b.c"), "3"); + + bad.setProperty(prefix, "NA"); + bad.setProperty(prefix + ".", "NA"); + bad.setProperty(String.format("%s.%s", prefix + "x", "bad"), "NA"); + bad.setProperty(String.format("%s.%s", "x" + prefix, "bad"), "NA"); + + for (String key : good.stringPropertyNames()) { + both.put(key, good.getProperty(key)); + } + for (String key : bad.stringPropertyNames()) { + both.put(key, bad.getProperty(key)); + } + + props = new ListenerProperties(prefix, both); + } + + @Test + public void testConstructor() { + props = new ListenerProperties(prefix, good); + assertEquals(prefix, props.getPrefix()); + assertEquals(good.size(), props.getProperties().size()); + + props = new ListenerProperties(prefix, bad); + assertEquals(prefix, props.getPrefix()); + assertTrue(props.getProperties().isEmpty()); + + props = new ListenerProperties(prefix, both); + assertEquals(prefix, props.getPrefix()); + assertEquals(good.size(), props.getProperties().size()); + + for (Object val : props.getProperties().values()) { + assertFalse("NA".equals(val.toString())); + } + + assertTrue(props.toString().contains(prefix)); + } + + @Test + public void testGetClass() { + assertNull(props.getListenerClass()); + props.setListenerClass(AbstractListener.class); + assertNotNull(props.getListenerClass()); + assertEquals(AbstractListener.class, props.getListenerClass()); + } + + @Test + public void testMessageServices() { + // Hardcode count so tests must be updated when values are added + assertEquals(1, MessageService.values().length); + + // Bad Input + MessageService def = MessageService.DMaaP; + assertEquals(def, MessageService.parse(null)); + assertEquals(def, MessageService.parse("")); + assertEquals(def, MessageService.parse("NotDMaaP")); + + // DMaaP case sensitivity + assertEquals(MessageService.DMaaP, MessageService.parse("dmaap")); + assertEquals(MessageService.DMaaP, MessageService.parse("DMAAP")); + assertEquals(MessageService.DMaaP, MessageService.parse("DMaaP")); + } + + @Test + public void testKeys() { + // Hardcode count so tests must be updated when values are added + assertEquals(19, ListenerProperties.KEYS.values().length); + + Properties tmp = new Properties(); + try { + tmp.load(getClass().getResourceAsStream("/org/onap/appc/default.properties")); + } catch (Exception e) { + fail("Could not load properties to test"); + } + String realPrefix = tmp.getProperty("test.prefix"); + assertNotNull(realPrefix); + props = new ListenerProperties(realPrefix, tmp); + + for (KEYS key : ListenerProperties.KEYS.values()) { + assertNotNull(key.getFullProp(realPrefix)); + assertNotNull(props.getProperty(key)); + assertNotNull(props.getProperty(key.getPropertySuffix())); + } + } + + @Test + public void testDisabled() throws Exception { + assertFalse(props.isDisabled()); + props.getProperties().put(KEYS.DISABLED.getPropertySuffix(), "TRUE"); + assertTrue(props.isDisabled()); + props.getProperties().put(KEYS.DISABLED.getPropertySuffix(), "N/A"); + assertFalse(props.isDisabled()); + props.getProperties().put(KEYS.DISABLED.getPropertySuffix(), "fAlse"); + assertFalse(props.isDisabled()); + props.getProperties().remove(KEYS.DISABLED.getPropertySuffix()); + assertFalse(props.isDisabled()); + } + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/TestUtil.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/TestUtil.java new file mode 100644 index 000000000..f28ad83b5 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/TestUtil.java @@ -0,0 +1,82 @@ +package org.onap.appc.listener; + +import com.fasterxml.jackson.databind.JsonNode; +import java.util.HashMap; +import java.util.Map; +import org.onap.appc.listener.LCM.model.ActionIdentifiers; +import org.onap.appc.listener.LCM.model.CommonHeader; +import org.onap.appc.listener.LCM.model.DmaapIncomingMessage; +import org.onap.appc.listener.LCM.model.DmaapMessage; +import org.onap.appc.listener.LCM.model.DmaapOutgoingMessage; +import org.onap.appc.listener.util.Mapper; + +public class TestUtil { + + public static final String JSON_INPUT_BODY_STR = + "{\"input\":{ \"common-header\": { \"timestamp\": \"2016-08-03T08:50:18.97Z\", " + + "\"api-ver\": \"1\", \"originator-id\": \"1\", \"request-id\": \"123\", \"sub-request-id\": \"1\", " + + "\"flags\": { \"force\":\"TRUE\", \"ttl\":\"9900\" } }, \"action\": \"Stop\", " + + "\"action-identifiers\": { \"vnf-id\": \"TEST\" } }}"; + + public static final String JSON_OUTPUT_BODY_STR = + "{\"output\":{\"common-header\":{\"timestamp\":\"2016-08-03T08:50:18.97Z\"," + + "\"api-ver\":\"1\",\"flags\":{\"force\":\"TRUE\",\"ttl\":\"9900\"},\"sub-request-id\":\"1\"," + + "\"request-id\":\"123\",\"originator-id\":\"1\"},\"locked\": \"test-locked\", " + + "\"status\":{\"message\":\"test message\",\"code\":200}}}"; + + public static DmaapMessage buildDmaapMessage() { + + DmaapMessage dmaapMessage = new DmaapMessage(); + dmaapMessage.setRpcName("test"); + JsonNode jsonNode = Mapper.toJsonNodeFromJsonString(JSON_INPUT_BODY_STR); + dmaapMessage.setBody(jsonNode); + return dmaapMessage; + } + + public static DmaapIncomingMessage buildDmaapIncomingMessage() { + DmaapIncomingMessage dmaapIncomingMessage = new DmaapIncomingMessage(); + dmaapIncomingMessage.setRpcName("test"); + JsonNode jsonNode = Mapper.toJsonNodeFromJsonString(JSON_INPUT_BODY_STR); + dmaapIncomingMessage.setBody(jsonNode); + return dmaapIncomingMessage; + + } + + public static DmaapOutgoingMessage buildDmaapOutgoingMessage() { + DmaapOutgoingMessage dmaapOutgoingMessage = new DmaapOutgoingMessage(); + dmaapOutgoingMessage.setRpcName("test"); + JsonNode jsonNode = Mapper.toJsonNodeFromJsonString(JSON_OUTPUT_BODY_STR); + dmaapOutgoingMessage.setBody(jsonNode); + return dmaapOutgoingMessage; + + } + + public static CommonHeader buildCommonHeader() { + + CommonHeader commonHeader = new CommonHeader(); + commonHeader.setTimeStamp("test-timestamp"); + commonHeader.setApiVer("test-api-version"); + commonHeader.setOriginatorId("test-originator-id"); + commonHeader.setRequestID("test-request-id"); + commonHeader.setSubRequestId("test-subrequest-id"); + + Map<String, String> flags = new HashMap<>(); + flags.put("key1", "flag1"); + flags.put("key2", "flag2"); + flags.put("key3", "flag3"); + + commonHeader.setFlags(flags); + return commonHeader; + } + + public static ActionIdentifiers buildActionIdentifiers() { + + ActionIdentifiers actionIdentifiers = new ActionIdentifiers(); + actionIdentifiers.setServiceInstanceId("test-instance-id"); + actionIdentifiers.setVnfID("test-vnf-id"); + actionIdentifiers.setVnfcName("test-name"); + actionIdentifiers.setVserverId("test-vserver-id"); + + return actionIdentifiers; + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/impl/TestProviderOperations.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/impl/TestProviderOperations.java new file mode 100644 index 000000000..55b0f2cb6 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/impl/TestProviderOperations.java @@ -0,0 +1,129 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Ericsson. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + * file except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.impl; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Mockito.when; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.internal.util.reflection.Whitebox; +import org.onap.appc.exceptions.APPCException; +import org.onap.appc.listener.demo.model.Action; +import org.onap.appc.listener.demo.model.CommonMessage.CommonHeader; +import org.onap.appc.listener.demo.model.CommonMessage.Payload; +import org.onap.appc.listener.demo.model.IncomingMessage; +import org.onap.appc.listener.util.HttpClientUtil; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(HttpClientUtil.class) +public class TestProviderOperations { + + private ProviderOperations providerOperations; + private IncomingMessage message; + private URL url; + private CommonHeader commonHeader; + private Payload payload; + private HttpClient httpClient; + private HttpResponse httpResponse; + private StatusLine statusLine; + private HttpEntity httpEntity; + private InputStream inputStream; + private String reponseMessage; + + @Before + public void setUp() throws Exception { + reponseMessage = "{\"output\":{\"common-response-header\":{\"success\":true,\"reason\":\"\"}}}"; + providerOperations = new ProviderOperations(); + PowerMockito.mockStatic(HttpClientUtil.class); + httpClient = PowerMockito.mock(HttpClient.class); + httpResponse = PowerMockito.mock(HttpResponse.class); + statusLine = PowerMockito.mock(StatusLine.class); + httpEntity = PowerMockito.mock(HttpEntity.class); + inputStream = new ByteArrayInputStream(reponseMessage.getBytes(StandardCharsets.UTF_8)); + message = Mockito.mock(IncomingMessage.class); + url = PowerMockito.mock(URL.class); + commonHeader = Mockito.mock(CommonHeader.class); + payload = Mockito.mock(Payload.class); + when(message.getAction()).thenReturn(Action.Evacuate); + when(message.getHeader()).thenReturn(commonHeader); + when(message.getPayload()).thenReturn(payload); + when(HttpClientUtil.getHttpClient("http")).thenReturn(httpClient); + when(httpClient.execute(anyObject())).thenReturn(httpResponse); + when(httpResponse.getStatusLine()).thenReturn(statusLine); + when(statusLine.getStatusCode()).thenReturn(200); + when(httpResponse.getEntity()).thenReturn(httpEntity); + when(httpEntity.getContent()).thenReturn(inputStream); + Whitebox.setInternalState(url, "protocol", "http"); + Whitebox.setInternalState(providerOperations, "url", url); + } + + @Test + public void testTopologyDG() throws APPCException, ClientProtocolException, IOException { + assertTrue(ProviderOperations.topologyDG(message)); + } + + @Test + public void testTopologyDGWithBaseAuth() + throws APPCException, ClientProtocolException, IOException { + ProviderOperations.setAuthentication("user", "password"); + ProviderOperations.setUrl("http://localhost:8080"); + assertTrue(ProviderOperations.topologyDG(message)); + } + + @Test(expected = APPCException.class) + public void testTopologyDGFail() throws APPCException, ClientProtocolException, IOException { + reponseMessage = + "{\"output\":{\"common-response-header\":{\"success\":false,\"reason\":\"\"}}}"; + inputStream = new ByteArrayInputStream(reponseMessage.getBytes(StandardCharsets.UTF_8)); + when(httpEntity.getContent()).thenReturn(inputStream); + ProviderOperations.topologyDG(message); + } + + @Test(expected = APPCException.class) + public void testTopologyDGInvalidResponse() + throws APPCException, ClientProtocolException, IOException { + reponseMessage = "{\"output\":{\"common-response-header\":{\"succss\":false,\"reason\":\"\"}}}"; + inputStream = new ByteArrayInputStream(reponseMessage.getBytes(StandardCharsets.UTF_8)); + when(httpEntity.getContent()).thenReturn(inputStream); + ProviderOperations.topologyDG(message); + } + + @Test(expected = APPCException.class) + public void testTopologyDGWithInvalidHttp() + throws APPCException, ClientProtocolException, IOException { + when(statusLine.getStatusCode()).thenReturn(500); + ProviderOperations.topologyDG(message); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/impl/TestWorkerImpl.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/impl/TestWorkerImpl.java new file mode 100644 index 000000000..e3f889c5e --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/impl/TestWorkerImpl.java @@ -0,0 +1,85 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Ericsson. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + * file except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.impl; + +import static org.mockito.Matchers.anyObject; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.times; + +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.onap.appc.exceptions.APPCException; +import org.onap.appc.listener.EventHandler; +import org.onap.appc.listener.demo.model.CommonMessage.CommonHeader; +import org.onap.appc.listener.demo.model.IncomingMessage; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(ProviderOperations.class) +public class TestWorkerImpl { + + private WorkerImpl workerImplSpy; + private IncomingMessage message; + private EventHandler dmaap; + + @Before + public void setUp() { + message = Mockito.mock(IncomingMessage.class); + dmaap = Mockito.mock(EventHandler.class); + workerImplSpy = Mockito.spy(new WorkerImpl(message, dmaap)); + } + + @Test + public void testRun() throws APPCException { + CommonHeader commonHeader = Mockito.mock(CommonHeader.class); + when(message.getHeader()).thenReturn(commonHeader); + when(commonHeader.getRequestID()).thenReturn("requestId"); + PowerMockito.mockStatic(ProviderOperations.class); + PowerMockito.when(ProviderOperations.topologyDG(anyObject())).thenReturn(true); + workerImplSpy.run(); + verify(workerImplSpy, times(1)).run(); + } + + @Test + public void testRunElseCase() throws APPCException { + CommonHeader commonHeader = Mockito.mock(CommonHeader.class); + when(message.getHeader()).thenReturn(commonHeader); + when(commonHeader.getRequestID()).thenReturn("requestId"); + when(message.toJson()).thenReturn(new JSONObject()); + PowerMockito.mockStatic(ProviderOperations.class); + PowerMockito.when(ProviderOperations.topologyDG(anyObject())).thenReturn(false); + workerImplSpy.run(); + verify(workerImplSpy, times(1)).run(); + } + + @Test + public void testRunWithException() throws APPCException { + CommonHeader commonHeader = Mockito.mock(CommonHeader.class); + when(message.getHeader()).thenReturn(commonHeader); + when(commonHeader.getRequestID()).thenReturn("requestId"); + workerImplSpy.run(); + verify(workerImplSpy, times(1)).run(); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/OutgoingMessageTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/OutgoingMessageTest.java new file mode 100644 index 000000000..b2838cb77 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/OutgoingMessageTest.java @@ -0,0 +1,91 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2019 Ericsson + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import org.apache.commons.io.IOUtils; +import org.hamcrest.CoreMatchers; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.onap.appc.listener.util.Mapper; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(Mapper.class) +public class OutgoingMessageTest { + + private IncomingMessage incomingMessage; + + @Before + public void setup() throws IOException { + String incomingStr = IOUtils.toString(getClass().getResourceAsStream("/IncomingMessagedemo.txt"), "UTF-8"); + incomingMessage = Mapper.mapOne(incomingStr, IncomingMessage.class); + } + + @Test + public void testOutgoingMessage() throws UnknownHostException { + InetAddress mockInetAddress = Mockito.mock(InetAddress.class); + Mockito.when(mockInetAddress.getCanonicalHostName()).thenReturn("TEST_CANONICAL_HOSTNAME"); + OutgoingMessage outgoingMessage = Mockito.spy(new OutgoingMessage(incomingMessage)); + PowerMockito.when(outgoingMessage.getLocalHost()).thenReturn(mockInetAddress); + outgoingMessage.updateResponseTime(); + assertEquals("appc@TEST_CANONICAL_HOSTNAME", outgoingMessage.generateFrom()); + } + + @Test + public void testOutgoingMessageUnknowHost() throws UnknownHostException { + OutgoingMessage outgoingMessage = Mockito.spy(new OutgoingMessage(incomingMessage)); + PowerMockito.when(outgoingMessage.getLocalHost()).thenThrow(new UnknownHostException()); + assertEquals("appc@UnknownHost", outgoingMessage.generateFrom()); + } + + @Test + public void testJson() { + PowerMockito.mockStatic(Mapper.class); + JSONObject mockObject = Mockito.mock(JSONObject.class); + PowerMockito.when(Mapper.toJsonObject(Mockito.any())).thenReturn(mockObject); + OutgoingMessage outgoingMessage = Mockito.spy(new OutgoingMessage(incomingMessage)); + assertEquals(mockObject, outgoingMessage.toResponse()); + } + + @Test + public void testSetResponse() { + OutgoingMessage outgoingMessage = new OutgoingMessage(incomingMessage); + outgoingMessage.setResponse(null); + assertEquals(new OutgoingMessage.OutStatus().getValue(), outgoingMessage.getStatus().getValue()); + outgoingMessage.setResponse(Status.ACCEPTED); + assertEquals("100", outgoingMessage.getStatus().getCode()); + outgoingMessage.setResponse(Status.FAILURE); + assertEquals("500", outgoingMessage.getStatus().getCode()); + outgoingMessage.setResponse(Status.SUCCESS); + assertEquals("400", outgoingMessage.getStatus().getCode()); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/TestCommonMessage.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/TestCommonMessage.java new file mode 100644 index 000000000..341492f26 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/TestCommonMessage.java @@ -0,0 +1,50 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2019 IBM. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.model; + +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Collection; + +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; + +public class TestCommonMessage { + + private CommonMessage commonMessage; + private CommonMessage.Payload payload; + + @Before + public void setUp() { + commonMessage = new CommonMessage(); + payload = new CommonMessage.Payload(); + } + + @Test + public void testToJson() { + assertTrue(commonMessage.toJson() instanceof JSONObject); + } + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/TestEnums.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/TestEnums.java new file mode 100644 index 000000000..2dbbdd64d --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/TestEnums.java @@ -0,0 +1,60 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.onap.appc.listener.demo.model.Action; +import org.onap.appc.listener.demo.model.Status; + +public class TestEnums { + + @Test + public void testAction() { + assertEquals(Action.Rebuild, Action.toAction("Rebuild")); + assertEquals(Action.Restart, Action.toAction("restart")); + assertEquals(Action.Migrate, Action.toAction("MIGRATE")); + assertEquals(Action.Evacuate, Action.toAction("Evacuate")); + assertNull(Action.toAction("Unknown")); + assertNull(Action.toAction(null)); + + assertEquals(6, Action.values().length); + } + + @Test + public void testStatus() { + + assertEquals(Status.ACCEPTED, Status.toStatus("accepted")); + assertEquals(Status.SUCCESS, Status.toStatus("SuCcEsS")); + assertEquals(Status.FAILURE, Status.toStatus("Failure")); + assertNull(Status.toStatus("Unknown")); + assertNull(Status.toStatus(null)); + + assertEquals(3, Status.values().length); + + } + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/TestIncomingMessage.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/TestIncomingMessage.java new file mode 100644 index 000000000..d8d0986ce --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/TestIncomingMessage.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2019 IBM. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.model; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +public class TestIncomingMessage { + + private IncomingMessage incomingMessage; + + @Before + public void setUp() { + incomingMessage = new IncomingMessage(); + } + + @Test + public void testToOutgoing() { + String expected = "{\"Status\":{\"Value\":null,\"Code\":null}}"; + assertEquals(expected, incomingMessage.toOutgoing(null)); + expected = "{\"Status\":{\"Value\":\""+Status.ACCEPTED.getValue()+"\",\"Code\":\"100\"}}"; + assertEquals(expected, incomingMessage.toOutgoing(Status.ACCEPTED)); + } + +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/TestMessages.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/TestMessages.java new file mode 100644 index 000000000..9cce23d95 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/demo/model/TestMessages.java @@ -0,0 +1,199 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Modification Copyright (C) 2018 IBM. + * ================================================================================ + * Modifications Copyright (C) 2019 Ericsson + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.demo.model; + + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import java.util.ArrayList; +import java.util.Collection; +import org.apache.commons.io.IOUtils; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.onap.appc.listener.demo.model.CommonMessage.Streams; +import org.onap.appc.listener.demo.model.IncomingMessage; +import org.onap.appc.listener.demo.model.OutgoingMessage; +import org.onap.appc.listener.demo.model.Status; +import org.onap.appc.listener.util.Mapper; + +public class TestMessages { + private IncomingMessage in; + private OutgoingMessage out; + + private String incomingStr; + private String outgoingStr; + + @Before + public void setup() { + try { + incomingStr = IOUtils.toString(getClass().getResourceAsStream("/IncomingMessagedemo.txt"), "UTF-8"); + outgoingStr = IOUtils.toString(getClass().getResourceAsStream("/OutgoingMessagedemo.txt"), "UTF-8"); + assertNotNull(incomingStr); + assertNotNull(outgoingStr); + + in = Mapper.mapOne(incomingStr, IncomingMessage.class); + + out = Mapper.mapOne(outgoingStr, OutgoingMessage.class); + + assertNotNull(in); + assertNotNull(out); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + // NOTE Test Mapper will be used to test an event from dmaap. + @Test + public void testGetterSetter() { + assertNotNull(in); + assertNotNull(in.getAction()); + assertNotNull(in.getHeader().getApiVer()); + assertNotNull(in.getHeader().getOriginatorId()); + assertNotNull(in.getHeader().getRequestID()); + assertNotNull(in.getHeader().getSubRequestId()); + assertNotNull(in.getHeader().getTimeStamp()); + + assertNotNull(out); + assertNotNull(out.getHeader().getApiVer()); + assertNotNull(out.getHeader().getOriginatorId()); + assertNotNull(out.getHeader().getRequestID()); + assertNotNull(out.getHeader().getSubRequestId()); + assertNotNull(out.getHeader().getTimeStamp()); + assertNotNull(out.getStatus().getCode()); + assertNotNull(out.getStatus().getValue()); + + } + + @Test + public void testGetRequest() + { + String request="testRequest"; + in.setRequest(request); + assertEquals(request, in.getRequest()); + } + + @Test + public void testIsValid() + { + assertEquals(true, in.isValid()); + } + + @Test + public void testTime() { + in.setStartTime(0); + assertEquals(0, in.getStartTime()); + } + + @Test + public void testPayload() { + CommonMessage.Payload payload = new CommonMessage.Payload(); + payload.setGenericVnfId("VNF_ID"); + CommonMessage.Streams streams = new CommonMessage.Streams(); + streams.setActiveStreams(7); + payload.setStreams(streams); + in.setPayload(payload); + assertEquals("VNF_ID", in.getPayload().getGenericVnfId()); + assertEquals("{\\\"streams\\\": {\\\"active-streams\\\": 7}}", + in.getPayload().getStreams()); + } + + @Test + @Ignore + public void testIncommingToOutgoing(){ + OutgoingMessage newOut; + newOut = Mapper.mapOne(in.toOutgoing(Status.ACCEPTED), OutgoingMessage.class); + assertNotNull(newOut); + assertNotNull(newOut.getHeader().getApiVer()); + assertNotNull(newOut.getHeader().getOriginatorId()); + assertNotNull(newOut.getHeader().getRequestID()); + assertNotNull(newOut.getHeader().getSubRequestId()); + assertNotNull(newOut.getHeader().getTimeStamp()); + assertNotNull(newOut.getStatus().getCode()); + assertNotNull(newOut.getStatus().getValue()); + } + + @Test + @Ignore + public void testToString() { + in = new IncomingMessage(); + assertNotNull(in.toString()); + String id = "test"; + //in.setId(id); + assertNotNull(in.toString()); + assertTrue(in.toString().contains(id)); + } + + @Test + @Ignore + public void testOutgoingUpdateTime() { + //String old = out.getResponseTime(); + out.updateResponseTime(); + //assertFalse(old.equals(out.getResponseTime())); + } + + // Testing for 1510 + @Test + @Ignore + public void testOutgoingToJson() { + // Message Set + String message = "MSG"; + //out.setMessage(message); + JSONObject json = out.toResponse(); + assertNotNull(json); + String respStr = json.getString("response"); + //assertTrue(respStr.contains(out.getResponse().getValue())); + + String msgStr = json.getString("message"); + assertNotNull(msgStr); + //assertFalse(msgStr.contains(out.getOriginalRequest())); // False for 1602 + //assertTrue(msgStr.contains(out.getMessage())); + + // Null Message + //out.setMessage(null); + json = out.toResponse(); + assertNotNull(json); + msgStr = json.getString("message"); + assertNotNull(msgStr); + //assertFalse(msgStr.contains(out.getOriginalRequest())); // False for 1602 + //assertTrue(msgStr.contains(out.getResponse().getValue())); + + // Echoing request + //assertNotNull(out.getOriginalRequest()); + } + + @Test + @Ignore + public void testOutgoingToString() { + String s = out.toString(); + //assertTrue(s.contains(out.getId())); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/impl/EventHandlerImplTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/impl/EventHandlerImplTest.java new file mode 100644 index 000000000..8f5ed6d74 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/impl/EventHandlerImplTest.java @@ -0,0 +1,279 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ================================================================================ + * Modifications Copyright (C) 2019 Ericsson + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.impl; + +import static com.google.common.collect.Lists.newArrayList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.appc.adapter.message.Consumer; +import org.onap.appc.adapter.message.Producer; +import org.onap.appc.listener.ListenerProperties; +import org.powermock.reflect.Whitebox; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +/** + * Test the ProviderAdapter implementation. + */ + +@RunWith(MockitoJUnitRunner.class) +public class EventHandlerImplTest { + + private TestEventHandlerImpl adapter; + private ListenerProperties properties; + + @Mock + private Producer mockProducer; + @Mock + private Consumer mockConsumer; + + private static final String PROP_FILE = "/org/onap/appc/default.properties"; + + private static final String MESSAGE_FILE = "/DCAEResponse.txt"; + + /** + * Setup the test environment. + */ + @Before + public void setup() { + Properties allProps = new Properties(); + try { + allProps.load(getClass().getResourceAsStream(PROP_FILE)); + allProps.remove("appc.ClosedLoop.topic.read.filter"); + properties = new ListenerProperties("appc.ClosedLoop", allProps); + } catch (IOException e) { + System.out.println("WARNING: Failed to load properties file: " + PROP_FILE); + } + adapter = new TestEventHandlerImpl(properties); + adapter.setConsumer(mockConsumer); + adapter.setProducer(mockProducer); + } + + @Test + public void testInitialProperties() { + assertEquals(properties.getProperty("topic.read"), adapter.getReadTopic()); + assertTrue(adapter.getWriteTopic().equals(properties.getProperty("topic.write"))); + assertEquals(properties.getProperty("client.name"), adapter.getClientName()); + assertEquals(properties.getProperty("client.name.id"), adapter.getClientId()); + + String hostStr = properties.getProperty("poolMembers"); + int hostCount = hostStr.length() > 0 ? hostStr.split(",").length : 0; + assertEquals(hostCount, adapter.getPool().size()); + } + + @Test + public void testGettersAndSetters() { + String readTopic = "read"; + String writeTopic = "write"; + String clientName = "APPC-TEST"; + String clientId = "00"; + String newHost = "google.com"; + + adapter.setReadTopic(readTopic); + assertEquals(readTopic, adapter.getReadTopic()); + + adapter.setWriteTopic(writeTopic); + assertEquals(writeTopic, adapter.getWriteTopic()); + + adapter.setClientName(clientName); + assertEquals(clientName, adapter.getClientName()); + + adapter.setClientId(clientId); + assertEquals(clientId, adapter.getClientId()); + + adapter.setCredentials("fake", "secret"); + adapter.clearCredentials(); + + int oldSize = adapter.getPool().size(); + adapter.addToPool(newHost); + assertEquals(oldSize + 1, adapter.getPool().size()); + assertTrue(adapter.getPool().contains(newHost)); + + adapter.removeFromPool(newHost); + assertEquals(oldSize, adapter.getPool().size()); + assertFalse(adapter.getPool().contains(newHost)); + + } + + @Test + public void getIncomingEvents_should_success_when_no_errors_encountered() { + + List<String> testResult = newArrayList("test-result1", "test-result2", "test-result3"); + when(mockConsumer.fetch(anyInt(), anyInt())).thenReturn(testResult); + + List<String> result = adapter.getIncomingEvents(5); + + for (int i = 0; i < testResult.size(); i++) { + assertEquals(testResult.get(i), result.get(i)); + } + } + + + @Test + public void postStatus_should_success_when_no_errors_encountered() { + + adapter.postStatus("test-partition", "test-event"); + verify(mockProducer).post("test-partition", "test-event"); + + adapter.postStatus("test-event"); + verify(mockProducer).post(null, "test-event"); + } + + + @Test + public void closeClients_should_close_producer_and_consumer() { + adapter.getIncomingEvents(5); + adapter.postStatus("test-partition", "test-event"); + + adapter.closeClients(); + verify(mockConsumer).close(); + verify(mockProducer).close(); + } + + @Test + public void testGetEvents() { + EventHandlerImpl adapter = new EventHandlerImpl(properties); + Consumer consumer = Mockito.mock(Consumer.class); + Mockito.when(consumer.fetch(Mockito.anyInt(), Mockito.anyInt())) + .thenReturn(new ArrayList<String>(Arrays.asList("TEST1"))); + Whitebox.setInternalState(adapter, "reader", consumer); + assertEquals("TEST1", adapter.getIncomingEvents().get(0)); + } + + @Test + public void testGetEventsClass() { + EventHandlerImpl adapter = new EventHandlerImpl(properties); + Consumer consumer = Mockito.mock(Consumer.class); + Mockito.when(consumer.fetch(Mockito.anyInt(), Mockito.anyInt())) + .thenReturn(new ArrayList<String>(Arrays.asList("1"))); + Whitebox.setInternalState(adapter, "reader", consumer); + assertEquals(Integer.valueOf(1), adapter.getIncomingEvents(Integer.class).get(0)); + } + + @Test + public void testSetters() { + EventHandlerImpl adapter = new EventHandlerImpl(properties); + adapter.setResponseProblemBlacklistTime("1"); + assertEquals("1", Whitebox.getInternalState(adapter, "responseProblemBlacklistTime")); + adapter.setServerProblemBlacklistTime("1"); + assertEquals("1", Whitebox.getInternalState(adapter, "serverProblemBlacklistTime")); + adapter.setDnsIssueBlacklistTime("1"); + assertEquals("1", Whitebox.getInternalState(adapter, "dnsIssueBlacklistTime")); + adapter.setIOExceptionBlacklistTime("1"); + assertEquals("1", Whitebox.getInternalState(adapter, "ioExceptionBlacklistTime")); + } + +// @Test + public void testRun() { + EventHandlerImpl adapter = new EventHandlerImpl(properties); + + // Runoff any old data + List<String> result = adapter.getIncomingEvents(); + assertNotNull(result); + + // Post new data + DummyObj data = new DummyObj(); + data.key = "value"; + adapter.postStatus(data.toJson()); + + // Wait to account for network delay + sleep(2000); + + // Get data back + List<DummyObj> result2 = adapter.getIncomingEvents(DummyObj.class); + assertNotNull(result2); +// assertEquals(1, result2.size()); + assertEquals(data.toJson(), result2.get(0).toJson()); + } + + private class TestEventHandlerImpl extends EventHandlerImpl { + + private Consumer mockConsumer; + private Producer mockProducer; + + private TestEventHandlerImpl(ListenerProperties props) { + super(props); + } + + @Override + protected Consumer getConsumer() { + return mockConsumer; + } + + @Override + protected Producer getProducer() { + return mockProducer; + } + + private void setConsumer(Consumer consumer) { + mockConsumer = consumer; + } + + private void setProducer(Producer producer) { + mockProducer = producer; + } + } + + @JsonSerialize + public static class DummyObj implements Serializable { + + @JsonProperty("request") // Call request for default filter + public String key; + + public DummyObj() { + } + + public String toJson() { + return String.format("{\"request\": \"%s\"}", key); + } + } + + private void sleep(long ms) { + try { + Thread.sleep(ms); + } catch (Exception e) { + return; + } + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/impl/TestController.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/impl/TestController.java new file mode 100644 index 000000000..ccea14cef --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/impl/TestController.java @@ -0,0 +1,104 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ================================================================================ + * Modifications Copyright (C) 2019 Ericsson + * ============================================================================= + * Modifications Copyright (C) 2019 IBM + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.impl; + +import static org.junit.Assert.assertTrue; + +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mockito; +import org.onap.appc.listener.Controller; +import org.onap.appc.listener.Listener; +import org.onap.appc.listener.ListenerProperties; +import org.onap.appc.listener.demo.impl.ListenerImpl; +import org.powermock.reflect.Whitebox; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +public class TestController { + + private ListenerProperties listenerProperties; + private Set<ListenerProperties> properties = Mockito.spy(new HashSet<>()); + private EELFLogger log = Mockito.spy(EELFManager.getInstance().getLogger(ControllerImpl.class)); + + @Rule + public ExpectedException expectedEx = ExpectedException.none(); + + @Test + public void testExceptionConstructor() { + listenerProperties = Mockito.mock(ListenerProperties.class); + properties.add(listenerProperties); + new ControllerImpl(properties); + Mockito.verify(properties).remove(Mockito.any()); + } + + @Test + public void testListeners() { + listenerProperties = Mockito.mock(ListenerProperties.class); + properties.add(listenerProperties); + assertTrue(new ControllerImpl(properties).getListeners() instanceof Map); + + } + + @Test + public void testStartException() throws NoSuchMethodException, SecurityException { + Properties props = new Properties(); + props.put("TEST", "TEST"); + listenerProperties = Mockito.spy(new ListenerProperties("TEST", props)); + listenerProperties.setListenerClass(Listener.class); + properties.add(listenerProperties); + ControllerImpl controllerImpl = new ControllerImpl(properties); + controllerImpl.start(); + Mockito.verify(listenerProperties, Mockito.times(2)).getListenerClass(); + } + + @Test + public void testStopException() throws NoSuchMethodException, SecurityException, InterruptedException { + Properties props = new Properties(); + props.put("TEST", "TEST"); + listenerProperties = Mockito.spy(new ListenerProperties("TEST", props)); + listenerProperties.setListenerClass(Listener.class); + properties.add(listenerProperties); + ControllerImpl controllerImpl = new ControllerImpl(properties); + //controllerImpl.start(); + Map<String, Listener> map = Whitebox.getInternalState(controllerImpl, "listeners"); + map.put("TEST", new ListenerImpl(listenerProperties)); + ThreadPoolExecutor executor = Mockito.mock(ThreadPoolExecutor.class); + Mockito.when(executor.awaitTermination(300, TimeUnit.SECONDS)).thenReturn(false); + Whitebox.setInternalState(controllerImpl, "executor", executor); + controllerImpl.stop(false); + Mockito.verify(executor).shutdown(); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/util/HttpClientUtilTest.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/util/HttpClientUtilTest.java new file mode 100644 index 000000000..084d51ed0 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/util/HttpClientUtilTest.java @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2019 Ericsson + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.util; + +import static org.junit.Assert.assertTrue; +import org.apache.http.client.HttpClient; +import org.junit.Test; +import org.onap.appc.exceptions.APPCException; + +public class HttpClientUtilTest { + + @Test + public void testHttps() throws APPCException { + assertTrue(HttpClientUtil.getHttpClient("https") instanceof HttpClient); + } + + @Test + public void testHttp() throws APPCException { + assertTrue(HttpClientUtil.getHttpClient("http") instanceof HttpClient); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/util/TestMapper.java b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/util/TestMapper.java new file mode 100644 index 000000000..2a9483364 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/java/org/onap/appc/listener/util/TestMapper.java @@ -0,0 +1,135 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ================================================================================ + * Modifications Copyright (C) 2019 Ericsson + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.listener.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.appc.listener.util.Mapper; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +public class TestMapper { + + private String dummyJson = "{\"a\":\"%s\"}"; + private DummyObj dummyObj = new DummyObj(); + + @JsonSerialize + public static class DummyObj implements Serializable { + @JsonProperty("a") + public String a; + + public DummyObj() { + } + } + + @Before + public void setup() { + } + + @Test + public void testGetMapper() { + assertNotNull(Mapper.getMapper()); + } + + @Test + public void testToJsonObject() { + JSONObject out; + out = Mapper.toJsonObject("."); + assertNull(out); + + String value = "b"; + out = Mapper.toJsonObject(String.format(dummyJson, value)); + assertNotNull(out); + assertEquals(value, out.get("a")); + } + + @Test + public void testConstructor() { + // Only here for code coverage + Mapper m = new Mapper(); + assertNotNull(m); + } + + @Test + public void testMap() { + List<String> in = new ArrayList<String>(); + in.add(""); + in.add(null); + + List<DummyObj> out = Mapper.mapList(in, DummyObj.class); + assertNotNull(out); + assertTrue(out.isEmpty()); + + in.add(String.format(dummyJson, "1")); + in.add("{\"invalid\":\"yes\"}"); + in.add(String.format(dummyJson, "2")); + + out = Mapper.mapList(in, DummyObj.class); + assertNotNull(out); + assertEquals(2, out.size()); + assertEquals("1", out.get(0).a); + assertEquals("2", out.get(1).a); + } + + @Test + public void testToJsonString() { + JSONObject jsonObject = Mockito.mock(JSONObject.class); + assertTrue(Mapper.toJsonString(jsonObject).startsWith("Mock for JSONObject")); + } + + @Test + public void testToJsonStringNonJsonObject() { + assertEquals("\"TEST\"", Mapper.toJsonString("TEST")); + } + + @Test + public void testToJsonStringException() { + assertNull(Mapper.toJsonString(new Mapper())); + } + + @Test + public void testToJsonNodeFromJsonStringException() { + assertNull(Mapper.toJsonNodeFromJsonString("{{}")); + } + + @Test + public void testToJsonNode() { + assertTrue(Mapper.toJsonNode(dummyObj) instanceof JsonNode); + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/resources/IncomingMessagedemo.txt b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/resources/IncomingMessagedemo.txt new file mode 100644 index 000000000..bd56e003d --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/resources/IncomingMessagedemo.txt @@ -0,0 +1,24 @@ +{ + "CommonHeader": { + "TimeStamp": "0000-00-00T00:00:00.000Z", + "APIver": "1.01", + "OriginatorID": "policy.pdp01", + "RequestID": "b74d13c5-bb26-4b04-992c-4679dfc8280e", + "SubRequestID": "1" + }, + "Action": "RESTART", + "Payload": { + "VServerSelfLink": "http://192.168.1.2:8774/v2/abcde12345fghijk6789lmnopq123rst/servers/abc12345-1234-5678-890a-abcdefg12345", + "VNF_NAME": "test", + "VMID": "abc12345-1234-5678-890a-abcdefg12345", + "TenantID": "abcde12345fghijk6789lmnopq123rst", + "LOC_ID": "Test", + "in-maint": "false", + "Identity": "http://example.com:5000/v2.0", + "Prov_status": "ACTIVE", + "OAM_IPV4": "192.168.1.2", + "is-closed-loop-disabled": "false", + "VM_NAME": "test", + "OAM_IPV6": "0000::0000:0000:0000:0000/64" + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/resources/OutgoingMessagedemo.txt b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/resources/OutgoingMessagedemo.txt new file mode 100644 index 000000000..af79c5aad --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/resources/OutgoingMessagedemo.txt @@ -0,0 +1,27 @@ +{ + "CommonHeader": { + "TimeStamp": "0000-00-00T00:00:00.000Z", + "APIver": "1.01", + "OriginatorID": "policy.pdp01", + "RequestID": "b74d13c5-bb26-4b04-992c-4679dfc8280e", + "SubRequestID": "1" + }, + "Status": { + "Code": 100, + "Value": "ACCEPT" + }, + "Payload": { + "VServerSelfLink": "http://192.168.1.2:8774/v2/abcde12345fghijk6789lmnopq123rst/servers/abc12345-1234-5678-890a-abcdefg12345", + "VNF_NAME": "test", + "VMID": "abc12345-1234-5678-890a-abcdefg12345", + "TenantID": "abcde12345fghijk6789lmnopq123rst", + "LOC_ID": "Test", + "in-maint": "false", + "Identity": "http://example.com:5000/v2.0", + "Prov_status": "ACTIVE", + "OAM_IPV4": "192.168.1.2", + "is-closed-loop-disabled": "false", + "VM_NAME": "test", + "OAM_IPV6": "0000::0000:0000:0000:0000/64" + } +} diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/resources/org/onap/appc/default.properties b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/resources/org/onap/appc/default.properties new file mode 100644 index 000000000..c729c7b0a --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/resources/org/onap/appc/default.properties @@ -0,0 +1,127 @@ +### +# ============LICENSE_START======================================================= +# ONAP : APPC +# ================================================================================ +# Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Copyright (C) 2017 Amdocs +# ============================================================================= +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END========================================================= +### + + + + + +### ### +### ### +###Properties below are default values to be provided with real valuesin appc.properties### +### ### +### ### + + + + + +### ### +###Closed Loop - properties ### +### ### +test.prefix=appc.ClosedLoop +appc.ClosedLoop.disabled=false +appc.ClosedLoop.service=dmaap +appc.ClosedLoop.poolMembers=192.168.1.2:3904 +appc.ClosedLoop.topic.read=APPC-TEST1 +appc.ClosedLoop.topic.read.timeout=5 +appc.ClosedLoop.topic.write=APPC-TEST1 +appc.ClosedLoop.topic.read.filter={"class":"Assigned","field":"request"} +appc.ClosedLoop.client.name=APPC-TEST1-CLOSED-LOOP +appc.ClosedLoop.client.name.id=0 + +# KEY AND SECRET BELOW NEED TO BE MODIFIED TO APPROPRIATE VALUES WHEN THE TOPIC IS API-KEY-BASED AUTH +appc.ClosedLoop.client.key=MY_API_KEY +appc.ClosedLoop.client.secret=MY_API_SECRET + +appc.ClosedLoop.threads.queuesize.min=1 +appc.ClosedLoop.threads.queuesize.max=1000 +appc.ClosedLoop.threads.poolsize.min=1 +appc.ClosedLoop.threads.poolsize.max=2 +appc.ClosedLoop.provider.url=https://admin:password@localhost:8443/restconf/operations/appc-provider:topology-operation +appc.ClosedLoop.topic.responseProblem.blacklistTime=60 +appc.ClosedLoop.topic.serverError.blacklistTime=60 +appc.ClosedLoop.topic.dnsIssue.blacklistTime=60 +appc.ClosedLoop.topic.ioException.blacklistTime=60 + + + + +### ### +###Closed Loop - 1607 properties ### +### ### +appc.ClosedLoop1607.poolMembers=192.168.1.2:3904 +appc.ClosedLoop1607.topic.read=MY_DMAAP_TOPIC +appc.ClosedLoop1607.topic.write=MY_DMAAP_TOPIC +appc.ClosedLoop1607.topic.read.filter={"class":"Unassigned","field":"Status"} +appc.ClosedLoop1607.client.name=DMAAP-CLIENT-NAME +appc.ClosedLoop1607.client.name.id=0 +#dmaap.client.key=random +#dmaap.client.secret=random +appc.ClosedLoop1607.threads.queuesize.min=1 +appc.ClosedLoop1607.threads.queuesize.max=1000 +appc.ClosedLoop1607.threads.poolsize.min=1 +appc.ClosedLoop1607.threads.poolsize.max=2 +appc.ClosedLoop1607.provider.url=https://admin:password@localhost:8443/restconf/operations/appc-provider:topology-operation + +### ### +### LCM properties ### +### ### +appc.LCM.disabled=true +appc.LCM.poolMembers=192.168.1.2:3904 +appc.LCM.topic.read=MY_DMAAP_TOPIC +appc.LCM.topic.write=MY_DMAAP_TOPIC +appc.LCM.topic.read.filter={"class":"Unassigned","field":"Status"} +appc.LCM.client.name=DMAAP-CLIENT-NAME +appc.LCM.client.name.id=0 +appc.LCM.threads.queuesize.min=1 +appc.LCM.threads.queuesize.max=1000 +appc.LCM.threads.poolsize.min=1 +appc.LCM.threads.poolsize.max=2 +appc.LCM.provider.url=https://admin:password@localhost:8443/restconf/operations/appc-provider:topology-operation + +### ### +### DEMO properties ### +### ### +appc.demo.poolMembers=192.168.1.2:3904 +appc.demo.topic.read=MY_DMAAP_TOPIC +appc.demo.topic.write=MY_DMAAP_TOPIC +appc.demo.topic.read.filter={"class":"Unassigned","field":"Status"} +appc.demo.client.name=DMAAP-CLIENT-NAME +appc.demo.client.name.id=0 +appc.demo.threads.queuesize.min=1 +appc.demo.threads.queuesize.max=1000 +appc.demo.threads.poolsize.min=1 +appc.demo.threads.poolsize.max=2 + +# OAM Listener +######################### +appc.OAM.disabled=false +appc.OAM.poolMembers=192.168.1.2:3904 +appc.OAM.topic.read=OAM_TOPIC +appc.OAM.topic.write=OAM_TOPIC +appc.OAM.client.name=OAM_CLIENT +#appc.OAM.provider.url= +#appc.OAM.provider.user=m97292@appc.att.com +#appc.OAM.provider.pass=enc:DBE7PBN7EAN+Pwom + +appc.demo.provider.url=https://admin:password@localhost:8443/restconf/operations/appc-provider:topology-operation
\ No newline at end of file diff --git a/services/appc-dmaap-service/appc-event-listener-bundle/src/test/resources/org/onap/appc/empty.properties b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/resources/org/onap/appc/empty.properties new file mode 100644 index 000000000..4b70a23c0 --- /dev/null +++ b/services/appc-dmaap-service/appc-event-listener-bundle/src/test/resources/org/onap/appc/empty.properties @@ -0,0 +1,32 @@ +### +# ============LICENSE_START======================================================= +# ONAP : APPC +# ================================================================================ +# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Copyright (C) 2017 Amdocs +# ============================================================================= +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END========================================================= +### + + + + + +### ### +### ### +###Properties below are default values to be provided with real valuesin appc.properties### +### ### +### ### diff --git a/services/appc-dmaap-service/appc-message-adapter-api/.gitignore b/services/appc-dmaap-service/appc-message-adapter-api/.gitignore new file mode 100644 index 000000000..eacf31a67 --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-api/.gitignore @@ -0,0 +1 @@ +/target-ide/ diff --git a/services/appc-dmaap-service/appc-message-adapter-api/pom.xml b/services/appc-dmaap-service/appc-message-adapter-api/pom.xml new file mode 100644 index 000000000..84cd805aa --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-api/pom.xml @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + ONAP : APPC + ================================================================================ + Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + Copyright (C) 2017 Amdocs + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR 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.appc.parent</groupId> + <artifactId>binding-parent</artifactId> + <version>2.6.2</version> + <relativePath /> + </parent> + + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>appc-message-adapter-api</artifactId> + <packaging>jar</packaging> + <name>appc-message-adapter-api</name> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-module-junit4</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.onap.ccsdk.sli.core</groupId> + <artifactId>sli-common</artifactId> + <scope>compile</scope> + <!-- Added exclusion to prevent missing dependency issue on dblib --> + <exclusions> + <exclusion> + <groupId>org.onap.ccsdk.sli.core</groupId> + <artifactId>dblib-provider</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.onap.ccsdk.sli.core</groupId> + <artifactId>sli-provider</artifactId> + <scope>compile</scope> + <!-- Added exclusion to prevent missing dependency issue on dblib --> + <exclusions> + <exclusion> + <groupId>org.onap.ccsdk.sli.core</groupId> + <artifactId>dblib-provider</artifactId> + </exclusion> + </exclusions> + </dependency> + + </dependencies> + + <version>1.7.0-SNAPSHOT</version> +</project> diff --git a/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/CallableConsumer.java b/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/CallableConsumer.java new file mode 100644 index 000000000..4359c51fb --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/CallableConsumer.java @@ -0,0 +1,60 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.message; + +import java.util.List; +import java.util.concurrent.Callable; + +public class CallableConsumer implements Callable<List<String>> { + + private Consumer consumer; + + private int timeout = 15000; + private int limit = 1000; + + public CallableConsumer(Consumer c) { + this.consumer = c; + } + + public CallableConsumer(Consumer c, int waitMs, int fetchSize) { + this.consumer = c; + this.timeout = waitMs; + this.limit = fetchSize; + } + + @Override + public List<String> call() { + return consumer.fetch(timeout, limit); + } + + /** + * The maximum amount of time to keep a connection alive. Currently is set to waitMs + 10s + * + * @return An integer representing the maximum amount of time to keep this thread alive + */ + public int getMaxLife() { + return 10000 + timeout; + } + +} diff --git a/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/Consumer.java b/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/Consumer.java new file mode 100644 index 000000000..542797ed2 --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/Consumer.java @@ -0,0 +1,92 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.message; + +import java.util.List; + +public interface Consumer { + + /** + * Gets a batch of messages from the topic. Defaults to 1000 messages with 15s wait for messages if empty. + * + * @return A list of strings representing the messages pulled from the topic. + */ + List<String> fetch(); + + /** + * Gets a batch of messages from the topic. + * + * @param waitMs + * The amount of time to wait in milliseconds if the topic is empty for data to be written. Should be no + * less than 15000ms to prevent too many requests + * @param limit + * The amount of messages to fetch + * @return A list of strings representing the messages pulled from the topic. + */ + List<String> fetch(int waitMs, int limit); + + /** + * Updates the api credentials for making authenticated requests. + * + * @param apiKey + * The public key to authenticate with + * @param apiSecret + * The secret key to authenticate with + */ + void updateCredentials(String apiKey, String apiSecret); + + /** + * Creates a dmaap client using a https connection + * + * @param yes + * True if https should be used, false otherwise. + */ + default void useHttps(boolean yes) {} + + /** + * Sets Blacklist time for a server with response problem in seconds + */ + default void setResponseProblemBlacklistTime(String duration) {} + + /** + * Sets Blacklist time for a server with server problem in seconds + */ + default void setServerProblemBlacklistTime(String duration) {} + + /** + * Sets Blacklist time for a server with DNS problem in seconds + */ + default void setDnsIssueBlacklistTime(String duration) {} + + /** + * Sets Blacklist time for a server with IO Exception problem in seconds + */ + default void setIOExceptionBlacklistTime(String duration) {} + + /** + * Closes the dmaap client https connection. + */ + default void close() {} + +} diff --git a/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/Manager.java b/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/Manager.java new file mode 100644 index 000000000..315e4bd0b --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/Manager.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.message; + +import java.util.Set; + +public interface Manager { + + /** + * Updates the api credentials for making authenticated requests + * + * @param apiKey + * The public key to authenticate with + * @param apiSecret + * The secret key to authenticate with + */ + public void updateCredentials(String apiKey, String apiSecret); + + /** + * Return a set of strings representing topics that the user can see + * + * @return A set of strings with topic names or an empty set if no topics are visible + */ + public Set<String> getTopics(); + +} diff --git a/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/MessageAdapterFactory.java b/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/MessageAdapterFactory.java new file mode 100644 index 000000000..03bc2b28a --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/MessageAdapterFactory.java @@ -0,0 +1,41 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ +package org.onap.appc.adapter.message; + +import java.util.Collection; +import java.util.Set; + +import org.onap.appc.adapter.message.Consumer; +import org.onap.appc.adapter.message.Producer; + +public interface MessageAdapterFactory { + + // TODO: how do you configure the MessageService type? + + public Producer createProducer(Collection<String> pools, String writeTopic, String apiKey, String apiSecret); + + public Producer createProducer(Collection<String> pools, Set<String> writeTopics, String apiKey, String apiSecret); + + public Consumer createConsumer(Collection<String> pool, String readTopic, + String clientName, String clientId, String filter_json, String apiKey, String apiSecret); +} diff --git a/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/MessageDestination.java b/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/MessageDestination.java new file mode 100644 index 000000000..02244ccd5 --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/MessageDestination.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.message; + +public enum MessageDestination { + DCAE +} diff --git a/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/Producer.java b/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/Producer.java new file mode 100644 index 000000000..8536d8257 --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-api/src/main/java/org/onap/appc/adapter/message/Producer.java @@ -0,0 +1,74 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.message; + +public interface Producer { + + boolean post(String partition, String data); + + /** + * Updates the api credentials for making authenticated requests. + * + * @param apiKey + * The public key to authenticate with + * @param apiSecret + * The secret key to authenticate with + */ + void updateCredentials(String apiKey, String apiSecret); + + /** + * Creates a dmaap client using a https connection. + * + * @param yes + * True if https should be used, false otherwise + */ + default void useHttps(boolean yes) {} + + /** + * Sets Blacklist time for a server with response problem in seconds + */ + default void setResponseProblemBlacklistTime(String duration) { } + + /** + * Sets Blacklist time for a server with server problem in seconds + */ + default void setServerProblemBlacklistTime(String duration) {} + + /** + * Sets Blacklist time for a server with DNS problem in seconds + */ + default void setDnsIssueBlacklistTime(String duration) {} + + /** + * Sets Blacklist time for a server with IO Exception problem in seconds + */ + default void setIOExceptionBlacklistTime(String duration) {} + + + /** + * Closes the dmaap client https connection. + */ + default void close() {} + +} diff --git a/services/appc-dmaap-service/appc-message-adapter-api/src/main/resources/org/onap/appc/default.properties b/services/appc-dmaap-service/appc-message-adapter-api/src/main/resources/org/onap/appc/default.properties new file mode 100644 index 000000000..da25a66a4 --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-api/src/main/resources/org/onap/appc/default.properties @@ -0,0 +1,25 @@ +### +# ============LICENSE_START======================================================= +# ONAP : APPC +# ================================================================================ +# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Copyright (C) 2017 Amdocs +# ============================================================================= +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END========================================================= +### + +org.onap.appc.bootstrap.file=appc.properties +org.onap.appc.bootstrap.path=/opt/onap/appc/data/properties,${user.home},. diff --git a/services/appc-dmaap-service/appc-message-adapter-api/src/test/java/org/onap/appc/adapter/message/TestCallableConsumer.java b/services/appc-dmaap-service/appc-message-adapter-api/src/test/java/org/onap/appc/adapter/message/TestCallableConsumer.java new file mode 100644 index 000000000..8c9dec31c --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-api/src/test/java/org/onap/appc/adapter/message/TestCallableConsumer.java @@ -0,0 +1,73 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 IBM. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.appc.adapter.message; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class TestCallableConsumer { + + CallableConsumer callableConsumer; + + @Mock + private Consumer consumer; + + private List<String> list; + private int waitMs = 15000; + private int limit = 1000; + private int maxLife = 25000; + + @Before + public void setUp() { + list = new ArrayList<String>(); + callableConsumer = new CallableConsumer(consumer, waitMs, limit); + } + + @Test + public void testCallableConsumer() { + CallableConsumer callableConsumer = new CallableConsumer(consumer); + Mockito.when(consumer.fetch()).thenReturn(list); + assertEquals(list, callableConsumer.call()); + } + + @Test + public void testCall() { + Mockito.when(consumer.fetch()).thenReturn(list); + assertEquals(list, callableConsumer.call()); + } + + @Test + public void testGetMaxLife() { + assertEquals(maxLife, callableConsumer.getMaxLife()); + } + +} diff --git a/services/appc-dmaap-service/appc-message-adapter-api/src/test/java/org/onap/appc/adapter/message/TestMessageDestination.java b/services/appc-dmaap-service/appc-message-adapter-api/src/test/java/org/onap/appc/adapter/message/TestMessageDestination.java new file mode 100644 index 000000000..53b4ad463 --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-api/src/test/java/org/onap/appc/adapter/message/TestMessageDestination.java @@ -0,0 +1,39 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : APPC +* ================================================================================ +* Copyright 2018 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +package org.onap.appc.adapter.message; + +import org.junit.Assert; +import org.junit.Test; + +public class TestMessageDestination { + + private MessageDestination messageDestination=MessageDestination.DCAE; + + @Test + public void testName() { + Assert.assertEquals("DCAE", messageDestination.name()); + } + + @Test + public void testEqual() { + Assert.assertTrue(messageDestination.equals(MessageDestination.DCAE)); + Assert.assertFalse(messageDestination.equals(null)); + } +} diff --git a/services/appc-dmaap-service/appc-message-adapter-factory/.gitignore b/services/appc-dmaap-service/appc-message-adapter-factory/.gitignore new file mode 100644 index 000000000..eacf31a67 --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-factory/.gitignore @@ -0,0 +1 @@ +/target-ide/ diff --git a/services/appc-dmaap-service/appc-message-adapter-factory/pom.xml b/services/appc-dmaap-service/appc-message-adapter-factory/pom.xml new file mode 100644 index 000000000..f234c92dd --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-factory/pom.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + ONAP : APPC + ================================================================================ + Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + Copyright (C) 2017 Amdocs + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR 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.appc.parent</groupId> + <artifactId>binding-parent</artifactId> + <version>2.6.2</version> + <relativePath /> + </parent> + + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>appc-message-adapter-factory</artifactId> + <packaging>jar</packaging> + <name>appc-message-adapter-factory</name> + + <dependencies> + + <dependency> + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>appc-dmaap-adapter-bundle</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>appc-message-adapter-api</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + + + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-module-junit4</artifactId> + <scope>test</scope> + </dependency> + + </dependencies> + + <version>1.7.0-SNAPSHOT</version> +</project> diff --git a/services/appc-dmaap-service/appc-message-adapter-factory/src/main/java/org/onap/appc/adapter/factory/DmaapMessageAdapterFactoryImpl.java b/services/appc-dmaap-service/appc-message-adapter-factory/src/main/java/org/onap/appc/adapter/factory/DmaapMessageAdapterFactoryImpl.java new file mode 100644 index 000000000..d182f4769 --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-factory/src/main/java/org/onap/appc/adapter/factory/DmaapMessageAdapterFactoryImpl.java @@ -0,0 +1,59 @@ +/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * Modifications Copyright (C) 2019 Ericsson
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.appc.adapter.factory;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.onap.appc.adapter.message.Consumer;
+import org.onap.appc.adapter.message.MessageAdapterFactory;
+import org.onap.appc.adapter.message.Producer;
+import org.onap.appc.adapter.messaging.dmaap.http.HttpDmaapConsumerImpl;
+import org.onap.appc.adapter.messaging.dmaap.http.HttpDmaapProducerImpl;
+
+public class DmaapMessageAdapterFactoryImpl implements MessageAdapterFactory {
+
+
+ @Override
+ public Producer createProducer(Collection<String> pools, String writeTopic, String apiKey, String apiSecret) {
+ return new HttpDmaapProducerImpl(pools, writeTopic);
+ }
+
+ @Override
+ public Producer createProducer(Collection<String> pools, Set<String> writeTopics, String apiKey, String apiSecret) {
+ String topic = "";
+ for(String s : writeTopics){
+ topic = s;
+ }
+ return new HttpDmaapProducerImpl(pools, topic);
+ }
+
+ @Override
+ public Consumer createConsumer(Collection<String> pool, String readTopic,
+ String clientName, String clientId, String filterJson, String apiKey, String apiSecret) {
+ return new HttpDmaapConsumerImpl(pool, readTopic, clientName, clientId, apiKey, apiSecret, filterJson);
+ }
+}
diff --git a/services/appc-dmaap-service/appc-message-adapter-factory/src/main/java/org/onap/appc/adapter/factory/MessageService.java b/services/appc-dmaap-service/appc-message-adapter-factory/src/main/java/org/onap/appc/adapter/factory/MessageService.java new file mode 100644 index 000000000..f7c51be29 --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-factory/src/main/java/org/onap/appc/adapter/factory/MessageService.java @@ -0,0 +1,58 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.factory; +/** + * The message service types that are available. Only DMaaP available + **/ +public enum MessageService { + DMaaP("dmaap"); + + private String val; + + private MessageService(String val) { + this.val = val; + } + + public String getValue() { + return val; + } + + /** + * Tries to match a string to a MessageService. If no match is found, returns the default (DMaaP) + * + * @param input + * the string to try and match + * @return A MessasgeService + */ + public static MessageService parse(String input) { + if (input != null) { + for (MessageService ms : MessageService.values()) { + if (input.equalsIgnoreCase(ms.getValue())) { + return ms; + } + } + } + return MessageService.DMaaP; // Default + } +} diff --git a/services/appc-dmaap-service/appc-message-adapter-factory/src/main/resources/org/onap/appc/default.properties b/services/appc-dmaap-service/appc-message-adapter-factory/src/main/resources/org/onap/appc/default.properties new file mode 100644 index 000000000..da25a66a4 --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-factory/src/main/resources/org/onap/appc/default.properties @@ -0,0 +1,25 @@ +### +# ============LICENSE_START======================================================= +# ONAP : APPC +# ================================================================================ +# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Copyright (C) 2017 Amdocs +# ============================================================================= +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END========================================================= +### + +org.onap.appc.bootstrap.file=appc.properties +org.onap.appc.bootstrap.path=/opt/onap/appc/data/properties,${user.home},. diff --git a/services/appc-dmaap-service/appc-message-adapter-factory/src/test/java/org/onap/appc/adapter/factory/DmaapMessageAdapterFactoryImplTest.java b/services/appc-dmaap-service/appc-message-adapter-factory/src/test/java/org/onap/appc/adapter/factory/DmaapMessageAdapterFactoryImplTest.java new file mode 100644 index 000000000..bfc469d7b --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-factory/src/test/java/org/onap/appc/adapter/factory/DmaapMessageAdapterFactoryImplTest.java @@ -0,0 +1,58 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2019 Ericsson + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.factory; + +import static org.junit.Assert.assertTrue; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import org.junit.Before; +import org.junit.Test; +import org.onap.appc.adapter.message.Consumer; +import org.onap.appc.adapter.message.Producer; + +public class DmaapMessageAdapterFactoryImplTest { + + private DmaapMessageAdapterFactoryImpl factory; + private Collection<String> pools; + + @Before + public void setup() { + factory = new DmaapMessageAdapterFactoryImpl(); + pools = new ArrayList<>(); + pools.add("http://server:1"); + } + + @Test + public void testCreateProducer() { + Set<String> writeTopics = new HashSet<>(); + assertTrue(factory.createProducer(pools, writeTopics, null, null) instanceof Producer); + assertTrue(factory.createProducer(pools, "TEST" , null, null) instanceof Producer); + } + + @Test + public void testCreateConsumer() { + assertTrue(factory.createConsumer(pools, "TEST", null, null, null, null, null) instanceof Consumer); + } + +} diff --git a/services/appc-dmaap-service/appc-message-adapter-factory/src/test/java/org/onap/appc/adapter/factory/MessageServiceTest.java b/services/appc-dmaap-service/appc-message-adapter-factory/src/test/java/org/onap/appc/adapter/factory/MessageServiceTest.java new file mode 100644 index 000000000..47fa1f6f3 --- /dev/null +++ b/services/appc-dmaap-service/appc-message-adapter-factory/src/test/java/org/onap/appc/adapter/factory/MessageServiceTest.java @@ -0,0 +1,49 @@ +/* +* ============LICENSE_START======================================================= +* ONAP : APPC +* ================================================================================ +* Copyright 2018 TechMahindra +*================================================================================= +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* ============LICENSE_END========================================================= +*/ +package org.onap.appc.adapter.factory; + +import org.junit.Assert; +import org.junit.Test; + +public class MessageServiceTest { + + private MessageService messageService = MessageService.DMaaP; + + @Test + public void testName() { + Assert.assertEquals("DMaaP", messageService.name()); + } + + @Test + public void testGetValue() { + Assert.assertEquals("dmaap", messageService.getValue()); + } + + @Test + public void testParse() { + Assert.assertEquals(messageService, MessageService.parse("DMAAP")); + } + + @Test + public void testParse_Null() { + Assert.assertEquals(MessageService.DMaaP, MessageService.parse(null)); + } + +} diff --git a/services/appc-dmaap-service/pom.xml b/services/appc-dmaap-service/pom.xml new file mode 100644 index 000000000..1c4a8c7b0 --- /dev/null +++ b/services/appc-dmaap-service/pom.xml @@ -0,0 +1,42 @@ +<!-- + ============LICENSE_START======================================================= + ONAP : APPC + ================================================================================ + Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.onap.appc.services.dmaap</groupId> + <artifactId>dmaap-service</artifactId> + <packaging>pom</packaging> + <version>1.7.0-SNAPSHOT</version> + <name>appc-dmaap-service</name> + <url>http://maven.apache.org</url> + <modules> + <module>appc-dmaap-adapter-bundle</module> + <module>appc-message-adapter-api</module> + <module>appc-message-adapter-factory</module> + <module>appc-event-listener-bundle</module> + <module>appc-dmaap-event-service</module> + </modules> + + <properties> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + </properties> + +</project> diff --git a/services/pom.xml b/services/pom.xml new file mode 100644 index 000000000..4737f98a9 --- /dev/null +++ b/services/pom.xml @@ -0,0 +1,42 @@ +<!-- + ============LICENSE_START======================================================= + ONAP : APPC + ================================================================================ + Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.onap.appc.services</groupId> + <artifactId>appc-services-root</artifactId> + <packaging>pom</packaging> + <version>1.7.0-SNAPSHOT</version> + <name>appc-services-root</name> + <modules> + <module>appc-dmaap-service</module> + </modules> + + <properties> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + </properties> + + <parent> + <groupId>org.onap.appc</groupId> + <artifactId>appc</artifactId> + <version>1.7.0-SNAPSHOT</version> + </parent> +</project> |