-
Notifications
You must be signed in to change notification settings - Fork 26
feat: support annotations #111
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| /* | ||
| * Copyright Strimzi authors. | ||
| * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). | ||
| */ | ||
| package io.strimzi.kafka.access.model; | ||
|
|
||
| import io.strimzi.api.kafka.model.common.Constants; | ||
| import io.sundr.builder.annotations.Buildable; | ||
|
|
||
| /** | ||
| * Template for KafkaAccess resources (e.g., Secret template) | ||
| */ | ||
| @Buildable( | ||
| editableEnabled = false, | ||
| builderPackage = Constants.FABRIC8_KUBERNETES_API | ||
| ) | ||
| public class KafkaAccessTemplate { | ||
|
|
||
| private SecretTemplate secret; | ||
|
|
||
| /** | ||
| * Gets the Secret template | ||
| * | ||
| * @return The SecretTemplate instance | ||
| */ | ||
| public SecretTemplate getSecret() { | ||
| return secret; | ||
| } | ||
|
|
||
| /** | ||
| * Sets the Secret template | ||
| * | ||
| * @param secret The SecretTemplate model | ||
| */ | ||
| public void setSecret(final SecretTemplate secret) { | ||
| this.secret = secret; | ||
| } | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| /* | ||
| * Copyright Strimzi authors. | ||
| * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). | ||
| */ | ||
| package io.strimzi.kafka.access.model; | ||
|
|
||
| import io.strimzi.api.kafka.model.common.Constants; | ||
| import io.sundr.builder.annotations.Buildable; | ||
|
|
||
| import java.util.Map; | ||
|
|
||
| /** | ||
| * Template for Kubernetes resource metadata (labels, annotations) | ||
| */ | ||
| @Buildable( | ||
| editableEnabled = false, | ||
| builderPackage = Constants.FABRIC8_KUBERNETES_API | ||
| ) | ||
| public class MetadataTemplate { | ||
|
|
||
| private Map<String, String> labels; | ||
| private Map<String, String> annotations; | ||
|
|
||
| /** | ||
| * Gets the labels | ||
| * | ||
| * @return A map of labels | ||
| */ | ||
| public Map<String, String> getLabels() { | ||
| return labels; | ||
| } | ||
|
|
||
| /** | ||
| * Sets the labels | ||
| * | ||
| * @param labels A map of labels | ||
| */ | ||
| public void setLabels(final Map<String, String> labels) { | ||
| this.labels = labels; | ||
| } | ||
|
|
||
| /** | ||
| * Gets the annotations | ||
| * | ||
| * @return A map of annotations | ||
| */ | ||
| public Map<String, String> getAnnotations() { | ||
| return annotations; | ||
| } | ||
|
|
||
| /** | ||
| * Sets the annotations | ||
| * | ||
| * @param annotations A map of annotations | ||
| */ | ||
| public void setAnnotations(final Map<String, String> annotations) { | ||
| this.annotations = annotations; | ||
| } | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| /* | ||
| * Copyright Strimzi authors. | ||
| * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). | ||
| */ | ||
| package io.strimzi.kafka.access.model; | ||
|
|
||
| import io.strimzi.api.kafka.model.common.Constants; | ||
| import io.sundr.builder.annotations.Buildable; | ||
|
|
||
| /** | ||
| * Template for Secret metadata (labels, annotations) | ||
| */ | ||
| @Buildable( | ||
| editableEnabled = false, | ||
| builderPackage = Constants.FABRIC8_KUBERNETES_API | ||
| ) | ||
| public class SecretTemplate { | ||
|
|
||
| private MetadataTemplate metadata; | ||
|
|
||
| /** | ||
| * Gets the metadata template | ||
| * | ||
| * @return The MetadataTemplate instance | ||
| */ | ||
| public MetadataTemplate getMetadata() { | ||
| return metadata; | ||
| } | ||
|
|
||
| /** | ||
| * Sets the metadata template | ||
| * | ||
| * @param metadata The MetadataTemplate model | ||
| */ | ||
| public void setMetadata(final MetadataTemplate metadata) { | ||
| this.metadata = metadata; | ||
| } | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # Example KafkaAccess using reflector/replicator annotations for secret replication | ||
| # This demonstrates how to use the template field to add annotations for | ||
| # Kubernetes secret replication tools like reflector and replicator | ||
| apiVersion: access.strimzi.io/v1alpha1 | ||
| kind: KafkaAccess | ||
| metadata: | ||
| name: my-replicated-kafka-access | ||
| spec: | ||
| kafka: | ||
| name: data-stream-serv | ||
| namespace: kafka | ||
| user: | ||
| kind: KafkaUser | ||
| apiGroup: kafka.strimzi.io | ||
| name: my-app-user | ||
| namespace: kafka | ||
| template: | ||
| secret: | ||
| metadata: | ||
| annotations: | ||
| # Replicator annotations (mittwald) | ||
| replicator.v1.mittwald.de/replicate-to: "namespace1,namespace2,namespace3" | ||
| # Reflector annotations (emberstack) | ||
| reflector.v1.k8s.emberstack.com/reflection-allowed: "true" | ||
| reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true" | ||
| reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "namespace1,namespace2,namespace3" | ||
| labels: | ||
| environment: production | ||
| team: platform | ||
|
|
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -59,6 +59,8 @@ public class KafkaAccessReconciler implements Reconciler<KafkaAccess> { | |||||||||
| public static final String KAFKA_USER_SECRET_EVENT_SOURCE = "KAFKA_USER_SECRET_EVENT_SOURCE"; | ||||||||||
|
|
||||||||||
| /** | ||||||||||
| * Constructs a new KafkaAccessReconciler with the specified Kubernetes client. | ||||||||||
| * | ||||||||||
| * @param kubernetesClient The Kubernetes client | ||||||||||
| */ | ||||||||||
| public KafkaAccessReconciler(final KubernetesClient kubernetesClient) { | ||||||||||
|
|
@@ -104,14 +106,38 @@ private void createOrUpdateSecret(final Map<String, String> data, final KafkaAcc | |||||||||
| if (kafkaAccessSecretEventSource == null) { | ||||||||||
| throw new IllegalStateException("Event source for Kafka Access Secret not initialized, cannot reconcile"); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| final Map<String, String> templateAnnotations = getTemplateAnnotations(kafkaAccess); | ||||||||||
| final Map<String, String> templateLabels = getTemplateLabels(kafkaAccess); | ||||||||||
|
|
||||||||||
| kafkaAccessSecretEventSource.get(new ResourceID(secretName, kafkaAccessNamespace)) | ||||||||||
| .ifPresentOrElse(secret -> { | ||||||||||
| final Map<String, String> currentData = secret.getData(); | ||||||||||
| if (!data.equals(currentData)) { | ||||||||||
| final Map<String, String> currentAnnotations = Optional.ofNullable(secret.getMetadata().getAnnotations()).orElse(new HashMap<>()); | ||||||||||
| final Map<String, String> currentLabels = Optional.ofNullable(secret.getMetadata().getLabels()).orElse(new HashMap<>()); | ||||||||||
|
|
||||||||||
| // Merge template annotations/labels with existing ones (template takes precedence) | ||||||||||
|
||||||||||
| // Merge template annotations/labels with existing ones (template takes precedence) | |
| // Merge template annotations/labels with existing ones. | |
| // Template values override matching keys, but all other existing metadata is preserved. | |
| // Note: Removing a key from the template will not remove it from existing secrets. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] This explicit no-argument constructor is unnecessary and can be removed. Java automatically provides a default no-argument constructor when no constructors are explicitly defined. Since this class only contains static methods, the constructor is never called directly. The Javadoc plugin warning (if any) should be configured to ignore classes that don't need explicit constructor documentation, rather than adding unnecessary constructors.