Skip to content

Commit

Permalink
DBZ-6962 Initial support for pod templating (#17)
Browse files Browse the repository at this point in the history
* DBZ-6962 Ability to configure various aspects of DebeziumServer's pod via PodTemplate

* DBZ-6962 Added property descriptions and other serialisation configuration
  • Loading branch information
jcechace authored and jpechane committed Nov 6, 2023
1 parent 6f242c0 commit a20381c
Show file tree
Hide file tree
Showing 18 changed files with 750 additions and 36 deletions.
2 changes: 1 addition & 1 deletion examples/postgres/010_debezium-server-ephemeral.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ kind: DebeziumServer
metadata:
name: my-debezium
spec:
image: quay.io/debezium/server:2.4.0.Final
image: quay.io/debezium/server:nightly
quarkus:
config:
log.console.json: false
Expand Down
426 changes: 426 additions & 0 deletions k8/debeziumservers.debezium.io-v1.yml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion k8/kubernetes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: quay.io/debezium/operator:2.4.0.Final
image: quay.io/debezium/operator:nightly
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@

import io.debezium.operator.DebeziumServer;
import io.debezium.operator.VersionProvider;
import io.debezium.operator.model.templates.PodTemplate;
import io.fabric8.kubernetes.api.model.ConfigMapVolumeSourceBuilder;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.ContainerBuilder;
import io.fabric8.kubernetes.api.model.ContainerPortBuilder;
import io.fabric8.kubernetes.api.model.EmptyDirVolumeSourceBuilder;
Expand Down Expand Up @@ -72,15 +74,16 @@ private String getTaggedImage(DebeziumServer primary) {
protected Deployment desired(DebeziumServer primary, Context<DebeziumServer> context) {
var name = primary.getMetadata().getName();
var image = getTaggedImage(primary);
var desiredContainer = desiredContainer(primary, name, image);
var labels = Map.of("app", name);
var annotations = Map.of(CONFIG_MD5_ANNOTATION, primary.asConfiguration().md5Sum());

var dataVolume = desiredDataVolume(primary);
var sa = context.getSecondaryResource(ServiceAccount.class)
.map(r -> r.getMetadata().getName())
.orElseThrow();

var quarkus = primary.getSpec().getQuarkus();
var probePort = quarkus.getConfig().getProps().getOrDefault("http.port", 8080);
var templates = primary.getSpec().getRuntime().getTemplates();

var deployment = new DeploymentBuilder()
.withMetadata(new ObjectMetaBuilder()
Expand All @@ -107,46 +110,30 @@ protected Deployment desired(DebeziumServer primary, Context<DebeziumServer> con
.build())
.build())
.addToVolumes(dataVolume)
.addToContainers(new ContainerBuilder()
.withName(name)
.withImage(image)
.withLivenessProbe(new ProbeBuilder()
.withHttpGet(new HTTPGetActionBuilder()
.withPath("/q/health/live")
.withPort(new IntOrString(probePort))
.build())
.build())
.withReadinessProbe(new ProbeBuilder()
.withHttpGet(new HTTPGetActionBuilder()
.withPath("/q/health/ready")
.withPort(new IntOrString(probePort))
.build())
.build())
.withPorts(new ContainerPortBuilder()
.withName("http")
.withProtocol("TCP")
.withContainerPort(DEFAULT_HTTP_PORT)
.build())
.addToVolumeMounts(new VolumeMountBuilder()
.withName(CONFIG_VOLUME_NAME)
.withMountPath(CONFIG_FILE_PATH)
.withSubPath(CONFIG_FILE_NAME)
.build())
.addToVolumeMounts(new VolumeMountBuilder()
.withName(DATA_VOLUME_NAME)
.withMountPath(DATA_VOLUME_PATH)
.build())
.build())
.addToContainers(desiredContainer)
.build())
.build())
.build())
.build();

addPodTemplateConfiguration(templates.getPod(), deployment);
addExternalEnvVariables(primary, deployment);
addExternalVolumes(primary, deployment);
return deployment;
}

