Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
Signed-off-by: Riccardo Pasquini <r.pasquini@almawave.it>
  • Loading branch information
morphy76 committed Jul 26, 2023
1 parent 54b7216 commit 3e5d403
Show file tree
Hide file tree
Showing 30 changed files with 1,158 additions and 2 deletions.
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,8 @@ target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
release.properties
release.properties

# Quarkus
.quarkus

3 changes: 2 additions & 1 deletion docs/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
* xref:index.adoc[Quarkus Config Extensions]
* xref:consul.adoc[HashiCorp Consul]
* xref:jdbc.adoc[JDBC Config]
* xref:jdbc.adoc[JDBC Config]
* xref:git.adoc[GIT Config]
132 changes: 132 additions & 0 deletions docs/modules/ROOT/pages/git.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
= Quarkus GIT Config

include::./includes/attributes.adoc[]

This guide explains how your Quarkus application can read configuration properties from a GIT repository.

== Prerequisites

To complete this guide, you need:

* less than 15 minutes
* an IDE
* JDK 11+ installed with `JAVA_HOME` configured appropriately
* Apache Maven {maven-version}


== Solution

We recommend that you follow the instructions in the next sections and create the application step by step.

== Introduction

TODO

== Creating the Maven project

First, we need a new project. Create a new project with the following command:

[source,bash,subs=attributes+]
----
mvn io.quarkus.platform:quarkus-maven-plugin:{quarkus-version}:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=config-git-quickstart \
-DclassName="org.acme.git.config.GreetingResource" \
-Dpath="/greeting" \
-Dextensions="config-git"
cd config-git-quickstart
----

This command generates a Maven project with a REST endpoint and imports the `config-git` extension.

If you already have your Quarkus project configured, you can add the `config-git` extension
to your project by running the following command in your project base directory:

[source,bash]
----
./mvnw quarkus:add-extension -Dextensions="config-git"
----

This will add the following to your `pom.xml`:

[source,xml,subs=attributes+]
----
<dependency>
<groupId>io.quarkiverse.config</groupId>
<artifactId>quarkus-config-git</artifactId>
<version>{quarkus-config-extensions-version}</version>
</dependency>
----

== GreetingController

The Quarkus Maven plugin automatically generated a `GreetingResource` JAX-RS resource in the
`src/main/java/org/acme/consul/config/client/GreetingResource.java` file that looks like:

[source,java]
----
package org.acme.consul.config.client;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/greeting")
public class GreetingResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "hello";
}
}
----

As we want to use configuration properties obtained from the Config Server, we will update the `GreetingResource` to inject the `message` property. The updated code will look like this:

[source,java]
----
package org.acme.consul.config.client;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.config.inject.ConfigProperty;
@Path("/greeting")
public class GreetingResource {
@ConfigProperty(name = "greeting.message", defaultValue="Hello from default")
String message;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return message;
}
}
----

== Configuring the application

Quarkus provides various configuration knobs under the `quarkus.git-config-source` root. For the purposes of this guide, our Quarkus application is going to be configured in `application.properties` as follows:

[source,properties]
----
quarkus.git-config-source.TODO
----

== Create a versioned property file

TODO


== Package and run the application

Run the application with: `./mvnw compile quarkus:dev`.
Open your browser to http://localhost:8080/greeting.

The result should be: `Hello from GIT` as it is the value obtained from the database.

== Run the application as a native executable

You can of course create a native image using the instructions of the link:building-native-image[Building a native executable guide].

== Configuration Reference

include::./includes/quarkus-git-config.adoc[]
32 changes: 32 additions & 0 deletions docs/modules/ROOT/pages/includes/quarkus-git-config.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[.configuration-legend]
icon:lock[title=Fixed at build time] Configuration property fixed at build time - All other configuration properties are overridable at runtime
[.configuration-reference.searchable, cols="80,.^10,.^10"]
|===

h|[[quarkus-git-config_configuration]]link:#quarkus-git-config_configuration[Configuration property]

h|Type
h|Default

a| [[quarkus-git-config_quarkus.git-config-source.TODO]]`link:#quarkus-git-config_quarkus.git-config-source.TODO[quarkus.git-config-source.TODO]`

[.description]
--
If set to true, the application will attempt to look up the configuration from a GIT repository
--|boolean
|`true`

|===
ifndef::no-duration-note[]
[NOTE]
[[duration-note-anchor]]
.About the Duration format
====
The format for durations uses the standard `java.time.Duration` format.
You can learn more about it in the link:https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html#parse-java.lang.CharSequence-[Duration#parse() javadoc].

