Skip to content

Commit

Permalink
DBZ-6962 Ability to configure various aspects of DebeziumServer's pod…
Browse files Browse the repository at this point in the history
… via PodTemplate
  • Loading branch information
jcechace committed Oct 16, 2023
1 parent de509eb commit 43783d4
Show file tree
Hide file tree
Showing 9 changed files with 631 additions and 35 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
383 changes: 383 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();
}
}
14 changes: 14 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,6 +8,8 @@
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;

Expand All @@ -17,9 +19,13 @@ public class Runtime {

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 +43,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;
}
}
28 changes: 28 additions & 0 deletions src/main/java/io/debezium/operator/model/Templates.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright Debezium Authors.
*
* Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package io.debezium.operator.model;

import com.fasterxml.jackson.annotation.JsonPropertyDescription;

import io.debezium.operator.model.templates.PodTemplate;

public class Templates {

@JsonPropertyDescription("Pod template.")
private PodTemplate pod;

public Templates() {
this.pod = new PodTemplate();
}

public PodTemplate getPod() {
return pod;
}

public void setPod(PodTemplate pod) {
this.pod = pod;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright Debezium Authors.
*
* Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package io.debezium.operator.model.templates;

/**
* Interface for kubernetes objects witch metadata
*/
public interface HasMetadataTemplate {

/**
* Gets template metadata
*
* @return Metadata template
*/
MetadataTemplate getMetadata();

/**
* Sets template metadata
*
* @param metadata Metadata template
*/
void setMetadata(MetadataTemplate metadata);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright Debezium Authors.
*
* Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package io.debezium.operator.model.templates;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@JsonPropertyOrder({ "labels", "annotations" })
public class MetadataTemplate implements Serializable {
public static final long serialVersionUID = 1L;

private Map<String, String> labels = new HashMap<>(0);
private Map<String, String> annotations = new HashMap<>(0);

public Map<String, String> getLabels() {
return labels;
}

public void setLabels(Map<String, String> labels) {
this.labels = labels;
}

public Map<String, String> getAnnotations() {
return annotations;
}

public void setAnnotations(Map<String, String> annotations) {
this.annotations = annotations;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof MetadataTemplate that)) {
return false;
}
return Objects.equals(labels, that.labels) && Objects.equals(annotations, that.annotations);
}

@Override
public int hashCode() {
return Objects.hash(labels, annotations);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright Debezium Authors.
*
* Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package io.debezium.operator.model.templates;

import java.util.List;

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

import io.fabric8.kubernetes.api.model.Affinity;
import io.fabric8.kubernetes.api.model.LocalObjectReference;
import io.fabric8.kubernetes.api.model.PodSecurityContext;

@JsonPropertyOrder({ "metadata", "imagePullSecrets", "affinity" })
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
public class PodTemplate implements HasMetadataTemplate {

@JsonPropertyDescription("Metadata applied to the resource.")
private MetadataTemplate metadata = new MetadataTemplate();

@JsonPropertyDescription("List of local references to secrets used for pulling any of the images used by this Pod.")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<LocalObjectReference> imagePullSecrets = List.of();

@JsonPropertyDescription("Pod affinity rules")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Affinity affinity;

@JsonPropertyDescription("Pod-level security attributes and container settings")
@JsonInclude(JsonInclude.Include.NON_NULL)
private PodSecurityContext securityContext;

@Override
public MetadataTemplate getMetadata() {
return metadata;
}

@Override
public void setMetadata(MetadataTemplate metadata) {
this.metadata = metadata;
}

public List<LocalObjectReference> getImagePullSecrets() {
return imagePullSecrets;
}

public void setImagePullSecrets(List<LocalObjectReference> imagePullSecrets) {
this.imagePullSecrets = imagePullSecrets;
}

public Affinity getAffinity() {
return affinity;
}

public void setAffinity(Affinity affinity) {
this.affinity = affinity;
}

public PodSecurityContext getSecurityContext() {
return securityContext;
}

public void setSecurityContext(PodSecurityContext securityContext) {
this.securityContext = securityContext;
}
}

0 comments on commit 43783d4

Please sign in to comment.