diff --git a/README.md b/README.md index 88aba165..870efc2c 100644 --- a/README.md +++ b/README.md @@ -548,6 +548,7 @@ The Event Management Agent comes with the following event or message broker plug * Solace PubSub+ * Confluent Schema Registry * MSK +* IBM MQ The default application.yml provides various plugin examples. For Kafka, the properties section under credentials is passthrough. For example a property in ConsumerConfig or SSLConfigs classes. diff --git a/service/application/pom.xml b/service/application/pom.xml index 8a530ea6..edc996ba 100644 --- a/service/application/pom.xml +++ b/service/application/pom.xml @@ -247,6 +247,11 @@ terraform-plugin 1.6.6-SNAPSHOT + + com.solace.maas.plugin.ibmmq + ibmmq-plugin + 1.6.6-SNAPSHOT + io.micrometer diff --git a/service/application/src/main/resources/application.yml b/service/application/src/main/resources/application.yml index 31385b9a..1a645acc 100644 --- a/service/application/src/main/resources/application.yml +++ b/service/application/src/main/resources/application.yml @@ -355,3 +355,22 @@ eventPortal: # value: software.amazon.msk.auth.iam.IAMLoginModule required; # - name: sasl.client.callback.handler.class # value: software.amazon.msk.auth.iam.IAMClientCallbackHandler +# # IBM MQ Example +# - id: ibmmqDefaultService +# type: IBMMQ +# name: IBM MQ Test Service +# connections: +# - name: IBMMQBroker +## Example: https://[domain:[port]]/ibmmq/rest/v1/admin/qmgr/{qmgrName} +# url: ${IBM_MQ_REST_API_URL} +# authentication: +# - protocol: BASIC +# credentials: +# - source: ENVIRONMENT_VARIABLE +# operations: +# - name: IBMMQ_ALL +# properties: +# - name: username +# value: ${IBMMQ_ADMINISTRATOR_USERNAME} +# - name: password +# value: ${IBMMQ_ADMINISTRATOR_PASSWORD} diff --git a/service/ibmmq-plugin/pom.xml b/service/ibmmq-plugin/pom.xml new file mode 100644 index 00000000..05ca5954 --- /dev/null +++ b/service/ibmmq-plugin/pom.xml @@ -0,0 +1,94 @@ + + + 4.0.0 + com.solace.maas.plugin.ibmmq + ibmmq-plugin + 1.6.6-SNAPSHOT + Solace Event Management Agent - IBM MQ Plugin + Solace Event Management Agent - IBM MQ Plugin + + + 17 + 17 + 1.6.6-SNAPSHOT + 3.1.11 + + 4.0.1 + 4.2.0 + UTF-8 + + + + + + org.springframework.boot + spring-boot-starter-webflux + ${spring.boot.version} + + + ch.qos.logback + logback-classic + + + + + + com.solace.maas + plugin + ${solace.maas.ema.version} + + + org.apache.camel + camel-jackson + ${camel.version} + + + + + org.springframework.boot + spring-boot-starter-test + ${spring.boot.version} + test + + + com.squareup.okhttp3 + okhttp + ${okhttp.version} + test + + + com.squareup.okhttp3 + mockwebserver + ${okhttp.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + \ No newline at end of file diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplication.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplication.java new file mode 100644 index 00000000..74c50b23 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplication.java @@ -0,0 +1,12 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class IbmMqApplication { + + public static void main(String[] args) { + SpringApplication.run(IbmMqApplication.class, args); + } +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java new file mode 100644 index 00000000..c4b77816 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java @@ -0,0 +1,19 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http; + +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; + +/** + * Interface for Spring HTTPInterface to create the IBM MQ Admin Client. + */ +@HttpExchange +public interface IbmMqHttpClient { + + /*Gets all queues on a given queue manager*/ + @GetExchange("/queue") + IbmMqQueueResponse getQueues(); + + /*Gets all subscriptions (topics) on a given queue manager*/ + @GetExchange("/subscription") + IbmMqSubscriptionResponse getSubscriptions(); +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqQueueResponse.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqQueueResponse.java new file mode 100644 index 00000000..d27b6a2a --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqQueueResponse.java @@ -0,0 +1,16 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.event.IbmMqQueueEvent; +import lombok.Getter; + +import java.util.List; + +/** + * Represents the response JSON from the IBM MQ Admin client + * when querying for Queue information. + */ +@Getter +public class IbmMqQueueResponse { + + private List queue; +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqSubscriptionResponse.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqSubscriptionResponse.java new file mode 100644 index 00000000..e64b6d3c --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqSubscriptionResponse.java @@ -0,0 +1,16 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.event.IbmMqSubscriptionEvent; +import lombok.Data; + +import java.util.List; + +/** + * Represents the response JSON from the IBM MQ Admin client + * when querying for Subscription (topic) information. + */ +@Data +public class IbmMqSubscriptionResponse { + + List subscription; +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java new file mode 100644 index 00000000..72eb071b --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java @@ -0,0 +1,13 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.manager.client; + +import com.solace.maas.ep.event.management.agent.plugin.manager.client.MessagingServiceClientConfig; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class IbmMqClientConfigImpl extends MessagingServiceClientConfig { + + protected IbmMqClientConfigImpl() { + super("IBMMQ", new IbmMqClientManagerImpl()); + } + +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java new file mode 100644 index 00000000..523c5075 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java @@ -0,0 +1,65 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.manager.client; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqHttpClient; +import com.solace.maas.ep.event.management.agent.plugin.manager.client.MessagingServiceClientManager; +import com.solace.maas.ep.event.management.agent.plugin.messagingService.event.AuthenticationDetailsEvent; +import com.solace.maas.ep.event.management.agent.plugin.messagingService.event.ConnectionDetailsEvent; +import com.solace.maas.ep.event.management.agent.plugin.util.MessagingServiceConfigurationUtil; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.ExchangeFilterFunctions; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.support.WebClientAdapter; +import org.springframework.web.service.invoker.HttpServiceProxyFactory; + +import java.util.NoSuchElementException; + +/** + * Implementation of the IBM MQ Administration client. + *

