debezium / debezium/dbz

Operator Helm chart: create `app.imagePullSecrets` from a Deployment baseline instead of the `serviceAccountName` anchor

Open
#2,588 0 comments 0 reactions 0 assignees View on GitHub
component/debezium-operator
Dominant language
HTML
Stars
6
Forks
8
Avg merge
2d 19h
Merged PRs (30d)
1

Description

## Feature request or enhancement

**Which use case/requirement will be addressed by the proposed feature?**

Follow-up to #2461 and debezium/debezium-operator#219, as discussed in https://github.com/debezium/debezium-operator/pull/219#issuecomment-5571649059.

PR debezium/debezium-operator#219 added the `app.imagePullSecrets` Helm value.
Because `quarkus-helm` can only replace a field that already exists in the generated resource (quarkiverse/quarkus-helm#453), the PR anchors a `quarkus.helm.expressions` entry on `serviceAccountName` and appends a multi-line YAML block to it:

```properties
quarkus.helm.expressions.0.path=(kind == Deployment).spec.template.spec.serviceAccountName
quarkus.helm.expressions.0.expression=debezium-operator\n {{- with .Values.app.imagePullSecrets }}\n imagePullSecrets:\n {{- toYaml . | nindent 8 }}\n {{- end }}
```

This has four drawbacks:

- It hardcodes the value of the anchor field. `debezium-operator` is the service account name. If the service account is renamed, the rendered template silently keeps the old name.
- It hardcodes the indentation inside the string (six spaces).
- It couples `imagePullSecrets` to an unrelated field. A reader cannot tell why `serviceAccountName` carries a pull-secret block.
- `quarkus-helm` re-inserts the line breaks of an adapted expression with `System.lineSeparator()`, so the generated template depends on the build platform.

The goal is the same `app.imagePullSecrets` value, created without the anchor.

---

**Implementation ideas (optional)**

Create the field in a Deployment baseline (`debezium-operator-core/src/main/kubernetes/kubernetes.yml`) with a placeholder list `imagePullSecrets: [~]`, then map it with a regular `quarkus.helm.values` entry and a one-line expression:

```properties
quarkus.helm.values.image-pull-secrets.property=imagePullSecrets
quarkus.helm.values.image-pull-secrets.paths=(kind == Deployment).spec.template.spec.imagePullSecrets
quarkus.helm.values.image-pull-secrets.expression={{- toYaml (.Values.app.imagePullSecrets | default list) | nindent 8 }}
```

`src/main/helm/values.yaml` (already present) keeps the `[]` default, and the `values-schema` entries stay as they are.
The `[~]` placeholder is needed because the fabric8 model marks `PodSpec.imagePullSecrets` with `@JsonInclude(NON_EMPTY)`, so an empty list `[]` does not survive the generation.
A list with one `null` element does.

The same approach is in production in aboutbits/postgresql-operator since v0.6.0. aboutbits/postgresql-operator#62 explains the alternatives that were tried and rejected.

### Effects on the generated artifacts

Verified with a local build of `debezium-operator-core` on `main`:

- Helm chart: `helm template` renders `imagePullSecrets: []` by default and `- name: ` when set. `helm lint` passes. `values.yaml`, `values.schema.json` and the chart README are unchanged.
- `k8/kubernetes.yml` and the OLM CSV gain `imagePullSecrets: [{}]`. The API server accepts an entry with an empty name (`validateImagePullSecrets` only rejects fields other than `name`), and the kubelet skips such an entry without a warning (`getPullSecretsForPod`, see kubernetes/kubernetes#99454).
- A baseline Deployment bypasses Dekorate's default Deployment factory, which has two side effects. Both are compensated in the same change:
- `KUBERNETES_NAMESPACE` is set by that factory only, so it is now set explicitly via `quarkus.kubernetes.env.fields.KUBERNETES_NAMESPACE=metadata.namespace`.
- The generated ClusterRole copies the Deployment labels at the moment it is created, before Quarkus adds its labels to the baseline. The baseline therefore carries `app.kubernetes.io/name` itself. The `app.kubernetes.io/version` label cannot be expressed in the baseline (no property interpolation), so the ClusterRole loses it. The Deployment already has no version label because of `quarkus.kubernetes.idempotent=true`, so this makes the labels consistent rather than breaking anything.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.