Skip to content

fix(helm): support omitting image.registry in querydoc chart#2124

Merged
EItanya merged 2 commits into
kagent-dev:mainfrom
michaelspinks:fix/querydoc-image-empty-registry
Jul 1, 2026
Merged

fix(helm): support omitting image.registry in querydoc chart#2124
EItanya merged 2 commits into
kagent-dev:mainfrom
michaelspinks:fix/querydoc-image-empty-registry

Conversation

@michaelspinks

Copy link
Copy Markdown
Contributor

What

Make the querydoc (doc2vec) chart render a valid image reference when image.registry is left empty, so the registry can be omitted (e.g. to pull from Docker Hub or a mirror) without producing a leading-slash, unpullable reference.

Why

The image is built inline in templates/deployment.yaml:

image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"

The / between registry and repository is written unconditionally. If image.registry is set to "", the result has a leading slash and is not a valid image reference, so the pod enters ImagePullBackOff:

/kagent-dev/doc2vec/mcp:1.1.10     # invalid reference

There is currently no way to omit the registry and let the container runtime resolve the repository against its default registry / a configured mirror.

Omitting the registry is a configuration users legitimately need:

  • Docker Hub. A bare org/image reference resolves to Docker Hub, so users mirroring the image there want kagent-dev/doc2vec/mcp:tag, not ghcr.io/....
  • Air-gapped / mirrored environments. Registry mirrors are configured at the container runtime, which rewrites the host — so chart values should carry only repository:tag.
  • Registry rewriting. Admission controllers (e.g. Kyverno) prepend an internal registry, so users leave registry: "".
  • Consistency. Other charts let you omit the registry; querydoc silently breaks with ImagePullBackOff, which reads like a bug.