You can also provide duration values starting with a number.
In this case, if the value consists only of a number, the converter treats the value as seconds.
Otherwise, `PT` is implicitly prepended to the value to obtain a standard `java.time.Duration` format.
====
endif::no-duration-note[]
54 changes: 54 additions & 0 deletions git/deployment/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.quarkiverse.config</groupId>
<artifactId>quarkus-config-git-parent</artifactId>
<version>2.0.1-SNAPSHOT</version>
</parent>
<artifactId>quarkus-config-git-deployment</artifactId>
<name>Quarkus - Config Extensions - GIT - Deployment</name>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.config</groupId>
<artifactId>quarkus-config-git</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkiverse.jgit</groupId>
<artifactId>quarkus-jgit-deployment</artifactId>
<version>${quarkus.jgit.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.quarkiverse.quarkus.git.config.deployment;

import io.quarkiverse.quarkus.git.config.runtime.GitConfigBuilder;
import io.quarkiverse.quarkus.git.config.runtime.config.GitConfigSourceConfiguration;
import io.quarkiverse.quarkus.git.config.runtime.deployment.GitConfigSourceRecorder;
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.RunTimeConfigBuilderBuildItem;

class GitConfigSourceProcessor {

private static final String FEATURE = GitConfigSourceConfiguration.EXTENSION_NAME;

@BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem(FEATURE);
}

@BuildStep
RunTimeConfigBuilderBuildItem configSource() {
return new RunTimeConfigBuilderBuildItem(GitConfigBuilder.class);
}

@BuildStep
@Record(value = ExecutionTime.RUNTIME_INIT)
void initGitSource(GitConfigSourceRecorder recorder) {
recorder.init();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package io.quarkiverse.quarkus.git.config.test;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;

import org.eclipse.microprofile.config.ConfigProvider;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkiverse.quarkus.git.config.test.resources.GitRepository;
import io.quarkus.test.QuarkusUnitTest;

public class GitFilenameOverrideConfigSourceTest {

private static final String TEST_NAME = "filename";

public static final Path TEST_REPO_ROOT = Path.of("/tmp/git-config-source/tests");

private static final Runnable BEFORE_ALL = () -> {
var repoPath = TEST_REPO_ROOT.resolve(TEST_NAME);
GitRepository.free(repoPath);
try {
Files.createDirectories(repoPath);
var sourceURL = Thread.currentThread().getContextClassLoader()
.getResource("remote-filename-application.properties");
GitRepository.of(repoPath).init().addFile(new File(sourceURL.toURI()), "filename_override.properties");
} catch (IOException | URISyntaxException e) {
throw new RuntimeException(e);
}
};

// Start unit test with your extension loaded
@RegisterExtension
static final QuarkusUnitTest unitTest = new QuarkusUnitTest()
.withConfigurationResource(TEST_NAME + "-application.properties")
.setBeforeAllCustomizer(BEFORE_ALL)
.setArchiveProducer(() -> {
return ShrinkWrap.create(JavaArchive.class)
.addClass(GitRepository.class)
.addAsResource("remote-application.properties");
});

@AfterAll
public static void afterAll() throws IOException {
Path repoPath = TEST_REPO_ROOT.resolve(TEST_NAME);
GitRepository.free(repoPath);
}

@Test
public void testTheConfigValue() {
var cfg = ConfigProvider.getConfig().getOptionalValue("a.test.key", String.class);
assertThat(cfg).isNotEmpty().contains("a test integration value from another place");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package io.quarkiverse.quarkus.git.config.test;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;

import org.eclipse.microprofile.config.ConfigProvider;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkiverse.quarkus.git.config.test.resources.GitRepository;
import io.quarkus.test.QuarkusUnitTest;

public class GitMinimalConfigSourceTest {

private static final String TEST_NAME = "minimal";

public static final Path TEST_REPO_ROOT = Path.of("/tmp/git-config-source/tests");

private static final Runnable BEFORE_ALL = () -> {
var repoPath = TEST_REPO_ROOT.resolve(TEST_NAME);
GitRepository.free(repoPath);
try {
Files.createDirectories(repoPath);
var sourceURL = Thread.currentThread().getContextClassLoader().getResource("remote-application.properties");
GitRepository.of(repoPath).init().addFile(new File(sourceURL.toURI()), "application.properties");
} catch (IOException | URISyntaxException e) {
throw new RuntimeException(e);
}
};

// Start unit test with your extension loaded
@RegisterExtension
static final QuarkusUnitTest unitTest = new QuarkusUnitTest()
.withConfigurationResource(TEST_NAME + "-application.properties")
.setBeforeAllCustomizer(BEFORE_ALL)
.setArchiveProducer(() -> {
return ShrinkWrap.create(JavaArchive.class)
.addClass(GitRepository.class)
.addAsResource("remote-application.properties");
});

@AfterAll
public static void afterAll() throws IOException {
Path repoPath = TEST_REPO_ROOT.resolve(TEST_NAME);
GitRepository.free(repoPath);
}

@Test
public void testTheConfigValue() {
var cfg = ConfigProvider.getConfig().getOptionalValue("a.test.key", String.class);
assertThat(cfg).isNotEmpty().contains("a test value");
}
}
Loading

0 comments on commit 3e5d403

Please sign in to comment.