This is an automated email from the ASF dual-hosted git repository.

jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit 9922cef851b8979cd11601942c62b1c35c1caaac
Author: James Netherton <[email protected]>
AuthorDate: Mon Feb 24 11:10:47 2025 +0000

    Add tests for Kubernetes property resolution and context reloading
---
 .../kubernetes/deployment/KubernetesProcessor.java |  15 +++
 integration-tests/kubernetes/README.adoc           |   8 ++
 .../kubernetes/it/KubernetesConfigMapResource.java |  23 ++++-
 .../kubernetes/it/KubernetesResource.java          |  32 ++++++
 .../component/kubernetes/it/KubernetesRoutes.java  |  25 +++++
 .../kubernetes/it/KubernetesSecretResource.java    |  18 ++++
 .../src/main/resources/application.properties      |  18 ++++
 .../it/KubernetesConfigMapContextReloadIT.java     |  25 +++++
 .../it/KubernetesConfigMapContextReloadTest.java   | 102 ++++++++++++++++++
 .../kubernetes/it/KubernetesConfigMapTest.java     |  41 ++++++++
 .../component/kubernetes/it/KubernetesJobTest.java |  38 +++----
 .../it/KubernetesSecretContextReloadIT.java        |  25 +++++
 .../it/KubernetesSecretContextReloadTest.java      | 115 +++++++++++++++++++++
 .../kubernetes/it/KubernetesSecretTest.java        |  53 +++++++++-
 14 files changed, 517 insertions(+), 21 deletions(-)

diff --git 
a/extensions/kubernetes/deployment/src/main/java/org/apache/camel/quarkus/component/kubernetes/deployment/KubernetesProcessor.java
 
b/extensions/kubernetes/deployment/src/main/java/org/apache/camel/quarkus/component/kubernetes/deployment/KubernetesProcessor.java
index a122e0987f..3280f2f596 100644
--- 
a/extensions/kubernetes/deployment/src/main/java/org/apache/camel/quarkus/component/kubernetes/deployment/KubernetesProcessor.java
+++ 
b/extensions/kubernetes/deployment/src/main/java/org/apache/camel/quarkus/component/kubernetes/deployment/KubernetesProcessor.java
@@ -18,12 +18,16 @@ package 
org.apache.camel.quarkus.component.kubernetes.deployment;
 
 import io.fabric8.kubernetes.client.KubernetesClient;
 import io.quarkus.arc.deployment.BeanContainerBuildItem;
+import io.quarkus.deployment.annotations.BuildProducer;
 import io.quarkus.deployment.annotations.BuildStep;
 import io.quarkus.deployment.annotations.ExecutionTime;
 import io.quarkus.deployment.annotations.Record;
 import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
 import org.apache.camel.quarkus.component.kubernetes.CamelKubernetesRecorder;
 import org.apache.camel.quarkus.core.deployment.spi.CamelRuntimeBeanBuildItem;
+import org.apache.camel.vault.KubernetesConfigMapVaultConfiguration;
+import org.apache.camel.vault.KubernetesVaultConfiguration;
 
 class KubernetesProcessor {
     private static final String FEATURE = "camel-kubernetes";
@@ -43,4 +47,15 @@ class KubernetesProcessor {
                 KubernetesClient.class.getName(),
                 recorder.getKubernetesClient(beanContainer.getValue()));
     }
+
+    /**
+     * TODO: Remove this https://github.com/apache/camel-quarkus/issues/7045
+     */
+    @BuildStep
+    void registerForReflection(BuildProducer<ReflectiveClassBuildItem> 
reflectiveClass) {
+        reflectiveClass.produce(ReflectiveClassBuildItem
+                .builder(KubernetesVaultConfiguration.class, 
KubernetesConfigMapVaultConfiguration.class)
+                .methods()
+                .build());
+    }
 }
diff --git a/integration-tests/kubernetes/README.adoc 
b/integration-tests/kubernetes/README.adoc
index 3799e9017f..95dc8b9fe8 100644
--- a/integration-tests/kubernetes/README.adoc
+++ b/integration-tests/kubernetes/README.adoc
@@ -19,3 +19,11 @@ Then provide the URL of your cluster.
 export QUARKUS_KUBERNETES_CLIENT_API_SERVER_URL=https://127.0.0.1:50239
 ----
 
