Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/test-helm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Helm Tests

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
helm-test:
name: Run on Ubuntu
runs-on: ubuntu-latest
steps:
- name: Clone the code
uses: actions/checkout@v4

- name: Install Helm
uses: azure/setup-helm@v4

- name: Lint the chart
run: make helm-lint

# Pre-installed because modern helm verifies plugin provenance by
# default and the unittest plugin publishes none; the Makefile's own
# bootstrap (helm plugin install without --verify=false) predates that
# and fails on a fresh runner. With the plugin present, make helm-test
# skips its bootstrap.
- name: Install helm-unittest plugin
run: helm plugin install https://github.com/helm-unittest/helm-unittest --verify=false

# Enforced here rather than developer-run only -- a green PR previously
# said nothing about the chart tests.
- name: Run chart unit tests
run: make helm-test
63 changes: 57 additions & 6 deletions helm/kmcp/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,41 @@ Allows overriding it for multi-namespace deployments in combined charts.
Create the image reference
*/}}
{{- define "kmcp.image" -}}
{{- $tag := .Values.image.tag | default .Chart.AppVersion | default "latest" }}
{{- printf "%s:%s" .Values.image.repository $tag }}
{{- $tag := .Values.image.tag | default .Chart.AppVersion | default "latest" -}}
{{/* image.repository used to be one string carrying its registry
(ghcr.io/kagent-dev/kmcp/controller). It is now the environment-invariant
path only, joined onto image.registry -- the same registry/repository split
every kagent-family chart uses, so one global.imageRegistry value redirects
them all. A values file still carrying a host in repository would render a
doubled path that fails only at pod start, as ImagePullBackOff, so it fails
the render here instead and names the split. */}}
{{- $first := first (splitList "/" .Values.image.repository) -}}
{{- if or (contains "." $first) (contains ":" $first) -}}
{{- fail (printf "image.repository (%q) carries a registry host. It is now the image path only: move the host into image.registry (or global.imageRegistry) and keep repository as the path, e.g. registry: ghcr.io, repository: kagent-dev/kmcp/controller." .Values.image.repository) -}}
{{- end -}}
{{- include "kmcp.images.image" (dict "imageRoot" (dict "registry" .Values.image.registry "repository" .Values.image.repository "tag" $tag) "global" .Values.global) -}}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The repository split changes the existing Helm fixtures from test-repo:v1.0.0 to ghcr.io/test-repo:v1.0.0, but this PR only migrates the Go e2e caller. helm unittest helm/kmcp passes all 48 tests on the merge base and fails 18 tests at this head, with 18 snapshot failures in the deployment and RBAC suites. Should we update those fixtures and their expected output, and add cases for the new registry/global behavior? Or, if a fixture is intended to keep an unqualified image, set image.registry: "" explicitly?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yep, you're right. Updated the fixtures AND added a CI job to run helm unit tests, this would have been more visible had we been running these tests in CI.

{{- end }}

{{/*
The resolved RBAC scope, as a JSON list so callers can range over it.
Precedence: rbac.namespaces > global.watchNamespaces > empty (cluster-scoped).
The global is a fallback, not an override: a values file that sets rbac.namespaces
renders exactly what it rendered before the global existed, and an explicit empty
list forces cluster-scoped RBAC (hasKey, not coalesce, so a present-but-empty key
wins). On the global path the install namespace is auto-appended: the global is a
shared signal a parent may aim at other charts, and failing this chart's render
over it would brick an install the value was never about.
*/}}
{{- define "kmcp.rbacNamespaces" -}}
{{- $scope := list -}}
{{- if and .Values.rbac (hasKey .Values.rbac "namespaces") -}}
{{- $scope = .Values.rbac.namespaces | default list -}}
{{- else if ((.Values.global).watchNamespaces) -}}
{{- $scope = concat (.Values.global).watchNamespaces (list (include "kmcp.namespace" .)) -}}
{{- end -}}
{{- $scope | uniq | sortAlpha | toJson -}}
{{- end -}}

{{/*
Guards on the rbac block
*/}}
Expand Down Expand Up @@ -98,9 +129,29 @@ Create controller manager container args
{{- if .Values.controller.metrics.enabled }}
{{- $args = append $args (printf "--metrics-bind-address=%s" .Values.controller.metrics.bindAddress) }}
{{- end }}
{{- if and .Values.rbac .Values.rbac.namespaces }}
{{- $namespaces := .Values.rbac.namespaces | uniq }}
{{- $args = append $args (printf "--watch-namespaces=%s" (join "," $namespaces)) }}
{{- $watchNs := include "kmcp.rbacNamespaces" . | fromJsonArray }}
{{- if $watchNs }}
{{- $args = append $args (printf "--watch-namespaces=%s" (join "," $watchNs)) }}
{{- end }}
{{- toYaml $args }}
{{- end }}
{{- end }}
{{/*
Pull secrets for the pod: the chart's own list merged (union) with
global.imagePullSecrets. Renders nothing when both are empty.
*/}}
{{- define "kmcp.imagePullSecrets" -}}
{{- $merged := concat (.Values.imagePullSecrets | default list) (((.Values.global).imagePullSecrets) | default list) | uniq -}}
{{- if $merged -}}
imagePullSecrets:
{{- toYaml $merged | nindent 2 }}
{{- end -}}
{{- end -}}

