You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/06/23 10:17:49 UTC
[camel] 01/03: CAMEL-18171: camel-kubernetes - Add configmap property placeholder function
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch cmap
in repository https://gitbox.apache.org/repos/asf/camel.git
commit bd53c058d9f9d911ed6ddce88a6ebac3292af356
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Jun 23 10:52:38 2022 +0200
CAMEL-18171: camel-kubernetes - Add configmap property placeholder function
---
components/camel-kubernetes/README.md | 38 ++++++++
.../org/apache/camel/properties-function/configmap | 2 +
.../properties/ConfigMapPropertiesFunction.java | 104 +++++++++++++++++++++
.../ConfigMapPropertiesFunctionRouteTest.java | 81 ++++++++++++++++
.../ConfigMapPropertiesFunctionTest.java | 64 +++++++++++++
5 files changed, 289 insertions(+)
diff --git a/components/camel-kubernetes/README.md b/components/camel-kubernetes/README.md
index bc14b34380a..59670dd2689 100644
--- a/components/camel-kubernetes/README.md
+++ b/components/camel-kubernetes/README.md
@@ -4,6 +4,8 @@
This component contains unit and integration tests. Some of them - like the consumer ones - require a Kubernetes environment.
+## Running using Kind
+
It is possible to run the integration tests using Kind. To do so, follow these steps:
1. Create a cluster:
@@ -30,3 +32,39 @@ export KUBE_HOST=https://localhost:$KIND_PORT
mvn -Dkubernetes.test.auth="$KUBE_TOKEN" -Dkubernetes.test.host=$KUBE_HOST -Dkubernetes.test.host.k8s=true clean verify
```
+
+## Running using Minikube
+
+It is possible to run the integration tests using Minikube. To do so, follow these steps:
+
+1. Create a cluster:
+
+```
+minikube start
+```
+
+2. Get the auth token:
+
+```
+export KUBE_TOKEN=$(kubectl get secrets -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='default')].data.token}"|base64 --decode)
+```
+
+4. Get the host:
+
+Find out the URL where the control plane is running:
+
+````
+kubectl cluster-info
+````
+
+And then set that as export, for example:
+
+```
+export KUBE_HOST=https://127.0.0.1:50179
+```
+
+5. Run the test:
+```
+mvn -Dkubernetes.test.auth="$KUBE_TOKEN" -Dkubernetes.test.host=$KUBE_HOST -Dkubernetes.test.host.k8s=true clean verify
+```
+
diff --git a/components/camel-kubernetes/src/generated/resources/META-INF/services/org/apache/camel/properties-function/configmap b/components/camel-kubernetes/src/generated/resources/META-INF/services/org/apache/camel/properties-function/configmap
new file mode 100644
index 00000000000..fd8e5d4f6d4
--- /dev/null
+++ b/components/camel-kubernetes/src/generated/resources/META-INF/services/org/apache/camel/properties-function/configmap
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.kubernetes.properties.ConfigMapPropertiesFunction
diff --git a/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/properties/ConfigMapPropertiesFunction.java b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/properties/ConfigMapPropertiesFunction.java
new file mode 100644
index 00000000000..d6bcb117730
--- /dev/null
+++ b/components/camel-kubernetes/src/main/java/org/apache/camel/component/kubernetes/properties/ConfigMapPropertiesFunction.java
@@ -0,0 +1,104 @@
+/*
+ * 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.component.kubernetes.properties;
+
+import java.util.Base64;
+
+import io.fabric8.kubernetes.api.model.ConfigMap;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.spi.PropertiesFunction;
+import org.apache.camel.support.CamelContextHelper;
+import org.apache.camel.support.service.ServiceSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.StringHelper;
+
+/**
+ * A {@link PropertiesFunction} that can lookup from Kubernetes configmaps.
+ */
+@org.apache.camel.spi.annotations.PropertiesFunction("configmap")
+public class ConfigMapPropertiesFunction extends ServiceSupport implements PropertiesFunction, CamelContextAware {
+
+ private CamelContext camelContext;
+ private KubernetesClient client;
+
+ @Override
+ protected void doInit() throws Exception {
+ if (client == null) {
+ client = CamelContextHelper.findSingleByType(camelContext, KubernetesClient.class);
+ }
+ ObjectHelper.notNull(client, "KubernetesClient must be configured");
+ }
+
+ @Override
+ public String getName() {
+ return "configmap";
+ }
+
+ @Override
+ public CamelContext getCamelContext() {
+ return camelContext;
+ }
+
+ @Override
+ public void setCamelContext(CamelContext camelContext) {
+ this.camelContext = camelContext;
+ }
+
+ public KubernetesClient getClient() {
+ return client;
+ }
+
+ public void setClient(KubernetesClient client) {
+ this.client = client;
+ }
+
+ @Override
+ public String apply(String remainder) {
+ String defaultValue = StringHelper.after(remainder, ":");
+
+ String name = StringHelper.before(remainder, "/");
+ String key = StringHelper.after(remainder, "/");
+
+ if (name == null || key == null) {
+ return defaultValue;
+ }
+
+ String answer = null;
+ ConfigMap cm = client.configMaps().withName(name).get();
+ if (cm != null) {
+ answer = cm.getData() != null ? cm.getData().get(key) : null;
+ if (answer == null) {
+ // maybe a binary data
+ answer = cm.getBinaryData() != null ? cm.getBinaryData().get(key) : null;
+ if (answer != null) {
+ // need to decode base64
+ byte[] data = Base64.getDecoder().decode(answer);
+ if (data != null) {
+ answer = new String(data);
+ }
+ }
+ }
+ }
+ if (answer == null) {
+ return defaultValue;
+ }
+
+ return answer;
+ }
+}
diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/properties/ConfigMapPropertiesFunctionRouteTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/properties/ConfigMapPropertiesFunctionRouteTest.java
new file mode 100644
index 00000000000..e4e65b806c8
--- /dev/null
+++ b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/properties/ConfigMapPropertiesFunctionRouteTest.java
@@ -0,0 +1,81 @@
+package org.apache.camel.component.kubernetes.properties;
+
+import java.util.Map;
+
+import io.fabric8.kubernetes.api.model.ConfigMap;
+import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
+import io.fabric8.kubernetes.client.ConfigBuilder;
+import io.fabric8.kubernetes.client.DefaultKubernetesClient;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import org.apache.camel.CamelContext;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.kubernetes.KubernetesTestSupport;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.condition.EnabledIfSystemProperties;
+import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
+
+@EnabledIfSystemProperties({
+ @EnabledIfSystemProperty(named = "kubernetes.test.auth", matches = ".*", disabledReason = "Requires kubernetes"),
+ @EnabledIfSystemProperty(named = "kubernetes.test.host", matches = ".*", disabledReason = "Requires kubernetes"),
+ @EnabledIfSystemProperty(named = "kubernetes.test.host.k8s", matches = "true", disabledReason = "Requires kubernetes"),
+})
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class ConfigMapPropertiesFunctionRouteTest extends KubernetesTestSupport {
+
+ private KubernetesClient client;
+ private ConfigMap cm;
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .transform().simple("Hello ${body} we are at {{configmap:myconfig/bar}}");
+ }
+ };
+ }
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext context = super.createCamelContext();
+
+ ConfigBuilder builder = new ConfigBuilder();
+ builder.withOauthToken(authToken);
+ builder.withMasterUrl(host);
+ client = new DefaultKubernetesClient(builder.build());
+ context.getRegistry().bind("KubernetesClient", client);
+
+ Map<String, String> data = Map.of("foo", "123", "bar", "Moes Bar");
+ ConfigMap cm = new ConfigMapBuilder().editOrNewMetadata().withName("myconfig").endMetadata().withData(data).build();
+ this.cm = client.configMaps().createOrReplace(cm);
+
+ return context;
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ if (client != null && cm != null) {
+ try {
+ client.configMaps().delete(cm);
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ super.tearDown();
+ }
+
+ @Test
+ @Order(1)
+ public void configMapPropertiesFunction() throws Exception {
+ String out = template.requestBody("direct:start", "Jack", String.class);
+ Assertions.assertEquals("Hello Jack we are at Moes Bar", out);
+ }
+
+}
diff --git a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/properties/ConfigMapPropertiesFunctionTest.java b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/properties/ConfigMapPropertiesFunctionTest.java
new file mode 100644
index 00000000000..80cef7af3b2
--- /dev/null
+++ b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/properties/ConfigMapPropertiesFunctionTest.java
@@ -0,0 +1,64 @@
+package org.apache.camel.component.kubernetes.properties;
+
+import java.util.Map;
+
+import io.fabric8.kubernetes.api.model.ConfigMap;
+import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
+import io.fabric8.kubernetes.client.ConfigBuilder;
+import io.fabric8.kubernetes.client.DefaultKubernetesClient;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import org.apache.camel.component.kubernetes.KubernetesTestSupport;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.condition.EnabledIfSystemProperties;
+import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
+
+@EnabledIfSystemProperties({
+ @EnabledIfSystemProperty(named = "kubernetes.test.auth", matches = ".*", disabledReason = "Requires kubernetes"),
+ @EnabledIfSystemProperty(named = "kubernetes.test.host", matches = ".*", disabledReason = "Requires kubernetes"),
+ @EnabledIfSystemProperty(named = "kubernetes.test.host.k8s", matches = "true", disabledReason = "Requires kubernetes"),
+})
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class ConfigMapPropertiesFunctionTest extends KubernetesTestSupport {
+
+ @Test
+ @Order(1)
+ public void configMapPropertiesFunction() throws Exception {
+ ConfigBuilder builder = new ConfigBuilder();
+ builder.withOauthToken(authToken);
+ builder.withMasterUrl(host);
+
+ KubernetesClient client = new DefaultKubernetesClient(builder.build());
+
+ Map<String, String> data = Map.of("foo", "123", "bar", "Moes Bar");
+ ConfigMap cm = new ConfigMapBuilder().editOrNewMetadata().withName("myconfig").endMetadata().withData(data).build();
+ client.configMaps().createOrReplace(cm);
+
+ try {
+ ConfigMapPropertiesFunction cmf = new ConfigMapPropertiesFunction();
+ cmf.setClient(client);
+ cmf.setCamelContext(context);
+ cmf.start();
+
+ String out = cmf.apply("myconfig/foo");
+ Assertions.assertEquals("123", out);
+
+ out = cmf.apply("myconfig/unknown");
+ Assertions.assertNull(out);
+
+ out = cmf.apply("myconfig/unknown:444");
+ Assertions.assertEquals("444", out);
+
+ out = cmf.apply("myconfig/bar");
+ Assertions.assertEquals("Moes Bar", out);
+
+ cmf.stop();
+ } finally {
+ client.configMaps().delete(cm);
+ }
+ }
+
+}