private void addPodTemplateConfiguration(PodTemplate template, Deployment deployment) {
var templateMeta = template.getMetadata();
var pod = deployment.getSpec().getTemplate();
var podSpec = pod.getSpec();
var podMeta = pod.getMetadata();

podSpec.setAffinity(template.getAffinity());
podSpec.setImagePullSecrets(template.getImagePullSecrets());
podMeta.getLabels().putAll(templateMeta.getLabels());
podMeta.getAnnotations().putAll(templateMeta.getAnnotations());
}

private void addExternalEnvVariables(DebeziumServer primary, Deployment deployment) {
var config = primary.getSpec().getRuntime();
var containers = deployment.getSpec().getTemplate().getSpec().getContainers();
Expand Down Expand Up @@ -182,7 +169,42 @@ private Volume desiredDataVolume(DebeziumServer primary) {
.withClaimName(storageConfig.getClaimName())
.build());
}

return builder.build();
}

private Container desiredContainer(DebeziumServer primary, String name, String image) {
var quarkus = primary.getSpec().getQuarkus();
var probePort = quarkus.getConfig().getProps().getOrDefault("http.port", 8080);

return new ContainerBuilder()
.withName(name)
.withImage(image)
.withLivenessProbe(new ProbeBuilder()
.withHttpGet(new HTTPGetActionBuilder()
.withPath("/q/health/live")
.withPort(new IntOrString(probePort))
.build())
.build())
.withReadinessProbe(new ProbeBuilder()
.withHttpGet(new HTTPGetActionBuilder()
.withPath("/q/health/ready")
.withPort(new IntOrString(probePort))
.build())
.build())
.withPorts(new ContainerPortBuilder()
.withName("http")
.withProtocol("TCP")
.withContainerPort(DEFAULT_HTTP_PORT)
.build())
.addToVolumeMounts(new VolumeMountBuilder()
.withName(CONFIG_VOLUME_NAME)
.withMountPath(CONFIG_FILE_PATH)
.withSubPath(CONFIG_FILE_NAME)
.build())
.addToVolumeMounts(new VolumeMountBuilder()
.withName(DATA_VOLUME_NAME)
.withMountPath(DATA_VOLUME_PATH)
.build())
.build();
}
}
26 changes: 26 additions & 0 deletions src/main/java/io/debezium/operator/model/DebeziumServerSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,45 @@
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;

import io.debezium.operator.config.ConfigMappable;
import io.debezium.operator.config.ConfigMapping;