+It's also good practice to set the default namespace when working with a real 
cluster.
+
+[source,shell]
+----
+export QUARKUS_KUBERNETES_CLIENT_NAMESPACE=my-namespace
+----
+
+Note that if you don't provide a default namespace then `default` is assumed 
to be the name of the default namespace.
diff --git 
a/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesConfigMapResource.java
 
b/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesConfigMapResource.java
index d93027bbc1..3697f12b90 100644
--- 
a/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesConfigMapResource.java
+++ 
b/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesConfigMapResource.java
@@ -20,6 +20,7 @@ import java.net.URI;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import io.fabric8.kubernetes.api.model.ConfigMap;
 import jakarta.enterprise.context.ApplicationScoped;
@@ -42,6 +43,7 @@ import 
org.apache.camel.component.kubernetes.KubernetesOperations;
 @Path("/kubernetes/configmap")
 @ApplicationScoped
 public class KubernetesConfigMapResource {
+    static final AtomicBoolean CONTEXT_RELOADED = new AtomicBoolean(false);
 
     @Inject
     ProducerTemplate producerTemplate;
@@ -135,7 +137,10 @@ public class KubernetesConfigMapResource {
         headers.put(KubernetesConstants.KUBERNETES_NAMESPACE_NAME, namespace);
         headers.put(KubernetesConstants.KUBERNETES_OPERATION, 
KubernetesOperations.LIST_CONFIGMAPS);
         List<ConfigMap> configMapList = 
producerTemplate.requestBodyAndHeaders("direct:start", null, headers, 
List.class);
-        return Response.ok().entity(configMapList).build();
+        return Response.ok()
+                .entity(configMapList.stream()
+                        .filter(configMap -> 
!configMap.getMetadata().getName().equals("kube-root-ca.crt")))
+                .build();
     }
 
     @Path("/labels/{namespace}")
@@ -161,4 +166,20 @@ public class KubernetesConfigMapResource {
         ConfigMap configMap = 
consumerTemplate.receiveBody("seda:configMapEvents", 10000, ConfigMap.class);
         return Response.ok().entity(configMap).build();
     }
+
+    @Path("/property/resolve")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response resolvePropertyFromConfigMap() {
+        String result = 
producerTemplate.requestBody("direct:configMapProperty", null, String.class);
+        return Response.ok().entity(result).build();
+    }
+
+    @Path("/context/reload/state")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response contextReloadState() {
+        String result = CONTEXT_RELOADED.get() ? "reloaded" : "not-reloaded";
+        return Response.ok().entity(result).build();
+    }
 }
diff --git 
a/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesResource.java
 
b/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesResource.java
index ec167718fc..ba46d2c177 100644
--- 
a/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesResource.java
+++ 
b/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesResource.java
@@ -18,19 +18,43 @@ package org.apache.camel.quarkus.component.kubernetes.it;
 
 import java.util.concurrent.atomic.AtomicReference;
 
+import io.fabric8.kubernetes.client.KubernetesClient;
+import jakarta.enterprise.event.Observes;
 import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
 import jakarta.ws.rs.POST;
 import jakarta.ws.rs.Path;
 import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
 import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
 import org.apache.camel.CamelContext;
+import 
org.apache.camel.component.kubernetes.config_maps.vault.ConfigmapsReloadTriggerTask;
 import 
