Dekorate, (formerly the ap4k project) is designed to make the generation of Kubernetes and OpenShift manifests in Java based projects easier. The project was rebranded since it now supports decorating Kubernetes manifests without the use of annotations, so the name ap4k no longer describes the project accurately.
Dekorate is a collection of Java compile-time generators and decorators for Kubernetes and OpenShift manifests. Developers don't need to edit any XML, JSON or YAML to customize these manifests.
With Dekorate developers can generate or customize manifests using annotation processing, configuration properties (application.properties), or both. Dekorate supports Kubernetes, OpenShift, Knative, Tekton, Prometheus, Jaeger, Service Catalog, and Halkyon CRD. Furthermore, Dekorate integrates with frameworks like Spring Boot, Quarkus, Thorntail, and also provides a build tool for generic Java projects that allow any maven, gradle, sbt, and bazel projects to generate the manifests.
As an example, let's explore how Dekorate integrates with a Quarkus application.
Quarkus already has a Kubernetes extension that internally uses Dekorate for generating and customizing manifests for Kubernetes, OpenShift, and Knative. This extension allows Quarkus to deploy an application to a Kubernetes cluster by applying the generated manifests, or even create a container image and push it to a registry before deploying the application (see the container image guide for more details).
To add the extension, you just need to execute in terminal:
mvn quarkus:add-extension -Dextensions="io.quarkus:quarkus-kubernetes"
After compilation finishes, the generated manifests will be available under: target/kubernetes/
.
The kubernetes.json file looks like this:
{
"apiVersion" : "v1",
"kind" : "ServiceAccount",
"metadata" : {
"annotations" : {
"app.quarkus.io/vcs-url" : "<>",
"app.quarkus.io/build-timestamp" : "2020-06-04 - 05:13:57 +0000",
"app.quarkus.io/commit-id" : "<>"
},
"labels" : {
"app.kubernetes.io/name" : "decorate",
"app.kubernetes.io/version" : "1.0.0-SNAPSHOT"
},
"name" : "decorate"
}
}
At the moment this extension will handle things like ports and health checks, with zero configuration from the user side. It's important to note that by design, this extension will not use the dekorate annotations for customizing the generated manifests.
For a Spring Boot application, there are two starters available, io.dekorate:kubernetes-spring-starter:1.0.0
for Kubernetes, and io.dekorate:openshift-spring-starter:1.0.0
for OpenShift.
On Spring Boot, it is possible to bypass annotations by utilizing already-existing, framework specific metadata. To customize generated manifests, you can add dekorate properties to your application.yml/application.properties, or even use annotations along with application.yml/application.properties. By default, dekorate properties override any existing annotation configuration.
Dekorate looks for supported configuration as follows in increasing order of priority:
- Annotations
- application.properties
- application.yaml
- application.yml
- application-kubernetes.properties
- application-kubernetes.yaml
- application-kubernetes.yml
For a Thorntail application, two starters are provided, io.dekorate:kubernetes-thorntail-starter:jar:1.0.0
for Kubernetes, and io.dekorate:openshift-thorntail-starter:jar:1.0.0
for OpenShift.
From these starters, you can start to use Dekorate annotations, such @KubernetesApplication
, @OpenShiftApplication
, etc.
To generate Kubernetes manifests for a generic Java application, you have to add the dependency io.dekorate:kubernetes-annotations:jar:1.0.0
for Kubernetes, and io.dekorate:openshit-annotations:jar:1.0.0
for OpenShift.
Then you need to add the @Dekorate
annotation, or @KubernetesApplication
, that is a more specialized form of @Dekorate
to one of your Java source files.
import io.dekorate.kubernetes.annotation.KubernetesApplication;
@KubernetesApplication
public class Main {
public static void main(String[] args) {
}
}
After running mvn clean package
you will see the generated manifests under target/classes/META-INF/dekorate.
The kubernetes.yml will look like:
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: "kubernetes-example"
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: "my-gradle-app"
app.kubernetes.io/version: "1.0-SNAPSHOT"
template:
metadata:
labels:
app.kubernetes.io/name: "my-gradle-app"
app.kubernetes.io/version: "1.0-SNAPSHOT"
spec:
containers:
- env:
- name: "KUBERNETES_NAMESPACE"
valueFrom:
fieldRef:
fieldPath: "metadata.namespace"
image: "default/my-gradle-app:1.0-SNAPSHOT"
imagePullPolicy: "IfNotPresent"
name: "my-gradle-app"
To generate OpenShift manifests for a generic Java application, you can use the @Dekorate
annotation, or @OpenshiftApplication
, that works exactly like @KubernetesApplication
, but generates the openshift.yml/openshift.json instead.
Dekorate brings some additional features apart from the core manifest generation feature. These features include things like building, deploying and testing.
Dekorate allows users to hook external tools (for example docker or oc) to trigger container image builds after the end of compilation, since it does not generate Docker files, nor does it provide internal support for performing docker or s2i builds.
At the moment, as an experimental feature the following hooks are provided:
- docker build hook (requires docker binary, triggered with -Ddekorate.build=true)
- docker push hook (requires docker binary, triggered with -Ddekorate.push=true)
- OpenShift s2i build hook (requires oc binary, triggered with -Ddekorate.deploy=true)
Dekorate also brings JUnit 5 extensions for Kubernetes and Openshift, which allow developers to run end-to-end tests. At this moment the supported features are environment conditions, container builds, apply generated manifests to test the environment, and inject tests with client/application pod.
More details, such as all the configuration options and code examples (Spring Boot, Thorntail, Vertx, Istio), can be found at the GitHub repo.