-
Notifications
You must be signed in to change notification settings - Fork 120
kind: replace the mesh-config node templating with a sam-node Helm chart #366
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
2565d52
charts: add sam-node chart for deploying a node with an optional serv…
kaisoz d25ee42
examples: replace sam-node-config.yaml with charts/sam-node values files
kaisoz fe43d8d
kind: deploy sam infrastructure only, drop the mesh-config node templ…
kaisoz de88f4a
e2e: deploy calc-mcp through charts/sam-node
kaisoz 087eef9
docs: kind mesh deploys infra only; services ship via charts/sam-node
kaisoz daa517d
kind, charts: guard the e2e helm fallback and fix the README config w…
kaisoz 3eeca72
examples: migrate chat-a2a to the charts/sam-node flow
kaisoz 341f77f
kind: add deploy-kind-example.sh wrapping the example deploy commands
kaisoz 796bca8
kind: deploy-kind-service.sh takes any service directory, moves to de…
kaisoz a818382
kind: deploy-kind-service.sh takes a plain directory path only
kaisoz 5ffef1d
kind: RELEASE env override lets deploy-kind-service.sh deploy one dir…
kaisoz 420855f
kind: replace the RELEASE env with a --release-name flag
kaisoz b1b8442
kind: run the local node with a throwaway data-dir so stale identitie…
kaisoz 41a7a91
kind: keep sam-nodes off the router worker; same-node hostPort dials …
kaisoz fec638e
charts: trim the sam-node README
kaisoz 271a0fd
charts: make the sam-node ServiceAccount optional and annotatable
kaisoz 05684f4
kind: wait on the deployment by label so release names containing sam…
kaisoz c086f18
kind: guard the throwaway data-dir removal
kaisoz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| apiVersion: v2 | ||
| name: sam-node | ||
| description: A Helm chart for deploying a SAM node, optionally hosting a service as a sidecar | ||
| type: application | ||
| version: 0.1.0 | ||
| appVersion: "1.0.0" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # sam-node | ||
|
|
||
| Deploys one SAM node into a Kubernetes cluster, optionally hosting a service | ||
| as a sidecar container. The node authenticates to the control plane with a | ||
| projected ServiceAccount token (Workload Identity Federation); the token's | ||
| `audience` must be listed in the control plane's `allowedAudiences`. | ||
|
|
||
| ## Usage | ||
|
|
||
| A bare node (a caller / mesh participant with no local service): | ||
|
|
||
| ```bash | ||
| helm install my-node charts/sam-node \ | ||
| --set controlPlaneUrl=http://sam-mesh-control-plane:8080 | ||
| ``` | ||
|
|
||
| A node hosting an MCP service (see `development/examples/*/values.yaml` for | ||
| complete, working examples): | ||
|
|
||
| ```yaml | ||
| controlPlaneUrl: http://sam-mesh-control-plane:8080 | ||
| config: | ||
| version: v1alpha1 | ||
| services: | ||
| - type: mcp | ||
| name: calculator | ||
| description: Simple math operations | ||
| target_url: http://127.0.0.1:7777/mcp | ||
| service: | ||
| name: calc-mcp | ||
| image: calc-mcp:local | ||
| ``` | ||
|
|
||
| ## Values | ||
|
|
||
| | Key | Default | Meaning | | ||
| |-----|---------|---------| | ||
| | `controlPlaneUrl` | — (required) | Control plane URL the node enrolls with | | ||
| | `audience` | `sam-mesh-audience` | Projected token audience | | ||
| | `apiToken` | `devtoken` | Bearer token for the node's local REST API | | ||
| | `bindAddr` | `127.0.0.1:8080` | Node API bind address (loopback = pod-private) | | ||
| | `extraArgs` | `[]` | Extra sam-node args | | ||
| | `config` | empty services | Merged over the chart's defaults and rendered as `sam-node.yaml`; pods roll on config changes | | ||
| | `service.image` | `""` | Service container image; empty = bare node | | ||
| | `service.name/command/env/ports/resources` | — | Service container spec | | ||
| | `serviceAccount.create/name/annotations` | `true` / fullname / `{}` | Skip creation, reuse an existing SA, or annotate it (e.g. Workload Identity) | | ||
| | `image.repository/tag/pullPolicy` | `sam-node:local` | Node image | | ||
| | `replicaCount` | `1` | Each replica enrolls as its own mesh node | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| {{/* | ||
| Expand the name of the chart. | ||
| */}} | ||
| {{- define "sam-node.name" -}} | ||
| {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} | ||
| {{- end }} | ||
|
|
||
| {{/* | ||
| Create a default fully qualified app name, truncated to the 63-char DNS limit. | ||
| */}} | ||
| {{- define "sam-node.fullname" -}} | ||
| {{- if .Values.fullnameOverride }} | ||
| {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} | ||
| {{- else }} | ||
| {{- $name := default .Chart.Name .Values.nameOverride }} | ||
| {{- if contains $name .Release.Name }} | ||
| {{- .Release.Name | trunc 63 | trimSuffix "-" }} | ||
| {{- else }} | ||
| {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} | ||
| {{- end }} | ||
| {{- end }} | ||
| {{- end }} | ||
|
|
||
| {{/* | ||
| Create chart name and version as used by the chart label. | ||
| */}} | ||
| {{- define "sam-node.chart" -}} | ||
| {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} | ||
| {{- end }} | ||
|
|
||
| {{/* | ||
| Common labels | ||
| */}} | ||
| {{- define "sam-node.labels" -}} | ||
| helm.sh/chart: {{ include "sam-node.chart" . }} | ||
| {{ include "sam-node.selectorLabels" . }} | ||
| {{- if .Chart.AppVersion }} | ||
| app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} | ||
| {{- end }} | ||
| app.kubernetes.io/managed-by: {{ .Release.Service }} | ||
| {{- end }} | ||
|
|
||
| {{/* | ||
| Selector labels | ||
| */}} | ||
| {{- define "sam-node.selectorLabels" -}} | ||
| app.kubernetes.io/name: {{ include "sam-node.name" . }} | ||
| app.kubernetes.io/instance: {{ .Release.Name }} | ||
| {{- end }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| apiVersion: v1 | ||
| kind: ConfigMap | ||
| metadata: | ||
| name: {{ include "sam-node.fullname" . }}-config | ||
| labels: | ||
| {{- include "sam-node.labels" . | nindent 4 }} | ||
| data: | ||
| sam-node.yaml: | | ||
| {{- .Values.config | toYaml | nindent 4 }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| apiVersion: apps/v1 | ||
| kind: Deployment | ||
| metadata: | ||
| name: {{ include "sam-node.fullname" . }} | ||
| labels: | ||
| {{- include "sam-node.labels" . | nindent 4 }} | ||
| spec: | ||
| replicas: {{ .Values.replicaCount }} | ||
| selector: | ||
| matchLabels: | ||
| {{- include "sam-node.selectorLabels" . | nindent 6 }} | ||
| template: | ||
| metadata: | ||
| labels: | ||
| {{- include "sam-node.selectorLabels" . | nindent 8 }} | ||
| annotations: | ||
| # A config-only change must roll the pods: the node reads its config | ||
| # file once at startup and never reloads it. | ||
| checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} | ||
| spec: | ||
| serviceAccountName: {{ default (include "sam-node.fullname" .) .Values.serviceAccount.name }} | ||
| containers: | ||
| - name: sam-node | ||
| image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" | ||
| imagePullPolicy: {{ .Values.image.pullPolicy }} | ||
| env: | ||
| - name: SAM_API_TOKEN | ||
| value: {{ .Values.apiToken | quote }} | ||
| args: | ||
| - "run" | ||
| - "--config=/etc/sam/sam-node.yaml" | ||
| - "--control-plane={{ required "controlPlaneUrl is required" .Values.controlPlaneUrl }}" | ||
| - "--jwt-path=/var/run/secrets/tokens/sam-token" | ||
| - "--bind-addr={{ .Values.bindAddr }}" | ||
| {{- range .Values.extraArgs }} | ||
| - {{ . | quote }} | ||
| {{- end }} | ||
| {{- with .Values.resources }} | ||
| resources: | ||
| {{- toYaml . | nindent 12 }} | ||
| {{- end }} | ||
| volumeMounts: | ||
| - name: config | ||
| mountPath: /etc/sam | ||
| - name: sam-token | ||
| mountPath: /var/run/secrets/tokens | ||
| readOnly: true | ||
| {{- if .Values.service.image }} | ||
| - name: {{ .Values.service.name }} | ||
| image: {{ .Values.service.image | quote }} | ||
| imagePullPolicy: {{ .Values.image.pullPolicy }} | ||
| {{- with .Values.service.command }} | ||
| command: | ||
| {{- toYaml . | nindent 12 }} | ||
| {{- end }} | ||
| {{- with .Values.service.env }} | ||
| env: | ||
| {{- toYaml . | nindent 12 }} | ||
| {{- end }} | ||
| {{- with .Values.service.ports }} | ||
| ports: | ||
| {{- toYaml . | nindent 12 }} | ||
| {{- end }} | ||
| {{- with .Values.service.resources }} | ||
| resources: | ||
| {{- toYaml . | nindent 12 }} | ||
| {{- end }} | ||
| {{- end }} | ||
| {{- with .Values.nodeSelector }} | ||
| nodeSelector: | ||
| {{- toYaml . | nindent 8 }} | ||
| {{- end }} | ||
| {{- with .Values.tolerations }} | ||
| tolerations: | ||
| {{- toYaml . | nindent 8 }} | ||
| {{- end }} | ||
| {{- with .Values.affinity }} | ||
| affinity: | ||
| {{- toYaml . | nindent 8 }} | ||
| {{- end }} | ||
| volumes: | ||
| - name: config | ||
| configMap: | ||
| name: {{ include "sam-node.fullname" . }}-config | ||
| - name: sam-token | ||
| projected: | ||
| sources: | ||
| - serviceAccountToken: | ||
| path: sam-token | ||
| expirationSeconds: 3600 | ||
| audience: {{ .Values.audience | quote }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| {{- if .Values.serviceAccount.create -}} | ||
| apiVersion: v1 | ||
| kind: ServiceAccount | ||
| metadata: | ||
| name: {{ default (include "sam-node.fullname" .) .Values.serviceAccount.name }} | ||
| labels: | ||
| {{- include "sam-node.labels" . | nindent 4 }} | ||
| {{- with .Values.serviceAccount.annotations }} | ||
| annotations: | ||
| {{- toYaml . | nindent 4 }} | ||
| {{- end }} | ||
| {{- end }} | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| suite: sam-node deployment | ||
| templates: | ||
| # configmap.yaml must be loaded for the checksum/config include to resolve | ||
| - templates/deployment.yaml | ||
| - templates/configmap.yaml | ||
| tests: | ||
| - it: fails without controlPlaneUrl | ||
| template: templates/deployment.yaml | ||
| asserts: | ||
| - failedTemplate: {} | ||
|
|
||
| - it: renders a bare node with one container | ||
| template: templates/deployment.yaml | ||
| set: | ||
| controlPlaneUrl: http://sam-mesh-control-plane:8080 | ||
| asserts: | ||
| - equal: | ||
| path: spec.template.spec.containers[0].name | ||
| value: sam-node | ||
| - lengthEqual: | ||
| path: spec.template.spec.containers | ||
| count: 1 | ||
| - contains: | ||
| path: spec.template.spec.containers[0].args | ||
| content: "--control-plane=http://sam-mesh-control-plane:8080" | ||
| - contains: | ||
| path: spec.template.spec.containers[0].args | ||
| content: "--bind-addr=127.0.0.1:8080" | ||
|
aojea marked this conversation as resolved.
|
||
| - equal: | ||
| path: spec.template.spec.volumes[1].projected.sources[0].serviceAccountToken.audience | ||
| value: sam-mesh-audience | ||
|
|
||
| - it: renders the service container when service.image is set | ||
| template: templates/deployment.yaml | ||
| set: | ||
| controlPlaneUrl: http://sam-mesh-control-plane:8080 | ||
| service: | ||
| name: calc-mcp | ||
| image: calc-mcp:local | ||
| asserts: | ||
| - lengthEqual: | ||
| path: spec.template.spec.containers | ||
| count: 2 | ||
| - equal: | ||
| path: spec.template.spec.containers[1].name | ||
| value: calc-mcp | ||
| - equal: | ||
| path: spec.template.spec.containers[1].image | ||
| value: calc-mcp:local | ||
|
|
||
| - it: appends extraArgs | ||
| template: templates/deployment.yaml | ||
| set: | ||
| controlPlaneUrl: http://sam-mesh-control-plane:8080 | ||
| extraArgs: ["--discovery-interval=200ms"] | ||
| asserts: | ||
| - contains: | ||
| path: spec.template.spec.containers[0].args | ||
| content: "--discovery-interval=200ms" | ||
|
|
||
| - it: honors serviceAccount.name for the pod | ||
| template: templates/deployment.yaml | ||
| set: | ||
| controlPlaneUrl: http://sam-mesh-control-plane:8080 | ||
| serviceAccount: | ||
| create: false | ||
| name: existing-sa | ||
| asserts: | ||
| - equal: | ||
| path: spec.template.spec.serviceAccountName | ||
| value: existing-sa | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| image: | ||
| repository: sam-node | ||
| tag: local | ||
| pullPolicy: IfNotPresent | ||
|
|
||
| replicaCount: 1 | ||
|
|
||
| # Required: control plane URL the node enrolls with, | ||
| # e.g. http://sam-mesh-control-plane:8080 | ||
| controlPlaneUrl: "" | ||
|
|
||
| # Audience of the projected ServiceAccount token; must be one of the control | ||
| # plane's allowedAudiences. | ||
| audience: sam-mesh-audience | ||
|
|
||
| # Bearer token protecting the node's local REST API. | ||
| apiToken: devtoken | ||
|
|
||
| # Address the node API binds inside the pod. Loopback keeps the API | ||
| # pod-private; set 0.0.0.0:8080 to expose it on the pod IP. | ||
| bindAddr: "127.0.0.1:8080" | ||
|
|
||
| # Extra sam-node args, e.g. ["--discovery-interval=200ms"]. | ||
| extraArgs: [] | ||
|
|
||
| # Rendered verbatim as the node's sam-node.yaml: static services the node | ||
| # advertises, and local attenuation. | ||
| config: | ||
| version: v1alpha1 | ||
| attenuation: | ||
| policies: [] | ||
| checks: [] | ||
| rules: [] | ||
| services: [] | ||
|
|
||
| # Optional service container next to the node; they share localhost, so | ||
| # config.services target_url entries point at 127.0.0.1:<port>. | ||
| # Rendered only when image is non-empty. | ||
| service: | ||
| name: service | ||
| image: "" | ||
| command: [] | ||
| env: [] | ||
| ports: [] | ||
| resources: {} | ||
|
|
||
| # Set create: false and name to reuse an existing ServiceAccount; annotations | ||
| # cover IAM bindings (e.g. GKE Workload Identity). | ||
| serviceAccount: | ||
| create: true | ||
| name: "" | ||
| annotations: {} | ||
|
|
||
| resources: {} | ||
|
kaisoz marked this conversation as resolved.
|
||
| nodeSelector: {} | ||
| tolerations: [] | ||
| affinity: {} | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make the Helm chart production-ready and flexible for cloud environments (where ServiceAccounts often require specific annotations for IAM/Workload Identity mapping, or where users might want to reuse an existing ServiceAccount), it is highly recommended to make the ServiceAccount creation optional and support custom annotations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done