This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch camel-master in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit babab8dd65ffe1943973e7114186d00f1c95f90b Author: JiriOndrusek <ondrusek.j...@gmail.com> AuthorDate: Tue Mar 16 11:29:38 2021 +0100 Splunk native support #1698 --- .../ROOT/pages/reference/extensions/splunk.adoc | 16 +- .../reference/components/aws-secrets-manager.adoc | 1 - .../ROOT/partials/reference/components/splunk.adoc | 8 +- extensions-jvm/pom.xml | 1 - .../splunk/deployment/SplunkProcessor.java | 46 ----- .../component/splunk/it/SplunkResource.java | 51 ----- extensions/pom.xml | 1 + .../splunk/deployment/pom.xml | 4 +- .../splunk/deployment/SplunkProcessor.java | 92 +++++++++ {extensions-jvm => extensions}/splunk/pom.xml | 5 +- .../splunk/runtime/pom.xml | 8 +- .../main/resources/META-INF/quarkus-extension.yaml | 3 +- integration-tests/pom.xml | 1 + .../splunk}/pom.xml | 68 ++++++- .../component/splunk/it/SplunkResource.java | 207 +++++++++++++++++++++ .../quarkus/component/splunk/it/SplunkIT.java | 16 +- .../quarkus/component/splunk/it/SplunkTest.java | 150 +++++++++++++++ .../component/splunk/it/SplunkTestResource.java | 79 ++++++++ tooling/scripts/test-categories.yaml | 1 + 19 files changed, 625 insertions(+), 133 deletions(-) diff --git a/docs/modules/ROOT/pages/reference/extensions/splunk.adoc b/docs/modules/ROOT/pages/reference/extensions/splunk.adoc index 2031f44..0368c70 100644 --- a/docs/modules/ROOT/pages/reference/extensions/splunk.adoc +++ b/docs/modules/ROOT/pages/reference/extensions/splunk.adoc @@ -2,15 +2,15 @@ // This file was generated by camel-quarkus-maven-plugin:update-extension-doc-page = Splunk :cq-artifact-id: camel-quarkus-splunk -:cq-native-supported: false -:cq-status: Preview +:cq-native-supported: true +:cq-status: Stable :cq-description: Publish or search for events in Splunk. :cq-deprecated: false -:cq-jvm-since: 1.1.0 -:cq-native-since: n/a +:cq-jvm-since: 1.8.0 +:cq-native-since: 1.8.0 [.badges] -[.badge-key]##JVM since##[.badge-supported]##1.1.0## [.badge-key]##Native##[.badge-unsupported]##unsupported## +[.badge-key]##JVM since##[.badge-supported]##1.8.0## [.badge-key]##Native since##[.badge-supported]##1.8.0## Publish or search for events in Splunk. @@ -31,3 +31,9 @@ Please refer to the above link for usage and configuration details. ---- Check the xref:user-guide/index.adoc[User guide] for more information about writing Camel Quarkus applications. + +== SSL in native mode + +This extension auto-enables SSL support in native mode. Hence you do not need to add +`quarkus.ssl.native=true` to your `application.properties` yourself. See also +https://quarkus.io/guides/native-and-ssl[Quarkus SSL guide]. diff --git a/docs/modules/ROOT/partials/reference/components/aws-secrets-manager.adoc b/docs/modules/ROOT/partials/reference/components/aws-secrets-manager.adoc deleted file mode 100644 index a509c1d..0000000 --- a/docs/modules/ROOT/partials/reference/components/aws-secrets-manager.adoc +++ /dev/null @@ -1 +0,0 @@ -// Empty partial for a Camel bit unsupported by Camel Quarkus to avoid warnings when this file is included from a Camel page diff --git a/docs/modules/ROOT/partials/reference/components/splunk.adoc b/docs/modules/ROOT/partials/reference/components/splunk.adoc index 6d99c40..c939e40 100644 --- a/docs/modules/ROOT/partials/reference/components/splunk.adoc +++ b/docs/modules/ROOT/partials/reference/components/splunk.adoc @@ -2,11 +2,11 @@ // This file was generated by camel-quarkus-maven-plugin:update-extension-doc-page :cq-artifact-id: camel-quarkus-splunk :cq-artifact-id-base: splunk -:cq-native-supported: false -:cq-status: Preview +:cq-native-supported: true +:cq-status: Stable :cq-deprecated: false -:cq-jvm-since: 1.1.0 -:cq-native-since: n/a +:cq-jvm-since: 1.8.0 +:cq-native-since: 1.8.0 :cq-camel-part-name: splunk :cq-camel-part-title: Splunk :cq-camel-part-description: Publish or search for events in Splunk. diff --git a/extensions-jvm/pom.xml b/extensions-jvm/pom.xml index ec38785..b5c9d55 100644 --- a/extensions-jvm/pom.xml +++ b/extensions-jvm/pom.xml @@ -108,7 +108,6 @@ <module>snmp</module> <module>soroush</module> <module>spark</module> - <module>splunk</module> <module>splunk-hec</module> <module>stitch</module> <module>stomp</module> diff --git a/extensions-jvm/splunk/deployment/src/main/java/org/apache/camel/quarkus/component/splunk/deployment/SplunkProcessor.java b/extensions-jvm/splunk/deployment/src/main/java/org/apache/camel/quarkus/component/splunk/deployment/SplunkProcessor.java deleted file mode 100644 index 2d0ae75..0000000 --- a/extensions-jvm/splunk/deployment/src/main/java/org/apache/camel/quarkus/component/splunk/deployment/SplunkProcessor.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.camel.quarkus.component.splunk.deployment; - -import io.quarkus.deployment.annotations.BuildStep; -import io.quarkus.deployment.annotations.ExecutionTime; -import io.quarkus.deployment.annotations.Record; -import io.quarkus.deployment.builditem.FeatureBuildItem; -import io.quarkus.deployment.pkg.steps.NativeBuild; -import org.apache.camel.quarkus.core.JvmOnlyRecorder; -import org.jboss.logging.Logger; - -class SplunkProcessor { - - private static final Logger LOG = Logger.getLogger(SplunkProcessor.class); - private static final String FEATURE = "camel-splunk"; - - @BuildStep - FeatureBuildItem feature() { - return new FeatureBuildItem(FEATURE); - } - - /** - * Remove this once this extension starts supporting the native mode. - */ - @BuildStep(onlyIf = NativeBuild.class) - @Record(value = ExecutionTime.RUNTIME_INIT) - void warnJvmInNative(JvmOnlyRecorder recorder) { - JvmOnlyRecorder.warnJvmInNative(LOG, FEATURE); // warn at build time - recorder.warnJvmInNative(FEATURE); // warn at runtime - } -} diff --git a/extensions-jvm/splunk/integration-test/src/main/java/org/apache/camel/quarkus/component/splunk/it/SplunkResource.java b/extensions-jvm/splunk/integration-test/src/main/java/org/apache/camel/quarkus/component/splunk/it/SplunkResource.java deleted file mode 100644 index 55b4cfe..0000000 --- a/extensions-jvm/splunk/integration-test/src/main/java/org/apache/camel/quarkus/component/splunk/it/SplunkResource.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.camel.quarkus.component.splunk.it; - -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import org.apache.camel.CamelContext; -import org.jboss.logging.Logger; - -@Path("/splunk") -@ApplicationScoped -public class SplunkResource { - - private static final Logger LOG = Logger.getLogger(SplunkResource.class); - - private static final String COMPONENT_SPLUNK = "splunk"; - @Inject - CamelContext context; - - @Path("/load/component/splunk") - @GET - @Produces(MediaType.TEXT_PLAIN) - public Response loadComponentSplunk() throws Exception { - /* This is an autogenerated test */ - if (context.getComponent(COMPONENT_SPLUNK) != null) { - return Response.ok().build(); - } - LOG.warnf("Could not load [%s] from the Camel context", COMPONENT_SPLUNK); - return Response.status(500, COMPONENT_SPLUNK + " could not be loaded from the Camel context").build(); - } -} diff --git a/extensions/pom.xml b/extensions/pom.xml index f83d486..f2f6b9e 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -206,6 +206,7 @@ <module>snakeyaml</module> <module>soap</module> <module>solr</module> + <module>splunk</module> <module>spring-rabbitmq</module> <module>sql</module> <module>ssh</module> diff --git a/extensions-jvm/splunk/deployment/pom.xml b/extensions/splunk/deployment/pom.xml similarity index 91% rename from extensions-jvm/splunk/deployment/pom.xml rename to extensions/splunk/deployment/pom.xml index ec453ef..a926b21 100644 --- a/extensions-jvm/splunk/deployment/pom.xml +++ b/extensions/splunk/deployment/pom.xml @@ -17,7 +17,9 @@ limitations under the License. --> -<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"> +<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.apache.camel.quarkus</groupId> diff --git a/extensions/splunk/deployment/src/main/java/org/apache/camel/quarkus/component/splunk/deployment/SplunkProcessor.java b/extensions/splunk/deployment/src/main/java/org/apache/camel/quarkus/component/splunk/deployment/SplunkProcessor.java new file mode 100644 index 0000000..69ae59d --- /dev/null +++ b/extensions/splunk/deployment/src/main/java/org/apache/camel/quarkus/component/splunk/deployment/SplunkProcessor.java @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.splunk.deployment; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.CombinedIndexBuildItem; +import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem; +import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.deployment.builditem.IndexDependencyBuildItem; +import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; +import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem; +import org.jboss.jandex.DotName; +import org.jboss.jandex.IndexView; +import org.joda.time.DateTimeZone; + +class SplunkProcessor { + + private static final String FEATURE = "camel-splunk"; + + @BuildStep + FeatureBuildItem feature() { + return new FeatureBuildItem(FEATURE); + } + + @BuildStep + ExtensionSslNativeSupportBuildItem activateSslNativeSupport() { + return new ExtensionSslNativeSupportBuildItem(FEATURE); + } + + @BuildStep + RuntimeInitializedClassBuildItem runtimeInitBcryptUtil() { + // this class uses a SecureRandom which needs to be initialised at run time + return new RuntimeInitializedClassBuildItem("com.splunk.HttpService"); + } + + @BuildStep + ReflectiveClassBuildItem registerForReflection(CombinedIndexBuildItem combinedIndex) { + IndexView index = combinedIndex.getIndex(); + + List<String> dtos = new LinkedList<>(); + dtos.addAll(index.getAllKnownSubclasses(DotName.createSimple("com.splunk.Input")).stream() + .map(c -> c.name().toString()).collect(Collectors.toList())); + + return new ReflectiveClassBuildItem(false, false, dtos.toArray(new String[dtos.size()])); + } + + @BuildStep + List<ReflectiveClassBuildItem> reflectiveClasses() { + return Arrays.asList(new ReflectiveClassBuildItem(false, false, "com.splunk.Index"), + new ReflectiveClassBuildItem(false, false, "com.splunk.SavedSearch"), + new ReflectiveClassBuildItem(false, false, "com.splunk.Service")); + } + + @BuildStep + IndexDependencyBuildItem registerDependencyForIndex() { + return new IndexDependencyBuildItem("org.apache.servicemix.bundles", "org.apache.servicemix.bundles.splunk"); + } + + @BuildStep + NativeImageResourceBuildItem nativeImageResources() { + List<String> timezones = new ArrayList<>(); + for (String timezone : DateTimeZone.getAvailableIDs()) { + String[] zoneParts = timezone.split("/"); + if (zoneParts.length == 2) { + timezones.add(String.format("org/joda/time/tz/data/%s/%s", zoneParts[0], zoneParts[1])); + } + } + return new NativeImageResourceBuildItem(timezones); + } + +} diff --git a/extensions-jvm/splunk/pom.xml b/extensions/splunk/pom.xml similarity index 84% rename from extensions-jvm/splunk/pom.xml rename to extensions/splunk/pom.xml index ffc07b5..f878d22 100644 --- a/extensions-jvm/splunk/pom.xml +++ b/extensions/splunk/pom.xml @@ -17,7 +17,9 @@ limitations under the License. --> -<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"> +<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.apache.camel.quarkus</groupId> @@ -33,6 +35,5 @@ <modules> <module>deployment</module> <module>runtime</module> - <module>integration-test</module> </modules> </project> diff --git a/extensions-jvm/splunk/runtime/pom.xml b/extensions/splunk/runtime/pom.xml similarity index 91% rename from extensions-jvm/splunk/runtime/pom.xml rename to extensions/splunk/runtime/pom.xml index 1cede50..b4567b7 100644 --- a/extensions-jvm/splunk/runtime/pom.xml +++ b/extensions/splunk/runtime/pom.xml @@ -17,7 +17,9 @@ limitations under the License. --> -<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"> +<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.apache.camel.quarkus</groupId> @@ -31,7 +33,8 @@ <description>Publish or search for events in Splunk.</description> <properties> - <camel.quarkus.jvmSince>1.1.0</camel.quarkus.jvmSince> + <camel.quarkus.jvmSince>1.8.0</camel.quarkus.jvmSince> + <camel.quarkus.nativeSince>1.8.0</camel.quarkus.nativeSince> </properties> <dependencyManagement> @@ -79,6 +82,7 @@ </plugins> </build> + <profiles> <profile> <id>full</id> diff --git a/extensions-jvm/splunk/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/splunk/runtime/src/main/resources/META-INF/quarkus-extension.yaml similarity index 97% rename from extensions-jvm/splunk/runtime/src/main/resources/META-INF/quarkus-extension.yaml rename to extensions/splunk/runtime/src/main/resources/META-INF/quarkus-extension.yaml index de4224a..1a24bcb 100644 --- a/extensions-jvm/splunk/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/splunk/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -24,9 +24,8 @@ name: "Camel Splunk" description: "Publish or search for events in Splunk" metadata: - unlisted: true guide: "https://camel.apache.org/camel-quarkus/latest/reference/extensions/splunk.html" categories: - "integration" status: - - "preview" + - "stable" diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 08fd199..e85d69f 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -184,6 +184,7 @@ <module>smallrye-reactive-messaging</module> <module>soap</module> <module>solr</module> + <module>splunk</module> <module>spring-rabbitmq</module> <module>sql</module> <module>ssh</module> diff --git a/extensions-jvm/splunk/integration-test/pom.xml b/integration-tests/splunk/pom.xml similarity index 54% rename from extensions-jvm/splunk/integration-test/pom.xml rename to integration-tests/splunk/pom.xml index cdc197b..a6d5639 100644 --- a/extensions-jvm/splunk/integration-test/pom.xml +++ b/integration-tests/splunk/pom.xml @@ -17,17 +17,19 @@ limitations under the License. --> -<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"> +<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.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-build-parent-it</artifactId> + <artifactId>camel-quarkus-integration-tests</artifactId> <version>1.8.0-SNAPSHOT</version> - <relativePath>../../../poms/build-parent-it/pom.xml</relativePath> + <relativePath>../pom.xml</relativePath> </parent> - <artifactId>camel-quarkus-splunk-integration-test</artifactId> - <name>Camel Quarkus :: Splunk :: Integration Test</name> + <artifactId>camel-quarkus-integration-test-splunk</artifactId> + <name>Camel Quarkus :: Integration Tests :: Splunk</name> <description>Integration tests for Camel Quarkus Splunk extension</description> <dependencyManagement> @@ -51,6 +53,14 @@ <groupId>io.quarkus</groupId> <artifactId>quarkus-resteasy</artifactId> </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-resteasy-jackson</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-direct</artifactId> + </dependency> <!-- test dependencies --> <dependency> @@ -63,10 +73,28 @@ <artifactId>rest-assured</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.testcontainers</groupId> + <artifactId>testcontainers</artifactId> + <scope>test</scope> + </dependency> <!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory --> <dependency> <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-direct-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-splunk-deployment</artifactId> <version>${project.version}</version> <type>pom</type> @@ -80,4 +108,34 @@ </dependency> </dependencies> + <profiles> + <profile> + <id>native</id> + <activation> + <property> + <name>native</name> + </property> + </activation> + <properties> + <quarkus.package.type>native</quarkus.package.type> + </properties> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> + </project> diff --git a/integration-tests/splunk/src/main/java/org/apache/camel/quarkus/component/splunk/it/SplunkResource.java b/integration-tests/splunk/src/main/java/org/apache/camel/quarkus/component/splunk/it/SplunkResource.java new file mode 100644 index 0000000..6a8dc72 --- /dev/null +++ b/integration-tests/splunk/src/main/java/org/apache/camel/quarkus/component/splunk/it/SplunkResource.java @@ -0,0 +1,207 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.splunk.it; + +import java.net.URI; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.inject.Named; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.camel.CamelContext; +import org.apache.camel.ConsumerTemplate; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.component.splunk.SplunkComponent; +import org.apache.camel.component.splunk.SplunkConfiguration; +import org.apache.camel.component.splunk.event.SplunkEvent; +import org.eclipse.microprofile.config.inject.ConfigProperty; + +@Path("/splunk") +@ApplicationScoped +public class SplunkResource { + + public static final String PARAM_REMOTE_PORT = "org.apache.camel.quarkus.component.splunk.it.SplunkResource_remotePort"; + public static final String PARAM_TCP_PORT = "org.apache.camel.quarkus.component.splunk.it.SplunkResource_tcpPort"; + public static final String SOURCE = "test"; + public static final String SOURCE_TYPE = "testSource"; + public static final int LOCAL_TCP_PORT = 9998; + + @Inject + ProducerTemplate producerTemplate; + + @Inject + ConsumerTemplate consumerTemplate; + + @ConfigProperty(name = PARAM_REMOTE_PORT) + Integer port; + + @ConfigProperty(name = PARAM_TCP_PORT) + Integer tcpPort; + + @Inject + CamelContext camelContext; + + @Named + SplunkComponent splunk() { + SplunkComponent component = new SplunkComponent(); + component.setSplunkConfigurationFactory(parameters -> new SplunkConfiguration()); + + return component; + } + + @Path("/normal") + @POST + @Produces(MediaType.APPLICATION_JSON) + public List normal(String search) throws Exception { + String url = String.format( + "splunk://normal?scheme=http&port=%d&delay=5000&initEarliestTime=-10s&search=" + + search, + port); + + final SplunkEvent m1 = consumerTemplate.receiveBody(url, 1000, SplunkEvent.class); + final SplunkEvent m2 = consumerTemplate.receiveBody(url, 1000, SplunkEvent.class); + final SplunkEvent m3 = consumerTemplate.receiveBody(url, 1000, SplunkEvent.class); + + List result = Arrays.stream(new SplunkEvent[] { m1, m2, m3 }) + .map(m -> m.getEventData().entrySet().stream() + .filter(e -> !e.getKey().startsWith("_")) + .collect(Collectors.toMap( + Map.Entry::getKey, + Map.Entry::getValue, + (v1, v2) -> v1))) + .collect(Collectors.toList()); + + return result; + } + + @Path("/savedSearch") + @POST + public String savedSearch(String name) throws Exception { + String url = String.format( + "splunk://savedsearch?scheme=http&port=%d&delay=500&initEarliestTime=-1m&savedsearch=%s", + port, name); + + final SplunkEvent m1 = consumerTemplate.receiveBody(url, 5000, SplunkEvent.class); + final SplunkEvent m2 = consumerTemplate.receiveBody(url, 1000, SplunkEvent.class); + final SplunkEvent m3 = consumerTemplate.receiveBody(url, 1000, SplunkEvent.class); + + List result = Arrays.stream(new SplunkEvent[] { m1, m2, m3 }) + .map(m -> { + if (m == null) { + return "null"; + } + return m.getEventData().get("_raw"); + }) + .collect(Collectors.toList()); + + return result.toString(); + } + + @Path("/directRealtimePolling") + @GET + @Produces(MediaType.APPLICATION_JSON) + public Map directRealtimePolling() throws Exception { + final SplunkEvent m1 = consumerTemplate.receiveBody("direct:realtimePolling", 3000, SplunkEvent.class); + + if (m1 == null) { + return Collections.emptyMap(); + } + + Map result = m1.getEventData().entrySet().stream() + .filter(e -> !e.getKey().startsWith("_")) + .collect(Collectors.toMap( + Map.Entry::getKey, + Map.Entry::getValue, + (v1, v2) -> v1)); + + return result; + } + + @Path("/startRealtimePolling") + @POST + public void startPolling(String search) { + // use another thread for polling consumer to demonstrate that we can wait before + // the message is sent to the queue + Executors.newSingleThreadExecutor().execute(() -> { + String url = String.format( + "splunk://realtime?scheme=http&port=%d&delay=3000&initEarliestTime=rt-10s&latestTime=RAW(rt+40s)&search=" + + search, + port); + SplunkEvent body = consumerTemplate.receiveBody(url, SplunkEvent.class); + producerTemplate.sendBody("direct:realtimePolling", body); + }); + } + + @Path("/submit") + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.TEXT_PLAIN) + public Response submit(Map<String, String> message, @QueryParam("index") String index) throws Exception { + return post(message, "submit", index, null); + } + + @Path("/stream") + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.TEXT_PLAIN) + public Response stream(Map<String, String> message, @QueryParam("index") String index) throws Exception { + return post(message, "stream", index, null); + } + + @Path("/tcp") + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.TEXT_PLAIN) + public Response tcp(Map<String, String> message, @QueryParam("index") String index) throws Exception { + return post(message, "tcp", index, tcpPort); + } + + private Response post(Map<String, String> message, String endpoint, String index, Integer tcpPort) throws Exception { + SplunkEvent se = new SplunkEvent(); + for (Map.Entry<String, String> e : message.entrySet()) { + se.addPair(e.getKey(), e.getValue()); + } + + String url = String.format( + "splunk:%s?scheme=http&port=%d&index=%s&sourceType=%s&source=%s", + endpoint, port, index, SOURCE_TYPE, SOURCE); + if (tcpPort != null) { + url = String.format( + "splunk:%s?username=admin&password=changeit&scheme=http&port=%d&index=%s&sourceType=%s&source=%s&tcpReceiverLocalPort=%d&tcpReceiverPort=%d", + endpoint, port, index, SOURCE_TYPE, SOURCE, LOCAL_TCP_PORT, tcpPort); + } + final String response = producerTemplate.requestBody(url, se, String.class); + return Response + .created(new URI("https://camel.apache.org/")) + .entity(response) + .build(); + } +} diff --git a/extensions-jvm/splunk/integration-test/src/test/java/org/apache/camel/quarkus/component/splunk/it/SplunkTest.java b/integration-tests/splunk/src/test/java/org/apache/camel/quarkus/component/splunk/it/SplunkIT.java similarity index 70% rename from extensions-jvm/splunk/integration-test/src/test/java/org/apache/camel/quarkus/component/splunk/it/SplunkTest.java rename to integration-tests/splunk/src/test/java/org/apache/camel/quarkus/component/splunk/it/SplunkIT.java index 57ddf6d..00bc15c 100644 --- a/extensions-jvm/splunk/integration-test/src/test/java/org/apache/camel/quarkus/component/splunk/it/SplunkTest.java +++ b/integration-tests/splunk/src/test/java/org/apache/camel/quarkus/component/splunk/it/SplunkIT.java @@ -16,19 +16,9 @@ */ package org.apache.camel.quarkus.component.splunk.it; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; +import io.quarkus.test.junit.NativeImageTest; -@QuarkusTest -class SplunkTest { - - @Test - public void loadComponentSplunk() { - /* A simple autogenerated test */ - RestAssured.get("/splunk/load/component/splunk") - .then() - .statusCode(200); - } +@NativeImageTest +class SplunkIT extends SplunkTest { } diff --git a/integration-tests/splunk/src/test/java/org/apache/camel/quarkus/component/splunk/it/SplunkTest.java b/integration-tests/splunk/src/test/java/org/apache/camel/quarkus/component/splunk/it/SplunkTest.java new file mode 100644 index 0000000..b1ad98f --- /dev/null +++ b/integration-tests/splunk/src/test/java/org/apache/camel/quarkus/component/splunk/it/SplunkTest.java @@ -0,0 +1,150 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.splunk.it; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import org.apache.camel.util.CollectionHelper; +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.Matchers.anyOf; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; + +@QuarkusTest +@QuarkusTestResource(SplunkTestResource.class) +class SplunkTest { + + @Test + public void testWriteTcpAndReadNormal() { + write("_normal", SplunkTestResource.TEST_INDEX, "tcp"); + + List<Map<String, String>> result = RestAssured.given() + .contentType(ContentType.TEXT) + .body(String.format( + "search index=%s sourcetype=%s | rex field=_raw \"Name: (?<name>.*) From: (?<from>.*)\"", + SplunkTestResource.TEST_INDEX, SplunkResource.SOURCE_TYPE)) + .post("/splunk/normal") + .then() + .statusCode(200) + .extract().as(List.class); + + Assert.assertEquals(3, result.size()); + Assert.assertEquals("Irma_normal", result.get(0).get("name")); + Assert.assertEquals("Earth\"", result.get(0).get("from")); + Assert.assertEquals("Leonard_normal", result.get(1).get("name")); + Assert.assertEquals("Earth 2.0\"", result.get(1).get("from")); + Assert.assertEquals("Sheldon_normal", result.get(2).get("name")); + Assert.assertEquals("Alpha Centauri\"", result.get(2).get("from")); + } + + @Test + public void testWriteSubmitAndReadRealtime() throws InterruptedException, ExecutionException { + + RestAssured.given() + .body(String.format( + "search index=%s sourcetype=%s | rex field=_raw \"Name: (?<name>.*) From: (?<from>.*)\"", + SplunkTestResource.TEST_INDEX, SplunkResource.SOURCE_TYPE)) + .post("/splunk/startRealtimePolling"); + + //wait some time to start polling + TimeUnit.SECONDS.sleep(3); + write("_realtime1", SplunkTestResource.TEST_INDEX, "submit"); + TimeUnit.SECONDS.sleep(1); + write("_realtime2", SplunkTestResource.TEST_INDEX, "submit"); + TimeUnit.SECONDS.sleep(1); + write("_realtime3", SplunkTestResource.TEST_INDEX, "submit"); + //wait some time to gather the pulls from splunk server + TimeUnit.SECONDS.sleep(3); + //there should be some data from realtime search in direct (concrete values depends on the speed of writing into index) + //test is asserting that there are some + RestAssured.get("/splunk/directRealtimePolling") + .then() + .statusCode(200) + .body(containsString("_realtime")); + } + + @Test + public void testWriteStreamAndReadSaved() throws InterruptedException { + int defaultPort = RestAssured.port; + String defaultUri = RestAssured.baseURI; + + //create saved search + RestAssured.given() + .baseUri("http://localhost") + .port(Integer.parseInt(System.getProperty(SplunkResource.PARAM_REMOTE_PORT))) + .contentType(ContentType.JSON) + .param("name", SplunkTestResource.SAVED_SEARCH_NAME) + .param("disabled", "0") + .param("description", "descritionText") + .param("search", + "index=" + SplunkTestResource.TEST_INDEX + " sourcetype=" + SplunkResource.SOURCE_TYPE) + .post("/services/saved/searches") + .then() + .statusCode(anyOf(is(201), is(409))); + write("_s", SplunkTestResource.TEST_INDEX, "stream"); + + RestAssured.given() + .contentType(ContentType.TEXT) + .body(SplunkTestResource.SAVED_SEARCH_NAME) + .post("/splunk/savedSearch") + .then() + .statusCode(200) + .body(containsString("Name: Sheldon_s")) + .body(containsString("Name: Leonard_s")) + .body(containsString("Name: Irma_s")); + } + + private void write(String suffix, String index, String endpoint) { + write(CollectionHelper.mapOf("entity", "Name: Sheldon" + suffix + " From: Alpha Centauri"), "submit", + index); + write(CollectionHelper.mapOf("entity", "Name: Leonard" + suffix + " From: Earth 2.0"), "submit", + index); + write(CollectionHelper.mapOf("entity", "Name: Irma" + suffix + " From: Earth"), "submit", index); + } + + private void write(Map<String, String> data, String endpoint, String index) { + + String expectedResult = expectedResult(data); + + RestAssured.given() + .contentType(ContentType.JSON) + .queryParam("index", index) + .body(data) + .post("/splunk/" + endpoint) + .then() + .statusCode(201) + .body(containsString(expectedResult)); + } + + private String expectedResult(Map<String, String> data) { + String expectedResult = data.entrySet().stream() + .map(e -> e.getKey() + "=\"" + e.getValue() + "\"") + .collect(Collectors.joining(" ")); + return expectedResult; + } + +} diff --git a/integration-tests/splunk/src/test/java/org/apache/camel/quarkus/component/splunk/it/SplunkTestResource.java b/integration-tests/splunk/src/test/java/org/apache/camel/quarkus/component/splunk/it/SplunkTestResource.java new file mode 100644 index 0000000..bf1f98e --- /dev/null +++ b/integration-tests/splunk/src/test/java/org/apache/camel/quarkus/component/splunk/it/SplunkTestResource.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.splunk.it; + +import java.time.Duration; +import java.util.Map; + +import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; +import org.apache.camel.util.CollectionHelper; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; + +public class SplunkTestResource implements QuarkusTestResourceLifecycleManager { + + public static String TEST_INDEX = "testindex"; + public static String SAVED_SEARCH_NAME = "savedSearchForTest"; + private static final int REMOTE_PORT = 8089; + + private GenericContainer container; + + @Override + public Map<String, String> start() { + + try { + container = new GenericContainer("splunk/splunk:8.1.2") + .withExposedPorts(REMOTE_PORT) + .withExposedPorts(SplunkResource.LOCAL_TCP_PORT) + .withEnv("SPLUNK_START_ARGS", "--accept-license") + .withEnv("SPLUNK_PASSWORD", "changeit") + .withEnv("SPLUNK_LICENSE_URI", "Free") + .waitingFor( + Wait.forLogMessage(".*Ansible playbook complete.*\\n", 1) + .withStartupTimeout(Duration.ofSeconds(120))); + + container.start(); + + container.execInContainer("sudo", "sed", "-i", "s/allowRemoteLogin=requireSetPassword/allowRemoteLogin=always/", + "/opt/splunk/etc/system/default/server.conf"); + container.execInContainer("sudo", "sed", "-i", "s/enableSplunkdSSL = true/enableSplunkdSSL = false/", + "/opt/splunk/etc/system/default/server.conf"); + container.execInContainer("sudo", "./bin/splunk", "restart"); + container.execInContainer("sudo", "./bin/splunk", "add", "index", TEST_INDEX); + container.execInContainer("sudo", "./bin/splunk", "add", "tcp", String.valueOf(SplunkResource.LOCAL_TCP_PORT), + "-sourcetype", + SplunkResource.SOURCE_TYPE); + + return CollectionHelper.mapOf( + SplunkResource.PARAM_REMOTE_PORT, container.getMappedPort(REMOTE_PORT).toString(), + SplunkResource.PARAM_TCP_PORT, container.getMappedPort(SplunkResource.LOCAL_TCP_PORT).toString()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public void stop() { + try { + if (container != null) { + container.stop(); + } + } catch (Exception e) { + // Ignored + } + } +} diff --git a/tooling/scripts/test-categories.yaml b/tooling/scripts/test-categories.yaml index 83a95ca..7384753 100644 --- a/tooling/scripts/test-categories.yaml +++ b/tooling/scripts/test-categories.yaml @@ -126,6 +126,7 @@ messaging-networking1: - kafka - messaging - nats + - splunk - spring-rabbitmq - rabbitmq - ftp