diff options
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> |