Skip to content

Commit aee7c8c

Browse files
fix(helm): support omitting image.registry in grafana-mcp chart (#2125)
## 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>
1 parent 841e807 commit aee7c8c

3 files changed

Lines changed: 30 additions & 1 deletion

File tree

helm/tools/grafana-mcp/templates/_helpers.tpl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,12 @@ Create the grafana server URL
6767
{{- define "grafana-mcp.serverUrl" -}}
6868
{{- printf "http://%s.%s:%d/mcp" (include "grafana-mcp.fullname" .) .Release.Namespace (.Values.service.port | int) }}
6969
{{- end }}
70+
71+
{{/*
72+
Join registry/repository for grafana-mcp image, skipping empty segments, then append tag
73+
*/}}
74+
{{- define "grafana-mcp.image" -}}
75+
{{- $img := .Values.image -}}
76+
{{- $parts := compact (list $img.registry $img.repository) -}}
77+
{{- printf "%s:%s" (join "/" $parts) $img.tag -}}
78+
{{- end -}}

helm/tools/grafana-mcp/templates/deployment.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ spec:
3535
- name: grafana-mcp
3636
securityContext:
3737
{{- toYaml .Values.securityContext | nindent 12 }}
38-
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}"
38+
image: {{ include "grafana-mcp.image" . }}
3939
imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }}
4040
args:
4141
- --transport

helm/tools/grafana-mcp/tests/deployment_test.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,23 @@ tests:
100100
- equal:
101101
path: spec.template.spec.containers[0].securityContext.runAsUser
102102
value: 1000
103+
104+
- it: should render the default container image
105+
template: deployment.yaml
106+
asserts:
107+
- equal:
108+
path: spec.template.spec.containers[0].image
109+
value: mcp/grafana:latest
110+
111+
- it: should omit empty registry segment in image
112+
template: deployment.yaml
113+
set:
114+
image:
115+
registry: ""
116+
asserts:
117+
- equal:
118+
path: spec.template.spec.containers[0].image
119+
value: grafana:latest
120+
- notMatchRegex:
121+
path: spec.template.spec.containers[0].image
122+
pattern: "^/" # no leading slash

0 commit comments

Comments
 (0)