diff --git a/camel-k-runtime-core/pom.xml b/camel-k-runtime-core/pom.xml index 085baadfd..592bd1524 100644 --- a/camel-k-runtime-core/pom.xml +++ b/camel-k-runtime-core/pom.xml @@ -110,6 +110,8 @@ ${project.basedir} + ${project.basedir}/src/test/resources/configmaps + ${project.basedir}/src/test/resources/secrets diff --git a/camel-k-runtime-core/src/main/java/org/apache/camel/k/Constants.java b/camel-k-runtime-core/src/main/java/org/apache/camel/k/Constants.java index 785dc5757..619408abb 100644 --- a/camel-k-runtime-core/src/main/java/org/apache/camel/k/Constants.java +++ b/camel-k-runtime-core/src/main/java/org/apache/camel/k/Constants.java @@ -29,6 +29,12 @@ public final class Constants { public static final String ENV_CAMEL_K_CUSTOMIZERS = "CAMEL_K_CUSTOMIZERS"; public static final String PROPERTY_CAMEL_K_CUSTOMIZER = "camel.k.customizer"; + public static final String ENV_CAMEL_K_MOUNT_PATH_CONFIGMAPS = "CAMEL_K_MOUNT_PATH_CONFIGMAPS"; + public static final String PROPERTY_CAMEL_K_MOUNT_PATH_CONFIGMAPS = "camel.k.mount-path.configmaps"; + + public static final String ENV_CAMEL_K_MOUNT_PATH_SECRETS = "CAMEL_K_MOUNT_PATH_SECRETS"; + public static final String PROPERTY_CAMEL_K_MOUNT_PATH_SECRETS = "camel.k.mount-path.secrets"; + public static final String SCHEME_CLASSPATH = "classpath:"; public static final String SCHEME_FILE = "file:"; public static final String LOGGING_LEVEL_PREFIX = "logging.level."; diff --git a/camel-k-runtime-core/src/main/java/org/apache/camel/k/listener/PropertiesFunctionsConfigurer.java b/camel-k-runtime-core/src/main/java/org/apache/camel/k/listener/PropertiesFunctionsConfigurer.java new file mode 100644 index 000000000..d16002a6f --- /dev/null +++ b/camel-k-runtime-core/src/main/java/org/apache/camel/k/listener/PropertiesFunctionsConfigurer.java @@ -0,0 +1,64 @@ +/* + * 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.k.listener; + +import org.apache.camel.k.Constants; +import org.apache.camel.k.Runtime; +import org.apache.camel.k.support.KubernetesPropertiesFunction; +import org.apache.camel.spi.PropertiesComponent; + +public class PropertiesFunctionsConfigurer extends AbstractPhaseListener { + public PropertiesFunctionsConfigurer() { + super(Runtime.Phase.Starting); + } + + @Override + protected void accept(Runtime runtime) { + // + // Register properties functions to resolve k8s secrets or config maps like: + // + // {{secret:name/key}} + // {{configmap:name/key}} + // + PropertiesComponent pc = runtime.getCamelContext().getPropertiesComponent(); + if (pc instanceof org.apache.camel.component.properties.PropertiesComponent) { + // + // ConfigMap + // + String cmPath = System.getProperty(Constants.PROPERTY_CAMEL_K_MOUNT_PATH_CONFIGMAPS); + if (cmPath == null) { + cmPath = System.getenv(Constants.ENV_CAMEL_K_MOUNT_PATH_CONFIGMAPS); + } + + ((org.apache.camel.component.properties.PropertiesComponent)pc).addFunction( + new KubernetesPropertiesFunction(cmPath, "configmap") + ); + + // + // Secret + // + String secretPath = System.getProperty(Constants.PROPERTY_CAMEL_K_MOUNT_PATH_SECRETS); + if (secretPath == null) { + secretPath = System.getenv(Constants.ENV_CAMEL_K_MOUNT_PATH_SECRETS); + } + + ((org.apache.camel.component.properties.PropertiesComponent)pc).addFunction( + new KubernetesPropertiesFunction(secretPath, "secret") + ); + } + } +} diff --git a/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/KubernetesPropertiesFunction.java b/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/KubernetesPropertiesFunction.java new file mode 100644 index 000000000..e7fc29988 --- /dev/null +++ b/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/KubernetesPropertiesFunction.java @@ -0,0 +1,66 @@ +/* + * 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.k.support; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.apache.camel.component.properties.PropertiesFunction; +import org.apache.camel.util.StringHelper; + +public class KubernetesPropertiesFunction implements PropertiesFunction { + private final String name; + private final Path root; + + public KubernetesPropertiesFunction(String path, String name) { + this.root = path != null ? Paths.get(path) : null; + this.name = name; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public String apply(String remainder) { + if (this.root == null) { + return remainder; + } + + final String name = StringHelper.before(remainder, "/"); + final String property = StringHelper.after(remainder, "/"); + + if (name == null || property == null) { + return remainder; + } + + Path file = this.root.resolve(name.toLowerCase()).resolve(property); + if (Files.exists(file) && !Files.isDirectory(file)) { + try { + return new String(Files.readAllBytes(file), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + return remainder; + } +} diff --git a/camel-k-runtime-core/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener b/camel-k-runtime-core/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener index c544dab86..8f6a5afbd 100644 --- a/camel-k-runtime-core/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener +++ b/camel-k-runtime-core/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener @@ -18,3 +18,4 @@ org.apache.camel.k.listener.ContextConfigurer org.apache.camel.k.listener.RoutesConfigurer org.apache.camel.k.listener.RoutesDumper +org.apache.camel.k.listener.PropertiesFunctionsConfigurer diff --git a/camel-k-runtime-core/src/test/java/org/apache/camel/k/listener/PropertiesFunctionsConfigurerTest.java b/camel-k-runtime-core/src/test/java/org/apache/camel/k/listener/PropertiesFunctionsConfigurerTest.java new file mode 100644 index 000000000..d8223d3e9 --- /dev/null +++ b/camel-k-runtime-core/src/test/java/org/apache/camel/k/listener/PropertiesFunctionsConfigurerTest.java @@ -0,0 +1,47 @@ +/* + * 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.k.listener; + +import java.util.Properties; + +import org.apache.camel.CamelContext; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.k.Runtime; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PropertiesFunctionsConfigurerTest { + @Test + public void testConfigMapFunction() { + Properties properties = new Properties(); + properties.setProperty("my.property", "{{secret:my-secret/my-property}}"); + + CamelContext context = new DefaultCamelContext(); + context.getPropertiesComponent().setInitialProperties(properties); + + new PropertiesFunctionsConfigurer().accept(Runtime.on(context)); + + assertThat(context.resolvePropertyPlaceholders("{{secret:my-secret/my-property}}")).isEqualTo("my-secret-property"); + assertThat(context.resolvePropertyPlaceholders("{{secret:none/my-property}}")).isEqualTo("none/my-property"); + + assertThat(context.resolvePropertyPlaceholders("{{configmap:my-cm/my-property}}")).isEqualTo("my-cm-property"); + assertThat(context.resolvePropertyPlaceholders("{{configmap:none/my-property}}")).isEqualTo("none/my-property"); + + assertThat(context.resolvePropertyPlaceholders("{{my.property}}")).isEqualTo("my-secret-property"); + } +} diff --git a/camel-k-runtime-core/src/test/resources/configmaps/my-cm/my-property b/camel-k-runtime-core/src/test/resources/configmaps/my-cm/my-property new file mode 100644 index 000000000..38c6ea5bd --- /dev/null +++ b/camel-k-runtime-core/src/test/resources/configmaps/my-cm/my-property @@ -0,0 +1 @@ +my-cm-property \ No newline at end of file diff --git a/camel-k-runtime-core/src/test/resources/secrets/my-secret/my-property b/camel-k-runtime-core/src/test/resources/secrets/my-secret/my-property new file mode 100644 index 000000000..01b39e434 --- /dev/null +++ b/camel-k-runtime-core/src/test/resources/secrets/my-secret/my-property @@ -0,0 +1 @@ +my-secret-property \ No newline at end of file