Skip to content

feat(chart): add imagePullSecrets support at per-agent and global level #910

@antigenius0910

Description

@antigenius0910

Description

The openab Helm chart currently has no way to specify imagePullSecrets on the agent Deployment. Operators pulling agent images from a private registry have no chart-managed mechanism to attach a kubernetes.io/dockerconfigjson secret to the pod spec.

In a multi-agent deployment this is awkward in either direction:

  • A chart-global $.Values.imagePullSecrets forces every pod to carry credentials it doesn't need (e.g. an agent pulling the public ghcr.io/openabdev/openab-claude image shouldn't have to reference a private-registry secret).
  • No support at all means operators have to patch the Deployment out-of-band after every helm upgrade.

Use Case

We run openab on EKS with two agents:

  • Agent A uses the public image ghcr.io/openabdev/openab-claude:0.8.3 — no pull secret needed.
  • Agent B uses a custom image at cr.dmnr.io/openab-claude-ops:latest extending openab-claude:0.8.3 with kubectl and aws CLI baked in for an on-call bot use case. This image lives in a private registry and requires a pull secret.

Our cluster's IDP provisions a kubernetes.io/dockerconfigjson secret (regcred) into each workload namespace via Terraform. We want to reference that existing secret from the chart, per-agent.

Current workaround (fragile — wiped on every helm upgrade)

kubectl patch deployment <release>-<agentKey> -n <namespace> \
  --type=json \
  -p='[{"op":"add","path":"/spec/template/spec/imagePullSecrets","value":[{"name":"regcred"}]}]'

CI/Spacelift re-runs helm upgrade and the patch disappears, breaking image pulls until someone re-patches.

Proposed Solution

Add imagePullSecrets at per-agent level with optional chart-global fallback, matching the existing per-agent image: override pattern.

values.yaml:

# Global fallback — used when an agent doesn't set its own imagePullSecrets
imagePullSecrets: []

agents:
  claude:
    image: "ghcr.io/openabdev/openab-claude:0.8.3"
    # inherits global imagePullSecrets: [] → no pull secret rendered

  custom-bot:
    image: "cr.dmnr.io/openab-claude-ops:latest"
    imagePullSecrets:
      - name: regcred

templates/deployment.yaml (after securityContext, before initContainers):

      {{- with $.Values.podSecurityContext }}
      securityContext:
        {{- toYaml . | nindent 8 }}
      {{- end }}
+     {{- with (default $.Values.imagePullSecrets $cfg.imagePullSecrets) }}
+     imagePullSecrets:
+       {{- toYaml . | nindent 8 }}
+     {{- end }}
      {{- with $cfg.extraInitContainers }}

Per-agent value wins when set; otherwise falls back to chart-global. Both empty = no imagePullSecrets rendered (current behaviour preserved, zero impact on existing users).

Why not ServiceAccount imagePullSecrets?

The chart doesn't create a serviceAccountName-bound SA per agent, so operators can't reliably attach pull secrets to the right SA without touching cluster state outside the chart. Keeping the value in the chart makes it explicit, per-agent, and chart-managed.

Prior art in this chart

PR #901 (feat(openab): add existingSecret support for Slack agent credentials, merged 2026-05-22) follows the same per-agent K8s-native secrets pattern. This request is the equivalent for image pull credentials.


Happy to send a PR if the direction is agreed.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions