From cac43e58b50b5f6d5e20441bf7a43982338dd75b Mon Sep 17 00:00:00 2001 From: Croway Date: Wed, 15 Jul 2026 17:13:09 +0200 Subject: [PATCH 1/2] CAMEL-24087: camel-test-infra - Add UI support to camel infra run --- .../camel/catalog/test-infra/metadata.json | 218 ++++++++++++------ .../camel/spi/annotations/InfraService.java | 9 + .../core/commands/infra/InfraBaseCommand.java | 30 ++- .../jbang/core/commands/infra/InfraRun.java | 2 +- .../dsl/jbang/core/model/InfraBaseDTO.java | 14 +- .../jbang/core/commands/infra/InfraTest.java | 4 +- .../resources/META-INF/metadata.json | 218 ++++++++++++------ .../services/ArangoDBInfraService.java | 4 + .../ArangoDBLocalContainerInfraService.java | 3 +- .../services/ArtemisAllInfraService.java | 8 +- .../artemis/services/ArtemisInfraService.java | 4 + .../services/ContainerEnvironmentUtil.java | 12 + .../consul/services/ConsulInfraService.java | 4 + .../ConsulLocalContainerInfraService.java | 3 +- .../services/CouchbaseInfraService.java | 4 + .../CouchbaseLocalContainerInfraService.java | 3 +- .../couchdb/services/CouchDbInfraService.java | 4 + .../CouchDbLocalContainerInfraService.java | 3 +- .../services/HashicorpVaultInfraService.java | 4 + ...hicorpVaultLocalContainerInfraService.java | 3 +- .../ibmmq/services/IbmMQInfraService.java | 4 + .../IbmMQLocalContainerInfraService.java | 8 +- .../services/InfinispanInfraService.java | 4 + .../InfinispanLocalContainerInfraService.java | 3 +- .../jaeger/services/JaegerInfraService.java | 4 + .../JaegerLocalContainerInfraService.java | 3 +- .../kafka/services/ConfluentInfraService.java | 2 +- .../ContainerLocalKafkaInfraService.java | 46 +++- .../kafka/services/KafkaInfraService.java | 3 + .../kafka/services/RedpandaInfraService.java | 2 +- .../kafka/services/StrimziInfraService.java | 2 +- .../infra/kafka/services/container.properties | 1 + .../services/KeycloakInfraService.java | 4 + .../KeycloakLocalContainerInfraService.java | 3 +- .../minio/services/MinioInfraService.java | 4 + .../MinioLocalContainerInfraService.java | 3 +- .../mongodb/services/MongoDBInfraService.java | 4 + .../MongoDBLocalContainerInfraService.java | 40 +++- .../mongodb/services/container.properties | 1 + .../neo4j/services/Neo4jInfraService.java | 4 + .../Neo4jLocalContainerInfraService.java | 8 +- .../services/OpenSearchInfraService.java | 4 + .../OpenSearchLocalContainerInfraService.java | 49 ++++ .../opensearch/services/container.properties | 1 + .../services/PostgresInfraService.java | 4 + .../PostgresLocalContainerInfraService.java | 46 +++- ...tgresVectorLocalContainerInfraService.java | 2 +- .../postgres/services/container.properties | 1 + .../qdrant/services/QdrantInfraService.java | 4 + .../QdrantLocalContainerInfraService.java | 3 +- .../services/RabbitMQInfraService.java | 4 + .../RabbitMQLocalContainerInfraService.java | 3 +- .../redis/services/RedisInfraService.java | 4 + .../RedisLocalContainerInfraService.java | 39 +++- .../infra/redis/services/container.properties | 1 + .../infra/solr/services/SolrInfraService.java | 4 + .../SolrLocalContainerInfraService.java | 3 +- .../CamelTestInfraGenerateMetadataMojo.java | 11 + .../camel/spi/annotations/InfraService.java | 9 + 59 files changed, 728 insertions(+), 171 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json index 11e895795c962..71c1c305f7870 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json @@ -7,7 +7,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-milvus", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "v2.6.20" + "serviceVersion" : "v2.6.20", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -17,7 +18,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -27,7 +29,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -37,7 +40,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.iggy.services.IggyInfraService", "description" : "Iggy is a persistent message streaming platform", @@ -47,7 +51,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-iggy", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "0.8.0" + "serviceVersion" : "0.8.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -57,7 +62,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.zookeeper.services.ZooKeeperInfraService", "description" : "Zookeeper is a server for highly reliable distributed coordination of cloud applications", @@ -67,7 +73,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-zookeeper", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "3.9.5" + "serviceVersion" : "3.9.5", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -77,7 +84,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.redis.services.RedisInfraService", "description" : "Redis is an open source in-memory data store", @@ -87,7 +95,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-redis", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "7.4.9-alpine" + "serviceVersion" : "7.4.9-alpine", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.elasticsearch.services.ElasticSearchInfraService", "description" : "Elasticsearch is a distributed search and analytics engine", @@ -97,7 +106,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-elasticsearch", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "9.1.0" + "serviceVersion" : "9.1.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.kafka.services.KafkaInfraService", "description" : "Apache Kafka, Distributed event streaming platform", @@ -107,7 +117,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-kafka", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "0.51.0-kafka-4.2.0" + "serviceVersion" : "0.51.0-kafka-4.2.0", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.kafka.services.KafkaInfraService", "description" : "Apache Kafka, Distributed event streaming platform", @@ -117,7 +128,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-kafka", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "8.3.0" + "serviceVersion" : "8.3.0", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.nats.services.NatsInfraService", "description" : "NATS is a high-performance messaging system for cloud native applications", @@ -127,7 +139,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-nats", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2.14.2" + "serviceVersion" : "2.14.2", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -137,7 +150,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.postgres.services.PostgresInfraService", "description" : "PostgreSQL is an open source object-relational database", @@ -147,7 +161,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-postgres", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "17.10-alpine" + "serviceVersion" : "17.10-alpine", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.kafka.services.KafkaInfraService", "description" : "Apache Kafka, Distributed event streaming platform", @@ -157,7 +172,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-kafka", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "v26.1.12" + "serviceVersion" : "v26.1.12", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.hashicorp.vault.services.HashicorpVaultInfraService", "description" : "HashiCorp Vault is a tool for securely accessing secrets", @@ -167,7 +183,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-hashicorp-vault", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2.0.3" + "serviceVersion" : "2.0.3", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -177,7 +194,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.artemis.services.ArtemisInfraService", "description" : "Apache Artemis is an open source message broker", @@ -187,7 +205,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-artemis", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "latest" + "serviceVersion" : "latest", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.solr.services.SolrInfraService", "description" : "Apache Solr is an open source search platform", @@ -197,7 +216,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-solr", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "9.10.1-slim" + "serviceVersion" : "9.10.1-slim", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.couchbase.services.CouchbaseInfraService", "description" : "Couchbase is a distributed NoSQL cloud database", @@ -207,7 +227,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-couchbase", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "8.0.0" + "serviceVersion" : "8.0.0", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -217,7 +238,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.couchdb.services.CouchDbInfraService", "description" : "Apache CouchDB is an open source NoSQL document database", @@ -227,7 +249,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-couchdb", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "3.5.1" + "serviceVersion" : "3.5.1", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.keycloak.services.KeycloakInfraService", "description" : "Keycloak is an open source identity and access management solution", @@ -237,7 +260,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-keycloak", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "26.6.4" + "serviceVersion" : "26.6.4", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.hivemq.services.HiveMQInfraService", "description" : "HiveMQ is an MQTT-based messaging platform for IoT", @@ -247,7 +271,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-hivemq", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2025.5" + "serviceVersion" : "2025.5", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.ibmmq.services.IbmMQInfraService", "description" : "IBM MQ is enterprise messaging middleware for reliable communication", @@ -257,7 +282,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-ibmmq", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "9.4.5.0-r2" + "serviceVersion" : "9.4.5.0-r2", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -267,7 +293,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.smb.services.SmbLocalContainerInfraService", "description" : "Samba provides file sharing services using the SMB protocol", @@ -277,7 +304,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-smb", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "0.14.0" + "serviceVersion" : "0.14.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.openldap.services.OpenldapInfraService", "description" : "OpenLDAP is an implementation of the Lightweight Directory Access Protocol", @@ -287,7 +315,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-openldap", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.0" + "serviceVersion" : "1.5.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.xmpp.services.XmppInfraService", "description" : "XMPP is an open communication protocol for messaging", @@ -297,7 +326,19 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-xmpp", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "0.3" + "serviceVersion" : "0.3", + "uiSupported" : false +}, { + "service" : "org.apache.camel.test.infra.opensearch.services.OpenSearchInfraService", + "description" : "OpenSearch is a distributed search and analytics engine", + "implementation" : "org.apache.camel.test.infra.opensearch.services.OpenSearchLocalContainerInfraService", + "alias" : [ "opensearch" ], + "aliasImplementation" : [ ], + "groupId" : "org.apache.camel", + "artifactId" : "camel-test-infra-opensearch", + "version" : "4.22.0-SNAPSHOT", + "serviceVersion" : "3.7.0", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.pulsar.services.PulsarInfraService", "description" : "Apache Pulsar is a distributed messaging and streaming platform", @@ -307,7 +348,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-pulsar", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "4.2.1" + "serviceVersion" : "4.2.1", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.artemis.services.ArtemisInfraService", "description" : "Apache Artemis is an open source message broker", @@ -317,7 +359,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-artemis", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "latest" + "serviceVersion" : "latest", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -327,7 +370,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -337,7 +381,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.google.pubsub.services.GooglePubSubInfraService", "description" : "Google Cloud Pub/Sub is a messaging service for event-driven systems", @@ -347,7 +392,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-google-pubsub", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "emulators" + "serviceVersion" : "emulators", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.chatscript.services.ChatScriptInfraService", "description" : "ChatScript is an open source chatbot engine", @@ -357,7 +403,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-chatscript", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "latest" + "serviceVersion" : "latest", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.arangodb.services.ArangoDBInfraService", "description" : "ArangoDB is a multi-model database for high-performance applications.", @@ -367,7 +414,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-arangodb", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "3.12.5.2" + "serviceVersion" : "3.12.5.2", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.ignite.services.IgniteInfraService", "description" : "Apache Ignite is a distributed database for high-performance computing", @@ -377,7 +425,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-ignite", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2.18.0" + "serviceVersion" : "2.18.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.rabbitmq.services.RabbitMQInfraService", "description" : "RabbitMQ is an open source message and streaming broker", @@ -387,7 +436,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-rabbitmq", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "4.2.5-management" + "serviceVersion" : "4.2.5-management", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.mosquitto.services.MosquittoInfraService", "description" : "Mosquitto is a message broker that implements MQTT protocol", @@ -397,7 +447,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-mosquitto", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2.0.22" + "serviceVersion" : "2.0.22", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.neo4j.services.Neo4jInfraService", "description" : "Neo4j is a graph database management system", @@ -407,7 +458,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-neo4j", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2026.05-community-ubi10" + "serviceVersion" : "2026.05-community-ubi10", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.rocketmq.services.RocketMQInfraService", "description" : "Apache RocketMQ is a distributed messaging and streaming platform", @@ -417,7 +469,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-rocketmq", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "5.3.3" + "serviceVersion" : "5.3.3", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -427,7 +480,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -437,7 +491,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -447,7 +502,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.cassandra.services.CassandraInfraService", "description" : "Apache Cassandra is a distributed NoSQL database", @@ -457,7 +513,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-cassandra", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "5.0.8" + "serviceVersion" : "5.0.8", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -467,7 +524,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.hazelcast.services.HazelcastInfraService", "description" : "Hazelcast is a distributed in-memory computing platform", @@ -477,7 +535,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-hazelcast", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "5.4.0" + "serviceVersion" : "5.4.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.hivemq.services.HiveMQInfraService", "description" : "HiveMQ is an MQTT-based messaging platform for IoT", @@ -487,7 +546,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-hivemq", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "camel" + "serviceVersion" : "camel", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.postgres.services.PostgresInfraService", "description" : "PostgreSQL with pgvector extension for vector similarity search", @@ -497,7 +557,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-postgres", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "pg18" + "serviceVersion" : "pg18", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.microprofile.lra.services.MicroprofileLRAInfraService", "description" : "Transaction Manager for microservices that is based on the SAGA pattern for distributed transaction.", @@ -507,7 +568,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-microprofile-lra", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "5.13.1.Final-2.16.6.Final" + "serviceVersion" : "5.13.1.Final-2.16.6.Final", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.minio.services.MinioInfraService", "description" : "MinIO is a high-performance S3 compatible object storage", @@ -517,7 +579,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-minio", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "RELEASE.2025-09-07T16-13-09Z-cpuv1" + "serviceVersion" : "RELEASE.2025-09-07T16-13-09Z-cpuv1", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.kafka.services.KafkaInfraService", "description" : "Apache Kafka, Distributed event streaming platform", @@ -527,7 +590,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-kafka", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "4.3.1" + "serviceVersion" : "4.3.1", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.azure.common.services.AzureInfraService", "description" : "Local Azure services with Azurite", @@ -537,7 +601,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-azure-storage-queue", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "3.35.0" + "serviceVersion" : "3.35.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.ftp.services.FtpInfraService", "description" : "Embedded SFTP Server", @@ -547,7 +612,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-ftp", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2.19.0" + "serviceVersion" : "2.19.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.jaeger.services.JaegerInfraService", "description" : "Jaeger is a distributed tracing backend with OTLP collector and UI", @@ -557,7 +623,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-jaeger", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2.19.0" + "serviceVersion" : "2.19.0", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.infinispan.services.InfinispanInfraService", "description" : "Infinispan is a distributed in-memory key/value data store", @@ -567,7 +634,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-infinispan", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "16.2" + "serviceVersion" : "16.2", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.weaviate.services.WeaviateInfraService", "description" : "Weaviate is an open source vector database", @@ -577,7 +645,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-weaviate", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.37.4" + "serviceVersion" : "1.37.4", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.consul.services.ConsulInfraService", "description" : "Consul is a service networking solution", @@ -587,7 +656,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-consul", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2.0.1" + "serviceVersion" : "2.0.1", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.qdrant.services.QdrantInfraService", "description" : "Qdrant is a vector similarity search engine and database", @@ -597,7 +667,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-qdrant", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "v1.18.2-unprivileged" + "serviceVersion" : "v1.18.2-unprivileged", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.ftp.services.FtpInfraService", "description" : "Embedded FTPS Server", @@ -607,7 +678,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-ftp", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.2.1" + "serviceVersion" : "1.2.1", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.ollama.services.OllamaInfraService", "description" : "Ollama is a tool for running large language models locally", @@ -617,7 +689,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-ollama", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "0.31.2" + "serviceVersion" : "0.31.2", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.azure.common.services.AzureInfraService", "description" : "Local Azure services with Azurite", @@ -627,7 +700,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-azure-storage-blob", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "3.35.0" + "serviceVersion" : "3.35.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.docling.services.DoclingInfraService", "description" : "Docling is a document processing and conversion toolkit", @@ -637,7 +711,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-docling", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "v1.26.0" + "serviceVersion" : "v1.26.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -647,7 +722,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.fhir.services.FhirInfraService", "description" : "HAPI FHIR RESTful test server", @@ -657,7 +733,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-fhir", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "v8.10.0-2" + "serviceVersion" : "v8.10.0-2", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.pinecone.services.PineconeInfraService", "description" : "Pinecone is a vector database for machine learning applications", @@ -667,7 +744,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-pinecone", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "v1.0.0.rc0" + "serviceVersion" : "v1.0.0.rc0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.ftp.services.FtpInfraService", "description" : "Embedded FTP Server", @@ -677,7 +755,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-ftp", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.2.1" + "serviceVersion" : "1.2.1", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.mongodb.services.MongoDBInfraService", "description" : "MongoDB is a document-oriented NoSQL database", @@ -687,5 +766,6 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-mongodb", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "7.0.31-jammy" + "serviceVersion" : "7.0.31-jammy", + "uiSupported" : true } ] \ No newline at end of file diff --git a/core/camel-api/src/generated/java/org/apache/camel/spi/annotations/InfraService.java b/core/camel-api/src/generated/java/org/apache/camel/spi/annotations/InfraService.java index fb6051e05581a..e4ef026135a79 100644 --- a/core/camel-api/src/generated/java/org/apache/camel/spi/annotations/InfraService.java +++ b/core/camel-api/src/generated/java/org/apache/camel/spi/annotations/InfraService.java @@ -81,4 +81,13 @@ * @return */ String serviceVersion() default ""; + + /** + * Whether this service supports a web UI (built-in or via companion container). + * + * When true, the service interface should provide a {@code uiUrl()} method that returns the UI URL when available. + * + * @return true if the service has UI support + */ + boolean uiSupported() default false; } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraBaseCommand.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraBaseCommand.java index e59bfd51653ad..8c6b0e7e9a541 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraBaseCommand.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraBaseCommand.java @@ -167,6 +167,9 @@ public int listServices(Consumer> serviceConsumer) throws IOException if (service.aliasImplementation() != null) { services.get(alias).getAliasImplementation().addAll(service.aliasImplementation()); } + if (service.uiSupported()) { + services.get(alias).setUiSupported(true); + } } } @@ -182,7 +185,8 @@ public int listServices(Consumer> serviceConsumer) throws IOException .sorted() .collect(Collectors.joining(", ")), entry.getValue().getDescription(), - getServiceData(entry.getKey(), pid))); + getServiceData(entry.getKey(), pid), + entry.getValue().isUiSupported())); } rows.sort(Comparator.comparing(InfraList.Row::alias)); @@ -195,7 +199,7 @@ public int listServices(Consumer> serviceConsumer) throws IOException Jsoner.serialize( rows.stream().map(row -> new InfraBaseDTO( row.alias, row.aliasImplementation, row.description, - parseServiceData(row.serviceData()))) + parseServiceData(row.serviceData()), row.uiSupported())) .map(InfraBaseDTO::toMap) .collect(Collectors.toList()))); } else { @@ -204,19 +208,22 @@ public int listServices(Consumer> serviceConsumer) throws IOException // IMPLEMENTATION is capped and SERVICE_DATA keeps a compact fixed width; both truncate with an ellipsis // instead of overflowing the terminal (the full, structured service data is available via --json). int serviceDataWidth = 30; + int uiWidth = 4; int aliasWidth = width + 2; int pidWidth = showPidColumn() ? CamelTableColumns.measure("PID", Integer.MAX_VALUE, rows, r -> r.pid) : 0; int implWidth = CamelTableColumns.measure("IMPLEMENTATION", 35, rows, Row::aliasImplementation); - int overhead = TerminalWidthHelper.noBorderOverhead(showPidColumn() ? 5 : 4); + int overhead = TerminalWidthHelper.noBorderOverhead(showPidColumn() ? 6 : 5); int descWidth = CamelTableColumns.lastColumnWidth( - tw, overhead, pidWidth, aliasWidth, implWidth, serviceDataWidth); + tw, overhead, pidWidth, aliasWidth, implWidth, uiWidth, serviceDataWidth); printer().println(AsciiTable.getTable(AsciiTable.NO_BORDERS, rows, Arrays.asList( new Column().header("PID").visible(showPidColumn()).headerAlign(HorizontalAlign.CENTER).with(r -> r.pid), new Column().header("ALIAS").minWidth(aliasWidth).dataAlign(HorizontalAlign.LEFT) .with(Row::alias), new Column().header("IMPLEMENTATION").maxWidth(implWidth, OverflowBehaviour.ELLIPSIS_RIGHT) .dataAlign(HorizontalAlign.LEFT).with(Row::aliasImplementation), + new Column().header("UI").maxWidth(uiWidth).dataAlign(HorizontalAlign.CENTER) + .with(r -> r.uiSupported() ? "x" : ""), CamelTableColumns.lastText("DESCRIPTION", descWidth).with(Row::description), new Column().header("SERVICE_DATA").maxWidth(serviceDataWidth, OverflowBehaviour.ELLIPSIS_RIGHT) .dataAlign(HorizontalAlign.LEFT).with(Row::serviceData)))); @@ -286,15 +293,18 @@ record TestInfraService( String groupId, String artifactId, String version, - String serviceVersion) { + String serviceVersion, + boolean uiSupported) { } - record Row(String pid, String alias, String aliasImplementation, String description, String serviceData) { + record Row(String pid, String alias, String aliasImplementation, String description, String serviceData, + boolean uiSupported) { } private static class InfraServiceAlias { private final String description; private final Set aliasImplementation = new HashSet<>(); + private boolean uiSupported; public InfraServiceAlias(String description) { this.description = description; @@ -307,5 +317,13 @@ public String getDescription() { public Set getAliasImplementation() { return aliasImplementation; } + + public boolean isUiSupported() { + return uiSupported; + } + + public void setUiSupported(boolean uiSupported) { + this.uiSupported = uiSupported; + } } } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java index cfca1893cb33e..6016cc331f302 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java @@ -169,7 +169,6 @@ protected Integer doRun(String testService, String testServiceImplementation, Te if (port != null) { System.setProperty("camel.infra.port", String.valueOf(port)); } - Object actualService = cl.loadClass(serviceImpl).newInstance(); // Make sure the actualService can be run with initialize method @@ -364,4 +363,5 @@ public boolean isLogToStdout() { public void setLogToStdout(boolean logToStdout) { this.logToStdout = logToStdout; } + } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/model/InfraBaseDTO.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/model/InfraBaseDTO.java index 8f69b30c8f2db..e92a0bac7f80f 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/model/InfraBaseDTO.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/model/InfraBaseDTO.java @@ -26,15 +26,18 @@ public class InfraBaseDTO { private String aliasImplementation; private String description; private Object serviceData; + private boolean uiSupported; public InfraBaseDTO() { } - public InfraBaseDTO(String alias, String aliasImplementation, String description, Object serviceData) { + public InfraBaseDTO(String alias, String aliasImplementation, String description, Object serviceData, + boolean uiSupported) { this.alias = alias; this.aliasImplementation = aliasImplementation; this.description = description; this.serviceData = serviceData; + this.uiSupported = uiSupported; } public String getAlias() { @@ -69,6 +72,14 @@ public void setServiceData(Object serviceData) { this.serviceData = serviceData; } + public boolean isUiSupported() { + return uiSupported; + } + + public void setUiSupported(boolean uiSupported) { + this.uiSupported = uiSupported; + } + public Map toMap() { JsonObject jo = new JsonObject(); jo.put("alias", alias); @@ -81,6 +92,7 @@ public Map toMap() { if (serviceData != null) { jo.put("serviceData", serviceData); } + jo.put("uiSupported", uiSupported); return jo; } } diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraTest.java b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraTest.java index e8983b74be705..794fa260c8b48 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraTest.java +++ b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraTest.java @@ -77,7 +77,7 @@ public void serviceDataInJsonIsNestedNotEscaped() { String rawServiceData = "{\"host\":\"localhost\",\"port\":61616}"; Object serviceData = InfraBaseCommand.parseServiceData(rawServiceData); - InfraBaseDTO dto = new InfraBaseDTO("artemis", "amqp", "AMQP broker", serviceData); + InfraBaseDTO dto = new InfraBaseDTO("artemis", "amqp", "AMQP broker", serviceData, true); String json = Jsoner.serialize(List.of(dto.toMap())); // serviceData is embedded as a nested JSON object (so --json is machine-parseable), not a string-escaped blob @@ -93,7 +93,7 @@ public void malformedServiceDataIsOmittedFromJson() { // unparseable content is dropped rather than emitted as an escaped string Assertions.assertThat(serviceData).isNull(); - InfraBaseDTO dto = new InfraBaseDTO("artemis", "amqp", "AMQP broker", serviceData); + InfraBaseDTO dto = new InfraBaseDTO("artemis", "amqp", "AMQP broker", serviceData, true); String json = Jsoner.serialize(List.of(dto.toMap())); Assertions.assertThat(json).contains("\"alias\":\"artemis\""); diff --git a/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json b/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json index 11e895795c962..71c1c305f7870 100644 --- a/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json +++ b/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json @@ -7,7 +7,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-milvus", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "v2.6.20" + "serviceVersion" : "v2.6.20", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -17,7 +18,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -27,7 +29,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -37,7 +40,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.iggy.services.IggyInfraService", "description" : "Iggy is a persistent message streaming platform", @@ -47,7 +51,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-iggy", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "0.8.0" + "serviceVersion" : "0.8.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -57,7 +62,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.zookeeper.services.ZooKeeperInfraService", "description" : "Zookeeper is a server for highly reliable distributed coordination of cloud applications", @@ -67,7 +73,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-zookeeper", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "3.9.5" + "serviceVersion" : "3.9.5", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -77,7 +84,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.redis.services.RedisInfraService", "description" : "Redis is an open source in-memory data store", @@ -87,7 +95,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-redis", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "7.4.9-alpine" + "serviceVersion" : "7.4.9-alpine", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.elasticsearch.services.ElasticSearchInfraService", "description" : "Elasticsearch is a distributed search and analytics engine", @@ -97,7 +106,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-elasticsearch", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "9.1.0" + "serviceVersion" : "9.1.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.kafka.services.KafkaInfraService", "description" : "Apache Kafka, Distributed event streaming platform", @@ -107,7 +117,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-kafka", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "0.51.0-kafka-4.2.0" + "serviceVersion" : "0.51.0-kafka-4.2.0", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.kafka.services.KafkaInfraService", "description" : "Apache Kafka, Distributed event streaming platform", @@ -117,7 +128,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-kafka", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "8.3.0" + "serviceVersion" : "8.3.0", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.nats.services.NatsInfraService", "description" : "NATS is a high-performance messaging system for cloud native applications", @@ -127,7 +139,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-nats", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2.14.2" + "serviceVersion" : "2.14.2", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -137,7 +150,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.postgres.services.PostgresInfraService", "description" : "PostgreSQL is an open source object-relational database", @@ -147,7 +161,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-postgres", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "17.10-alpine" + "serviceVersion" : "17.10-alpine", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.kafka.services.KafkaInfraService", "description" : "Apache Kafka, Distributed event streaming platform", @@ -157,7 +172,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-kafka", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "v26.1.12" + "serviceVersion" : "v26.1.12", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.hashicorp.vault.services.HashicorpVaultInfraService", "description" : "HashiCorp Vault is a tool for securely accessing secrets", @@ -167,7 +183,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-hashicorp-vault", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2.0.3" + "serviceVersion" : "2.0.3", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -177,7 +194,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.artemis.services.ArtemisInfraService", "description" : "Apache Artemis is an open source message broker", @@ -187,7 +205,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-artemis", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "latest" + "serviceVersion" : "latest", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.solr.services.SolrInfraService", "description" : "Apache Solr is an open source search platform", @@ -197,7 +216,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-solr", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "9.10.1-slim" + "serviceVersion" : "9.10.1-slim", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.couchbase.services.CouchbaseInfraService", "description" : "Couchbase is a distributed NoSQL cloud database", @@ -207,7 +227,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-couchbase", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "8.0.0" + "serviceVersion" : "8.0.0", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -217,7 +238,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.couchdb.services.CouchDbInfraService", "description" : "Apache CouchDB is an open source NoSQL document database", @@ -227,7 +249,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-couchdb", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "3.5.1" + "serviceVersion" : "3.5.1", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.keycloak.services.KeycloakInfraService", "description" : "Keycloak is an open source identity and access management solution", @@ -237,7 +260,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-keycloak", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "26.6.4" + "serviceVersion" : "26.6.4", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.hivemq.services.HiveMQInfraService", "description" : "HiveMQ is an MQTT-based messaging platform for IoT", @@ -247,7 +271,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-hivemq", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2025.5" + "serviceVersion" : "2025.5", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.ibmmq.services.IbmMQInfraService", "description" : "IBM MQ is enterprise messaging middleware for reliable communication", @@ -257,7 +282,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-ibmmq", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "9.4.5.0-r2" + "serviceVersion" : "9.4.5.0-r2", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -267,7 +293,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.smb.services.SmbLocalContainerInfraService", "description" : "Samba provides file sharing services using the SMB protocol", @@ -277,7 +304,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-smb", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "0.14.0" + "serviceVersion" : "0.14.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.openldap.services.OpenldapInfraService", "description" : "OpenLDAP is an implementation of the Lightweight Directory Access Protocol", @@ -287,7 +315,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-openldap", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.0" + "serviceVersion" : "1.5.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.xmpp.services.XmppInfraService", "description" : "XMPP is an open communication protocol for messaging", @@ -297,7 +326,19 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-xmpp", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "0.3" + "serviceVersion" : "0.3", + "uiSupported" : false +}, { + "service" : "org.apache.camel.test.infra.opensearch.services.OpenSearchInfraService", + "description" : "OpenSearch is a distributed search and analytics engine", + "implementation" : "org.apache.camel.test.infra.opensearch.services.OpenSearchLocalContainerInfraService", + "alias" : [ "opensearch" ], + "aliasImplementation" : [ ], + "groupId" : "org.apache.camel", + "artifactId" : "camel-test-infra-opensearch", + "version" : "4.22.0-SNAPSHOT", + "serviceVersion" : "3.7.0", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.pulsar.services.PulsarInfraService", "description" : "Apache Pulsar is a distributed messaging and streaming platform", @@ -307,7 +348,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-pulsar", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "4.2.1" + "serviceVersion" : "4.2.1", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.artemis.services.ArtemisInfraService", "description" : "Apache Artemis is an open source message broker", @@ -317,7 +359,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-artemis", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "latest" + "serviceVersion" : "latest", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -327,7 +370,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -337,7 +381,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.google.pubsub.services.GooglePubSubInfraService", "description" : "Google Cloud Pub/Sub is a messaging service for event-driven systems", @@ -347,7 +392,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-google-pubsub", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "emulators" + "serviceVersion" : "emulators", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.chatscript.services.ChatScriptInfraService", "description" : "ChatScript is an open source chatbot engine", @@ -357,7 +403,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-chatscript", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "latest" + "serviceVersion" : "latest", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.arangodb.services.ArangoDBInfraService", "description" : "ArangoDB is a multi-model database for high-performance applications.", @@ -367,7 +414,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-arangodb", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "3.12.5.2" + "serviceVersion" : "3.12.5.2", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.ignite.services.IgniteInfraService", "description" : "Apache Ignite is a distributed database for high-performance computing", @@ -377,7 +425,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-ignite", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2.18.0" + "serviceVersion" : "2.18.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.rabbitmq.services.RabbitMQInfraService", "description" : "RabbitMQ is an open source message and streaming broker", @@ -387,7 +436,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-rabbitmq", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "4.2.5-management" + "serviceVersion" : "4.2.5-management", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.mosquitto.services.MosquittoInfraService", "description" : "Mosquitto is a message broker that implements MQTT protocol", @@ -397,7 +447,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-mosquitto", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2.0.22" + "serviceVersion" : "2.0.22", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.neo4j.services.Neo4jInfraService", "description" : "Neo4j is a graph database management system", @@ -407,7 +458,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-neo4j", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2026.05-community-ubi10" + "serviceVersion" : "2026.05-community-ubi10", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.rocketmq.services.RocketMQInfraService", "description" : "Apache RocketMQ is a distributed messaging and streaming platform", @@ -417,7 +469,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-rocketmq", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "5.3.3" + "serviceVersion" : "5.3.3", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -427,7 +480,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -437,7 +491,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -447,7 +502,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.cassandra.services.CassandraInfraService", "description" : "Apache Cassandra is a distributed NoSQL database", @@ -457,7 +513,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-cassandra", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "5.0.8" + "serviceVersion" : "5.0.8", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -467,7 +524,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.hazelcast.services.HazelcastInfraService", "description" : "Hazelcast is a distributed in-memory computing platform", @@ -477,7 +535,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-hazelcast", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "5.4.0" + "serviceVersion" : "5.4.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.hivemq.services.HiveMQInfraService", "description" : "HiveMQ is an MQTT-based messaging platform for IoT", @@ -487,7 +546,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-hivemq", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "camel" + "serviceVersion" : "camel", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.postgres.services.PostgresInfraService", "description" : "PostgreSQL with pgvector extension for vector similarity search", @@ -497,7 +557,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-postgres", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "pg18" + "serviceVersion" : "pg18", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.microprofile.lra.services.MicroprofileLRAInfraService", "description" : "Transaction Manager for microservices that is based on the SAGA pattern for distributed transaction.", @@ -507,7 +568,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-microprofile-lra", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "5.13.1.Final-2.16.6.Final" + "serviceVersion" : "5.13.1.Final-2.16.6.Final", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.minio.services.MinioInfraService", "description" : "MinIO is a high-performance S3 compatible object storage", @@ -517,7 +579,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-minio", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "RELEASE.2025-09-07T16-13-09Z-cpuv1" + "serviceVersion" : "RELEASE.2025-09-07T16-13-09Z-cpuv1", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.kafka.services.KafkaInfraService", "description" : "Apache Kafka, Distributed event streaming platform", @@ -527,7 +590,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-kafka", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "4.3.1" + "serviceVersion" : "4.3.1", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.azure.common.services.AzureInfraService", "description" : "Local Azure services with Azurite", @@ -537,7 +601,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-azure-storage-queue", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "3.35.0" + "serviceVersion" : "3.35.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.ftp.services.FtpInfraService", "description" : "Embedded SFTP Server", @@ -547,7 +612,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-ftp", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2.19.0" + "serviceVersion" : "2.19.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.jaeger.services.JaegerInfraService", "description" : "Jaeger is a distributed tracing backend with OTLP collector and UI", @@ -557,7 +623,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-jaeger", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2.19.0" + "serviceVersion" : "2.19.0", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.infinispan.services.InfinispanInfraService", "description" : "Infinispan is a distributed in-memory key/value data store", @@ -567,7 +634,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-infinispan", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "16.2" + "serviceVersion" : "16.2", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.weaviate.services.WeaviateInfraService", "description" : "Weaviate is an open source vector database", @@ -577,7 +645,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-weaviate", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.37.4" + "serviceVersion" : "1.37.4", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.consul.services.ConsulInfraService", "description" : "Consul is a service networking solution", @@ -587,7 +656,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-consul", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "2.0.1" + "serviceVersion" : "2.0.1", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.qdrant.services.QdrantInfraService", "description" : "Qdrant is a vector similarity search engine and database", @@ -597,7 +667,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-qdrant", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "v1.18.2-unprivileged" + "serviceVersion" : "v1.18.2-unprivileged", + "uiSupported" : true }, { "service" : "org.apache.camel.test.infra.ftp.services.FtpInfraService", "description" : "Embedded FTPS Server", @@ -607,7 +678,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-ftp", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.2.1" + "serviceVersion" : "1.2.1", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.ollama.services.OllamaInfraService", "description" : "Ollama is a tool for running large language models locally", @@ -617,7 +689,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-ollama", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "0.31.2" + "serviceVersion" : "0.31.2", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.azure.common.services.AzureInfraService", "description" : "Local Azure services with Azurite", @@ -627,7 +700,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-azure-storage-blob", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "3.35.0" + "serviceVersion" : "3.35.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.docling.services.DoclingInfraService", "description" : "Docling is a document processing and conversion toolkit", @@ -637,7 +711,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-docling", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "v1.26.0" + "serviceVersion" : "v1.26.0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.aws.common.services.AWSInfraService", "description" : "Local AWS Services with LocalStack", @@ -647,7 +722,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-aws-v2", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.5.28" + "serviceVersion" : "1.5.28", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.fhir.services.FhirInfraService", "description" : "HAPI FHIR RESTful test server", @@ -657,7 +733,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-fhir", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "v8.10.0-2" + "serviceVersion" : "v8.10.0-2", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.pinecone.services.PineconeInfraService", "description" : "Pinecone is a vector database for machine learning applications", @@ -667,7 +744,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-pinecone", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "v1.0.0.rc0" + "serviceVersion" : "v1.0.0.rc0", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.ftp.services.FtpInfraService", "description" : "Embedded FTP Server", @@ -677,7 +755,8 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-ftp", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "1.2.1" + "serviceVersion" : "1.2.1", + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.mongodb.services.MongoDBInfraService", "description" : "MongoDB is a document-oriented NoSQL database", @@ -687,5 +766,6 @@ "groupId" : "org.apache.camel", "artifactId" : "camel-test-infra-mongodb", "version" : "4.22.0-SNAPSHOT", - "serviceVersion" : "7.0.31-jammy" + "serviceVersion" : "7.0.31-jammy", + "uiSupported" : true } ] \ No newline at end of file diff --git a/test-infra/camel-test-infra-arangodb/src/main/java/org/apache/camel/test/infra/arangodb/services/ArangoDBInfraService.java b/test-infra/camel-test-infra-arangodb/src/main/java/org/apache/camel/test/infra/arangodb/services/ArangoDBInfraService.java index 357f4439c4634..9d5440b4e209c 100644 --- a/test-infra/camel-test-infra-arangodb/src/main/java/org/apache/camel/test/infra/arangodb/services/ArangoDBInfraService.java +++ b/test-infra/camel-test-infra-arangodb/src/main/java/org/apache/camel/test/infra/arangodb/services/ArangoDBInfraService.java @@ -58,4 +58,8 @@ default String user() { default String password() { return ""; } + + default String uiUrl() { + return String.format("http://%s:%d", host(), port()); + } } diff --git a/test-infra/camel-test-infra-arangodb/src/main/java/org/apache/camel/test/infra/arangodb/services/ArangoDBLocalContainerInfraService.java b/test-infra/camel-test-infra-arangodb/src/main/java/org/apache/camel/test/infra/arangodb/services/ArangoDBLocalContainerInfraService.java index 555231e0259ed..759f0304a2673 100644 --- a/test-infra/camel-test-infra-arangodb/src/main/java/org/apache/camel/test/infra/arangodb/services/ArangoDBLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-arangodb/src/main/java/org/apache/camel/test/infra/arangodb/services/ArangoDBLocalContainerInfraService.java @@ -26,7 +26,8 @@ @InfraService(service = ArangoDBInfraService.class, description = "ArangoDB is a multi-model database for high-performance applications.", - serviceAlias = "arangodb") + serviceAlias = "arangodb", + uiSupported = true) public class ArangoDBLocalContainerInfraService implements ArangoDBInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(ArangoDBLocalContainerInfraService.class); diff --git a/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/ArtemisAllInfraService.java b/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/ArtemisAllInfraService.java index 3426db9d8eaba..3e8028c07dcbf 100644 --- a/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/ArtemisAllInfraService.java +++ b/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/ArtemisAllInfraService.java @@ -25,7 +25,8 @@ @InfraService(service = ArtemisInfraService.class, description = "Apache Artemis is an open source message broker", - serviceAlias = "artemis") + serviceAlias = "artemis", + uiSupported = true) public class ArtemisAllInfraService implements ArtemisInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(ArtemisAllInfraService.class); @@ -102,4 +103,9 @@ public ArtemisContainer getContainer() { public String remoteURI() { return serviceAddress(); } + + @Override + public String uiUrl() { + return container.adminURL(); + } } diff --git a/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/ArtemisInfraService.java b/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/ArtemisInfraService.java index 105fcefff66d7..09d97457de15b 100644 --- a/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/ArtemisInfraService.java +++ b/test-infra/camel-test-infra-artemis/src/main/java/org/apache/camel/test/infra/artemis/services/ArtemisInfraService.java @@ -59,6 +59,10 @@ default void registerProperties() { System.setProperty(ArtemisProperties.ARTEMIS_PASSWORD, password()); } + default String uiUrl() { + return null; + } + void restart(); long countMessages(String queue) throws Exception; diff --git a/test-infra/camel-test-infra-common/src/main/java/org/apache/camel/test/infra/common/services/ContainerEnvironmentUtil.java b/test-infra/camel-test-infra-common/src/main/java/org/apache/camel/test/infra/common/services/ContainerEnvironmentUtil.java index 72cbfc840e78b..7da3d1814fb8c 100644 --- a/test-infra/camel-test-infra-common/src/main/java/org/apache/camel/test/infra/common/services/ContainerEnvironmentUtil.java +++ b/test-infra/camel-test-infra-common/src/main/java/org/apache/camel/test/infra/common/services/ContainerEnvironmentUtil.java @@ -35,6 +35,7 @@ public final class ContainerEnvironmentUtil { public static final String STARTUP_ATTEMPTS_PROPERTY = ".startup.attempts"; public static final String INFRA_PORT_PROPERTY = "camel.infra.port"; public static final String INFRA_FIXED_PORT_PROPERTY = "camel.infra.fixedPort"; + private static final Logger LOG = LoggerFactory.getLogger(ContainerEnvironmentUtil.class); private static final AtomicInteger INSTANCE_COUNTER = new AtomicInteger(0); @@ -108,6 +109,17 @@ public static boolean isFixedPort(@SuppressWarnings("rawtypes") Class cls) { return fixedPort; } + /** + * Determines if companion UI containers should be started alongside infrastructure services. Returns true when in + * fixed port mode (Camel CLI). This ensures UI containers are never started during tests (which don't set + * fixedPort). + * + * @return true if companion UI containers should be started + */ + public static boolean isWithUi() { + return Boolean.parseBoolean(System.getProperty(INFRA_FIXED_PORT_PROPERTY, "false")); + } + public static String containerName(Class cls) { InfraService annotation = findAnnotation(cls); String name = null; diff --git a/test-infra/camel-test-infra-consul/src/main/java/org/apache/camel/test/infra/consul/services/ConsulInfraService.java b/test-infra/camel-test-infra-consul/src/main/java/org/apache/camel/test/infra/consul/services/ConsulInfraService.java index 08b0bc40cc6a7..c130c7fe0f727 100644 --- a/test-infra/camel-test-infra-consul/src/main/java/org/apache/camel/test/infra/consul/services/ConsulInfraService.java +++ b/test-infra/camel-test-infra-consul/src/main/java/org/apache/camel/test/infra/consul/services/ConsulInfraService.java @@ -28,4 +28,8 @@ public interface ConsulInfraService extends InfrastructureService { String host(); int port(); + + default String uiUrl() { + return getConsulUrl() + "/ui"; + } } diff --git a/test-infra/camel-test-infra-consul/src/main/java/org/apache/camel/test/infra/consul/services/ConsulLocalContainerInfraService.java b/test-infra/camel-test-infra-consul/src/main/java/org/apache/camel/test/infra/consul/services/ConsulLocalContainerInfraService.java index 25b8a248e2bcc..a44a53b99e40d 100644 --- a/test-infra/camel-test-infra-consul/src/main/java/org/apache/camel/test/infra/consul/services/ConsulLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-consul/src/main/java/org/apache/camel/test/infra/consul/services/ConsulLocalContainerInfraService.java @@ -28,7 +28,8 @@ @InfraService(service = ConsulInfraService.class, description = "Consul is a service networking solution", - serviceAlias = { "consul" }) + serviceAlias = { "consul" }, + uiSupported = true) public class ConsulLocalContainerInfraService implements ConsulInfraService, ContainerService> { public static final String CONTAINER_NAME = "consul"; diff --git a/test-infra/camel-test-infra-couchbase/src/main/java/org/apache/camel/test/infra/couchbase/services/CouchbaseInfraService.java b/test-infra/camel-test-infra-couchbase/src/main/java/org/apache/camel/test/infra/couchbase/services/CouchbaseInfraService.java index b09cd51b5ba01..41fc41f1eed4a 100644 --- a/test-infra/camel-test-infra-couchbase/src/main/java/org/apache/camel/test/infra/couchbase/services/CouchbaseInfraService.java +++ b/test-infra/camel-test-infra-couchbase/src/main/java/org/apache/camel/test/infra/couchbase/services/CouchbaseInfraService.java @@ -63,4 +63,8 @@ default String endpointUri() { default String connectionBase() { return String.format("couchbase:%s://%s:%d", protocol(), hostname(), port()); } + + default String uiUrl() { + return String.format("http://%s:%d", hostname(), port()); + } } diff --git a/test-infra/camel-test-infra-couchbase/src/main/java/org/apache/camel/test/infra/couchbase/services/CouchbaseLocalContainerInfraService.java b/test-infra/camel-test-infra-couchbase/src/main/java/org/apache/camel/test/infra/couchbase/services/CouchbaseLocalContainerInfraService.java index 1f22bd4a9e7ae..f5f74412d7007 100644 --- a/test-infra/camel-test-infra-couchbase/src/main/java/org/apache/camel/test/infra/couchbase/services/CouchbaseLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-couchbase/src/main/java/org/apache/camel/test/infra/couchbase/services/CouchbaseLocalContainerInfraService.java @@ -37,7 +37,8 @@ @InfraService(service = CouchbaseInfraService.class, description = "Couchbase is a distributed NoSQL cloud database", - serviceAlias = { "couchbase" }) + serviceAlias = { "couchbase" }, + uiSupported = true) public class CouchbaseLocalContainerInfraService implements CouchbaseInfraService, ContainerService { private class CustomCouchbaseContainer extends CouchbaseContainer { diff --git a/test-infra/camel-test-infra-couchdb/src/main/java/org/apache/camel/test/infra/couchdb/services/CouchDbInfraService.java b/test-infra/camel-test-infra-couchdb/src/main/java/org/apache/camel/test/infra/couchdb/services/CouchDbInfraService.java index f9de00a66b592..95f238c71ce1c 100644 --- a/test-infra/camel-test-infra-couchdb/src/main/java/org/apache/camel/test/infra/couchdb/services/CouchDbInfraService.java +++ b/test-infra/camel-test-infra-couchdb/src/main/java/org/apache/camel/test/infra/couchdb/services/CouchDbInfraService.java @@ -43,4 +43,8 @@ default String endpointUri() { default String connectionBase() { return String.format("couchdb:http:%s:%d", host(), port()); } + + default String uiUrl() { + return String.format("http://%s:%d/_utils", host(), port()); + } } diff --git a/test-infra/camel-test-infra-couchdb/src/main/java/org/apache/camel/test/infra/couchdb/services/CouchDbLocalContainerInfraService.java b/test-infra/camel-test-infra-couchdb/src/main/java/org/apache/camel/test/infra/couchdb/services/CouchDbLocalContainerInfraService.java index 1a036ffac97a9..e74bd823d329f 100644 --- a/test-infra/camel-test-infra-couchdb/src/main/java/org/apache/camel/test/infra/couchdb/services/CouchDbLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-couchdb/src/main/java/org/apache/camel/test/infra/couchdb/services/CouchDbLocalContainerInfraService.java @@ -29,7 +29,8 @@ @InfraService(service = CouchDbInfraService.class, description = "Apache CouchDB is an open source NoSQL document database", - serviceAlias = { "couchdb" }) + serviceAlias = { "couchdb" }, + uiSupported = true) public class CouchDbLocalContainerInfraService implements CouchDbInfraService, ContainerService> { public static final String CONTAINER_NAME = "couchdb"; diff --git a/test-infra/camel-test-infra-hashicorp-vault/src/main/java/org/apache/camel/test/infra/hashicorp/vault/services/HashicorpVaultInfraService.java b/test-infra/camel-test-infra-hashicorp-vault/src/main/java/org/apache/camel/test/infra/hashicorp/vault/services/HashicorpVaultInfraService.java index bb83f4db7f3b4..cb12baf62cbbe 100644 --- a/test-infra/camel-test-infra-hashicorp-vault/src/main/java/org/apache/camel/test/infra/hashicorp/vault/services/HashicorpVaultInfraService.java +++ b/test-infra/camel-test-infra-hashicorp-vault/src/main/java/org/apache/camel/test/infra/hashicorp/vault/services/HashicorpVaultInfraService.java @@ -32,4 +32,8 @@ public interface HashicorpVaultInfraService extends InfrastructureService { default String scheme() { return "http"; } + + default String uiUrl() { + return String.format("%s://%s:%d/ui", scheme(), host(), port()); + } } diff --git a/test-infra/camel-test-infra-hashicorp-vault/src/main/java/org/apache/camel/test/infra/hashicorp/vault/services/HashicorpVaultLocalContainerInfraService.java b/test-infra/camel-test-infra-hashicorp-vault/src/main/java/org/apache/camel/test/infra/hashicorp/vault/services/HashicorpVaultLocalContainerInfraService.java index 55b05d1a86aa1..316fe5fda02e6 100644 --- a/test-infra/camel-test-infra-hashicorp-vault/src/main/java/org/apache/camel/test/infra/hashicorp/vault/services/HashicorpVaultLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-hashicorp-vault/src/main/java/org/apache/camel/test/infra/hashicorp/vault/services/HashicorpVaultLocalContainerInfraService.java @@ -35,7 +35,8 @@ @InfraService(service = HashicorpVaultInfraService.class, description = "HashiCorp Vault is a tool for securely accessing secrets", serviceAlias = "hashicorp", - serviceImplementationAlias = "vault") + serviceImplementationAlias = "vault", + uiSupported = true) public class HashicorpVaultLocalContainerInfraService implements HashicorpVaultInfraService, ContainerService> { public static final String CONTAINER_NAME = "hashicorp-vault"; diff --git a/test-infra/camel-test-infra-ibmmq/src/main/java/org/apache/camel/test/infra/ibmmq/services/IbmMQInfraService.java b/test-infra/camel-test-infra-ibmmq/src/main/java/org/apache/camel/test/infra/ibmmq/services/IbmMQInfraService.java index 0d668c697ee61..60bd1cee7f313 100644 --- a/test-infra/camel-test-infra-ibmmq/src/main/java/org/apache/camel/test/infra/ibmmq/services/IbmMQInfraService.java +++ b/test-infra/camel-test-infra-ibmmq/src/main/java/org/apache/camel/test/infra/ibmmq/services/IbmMQInfraService.java @@ -48,4 +48,8 @@ default String password() { default String brokerUrl() { return String.format("amqp://%s:%d", host(), port()); } + + default String uiUrl() { + return null; + } } diff --git a/test-infra/camel-test-infra-ibmmq/src/main/java/org/apache/camel/test/infra/ibmmq/services/IbmMQLocalContainerInfraService.java b/test-infra/camel-test-infra-ibmmq/src/main/java/org/apache/camel/test/infra/ibmmq/services/IbmMQLocalContainerInfraService.java index 00d32805b8a98..41b577c539a1c 100644 --- a/test-infra/camel-test-infra-ibmmq/src/main/java/org/apache/camel/test/infra/ibmmq/services/IbmMQLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-ibmmq/src/main/java/org/apache/camel/test/infra/ibmmq/services/IbmMQLocalContainerInfraService.java @@ -39,7 +39,8 @@ @InfraService(service = IbmMQInfraService.class, description = "IBM MQ is enterprise messaging middleware for reliable communication", - serviceAlias = "ibmmq") + serviceAlias = "ibmmq", + uiSupported = true) public class IbmMQLocalContainerInfraService implements IbmMQInfraService, ContainerService> { public static final String CONTAINER_NAME = "ibmmq"; @@ -148,4 +149,9 @@ public String queueManager() { public int listenerPort() { return container.getMappedPort(MQ_LISTENER_PORT); } + + @Override + public String uiUrl() { + return String.format("https://%s:%d/ibmmq/console", container.getHost(), container.getMappedPort(WEB_CONSOLE_PORT)); + } } diff --git a/test-infra/camel-test-infra-infinispan/src/main/java/org/apache/camel/test/infra/infinispan/services/InfinispanInfraService.java b/test-infra/camel-test-infra-infinispan/src/main/java/org/apache/camel/test/infra/infinispan/services/InfinispanInfraService.java index 87124267fe753..1a55f60e62eed 100644 --- a/test-infra/camel-test-infra-infinispan/src/main/java/org/apache/camel/test/infra/infinispan/services/InfinispanInfraService.java +++ b/test-infra/camel-test-infra-infinispan/src/main/java/org/apache/camel/test/infra/infinispan/services/InfinispanInfraService.java @@ -37,4 +37,8 @@ public interface InfinispanInfraService extends InfrastructureService { default String hosts() { return String.format("%s:%d", host(), port()); } + + default String uiUrl() { + return String.format("http://%s:%d/console", host(), port()); + } } diff --git a/test-infra/camel-test-infra-infinispan/src/main/java/org/apache/camel/test/infra/infinispan/services/InfinispanLocalContainerInfraService.java b/test-infra/camel-test-infra-infinispan/src/main/java/org/apache/camel/test/infra/infinispan/services/InfinispanLocalContainerInfraService.java index 1c415377de072..15962f2ea89ca 100644 --- a/test-infra/camel-test-infra-infinispan/src/main/java/org/apache/camel/test/infra/infinispan/services/InfinispanLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-infinispan/src/main/java/org/apache/camel/test/infra/infinispan/services/InfinispanLocalContainerInfraService.java @@ -34,7 +34,8 @@ @InfraService(service = InfinispanInfraService.class, description = "Infinispan is a distributed in-memory key/value data store", - serviceAlias = { "infinispan" }) + serviceAlias = { "infinispan" }, + uiSupported = true) public class InfinispanLocalContainerInfraService implements InfinispanInfraService, ContainerService> { public static final String CONTAINER_NAME = "infinispan"; private static final String DEFAULT_USERNAME = "admin"; diff --git a/test-infra/camel-test-infra-jaeger/src/main/java/org/apache/camel/test/infra/jaeger/services/JaegerInfraService.java b/test-infra/camel-test-infra-jaeger/src/main/java/org/apache/camel/test/infra/jaeger/services/JaegerInfraService.java index d89088ea5b16f..03f5d468d65a6 100644 --- a/test-infra/camel-test-infra-jaeger/src/main/java/org/apache/camel/test/infra/jaeger/services/JaegerInfraService.java +++ b/test-infra/camel-test-infra-jaeger/src/main/java/org/apache/camel/test/infra/jaeger/services/JaegerInfraService.java @@ -45,4 +45,8 @@ default String collectorHttpEndpoint() { default String queryUiUrl() { return String.format("http://%s:%d", host(), queryUiPort()); } + + default String uiUrl() { + return queryUiUrl(); + } } diff --git a/test-infra/camel-test-infra-jaeger/src/main/java/org/apache/camel/test/infra/jaeger/services/JaegerLocalContainerInfraService.java b/test-infra/camel-test-infra-jaeger/src/main/java/org/apache/camel/test/infra/jaeger/services/JaegerLocalContainerInfraService.java index 94fa4c279dc74..9067785463f11 100644 --- a/test-infra/camel-test-infra-jaeger/src/main/java/org/apache/camel/test/infra/jaeger/services/JaegerLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-jaeger/src/main/java/org/apache/camel/test/infra/jaeger/services/JaegerLocalContainerInfraService.java @@ -28,7 +28,8 @@ */ @InfraService(service = JaegerInfraService.class, description = "Jaeger is a distributed tracing backend with OTLP collector and UI", - serviceAlias = { "jaeger" }) + serviceAlias = { "jaeger" }, + uiSupported = true) public class JaegerLocalContainerInfraService implements JaegerInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(JaegerLocalContainerInfraService.class); diff --git a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ConfluentInfraService.java b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ConfluentInfraService.java index 93c95805f865e..2033f566b4aab 100644 --- a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ConfluentInfraService.java +++ b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ConfluentInfraService.java @@ -28,7 +28,7 @@ @InfraService(service = KafkaInfraService.class, description = "Apache Kafka, Distributed event streaming platform", - serviceAlias = "kafka", serviceImplementationAlias = "confluent") + serviceAlias = "kafka", serviceImplementationAlias = "confluent", uiSupported = true) public class ConfluentInfraService implements KafkaInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(ConfluentInfraService.class); diff --git a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ContainerLocalKafkaInfraService.java b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ContainerLocalKafkaInfraService.java index 80fc7143d1f89..be80531e52b56 100644 --- a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ContainerLocalKafkaInfraService.java +++ b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ContainerLocalKafkaInfraService.java @@ -24,19 +24,25 @@ import org.apache.camel.test.infra.kafka.common.KafkaProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.testcontainers.Testcontainers; +import org.testcontainers.containers.GenericContainer; import org.testcontainers.kafka.KafkaContainer; import org.testcontainers.utility.DockerImageName; @InfraService(service = KafkaInfraService.class, description = "Apache Kafka, Distributed event streaming platform", - serviceAlias = "kafka") + serviceAlias = "kafka", uiSupported = true) public class ContainerLocalKafkaInfraService implements KafkaInfraService, ContainerService { public static final String KAFKA_IMAGE_NAME = LocalPropertyResolver.getProperty( ContainerLocalKafkaInfraService.class, KafkaProperties.KAFKA_CONTAINER); + private static final String KAFKA_UI_CONTAINER_IMAGE = "kafka-ui.container.image"; + private static final int KAFKA_UI_PORT = 9080; + private static final Logger LOG = LoggerFactory.getLogger(ContainerLocalKafkaInfraService.class); protected KafkaContainer kafka; + private GenericContainer uiContainer; public ContainerLocalKafkaInfraService() { kafka = initContainer(); @@ -87,14 +93,52 @@ public void initialize() { registerProperties(); LOG.info("Kafka bootstrap server running at address {}", kafka.getBootstrapServers()); + + if (ContainerEnvironmentUtil.isWithUi()) { + try { + startUiContainer(); + } catch (Exception e) { + LOG.warn("Failed to start Kafka UI container: {}", e.getMessage()); + } + } + } + + private void startUiContainer() { + String uiImage = LocalPropertyResolver.getProperty( + ContainerLocalKafkaInfraService.class, KAFKA_UI_CONTAINER_IMAGE); + int kafkaPort = ContainerEnvironmentUtil.getConfiguredPort(9092); + Testcontainers.exposeHostPorts(kafkaPort); + + uiContainer = new GenericContainer<>(uiImage) + .withEnv("DYNAMIC_CONFIG_ENABLED", "true") + .withEnv("KAFKA_CLUSTERS_0_NAME", "camel-infra") + .withEnv("KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS", "host.testcontainers.internal:" + kafkaPort) + .withEnv("SERVER_PORT", String.valueOf(KAFKA_UI_PORT)) + .withAccessToHost(true); + ContainerEnvironmentUtil.configurePort(uiContainer, true, KAFKA_UI_PORT); + uiContainer.start(); + + LOG.info("Kafka UI running at http://{}:{}", uiContainer.getHost(), uiContainer.getMappedPort(KAFKA_UI_PORT)); } @Override public void shutdown() { + if (uiContainer != null) { + LOG.info("Shutting down Kafka UI container"); + uiContainer.stop(); + } LOG.info("Shutting down Kafka container"); kafka.stop(); } + @Override + public String uiUrl() { + if (uiContainer != null && uiContainer.isRunning()) { + return String.format("http://%s:%d", uiContainer.getHost(), uiContainer.getMappedPort(KAFKA_UI_PORT)); + } + return null; + } + @Override public KafkaContainer getContainer() { return kafka; diff --git a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/KafkaInfraService.java b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/KafkaInfraService.java index 108982f577756..934cb23245e88 100644 --- a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/KafkaInfraService.java +++ b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/KafkaInfraService.java @@ -33,4 +33,7 @@ public interface KafkaInfraService extends InfrastructureService { String brokers(); + default String uiUrl() { + return null; + } } diff --git a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/RedpandaInfraService.java b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/RedpandaInfraService.java index 301791202efcf..b35bb07752355 100644 --- a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/RedpandaInfraService.java +++ b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/RedpandaInfraService.java @@ -28,7 +28,7 @@ @InfraService(service = KafkaInfraService.class, description = "Apache Kafka, Distributed event streaming platform", - serviceAlias = "kafka", serviceImplementationAlias = "redpanda") + serviceAlias = "kafka", serviceImplementationAlias = "redpanda", uiSupported = true) public class RedpandaInfraService implements KafkaInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(RedpandaInfraService.class); diff --git a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/StrimziInfraService.java b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/StrimziInfraService.java index f6cada56317fe..e7c5ab3aafe1e 100644 --- a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/StrimziInfraService.java +++ b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/StrimziInfraService.java @@ -28,7 +28,7 @@ @InfraService(service = KafkaInfraService.class, description = "Apache Kafka, Distributed event streaming platform", - serviceAlias = "kafka", serviceImplementationAlias = "strimzi") + serviceAlias = "kafka", serviceImplementationAlias = "strimzi", uiSupported = true) public class StrimziInfraService implements KafkaInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(StrimziInfraService.class); diff --git a/test-infra/camel-test-infra-kafka/src/main/resources/org/apache/camel/test/infra/kafka/services/container.properties b/test-infra/camel-test-infra-kafka/src/main/resources/org/apache/camel/test/infra/kafka/services/container.properties index e83a87bb99813..0abfcfe8e75be 100644 --- a/test-infra/camel-test-infra-kafka/src/main/resources/org/apache/camel/test/infra/kafka/services/container.properties +++ b/test-infra/camel-test-infra-kafka/src/main/resources/org/apache/camel/test/infra/kafka/services/container.properties @@ -25,3 +25,4 @@ kafka.container.image.version.freeze.major=true redpanda.container.image.version.exclude=fips,amd64,arm64 strimzi.container.image.version.freeze.major=true confluent.container.image.version.freeze.major=true +kafka-ui.container.image=mirror.gcr.io/provectuslabs/kafka-ui:v0.7.2 diff --git a/test-infra/camel-test-infra-keycloak/src/main/java/org/apache/camel/test/infra/keycloak/services/KeycloakInfraService.java b/test-infra/camel-test-infra-keycloak/src/main/java/org/apache/camel/test/infra/keycloak/services/KeycloakInfraService.java index 3108955e5fd61..8d2e9240e1054 100644 --- a/test-infra/camel-test-infra-keycloak/src/main/java/org/apache/camel/test/infra/keycloak/services/KeycloakInfraService.java +++ b/test-infra/camel-test-infra-keycloak/src/main/java/org/apache/camel/test/infra/keycloak/services/KeycloakInfraService.java @@ -58,4 +58,8 @@ default String username() { default String password() { return getKeycloakPassword(); } + + default String uiUrl() { + return serverUrl() + "/admin"; + } } diff --git a/test-infra/camel-test-infra-keycloak/src/main/java/org/apache/camel/test/infra/keycloak/services/KeycloakLocalContainerInfraService.java b/test-infra/camel-test-infra-keycloak/src/main/java/org/apache/camel/test/infra/keycloak/services/KeycloakLocalContainerInfraService.java index 16a3ced4b56b5..60abddf65c0a3 100644 --- a/test-infra/camel-test-infra-keycloak/src/main/java/org/apache/camel/test/infra/keycloak/services/KeycloakLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-keycloak/src/main/java/org/apache/camel/test/infra/keycloak/services/KeycloakLocalContainerInfraService.java @@ -33,7 +33,8 @@ @InfraService(service = KeycloakInfraService.class, description = "Keycloak is an open source identity and access management solution", - serviceAlias = { "keycloak" }) + serviceAlias = { "keycloak" }, + uiSupported = true) public class KeycloakLocalContainerInfraService implements KeycloakInfraService, ContainerService> { private static final Logger LOG = LoggerFactory.getLogger(KeycloakLocalContainerInfraService.class); diff --git a/test-infra/camel-test-infra-minio/src/main/java/org/apache/camel/test/infra/minio/services/MinioInfraService.java b/test-infra/camel-test-infra-minio/src/main/java/org/apache/camel/test/infra/minio/services/MinioInfraService.java index 2594ae1c475d2..7ecdb6d32e3d1 100644 --- a/test-infra/camel-test-infra-minio/src/main/java/org/apache/camel/test/infra/minio/services/MinioInfraService.java +++ b/test-infra/camel-test-infra-minio/src/main/java/org/apache/camel/test/infra/minio/services/MinioInfraService.java @@ -40,4 +40,8 @@ public interface MinioInfraService extends InfrastructureService { default String endpoint() { return String.format("http://%s:%d", host(), port()); } + + default String uiUrl() { + return String.format("http://%s:%d", host(), consolePort()); + } } diff --git a/test-infra/camel-test-infra-minio/src/main/java/org/apache/camel/test/infra/minio/services/MinioLocalContainerInfraService.java b/test-infra/camel-test-infra-minio/src/main/java/org/apache/camel/test/infra/minio/services/MinioLocalContainerInfraService.java index 12a85538ff626..420006bc634f5 100644 --- a/test-infra/camel-test-infra-minio/src/main/java/org/apache/camel/test/infra/minio/services/MinioLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-minio/src/main/java/org/apache/camel/test/infra/minio/services/MinioLocalContainerInfraService.java @@ -30,7 +30,8 @@ @InfraService(service = MinioInfraService.class, description = "MinIO is a high-performance S3 compatible object storage", - serviceAlias = { "minio" }) + serviceAlias = { "minio" }, + uiSupported = true) public class MinioLocalContainerInfraService implements MinioInfraService, ContainerService> { public static final String CONTAINER_NAME = "minio"; private static final String ACCESS_KEY = System.getProperty(MinioProperties.ACCESS_KEY, "testAccessKey"); diff --git a/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBInfraService.java b/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBInfraService.java index 392eaa2784aa0..acf146e486de0 100644 --- a/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBInfraService.java +++ b/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBInfraService.java @@ -40,4 +40,8 @@ public interface MongoDBInfraService extends InfrastructureService { default String hosts() { return getConnectionAddress(); } + + default String uiUrl() { + return null; + } } diff --git a/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBLocalContainerInfraService.java b/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBLocalContainerInfraService.java index caa92fe76048d..3e640ea871679 100644 --- a/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBLocalContainerInfraService.java @@ -24,16 +24,22 @@ import org.apache.camel.test.infra.mongodb.common.MongoDBProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.testcontainers.Testcontainers; +import org.testcontainers.containers.GenericContainer; import org.testcontainers.mongodb.MongoDBContainer; import org.testcontainers.utility.DockerImageName; @InfraService(service = MongoDBInfraService.class, description = "MongoDB is a document-oriented NoSQL database", - serviceAlias = { "mongodb" }) + serviceAlias = { "mongodb" }, uiSupported = true) public class MongoDBLocalContainerInfraService implements MongoDBInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(MongoDBLocalContainerInfraService.class); private static final int DEFAULT_MONGODB_PORT = 27017; + private static final String MONGO_EXPRESS_CONTAINER_IMAGE = "mongo-express.container.image"; + private static final int MONGO_EXPRESS_PORT = 8081; + private final MongoDBContainer container; + private GenericContainer uiContainer; public MongoDBLocalContainerInfraService() { this(LocalPropertyResolver.getProperty(MongoDBLocalContainerInfraService.class, MongoDBProperties.MONGODB_CONTAINER)); @@ -87,14 +93,46 @@ public void initialize() { container.start(); registerProperties(); LOG.info("MongoDB service running at {}", container.getReplicaSetUrl()); + + if (ContainerEnvironmentUtil.isWithUi()) { + try { + String uiImage = LocalPropertyResolver.getProperty( + MongoDBLocalContainerInfraService.class, MONGO_EXPRESS_CONTAINER_IMAGE); + int mongoPort = ContainerEnvironmentUtil.getConfiguredPort(DEFAULT_MONGODB_PORT); + Testcontainers.exposeHostPorts(mongoPort); + uiContainer = new GenericContainer<>(uiImage) + .withEnv("ME_CONFIG_MONGODB_URL", + "mongodb://host.testcontainers.internal:" + mongoPort + "/?directConnection=true") + .withEnv("ME_CONFIG_BASICAUTH", "false") + .withAccessToHost(true); + ContainerEnvironmentUtil.configurePort(uiContainer, true, MONGO_EXPRESS_PORT); + uiContainer.start(); + LOG.info("Mongo Express running at http://{}:{}", uiContainer.getHost(), + uiContainer.getMappedPort(MONGO_EXPRESS_PORT)); + } catch (Exception e) { + LOG.warn("Failed to start Mongo Express UI container: {}", e.getMessage()); + } + } } @Override public void shutdown() { + if (uiContainer != null) { + LOG.info("Stopping the Mongo Express container"); + uiContainer.stop(); + } LOG.info("Stopping the MongoDB container"); container.stop(); } + @Override + public String uiUrl() { + if (uiContainer != null && uiContainer.isRunning()) { + return String.format("http://%s:%d", uiContainer.getHost(), uiContainer.getMappedPort(MONGO_EXPRESS_PORT)); + } + return null; + } + @Override public MongoDBContainer getContainer() { return container; diff --git a/test-infra/camel-test-infra-mongodb/src/main/resources/org/apache/camel/test/infra/mongodb/services/container.properties b/test-infra/camel-test-infra-mongodb/src/main/resources/org/apache/camel/test/infra/mongodb/services/container.properties index 1b8c67213bc6d..773aea4f6ac96 100644 --- a/test-infra/camel-test-infra-mongodb/src/main/resources/org/apache/camel/test/infra/mongodb/services/container.properties +++ b/test-infra/camel-test-infra-mongodb/src/main/resources/org/apache/camel/test/infra/mongodb/services/container.properties @@ -19,3 +19,4 @@ mongodb.container.ppc64le=icr.io/ppc64le-oss/mongodb-ppc64le:4.4.24 mongodb.container.version.include=jammy mongodb.container.ppc64le.version.exclude=bv mongodb.container.ppc64le.version.freeze.major=true +mongo-express.container.image=mirror.gcr.io/library/mongo-express:1.0.2 diff --git a/test-infra/camel-test-infra-neo4j/src/main/java/org/apache/camel/test/infra/neo4j/services/Neo4jInfraService.java b/test-infra/camel-test-infra-neo4j/src/main/java/org/apache/camel/test/infra/neo4j/services/Neo4jInfraService.java index ece157e2ae0a5..a0ed56cbba02d 100644 --- a/test-infra/camel-test-infra-neo4j/src/main/java/org/apache/camel/test/infra/neo4j/services/Neo4jInfraService.java +++ b/test-infra/camel-test-infra-neo4j/src/main/java/org/apache/camel/test/infra/neo4j/services/Neo4jInfraService.java @@ -25,4 +25,8 @@ public interface Neo4jInfraService extends InfrastructureService { String getNeo4jDatabaseUser(); String getNeo4jDatabasePassword(); + + default String uiUrl() { + return null; + } } diff --git a/test-infra/camel-test-infra-neo4j/src/main/java/org/apache/camel/test/infra/neo4j/services/Neo4jLocalContainerInfraService.java b/test-infra/camel-test-infra-neo4j/src/main/java/org/apache/camel/test/infra/neo4j/services/Neo4jLocalContainerInfraService.java index fee77cd820617..f1901dd49766f 100644 --- a/test-infra/camel-test-infra-neo4j/src/main/java/org/apache/camel/test/infra/neo4j/services/Neo4jLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-neo4j/src/main/java/org/apache/camel/test/infra/neo4j/services/Neo4jLocalContainerInfraService.java @@ -30,7 +30,8 @@ @InfraService(service = Neo4jInfraService.class, description = "Neo4j is a graph database management system", - serviceAlias = { "neo4j" }) + serviceAlias = { "neo4j" }, + uiSupported = true) public class Neo4jLocalContainerInfraService implements Neo4jInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(Neo4jLocalContainerInfraService.class); @@ -110,4 +111,9 @@ public String getNeo4jDatabaseUser() { public String getNeo4jDatabasePassword() { return container.getAdminPassword(); } + + @Override + public String uiUrl() { + return String.format("http://%s:%d", container.getHost(), container.getMappedPort(7474)); + } } diff --git a/test-infra/camel-test-infra-opensearch/src/main/java/org/apache/camel/test/infra/opensearch/services/OpenSearchInfraService.java b/test-infra/camel-test-infra-opensearch/src/main/java/org/apache/camel/test/infra/opensearch/services/OpenSearchInfraService.java index 1a06dfc8b3596..b43715f081e83 100644 --- a/test-infra/camel-test-infra-opensearch/src/main/java/org/apache/camel/test/infra/opensearch/services/OpenSearchInfraService.java +++ b/test-infra/camel-test-infra-opensearch/src/main/java/org/apache/camel/test/infra/opensearch/services/OpenSearchInfraService.java @@ -32,4 +32,8 @@ default String getHttpHostAddress() { String getUsername(); String getPassword(); + + default String uiUrl() { + return null; + } } diff --git a/test-infra/camel-test-infra-opensearch/src/main/java/org/apache/camel/test/infra/opensearch/services/OpenSearchLocalContainerInfraService.java b/test-infra/camel-test-infra-opensearch/src/main/java/org/apache/camel/test/infra/opensearch/services/OpenSearchLocalContainerInfraService.java index 577ad23abbd36..aa4f68489b8c7 100644 --- a/test-infra/camel-test-infra-opensearch/src/main/java/org/apache/camel/test/infra/opensearch/services/OpenSearchLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-opensearch/src/main/java/org/apache/camel/test/infra/opensearch/services/OpenSearchLocalContainerInfraService.java @@ -19,6 +19,7 @@ import java.time.Duration; +import org.apache.camel.spi.annotations.InfraService; import org.apache.camel.test.infra.common.LocalPropertyResolver; import org.apache.camel.test.infra.common.services.ContainerEnvironmentUtil; import org.apache.camel.test.infra.common.services.ContainerService; @@ -26,17 +27,27 @@ import org.opensearch.testcontainers.OpensearchContainer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.testcontainers.Testcontainers; +import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; import org.testcontainers.utility.DockerImageName; +@InfraService(service = OpenSearchInfraService.class, + description = "OpenSearch is a distributed search and analytics engine", + serviceAlias = { "opensearch" }, uiSupported = true) public class OpenSearchLocalContainerInfraService implements OpenSearchInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(OpenSearchLocalContainerInfraService.class); private static final int OPEN_SEARCH_PORT = 9200; private static final String USER_NAME = "admin"; // NOTE: default value used for testing purposes only. private static final String PASSWORD = "admin"; // NOSONAR + + private static final String OPENSEARCH_DASHBOARDS_CONTAINER_IMAGE = "opensearch-dashboards.container.image"; + private static final int OPENSEARCH_DASHBOARDS_PORT = 5601; + private final OpensearchContainer container; + private GenericContainer uiContainer; public OpenSearchLocalContainerInfraService() { this(LocalPropertyResolver.getProperty(OpenSearchLocalContainerInfraService.class, @@ -112,10 +123,39 @@ public void initialize() { registerProperties(); LOG.info("OpenSearch instance running at {}", getHttpHostAddress()); + + if (ContainerEnvironmentUtil.isWithUi()) { + try { + startUiContainer(); + } catch (Exception e) { + LOG.warn("Failed to start OpenSearch Dashboards UI container: {}", e.getMessage()); + } + } + } + + private void startUiContainer() { + String uiImage = LocalPropertyResolver.getProperty( + OpenSearchLocalContainerInfraService.class, OPENSEARCH_DASHBOARDS_CONTAINER_IMAGE); + int opensearchPort = ContainerEnvironmentUtil.getConfiguredPort(OPEN_SEARCH_PORT); + Testcontainers.exposeHostPorts(opensearchPort); + + uiContainer = new GenericContainer<>(uiImage) + .withEnv("OPENSEARCH_HOSTS", "[\"http://host.testcontainers.internal:" + opensearchPort + "\"]") + .withEnv("DISABLE_SECURITY_DASHBOARDS_PLUGIN", "true") + .withAccessToHost(true); + ContainerEnvironmentUtil.configurePort(uiContainer, true, OPENSEARCH_DASHBOARDS_PORT); + uiContainer.start(); + + LOG.info("OpenSearch Dashboards running at http://{}:{}", + uiContainer.getHost(), uiContainer.getMappedPort(OPENSEARCH_DASHBOARDS_PORT)); } @Override public void shutdown() { + if (uiContainer != null) { + LOG.info("Shutting down OpenSearch Dashboards container"); + uiContainer.stop(); + } LOG.info("Stopping the OpenSearch container"); container.stop(); } @@ -134,4 +174,13 @@ public String getUsername() { public String getPassword() { return PASSWORD; } + + @Override + public String uiUrl() { + if (uiContainer != null && uiContainer.isRunning()) { + return String.format("http://%s:%d", uiContainer.getHost(), + uiContainer.getMappedPort(OPENSEARCH_DASHBOARDS_PORT)); + } + return null; + } } diff --git a/test-infra/camel-test-infra-opensearch/src/main/resources/org/apache/camel/test/infra/opensearch/services/container.properties b/test-infra/camel-test-infra-opensearch/src/main/resources/org/apache/camel/test/infra/opensearch/services/container.properties index fa19956c85a6d..39403ac6b92d9 100644 --- a/test-infra/camel-test-infra-opensearch/src/main/resources/org/apache/camel/test/infra/opensearch/services/container.properties +++ b/test-infra/camel-test-infra-opensearch/src/main/resources/org/apache/camel/test/infra/opensearch/services/container.properties @@ -16,3 +16,4 @@ ## --------------------------------------------------------------------------- opensearch.container=mirror.gcr.io/opensearchproject/opensearch:3.7.0 opensearch.container.ppc64le=icr.io/ppc64le-oss/opensearch-ppc64le:3.3.0 +opensearch-dashboards.container.image=mirror.gcr.io/opensearchproject/opensearch-dashboards:2.21.0 diff --git a/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresInfraService.java b/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresInfraService.java index 4d6b5a3138745..aef2ac36aa1d7 100644 --- a/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresInfraService.java +++ b/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresInfraService.java @@ -64,4 +64,8 @@ default Map beanProperties() { properties.put("camel.beans.postgresDS.password", password()); return properties; } + + default String uiUrl() { + return null; + } } diff --git a/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresLocalContainerInfraService.java b/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresLocalContainerInfraService.java index cc09fcad11cde..87b40c04cd3f2 100644 --- a/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresLocalContainerInfraService.java @@ -25,20 +25,27 @@ import org.apache.camel.test.infra.postgres.common.PostgresProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.testcontainers.Testcontainers; +import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.postgresql.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; @InfraService(service = PostgresInfraService.class, description = "PostgreSQL is an open source object-relational database", - serviceAlias = { "postgres" }) + serviceAlias = { "postgres" }, uiSupported = true) public class PostgresLocalContainerInfraService implements PostgresInfraService, ContainerService { public static final String DEFAULT_POSTGRES_CONTAINER = LocalPropertyResolver.getProperty(PostgresLocalContainerInfraService.class, PostgresProperties.POSTGRES_CONTAINER); + + private static final String PGADMIN_CONTAINER_IMAGE = "pgadmin.container.image"; + private static final int PGADMIN_PORT = 5050; + private static final Logger LOG = LoggerFactory.getLogger(PostgresLocalContainerInfraService.class); private final PostgreSQLContainer container; + private GenericContainer uiContainer; public PostgresLocalContainerInfraService() { this(DEFAULT_POSTGRES_CONTAINER); @@ -96,10 +103,39 @@ public void initialize() { registerProperties(); LOG.info("Postgres instance running at {}", getServiceAddress()); + + if (ContainerEnvironmentUtil.isWithUi()) { + try { + startUiContainer(); + } catch (Exception e) { + LOG.warn("Failed to start pgAdmin UI container: {}", e.getMessage()); + } + } + } + + private void startUiContainer() { + String uiImage = LocalPropertyResolver.getProperty( + PostgresLocalContainerInfraService.class, PGADMIN_CONTAINER_IMAGE); + int pgPort = ContainerEnvironmentUtil.getConfiguredPort(5432); + Testcontainers.exposeHostPorts(pgPort); + + uiContainer = new GenericContainer<>(uiImage) + .withEnv("PGADMIN_DEFAULT_EMAIL", "admin@camel.apache.org") + .withEnv("PGADMIN_DEFAULT_PASSWORD", "admin") + .withEnv("PGADMIN_LISTEN_PORT", "5050") + .withAccessToHost(true); + ContainerEnvironmentUtil.configurePort(uiContainer, true, PGADMIN_PORT); + uiContainer.start(); + + LOG.info("pgAdmin running at http://{}:{}", uiContainer.getHost(), uiContainer.getMappedPort(PGADMIN_PORT)); } @Override public void shutdown() { + if (uiContainer != null) { + LOG.info("Shutting down pgAdmin container"); + uiContainer.stop(); + } LOG.info("Stopping the Postgres container"); container.stop(); } @@ -133,4 +169,12 @@ public String userName() { public String password() { return container.getPassword(); } + + @Override + public String uiUrl() { + if (uiContainer != null && uiContainer.isRunning()) { + return String.format("http://%s:%d", uiContainer.getHost(), uiContainer.getMappedPort(PGADMIN_PORT)); + } + return null; + } } diff --git a/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresVectorLocalContainerInfraService.java b/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresVectorLocalContainerInfraService.java index 3ac2a518edc40..169604470f3ee 100644 --- a/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresVectorLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresVectorLocalContainerInfraService.java @@ -22,7 +22,7 @@ @InfraService(service = PostgresInfraService.class, description = "PostgreSQL with pgvector extension for vector similarity search", - serviceAlias = { "postgres-vector", "pgvector" }) + serviceAlias = { "postgres-vector", "pgvector" }, uiSupported = true) public class PostgresVectorLocalContainerInfraService extends PostgresLocalContainerInfraService { public static final String DEFAULT_POSTGRES_VECTOR_CONTAINER diff --git a/test-infra/camel-test-infra-postgres/src/main/resources/org/apache/camel/test/infra/postgres/services/container.properties b/test-infra/camel-test-infra-postgres/src/main/resources/org/apache/camel/test/infra/postgres/services/container.properties index 23cf52bd9544b..4445846efb37f 100644 --- a/test-infra/camel-test-infra-postgres/src/main/resources/org/apache/camel/test/infra/postgres/services/container.properties +++ b/test-infra/camel-test-infra-postgres/src/main/resources/org/apache/camel/test/infra/postgres/services/container.properties @@ -18,3 +18,4 @@ postgres.container=mirror.gcr.io/postgres:17.10-alpine postgres.container.version.include=alpine postgres.container.version.freeze.major=true postgres.vector.container=mirror.gcr.io/pgvector/pgvector:pg18 +pgadmin.container.image=mirror.gcr.io/dpage/pgadmin4:9 diff --git a/test-infra/camel-test-infra-qdrant/src/main/java/org/apache/camel/test/infra/qdrant/services/QdrantInfraService.java b/test-infra/camel-test-infra-qdrant/src/main/java/org/apache/camel/test/infra/qdrant/services/QdrantInfraService.java index 7ffc6998d81a4..2d54a24db7945 100644 --- a/test-infra/camel-test-infra-qdrant/src/main/java/org/apache/camel/test/infra/qdrant/services/QdrantInfraService.java +++ b/test-infra/camel-test-infra-qdrant/src/main/java/org/apache/camel/test/infra/qdrant/services/QdrantInfraService.java @@ -51,6 +51,10 @@ default String apiKey() { return ""; } + default String uiUrl() { + return String.format("http://%s:%d/dashboard", getHttpHost(), getHttpPort()); + } + default HttpResponse put(String path, Map body) throws Exception { final String reqPath = !path.startsWith("/") ? "/" + path : path; final String reqUrl = String.format("http://%s:%d%s", getHttpHost(), getHttpPort(), reqPath); diff --git a/test-infra/camel-test-infra-qdrant/src/main/java/org/apache/camel/test/infra/qdrant/services/QdrantLocalContainerInfraService.java b/test-infra/camel-test-infra-qdrant/src/main/java/org/apache/camel/test/infra/qdrant/services/QdrantLocalContainerInfraService.java index 08605b8f43d19..2bfa142e730c4 100644 --- a/test-infra/camel-test-infra-qdrant/src/main/java/org/apache/camel/test/infra/qdrant/services/QdrantLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-qdrant/src/main/java/org/apache/camel/test/infra/qdrant/services/QdrantLocalContainerInfraService.java @@ -29,7 +29,8 @@ @InfraService(service = QdrantInfraService.class, description = "Qdrant is a vector similarity search engine and database", - serviceAlias = { "qdrant" }) + serviceAlias = { "qdrant" }, + uiSupported = true) public class QdrantLocalContainerInfraService implements QdrantInfraService, ContainerService { public static final int HTTP_PORT = 6333; public static final int GRPC_PORT = 6334; diff --git a/test-infra/camel-test-infra-rabbitmq/src/main/java/org/apache/camel/test/infra/rabbitmq/services/RabbitMQInfraService.java b/test-infra/camel-test-infra-rabbitmq/src/main/java/org/apache/camel/test/infra/rabbitmq/services/RabbitMQInfraService.java index 8c3682211964c..24e828942f237 100644 --- a/test-infra/camel-test-infra-rabbitmq/src/main/java/org/apache/camel/test/infra/rabbitmq/services/RabbitMQInfraService.java +++ b/test-infra/camel-test-infra-rabbitmq/src/main/java/org/apache/camel/test/infra/rabbitmq/services/RabbitMQInfraService.java @@ -89,4 +89,8 @@ default String host() { default String brokerUrl() { return String.format("amqp://%s:%d", hostname(), port()); } + + default String uiUrl() { + return managementUri(); + } } diff --git a/test-infra/camel-test-infra-rabbitmq/src/main/java/org/apache/camel/test/infra/rabbitmq/services/RabbitMQLocalContainerInfraService.java b/test-infra/camel-test-infra-rabbitmq/src/main/java/org/apache/camel/test/infra/rabbitmq/services/RabbitMQLocalContainerInfraService.java index 2aa1e46271ff3..704110fe12354 100644 --- a/test-infra/camel-test-infra-rabbitmq/src/main/java/org/apache/camel/test/infra/rabbitmq/services/RabbitMQLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-rabbitmq/src/main/java/org/apache/camel/test/infra/rabbitmq/services/RabbitMQLocalContainerInfraService.java @@ -29,7 +29,8 @@ @InfraService(service = RabbitMQInfraService.class, description = "RabbitMQ is an open source message and streaming broker", - serviceAlias = { "rabbitmq" }) + serviceAlias = { "rabbitmq" }, + uiSupported = true) public class RabbitMQLocalContainerInfraService implements RabbitMQInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(RabbitMQLocalContainerInfraService.class); diff --git a/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisInfraService.java b/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisInfraService.java index 0d7635248d908..9ad9dd05dada9 100644 --- a/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisInfraService.java +++ b/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisInfraService.java @@ -35,4 +35,8 @@ default String getServiceAddress() { default String endpointUri() { return String.format("spring-redis:%s:%d", host(), port()); } + + default String uiUrl() { + return null; + } } diff --git a/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisLocalContainerInfraService.java b/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisLocalContainerInfraService.java index 56ab2aaf41900..ae5297413cff9 100644 --- a/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisLocalContainerInfraService.java @@ -17,19 +17,25 @@ package org.apache.camel.test.infra.redis.services; import org.apache.camel.spi.annotations.InfraService; +import org.apache.camel.test.infra.common.LocalPropertyResolver; import org.apache.camel.test.infra.common.services.ContainerEnvironmentUtil; import org.apache.camel.test.infra.common.services.ContainerService; import org.apache.camel.test.infra.redis.common.RedisProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.testcontainers.Testcontainers; +import org.testcontainers.containers.GenericContainer; @InfraService(service = RedisInfraService.class, description = "Redis is an open source in-memory data store", - serviceAlias = { "redis" }) + serviceAlias = { "redis" }, uiSupported = true) public class RedisLocalContainerInfraService implements RedisInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(RedisLocalContainerInfraService.class); + private static final String REDIS_COMMANDER_CONTAINER_IMAGE = "redis-commander.container.image"; + private static final int REDIS_COMMANDER_PORT = 8082; private final RedisContainer container; + private GenericContainer uiContainer; public RedisLocalContainerInfraService() { container = initContainer(); @@ -71,14 +77,45 @@ public void initialize() { registerProperties(); LOG.info("Redis instance running at {}", getServiceAddress()); + + if (ContainerEnvironmentUtil.isWithUi()) { + try { + String uiImage = LocalPropertyResolver.getProperty( + RedisLocalContainerInfraService.class, REDIS_COMMANDER_CONTAINER_IMAGE); + int redisPort = ContainerEnvironmentUtil.getConfiguredPort(RedisProperties.DEFAULT_PORT); + Testcontainers.exposeHostPorts(redisPort); + uiContainer = new GenericContainer<>(uiImage) + .withEnv("REDIS_HOSTS", "local:host.testcontainers.internal:" + redisPort) + .withEnv("PORT", String.valueOf(REDIS_COMMANDER_PORT)) + .withAccessToHost(true); + ContainerEnvironmentUtil.configurePort(uiContainer, true, REDIS_COMMANDER_PORT); + uiContainer.start(); + LOG.info("Redis Commander running at http://{}:{}", uiContainer.getHost(), + uiContainer.getMappedPort(REDIS_COMMANDER_PORT)); + } catch (Exception e) { + LOG.warn("Failed to start Redis Commander UI container: {}", e.getMessage()); + } + } } @Override public void shutdown() { + if (uiContainer != null) { + LOG.info("Stopping the Redis Commander container"); + uiContainer.stop(); + } LOG.info("Stopping the Redis container"); container.stop(); } + @Override + public String uiUrl() { + if (uiContainer != null && uiContainer.isRunning()) { + return String.format("http://%s:%d", uiContainer.getHost(), uiContainer.getMappedPort(REDIS_COMMANDER_PORT)); + } + return null; + } + @Override public RedisContainer getContainer() { return container; diff --git a/test-infra/camel-test-infra-redis/src/main/resources/org/apache/camel/test/infra/redis/services/container.properties b/test-infra/camel-test-infra-redis/src/main/resources/org/apache/camel/test/infra/redis/services/container.properties index f2bf442ee54e7..72e89609a3b01 100644 --- a/test-infra/camel-test-infra-redis/src/main/resources/org/apache/camel/test/infra/redis/services/container.properties +++ b/test-infra/camel-test-infra-redis/src/main/resources/org/apache/camel/test/infra/redis/services/container.properties @@ -18,3 +18,4 @@ redis.container=mirror.gcr.io/redis:7.4.9-alpine redis.container.version.include=alpine redis.container.version.exclude=rc,beta redis.container.version.freeze.major=true +redis-commander.container.image=mirror.gcr.io/rediscommander/redis-commander:latest diff --git a/test-infra/camel-test-infra-solr/src/main/java/org/apache/camel/test/infra/solr/services/SolrInfraService.java b/test-infra/camel-test-infra-solr/src/main/java/org/apache/camel/test/infra/solr/services/SolrInfraService.java index 5f5d8c79b42c2..1fac820bbba84 100644 --- a/test-infra/camel-test-infra-solr/src/main/java/org/apache/camel/test/infra/solr/services/SolrInfraService.java +++ b/test-infra/camel-test-infra-solr/src/main/java/org/apache/camel/test/infra/solr/services/SolrInfraService.java @@ -39,4 +39,8 @@ default String host() { default int port() { return getPort(); } + + default String uiUrl() { + return String.format("http://%s:%d/solr", host(), port()); + } } diff --git a/test-infra/camel-test-infra-solr/src/main/java/org/apache/camel/test/infra/solr/services/SolrLocalContainerInfraService.java b/test-infra/camel-test-infra-solr/src/main/java/org/apache/camel/test/infra/solr/services/SolrLocalContainerInfraService.java index 1abd2e3141ae7..70105cc8cee87 100644 --- a/test-infra/camel-test-infra-solr/src/main/java/org/apache/camel/test/infra/solr/services/SolrLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-solr/src/main/java/org/apache/camel/test/infra/solr/services/SolrLocalContainerInfraService.java @@ -25,7 +25,8 @@ @InfraService(service = SolrInfraService.class, description = "Apache Solr is an open source search platform", - serviceAlias = { "solr" }) + serviceAlias = { "solr" }, + uiSupported = true) public class SolrLocalContainerInfraService implements SolrInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(SolrLocalContainerInfraService.class); diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/CamelTestInfraGenerateMetadataMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/CamelTestInfraGenerateMetadataMojo.java index 5332a0dcd18ba..27181414c3776 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/CamelTestInfraGenerateMetadataMojo.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/CamelTestInfraGenerateMetadataMojo.java @@ -119,6 +119,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { infrastructureServiceModel.setDescription(av.asString()); } else if (av.name().equals("serviceVersion")) { annotationServiceVersion = av.asString(); + } else if (av.name().equals("uiSupported")) { + infrastructureServiceModel.setUiSupported(av.asBoolean()); } } @@ -378,6 +380,7 @@ private class InfrastructureServiceModel { private String artifactId; private String version; private String serviceVersion; + private boolean uiSupported; public String getService() { return service; @@ -450,5 +453,13 @@ public String getServiceVersion() { public void setServiceVersion(String serviceVersion) { this.serviceVersion = serviceVersion; } + + public boolean isUiSupported() { + return uiSupported; + } + + public void setUiSupported(boolean uiSupported) { + this.uiSupported = uiSupported; + } } } diff --git a/tooling/spi-annotations/src/main/java/org/apache/camel/spi/annotations/InfraService.java b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/annotations/InfraService.java index fb6051e05581a..e4ef026135a79 100644 --- a/tooling/spi-annotations/src/main/java/org/apache/camel/spi/annotations/InfraService.java +++ b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/annotations/InfraService.java @@ -81,4 +81,13 @@ * @return */ String serviceVersion() default ""; + + /** + * Whether this service supports a web UI (built-in or via companion container). + * + * When true, the service interface should provide a {@code uiUrl()} method that returns the UI URL when available. + * + * @return true if the service has UI support + */ + boolean uiSupported() default false; } From f49d4a8ef05dcb8614d9ac93c4ab127013fc3922 Mon Sep 17 00:00:00 2001 From: Croway Date: Thu, 16 Jul 2026 11:53:06 +0200 Subject: [PATCH 2/2] CAMEL-24087: Address review feedback - fix blockers and design issues --- .../camel/catalog/test-infra/metadata.json | 6 ++-- .../jbang-commands/camel-jbang-infra-run.adoc | 1 + .../camel-jbang-commands-metadata.json | 2 +- .../jbang/core/commands/infra/InfraRun.java | 11 +++++++ .../resources/META-INF/metadata.json | 6 ++-- .../services/ContainerEnvironmentUtil.java | 12 ++++++-- .../kafka/services/ConfluentInfraService.java | 2 +- .../ContainerLocalKafkaInfraService.java | 27 ++++++++++++----- .../kafka/services/RedpandaInfraService.java | 2 +- .../kafka/services/StrimziInfraService.java | 2 +- .../MongoDBLocalContainerInfraService.java | 2 +- .../OpenSearchLocalContainerInfraService.java | 2 +- .../opensearch/services/container.properties | 2 +- .../PostgresLocalContainerInfraService.java | 29 +++++++++++++++---- .../RedisLocalContainerInfraService.java | 2 +- .../infra/redis/services/container.properties | 2 +- 16 files changed, 79 insertions(+), 31 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json index 71c1c305f7870..a751e0b1d99ee 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json @@ -118,7 +118,7 @@ "artifactId" : "camel-test-infra-kafka", "version" : "4.22.0-SNAPSHOT", "serviceVersion" : "0.51.0-kafka-4.2.0", - "uiSupported" : true + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.kafka.services.KafkaInfraService", "description" : "Apache Kafka, Distributed event streaming platform", @@ -129,7 +129,7 @@ "artifactId" : "camel-test-infra-kafka", "version" : "4.22.0-SNAPSHOT", "serviceVersion" : "8.3.0", - "uiSupported" : true + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.nats.services.NatsInfraService", "description" : "NATS is a high-performance messaging system for cloud native applications", @@ -173,7 +173,7 @@ "artifactId" : "camel-test-infra-kafka", "version" : "4.22.0-SNAPSHOT", "serviceVersion" : "v26.1.12", - "uiSupported" : true + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.hashicorp.vault.services.HashicorpVaultInfraService", "description" : "HashiCorp Vault is a tool for securely accessing secrets", diff --git a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-infra-run.adoc b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-infra-run.adoc index bc7b7bcf2c937..a0d1592f27646 100644 --- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-infra-run.adoc +++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-infra-run.adoc @@ -22,6 +22,7 @@ camel infra run [options] | `--background` | Run in the background | false | boolean | `--json` | Output in JSON Format | | boolean | `--log` | Log container output to console | | boolean +| `--no-ui` | Do not start companion UI containers | false | boolean | `--port` | Override the default port for the service | | Integer | `-h,--help` | Display the help and sub-commands | | boolean |=== diff --git a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json index d207910f993c0..b19e55604a5cc 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json +++ b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json @@ -18,7 +18,7 @@ { "name": "get", "fullName": "get", "description": "Get status of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.CamelStatus", "options": [ { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "activity", "fullName": "get activity", "description": "Get recent completed exchange activity", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListActivity", "options": [ { "names": "--filter", "description": "Filter activity by route ID", "javaType": "java.lang.String", "type": "string" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--limit", "description": "Filter activity by limiting to the given number of rows", "javaType": "int", "type": "integer" }, { "names": "--short-uri", "description": "List endpoint URI without query parameters (short)", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name, age, elapsed, or since", "defaultValue": "since", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "--wide-uri", "description": "List endpoint URI in full details", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "bean", "fullName": "get bean", "description": "List beans in a running Camel integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.action.CamelBeanDump", "options": [ { "names": "--dsl", "description": "Include only beans from YAML or XML DSL", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--filter", "description": "Filter beans names (use all to include all beans)", "defaultValue": "all", "javaType": "java.lang.String", "type": "string" }, { "names": "--internal", "description": "Include internal Camel beans", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--nulls", "description": "Include null values", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--properties", "description": "Show bean properties", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--scope", "description": "Filter beans by scope: all, user (excludes Camel\/Spring\/Quarkus\/JDK), camel, spring, quarkus", "defaultValue": "all", "javaType": "java.lang.String", "type": "string" }, { "names": "--sort", "description": "Sort by name or type", "defaultValue": "name", "javaType": "java.lang.String", "type": "string" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "blocked", "fullName": "get blocked", "description": "Get blocked messages of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListBlocked", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "circuit-breaker", "fullName": "get circuit-breaker", "description": "Get status of Circuit Breaker EIPs", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListCircuitBreaker", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "consumer", "fullName": "get consumer", "description": "Get status of Camel consumers", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListConsumer", "options": [ { "names": "--filter", "description": "Filter consumers by URI", "javaType": "java.lang.String", "type": "string" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--limit", "description": "Filter consumers by limiting to the given number of rows", "javaType": "int", "type": "integer" }, { "names": "--scheduled", "description": "Filter consumer to only show scheduled based consumers", "javaType": "boolean", "type": "boolean" }, { "names": "--short-uri", "description": "List endpoint URI without query parameters (short)", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "--wide-uri", "description": "List endpoint URI in full details", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "context", "fullName": "get context", "description": "Get status of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.CamelContextStatus", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--remote", "description": "Break down counters into remote\/total pairs", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "count", "fullName": "get count", "description": "Get total and failed exchanges", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.CamelCount", "options": [ { "names": "--fail", "description": "Get the failed exchanges from a running integration", "javaType": "boolean", "type": "boolean" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--total", "description": "Get the total exchanges from a running integration", "javaType": "boolean", "type": "boolean" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "datasource", "fullName": "get datasource", "description": "Get status of DataSource connection pools", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListDataSource", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "endpoint", "fullName": "get endpoint", "description": "Get usage of Camel endpoints", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListEndpoint", "options": [ { "names": "--filter", "description": "Filter endpoints by URI", "javaType": "java.lang.String", "type": "string" }, { "names": "--filter-direction", "description": "Filter by direction (in or out)", "javaType": "java.lang.String", "type": "string" }, { "names": "--filter-total", "description": "Filter endpoints that must be higher than the given usage", "javaType": "long", "type": "integer" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--limit", "description": "Filter endpoints by limiting to the given number of rows", "javaType": "int", "type": "integer" }, { "names": "--short-uri", "description": "List endpoint URI without query parameters (short)", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name, age, total, or size", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--verbose", "description": "Show additional size statistics (min\/max body and headers)", "javaType": "boolean", "type": "boolean" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "--wide-uri", "description": "List endpoint URI in full details", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "error", "fullName": "get error", "description": "Get captured routing errors of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListError", "options": [ { "names": "--ago", "description": "Filter by time window, e.g. 60s, 5m, 1h", "javaType": "java.lang.String", "type": "string" }, { "names": "--detail", "description": "Show full details of each error entry", "javaType": "boolean", "type": "boolean" }, { "names": "--diagram", "description": "Display a route diagram with the error path highlighted", "javaType": "boolean", "type": "boolean" }, { "names": "--exception", "description": "Filter by exception type (substring match)", "javaType": "java.lang.String", "type": "string" }, { "names": "--handled", "description": "Filter by handled status (true or false)", "javaType": "java.lang.String", "type": "string" }, { "names": "--id", "description": "Filter by exchange ID", "javaType": "java.lang.String", "type": "string" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--last", "description": "Show only the last (newest) error with full details", "javaType": "boolean", "type": "boolean" }, { "names": "--limit", "description": "Maximum number of entries to display", "javaType": "int", "type": "integer" }, { "names": "--logging-color", "description": "Use colored logging", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--route", "description": "Filter by route ID", "javaType": "java.lang.String", "type": "string" }, { "names": "--show", "description": "Comma-separated detail sections to show: body, headers, properties, variables, history, stackTrace, or 'all' for all sections", "javaType": "java.lang.String", "type": "string" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--theme", "description": "Diagram color theme (ascii, unicode, dark, light, transparent, or custom)", "defaultValue": "unicode", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "event", "fullName": "get event", "description": "Get latest events of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListEvent", "options": [ { "names": "--filter", "description": "Filter event by event type: context, route, or exchange", "javaType": "java.lang.String", "type": "string" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "groovy", "fullName": "get groovy", "description": "Groovy Sources used of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListGroovy", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid or name", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "group", "fullName": "get group", "description": "Get status of Camel route groups", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.CamelRouteGroupStatus", "options": [ { "names": "--filter", "description": "Filter groups by name", "javaType": "java.lang.String", "type": "string" }, { "names": "--filter-mean", "description": "Filter groups that must be slower than the given time (ms)", "javaType": "long", "type": "integer" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--limit", "description": "Filter groups by limiting to the given number of rows", "javaType": "int", "type": "integer" }, { "names": "--running", "description": "Only include running groups", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name, age or group", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "health", "fullName": "get health", "description": "Get health check status of running Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListHealth", "options": [ { "names": "--depth", "description": "Max depth of stack-trace", "defaultValue": "1", "javaType": "int", "type": "integer" }, { "names": "--down", "description": "Show only checks which are DOWN", "javaType": "boolean", "type": "boolean" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--level", "description": "Level of details: full, or default", "defaultValue": "default", "javaType": "java.lang.String", "type": "string" }, { "names": "--live", "description": "Show only liveness checks", "javaType": "boolean", "type": "boolean" }, { "names": "--ready", "description": "Show only readiness checks", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--trace", "description": "Include stack-traces in error messages", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "history", "fullName": "get history", "description": "History of latest completed exchange", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.action.CamelHistoryAction", "options": [ { "names": "--ago", "description": "Use ago instead of yyyy-MM-dd HH:mm:ss in timestamp.", "javaType": "boolean", "type": "boolean" }, { "names": "--depth", "description": "Depth of tracing. 0=Created Completed. 1=All events on 1st route, 2=All events on 1st 2nd depth, and so on. 9 = all events on every depth.", "defaultValue": "9", "javaType": "int", "type": "integer" }, { "names": "--diagram", "description": "Display a route diagram with the message path highlighted", "javaType": "boolean", "type": "boolean" }, { "names": "--it", "description": "Interactive mode for enhanced history information", "javaType": "boolean", "type": "boolean" }, { "names": "--limit-split", "description": "Limit Split to a maximum number of entries to be displayed", "javaType": "int", "type": "integer" }, { "names": "--logging-color", "description": "Use colored logging", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--mask", "description": "Whether to mask endpoint URIs to avoid printing sensitive information such as password or access keys", "javaType": "boolean", "type": "boolean" }, { "names": "--pretty", "description": "Pretty print message body when using JSon or XML format", "javaType": "boolean", "type": "boolean" }, { "names": "--show-body", "description": "Show message body in debug messages", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--show-exception", "description": "Show exception and stacktrace for failed messages", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--show-exchange-properties", "description": "Show exchange properties in debug messages", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--show-exchange-variables", "description": "Show exchange variables in debug messages", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--show-headers", "description": "Show message headers in debug messages", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--source", "description": "Prefer to display source filename\/code instead of IDs", "javaType": "boolean", "type": "boolean" }, { "names": "--theme", "description": "Diagram color theme (ascii, unicode, dark, light, transparent, or custom)", "defaultValue": "unicode", "javaType": "java.lang.String", "type": "string" }, { "names": "--timestamp", "description": "Print timestamp.", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "inflight", "fullName": "get inflight", "description": "Get inflight messages of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListInflight", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "internal-task", "fullName": "get internal-task", "description": "List internal tasks of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListInternalTask", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "kafka", "fullName": "get kafka", "description": "List Kafka consumers of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListKafka", "options": [ { "names": "--committed", "description": "Show committed offset (slower due to sync call to Kafka brokers)", "javaType": "boolean", "type": "boolean" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--short-uri", "description": "List endpoint URI without query parameters (short)", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "--wide-uri", "description": "List endpoint URI in full details", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "metric", "fullName": "get metric", "description": "Get metrics (micrometer) of running Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListMetric", "options": [ { "names": "--all", "description": "Whether to show all metrics (also unused with counter being 0)", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--custom", "description": "Only show custom metrics", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--filter", "description": "Filter metric by type, name or tags", "javaType": "java.lang.String", "type": "string" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--tags", "description": "Show metric tags", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "platform-http", "fullName": "get platform-http", "description": "Get embedded HTTP services of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListPlatformHttp", "options": [ { "names": "--all", "description": "Include management endpoints", "javaType": "boolean", "type": "boolean" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "processor", "fullName": "get processor", "description": "Get status of Camel processors", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.CamelProcessorStatus", "options": [ { "names": "--description", "description": "Include description in the ID column (if available)", "javaType": "boolean", "type": "boolean" }, { "names": "--filter", "description": "Filter processors by id", "javaType": "java.lang.String", "type": "string" }, { "names": "--filter-mean", "description": "Filter processors that must be slower than the given time (ms)", "javaType": "long", "type": "integer" }, { "names": "--group", "description": "Filter processors by group", "javaType": "java.lang.String", "type": "string" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--limit", "description": "Filter routes by limiting to the given number of rows", "javaType": "int", "type": "integer" }, { "names": "--note", "description": "Include note in the ID column (if available)", "javaType": "boolean", "type": "boolean" }, { "names": "--remote", "description": "Break down counters into remote\/total pairs", "javaType": "boolean", "type": "boolean" }, { "names": "--running", "description": "Only include running processors", "javaType": "boolean", "type": "boolean" }, { "names": "--show-group", "description": "Include group column", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid or name", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--source", "description": "Prefer to display source filename\/code instead of IDs", "javaType": "boolean", "type": "boolean" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "producer", "fullName": "get producer", "description": "Get status of Camel producers", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListProducer", "options": [ { "names": "--filter", "description": "Filter producers by URI", "javaType": "java.lang.String", "type": "string" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--limit", "description": "Filter producers by limiting to the given number of rows", "javaType": "int", "type": "integer" }, { "names": "--short-uri", "description": "List endpoint URI without query parameters (short)", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "--wide-uri", "description": "List endpoint URI in full details", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "properties", "fullName": "get properties", "description": "List configuration properties", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListProperties", "options": [ { "names": "--internal", "description": "Whether to include internal configuration", "javaType": "boolean", "type": "boolean" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--mask", "description": "Whether to mask configuration values to avoid printing sensitive information such as password or access keys", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or key", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--startup", "description": "List only startup configuration", "javaType": "boolean", "type": "boolean" }, { "names": "--verbose", "description": "Whether to include more details", "javaType": "boolean", "type": "boolean" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "rest", "fullName": "get rest", "description": "Get REST services of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListRest", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--verbose", "description": "Show more details", "javaType": "boolean", "type": "boolean" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "route", "fullName": "get route", "description": "Get status of Camel routes", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.CamelRouteStatus", "options": [ { "names": "--description", "description": "Include description in the ID column (if available)", "javaType": "boolean", "type": "boolean" }, { "names": "--error", "description": "Shows detailed information for routes that has error status", "javaType": "boolean", "type": "boolean" }, { "names": "--filter", "description": "Filter routes by id, or url", "javaType": "java.lang.String", "type": "string" }, { "names": "--filter-mean", "description": "Filter routes that must be slower than the given time (ms)", "javaType": "long", "type": "integer" }, { "names": "--group", "description": "Filter routes by group", "javaType": "java.lang.String", "type": "string" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--limit", "description": "Filter routes by limiting to the given number of rows", "javaType": "int", "type": "integer" }, { "names": "--note", "description": "Include note in the ID column (if available)", "javaType": "boolean", "type": "boolean" }, { "names": "--running", "description": "Only include running routes", "javaType": "boolean", "type": "boolean" }, { "names": "--short-uri", "description": "List endpoint URI without query parameters (short)", "javaType": "boolean", "type": "boolean" }, { "names": "--show-group", "description": "Include group column", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--source", "description": "Prefer to display source filename\/code instead of IDs", "javaType": "boolean", "type": "boolean" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "--wide-uri", "description": "List endpoint URI in full details", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "route-controller", "fullName": "get route-controller", "description": "List status of route controller", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.action.RouteControllerAction", "options": [ { "names": "--depth", "description": "Max depth of stack-trace", "defaultValue": "1", "javaType": "int", "type": "integer" }, { "names": "--header", "description": "Include controller configuration details", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by id, or state", "defaultValue": "id", "javaType": "java.lang.String", "type": "string" }, { "names": "--trace", "description": "Include stack-traces in error messages", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "service", "fullName": "get service", "description": "Get services of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListService", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--metadata", "description": "Show service metadata (only available for some services)", "javaType": "boolean", "type": "boolean" }, { "names": "--short-uri", "description": "List endpoint URI without query parameters (short)", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "--wide-uri", "description": "List endpoint URI in full details", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "source", "fullName": "get source", "description": "Display Camel route source code", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.action.CamelSourceAction", "options": [ { "names": "--filter", "description": "Filter source by filename (multiple names can be separated by comma)", "javaType": "java.lang.String", "type": "string" }, { "names": "--sort", "description": "Sort source by name", "defaultValue": "name", "javaType": "java.lang.String", "type": "string" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "sql-trace", "fullName": "get sql-trace", "description": "Get SQL query trace data", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListSqlTrace", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or age", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "startup-recorder", "fullName": "get startup-recorder", "description": "Display startup recording", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.action.CamelStartupRecorderAction", "options": [ { "names": "--sort", "description": "Sort by duration, or type", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "transformer", "fullName": "get transformer", "description": "Get list of data type transformers", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListTransformer", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name, age or total", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "variable", "fullName": "get variable", "description": "List variables of Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListVariable", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name or key", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "vault", "fullName": "get vault", "description": "List secrets from security vaults", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.ListVault", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--sort", "description": "Sort by pid, name", "defaultValue": "pid", "javaType": "java.lang.String", "type": "string" }, { "names": "--watch", "description": "Execute periodically and showing output fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] } ] }, { "name": "harden", "fullName": "harden", "description": "Suggest security hardening for Camel routes using AI\/LLM", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Harden", "options": [ { "names": "--api-key", "description": "API key for authentication. Also reads OPENAI_API_KEY or LLM_API_KEY env vars", "javaType": "java.lang.String", "type": "string" }, { "names": "--api-type", "description": "API type: 'ollama' or 'openai' (OpenAI-compatible)", "defaultValue": "ollama", "javaType": "org.apache.camel.dsl.jbang.core.commands.ApiType", "type": "object" }, { "names": "--catalog-context", "description": "Include Camel Catalog descriptions in the prompt", "javaType": "boolean", "type": "boolean" }, { "names": "--format", "description": "Output format (text, markdown)", "defaultValue": "text", "javaType": "java.lang.String", "type": "string" }, { "names": "--model", "description": "Model to use", "defaultValue": "DEFAULT_MODEL", "javaType": "java.lang.String", "type": "string" }, { "names": "--show-prompt", "description": "Show the prompt sent to the LLM", "javaType": "boolean", "type": "boolean" }, { "names": "--stream", "description": "Stream the response as it's generated (shows progress)", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--system-prompt", "description": "Custom system prompt", "javaType": "java.lang.String", "type": "string" }, { "names": "--temperature", "description": "Temperature for response generation (0.0-2.0)", "defaultValue": "0.7", "javaType": "double", "type": "number" }, { "names": "--timeout", "description": "Timeout in seconds for LLM response", "defaultValue": "120", "javaType": "int", "type": "integer" }, { "names": "--url", "description": "LLM API endpoint URL. Auto-detected from 'camel infra' for Ollama if not specified.", "javaType": "java.lang.String", "type": "string" }, { "names": "--verbose,-v", "description": "Include detailed security recommendations with code examples", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "hawtio", "fullName": "hawtio", "description": "Launch Hawtio web console", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.Hawtio", "options": [ { "names": "--host", "description": "Hostname to bind the Hawtio web console to", "defaultValue": "127.0.0.1", "javaType": "java.lang.String", "type": "string" }, { "names": "--openUrl", "description": "To automatic open Hawtio web console in the web browser", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--port", "description": "Port number to use for Hawtio web console (port 8888 by default)", "defaultValue": "8888", "javaType": "int", "type": "integer" }, { "names": "--version", "description": "Version of the Hawtio web console", "defaultValue": "HawtioVersion.HAWTIO_VERSION", "javaType": "java.lang.String", "type": "string" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, - { "name": "infra", "fullName": "infra", "description": "List and Run external services for testing and prototyping", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraCommand", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "get", "fullName": "infra get", "description": "Displays running service(s) information", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraGet", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "list", "fullName": "infra list", "description": "Displays available external services", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraList", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "log", "fullName": "infra log", "description": "Displays external service logs", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraLog", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--lines", "description": "The number of lines from the end of the log to use as starting offset", "defaultValue": "50", "javaType": "int", "type": "integer" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "ps", "fullName": "infra ps", "description": "Displays running services", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraPs", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "restart", "fullName": "infra restart", "description": "Restarts a running external service", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraRestart", "options": [ { "names": "--background", "description": "Run in the background", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--kill", "description": "To force killing the process (SIGKILL) when stopping", "javaType": "boolean", "type": "boolean" }, { "names": "--log", "description": "Log container output to console", "javaType": "boolean", "type": "boolean" }, { "names": "--port", "description": "Override the default port for the service", "javaType": "java.lang.Integer", "type": "integer" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "run", "fullName": "infra run", "description": "Run an external service", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraRun", "options": [ { "names": "--background", "description": "Run in the background", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--log", "description": "Log container output to console", "javaType": "boolean", "type": "boolean" }, { "names": "--port", "description": "Override the default port for the service", "javaType": "java.lang.Integer", "type": "integer" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "stop", "fullName": "infra stop", "description": "Shuts down running external services", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraStop", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--kill", "description": "To force killing the process (SIGKILL)", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] } ] }, + { "name": "infra", "fullName": "infra", "description": "List and Run external services for testing and prototyping", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraCommand", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "get", "fullName": "infra get", "description": "Displays running service(s) information", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraGet", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "list", "fullName": "infra list", "description": "Displays available external services", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraList", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "log", "fullName": "infra log", "description": "Displays external service logs", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraLog", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--lines", "description": "The number of lines from the end of the log to use as starting offset", "defaultValue": "50", "javaType": "int", "type": "integer" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "ps", "fullName": "infra ps", "description": "Displays running services", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraPs", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "restart", "fullName": "infra restart", "description": "Restarts a running external service", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraRestart", "options": [ { "names": "--background", "description": "Run in the background", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--kill", "description": "To force killing the process (SIGKILL) when stopping", "javaType": "boolean", "type": "boolean" }, { "names": "--log", "description": "Log container output to console", "javaType": "boolean", "type": "boolean" }, { "names": "--port", "description": "Override the default port for the service", "javaType": "java.lang.Integer", "type": "integer" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "run", "fullName": "infra run", "description": "Run an external service", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraRun", "options": [ { "names": "--background", "description": "Run in the background", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--log", "description": "Log container output to console", "javaType": "boolean", "type": "boolean" }, { "names": "--no-ui", "description": "Do not start companion UI containers", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--port", "description": "Override the default port for the service", "javaType": "java.lang.Integer", "type": "integer" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "stop", "fullName": "infra stop", "description": "Shuts down running external services", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.infra.InfraStop", "options": [ { "names": "--json", "description": "Output in JSON Format", "javaType": "boolean", "type": "boolean" }, { "names": "--kill", "description": "To force killing the process (SIGKILL)", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] } ] }, { "name": "init", "fullName": "init", "description": "Creates a new Camel integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Init", "options": [ { "names": "--clean-dir,--clean-directory", "description": "Whether to clean directory first (deletes all files in directory)", "javaType": "boolean", "type": "boolean" }, { "names": "--dir,--directory", "description": "Directory relative path where the new Camel integration will be saved", "defaultValue": ".", "javaType": "java.lang.String", "type": "string" }, { "names": "--from-kamelet", "description": "To be used when extending an existing Kamelet", "javaType": "java.lang.String", "type": "string" }, { "names": "--kamelets-version", "description": "Apache Camel Kamelets version (auto-detected from classpath if not set)", "javaType": "java.lang.String", "type": "string" }, { "names": "--list", "description": "List available templates", "javaType": "boolean", "type": "boolean" }, { "names": "--pipe", "description": "When creating a yaml file should it be created as a Pipe CR", "javaType": "boolean", "type": "boolean" }, { "names": "--repo,--repos", "description": "Additional maven repositories (Use commas to separate multiple repositories)", "javaType": "java.lang.String", "type": "string" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "jolokia", "fullName": "jolokia", "description": "Attach Jolokia JVM Agent to a running Camel integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.Jolokia", "options": [ { "names": "--port", "description": "To use a specific port number when attaching Jolokia JVM Agent (default a free port is found in range 8778-9999)", "javaType": "int", "type": "integer" }, { "names": "--stop", "description": "Stops the Jolokia JVM Agent in the running Camel integration", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, { "name": "log", "fullName": "log", "description": "Tail logs from running Camel integrations", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.action.CamelLogAction", "options": [ { "names": "--find", "description": "Find and highlight matching text (ignore case).", "javaType": "java.lang.String", "type": "string" }, { "names": "--follow", "description": "Keep following and outputting new log lines (press enter to exit).", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--grep", "description": "Filter logs to only output lines matching text (ignore case).", "javaType": "java.lang.String", "type": "string" }, { "names": "--logging-color", "description": "Use colored logging", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "--prefix", "description": "Print prefix with running Camel integration name. auto=only prefix when running multiple integrations. true=always prefix. false=prefix off.", "defaultValue": "auto", "javaType": "java.lang.String", "type": "string" }, { "names": "--since", "description": "Return logs newer than a relative duration like 5s, 2m, or 1h. The value is in seconds if no unit specified.", "javaType": "java.lang.String", "type": "string" }, { "names": "--startup", "description": "Only shows logs from the starting phase to make it quick to look at how Camel was started.", "defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": "--tail", "description": "The number of lines from the end of the logs to show. Use -1 to read from the beginning. Use 0 to read only new lines. Defaults to showing all logs from beginning.", "defaultValue": "-1", "javaType": "int", "type": "integer" }, { "names": "--timestamp", "description": "Print timestamp.", "defaultValue": "true", "javaType": "boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display the help and sub-commands", "javaType": "boolean", "type": "boolean" } ] }, diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java index 6016cc331f302..244707de8287e 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java @@ -65,6 +65,10 @@ public class InfraRun extends InfraBaseCommand { description = "Override the default port for the service") Integer port; + @CommandLine.Option(names = { "--no-ui" }, defaultValue = "false", + description = "Do not start companion UI containers") + boolean noUi; + public InfraRun(CamelJBangMain main) { super(main); } @@ -137,6 +141,9 @@ protected int runBackground(String testService) throws Exception { if (logToStdout) { cmds.add("--log"); } + if (noUi) { + cmds.add("--no-ui"); + } } cmds.remove("--background=true"); @@ -169,6 +176,9 @@ protected Integer doRun(String testService, String testServiceImplementation, Te if (port != null) { System.setProperty("camel.infra.port", String.valueOf(port)); } + if (noUi) { + System.setProperty("camel.infra.ui", "false"); + } Object actualService = cl.loadClass(serviceImpl).newInstance(); // Make sure the actualService can be run with initialize method @@ -315,6 +325,7 @@ private static void shutdownInfra(AtomicBoolean closed, Path logFile, Path jsonF } System.clearProperty("camel.infra.port"); System.clearProperty("camel.infra.fixedPort"); + System.clearProperty("camel.infra.ui"); } } diff --git a/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json b/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json index 71c1c305f7870..a751e0b1d99ee 100644 --- a/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json +++ b/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json @@ -118,7 +118,7 @@ "artifactId" : "camel-test-infra-kafka", "version" : "4.22.0-SNAPSHOT", "serviceVersion" : "0.51.0-kafka-4.2.0", - "uiSupported" : true + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.kafka.services.KafkaInfraService", "description" : "Apache Kafka, Distributed event streaming platform", @@ -129,7 +129,7 @@ "artifactId" : "camel-test-infra-kafka", "version" : "4.22.0-SNAPSHOT", "serviceVersion" : "8.3.0", - "uiSupported" : true + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.nats.services.NatsInfraService", "description" : "NATS is a high-performance messaging system for cloud native applications", @@ -173,7 +173,7 @@ "artifactId" : "camel-test-infra-kafka", "version" : "4.22.0-SNAPSHOT", "serviceVersion" : "v26.1.12", - "uiSupported" : true + "uiSupported" : false }, { "service" : "org.apache.camel.test.infra.hashicorp.vault.services.HashicorpVaultInfraService", "description" : "HashiCorp Vault is a tool for securely accessing secrets", diff --git a/test-infra/camel-test-infra-common/src/main/java/org/apache/camel/test/infra/common/services/ContainerEnvironmentUtil.java b/test-infra/camel-test-infra-common/src/main/java/org/apache/camel/test/infra/common/services/ContainerEnvironmentUtil.java index 7da3d1814fb8c..4f23e9235a736 100644 --- a/test-infra/camel-test-infra-common/src/main/java/org/apache/camel/test/infra/common/services/ContainerEnvironmentUtil.java +++ b/test-infra/camel-test-infra-common/src/main/java/org/apache/camel/test/infra/common/services/ContainerEnvironmentUtil.java @@ -35,6 +35,7 @@ public final class ContainerEnvironmentUtil { public static final String STARTUP_ATTEMPTS_PROPERTY = ".startup.attempts"; public static final String INFRA_PORT_PROPERTY = "camel.infra.port"; public static final String INFRA_FIXED_PORT_PROPERTY = "camel.infra.fixedPort"; + public static final String INFRA_UI_PROPERTY = "camel.infra.ui"; private static final Logger LOG = LoggerFactory.getLogger(ContainerEnvironmentUtil.class); private static final AtomicInteger INSTANCE_COUNTER = new AtomicInteger(0); @@ -110,13 +111,18 @@ public static boolean isFixedPort(@SuppressWarnings("rawtypes") Class cls) { } /** - * Determines if companion UI containers should be started alongside infrastructure services. Returns true when in - * fixed port mode (Camel CLI). This ensures UI containers are never started during tests (which don't set - * fixedPort). + * Determines if companion UI containers should be started alongside infrastructure services. Driven by the + * {@link #INFRA_UI_PROPERTY} system property: {@code "true"} to start UI containers, {@code "false"} to suppress + * them. When the property is not set, defaults to {@code true} in fixed-port mode (Camel CLI) and {@code false} + * otherwise (tests). * * @return true if companion UI containers should be started */ public static boolean isWithUi() { + String uiProp = System.getProperty(INFRA_UI_PROPERTY); + if (uiProp != null) { + return Boolean.parseBoolean(uiProp); + } return Boolean.parseBoolean(System.getProperty(INFRA_FIXED_PORT_PROPERTY, "false")); } diff --git a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ConfluentInfraService.java b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ConfluentInfraService.java index 2033f566b4aab..93c95805f865e 100644 --- a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ConfluentInfraService.java +++ b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ConfluentInfraService.java @@ -28,7 +28,7 @@ @InfraService(service = KafkaInfraService.class, description = "Apache Kafka, Distributed event streaming platform", - serviceAlias = "kafka", serviceImplementationAlias = "confluent", uiSupported = true) + serviceAlias = "kafka", serviceImplementationAlias = "confluent") public class ConfluentInfraService implements KafkaInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(ConfluentInfraService.class); diff --git a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ContainerLocalKafkaInfraService.java b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ContainerLocalKafkaInfraService.java index be80531e52b56..bc1c190b0787f 100644 --- a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ContainerLocalKafkaInfraService.java +++ b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/ContainerLocalKafkaInfraService.java @@ -24,8 +24,8 @@ import org.apache.camel.test.infra.kafka.common.KafkaProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.testcontainers.Testcontainers; import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.Network; import org.testcontainers.kafka.KafkaContainer; import org.testcontainers.utility.DockerImageName; @@ -39,10 +39,12 @@ public class ContainerLocalKafkaInfraService implements KafkaInfraService, Conta private static final String KAFKA_UI_CONTAINER_IMAGE = "kafka-ui.container.image"; private static final int KAFKA_UI_PORT = 9080; + private static final String KAFKA_NETWORK_ALIAS = "kafka-broker"; private static final Logger LOG = LoggerFactory.getLogger(ContainerLocalKafkaInfraService.class); protected KafkaContainer kafka; private GenericContainer uiContainer; + private Network uiNetwork; public ContainerLocalKafkaInfraService() { kafka = initContainer(); @@ -61,6 +63,8 @@ public ContainerLocalKafkaInfraService(KafkaContainer kafka) { } protected KafkaContainer initContainer() { + boolean fixedPort = ContainerEnvironmentUtil.isFixedPort(this.getClass()); + class TestInfraKafkaContainer extends KafkaContainer { public TestInfraKafkaContainer(boolean fixedPort) { super(DockerImageName.parse(System.getProperty(KafkaProperties.KAFKA_CONTAINER, KAFKA_IMAGE_NAME)) @@ -70,7 +74,16 @@ public TestInfraKafkaContainer(boolean fixedPort) { } } - return new TestInfraKafkaContainer(ContainerEnvironmentUtil.isFixedPort(this.getClass())); + KafkaContainer container = new TestInfraKafkaContainer(fixedPort); + + if (ContainerEnvironmentUtil.isWithUi()) { + uiNetwork = Network.newNetwork(); + container.withNetwork(uiNetwork) + .withNetworkAliases(KAFKA_NETWORK_ALIAS) + .withListener(KAFKA_NETWORK_ALIAS + ":19092"); + } + + return container; } public String getBootstrapServers() { @@ -98,7 +111,7 @@ public void initialize() { try { startUiContainer(); } catch (Exception e) { - LOG.warn("Failed to start Kafka UI container: {}", e.getMessage()); + LOG.warn("Failed to start Kafka UI container: {}", e.getMessage(), e); } } } @@ -106,15 +119,13 @@ public void initialize() { private void startUiContainer() { String uiImage = LocalPropertyResolver.getProperty( ContainerLocalKafkaInfraService.class, KAFKA_UI_CONTAINER_IMAGE); - int kafkaPort = ContainerEnvironmentUtil.getConfiguredPort(9092); - Testcontainers.exposeHostPorts(kafkaPort); uiContainer = new GenericContainer<>(uiImage) + .withNetwork(uiNetwork) .withEnv("DYNAMIC_CONFIG_ENABLED", "true") .withEnv("KAFKA_CLUSTERS_0_NAME", "camel-infra") - .withEnv("KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS", "host.testcontainers.internal:" + kafkaPort) - .withEnv("SERVER_PORT", String.valueOf(KAFKA_UI_PORT)) - .withAccessToHost(true); + .withEnv("KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS", KAFKA_NETWORK_ALIAS + ":19092") + .withEnv("SERVER_PORT", String.valueOf(KAFKA_UI_PORT)); ContainerEnvironmentUtil.configurePort(uiContainer, true, KAFKA_UI_PORT); uiContainer.start(); diff --git a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/RedpandaInfraService.java b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/RedpandaInfraService.java index b35bb07752355..301791202efcf 100644 --- a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/RedpandaInfraService.java +++ b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/RedpandaInfraService.java @@ -28,7 +28,7 @@ @InfraService(service = KafkaInfraService.class, description = "Apache Kafka, Distributed event streaming platform", - serviceAlias = "kafka", serviceImplementationAlias = "redpanda", uiSupported = true) + serviceAlias = "kafka", serviceImplementationAlias = "redpanda") public class RedpandaInfraService implements KafkaInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(RedpandaInfraService.class); diff --git a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/StrimziInfraService.java b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/StrimziInfraService.java index e7c5ab3aafe1e..f6cada56317fe 100644 --- a/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/StrimziInfraService.java +++ b/test-infra/camel-test-infra-kafka/src/main/java/org/apache/camel/test/infra/kafka/services/StrimziInfraService.java @@ -28,7 +28,7 @@ @InfraService(service = KafkaInfraService.class, description = "Apache Kafka, Distributed event streaming platform", - serviceAlias = "kafka", serviceImplementationAlias = "strimzi", uiSupported = true) + serviceAlias = "kafka", serviceImplementationAlias = "strimzi") public class StrimziInfraService implements KafkaInfraService, ContainerService { private static final Logger LOG = LoggerFactory.getLogger(StrimziInfraService.class); diff --git a/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBLocalContainerInfraService.java b/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBLocalContainerInfraService.java index 3e640ea871679..60ac12a916bfa 100644 --- a/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-mongodb/src/main/java/org/apache/camel/test/infra/mongodb/services/MongoDBLocalContainerInfraService.java @@ -110,7 +110,7 @@ public void initialize() { LOG.info("Mongo Express running at http://{}:{}", uiContainer.getHost(), uiContainer.getMappedPort(MONGO_EXPRESS_PORT)); } catch (Exception e) { - LOG.warn("Failed to start Mongo Express UI container: {}", e.getMessage()); + LOG.warn("Failed to start Mongo Express UI container: {}", e.getMessage(), e); } } } diff --git a/test-infra/camel-test-infra-opensearch/src/main/java/org/apache/camel/test/infra/opensearch/services/OpenSearchLocalContainerInfraService.java b/test-infra/camel-test-infra-opensearch/src/main/java/org/apache/camel/test/infra/opensearch/services/OpenSearchLocalContainerInfraService.java index aa4f68489b8c7..3d1bfac1e93bc 100644 --- a/test-infra/camel-test-infra-opensearch/src/main/java/org/apache/camel/test/infra/opensearch/services/OpenSearchLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-opensearch/src/main/java/org/apache/camel/test/infra/opensearch/services/OpenSearchLocalContainerInfraService.java @@ -128,7 +128,7 @@ public void initialize() { try { startUiContainer(); } catch (Exception e) { - LOG.warn("Failed to start OpenSearch Dashboards UI container: {}", e.getMessage()); + LOG.warn("Failed to start OpenSearch Dashboards UI container: {}", e.getMessage(), e); } } } diff --git a/test-infra/camel-test-infra-opensearch/src/main/resources/org/apache/camel/test/infra/opensearch/services/container.properties b/test-infra/camel-test-infra-opensearch/src/main/resources/org/apache/camel/test/infra/opensearch/services/container.properties index 39403ac6b92d9..9c5f81f29a88d 100644 --- a/test-infra/camel-test-infra-opensearch/src/main/resources/org/apache/camel/test/infra/opensearch/services/container.properties +++ b/test-infra/camel-test-infra-opensearch/src/main/resources/org/apache/camel/test/infra/opensearch/services/container.properties @@ -16,4 +16,4 @@ ## --------------------------------------------------------------------------- opensearch.container=mirror.gcr.io/opensearchproject/opensearch:3.7.0 opensearch.container.ppc64le=icr.io/ppc64le-oss/opensearch-ppc64le:3.3.0 -opensearch-dashboards.container.image=mirror.gcr.io/opensearchproject/opensearch-dashboards:2.21.0 +opensearch-dashboards.container.image=mirror.gcr.io/opensearchproject/opensearch-dashboards:3.7.0 diff --git a/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresLocalContainerInfraService.java b/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresLocalContainerInfraService.java index 87b40c04cd3f2..b5733d95a4986 100644 --- a/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-postgres/src/main/java/org/apache/camel/test/infra/postgres/services/PostgresLocalContainerInfraService.java @@ -28,6 +28,7 @@ import org.testcontainers.Testcontainers; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.images.builder.Transferable; import org.testcontainers.postgresql.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; @@ -42,6 +43,9 @@ public class PostgresLocalContainerInfraService implements PostgresInfraService, private static final String PGADMIN_CONTAINER_IMAGE = "pgadmin.container.image"; private static final int PGADMIN_PORT = 5050; + private static final String PGADMIN_EMAIL = "admin@camel.apache.org"; + // NOTE: default value used for local development only + private static final String PGADMIN_PASSWORD = "admin"; // NOSONAR private static final Logger LOG = LoggerFactory.getLogger(PostgresLocalContainerInfraService.class); private final PostgreSQLContainer container; @@ -108,7 +112,7 @@ public void initialize() { try { startUiContainer(); } catch (Exception e) { - LOG.warn("Failed to start pgAdmin UI container: {}", e.getMessage()); + LOG.warn("Failed to start pgAdmin UI container: {}", e.getMessage(), e); } } } @@ -119,15 +123,30 @@ private void startUiContainer() { int pgPort = ContainerEnvironmentUtil.getConfiguredPort(5432); Testcontainers.exposeHostPorts(pgPort); + String serversJson = String.format( + "{\"Servers\":{\"1\":{\"Name\":\"camel-infra\",\"Group\":\"Servers\"," + + "\"Host\":\"host.testcontainers.internal\",\"Port\":%d," + + "\"MaintenanceDB\":\"postgres\",\"Username\":\"%s\"," + + "\"PassFile\":\"/tmp/pgpassfile\",\"SSLMode\":\"prefer\"}}}", + pgPort, container.getUsername()); + String pgpassFile = String.format( + "host.testcontainers.internal:%d:postgres:%s:%s", + pgPort, container.getUsername(), container.getPassword()); + uiContainer = new GenericContainer<>(uiImage) - .withEnv("PGADMIN_DEFAULT_EMAIL", "admin@camel.apache.org") - .withEnv("PGADMIN_DEFAULT_PASSWORD", "admin") - .withEnv("PGADMIN_LISTEN_PORT", "5050") + .withEnv("PGADMIN_DEFAULT_EMAIL", PGADMIN_EMAIL) + .withEnv("PGADMIN_DEFAULT_PASSWORD", PGADMIN_PASSWORD) + .withEnv("PGADMIN_LISTEN_PORT", String.valueOf(PGADMIN_PORT)) + .withEnv("PGADMIN_CONFIG_SERVER_MODE", "False") + .withEnv("PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED", "False") + .withCopyToContainer(Transferable.of(serversJson), "/pgadmin4/servers.json") + .withCopyToContainer(Transferable.of(pgpassFile, 0600), "/tmp/pgpassfile") .withAccessToHost(true); ContainerEnvironmentUtil.configurePort(uiContainer, true, PGADMIN_PORT); uiContainer.start(); - LOG.info("pgAdmin running at http://{}:{}", uiContainer.getHost(), uiContainer.getMappedPort(PGADMIN_PORT)); + LOG.info("pgAdmin running at http://{}:{} (email: {}, password: {})", + uiContainer.getHost(), uiContainer.getMappedPort(PGADMIN_PORT), PGADMIN_EMAIL, PGADMIN_PASSWORD); } @Override diff --git a/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisLocalContainerInfraService.java b/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisLocalContainerInfraService.java index ae5297413cff9..5daa00327321f 100644 --- a/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisLocalContainerInfraService.java +++ b/test-infra/camel-test-infra-redis/src/main/java/org/apache/camel/test/infra/redis/services/RedisLocalContainerInfraService.java @@ -93,7 +93,7 @@ public void initialize() { LOG.info("Redis Commander running at http://{}:{}", uiContainer.getHost(), uiContainer.getMappedPort(REDIS_COMMANDER_PORT)); } catch (Exception e) { - LOG.warn("Failed to start Redis Commander UI container: {}", e.getMessage()); + LOG.warn("Failed to start Redis Commander UI container: {}", e.getMessage(), e); } } } diff --git a/test-infra/camel-test-infra-redis/src/main/resources/org/apache/camel/test/infra/redis/services/container.properties b/test-infra/camel-test-infra-redis/src/main/resources/org/apache/camel/test/infra/redis/services/container.properties index 72e89609a3b01..fe31a258527d3 100644 --- a/test-infra/camel-test-infra-redis/src/main/resources/org/apache/camel/test/infra/redis/services/container.properties +++ b/test-infra/camel-test-infra-redis/src/main/resources/org/apache/camel/test/infra/redis/services/container.properties @@ -18,4 +18,4 @@ redis.container=mirror.gcr.io/redis:7.4.9-alpine redis.container.version.include=alpine redis.container.version.exclude=rc,beta redis.container.version.freeze.major=true -redis-commander.container.image=mirror.gcr.io/rediscommander/redis-commander:latest +redis-commander.container.image=ghcr.io/joeferner/redis-commander:0.9.1