Skip to content

Commit

Permalink
Example with Kubernetes ConfigMap. (#337)
Browse files Browse the repository at this point in the history
  • Loading branch information
radcortez authored Jun 22, 2020
1 parent a607a40 commit 5cf8878
Show file tree
Hide file tree
Showing 9 changed files with 324 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ The same mapping rules as defined for environment variables are applied, so the

To use the FileSystem Config Source, add the following to your Maven `pom.xml`:

[source,xml,subs="verbatim,attributes"]
https://xxx[[source,xml,subs="verbatim,attributes"]
----
<dependency>
<groupId>io.smallrye.config</groupId>
<artifactId>smallrye-config-source-file-system</artifactId>
<version>{version}</version>
</dependency>
----
----]
This Config Source is not automatically registered. This means that you also need to provide your own
`ConfigSourceProvider` implementation and registration via `ServiceLoader` to use this Config Source like documented in
Expand Down
57 changes: 57 additions & 0 deletions examples/configmap/.kubernetes/configmap-app.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
apiVersion: v1
kind: Service
metadata:
name: configmap-app
spec:
type: "LoadBalancer"
ports:
- name: "http"
port: 8080
targetPort: 8080
selector:
app: configmap-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: configmap-app
labels:
app: configmap-app
spec:
replicas: 1
selector:
matchLabels:
app: configmap-app
template:
metadata:
labels:
app: configmap-app
spec:
containers:
- name: configmap-app
image: docker-registry:5000/smallrye-config-examples/configmap-app
imagePullPolicy: Always
ports:
- containerPort: 8080
env:
- name: CONFIG_MAP_DIR_SOURCE
value: "/usr/local/apps/config"
volumeMounts:
- name: configmap-app
mountPath: /usr/local/apps/config
volumes:
- name: configmap-app
configMap:
name: configmap-app
restartPolicy: Always
---
apiVersion: v1
kind: ConfigMap
metadata:
name: configmap-app
labels:
app: configmap-app
data:
smallrye.config.example.configmap.foo: something
smallrye.config.example.configmap.bar: something-else
76 changes: 76 additions & 0 deletions examples/configmap/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
= Kubernetes ConfigMap ConfigSource Example

In this example, the `FileSystemConfigSource` is used to access a Kubernetes ConfigMap configuration.

== Setup

Since the `FileSystemConfigSource` is implemented in a separate `SmallRyeConfig` module, it requires an additional
dependency in the project that wants to read configuration from Kubernetes ConfigMap.

[source,xml,subs="verbatim,attributes"]
----
<dependency>
<groupId>io.smallrye.config</groupId>
<artifactId>smallrye-config-source-file-system</artifactId>
<version>{version}</version>
</dependency>
----

== Implementation

The `FileSystemConfigSource` needs to be registed with the application. The recommended way is to use a
`ConfigSourceFactory` via the standard ServiceLoader mechanism. The factory gives the option to configure the
`FileSystemConfigSource` with higher priority ConfigSources.

[source,java]
----
public class ConfigMapConfigSourceFactory implements ConfigSourceFactory {
@Override
public ConfigSource getSource(final ConfigSourceContext context) {
final ConfigValue value = context.getValue("CONFIG_MAP_DIR_SOURCE");
if (value == null || value.getValue() == null) {
throw new IllegalArgumentException("CONFIG_MAP_DIR_SOURCE not defined");
}
return new FileSystemConfigSource(value.getValue());
}
@Override
public OptionalInt getPriority() {
return OptionalInt.of(200);
}
}
----

In this case, the volume path to read the Kubernetes ConfigMap comes from an environment variable configuration.

== Run

The example starts a simple http server with a single endpoint im `/configMap`. To deploy the example in a Kubernetes
cluster requires the following steps.

Set up a local Docker Registry first to store the generated Docker images:

[source,bash]
----
docker run -d -p 5000:5000 --restart=always --name docker-registry registry:2
----

Set up a host in '/etc/hosts' pointing `127.0.0.1` to `docker-registry`.

Build the example with:

[source,bash]
----
mvn package docker:build docker:push
----

Deploy to Kubernetes with:

[source,bash]
----
kubectl apply -f .kubernetes
----

Call tbe endpoint `curl http://localhost:8080/configMap`. This should list all the configurations set in the Kubernets
Config Map. The Kubernetes and ConfigMap configuration can be found in `.kubernetes/configmap-app.yml`.
110 changes: 110 additions & 0 deletions examples/configmap/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.smallrye</groupId>
<artifactId>smallrye-parent</artifactId>
<version>20</version>
</parent>