+ * This client provides access to the various administrative endpoints exposed by IBM MQ. + */ +@Slf4j +@Data +@Component +public class IbmMqClientManagerImpl implements MessagingServiceClientManager { + + public IbmMqClientManagerImpl() { + } + + @Override + public IbmMqHttpClient getClient(ConnectionDetailsEvent connectionDetailsEvent) { + + log.trace("Creating IBM MQ RESTful client for event broker [{}].", + connectionDetailsEvent.getMessagingServiceId()); + + //get authentication details from config file + AuthenticationDetailsEvent authenticationDetailsEvent = connectionDetailsEvent.getAuthenticationDetails() + .stream() + .findFirst().orElseThrow(() -> { + String message = String.format("Could not find authentication details for service with id [%s].", + connectionDetailsEvent.getMessagingServiceId()); + log.error(message); + return new NoSuchElementException(message); + }); + + //grab authentication details + String username = MessagingServiceConfigurationUtil.getUsername(authenticationDetailsEvent); + String password = MessagingServiceConfigurationUtil.getPassword(authenticationDetailsEvent); + String url = connectionDetailsEvent.getUrl(); + + //setup a basic webclient that will be used in generating + //the actual IBM HTTP Client + WebClient client = WebClient.builder() + .filter(ExchangeFilterFunctions.basicAuthentication(username, password)) + .baseUrl(url) + .build(); + + HttpServiceProxyFactory proxyFactory = HttpServiceProxyFactory + .builder(WebClientAdapter.forClient(client)).build(); + + return proxyFactory.createClient(IbmMqHttpClient.class); + } + +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqQueueProcessor.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqQueueProcessor.java new file mode 100644 index 00000000..d582da5c --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqQueueProcessor.java @@ -0,0 +1,39 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor; + +import com.solace.maas.ep.event.management.agent.plugin.constants.RouteConstants; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqHttpClient; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqQueueResponse; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.event.IbmMqQueueEvent; +import com.solace.maas.ep.event.management.agent.plugin.processor.base.ResultProcessorImpl; +import com.solace.maas.ep.event.management.agent.plugin.service.MessagingServiceDelegateService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +@Slf4j +@Component +public class IbmMqQueueProcessor extends ResultProcessorImpl, Void> { + private final MessagingServiceDelegateService messagingServiceDelegateService; + + @Autowired + public IbmMqQueueProcessor(MessagingServiceDelegateService messagingServiceDelegateService) { + super(); + this.messagingServiceDelegateService = messagingServiceDelegateService; + } + + @Override + public List handleEvent(Map properties, Void body) throws Exception { + String messagingServiceId = (String) properties.get(RouteConstants.MESSAGING_SERVICE_ID); + + IbmMqHttpClient client = messagingServiceDelegateService.getMessagingServiceClient(messagingServiceId); + + log.info("### Invoking Queue endpoint for broker with ID {}", messagingServiceId); + IbmMqQueueResponse queueList = client.getQueues(); + + return queueList.getQueue(); + } + +} \ No newline at end of file diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqSubscriptionProcessor.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqSubscriptionProcessor.java new file mode 100644 index 00000000..61520a2e --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqSubscriptionProcessor.java @@ -0,0 +1,39 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor; + +import com.solace.maas.ep.event.management.agent.plugin.constants.RouteConstants; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqHttpClient; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqSubscriptionResponse; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.event.IbmMqSubscriptionEvent; +import com.solace.maas.ep.event.management.agent.plugin.processor.base.ResultProcessorImpl; +import com.solace.maas.ep.event.management.agent.plugin.service.MessagingServiceDelegateService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +@Slf4j +@Component +public class IbmMqSubscriptionProcessor extends ResultProcessorImpl, Void> { + private final MessagingServiceDelegateService messagingServiceDelegateService; + + @Autowired + public IbmMqSubscriptionProcessor(MessagingServiceDelegateService messagingServiceDelegateService) { + super(); + this.messagingServiceDelegateService = messagingServiceDelegateService; + } + + @Override + public List handleEvent(Map properties, Void body) throws Exception { + String messagingServiceId = (String) properties.get(RouteConstants.MESSAGING_SERVICE_ID); + + IbmMqHttpClient client = messagingServiceDelegateService.getMessagingServiceClient(messagingServiceId); + + log.info("### Invoking Queue endpoint for broker with ID {}", messagingServiceId); + IbmMqSubscriptionResponse subscriptionList = client.getSubscriptions(); + + return subscriptionList.getSubscription(); + } + +} \ No newline at end of file diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqQueueEvent.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqQueueEvent.java new file mode 100644 index 00000000..f9ad31ac --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqQueueEvent.java @@ -0,0 +1,18 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.event; + +import lombok.Getter; + +import java.io.Serializable; + +/** + * Attributes parsed from the response JSON. + * Note: Other attributes may be returned in the raw JSON. + */ +@Getter +public class IbmMqQueueEvent implements Serializable { + + private static final long serialVersionUID = 7693606299215131178L; + + private String name; + private String type; +} \ No newline at end of file diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqSubscriptionEvent.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqSubscriptionEvent.java new file mode 100644 index 00000000..df9d5e65 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqSubscriptionEvent.java @@ -0,0 +1,19 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.event; + +import lombok.Data; + +import java.io.Serializable; + +/** + * Attributes parsed from the response JSON. + * Note: Other attributes may be returned in the raw JSON. + */ +@Data +public class IbmMqSubscriptionEvent implements Serializable { + + private static final long serialVersionUID = 7693606299215131178L; + + private String resolvedTopicString; + private String name; + private String id; +} \ No newline at end of file diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/delegate/IbmMqRouteDelegateImpl.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/delegate/IbmMqRouteDelegateImpl.java new file mode 100644 index 00000000..dfd69db7 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/delegate/IbmMqRouteDelegateImpl.java @@ -0,0 +1,58 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.delegate; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqRouteId; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqRouteType; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqScanType; +import com.solace.maas.ep.event.management.agent.plugin.jacoco.ExcludeFromJacocoGeneratedReport; +import com.solace.maas.ep.event.management.agent.plugin.route.RouteBundle; +import com.solace.maas.ep.event.management.agent.plugin.route.delegate.base.MessagingServiceRouteDelegateImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@ExcludeFromJacocoGeneratedReport +@SuppressWarnings("CPD-START") +@Component +@Slf4j +public class IbmMqRouteDelegateImpl extends MessagingServiceRouteDelegateImpl { + + public IbmMqRouteDelegateImpl() { + super("IBMMQ"); + log.debug("### PLUGIN `IBMMQ` HAS LOADED ###"); + } + + @Override + public List generateRouteList(List destinations, List recipients, + String scanType, String messagingServiceId) { + List result = new ArrayList<>(); + + switch (IbmMqScanType.valueOf(scanType)) { + case IBMMQ_ALL: + result.add(queueRouteBundle(destinations, recipients, messagingServiceId)); + result.add(subscriptionRouteBundle(destinations, recipients, messagingServiceId)); + break; + case IBMMQ_QUEUE: + result.add(queueRouteBundle(destinations, recipients, messagingServiceId)); + break; + case IBMMQ_SUBSCRIPTION: + result.add(subscriptionRouteBundle(destinations, recipients, messagingServiceId)); + break; + } + + return result; + } + + private RouteBundle queueRouteBundle(List destinations, List recipients, + String messagingServiceId) { + return createRouteBundle(destinations, recipients, IbmMqRouteType.IBMMQ_QUEUE.label, messagingServiceId, + IbmMqRouteId.IBMMQ_QUEUE.label, true); + } + + private RouteBundle subscriptionRouteBundle(List destinations, List recipients, + String messagingServiceId) { + return createRouteBundle(destinations, recipients, IbmMqRouteType.IBMMQ_SUBSCRIPTION.label, messagingServiceId, + IbmMqRouteId.IBMMQ_SUBSCRIPTION.label, false); + } +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqRouteId.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqRouteId.java new file mode 100644 index 00000000..fbdb27ea --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqRouteId.java @@ -0,0 +1,12 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration; + +public enum IbmMqRouteId { + IBMMQ_QUEUE("IBMMQQueueListing"), + IBMMQ_SUBSCRIPTION("IBMMQSubscriptionListing"); + + public final String label; + + IbmMqRouteId(String label) { + this.label = label; + } +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqRouteType.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqRouteType.java new file mode 100644 index 00000000..0601b43f --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqRouteType.java @@ -0,0 +1,12 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration; + +public enum IbmMqRouteType { + IBMMQ_QUEUE("queueListing"), + IBMMQ_SUBSCRIPTION("subscriptionListing"); + + public final String label; + + IbmMqRouteType(String label) { + this.label = label; + } +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqScanType.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqScanType.java new file mode 100644 index 00000000..d4a2b90e --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqScanType.java @@ -0,0 +1,8 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration; + +public enum IbmMqScanType { + + IBMMQ_ALL, + IBMMQ_QUEUE, + IBMMQ_SUBSCRIPTION; +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/handler/IbmMqQueueDataPublisherRoute.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/handler/IbmMqQueueDataPublisherRoute.java new file mode 100644 index 00000000..69029628 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/handler/IbmMqQueueDataPublisherRoute.java @@ -0,0 +1,23 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.handler; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.IbmMqQueueProcessor; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqRouteId; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqRouteType; +import com.solace.maas.ep.event.management.agent.plugin.processor.ScanTypeDescendentsProcessor; +import com.solace.maas.ep.event.management.agent.plugin.processor.logging.MDCProcessor; +import com.solace.maas.ep.event.management.agent.plugin.route.handler.base.DataPublisherRouteBuilder; +import com.solace.maas.ep.event.management.agent.plugin.route.manager.RouteManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class IbmMqQueueDataPublisherRoute extends DataPublisherRouteBuilder { + + @Autowired + public IbmMqQueueDataPublisherRoute(IbmMqQueueProcessor processor, RouteManager routeManager, + MDCProcessor mdcProcessor, ScanTypeDescendentsProcessor scanTypeDescendentsProcessor) { + super(processor, IbmMqRouteId.IBMMQ_QUEUE.label, IbmMqRouteType.IBMMQ_QUEUE.label, + routeManager, mdcProcessor, scanTypeDescendentsProcessor); + + } +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/handler/IbmMqSubscriptionDataPublisherRoute.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/handler/IbmMqSubscriptionDataPublisherRoute.java new file mode 100644 index 00000000..855e6c3c --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/handler/IbmMqSubscriptionDataPublisherRoute.java @@ -0,0 +1,23 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.handler; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.IbmMqSubscriptionProcessor; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqRouteId; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqRouteType; +import com.solace.maas.ep.event.management.agent.plugin.processor.ScanTypeDescendentsProcessor; +import com.solace.maas.ep.event.management.agent.plugin.processor.logging.MDCProcessor; +import com.solace.maas.ep.event.management.agent.plugin.route.handler.base.DataPublisherRouteBuilder; +import com.solace.maas.ep.event.management.agent.plugin.route.manager.RouteManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class IbmMqSubscriptionDataPublisherRoute extends DataPublisherRouteBuilder { + + @Autowired + public IbmMqSubscriptionDataPublisherRoute(IbmMqSubscriptionProcessor processor, RouteManager routeManager, + MDCProcessor mdcProcessor, ScanTypeDescendentsProcessor scanTypeDescendentsProcessor) { + super(processor, IbmMqRouteId.IBMMQ_SUBSCRIPTION.label, IbmMqRouteType.IBMMQ_SUBSCRIPTION.label, + routeManager, mdcProcessor, scanTypeDescendentsProcessor); + } + +} diff --git a/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplicationTests.java b/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplicationTests.java new file mode 100644 index 00000000..5370ae56 --- /dev/null +++ b/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplicationTests.java @@ -0,0 +1,116 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqHttpClient; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqQueueResponse; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqSubscriptionResponse; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.manager.client.IbmMqClientManagerImpl; +import com.solace.maas.ep.event.management.agent.plugin.messagingService.event.AuthenticationDetailsEvent; +import com.solace.maas.ep.event.management.agent.plugin.messagingService.event.ConnectionDetailsEvent; +import com.solace.maas.ep.event.management.agent.plugin.messagingService.event.CredentialDetailsEvent; +import com.solace.maas.ep.event.management.agent.plugin.messagingService.event.EventProperty; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import org.junit.Assert; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = IbmMqTestConfig.class) +@SuppressWarnings("PMD") +class IbmMqApplicationTests { + + public static MockWebServer mockWebServer; + + private ConnectionDetailsEvent connectionDetailsEvent; + + @BeforeAll + static void setup() throws Exception { + mockWebServer = new MockWebServer(); + mockWebServer.start(); + + } + + @BeforeEach + void init() throws Exception { + String baseurl = String.format("http://localhost:%s", mockWebServer.getPort()); + + connectionDetailsEvent = ConnectionDetailsEvent.builder() + .url(baseurl) + .messagingServiceId("1") + .name("name") + .authenticationDetails(List.of(AuthenticationDetailsEvent.builder() + .credentials(List.of(CredentialDetailsEvent.builder() + .properties(List.of( + EventProperty.builder() + .name("username") + .value("ush") + .build(), + EventProperty.builder() + .name("password") + .value("password") + .build())) + .build())) + .build())) + .build(); + } + + @Test + void testGetQueues() throws Exception { + IbmMqClientManagerImpl client = new IbmMqClientManagerImpl(); + IbmMqHttpClient httpClient = client.getClient(connectionDetailsEvent); + + Path filePath = Paths.get("src/test/resources/queue_response.json"); + String queueJson = Files.readString(filePath); + + mockWebServer.enqueue(new MockResponse() + .setBody(queueJson) + .addHeader("Content-Type", "application/json") + ); + + IbmMqQueueResponse response = httpClient.getQueues(); + + long expected_queue_count = 8; + + Assert.assertEquals("Unexpected number of queues returned.", expected_queue_count, response.getQueue().size()); + Assert.assertEquals("First element does not match expected queue name,", + "SYSTEM.ADMIN.STATISTICS.QUEUE", response.getQueue().get(0).getName()); + } + + @Test + void testGetSubscriptions() throws Exception { + IbmMqClientManagerImpl client = new IbmMqClientManagerImpl(); + IbmMqHttpClient httpClient = client.getClient(connectionDetailsEvent); + + //load our test file + Path filePath = Paths.get("src/test/resources/subscription_response.json"); + String subJson = Files.readString(filePath); + + //add it to our Mock Webserver. + //The server will respond with the contents of the test file + mockWebServer.enqueue(new MockResponse() + .setBody(subJson) + .addHeader("Content-Type", "application/json") + ); + + IbmMqSubscriptionResponse response = httpClient.getSubscriptions(); + + //ensure we received correct data + long expected_topic_count = 15; + + Assert.assertEquals("Unexpected number of queues returned.", expected_topic_count, response.getSubscription().size()); + Assert.assertEquals("First element does not match expected subscription name,", + "$SYS/MQ/INFO/QMGR/QM1/Monitor/CPU/SystemSummary", response.getSubscription().get(0).getResolvedTopicString()); + } + + @AfterAll + static void shutDown() throws Exception { + mockWebServer.shutdown(); + } +} diff --git a/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqTestConfig.java b/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqTestConfig.java new file mode 100644 index 00000000..af95986e --- /dev/null +++ b/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqTestConfig.java @@ -0,0 +1,40 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq; + +import com.solace.maas.ep.event.management.agent.plugin.processor.ScanTypeDescendentsProcessor; +import com.solace.maas.ep.event.management.agent.plugin.processor.logging.MDCProcessor; +import com.solace.maas.ep.event.management.agent.plugin.route.manager.RouteManager; +import com.solace.maas.ep.event.management.agent.plugin.service.MessagingServiceDelegateService; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; + +import static org.mockito.Mockito.mock; + +@TestConfiguration +public class IbmMqTestConfig { + + @Bean + @Primary + public MessagingServiceDelegateService messagingServiceDelegateService() { + return mock(MessagingServiceDelegateService.class); + } + + @Bean + @Primary + public MDCProcessor mdcProcessor() { + return mock(MDCProcessor.class); + } + + @Bean + @Primary + public ScanTypeDescendentsProcessor emptyScanEntityProcessor() { + return mock(ScanTypeDescendentsProcessor.class); + } + + @Bean + @Primary + public RouteManager RouteManager() { + return mock(RouteManager.class); + } + +} diff --git a/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/delegate/IbmMqRouteDelegateImplTests.java b/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/delegate/IbmMqRouteDelegateImplTests.java new file mode 100644 index 00000000..c5bc2cef --- /dev/null +++ b/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/delegate/IbmMqRouteDelegateImplTests.java @@ -0,0 +1,61 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.delegate; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.IbmMqTestConfig; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqScanType; +import com.solace.maas.ep.event.management.agent.plugin.route.RouteBundle; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; + +@ActiveProfiles("TEST") +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = IbmMqTestConfig.class) +public class IbmMqRouteDelegateImplTests { + + @InjectMocks + private IbmMqRouteDelegateImpl ibmMqRouteDelegate; + + private final List destinations = List.of( + RouteBundle.builder() + .destinations(List.of()) + .recipients(List.of()) + .routeId("testRoute") + .firstRouteInChain(false) + .messagingServiceId("service1") + .build()); + + @Test + public void testGenerateIbmMqQueueRouteList() { + List routeBundles = ibmMqRouteDelegate.generateRouteList(destinations, List.of(), + IbmMqScanType.IBMMQ_QUEUE.name(), + "service1"); + + assertThatNoException(); + assertThat(!routeBundles.isEmpty()); + } + + @Test + public void testGenerateIbmMqSubscriptionRouteList() { + List routeBundles = ibmMqRouteDelegate.generateRouteList(destinations, List.of(), + IbmMqScanType.IBMMQ_SUBSCRIPTION.name(), + "service1"); + + assertThatNoException(); + assertThat(!routeBundles.isEmpty()); + } + + @Test + public void testGenerateIbmMqAllRouteList() { + List routeBundles = ibmMqRouteDelegate.generateRouteList(destinations, List.of(), + IbmMqScanType.IBMMQ_ALL.name(), + "service1"); + + assertThatNoException(); + assertThat(!routeBundles.isEmpty()); + } +} diff --git a/service/ibmmq-plugin/src/test/resources/queue_response.json b/service/ibmmq-plugin/src/test/resources/queue_response.json new file mode 100644 index 00000000..f3457189 --- /dev/null +++ b/service/ibmmq-plugin/src/test/resources/queue_response.json @@ -0,0 +1,42 @@ +{ + "queue": [ + { + "name": "SYSTEM.ADMIN.STATISTICS.QUEUE", + "type": "local" + }, + { + "name": "SYSTEM.DEFAULT.INITIATION.QUEUE", + "type": "local" + }, + { + "name": "SYSTEM.ADMIN.ACCOUNTING.QUEUE", + "type": "local" + }, + { + "name": "SYSTEM.ADMIN.LOGGER.EVENT", + "type": "local" + }, + { + "name": "SYSTEM.BROKER.CONTROL.QUEUE", + "type": "local" + }, + { + "name": "SYSTEM.CLUSTER.TRANSMIT.MODEL.QUEUE", + "model": { + "type": "permanentDynamic" + }, + "type": "model" + }, + { + "name": "SYSTEM.ADMIN.TRACE.ROUTE.QUEUE", + "type": "local" + }, + { + "name": "SYSTEM.MQEXPLORER.REPLY.MODEL", + "model": { + "type": "temporaryDynamic" + }, + "type": "model" + } + ] +} \ No newline at end of file diff --git a/service/ibmmq-plugin/src/test/resources/subscription_response.json b/service/ibmmq-plugin/src/test/resources/subscription_response.json new file mode 100644 index 00000000..6a113e30 --- /dev/null +++ b/service/ibmmq-plugin/src/test/resources/subscription_response.json @@ -0,0 +1,79 @@ +{ + "subscription": [ + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/CPU/SystemSummary", + "name": "", + "id": "414D5120514D312020202020202020203C434B6567270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/CPU/QMgrSummary", + "name": "", + "id": "414D5120514D312020202020202020203C434B6569270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/DISK/SystemSummary", + "name": "", + "id": "414D5120514D312020202020202020203C434B656B270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/DISK/QMgrSummary", + "name": "", + "id": "414D5120514D312020202020202020203C434B656D270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/DISK/Log", + "name": "", + "id": "414D5120514D312020202020202020203C434B656F270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/PUBLISH", + "name": "", + "id": "414D5120514D312020202020202020203C434B6571270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/CONNDISC", + "name": "", + "id": "414D5120514D312020202020202020203C434B6573270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/OPENCLOSE", + "name": "", + "id": "414D5120514D312020202020202020203C434B6575270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/INQSET", + "name": "", + "id": "414D5120514D312020202020202020203C434B6577270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/PUT", + "name": "", + "id": "414D5120514D312020202020202020203C434B6579270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/GET", + "name": "", + "id": "414D5120514D312020202020202020203C434B657B270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/SYNCPOINT", + "name": "", + "id": "414D5120514D312020202020202020203C434B657D270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/SUBSCRIBE", + "name": "", + "id": "414D5120514D312020202020202020203C434B657F270040" + }, + { + "resolvedTopicString": "", + "name": "SYSTEM.DEFAULT.SUB", + "id": "414D5120514D312020202020202020207964416503010040" + }, + { + "resolvedTopicString": "SYSTEM.BROKER.ADMIN.STREAM/MQ/QM1 /StreamSupport", + "name": "QM1 SYSTEM.BROKER.INTER.BROKER.COMMUNICATIONS 414D51590101000000000000000000000000000000000000 SYSTEM.BROKER.ADMIN.STREAM MQ/QM1 /StreamSupport", + "id": "414D5120514D31202020202020202020B2644165061D0040" + } + ] +} \ No newline at end of file diff --git a/service/pom.xml b/service/pom.xml index d7e240d4..a7aee78d 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -21,6 +21,7 @@ terraform-plugin local-storage-plugin confluent-schema-registry-plugin + ibmmq-plugin application