org.apache.camel.component.kubernetes.customresources.KubernetesCustomResourcesConsumer;
+import 
org.apache.camel.component.kubernetes.secrets.vault.SecretsReloadTriggerTask;
+import org.apache.camel.impl.event.CamelContextReloadedEvent;
+import org.apache.camel.util.ObjectHelper;
 
 @Path("/kubernetes")
 public class KubernetesResource {
     @Inject
     CamelContext context;
 
+    @Inject
+    KubernetesClient client;
+
+    void onReload(@Observes CamelContextReloadedEvent event) {
+        String eventSource = event.getAction().getClass().getName();
+        if 
(eventSource.startsWith(ConfigmapsReloadTriggerTask.class.getName())) {
+            KubernetesConfigMapResource.CONTEXT_RELOADED.set(true);
+        }
+
+        if (eventSource.startsWith(SecretsReloadTriggerTask.class.getName())) {
+            KubernetesSecretResource.CONTEXT_RELOADED.set(true);
+        }
+    }
+
     @Path("/route/{routeId}/start")
     @POST
     public void startRoute(
@@ -57,4 +81,12 @@ public class KubernetesResource {
         reference.set(null);
         context.getRouteController().stopRoute(routeId);
     }
+
+    @Path("/default/namespace")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response getDefaultNamespace() {
+        String namespace = ObjectHelper.isEmpty(client.getNamespace()) ? 
"default" : client.getNamespace();
+        return Response.ok().entity(namespace).build();
+    }
 }
diff --git 
a/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesRoutes.java
 
b/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesRoutes.java
index 9c98bc0f76..426abd39e6 100644
--- 
a/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesRoutes.java
+++ 
b/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesRoutes.java
@@ -20,7 +20,10 @@ import java.util.concurrent.atomic.AtomicReference;
 
 import io.quarkus.runtime.annotations.RegisterForReflection;
 import org.apache.camel.BindToRegistry;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spi.PropertiesComponent;
 
 @RegisterForReflection(targets = AtomicReference.class)
 public class KubernetesRoutes extends RouteBuilder {
@@ -35,6 +38,28 @@ public class KubernetesRoutes extends RouteBuilder {
         from("direct:startNoAutoWired")
                 .toD("kubernetes-pods-no-autowire:${header.masterUrl}");
 
+        from("direct:configMapProperty")
+                .process(new Processor() {
+                    @Override
+                    public void process(Exchange exchange) {
+                        PropertiesComponent component = 
exchange.getContext().getPropertiesComponent();
+                        
component.resolveProperty("configmap:greeting-config/greeting").ifPresent(value 
-> {
+                            exchange.getMessage().setBody("Hello " + value);
+                        });
+                    }
+                });
+
+        from("direct:secretProperty")
+                .process(new Processor() {
+                    @Override
+                    public void process(Exchange exchange) {
+                        PropertiesComponent component = 
exchange.getContext().getPropertiesComponent();
+                        
component.resolveProperty("secret:secret-config/greeting").ifPresent(value -> {
+                            exchange.getMessage().setBody("Hello " + value);
+                        });
+                    }
+                });
+
         
from("kubernetes-config-maps:local?resourceName=camel-configmap-watched")
                 .id("configmap-listener")
                 .autoStartup(false)
diff --git 
a/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesSecretResource.java
 
b/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesSecretResource.java
index 587ce30a51..df088cc5cd 100644
--- 
a/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesSecretResource.java
+++ 
b/integration-tests/kubernetes/src/main/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesSecretResource.java
@@ -19,6 +19,7 @@ package org.apache.camel.quarkus.component.kubernetes.it;
 import java.net.URI;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import io.fabric8.kubernetes.api.model.Secret;
 import jakarta.enterprise.context.ApplicationScoped;
@@ -40,6 +41,7 @@ import 
org.apache.camel.component.kubernetes.KubernetesOperations;
 @Path("/kubernetes/secret")
 @ApplicationScoped
 public class KubernetesSecretResource {
+    static final AtomicBoolean CONTEXT_RELOADED = new AtomicBoolean(false);
 
     @Inject
     ProducerTemplate producerTemplate;
@@ -150,4 +152,20 @@ public class KubernetesSecretResource {
         List<Secret> list = 
producerTemplate.requestBodyAndHeaders("direct:start", null, headers, 
List.class);
         return Response.ok().entity(list).build();
     }
+
+    @Path("/property/resolve")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response resolvePropertyFromSecret() {
+        String result = producerTemplate.requestBody("direct:secretProperty", 
null, String.class);
+        return Response.ok().entity(result).build();
+    }
+
+    @Path("/context/reload/state")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response contextReloadState() {
+        String result = CONTEXT_RELOADED.get() ? "reloaded" : "not-reloaded";
+        return Response.ok().entity(result).build();
+    }
 }
diff --git 
a/integration-tests/kubernetes/src/main/resources/application.properties 
b/integration-tests/kubernetes/src/main/resources/application.properties
new file mode 100644
index 0000000000..0ae1d8a084
--- /dev/null
+++ b/integration-tests/kubernetes/src/main/resources/application.properties
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+camel.main.context-reload-enabled = true
diff --git 
a/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesConfigMapContextReloadIT.java
 
b/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesConfigMapContextReloadIT.java
new file mode 100644
index 0000000000..696275675d
--- /dev/null
+++ 
b/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesConfigMapContextReloadIT.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.kubernetes.it;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.junit.jupiter.api.Disabled;
+
+@Disabled("https://github.com/apache/camel-quarkus/issues/7042";)
+@QuarkusTest
+class KubernetesConfigMapContextReloadIT extends 
KubernetesConfigMapContextReloadTest {
+}
diff --git 
a/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesConfigMapContextReloadTest.java
 
b/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesConfigMapContextReloadTest.java
new file mode 100644
index 0000000000..2843c105a4
--- /dev/null
+++ 
b/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesConfigMapContextReloadTest.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.kubernetes.it;
+
+import java.time.Duration;
+import java.util.Map;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.QuarkusTestProfile;
+import io.quarkus.test.junit.TestProfile;
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+import org.awaitility.Awaitility;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.Matchers.is;
+
+@Disabled("https://github.com/apache/camel-quarkus/issues/7042";)
+@TestProfile(KubernetesConfigMapContextReloadTest.KubernetesConfigMapContextReloadTestProfile.class)
+@QuarkusTest
+class KubernetesConfigMapContextReloadTest {
+    @Test
+    void configMapTriggersCamelContextReload() throws Exception {
+        Map<String, String> data = Map.of("foo", "bar");
+
+        String name = 
ConfigProvider.getConfig().getValue("camel.vault.kubernetescm.configmaps", 
String.class);
+        String namespace = RestAssured.get("/kubernetes/default/namespace")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .asString();
+
+        try {
+            // Create
+            RestAssured.given()
+                    .contentType(ContentType.JSON)
+                    .body(data)
+                    .when()
+                    .post("/kubernetes/configmap/" + namespace + "/" + name)
+                    .then()
+                    .statusCode(201)
+                    .body("metadata.name", is(name),
+                            "metadata.namespace", is(namespace),
+                            "data.foo", is("bar"));
+
+            // Need to delay before updating the secret so that the reload 
trigger task can capture the event
+            Thread.sleep(500);
+
+            // Update to trigger context reload
+            Map<String, String> updatedData = Map.of("bin", "baz");
+            RestAssured.given()
+                    .contentType(ContentType.JSON)
+                    .body(updatedData)
+                    .when()
+                    .put("/kubernetes/configmap/" + namespace + "/" + name)
+                    .then()
+                    .statusCode(200)
+                    .body("metadata.name", is(name),
+                            "data.bin", is("baz"));
+
+            
Awaitility.await().pollInterval(Duration.ofMillis(250)).atMost(Duration.ofMinutes(1)).untilAsserted(()
 -> {
+                RestAssured.get("/kubernetes/configmap/context/reload/state")
+                        .then()
+                        .statusCode(200)
+                        .body(is("reloaded"));
+            });
+        } finally {
+            // Clean up
+            RestAssured.given()
+                    .when()
+                    .delete("/kubernetes/configmap/" + namespace + "/" + name)
+                    .then()
+                    .statusCode(204);
+        }
+    }
+
+    public static final class KubernetesConfigMapContextReloadTestProfile 
implements QuarkusTestProfile {
+        @Override
+        public Map<String, String> getConfigOverrides() {
+            return Map.of(
+                    "camel.vault.kubernetescm.refreshEnabled", "true",
+                    "camel.vault.kubernetescm.configmaps", 
"configmap-reload-config");
+        }
+    }
+}
diff --git 
a/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesConfigMapTest.java
 
b/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesConfigMapTest.java
index 5d2b67d544..d7a257e2d3 100644
--- 
a/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesConfigMapTest.java
+++ 
b/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesConfigMapTest.java
@@ -28,10 +28,13 @@ import io.quarkus.test.junit.QuarkusTest;
 import io.quarkus.test.kubernetes.client.KubernetesTestServer;
 import io.restassured.RestAssured;
 import io.restassured.http.ContentType;
+import org.apache.camel.quarkus.test.EnabledIf;
+import org.apache.camel.quarkus.test.mock.backend.MockBackendEnabled;
 import org.awaitility.Awaitility;
 import org.junit.jupiter.api.Test;
 
 import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.oneOf;
 
 @QuarkusTest
 @QuarkusTestResource(CamelQuarkusKubernetesServerTestResource.class)
@@ -200,4 +203,42 @@ class KubernetesConfigMapTest {
                     .statusCode(204);
         }
     }
+
+    @Test
+    void configMapPropertyResolution() throws Exception {
+        Map<String, String> data = Map.of("greeting", "Camel Quarkus");
+
+        String namespace = RestAssured.get("/kubernetes/default/namespace")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .asString();
+
+        try {
+            // Create
+            RestAssured.given()
+                    .contentType(ContentType.JSON)
+                    .body(data)
+                    .when()
+                    .post("/kubernetes/configmap/" + namespace + 
"/greeting-config")
+                    .then()
+                    .statusCode(201)
+                    .body("metadata.name", is("greeting-config"),
+                            "data.greeting", is(data.get("greeting")));
+
+            // Resolve property from ConfigMap
+            RestAssured.get("/kubernetes/configmap/property/resolve")
+                    .then()
+                    .statusCode(200)
+                    .body(is("Hello Camel Quarkus"));
+        } finally {
+            // Clean up
+            RestAssured.given()
+                    .when()
+                    .delete("/kubernetes/configmap/" + namespace + 
"/greeting-config")
+                    .then()
+                    .statusCode(oneOf(404, 204));
+        }
+    }
 }
diff --git 
a/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesJobTest.java
 
b/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesJobTest.java
index cdab0d5c83..5f07b60615 100644
--- 
a/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesJobTest.java
+++ 
b/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesJobTest.java
@@ -128,27 +128,27 @@ class KubernetesJobTest {
                         .withPath("/apis/batch/v1/namespaces/" + listNamespace 
+ "/jobs?labelSelector=app%3Dcamel-job")
                         .andReturn(200, new 
JobListBuilder().addAllToItems(List.of(updatedJob)).build())
                         .once();
-            }
 
-            // List
-            RestAssured.given()
-                    .when()
-                    .get("/kubernetes/job/" + listNamespace)
-                    .then()
-                    .statusCode(200)
-                    .body("[0].metadata.name", is("camel-job"),
-                            "[0].metadata.namespace", 
is(namespace.getNamespace()));
+                // List
+                RestAssured.given()
+                        .when()
+                        .get("/kubernetes/job/" + listNamespace)
+                        .then()
+                        .statusCode(200)
+                        .body("[0].metadata.name", is("camel-job"),
+                                "[0].metadata.namespace", 
is(namespace.getNamespace()));
 
-            // List by labels
-            RestAssured.given()
-                    .contentType(ContentType.JSON)
-                    .body(Map.of("app", "camel-job"))
-                    .when()
-                    .get("/kubernetes/job/labels/" + listNamespace)
-                    .then()
-                    .statusCode(200)
-                    .body("[0].metadata.name", is("camel-job"),
-                            "[0].metadata.namespace", 
is(namespace.getNamespace()));
+                // List by labels
+                RestAssured.given()
+                        .contentType(ContentType.JSON)
+                        .body(Map.of("app", "camel-job"))
+                        .when()
+                        .get("/kubernetes/job/labels/" + listNamespace)
+                        .then()
+                        .statusCode(200)
+                        .body("[0].metadata.name", is("camel-job"),
+                                "[0].metadata.namespace", 
is(namespace.getNamespace()));
+            }
 
             // Delete
             RestAssured.given()