<groupId>io.smallrye.config.examples</groupId>
<artifactId>configmap</artifactId>
<version>1.8.2-SNAPSHOT</version>

<name>SmallRye Config Examples: ConfigMap</name>

<dependencies>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
</dependency>

<dependency>
<groupId>io.smallrye.config</groupId>
<artifactId>smallrye-config</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>io.smallrye.config</groupId>
<artifactId>smallrye-config-source-file-system</artifactId>
<version>${project.version}</version>
</dependency>

<!-- Test Dependencies -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<finalName>${project.artifactId}-app</finalName>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>io.smallrye.config.examples.configmap.ConfigMapApp</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>create-jar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>

<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.33.0</version>
<configuration>
<verbose>true</verbose>
<registry>docker-registry:5000</registry>
<pullRegistry>docker.io</pullRegistry>
<images>
<image>
<name>smallrye-config-examples/configmap-app</name>
<build>
<from>adoptopenjdk/openjdk11:alpine-slim</from>
<ports>
<port>8080</port>
</ports>
<workdir>/usr/local/apps</workdir>
<assembly>
<name>usr/local/apps</name>
<inline>
<files>
<file>
<source>${project.build.directory}/${project.artifactId}-app.jar</source>
<destName>${project.artifactId}-app.jar</destName>
</file>
</files>
</inline>
</assembly>
<cmd>java -jar ${project.artifactId}-app.jar</cmd>
</build>
<run>
<ports>
<port>8080:8080</port>
</ports>
</run>
</image>
</images>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.smallrye.config.examples.configmap;

import java.net.InetSocketAddress;
import java.util.Map;

import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.config.spi.ConfigSource;

import com.sun.net.httpserver.HttpServer;

public class ConfigMapApp {
public static void main(String[] args) throws Exception {
Config config = ConfigProvider.getConfig();

HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
server.createContext("/configMap", exchange -> {
boolean responseSent = false;

final Iterable<ConfigSource> configSources = config.getConfigSources();
for (ConfigSource configSource : configSources) {
if (configSource.getName().startsWith("FileSystemConfig")) {
final Map<String, String> properties = configSource.getProperties();
final byte[] bytes = properties.toString().getBytes();
exchange.sendResponseHeaders(200, properties.toString().length());
exchange.getResponseBody().write(bytes);
exchange.getResponseBody().flush();
exchange.getResponseBody().close();
responseSent = true;
break;
}
}

if (!responseSent) {
exchange.sendResponseHeaders(404, 0);
exchange.getResponseBody().write(new byte[0]);
exchange.getResponseBody().flush();
exchange.getResponseBody().close();
}
});

server.start();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.smallrye.config.examples.configmap;

import java.util.OptionalInt;

import org.eclipse.microprofile.config.spi.ConfigSource;

import io.smallrye.config.ConfigSourceContext;
import io.smallrye.config.ConfigSourceFactory;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.source.file.FileSystemConfigSource;

public class ConfigMapConfigSourceFactory implements ConfigSourceFactory {
@Override
public ConfigSource getSource(final ConfigSourceContext context) {
final ConfigValue value = context.getValue("config.map.dir.source");
if (value == null || value.getValue() == null) {
throw new IllegalArgumentException("CONFIG_MAP_DIR_SOURCE not defined");
}

return new FileSystemConfigSource(value.getValue());
}

@Override
public OptionalInt getPriority() {
return OptionalInt.of(200);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.smallrye.config.examples.configmap.ConfigMapConfigSourceFactory
1 change: 1 addition & 0 deletions examples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@
<module>interceptors</module>
<module>expansion</module>
<module>profiles</module>
<module>configmap</module>
</modules>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,22 @@ public class FileSystemConfigSource extends MapBackedConfigSource {

private static final Pattern PATTERN = Pattern.compile("[^a-zA-Z0-9_]");

FileSystemConfigSource(File dir) {
public FileSystemConfigSource(File dir) {
this(dir, DEFAULT_ORDINAL);
}

public FileSystemConfigSource(String dir) {
this(new File(dir), DEFAULT_ORDINAL);
}

/**
* Construct a new instance
*
* @param dir the directory, containing configuration files
* @param ordinal the ordinal value
*/
public FileSystemConfigSource(File dir, int ordinal) {
super("DirConfigSource[dir=" + dir.getAbsolutePath() + "]", scan(dir), ordinal);
super("FileSystemConfigSource[dir=" + dir.getAbsolutePath() + "]", scan(dir), ordinal);
}

private static Map<String, String> scan(File directory) {
Expand Down

0 comments on commit 5cf8878

Please sign in to comment.