diff --git a/examples/postgres/010_debezium-server-ephemeral.yml b/examples/postgres/010_debezium-server-ephemeral.yml index 018fd1e..8527071 100644 --- a/examples/postgres/010_debezium-server-ephemeral.yml +++ b/examples/postgres/010_debezium-server-ephemeral.yml @@ -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 diff --git a/k8/debeziumservers.debezium.io-v1.yml b/k8/debeziumservers.debezium.io-v1.yml index 4f2a56d..4958606 100644 --- a/k8/debeziumservers.debezium.io-v1.yml +++ b/k8/debeziumservers.debezium.io-v1.yml @@ -18,8 +18,11 @@ spec: spec: properties: runtime: + description: Configuration allowing the modification of various aspects + of Debezium Server runtime. properties: volumes: + description: Additional volumes mounted to containers. items: properties: hostPath: @@ -669,6 +672,8 @@ spec: type: object type: array env: + description: Additional environment variables set from ConfigMaps + or Secrets in containers. items: properties: prefix: @@ -689,15 +694,406 @@ spec: type: object type: object type: array + templates: + description: Debezium Server resource templates. + properties: + pod: + description: Pod template. + properties: + affinity: + description: Pod affinity rules + properties: + podAntiAffinity: + properties: + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + namespaces: + items: + type: string + type: array + topologyKey: + type: string + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + values: + items: + type: string + type: array + operator: + type: string + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + values: + items: + type: string + type: array + operator: + type: string + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + type: object + type: array + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + namespaces: + items: + type: string + type: array + topologyKey: + type: string + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + values: + items: + type: string + type: array + operator: + type: string + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + values: + items: + type: string + type: array + operator: + type: string + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + type: object + weight: + type: integer + type: object + type: array + type: object + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + weight: + type: integer + preference: + properties: + matchFields: + items: + properties: + key: + type: string + values: + items: + type: string + type: array + operator: + type: string + type: object + type: array + matchExpressions: + items: + properties: + key: + type: string + values: + items: + type: string + type: array + operator: + type: string + type: object + type: array + type: object + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchFields: + items: + properties: + key: + type: string + values: + items: + type: string + type: array + operator: + type: string + type: object + type: array + matchExpressions: + items: + properties: + key: + type: string + values: + items: + type: string + type: array + operator: + type: string + type: object + type: array + type: object + type: array + type: object + type: object + podAffinity: + properties: + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + namespaces: + items: + type: string + type: array + topologyKey: + type: string + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + values: + items: + type: string + type: array + operator: + type: string + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + values: + items: + type: string + type: array + operator: + type: string + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + type: object + type: array + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + namespaces: + items: + type: string + type: array + topologyKey: + type: string + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + values: + items: + type: string + type: array + operator: + type: string + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + values: + items: + type: string + type: array + operator: + type: string + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + type: object + weight: + type: integer + type: object + type: array + type: object + type: object + metadata: + description: Metadata applied to the resource. + properties: + labels: + additionalProperties: + type: string + type: object + annotations: + additionalProperties: + type: string + type: object + type: object + securityContext: + description: Pod-level security attributes and container + settings + properties: + runAsGroup: + type: integer + runAsNonRoot: + type: boolean + windowsOptions: + properties: + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + gmsaCredentialSpec: + type: string + runAsUserName: + type: string + type: object + sysctls: + items: + properties: + value: + type: string + name: + type: string + type: object + type: array + fsGroupChangePolicy: + type: string + seLinuxOptions: + properties: + role: + type: string + type: + type: string + user: + type: string + level: + type: string + type: object + fsGroup: + type: integer + supplementalGroups: + items: + type: integer + type: array + runAsUser: + type: integer + seccompProfile: + properties: + type: + type: string + localhostProfile: + type: string + type: object + type: object + imagePullSecrets: + description: List of local references to secrets used + for pulling any of the images used by this Pod. + items: + properties: + name: + type: string + type: object + type: array + type: object + type: object type: object transforms: + description: Single Message Transformations employed by this instance + of Debezium Server. items: properties: negate: + description: Determines if the result of the applied predicate + will be negated. type: boolean predicate: + description: The name of the predicate to be applied to this + transformation. type: string type: + description: Fully qualified name of Java class implementing + the transformation. type: string config: properties: @@ -711,10 +1107,13 @@ spec: type: object type: array sink: + description: Sink configuration. properties: type: + description: Sink type recognised by Debezium Server. type: string config: + description: Sink configuration properties. properties: props: additionalProperties: @@ -725,22 +1124,32 @@ spec: x-kubernetes-preserve-unknown-fields: true type: object storage: + description: Storage configuration to be used by this instance of + Debezium Server. properties: claimName: + description: Name of persistent volume claim for persistent storage. type: string type: + description: Storage type. enum: - persistent - ephemeral type: string type: object version: + description: Version of Debezium Server to be used. type: string image: + description: Image used for Debezium Server container. This property + takes precedence over version. type: string quarkus: + description: Quarkus configuration passed down to Debezium Server + process. properties: config: + description: Quarkus configuration properties. properties: props: additionalProperties: @@ -754,8 +1163,11 @@ spec: additionalProperties: properties: type: + description: Fully qualified name of Java class implementing + the predicate. type: string config: + description: Predicate configuration properties. properties: props: additionalProperties: @@ -765,12 +1177,16 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: object + description: Predicates employed by this instance of Debezium Server. type: object source: + description: Debezium source connector configuration. properties: class: + description: Fully qualified name of source connector Java class. type: string config: + description: Source connector configuration properties. properties: props: additionalProperties: @@ -781,12 +1197,16 @@ spec: x-kubernetes-preserve-unknown-fields: true type: object format: + description: Message output format configuration. properties: key: + description: Message key format configuration. properties: type: + description: Format type recognised by Debezium Server. type: string config: + description: Format configuration properties. properties: props: additionalProperties: @@ -797,10 +1217,13 @@ spec: x-kubernetes-preserve-unknown-fields: true type: object value: + description: Message value format configuration. properties: type: + description: Format type recognised by Debezium Server. type: string config: + description: Format configuration properties. properties: props: additionalProperties: @@ -811,10 +1234,13 @@ spec: x-kubernetes-preserve-unknown-fields: true type: object header: + description: Message header format configuration. properties: type: + description: Format type recognised by Debezium Server. type: string config: + description: Format configuration properties. properties: props: additionalProperties: diff --git a/k8/kubernetes.yml b/k8/kubernetes.yml index 1101cbd..171c7a9 100644 --- a/k8/kubernetes.yml +++ b/k8/kubernetes.yml @@ -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 diff --git a/src/main/java/io/debezium/operator/dependent/DeploymentDependent.java b/src/main/java/io/debezium/operator/dependent/DeploymentDependent.java index 98e9eaf..92bd1bb 100644 --- a/src/main/java/io/debezium/operator/dependent/DeploymentDependent.java +++ b/src/main/java/io/debezium/operator/dependent/DeploymentDependent.java @@ -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; @@ -72,15 +74,16 @@ private String getTaggedImage(DebeziumServer primary) { protected Deployment desired(DebeziumServer primary, Context 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() @@ -107,46 +110,30 @@ protected Deployment desired(DebeziumServer primary, Context 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(); @@ -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(); + } } diff --git a/src/main/java/io/debezium/operator/model/DebeziumServerSpec.java b/src/main/java/io/debezium/operator/model/DebeziumServerSpec.java index 3062b1f..2d53c1e 100644 --- a/src/main/java/io/debezium/operator/model/DebeziumServerSpec.java +++ b/src/main/java/io/debezium/operator/model/DebeziumServerSpec.java @@ -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 transforms; + + @JsonPropertyDescription("Predicates employed by this instance of Debezium Server.") + @JsonInclude(JsonInclude.Include.NON_EMPTY) private Map predicates; public DebeziumServerSpec() { diff --git a/src/main/java/io/debezium/operator/model/Format.java b/src/main/java/io/debezium/operator/model/Format.java index 281c746..5a2fa3f 100644 --- a/src/main/java/io/debezium/operator/model/Format.java +++ b/src/main/java/io/debezium/operator/model/Format.java @@ -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() { diff --git a/src/main/java/io/debezium/operator/model/FormatType.java b/src/main/java/io/debezium/operator/model/FormatType.java index c4ee3f1..85c5b58 100644 --- a/src/main/java/io/debezium/operator/model/FormatType.java +++ b/src/main/java/io/debezium/operator/model/FormatType.java @@ -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() { diff --git a/src/main/java/io/debezium/operator/model/Predicate.java b/src/main/java/io/debezium/operator/model/Predicate.java index 2271d28..2a12e41 100644 --- a/src/main/java/io/debezium/operator/model/Predicate.java +++ b/src/main/java/io/debezium/operator/model/Predicate.java @@ -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() { diff --git a/src/main/java/io/debezium/operator/model/Quarkus.java b/src/main/java/io/debezium/operator/model/Quarkus.java index 0689934..9c1c749 100644 --- a/src/main/java/io/debezium/operator/model/Quarkus.java +++ b/src/main/java/io/debezium/operator/model/Quarkus.java @@ -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() { diff --git a/src/main/java/io/debezium/operator/model/Runtime.java b/src/main/java/io/debezium/operator/model/Runtime.java index 9240a96..8e39082 100644 --- a/src/main/java/io/debezium/operator/model/Runtime.java +++ b/src/main/java/io/debezium/operator/model/Runtime.java @@ -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 env; + @JsonPropertyDescription("Additional volumes mounted to containers.") private List 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 getEnv() { @@ -37,4 +45,12 @@ public List getVolumes() { public void setVolumes(List volumes) { this.volumes = volumes; } + + public Templates getTemplates() { + return templates; + } + + public void setTemplates(Templates templates) { + this.templates = templates; + } } diff --git a/src/main/java/io/debezium/operator/model/Sink.java b/src/main/java/io/debezium/operator/model/Sink.java index 07c9157..90630a7 100644 --- a/src/main/java/io/debezium/operator/model/Sink.java +++ b/src/main/java/io/debezium/operator/model/Sink.java @@ -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() { diff --git a/src/main/java/io/debezium/operator/model/Source.java b/src/main/java/io/debezium/operator/model/Source.java index 3124574..70647ac 100644 --- a/src/main/java/io/debezium/operator/model/Source.java +++ b/src/main/java/io/debezium/operator/model/Source.java @@ -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; } diff --git a/src/main/java/io/debezium/operator/model/Storage.java b/src/main/java/io/debezium/operator/model/Storage.java index 20066c6..73488d9 100644 --- a/src/main/java/io/debezium/operator/model/Storage.java +++ b/src/main/java/io/debezium/operator/model/Storage.java @@ -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() { diff --git a/src/main/java/io/debezium/operator/model/Templates.java b/src/main/java/io/debezium/operator/model/Templates.java new file mode 100644 index 0000000..0f354df --- /dev/null +++ b/src/main/java/io/debezium/operator/model/Templates.java @@ -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; + } +} diff --git a/src/main/java/io/debezium/operator/model/Transformation.java b/src/main/java/io/debezium/operator/model/Transformation.java index db7106f..737d109 100644 --- a/src/main/java/io/debezium/operator/model/Transformation.java +++ b/src/main/java/io/debezium/operator/model/Transformation.java @@ -5,13 +5,22 @@ */ 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 Transformation implements ConfigMappable { + @JsonPropertyDescription("Fully qualified name of Java class implementing the transformation.") + @JsonProperty(required = true) private String type; + + @JsonPropertyDescription("The name of the predicate to be applied to this transformation.") private String predicate; + + @JsonPropertyDescription("Determines if the result of the applied predicate will be negated.") private boolean negate = false; private ConfigProperties config; diff --git a/src/main/java/io/debezium/operator/model/templates/HasMetadataTemplate.java b/src/main/java/io/debezium/operator/model/templates/HasMetadataTemplate.java new file mode 100644 index 0000000..07736df --- /dev/null +++ b/src/main/java/io/debezium/operator/model/templates/HasMetadataTemplate.java @@ -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); +} diff --git a/src/main/java/io/debezium/operator/model/templates/MetadataTemplate.java b/src/main/java/io/debezium/operator/model/templates/MetadataTemplate.java new file mode 100644 index 0000000..745f79d --- /dev/null +++ b/src/main/java/io/debezium/operator/model/templates/MetadataTemplate.java @@ -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 labels = new HashMap<>(0); + private Map annotations = new HashMap<>(0); + + public Map getLabels() { + return labels; + } + + public void setLabels(Map labels) { + this.labels = labels; + } + + public Map getAnnotations() { + return annotations; + } + + public void setAnnotations(Map 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); + } +} diff --git a/src/main/java/io/debezium/operator/model/templates/PodTemplate.java b/src/main/java/io/debezium/operator/model/templates/PodTemplate.java new file mode 100644 index 0000000..b696aad --- /dev/null +++ b/src/main/java/io/debezium/operator/model/templates/PodTemplate.java @@ -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 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 getImagePullSecrets() { + return imagePullSecrets; + } + + public void setImagePullSecrets(List 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; + } +}