diff --git 
a/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesSecretContextReloadIT.java
 
b/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesSecretContextReloadIT.java
new file mode 100644
index 0000000000..4bea227c04
--- /dev/null
+++ 
b/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesSecretContextReloadIT.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.kubernetes.it;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+import org.junit.jupiter.api.Disabled;
+
+@Disabled("https://github.com/apache/camel-quarkus/issues/7042";)
+@QuarkusIntegrationTest
+class KubernetesSecretContextReloadIT extends 
KubernetesSecretContextReloadTest {
+}
diff --git 
a/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesSecretContextReloadTest.java
 
b/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesSecretContextReloadTest.java
new file mode 100644
index 0000000000..38c92983e9
--- /dev/null
+++ 
b/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesSecretContextReloadTest.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.kubernetes.it;
+
+import java.time.Duration;
+import java.util.Map;
+
+import io.fabric8.kubernetes.api.model.Secret;
+import io.fabric8.kubernetes.api.model.SecretBuilder;
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.QuarkusTestProfile;
+import io.quarkus.test.junit.TestProfile;
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+import org.awaitility.Awaitility;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.Matchers.is;
+
+@Disabled("https://github.com/apache/camel-quarkus/issues/7042";)
+@TestProfile(KubernetesSecretContextReloadTest.KubernetesSecretContextReloadTestProfile.class)
+@QuarkusTest
+class KubernetesSecretContextReloadTest {
+    @Test
+    void secretTriggersCamelContextReload() throws Exception {
+        Map<String, String> data = Map.of("project-name", "Camel");
+
+        String name = 
ConfigProvider.getConfig().getValue("camel.vault.kubernetes.secrets", 
String.class);
+        Secret secret = new SecretBuilder()
+                .withNewMetadata()
+                .withLabels(Map.of("app", name))
+                .withName(name)
+                .endMetadata()
+                .withData(data)
+                .build();
+
+        String namespace = RestAssured.get("/kubernetes/default/namespace")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .asString();
+
+        try {
+            // Create
+            RestAssured.given()
+                    .contentType(ContentType.JSON)
+                    .body(secret)
+                    .when()
+                    .post("/kubernetes/secret/" + namespace)
+                    .then()
+                    .statusCode(201)
+                    .body("metadata.name", is(name),
+                            "metadata.namespace", is(namespace),
+                            "metadata.annotations.app", is(name),
+                            "data.project-name", is(data.get("project-name")));
+
+            // Need to delay before updating the secret so that the reload 
trigger task can capture the event
+            Thread.sleep(500);
+
+            // Update to trigger context reload
+            Map<String, String> newData = Map.of("project-name", "Apache Camel 
Quarkus");
+            secret.setData(newData);
+            RestAssured.given()
+                    .contentType(ContentType.JSON)
+                    .body(secret)
+                    .when()
+                    .put("/kubernetes/secret/" + namespace)
+                    .then()
+                    .statusCode(200)
+                    .body("metadata.name", is(name),
+                            "data.project-name", 
is(newData.get("project-name")));
+
+            
Awaitility.await().pollInterval(Duration.ofMillis(250)).atMost(Duration.ofMinutes(1)).untilAsserted(()
 -> {
+                RestAssured.get("/kubernetes/secret/context/reload/state")
+                        .then()
+                        .statusCode(200)
+                        .body(is("reloaded"));
+            });
+
+        } finally {
+            // Clean up
+            RestAssured.given()
+                    .when()
+                    .delete("/kubernetes/secret/" + namespace + "/" + name)
+                    .then()
+                    .statusCode(204);
+        }
+    }
+
+    public static final class KubernetesSecretContextReloadTestProfile 
implements QuarkusTestProfile {
+        @Override
+        public Map<String, String> getConfigOverrides() {
+            return Map.of(
+                    "camel.vault.kubernetes.refreshEnabled", "true",
+                    "camel.vault.kubernetes.secrets", "secret-reload-config");
+        }
+    }
+}
diff --git 
a/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesSecretTest.java
 
b/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesSecretTest.java
index ca83d83cd7..f06072066f 100644
--- 
a/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesSecretTest.java
+++ 
b/integration-tests/kubernetes/src/test/java/org/apache/camel/quarkus/component/kubernetes/it/KubernetesSecretTest.java
@@ -52,7 +52,8 @@ class KubernetesSecretTest {
                     .withNewMetadata()
                     .withLabels(Map.of("app", name))
                     .withName(name)
-                    .endMetadata().withData(data)
+                    .endMetadata()
+                    .withData(data)
                     .build();
 
             // Create
@@ -141,4 +142,54 @@ class KubernetesSecretTest {
                             .body("size()", is(0)));
         }
     }
