From f1ae87fba9de1f40f62e516997e5c5396f587f4e Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Wed, 5 Nov 2025 22:36:09 +0300 Subject: [PATCH 1/2] feat(gateway-api): add HTTPRoute support Add support for Kubernetes Gateway API HTTPRoute resource as a modern alternative to Ingress. The implementation follows the same pattern as the existing Ingress template. Changes: - Add HTTPRoute template with configurable parentRefs, hostnames, and rules - Add httpRoute section to values.yaml with generic examples - Update Chart version from 2.5.0 to 2.6.0 - Add Artifact Hub changelog annotation - Add HTTPRoute documentation to README Co-Authored-By: Claude Signed-off-by: Aleksei Sviridkin --- charts/jellyfin/Chart.yaml | 6 ++++- charts/jellyfin/README.md | 33 +++++++++++++++++++++++- charts/jellyfin/README.md.gotmpl | 27 +++++++++++++++++++ charts/jellyfin/templates/httproute.yaml | 33 ++++++++++++++++++++++++ charts/jellyfin/values.yaml | 19 ++++++++++++++ 5 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 charts/jellyfin/templates/httproute.yaml diff --git a/charts/jellyfin/Chart.yaml b/charts/jellyfin/Chart.yaml index 96a351b..8c9328f 100644 --- a/charts/jellyfin/Chart.yaml +++ b/charts/jellyfin/Chart.yaml @@ -8,5 +8,9 @@ keywords: - jellyfin - media - self-hosted -version: 2.5.0 +version: 2.6.0 appVersion: 10.11.2 +annotations: + artifacthub.io/changes: | + - kind: added + description: Add support for Gateway API HTTPRoute resource diff --git a/charts/jellyfin/README.md b/charts/jellyfin/README.md index 10952b6..ff6e753 100644 --- a/charts/jellyfin/README.md +++ b/charts/jellyfin/README.md @@ -1,6 +1,6 @@ # jellyfin -![Version: 2.5.0](https://img.shields.io/badge/Version-2.5.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 10.11.2](https://img.shields.io/badge/AppVersion-10.11.2-informational?style=flat-square) +![Version: 2.6.0](https://img.shields.io/badge/Version-2.6.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 10.11.2](https://img.shields.io/badge/AppVersion-10.11.2-informational?style=flat-square) A Helm chart for Jellyfin Media Server @@ -60,6 +60,10 @@ helm install my-jellyfin jellyfin/jellyfin -f values.yaml | extraContainers | list | `[]` | additional sidecar containers to run inside the pod. | | extraInitContainers | list | `[]` | additional init containers to run inside the pod. | | fullnameOverride | string | `""` | Override the default full name of the chart. | +| httpRoute | object | `{"annotations":{},"enabled":false,"hostnames":[],"parentRefs":[],"rules":[{"matches":[{"path":{"type":"PathPrefix","value":"/"}}]}]}` | HTTPRoute configuration for Gateway API. See: https://gateway-api.sigs.k8s.io/ | +| httpRoute.hostnames | list | `[]` | Hostnames to match for this HTTPRoute | +| httpRoute.parentRefs | list | `[]` | Gateway references to attach this HTTPRoute to | +| httpRoute.rules | list | `[{"matches":[{"path":{"type":"PathPrefix","value":"/"}}]}]` | Rules for routing traffic | | image.pullPolicy | string | `"IfNotPresent"` | Image pull policy (Always, IfNotPresent, or Never). | | image.repository | string | `"docker.io/jellyfin/jellyfin"` | Container image repository for Jellyfin. | | image.tag | string | `""` | Jellyfin container image tag. Leave empty to automatically use the Chart's app version. | @@ -134,6 +138,33 @@ helm install my-jellyfin jellyfin/jellyfin -f values.yaml ---------------------------------------------- Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) +## Gateway API HTTPRoute + +This chart supports the Kubernetes Gateway API HTTPRoute resource as a modern alternative to Ingress. + +To use HTTPRoute, you need to have Gateway API CRDs installed in your cluster and a Gateway resource configured. + +Example configuration: + +```yaml +httpRoute: + enabled: true + annotations: {} + parentRefs: + - name: my-gateway + namespace: gateway-system + sectionName: https + hostnames: + - jellyfin.example.com + rules: + - matches: + - path: + type: PathPrefix + value: / +``` + +For more information about Gateway API, see: + ## Hardware acceleration Out of the box the pod does not have the necessary permissions to enable hardware acceleration (HWA) in Jellyfin. diff --git a/charts/jellyfin/README.md.gotmpl b/charts/jellyfin/README.md.gotmpl index ee08a35..bbcd888 100644 --- a/charts/jellyfin/README.md.gotmpl +++ b/charts/jellyfin/README.md.gotmpl @@ -59,6 +59,33 @@ helm install my-jellyfin jellyfin/jellyfin -f values.yaml {{ template "helm-docs.versionFooter" . }} +## Gateway API HTTPRoute + +This chart supports the Kubernetes Gateway API HTTPRoute resource as a modern alternative to Ingress. + +To use HTTPRoute, you need to have Gateway API CRDs installed in your cluster and a Gateway resource configured. + +Example configuration: + +```yaml +httpRoute: + enabled: true + annotations: {} + parentRefs: + - name: my-gateway + namespace: gateway-system + sectionName: https + hostnames: + - jellyfin.example.com + rules: + - matches: + - path: + type: PathPrefix + value: / +``` + +For more information about Gateway API, see: + ## Hardware acceleration Out of the box the pod does not have the necessary permissions to enable hardware acceleration (HWA) in Jellyfin. diff --git a/charts/jellyfin/templates/httproute.yaml b/charts/jellyfin/templates/httproute.yaml new file mode 100644 index 0000000..c701451 --- /dev/null +++ b/charts/jellyfin/templates/httproute.yaml @@ -0,0 +1,33 @@ +{{- if .Values.httpRoute.enabled }} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ include "jellyfin.fullname" . }} + labels: + {{- include "jellyfin.labels" . | nindent 4 }} + {{- with .Values.httpRoute.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.httpRoute.parentRefs }} + parentRefs: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.httpRoute.hostnames }} + hostnames: + {{- toYaml . | nindent 4 }} + {{- end }} + rules: + {{- range .Values.httpRoute.rules }} + - matches: + {{- range .matches }} + - path: + type: {{ .path.type }} + value: {{ .path.value }} + {{- end }} + backendRefs: + - name: {{ include "jellyfin.fullname" $ }} + port: {{ $.Values.service.port }} + {{- end }} +{{- end }} diff --git a/charts/jellyfin/values.yaml b/charts/jellyfin/values.yaml index 068c0ef..0ae375c 100644 --- a/charts/jellyfin/values.yaml +++ b/charts/jellyfin/values.yaml @@ -124,6 +124,25 @@ ingress: # hosts: # - chart-example.local +# -- HTTPRoute configuration for Gateway API. See: https://gateway-api.sigs.k8s.io/ +httpRoute: + enabled: false + annotations: {} + # -- Gateway references to attach this HTTPRoute to + parentRefs: [] + # - name: my-gateway + # namespace: gateway-system + # sectionName: https + # -- Hostnames to match for this HTTPRoute + hostnames: [] + # - jellyfin.example.com + # -- Rules for routing traffic + rules: + - matches: + - path: + type: PathPrefix + value: / + # -- Resource requests and limits for the Jellyfin container. resources: {} # limits: From 77241b18b50b901fef2c03d6b484ce8bee23f2f5 Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Fri, 7 Nov 2025 19:48:09 +0300 Subject: [PATCH 2/2] test(httproute): add comprehensive unit tests and deployment notes Add helm-unittest test suite for HTTPRoute (Gateway API) covering: - Not created by default (enabled: false) - Created when enabled with required configuration - Annotations support - parentRefs configuration (name, namespace, sectionName) - Hostnames support (single and multiple) - Path matching rules (PathPrefix, Exact) - Multiple rules and multiple matches per rule - Backend references to Jellyfin service - Custom service port handling Add NOTES.txt with HTTPRoute-specific deployment information: - Gateway references and configuration status - Configured hostnames - Number of routes - Backend service details - Access URLs when hostnames configured - Warnings for missing parentRefs Tests ensure HTTPRoute works correctly across all Gateway API scenarios. Co-Authored-By: Claude Signed-off-by: Aleksei Sviridkin --- charts/jellyfin/templates/NOTES.txt | 53 ++++++ charts/jellyfin/tests/httproute_test.yaml | 193 ++++++++++++++++++++++ 2 files changed, 246 insertions(+) create mode 100644 charts/jellyfin/templates/NOTES.txt create mode 100644 charts/jellyfin/tests/httproute_test.yaml diff --git a/charts/jellyfin/templates/NOTES.txt b/charts/jellyfin/templates/NOTES.txt new file mode 100644 index 0000000..3206486 --- /dev/null +++ b/charts/jellyfin/templates/NOTES.txt @@ -0,0 +1,53 @@ +Thank you for installing {{ .Chart.Name }}. + +Your release is named {{ .Release.Name }}. + +To learn more about the release, try: + + $ helm status {{ .Release.Name }} + $ helm get all {{ .Release.Name }} + +{{- if .Values.httpRoute.enabled }} + +HTTPRoute (Gateway API) is ENABLED: +{{- if .Values.httpRoute.parentRefs }} + Gateway References: + {{- range .Values.httpRoute.parentRefs }} + - {{ .name }}{{ if .namespace }} (namespace: {{ .namespace }}){{ end }}{{ if .sectionName }} [{{ .sectionName }}]{{ end }} + {{- end }} +{{- else }} + ⚠ WARNING: No parentRefs defined - HTTPRoute will not attach to any Gateway! +{{- end }} +{{- if .Values.httpRoute.hostnames }} + Hostnames: + {{- range .Values.httpRoute.hostnames }} + - {{ . }} + {{- end }} +{{- end }} + Rules: {{ len .Values.httpRoute.rules }} route(s) configured + Backend: {{ include "jellyfin.fullname" . }}:{{ .Values.service.port }} + +Access Jellyfin via Gateway API at: +{{- if .Values.httpRoute.hostnames }} +{{- range .Values.httpRoute.hostnames }} + https://{{ . }}{{ (index $.Values.httpRoute.rules 0).matches 0 .path.value }} +{{- end }} +{{- else }} + (Configure httpRoute.hostnames for external access) +{{- end }} + +Note: Ensure your Gateway API CRDs are installed and Gateway is configured. +{{- else if .Values.ingress.enabled }} + +Jellyfin is available via Ingress at: +{{- range .Values.ingress.hosts }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ .host }}{{ (index .paths 0).path }} +{{- end }} +{{- else }} + +To access Jellyfin, you can use port-forwarding: + + $ kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ include "jellyfin.fullname" . }} {{ .Values.service.port }}:{{ .Values.service.port }} + +Then visit http://localhost:{{ .Values.service.port }} in your browser. +{{- end }} diff --git a/charts/jellyfin/tests/httproute_test.yaml b/charts/jellyfin/tests/httproute_test.yaml new file mode 100644 index 0000000..7ee0ab4 --- /dev/null +++ b/charts/jellyfin/tests/httproute_test.yaml @@ -0,0 +1,193 @@ +suite: test httproute +templates: + - httproute.yaml +tests: + - it: should not create HTTPRoute by default + asserts: + - hasDocuments: + count: 0 + + - it: should create HTTPRoute when enabled + set: + httpRoute.enabled: true + httpRoute.parentRefs: + - name: my-gateway + namespace: gateway-system + httpRoute.rules: + - matches: + - path: + type: PathPrefix + value: / + asserts: + - hasDocuments: + count: 1 + - isKind: + of: HTTPRoute + - isAPIVersion: + of: gateway.networking.k8s.io/v1 + - equal: + path: metadata.name + value: RELEASE-NAME-jellyfin + + - it: should add annotations when specified + set: + httpRoute.enabled: true + httpRoute.annotations: + my-annotation: my-value + httpRoute.parentRefs: + - name: my-gateway + httpRoute.rules: + - matches: + - path: + type: PathPrefix + value: / + asserts: + - equal: + path: metadata.annotations.my-annotation + value: my-value + + - it: should set parentRefs correctly + set: + httpRoute.enabled: true + httpRoute.parentRefs: + - name: my-gateway + namespace: gateway-system + sectionName: https + httpRoute.rules: + - matches: + - path: + type: PathPrefix + value: / + asserts: + - equal: + path: spec.parentRefs[0].name + value: my-gateway + - equal: + path: spec.parentRefs[0].namespace + value: gateway-system + - equal: + path: spec.parentRefs[0].sectionName + value: https + + - it: should set hostnames when specified + set: + httpRoute.enabled: true + httpRoute.hostnames: + - jellyfin.example.com + - media.example.com + httpRoute.parentRefs: + - name: my-gateway + httpRoute.rules: + - matches: + - path: + type: PathPrefix + value: / + asserts: + - equal: + path: spec.hostnames[0] + value: jellyfin.example.com + - equal: + path: spec.hostnames[1] + value: media.example.com + + - it: should create rules with path matches + set: + httpRoute.enabled: true + httpRoute.parentRefs: + - name: my-gateway + httpRoute.rules: + - matches: + - path: + type: PathPrefix + value: /jellyfin + asserts: + - equal: + path: spec.rules[0].matches[0].path.type + value: PathPrefix + - equal: + path: spec.rules[0].matches[0].path.value + value: /jellyfin + + - it: should set backendRefs to jellyfin service + set: + httpRoute.enabled: true + service.port: 8096 + httpRoute.parentRefs: + - name: my-gateway + httpRoute.rules: + - matches: + - path: + type: PathPrefix + value: / + asserts: + - equal: + path: spec.rules[0].backendRefs[0].name + value: RELEASE-NAME-jellyfin + - equal: + path: spec.rules[0].backendRefs[0].port + value: 8096 + + - it: should support multiple rules + set: + httpRoute.enabled: true + httpRoute.parentRefs: + - name: my-gateway + httpRoute.rules: + - matches: + - path: + type: PathPrefix + value: / + - matches: + - path: + type: Exact + value: /api + asserts: + - lengthEqual: + path: spec.rules + count: 2 + - equal: + path: spec.rules[0].matches[0].path.value + value: / + - equal: + path: spec.rules[1].matches[0].path.value + value: /api + + - it: should support multiple matches in single rule + set: + httpRoute.enabled: true + httpRoute.parentRefs: + - name: my-gateway + httpRoute.rules: + - matches: + - path: + type: PathPrefix + value: /api + - path: + type: PathPrefix + value: /web + asserts: + - lengthEqual: + path: spec.rules[0].matches + count: 2 + - equal: + path: spec.rules[0].matches[0].path.value + value: /api + - equal: + path: spec.rules[0].matches[1].path.value + value: /web + + - it: should use custom service port + set: + httpRoute.enabled: true + service.port: 9000 + httpRoute.parentRefs: + - name: my-gateway + httpRoute.rules: + - matches: + - path: + type: PathPrefix + value: / + asserts: + - equal: + path: spec.rules[0].backendRefs[0].port + value: 9000