{{/*
imagePullPolicy for a container: the component's own value, then
global.imagePullPolicy, then IfNotPresent. One definition so the fallback chain
cannot drift between pods.
*/}}
{{- define "kmcp.imagePullPolicy" -}}
{{- .local | default (((.root.Values.global)).imagePullPolicy) | default "IfNotPresent" -}}
{{- end -}}
32 changes: 32 additions & 0 deletions helm/kmcp/templates/_images.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}

{{/* vim: set filetype=mustache: */}}
{{/*
Return the proper image name.
If image tag and digest are not defined, termination fallbacks to chart appVersion.
{{ include "kmcp.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global "chart" .Chart ) }}
*/}}
{{- define "kmcp.images.image" -}}
{{- $registryName := default .imageRoot.registry ((.global).imageRegistry) -}}
{{- $repositoryName := .imageRoot.repository -}}
{{- $separator := ":" -}}
{{- $termination := .imageRoot.tag | toString -}}

{{- if not .imageRoot.tag }}
{{- if .chart }}
{{- $termination = .chart.AppVersion | toString -}}
{{- end -}}
{{- end -}}
{{- if .imageRoot.digest }}
{{- $separator = "@" -}}
{{- $termination = .imageRoot.digest | toString -}}
{{- end -}}
{{- if $registryName }}
{{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}}
{{- else -}}
{{- printf "%s%s%s" $repositoryName $separator $termination -}}
{{- end -}}
{{- end -}}
7 changes: 2 additions & 5 deletions helm/kmcp/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,14 @@ spec:
labels:
{{- include "kmcp.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with include "kmcp.imagePullSecrets" . }}{{- . | nindent 6 }}{{- end }}
serviceAccountName: {{ include "kmcp.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: manager
image: {{ include "kmcp.image" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
imagePullPolicy: {{ include "kmcp.imagePullPolicy" (dict "root" . "local" .Values.image.pullPolicy) }}
command:
- /manager
args:
Expand Down
5 changes: 3 additions & 2 deletions helm/kmcp/templates/rbac/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@

{{- if .Values.rbac.create }}
{{- include "kmcp.rbac.validate" . -}}
{{- if .Values.rbac.namespaces }}
{{- range $namespace := (.Values.rbac.namespaces | uniq | sortAlpha) }}
{{- $rbacNamespaces := include "kmcp.rbacNamespaces" . | fromJsonArray }}
{{- if $rbacNamespaces }}
{{- range $namespace := $rbacNamespaces }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
Expand Down
5 changes: 3 additions & 2 deletions helm/kmcp/templates/rbac/clusterrolebinding.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{{- if .Values.rbac.create }}
{{- include "kmcp.rbac.validate" . -}}
{{- if .Values.rbac.namespaces }}
{{- range $namespace := (.Values.rbac.namespaces | uniq | sortAlpha) }}
{{- $rbacNamespaces := include "kmcp.rbacNamespaces" . | fromJsonArray }}
{{- if $rbacNamespaces }}
{{- range $namespace := $rbacNamespaces }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
Expand Down
24 changes: 12 additions & 12 deletions helm/kmcp/tests/__snapshot__/deployment_test.yaml.snap
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ should create deployment with default values:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -112,7 +112,7 @@ should include health probe ports when health probe enabled:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -190,7 +190,7 @@ should include image pull secrets when specified:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -270,7 +270,7 @@ should include metrics port when metrics enabled:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -348,7 +348,7 @@ should include node selector when specified:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -430,7 +430,7 @@ should include pod annotations when specified:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -508,7 +508,7 @@ should include tolerations when specified:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -591,7 +591,7 @@ should set custom replica count:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -669,7 +669,7 @@ should set custom resources:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -747,7 +747,7 @@ should set pod security context:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -825,7 +825,7 @@ should set security context:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -903,7 +903,7 @@ should set termination grace period:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down
12 changes: 6 additions & 6 deletions helm/kmcp/tests/__snapshot__/integration_test.yaml.snap
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ should create deployment when metrics enabled:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -112,7 +112,7 @@ should create deployment with default values:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -189,7 +189,7 @@ should create deployment with minimal configuration:
- --health-probe-bind-address=:8081
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -264,7 +264,7 @@ should include metrics port in deployment when metrics enabled:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -342,7 +342,7 @@ should use custom namespace:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down Expand Up @@ -420,7 +420,7 @@ should use custom release name:
- --metrics-bind-address=:8443
command:
- /manager
image: test-repo:v1.0.0
image: ghcr.io/test-repo:v1.0.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
Expand Down
Loading
Loading