+
+    @Test
+    void secretPropertyResolution() throws Exception {
+        // base64 encoded string for: Camel Quarkus
+        Map<String, String> data = Map.of("greeting", "Q2FtZWwgUXVhcmt1cw==");
+
+        String name = "secret-config";
+        Secret secret = new SecretBuilder()
+                .withNewMetadata()
+                .withLabels(Map.of("app", name))
+                .withName(name)
+                .endMetadata()
+                .withData(data)
+                .build();
+
+        String namespace = RestAssured.get("/kubernetes/default/namespace")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .asString();
+
+        try {
+            // Create
+            RestAssured.given()
+                    .contentType(ContentType.JSON)
+                    .body(secret)
+                    .when()
+                    .post("/kubernetes/secret/" + namespace)
+                    .then()
+                    .statusCode(201)
+                    .body("metadata.name", is(name),
+                            "metadata.namespace", is(namespace),
+                            "metadata.annotations.app", is(name),
+                            "data.greeting", is(data.get("greeting")));
+
+            // Resolve property from Secret
+            RestAssured.get("/kubernetes/secret/property/resolve")
+                    .then()
+                    .statusCode(200)
+                    .body(is("Hello Camel Quarkus"));
+        } finally {
+            // Clean up
+            RestAssured.given()
+                    .when()
+                    .delete("/kubernetes/secret/" + namespace + "/" + name)
+                    .then()
+                    .statusCode(204);
+        }
+    }
 }


Reply via email to