From 6b4e237321418d8f305ae47cc7e0a948cac1c5bd Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Sat, 9 May 2026 18:49:25 +0200 Subject: [PATCH 1/2] feat: integrate gateway api endpoint for chart deployment The Gateway API had been established as the new standard as an alternative for Ingress resources. With this change it's possible to deploy the HTTPRoute resource directly as part of the chart. Signed-off-by: Thomas Boerger --- charts/backstage/Chart.yaml | 2 +- charts/backstage/README.md | 9 +- charts/backstage/ci/httproute-values.yaml | 7 + charts/backstage/templates/httproute.yaml | 51 +++++ charts/backstage/values.schema.json | 217 +++++++++++++++++++++ charts/backstage/values.schema.tmpl.json | 219 +++++++++++++++++++++- charts/backstage/values.yaml | 25 +++ 7 files changed, 527 insertions(+), 3 deletions(-) create mode 100644 charts/backstage/ci/httproute-values.yaml create mode 100644 charts/backstage/templates/httproute.yaml diff --git a/charts/backstage/Chart.yaml b/charts/backstage/Chart.yaml index bfc5e0d..4640ed9 100644 --- a/charts/backstage/Chart.yaml +++ b/charts/backstage/Chart.yaml @@ -38,4 +38,4 @@ sources: # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 2.7.0 +version: 2.8.0 diff --git a/charts/backstage/README.md b/charts/backstage/README.md index 8d57495..8aae00b 100644 --- a/charts/backstage/README.md +++ b/charts/backstage/README.md @@ -2,7 +2,7 @@ # Backstage Helm Chart [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/backstage)](https://artifacthub.io/packages/search?repo=backstage) -![Version: 2.7.0](https://img.shields.io/badge/Version-2.7.0-informational?style=flat-square) +![Version: 2.8.0](https://img.shields.io/badge/Version-2.8.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) A Helm chart for deploying a Backstage application @@ -164,6 +164,13 @@ Kubernetes: `>= 1.19.0-0` | global | Global parameters Global Docker image parameters Please, note that this will override the image parameters, including dependencies, configured to use the global value Current available global Docker image parameters: imageRegistry, imagePullSecrets and storageClass | object | See below | | global.imagePullSecrets | Global Docker registry secret names as an array
E.g. `imagePullSecrets: [myRegistryKeySecretName]` | list | `[]` | | global.imageRegistry | Global Docker image registry | string | `""` | +| httpRoute | HTTPRoute parameters | object | `{"annotations":{},"enabled":false,"hostnames":[],"labels":{},"parentRefs":[],"rules":[{"matches":[{"path":{"type":"PathPrefix","value":"/"}}]}]}` | +| httpRoute.annotations | Additional annotations for the HTTPRoute resource | object | `{}` | +| httpRoute.enabled | Enable the creation of the HTTPRoute resource | bool | `false` | +| httpRoute.hostnames | List of hostnames matching HTTP header | list | `[]` | +| httpRoute.labels | Additional labels for the HTTPRoute resource | object | `{}` | +| httpRoute.parentRefs | List of Gateways this HTTPRoute is attached to | list | `[]` | +| httpRoute.rules | List of rules and filters applied to the HTTPRoute | list | `[{"matches":[{"path":{"type":"PathPrefix","value":"/"}}]}]` | | ingress | Ingress parameters | object | `{"annotations":{},"className":"","enabled":false,"extraHosts":[],"extraTls":[],"host":"","path":"/","tls":{"enabled":false,"secretName":""}}` | | ingress.annotations | Additional annotations for the Ingress resource | object | `{}` | | ingress.className | Name of the IngressClass cluster resource which defines which controller will implement the resource (e.g nginx) | string | `""` | diff --git a/charts/backstage/ci/httproute-values.yaml b/charts/backstage/ci/httproute-values.yaml new file mode 100644 index 0000000..95df65b --- /dev/null +++ b/charts/backstage/ci/httproute-values.yaml @@ -0,0 +1,7 @@ +httpRoute: + enabled: true + parentRefs: + - name: default + namespace: proxy + hostnames: + - backstage.example.com diff --git a/charts/backstage/templates/httproute.yaml b/charts/backstage/templates/httproute.yaml new file mode 100644 index 0000000..9abd57a --- /dev/null +++ b/charts/backstage/templates/httproute.yaml @@ -0,0 +1,51 @@ +{{- if .Values.httpRoute.enabled -}} +{{- $fullName := include "common.names.fullname" . -}} +{{- $svcPort := .Values.service.ports.backend -}} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ $fullName }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: backstage + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.httpRoute.labels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.httpRoute.labels "context" $) | nindent 4 }} + {{- end }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.httpRoute.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.httpRoute.annotations "context" $) | nindent 4 }} + {{- end }} +spec: + parentRefs: + {{- with .Values.httpRoute.parentRefs }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.httpRoute.hostnames }} + hostnames: + {{- toYaml . | nindent 4 }} + {{- end }} + rules: + {{- range .Values.httpRoute.rules }} + {{- with .matches }} + - matches: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .filters }} + filters: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .name }} + name: {{ .name }} + {{- end }} + backendRefs: + - name: {{ $fullName }} + port: {{ $svcPort }} + weight: 1 + {{- end }} +{{- end }} diff --git a/charts/backstage/values.schema.json b/charts/backstage/values.schema.json index 76b090e..b4525a3 100644 --- a/charts/backstage/values.schema.json +++ b/charts/backstage/values.schema.json @@ -6358,6 +6358,223 @@ "title": "Global parameters.", "type": "object" }, + "httpRoute": { + "additionalProperties": false, + "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "default": {}, + "title": "Additional annotations for the HTTPRoute resource", + "type": "object" + }, + "enabled": { + "default": false, + "title": "Enable the creation of the HTTPRoute resource", + "type": "boolean" + }, + "hostnames": { + "default": [], + "items": { + "type": "string" + }, + "title": "List of hostnames matching HTTP header", + "type": "array" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "default": {}, + "title": "Additional labels for the HTTPRoute resource", + "type": "object" + }, + "parentRefs": { + "default": [], + "items": { + "additionalProperties": false, + "properties": { + "group": { + "title": "Group is the group of the referent.", + "type": "string" + }, + "kind": { + "title": "Kind is kind of the referent.", + "type": "string" + }, + "name": { + "title": "Name is the name of the referent.", + "type": "string" + }, + "namespace": { + "title": "Namespace is the namespace of the referent.", + "type": "string" + }, + "port": { + "title": "Port is the network port this Route targets.", + "type": "integer" + }, + "sectionName": { + "title": "SectionName is the name of a section within the target resource.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "title": "List of Gateways this HTTPRoute is attached to", + "type": "array" + }, + "rules": { + "default": [], + "items": { + "additionalProperties": false, + "properties": { + "backendRefs": { + "items": { + "additionalProperties": false, + "properties": { + "group": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "weight": { + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + }, + "filters": { + "items": { + "type": "object" + }, + "type": "array" + }, + "matches": { + "items": { + "additionalProperties": false, + "properties": { + "headers": { + "items": { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "type": { + "enum": [ + "Exact", + "RegularExpression" + ], + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "method": { + "enum": [ + "GET", + "HEAD", + "POST", + "PUT", + "DELETE", + "CONNECT", + "OPTIONS", + "TRACE", + "PATCH" + ], + "type": "string" + }, + "path": { + "additionalProperties": false, + "properties": { + "type": { + "enum": [ + "Exact", + "PathPrefix", + "RegularExpression" + ], + "title": "HTTPPathMatchType specifies the semantics of how HTTP paths should be compared.", + "type": "string" + }, + "value": { + "title": "Value of the HTTP path to match against.", + "type": "string" + } + }, + "title": "Path specifies a HTTP request path matcher.", + "type": "object" + }, + "queryParams": { + "items": { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "type": { + "enum": [ + "Exact", + "RegularExpression" + ], + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "type": "array" + }, + "name": { + "title": "Name is the name of the rule.", + "type": "string" + } + }, + "type": "object" + }, + "title": "List of rules and filters applied to the HTTPRoute", + "type": "array" + } + }, + "title": "HTTPRoute parameters", + "type": "object" + }, "ingress": { "additionalProperties": false, "properties": { diff --git a/charts/backstage/values.schema.tmpl.json b/charts/backstage/values.schema.tmpl.json index 62fa600..95b0867 100644 --- a/charts/backstage/values.schema.tmpl.json +++ b/charts/backstage/values.schema.tmpl.json @@ -109,6 +109,223 @@ } } }, + "httpRoute": { + "additionalProperties": false, + "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "default": {}, + "title": "Additional annotations for the HTTPRoute resource", + "type": "object" + }, + "enabled": { + "default": false, + "title": "Enable the creation of the HTTPRoute resource", + "type": "boolean" + }, + "hostnames": { + "default": [], + "items": { + "type": "string" + }, + "title": "List of hostnames matching HTTP header", + "type": "array" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "default": {}, + "title": "Additional labels for the HTTPRoute resource", + "type": "object" + }, + "parentRefs": { + "default": [], + "items": { + "additionalProperties": false, + "properties": { + "group": { + "title": "Group is the group of the referent.", + "type": "string" + }, + "kind": { + "title": "Kind is kind of the referent.", + "type": "string" + }, + "name": { + "title": "Name is the name of the referent.", + "type": "string" + }, + "namespace": { + "title": "Namespace is the namespace of the referent.", + "type": "string" + }, + "port": { + "title": "Port is the network port this Route targets.", + "type": "integer" + }, + "sectionName": { + "title": "SectionName is the name of a section within the target resource.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "title": "List of Gateways this HTTPRoute is attached to", + "type": "array" + }, + "rules": { + "default": [], + "items": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name is the name of the rule.", + "type": "string" + }, + "backendRefs": { + "items": { + "additionalProperties": false, + "properties": { + "group": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "weight": { + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + }, + "filters": { + "items": { + "type": "object" + }, + "type": "array" + }, + "matches": { + "items": { + "additionalProperties": false, + "properties": { + "headers": { + "items": { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "type": { + "enum": [ + "Exact", + "RegularExpression" + ], + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "method": { + "enum": [ + "GET", + "HEAD", + "POST", + "PUT", + "DELETE", + "CONNECT", + "OPTIONS", + "TRACE", + "PATCH" + ], + "type": "string" + }, + "path": { + "additionalProperties": false, + "properties": { + "type": { + "enum": [ + "Exact", + "PathPrefix", + "RegularExpression" + ], + "title": "HTTPPathMatchType specifies the semantics of how HTTP paths should be compared.", + "type": "string" + }, + "value": { + "title": "Value of the HTTP path to match against.", + "type": "string" + } + }, + "title": "Path specifies a HTTP request path matcher.", + "type": "object" + }, + "queryParams": { + "items": { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "type": { + "enum": [ + "Exact", + "RegularExpression" + ], + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "title": "List of rules and filters applied to the HTTPRoute", + "type": "array" + } + }, + "title": "HTTPRoute parameters", + "type": "object" + }, "ingress": { "title": "Ingress parameters", "type": "object", @@ -1003,4 +1220,4 @@ } } } -} \ No newline at end of file +} diff --git a/charts/backstage/values.yaml b/charts/backstage/values.yaml index 5d0d231..aac1f23 100644 --- a/charts/backstage/values.yaml +++ b/charts/backstage/values.yaml @@ -97,6 +97,31 @@ ingress: # secretName: backstage-env --> extraTls: [] +# -- HTTPRoute parameters +httpRoute: + + # -- Enable the creation of the HTTPRoute resource + enabled: false + + # -- Additional labels for the HTTPRoute resource + labels: {} + + # -- Additional annotations for the HTTPRoute resource + annotations: {} + + # -- List of Gateways this HTTPRoute is attached to + parentRefs: [] + + # -- List of hostnames matching HTTP header + hostnames: [] + + # -- List of rules and filters applied to the HTTPRoute + rules: + - matches: + - path: + type: PathPrefix + value: / + # -- Backstage parameters # @default -- See below backstage: From 084b4db9d4d05818ca8810b9568add8ad983ae32 Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Mon, 11 May 2026 15:38:44 +0200 Subject: [PATCH 2/2] ci: install gateway api crds while testing chart values Signed-off-by: Thomas Boerger --- .github/workflows/test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cc35a0a..0a4cba8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,6 +46,10 @@ jobs: if: steps.list-changed.outputs.changed == 'true' uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # pin@v1.14.0 + - name: Install Gateway API CRDs + if: steps.list-changed.outputs.changed == 'true' + run: kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.5.0/standard-install.yaml + - name: Install Ingress Controller if: steps.list-changed.outputs.changed == 'true' run: "helm install ingress-nginx/ingress-nginx --generate-name --set controller.service.type='NodePort' --set controller.admissionWebhooks.enabled=false"