@JsonInclude(JsonInclude.Include.NON_DEFAULT)
public class DebeziumServerSpec implements ConfigMappable {

@JsonPropertyDescription("Image used for Debezium Server container. This property takes precedence over version.")
private String image;

@JsonPropertyDescription("Version of Debezium Server to be used.")
private String version;

@JsonPropertyDescription("Storage configuration to be used by this instance of Debezium Server.")
private Storage storage;

@JsonPropertyDescription("Sink configuration.")
private Sink sink;

@JsonPropertyDescription("Debezium source connector configuration.")
private Source source;

@JsonPropertyDescription("Message output format configuration.")
private Format format;

@JsonPropertyDescription("Quarkus configuration passed down to Debezium Server process.")
private Quarkus quarkus;

@JsonPropertyDescription("Configuration allowing the modification of various aspects of Debezium Server runtime.")
private Runtime runtime;

@JsonPropertyDescription("Single Message Transformations employed by this instance of Debezium Server.")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<Transformation> transforms;

@JsonPropertyDescription("Predicates employed by this instance of Debezium Server.")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private Map<String, Predicate> predicates;

public DebeziumServerSpec() {
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/io/debezium/operator/model/Format.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@
*/
package io.debezium.operator.model;

import com.fasterxml.jackson.annotation.JsonPropertyDescription;

import io.debezium.operator.config.ConfigMappable;
import io.debezium.operator.config.ConfigMapping;

public class Format implements ConfigMappable {

@JsonPropertyDescription("Message key format configuration.")
private FormatType key;

@JsonPropertyDescription("Message value format configuration.")
private FormatType value;

@JsonPropertyDescription("Message header format configuration.")
private FormatType header;

public Format() {
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/io/debezium/operator/model/FormatType.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
*/
package io.debezium.operator.model;

import com.fasterxml.jackson.annotation.JsonPropertyDescription;

import io.debezium.operator.config.ConfigMappable;
import io.debezium.operator.config.ConfigMapping;

public class FormatType implements ConfigMappable {

@JsonPropertyDescription("Format type recognised by Debezium Server.")
private String type;

@JsonPropertyDescription("Format configuration properties.")
private ConfigProperties config;

public FormatType() {
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/io/debezium/operator/model/Predicate.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@
*/
package io.debezium.operator.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;

import io.debezium.operator.config.ConfigMappable;
import io.debezium.operator.config.ConfigMapping;

public class Predicate implements ConfigMappable {

@JsonPropertyDescription("Fully qualified name of Java class implementing the predicate.")
@JsonProperty(required = true)
private String type;

@JsonPropertyDescription("Predicate configuration properties.")
private ConfigProperties config;

public Predicate() {
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/io/debezium/operator/model/Quarkus.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
*/
package io.debezium.operator.model;

import com.fasterxml.jackson.annotation.JsonPropertyDescription;

import io.debezium.operator.config.ConfigMappable;
import io.debezium.operator.config.ConfigMapping;

public class Quarkus implements ConfigMappable {

@JsonPropertyDescription("Quarkus configuration properties.")
private ConfigProperties config;

public Quarkus() {
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/io/debezium/operator/model/Runtime.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,26 @@
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonPropertyDescription;

import io.fabric8.kubernetes.api.model.EnvFromSource;
import io.fabric8.kubernetes.api.model.Volume;

public class Runtime {

@JsonPropertyDescription("Additional environment variables set from ConfigMaps or Secrets in containers.")
private List<EnvFromSource> env;

@JsonPropertyDescription("Additional volumes mounted to containers.")
private List<Volume> volumes;

@JsonPropertyDescription("Debezium Server resource templates.")
private Templates templates;

public Runtime() {
this.env = new ArrayList<>();
this.volumes = new ArrayList<>();
this.templates = new Templates();
}

public List<EnvFromSource> getEnv() {
Expand All @@ -37,4 +45,12 @@ public List<Volume> getVolumes() {
public void setVolumes(List<Volume> volumes) {
this.volumes = volumes;
}

public Templates getTemplates() {
return templates;
}

public void setTemplates(Templates templates) {
this.templates = templates;
}
}
7 changes: 7 additions & 0 deletions src/main/java/io/debezium/operator/model/Sink.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@
*/
package io.debezium.operator.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;

import io.debezium.operator.config.ConfigMappable;
import io.debezium.operator.config.ConfigMapping;

public class Sink implements ConfigMappable {

@JsonPropertyDescription("Sink type recognised by Debezium Server.")
@JsonProperty(required = true)
private String type;

@JsonPropertyDescription("Sink configuration properties.")
private ConfigProperties config;

public Sink() {
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/io/debezium/operator/model/Source.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,24 @@
package io.debezium.operator.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;

import io.debezium.operator.config.ConfigMappable;
import io.debezium.operator.config.ConfigMapping;

public class Source implements ConfigMappable {

@JsonPropertyDescription("Fully qualified name of source connector Java class.")
@JsonProperty(value = "class", required = true)
private String sourceClass;

@JsonPropertyDescription("Source connector configuration properties.")
private ConfigProperties config;

public Source() {
this.config = new ConfigProperties();
}

@JsonProperty("class")
public String getSourceClass() {
return sourceClass;
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/io/debezium/operator/model/Storage.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@
*/
package io.debezium.operator.model;

import com.fasterxml.jackson.annotation.JsonPropertyDescription;

public class Storage {

@JsonPropertyDescription("Storage type.")
private StorageType type;

@JsonPropertyDescription("Name of persistent volume claim for persistent storage.")
private String claimName;

public Storage() {
Expand Down
Loading

0 comments on commit a20381c

Please sign in to comment.