Note: this is a different issue from the bundled-PostgreSQL registry//name:tag
double-slash bug (#2120). That helper uses a 3-segment registry/repository/name:tag
shape; querydoc uses a 2-segment registry/repository:tag shape with no separate
image name, so the failure here is a leading slash from an empty registry, not a
double slash from an empty repository. They are fixed independently.

Fix

Introduce a querydoc.image helper (the chart currently has none) that builds the path from non-empty segments via compact + join, and call it from the deployment:

{{- define "querydoc.image" -}}
{{- $img := .Values.image -}}
{{- $parts := compact (list $img.registry $img.repository) -}}
{{- printf "%s:%s" (join "/" $parts) ($img.tag | default .Chart.AppVersion) -}}
{{- end -}}
# templates/deployment.yaml
image: "{{ include "querydoc.image" . }}"

Rendered results:

registry repository tag result
ghcr.io kagent-dev/doc2vec/mcp 1.1.10 ghcr.io/kagent-dev/doc2vec/mcp:1.1.10 (unchanged)
ghcr.io kagent-dev/doc2vec/mcp v2.0.0 ghcr.io/kagent-dev/doc2vec/mcp:v2.0.0 (unchanged)
"" kagent-dev/doc2vec/mcp 1.1.10 kagent-dev/doc2vec/mcp:1.1.10 (fixed)

Tests

Added one case to helm/tools/querydoc/tests/deployment_test.yaml for the empty-registry path (developed test-first). The existing "should have correct container image" and "should use custom image tag when set" tests already guard the default and custom-tag paths, so no regression test was duplicated.

  - it: should omit empty registry segment in image
    template: deployment.yaml
    set:
      image:
        registry: ""
    asserts:
      - equal:
          path: spec.template.spec.containers[0].image
          value: kagent-dev/doc2vec/mcp:1.1.10
      - notMatchRegex:
          path: spec.template.spec.containers[0].image
          pattern: "^/"

The test fails without this change (/kagent-dev/doc2vec/mcp:1.1.10) and passes with it — revert the deployment.yaml/_helpers.tpl hunks to reproduce.

How to verify

make helm-tools                                     # generate querydoc Chart.yaml
helm unittest helm/tools/querydoc                   # full suite green (incl. new case)
helm lint helm/tools/querydoc

# test-independent reproduction:
helm template t helm/tools/querydoc --set image.registry="" | grep image:
# before: /kagent-dev/doc2vec/mcp:1.1.10
# after:  kagent-dev/doc2vec/mcp:1.1.10

Scope

Limited to the querydoc chart's image construction. Empty repository is not made valid here, because the repository carries the full image path and there is no separate image-name segment — omitting it leaves no image to pull. This PR only makes
image.registry optional.

Checklist

  • Commit is DCO signed-off (git commit -s).
  • helm unittest helm/tools/querydoc green; helm lint helm/tools/querydoc clean.
  • Diff limited to templates/_helpers.tpl, templates/deployment.yaml, and
    tests/deployment_test.yaml (generated chart files excluded).
  • Test fails without the fix, passes with it.

Signed-off-by: Mike Spinks <mikespinks@gmail.com>
Copilot AI review requested due to automatic review settings July 1, 2026 09:12
@github-actions github-actions Bot added the bug Something isn't working label Jul 1, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the QueryDoc (doc2vec) Helm chart to render a valid container image reference when image.registry is empty, enabling users to omit the registry (e.g., Docker Hub/mirrors) without producing a leading-slash invalid image.

Changes:

  • Add a querydoc.image helper that builds the image path from non-empty segments via compact + join.
  • Switch templates/deployment.yaml to use the new helper for the container image.
  • Add a Helm unittest case verifying that an empty image.registry does not produce a leading slash.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
helm/tools/querydoc/templates/_helpers.tpl Adds querydoc.image helper to compose image references from optional segments.
helm/tools/querydoc/templates/deployment.yaml Uses querydoc.image helper for the Deployment container image field.
helm/tools/querydoc/tests/deployment_test.yaml Adds coverage for empty-registry image rendering (no leading slash).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread helm/tools/querydoc/templates/deployment.yaml Outdated
Signed-off-by: Mike Spinks <mikespinks@gmail.com>
EItanya pushed a commit that referenced this pull request Jul 1, 2026
## What

Make the grafana-mcp chart render a valid image reference when
`image.registry` is left empty, so the registry can be omitted (e.g. to
pull from a mirror or let the runtime resolve the default registry)
without producing a leading-slash, unpullable reference.

## Why

The image is built inline in `templates/deployment.yaml`:

```gotemplate
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}"
```

The `/` between registry and repository is written unconditionally. If
`image.registry` is set to `""`, the result has a leading slash and is
not a valid image reference, so the pod enters `ImagePullBackOff`:

```
/grafana:latest     # invalid reference
```

There is currently no way to omit the registry and let the container
runtime resolve the repository against its default registry / a
configured mirror.

Omitting the registry is a configuration users legitimately need:

- **Air-gapped / mirrored environments.** Registry mirrors are
configured at the container runtime, which rewrites the host — so chart
values should carry only `repository:tag`.
- **Registry rewriting.** Admission controllers (e.g. Kyverno) prepend
an internal registry, so users leave `registry: ""`.
- **Consistency.** Other charts let you omit the registry; grafana-mcp
silently breaks with `ImagePullBackOff`, which reads like a bug.

> Note: the default `registry: mcp` is intentional and unchanged —
`mcp/grafana` resolves to `docker.io/mcp/grafana` (Docker Hub's `mcp`
namespace). This PR only makes an *empty* registry valid; the default
path still renders `mcp/grafana:latest`.
> This is the same 2-segment `registry/repository:tag` leading-slash
shape as the querydoc chart (#2124), and distinct from the
bundled-PostgreSQL `registry//name:tag` double-slash bug (#2120), which
uses a 3-segment shape. All fixed independently.

## Fix

Introduce a `grafana-mcp.image` helper (the chart currently has none)
that builds the path from non-empty segments via `compact` + `join`, and
call it from the deployment:

```gotemplate
{{- define "grafana-mcp.image" -}}
{{- $img := .Values.image -}}
{{- $parts := compact (list $img.registry $img.repository) -}}
{{- printf "%s:%s" (join "/" $parts) $img.tag -}}
{{- end -}}
```

```gotemplate
# templates/deployment.yaml
image: "{{ include "grafana-mcp.image" . }}"
```

Rendered results:

| registry | repository | tag | result |
|---|---|---|---|
| `mcp` | `grafana` | `latest` | `mcp/grafana:latest` (unchanged) |
| `""` | `grafana` | `latest` | `grafana:latest` (fixed) |

## Tests

Added two cases to `helm/tools/grafana-mcp/tests/deployment_test.yaml`
(developed test-first): a default-image regression guard (the suite had
no image assertion), and the empty-registry path.

```yaml
  - it: should render the default container image
    template: deployment.yaml
    asserts:
      - equal:
          path: spec.template.spec.containers[0].image
          value: mcp/grafana:latest

  - it: should omit empty registry segment in image
    template: deployment.yaml
    set:
      image:
        registry: ""
    asserts:
      - equal:
          path: spec.template.spec.containers[0].image
          value: grafana:latest
      - notMatchRegex:
          path: spec.template.spec.containers[0].image
          pattern: "^/"
```

The empty-registry test fails without this change (`/grafana:latest`)
and passes with it — revert the `deployment.yaml`/`_helpers.tpl` hunks
to reproduce.

## How to verify

```bash
make helm-tools                                       # generate grafana-mcp Chart.yaml
helm unittest helm/tools/grafana-mcp                  # full suite green (incl. new cases)
helm lint helm/tools/grafana-mcp

# test-independent reproduction:
helm template t helm/tools/grafana-mcp --set image.registry="" | grep image:
# before: /grafana:latest
# after:  grafana:latest
```

## Scope

Limited to the grafana-mcp chart's image construction. Empty
`repository` is not made valid here — omitting it leaves no image to
pull. This PR only makes `image.registry` optional.

## Checklist

- [x] Commit is DCO signed-off (`git commit -s`).
- [x] `helm unittest helm/tools/grafana-mcp` green; `helm lint
helm/tools/grafana-mcp` clean.
- [x] Default image still renders `mcp/grafana:latest` (regression
guard).
- [x] Diff limited to `templates/_helpers.tpl`,
`templates/deployment.yaml`, and `tests/deployment_test.yaml` (generated
chart files excluded).
- [x] Test fails without the fix, passes with it.

Signed-off-by: Mike Spinks <mikespinks@gmail.com>
@EItanya EItanya merged commit 13fb436 into kagent-dev:main Jul 1, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants