From e52a3da7ccbb9078c1376e5a9a9fc436291ac0c7 Mon Sep 17 00:00:00 2001 From: Adam Zahorscak <69020096+Azahorscak@users.noreply.github.com> Date: Mon, 11 May 2026 17:52:00 -0400 Subject: [PATCH] Gateway api resources (#1) * feat: add consistent, off-by-default, gatewayAPI configuration options * fix: versions and docs --- .tool-versions | 1 + charts/posit-chronicle/README.md | 2 +- charts/rstudio-connect/Chart.lock | 6 +- charts/rstudio-connect/Chart.yaml | 4 +- charts/rstudio-connect/Makefile | 1 + charts/rstudio-connect/NEWS.md | 5 ++ charts/rstudio-connect/README.md | 44 +++++++++- charts/rstudio-connect/README.md.gotmpl | 31 +++++++ .../lint/gateway-api-values.yaml | 36 ++++++++ .../rstudio-connect/templates/httproute.yaml | 37 ++++++++ .../tests/gateway_api_test.yaml | 84 +++++++++++++++++++ charts/rstudio-connect/values.yaml | 23 +++++ charts/rstudio-launcher-rbac/README.md | 2 +- charts/rstudio-library/Chart.yaml | 4 +- charts/rstudio-library/NEWS.md | 4 + charts/rstudio-library/README.md | 4 +- charts/rstudio-library/templates/_gateway.tpl | 69 +++++++++++++++ charts/rstudio-pm/Chart.lock | 6 +- charts/rstudio-pm/Chart.yaml | 4 +- charts/rstudio-pm/Makefile | 1 + charts/rstudio-pm/NEWS.md | 5 ++ charts/rstudio-pm/README.md | 44 +++++++++- charts/rstudio-pm/README.md.gotmpl | 31 +++++++ .../rstudio-pm/lint/gateway-api-values.yaml | 24 ++++++ charts/rstudio-pm/templates/httproute.yaml | 37 ++++++++ charts/rstudio-pm/tests/gateway_api_test.yaml | 84 +++++++++++++++++++ charts/rstudio-pm/values.yaml | 23 +++++ charts/rstudio-workbench/Chart.lock | 6 +- charts/rstudio-workbench/Chart.yaml | 4 +- charts/rstudio-workbench/Makefile | 1 + charts/rstudio-workbench/NEWS.md | 5 ++ charts/rstudio-workbench/README.md | 44 +++++++++- charts/rstudio-workbench/README.md.gotmpl | 31 +++++++ .../lint/gateway-api-values.yaml | 21 +++++ .../templates/httproute.yaml | 37 ++++++++ .../tests/gateway_api_test.yaml | 84 +++++++++++++++++++ charts/rstudio-workbench/values.yaml | 23 +++++ examples/connect/ingress/aws-alb.qmd | 6 ++ .../ingress/rstudio-connect-alb-ingress.yaml | 3 + examples/gateway-api/README.md | 14 ++++ examples/gateway-api/aws/README.md | 45 ++++++++++ examples/gateway-api/aws/gateway.yaml | 26 ++++++ examples/gateway-api/aws/gatewayclass.yaml | 9 ++ .../aws/loadbalancerconfiguration.yaml | 13 +++ examples/gateway-api/aws/referencegrant.yaml | 22 +++++ .../gateway-api/aws/values-gateway-api.yaml | 62 ++++++++++++++ examples/gateway-api/kgateway/README.md | 31 +++++++ examples/gateway-api/kgateway/gateway.yaml | 28 +++++++ .../gateway-api/kgateway/referencegrant.yaml | 21 +++++ .../kgateway/values-gateway-api.yaml | 62 ++++++++++++++ examples/package-manager/ingress/aws-alb.qmd | 6 ++ .../ingress/rstudio-pm-alb-ingress.yaml | 3 + examples/workbench/ingress/aws-alb.qmd | 6 ++ .../rstudio-workbench-alb-ingress.yaml | 3 + other-charts/prepull-daemonset/README.md | 2 +- other-charts/rstudio-library-test/README.md | 2 +- 56 files changed, 1201 insertions(+), 35 deletions(-) create mode 100644 .tool-versions create mode 100644 charts/rstudio-connect/lint/gateway-api-values.yaml create mode 100644 charts/rstudio-connect/templates/httproute.yaml create mode 100644 charts/rstudio-connect/tests/gateway_api_test.yaml create mode 100644 charts/rstudio-library/templates/_gateway.tpl create mode 100644 charts/rstudio-pm/lint/gateway-api-values.yaml create mode 100644 charts/rstudio-pm/templates/httproute.yaml create mode 100644 charts/rstudio-pm/tests/gateway_api_test.yaml create mode 100644 charts/rstudio-workbench/lint/gateway-api-values.yaml create mode 100644 charts/rstudio-workbench/templates/httproute.yaml create mode 100644 charts/rstudio-workbench/tests/gateway_api_test.yaml create mode 100644 examples/gateway-api/README.md create mode 100644 examples/gateway-api/aws/README.md create mode 100644 examples/gateway-api/aws/gateway.yaml create mode 100644 examples/gateway-api/aws/gatewayclass.yaml create mode 100644 examples/gateway-api/aws/loadbalancerconfiguration.yaml create mode 100644 examples/gateway-api/aws/referencegrant.yaml create mode 100644 examples/gateway-api/aws/values-gateway-api.yaml create mode 100644 examples/gateway-api/kgateway/README.md create mode 100644 examples/gateway-api/kgateway/gateway.yaml create mode 100644 examples/gateway-api/kgateway/referencegrant.yaml create mode 100644 examples/gateway-api/kgateway/values-gateway-api.yaml diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 000000000..0fcdf872d --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +helm 3.18.2 diff --git a/charts/posit-chronicle/README.md b/charts/posit-chronicle/README.md index f017056ff..e32ec3a11 100644 --- a/charts/posit-chronicle/README.md +++ b/charts/posit-chronicle/README.md @@ -260,5 +260,5 @@ reference page](https://docs.posit.co/chronicle/appendix/library/advanced-server | serviceAccount.name | string | `""` | Override for the service account name, defaults to fullname | ---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.13.1](https://github.com/norwoodj/helm-docs/releases/v1.13.1) +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/charts/rstudio-connect/Chart.lock b/charts/rstudio-connect/Chart.lock index f82354682..aee0b7340 100644 --- a/charts/rstudio-connect/Chart.lock +++ b/charts/rstudio-connect/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: rstudio-library repository: https://helm.rstudio.com - version: 0.1.36 -digest: sha256:cde061b0b7da43d7adbfcbc8d90e6d466d453dd707d8dad4f702fec6aeea103b -generated: "2026-04-01T12:03:45.783681-05:00" + version: 0.1.37 +digest: sha256:43574c2b3fcee11a2ad66364bdb49510315e447caf4a5d829019adf53782f478 +generated: "2025-03-23T00:00:00Z" diff --git a/charts/rstudio-connect/Chart.yaml b/charts/rstudio-connect/Chart.yaml index 9463b84ad..902eaf3fc 100644 --- a/charts/rstudio-connect/Chart.yaml +++ b/charts/rstudio-connect/Chart.yaml @@ -1,6 +1,6 @@ name: rstudio-connect description: Official Helm chart for Posit Connect -version: 0.9.4 +version: 0.9.5 apiVersion: v2 appVersion: 2026.04.0 icon: https://raw.githubusercontent.com/rstudio/helm/main/images/posit-icon-fullcolor.svg @@ -13,7 +13,7 @@ maintainers: url: https://github.com/sol-eng dependencies: - name: rstudio-library - version: 0.1.36 + version: 0.1.37 repository: https://helm.rstudio.com annotations: artifacthub.io/images: | diff --git a/charts/rstudio-connect/Makefile b/charts/rstudio-connect/Makefile index ff70d2145..37a8ac626 100644 --- a/charts/rstudio-connect/Makefile +++ b/charts/rstudio-connect/Makefile @@ -1,6 +1,7 @@ lint: helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./ci/complex-values.yaml . helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./ci/simple-values.yaml . + helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./lint/gateway-api-values.yaml . helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./ci/empty-values.yaml . template: diff --git a/charts/rstudio-connect/NEWS.md b/charts/rstudio-connect/NEWS.md index f31b1aeca..24116febb 100644 --- a/charts/rstudio-connect/NEWS.md +++ b/charts/rstudio-connect/NEWS.md @@ -1,4 +1,8 @@ # Changelog +## 0.9.5 + +- Document shared Gateway API examples (`examples/gateway-api/aws`, `examples/gateway-api/kgateway`) in the README. +- Add optional Gateway API support (`HTTPRoute` via `gatewayApi` values), independent of `ingress`. ## 0.9.4 @@ -36,6 +40,7 @@ - Remove deprecated default value `Metrics.Enabled = true` - Remove legacy Graphite exporter sidecar (`prometheus.legacy`, `prometheusExporter.*`, and `configmap-graphite-exporter.yaml`). The built-in Prometheus `/metrics` endpoint is now the only supported metrics path. Use OpenTelemetry for richer instrumentation. + ## 0.8.35 - Add `executionEnvironments` value for [declarative management of execution environments](https://docs.posit.co/connect/admin/appendix/off-host/execution-environments/#declarative-management). Unlike `launcher.customRuntimeYaml`, changes take effect on every `helm upgrade` without requiring a pod restart or database reset. Requires Connect version 2026.03.0 or later. diff --git a/charts/rstudio-connect/README.md b/charts/rstudio-connect/README.md index 116b06cb6..05dab431f 100644 --- a/charts/rstudio-connect/README.md +++ b/charts/rstudio-connect/README.md @@ -1,6 +1,6 @@ # Posit Connect -![Version: 0.9.4](https://img.shields.io/badge/Version-0.9.4-informational?style=flat-square) ![AppVersion: 2026.04.0](https://img.shields.io/badge/AppVersion-2026.04.0-informational?style=flat-square) +![Version: 0.9.5](https://img.shields.io/badge/Version-0.9.5-informational?style=flat-square) ![AppVersion: 2026.04.0](https://img.shields.io/badge/AppVersion-2026.04.0-informational?style=flat-square) #### _Official Helm chart for Posit Connect_ @@ -30,11 +30,11 @@ To ensure reproducibility in your environment and insulate yourself from future ## Installing the chart -To install the chart with the release name `my-release` at version 0.9.4: +To install the chart with the release name `my-release` at version 0.9.5: ```{.bash} helm repo add rstudio https://helm.rstudio.com -helm upgrade --install my-release rstudio/rstudio-connect --version=0.9.4 +helm upgrade --install my-release rstudio/rstudio-connect --version=0.9.5 ``` To explore other chart versions, look at: @@ -243,6 +243,37 @@ job pods to reach Connect's embedded OTel collector directly (pod-to-pod). To override the advertise host, set `CONNECT_OPENTELEMETRY_COLLECTORADVERTISEHOST` explicitly in `pod.env`. +## Gateway API + +This chart can optionally create Kubernetes [Gateway API](https://gateway-api.sigs.k8s.io/) `HTTPRoute` resources that point at the chart `Service`. This is controlled with `gatewayApi.enabled` and is **independent** of the built-in `Ingress` (`ingress.enabled`); you may enable one, both, or neither. + +**Prerequisites:** Install the Gateway API CRDs in your cluster and provision a `Gateway` (and `GatewayClass`) appropriate for your ingress controller. This chart does not create a `Gateway` resource; set `gatewayApi.parentRefs` to attach each `HTTPRoute` to your existing `Gateway`. + +**TLS:** Termination is typically configured on the `Gateway` listener or by your controller, not on `HTTPRoute`. This chart does not mirror `ingress.tls` onto Gateway API resources. + +**Cross-namespace parents:** If the `Gateway` lives in another namespace, ensure your controller requirements are met (for example a [`ReferenceGrant`](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ReferenceGrant)). + +Example: + +```yaml +gatewayApi: + enabled: true + parentRefs: + - name: contour + namespace: projectcontour + kind: Gateway + group: gateway.networking.k8s.io + hosts: + - host: connect.example.com + paths: + - path: / + pathType: Prefix +``` + +Path entries use the same shape as `ingress.hosts` paths: a string or an object with `path` and optional `pathType` (`Prefix`, `Exact`, or `ImplementationSpecific`). Each `gatewayApi.hosts` entry becomes one `HTTPRoute`. The backend uses `service.port`, which must be numeric for the Gateway API `backendRef`. + +**Examples:** Shared-gateway walkthroughs for [AWS Load Balancer Controller (ALB)](../../examples/gateway-api/aws/README.md) and [KGateway](../../examples/gateway-api/kgateway/README.md) live under `examples/gateway-api/` in this repository. + ## General principles - In most places, we opt to pass Helm values over configmaps. We translate these into the valid `.gcfg` file format @@ -300,6 +331,11 @@ The Helm `config` values are converted into the `rstudio-connect.gcfg` service c | executionEnvironments | list | `[]` (disabled) | Optional list of execution environments to manage declaratively. Requires Connect version 2026.03.0 or later. When set, the chart renders these into a ConfigMap, mounts it into the Connect pod, and sets ExecutionEnvironments.ConfigFilePath in the Connect configuration. Unlike launcher.customRuntimeYaml, changes take effect on every helm upgrade without requiring a pod restart or database reset. | | extraObjects | list | `[]` | Extra objects to deploy (value evaluated as a template) | | fullnameOverride | string | `""` | The full name of the release (can be overridden) | +| gatewayApi | object | `{"annotations":{},"enabled":false,"hosts":[],"labels":{},"parentRefs":[]}` | Gateway API (HTTPRoute) resources. Independent of `ingress`; both may be enabled if desired. | +| gatewayApi.annotations | object | `{}` | Annotations for all HTTPRoute resources created by this chart | +| gatewayApi.hosts | list | `[]` | Same shape as `ingress.hosts`. Each entry becomes one HTTPRoute; omit or use empty `paths` to skip an entry. | +| gatewayApi.labels | object | `{}` | Extra labels for all HTTPRoute resources created by this chart | +| gatewayApi.parentRefs | list | `[]` | parentRefs attach HTTPRoutes to an existing Gateway (or other supported parent). Required when `gatewayApi.enabled` is true. [Gateway API parent reference](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ParentReference) | | image | object | `{"imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"repository":"ghcr.io/rstudio/rstudio-connect","tag":"","tagPrefix":"ubuntu2204-"}` | Defines the Posit Connect image to deploy | | image.imagePullPolicy | string | `"IfNotPresent"` | The imagePullPolicy for the main pod image | | image.imagePullSecrets | list | `[]` | an array of kubernetes secrets for pulling the main pod image from private registries | @@ -402,5 +438,5 @@ The Helm `config` values are converted into the `rstudio-connect.gcfg` service c | versionOverride | string | `""` | A Connect version to override the "tag" for the Posit Connect image and the Content Init image. Necessary until https://github.com/helm/helm/issues/8194 | ---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.13.1](https://github.com/norwoodj/helm-docs/releases/v1.13.1) +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/charts/rstudio-connect/README.md.gotmpl b/charts/rstudio-connect/README.md.gotmpl index bb511abd9..1a234de17 100644 --- a/charts/rstudio-connect/README.md.gotmpl +++ b/charts/rstudio-connect/README.md.gotmpl @@ -183,6 +183,37 @@ job pods to reach Connect's embedded OTel collector directly (pod-to-pod). To override the advertise host, set `CONNECT_OPENTELEMETRY_COLLECTORADVERTISEHOST` explicitly in `pod.env`. +## Gateway API + +This chart can optionally create Kubernetes [Gateway API](https://gateway-api.sigs.k8s.io/) `HTTPRoute` resources that point at the chart `Service`. This is controlled with `gatewayApi.enabled` and is **independent** of the built-in `Ingress` (`ingress.enabled`); you may enable one, both, or neither. + +**Prerequisites:** Install the Gateway API CRDs in your cluster and provision a `Gateway` (and `GatewayClass`) appropriate for your ingress controller. This chart does not create a `Gateway` resource; set `gatewayApi.parentRefs` to attach each `HTTPRoute` to your existing `Gateway`. + +**TLS:** Termination is typically configured on the `Gateway` listener or by your controller, not on `HTTPRoute`. This chart does not mirror `ingress.tls` onto Gateway API resources. + +**Cross-namespace parents:** If the `Gateway` lives in another namespace, ensure your controller requirements are met (for example a [`ReferenceGrant`](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ReferenceGrant)). + +Example: + +```yaml +gatewayApi: + enabled: true + parentRefs: + - name: contour + namespace: projectcontour + kind: Gateway + group: gateway.networking.k8s.io + hosts: + - host: connect.example.com + paths: + - path: / + pathType: Prefix +``` + +Path entries use the same shape as `ingress.hosts` paths: a string or an object with `path` and optional `pathType` (`Prefix`, `Exact`, or `ImplementationSpecific`). Each `gatewayApi.hosts` entry becomes one `HTTPRoute`. The backend uses `service.port`, which must be numeric for the Gateway API `backendRef`. + +**Examples:** Shared-gateway walkthroughs for [AWS Load Balancer Controller (ALB)](../../examples/gateway-api/aws/README.md) and [KGateway](../../examples/gateway-api/kgateway/README.md) live under `examples/gateway-api/` in this repository. + ## General principles - In most places, we opt to pass Helm values over configmaps. We translate these into the valid `.gcfg` file format diff --git a/charts/rstudio-connect/lint/gateway-api-values.yaml b/charts/rstudio-connect/lint/gateway-api-values.yaml new file mode 100644 index 000000000..2e9a3960c --- /dev/null +++ b/charts/rstudio-connect/lint/gateway-api-values.yaml @@ -0,0 +1,36 @@ +sharedStorage: + create: true + requests: + storage: "1Gi" +license: + key: test +nodePort: 32390 +replicas: 1 +config: + HTTP: + Listen: :3939 + Authentication: + Provider: password + Python: + Enabled: true + Executable: /opt/python/3.6.5/bin/python + 'RPackageRepository "CRAN"': + URL: https://packagemanager.rstudio.com/cran/__linux__/bionic/latest + 'RPackageRepository "RSPM"': + URL: https://packagemanager.rstudio.com/cran/__linux__/bionic/latest + Server: + Address: http://localhost:3939 + DataDir: /var/lib/rstudio-connect + RVersionScanning: false + RVersion: + - /opt/R/3.6.2 +gatewayApi: + enabled: true + parentRefs: + - name: example-gateway + kind: Gateway + group: gateway.networking.k8s.io + hosts: + - host: connect.example.com + paths: + - / diff --git a/charts/rstudio-connect/templates/httproute.yaml b/charts/rstudio-connect/templates/httproute.yaml new file mode 100644 index 000000000..8f2d2d2ac --- /dev/null +++ b/charts/rstudio-connect/templates/httproute.yaml @@ -0,0 +1,37 @@ +{{- if and .Values.gatewayApi.enabled .Values.gatewayApi.hosts -}} +{{- $apiVersion := include "rstudio-library.gateway.apiVersion" . -}} +{{- $fullName := include "rstudio-connect.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- $root := . -}} +{{- range $i, $h := .Values.gatewayApi.hosts }} +{{- if and $h.paths (gt (len $h.paths) 0) }} +--- +apiVersion: {{ $apiVersion }} +kind: HTTPRoute +metadata: + name: {{ include "rstudio-library.gateway.httpRouteName" (dict "fullName" $fullName "index" $i) }} + labels: + {{- include "rstudio-connect.labels" $root | nindent 4 }} + {{- with $root.Values.gatewayApi.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with $root.Values.gatewayApi.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + parentRefs: + {{- toYaml $root.Values.gatewayApi.parentRefs | nindent 4 }} + hostnames: + - {{ $h.host | quote }} + rules: + - matches: + {{- range $h.paths }} + - path: + {{- include "rstudio-library.gateway.httpPathMatchBody" (dict "pathData" .) | nindent 12 }} + {{- end }} + backendRefs: + {{- include "rstudio-library.gateway.serviceBackendRef" (dict "svcName" $fullName "svcPort" $svcPort) | nindent 8 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/rstudio-connect/tests/gateway_api_test.yaml b/charts/rstudio-connect/tests/gateway_api_test.yaml new file mode 100644 index 000000000..3b396395e --- /dev/null +++ b/charts/rstudio-connect/tests/gateway_api_test.yaml @@ -0,0 +1,84 @@ +suite: Connect Gateway API +templates: + - httproute.yaml +tests: + - it: should not create HTTPRoute when gatewayApi is disabled + template: httproute.yaml + asserts: + - hasDocuments: + count: 0 + - it: should not create HTTPRoute when enabled but hosts is empty + template: httproute.yaml + set: + gatewayApi: + enabled: true + parentRefs: + - name: gw + kind: Gateway + group: gateway.networking.k8s.io + hosts: [] + asserts: + - hasDocuments: + count: 0 + - it: should create HTTPRoute when enabled with hosts and parentRefs + template: httproute.yaml + set: + gatewayApi: + enabled: true + annotations: + test.io/route: "true" + labels: + test.io/kind: httproute + parentRefs: + - name: test-gateway + namespace: gw-ns + kind: Gateway + group: gateway.networking.k8s.io + hosts: + - host: example.com + paths: + - / + - path: /api + pathType: Prefix + asserts: + - hasDocuments: + count: 1 + - isKind: + of: HTTPRoute + apiVersion: gateway.networking.k8s.io/v1 + - equal: + path: metadata.name + value: RELEASE-NAME-rstudio-connect-gw-0 + - equal: + path: metadata.annotations["test.io/route"] + value: "true" + - equal: + path: metadata.labels["test.io/kind"] + value: httproute + - equal: + path: spec.parentRefs[0].name + value: test-gateway + - equal: + path: spec.parentRefs[0].namespace + value: gw-ns + - equal: + path: spec.hostnames[0] + value: example.com + - equal: + path: spec.rules[0].matches[0].path.type + value: PathPrefix + - equal: + path: spec.rules[0].matches[0].path.value + value: / + - equal: + path: spec.rules[0].matches[1].path.type + value: PathPrefix + - equal: + path: spec.rules[0].matches[1].path.value + value: /api + - equal: + path: spec.rules[0].backendRefs[0].name + value: RELEASE-NAME-rstudio-connect + - equal: + path: spec.rules[0].backendRefs[0].port + value: 80 diff --git a/charts/rstudio-connect/values.yaml b/charts/rstudio-connect/values.yaml index a1c67fa95..e7601efdc 100644 --- a/charts/rstudio-connect/values.yaml +++ b/charts/rstudio-connect/values.yaml @@ -251,6 +251,29 @@ ingress: # hosts: # - chart-example.local +# -- Gateway API (HTTPRoute) resources. Independent of `ingress`; both may be enabled if desired. +gatewayApi: + enabled: false + # -- Annotations for all HTTPRoute resources created by this chart + annotations: {} + # -- Extra labels for all HTTPRoute resources created by this chart + labels: {} + # -- parentRefs attach HTTPRoutes to an existing Gateway (or other supported parent). + # Required when `gatewayApi.enabled` is true. + # [Gateway API parent reference](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ParentReference) + parentRefs: [] + # - name: example-gateway + # namespace: gateway-namespace + # kind: Gateway + # group: gateway.networking.k8s.io + # -- Same shape as `ingress.hosts`. Each entry becomes one HTTPRoute; omit or use empty `paths` to skip an entry. + hosts: [] + # - host: chart-example.local + # paths: + # - / + # # or path: /api + # # pathType: Prefix + # Settings for the Chronicle Agent sidecar container chronicleAgent: # -- Creates a Chronicle agent sidecar container in the pod if true diff --git a/charts/rstudio-launcher-rbac/README.md b/charts/rstudio-launcher-rbac/README.md index d8f5aa4c9..ad32e24a0 100644 --- a/charts/rstudio-launcher-rbac/README.md +++ b/charts/rstudio-launcher-rbac/README.md @@ -62,5 +62,5 @@ helm template -n rstudio rstudio-launcher-rbac rstudio/rstudio-launcher-rbac | targetNamespaces | list | `[]` | The targetNamespaces that the launcher will be able to launch sessions into | ---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.13.1](https://github.com/norwoodj/helm-docs/releases/v1.13.1) +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/charts/rstudio-library/Chart.yaml b/charts/rstudio-library/Chart.yaml index ac3b1d749..d9b67fa6b 100644 --- a/charts/rstudio-library/Chart.yaml +++ b/charts/rstudio-library/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: rstudio-library description: Helm library helpers for use by official RStudio charts type: library -version: 0.1.36 -appVersion: 0.1.35 +version: 0.1.37 +appVersion: 0.1.37 icon: https://raw.githubusercontent.com/rstudio/helm/main/images/posit-icon-fullcolor.svg home: https://www.rstudio.com diff --git a/charts/rstudio-library/NEWS.md b/charts/rstudio-library/NEWS.md index a49d5b6f1..fe2f7683f 100644 --- a/charts/rstudio-library/NEWS.md +++ b/charts/rstudio-library/NEWS.md @@ -1,5 +1,9 @@ # Changelog +## 0.1.37 + +- Add Gateway API helpers in `_gateway.tpl` (`apiVersion`, path match mapping, HTTPRoute naming, service `backendRef`). + ## 0.1.36 - Update chart icon to Posit icon diff --git a/charts/rstudio-library/README.md b/charts/rstudio-library/README.md index 7b28d09c8..29c2e4527 100644 --- a/charts/rstudio-library/README.md +++ b/charts/rstudio-library/README.md @@ -1,6 +1,6 @@ # rstudio-library -![Version: 0.1.36](https://img.shields.io/badge/Version-0.1.36-informational?style=flat-square) ![Type: library](https://img.shields.io/badge/Type-library-informational?style=flat-square) ![AppVersion: 0.1.35](https://img.shields.io/badge/AppVersion-0.1.35-informational?style=flat-square) +![Version: 0.1.37](https://img.shields.io/badge/Version-0.1.37-informational?style=flat-square) ![Type: library](https://img.shields.io/badge/Type-library-informational?style=flat-square) ![AppVersion: 0.1.37](https://img.shields.io/badge/AppVersion-0.1.37-informational?style=flat-square) #### _Helm library helpers for use by official RStudio charts_ @@ -34,5 +34,5 @@ If you are curious about its usage, take a look at the other charts (i.e. `rstud for `rstudio-library` in the `templates/` directory. ---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.13.1](https://github.com/norwoodj/helm-docs/releases/v1.13.1) +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/charts/rstudio-library/templates/_gateway.tpl b/charts/rstudio-library/templates/_gateway.tpl new file mode 100644 index 000000000..566b5d2dc --- /dev/null +++ b/charts/rstudio-library/templates/_gateway.tpl @@ -0,0 +1,69 @@ +{{- /* + Gateway API group/version for HTTPRoute and related resources +*/ -}} +{{- define "rstudio-library.gateway.apiVersion" -}} +gateway.networking.k8s.io/v1 +{{- end -}} + +{{- /* + Map Ingress pathType values to Gateway API HTTPPathMatch type values. + Takes the pathType string (e.g. Prefix, Exact, ImplementationSpecific). +*/ -}} +{{- define "rstudio-library.gateway.ingressPathTypeToGateway" -}} +{{- $t := . | default "Prefix" | toString -}} +{{- if eq $t "Prefix" -}} +PathPrefix +{{- else if eq $t "Exact" -}} +Exact +{{- else if eq $t "ImplementationSpecific" -}} +ImplementationSpecific +{{- else if eq $t "PathPrefix" -}} +PathPrefix +{{- else if eq $t "RegularExpression" -}} +RegularExpression +{{- else -}} +PathPrefix +{{- end -}} +{{- end -}} + +{{- /* + YAML body for HTTPPathMatch (path.type and path.value), indented under "path:". + Takes a dict: + "pathData" — same as ingress path entry: string or map with .path and optional .pathType +*/ -}} +{{- define "rstudio-library.gateway.httpPathMatchBody" -}} +{{- $pathData := .pathData -}} +{{- $path := "/" -}} +{{- $pathType := "Prefix" -}} +{{- if kindIs "string" $pathData -}} +{{- $path = $pathData -}} +{{- else -}} +{{- $path = $pathData.path -}} +{{- if hasKey $pathData "pathType" -}} +{{- $pathType = $pathData.pathType | default "Prefix" -}} +{{- end -}} +{{- end -}} +type: {{ include "rstudio-library.gateway.ingressPathTypeToGateway" $pathType }} +value: {{ $path | quote }} +{{- end -}} + +{{- /* + Kubernetes-safe HTTPRoute name from release fullname and host index (DNS-1123, max 63 chars). + Takes a dict: "fullName" and "index" (int). +*/ -}} +{{- define "rstudio-library.gateway.httpRouteName" -}} +{{- $fullName := .fullName -}} +{{- $idx := int .index -}} +{{- printf "%s-gw-%d" ($fullName | trunc 56) $idx | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- /* + Service backendRef for HTTPRoute (port must be numeric for standard Service refs). + Takes a dict: "svcName", "svcPort" +*/ -}} +{{- define "rstudio-library.gateway.serviceBackendRef" -}} +{{- $svcName := .svcName -}} +{{- $svcPort := .svcPort -}} +- name: {{ $svcName }} + port: {{ $svcPort | int }} +{{- end -}} diff --git a/charts/rstudio-pm/Chart.lock b/charts/rstudio-pm/Chart.lock index 49dfebdee..aee0b7340 100644 --- a/charts/rstudio-pm/Chart.lock +++ b/charts/rstudio-pm/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: rstudio-library repository: https://helm.rstudio.com - version: 0.1.31 -digest: sha256:2a0e98b8fa01730bf2db3816a7310462c921b9fa2f1f3c74f85fedede82e1593 -generated: "2024-11-01T10:21:00.666975-04:00" + version: 0.1.37 +digest: sha256:43574c2b3fcee11a2ad66364bdb49510315e447caf4a5d829019adf53782f478 +generated: "2025-03-23T00:00:00Z" diff --git a/charts/rstudio-pm/Chart.yaml b/charts/rstudio-pm/Chart.yaml index 1ba489c32..5f618d44d 100644 --- a/charts/rstudio-pm/Chart.yaml +++ b/charts/rstudio-pm/Chart.yaml @@ -1,6 +1,6 @@ name: rstudio-pm description: Official Helm chart for Posit Package Manager -version: 0.5.57 +version: 0.5.58 apiVersion: v2 appVersion: 2026.04.2 icon: https://raw.githubusercontent.com/rstudio/helm/main/images/posit-icon-fullcolor.svg @@ -14,7 +14,7 @@ maintainers: url: https://github.com/rstudio/helm dependencies: - name: rstudio-library - version: 0.1.31 + version: 0.1.37 repository: https://helm.rstudio.com annotations: artifacthub.io/images: | diff --git a/charts/rstudio-pm/Makefile b/charts/rstudio-pm/Makefile index 64d8ec2d7..b76208f4b 100644 --- a/charts/rstudio-pm/Makefile +++ b/charts/rstudio-pm/Makefile @@ -1,5 +1,6 @@ lint: helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./ci/simple-values.yaml . + helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./lint/gateway-api-values.yaml . helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./ci/empty-values.yaml . helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./ci/all-values.yaml . diff --git a/charts/rstudio-pm/NEWS.md b/charts/rstudio-pm/NEWS.md index 729f2ce76..f8bb44c8d 100644 --- a/charts/rstudio-pm/NEWS.md +++ b/charts/rstudio-pm/NEWS.md @@ -1,5 +1,10 @@ # Changelog +## 0.5.58 + +- Document shared Gateway API examples (`examples/gateway-api/aws`, `examples/gateway-api/kgateway`) in the README. +- Add optional Gateway API support (`HTTPRoute` via `gatewayApi` values), independent of `ingress`. + ## 0.5.57 - Update default Posit Package Manager version to 2026.04.2 diff --git a/charts/rstudio-pm/README.md b/charts/rstudio-pm/README.md index 2b3c6c564..73163f2c8 100644 --- a/charts/rstudio-pm/README.md +++ b/charts/rstudio-pm/README.md @@ -1,6 +1,6 @@ # Posit Package Manager -![Version: 0.5.57](https://img.shields.io/badge/Version-0.5.57-informational?style=flat-square) ![AppVersion: 2026.04.2](https://img.shields.io/badge/AppVersion-2026.04.2-informational?style=flat-square) +![Version: 0.5.58](https://img.shields.io/badge/Version-0.5.58-informational?style=flat-square) ![AppVersion: 2026.04.2](https://img.shields.io/badge/AppVersion-2026.04.2-informational?style=flat-square) #### _Official Helm chart for Posit Package Manager_ @@ -24,11 +24,11 @@ To ensure a stable production deployment: ## Installing the chart -To install the chart with the release name `my-release` at version 0.5.57: +To install the chart with the release name `my-release` at version 0.5.58: ```{.bash} helm repo add rstudio https://helm.rstudio.com -helm upgrade --install my-release rstudio/rstudio-pm --version=0.5.57 +helm upgrade --install my-release rstudio/rstudio-pm --version=0.5.58 ``` To explore other chart versions, look at: @@ -176,6 +176,37 @@ awsSecretAccessKey: your-secret-access-key Bear in mind that static, long-lived credentials are the least secure option and should be avoided if at all possible. +## Gateway API + +This chart can optionally create Kubernetes [Gateway API](https://gateway-api.sigs.k8s.io/) `HTTPRoute` resources that point at the chart `Service`. This is controlled with `gatewayApi.enabled` and is **independent** of the built-in `Ingress` (`ingress.enabled`); you may enable one, both, or neither. + +**Prerequisites:** Install the Gateway API CRDs in your cluster and provision a `Gateway` (and `GatewayClass`) appropriate for your ingress controller. This chart does not create a `Gateway` resource; set `gatewayApi.parentRefs` to attach each `HTTPRoute` to your existing `Gateway`. + +**TLS:** Termination is typically configured on the `Gateway` listener or by your controller, not on `HTTPRoute`. This chart does not mirror `ingress.tls` onto Gateway API resources. + +**Cross-namespace parents:** If the `Gateway` lives in another namespace, ensure your controller requirements are met (for example a [`ReferenceGrant`](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ReferenceGrant)). + +Example: + +```yaml +gatewayApi: + enabled: true + parentRefs: + - name: contour + namespace: projectcontour + kind: Gateway + group: gateway.networking.k8s.io + hosts: + - host: package-manager.example.com + paths: + - path: / + pathType: Prefix +``` + +Path entries use the same shape as `ingress.hosts` paths: a string or an object with `path` and optional `pathType` (`Prefix`, `Exact`, or `ImplementationSpecific`). Each `gatewayApi.hosts` entry becomes one `HTTPRoute`. The backend uses `service.port`, which must be numeric for the Gateway API `backendRef`. + +**Examples:** Shared-gateway walkthroughs for [AWS Load Balancer Controller (ALB)](../../examples/gateway-api/aws/README.md) and [KGateway](../../examples/gateway-api/kgateway/README.md) live under `examples/gateway-api/` in this repository. + ## General principles - In most places, we opt to pass Helm values over configmaps. We translate these into the valid `.gcfg` file format @@ -207,6 +238,11 @@ The Helm `config` values are converted into the `rstudio-pm.gcfg` service config | extraContainers | list | `[]` | sidecar container list | | extraObjects | list | `[]` | Extra objects to deploy (value evaluated as a template) | | fullnameOverride | string | `""` | the full name of the release (can be overridden) | +| gatewayApi | object | `{"annotations":{},"enabled":false,"hosts":[],"labels":{},"parentRefs":[]}` | Gateway API (HTTPRoute) resources. Independent of `ingress`; both may be enabled if desired. | +| gatewayApi.annotations | object | `{}` | Annotations for all HTTPRoute resources created by this chart | +| gatewayApi.hosts | list | `[]` | Same shape as `ingress.hosts`. Each entry becomes one HTTPRoute; omit or use empty `paths` to skip an entry. | +| gatewayApi.labels | object | `{}` | Extra labels for all HTTPRoute resources created by this chart | +| gatewayApi.parentRefs | list | `[]` | parentRefs attach HTTPRoutes to an existing Gateway (or other supported parent). Required when `gatewayApi.enabled` is true. [Gateway API parent reference](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ParentReference) | | image.imagePullPolicy | string | `"IfNotPresent"` | the imagePullPolicy for the main pod image | | image.imagePullSecrets | list | `[]` | an array of kubernetes secrets for pulling the main pod image from private registries | | image.repository | string | `"rstudio/rstudio-package-manager"` | the repository to use for the main pod image | @@ -281,5 +317,5 @@ The Helm `config` values are converted into the `rstudio-pm.gcfg` service config | versionOverride | string | `""` | A Package Manager version to override the "tag" for the RStudio Package Manager image. Necessary until https://github.com/helm/helm/issues/8194 | ---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.13.1](https://github.com/norwoodj/helm-docs/releases/v1.13.1) +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/charts/rstudio-pm/README.md.gotmpl b/charts/rstudio-pm/README.md.gotmpl index 4a77167eb..25d173813 100644 --- a/charts/rstudio-pm/README.md.gotmpl +++ b/charts/rstudio-pm/README.md.gotmpl @@ -122,6 +122,37 @@ awsSecretAccessKey: your-secret-access-key Bear in mind that static, long-lived credentials are the least secure option and should be avoided if at all possible. +## Gateway API + +This chart can optionally create Kubernetes [Gateway API](https://gateway-api.sigs.k8s.io/) `HTTPRoute` resources that point at the chart `Service`. This is controlled with `gatewayApi.enabled` and is **independent** of the built-in `Ingress` (`ingress.enabled`); you may enable one, both, or neither. + +**Prerequisites:** Install the Gateway API CRDs in your cluster and provision a `Gateway` (and `GatewayClass`) appropriate for your ingress controller. This chart does not create a `Gateway` resource; set `gatewayApi.parentRefs` to attach each `HTTPRoute` to your existing `Gateway`. + +**TLS:** Termination is typically configured on the `Gateway` listener or by your controller, not on `HTTPRoute`. This chart does not mirror `ingress.tls` onto Gateway API resources. + +**Cross-namespace parents:** If the `Gateway` lives in another namespace, ensure your controller requirements are met (for example a [`ReferenceGrant`](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ReferenceGrant)). + +Example: + +```yaml +gatewayApi: + enabled: true + parentRefs: + - name: contour + namespace: projectcontour + kind: Gateway + group: gateway.networking.k8s.io + hosts: + - host: package-manager.example.com + paths: + - path: / + pathType: Prefix +``` + +Path entries use the same shape as `ingress.hosts` paths: a string or an object with `path` and optional `pathType` (`Prefix`, `Exact`, or `ImplementationSpecific`). Each `gatewayApi.hosts` entry becomes one `HTTPRoute`. The backend uses `service.port`, which must be numeric for the Gateway API `backendRef`. + +**Examples:** Shared-gateway walkthroughs for [AWS Load Balancer Controller (ALB)](../../examples/gateway-api/aws/README.md) and [KGateway](../../examples/gateway-api/kgateway/README.md) live under `examples/gateway-api/` in this repository. + ## General principles - In most places, we opt to pass Helm values over configmaps. We translate these into the valid `.gcfg` file format diff --git a/charts/rstudio-pm/lint/gateway-api-values.yaml b/charts/rstudio-pm/lint/gateway-api-values.yaml new file mode 100644 index 000000000..b2894fad8 --- /dev/null +++ b/charts/rstudio-pm/lint/gateway-api-values.yaml @@ -0,0 +1,24 @@ +license: + key: test +nodePort: 32420 +metricsNodePort: 32112 +replicas: 1 +config: + HTTP: + Listen: :4242 + Server: + DataDir: /var/lib/rstudio-pm + RVersion: + - /opt/R/3.6.2 + Git: + BuilderDir: "/tmp/git" +gatewayApi: + enabled: true + parentRefs: + - name: example-gateway + kind: Gateway + group: gateway.networking.k8s.io + hosts: + - host: pm.example.com + paths: + - / diff --git a/charts/rstudio-pm/templates/httproute.yaml b/charts/rstudio-pm/templates/httproute.yaml new file mode 100644 index 000000000..769bd28fa --- /dev/null +++ b/charts/rstudio-pm/templates/httproute.yaml @@ -0,0 +1,37 @@ +{{- if and .Values.gatewayApi.enabled .Values.gatewayApi.hosts -}} +{{- $apiVersion := include "rstudio-library.gateway.apiVersion" . -}} +{{- $fullName := include "rstudio-pm.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- $root := . -}} +{{- range $i, $h := .Values.gatewayApi.hosts }} +{{- if and $h.paths (gt (len $h.paths) 0) }} +--- +apiVersion: {{ $apiVersion }} +kind: HTTPRoute +metadata: + name: {{ include "rstudio-library.gateway.httpRouteName" (dict "fullName" $fullName "index" $i) }} + labels: + {{- include "rstudio-pm.labels" $root | nindent 4 }} + {{- with $root.Values.gatewayApi.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with $root.Values.gatewayApi.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + parentRefs: + {{- toYaml $root.Values.gatewayApi.parentRefs | nindent 4 }} + hostnames: + - {{ $h.host | quote }} + rules: + - matches: + {{- range $h.paths }} + - path: + {{- include "rstudio-library.gateway.httpPathMatchBody" (dict "pathData" .) | nindent 12 }} + {{- end }} + backendRefs: + {{- include "rstudio-library.gateway.serviceBackendRef" (dict "svcName" $fullName "svcPort" $svcPort) | nindent 8 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/rstudio-pm/tests/gateway_api_test.yaml b/charts/rstudio-pm/tests/gateway_api_test.yaml new file mode 100644 index 000000000..fac4adb86 --- /dev/null +++ b/charts/rstudio-pm/tests/gateway_api_test.yaml @@ -0,0 +1,84 @@ +suite: Package Manager Gateway API +templates: + - httproute.yaml +tests: + - it: should not create HTTPRoute when gatewayApi is disabled + template: httproute.yaml + asserts: + - hasDocuments: + count: 0 + - it: should not create HTTPRoute when enabled but hosts is empty + template: httproute.yaml + set: + gatewayApi: + enabled: true + parentRefs: + - name: gw + kind: Gateway + group: gateway.networking.k8s.io + hosts: [] + asserts: + - hasDocuments: + count: 0 + - it: should create HTTPRoute when enabled with hosts and parentRefs + template: httproute.yaml + set: + gatewayApi: + enabled: true + annotations: + test.io/route: "true" + labels: + test.io/kind: httproute + parentRefs: + - name: test-gateway + namespace: gw-ns + kind: Gateway + group: gateway.networking.k8s.io + hosts: + - host: example.com + paths: + - / + - path: /api + pathType: Prefix + asserts: + - hasDocuments: + count: 1 + - isKind: + of: HTTPRoute + apiVersion: gateway.networking.k8s.io/v1 + - equal: + path: metadata.name + value: RELEASE-NAME-rstudio-pm-gw-0 + - equal: + path: metadata.annotations["test.io/route"] + value: "true" + - equal: + path: metadata.labels["test.io/kind"] + value: httproute + - equal: + path: spec.parentRefs[0].name + value: test-gateway + - equal: + path: spec.parentRefs[0].namespace + value: gw-ns + - equal: + path: spec.hostnames[0] + value: example.com + - equal: + path: spec.rules[0].matches[0].path.type + value: PathPrefix + - equal: + path: spec.rules[0].matches[0].path.value + value: / + - equal: + path: spec.rules[0].matches[1].path.type + value: PathPrefix + - equal: + path: spec.rules[0].matches[1].path.value + value: /api + - equal: + path: spec.rules[0].backendRefs[0].name + value: RELEASE-NAME-rstudio-pm + - equal: + path: spec.rules[0].backendRefs[0].port + value: 80 diff --git a/charts/rstudio-pm/values.yaml b/charts/rstudio-pm/values.yaml index a79e8f366..5a6d5a550 100644 --- a/charts/rstudio-pm/values.yaml +++ b/charts/rstudio-pm/values.yaml @@ -212,6 +212,29 @@ ingress: # hosts: # - chart-example.local +# -- Gateway API (HTTPRoute) resources. Independent of `ingress`; both may be enabled if desired. +gatewayApi: + enabled: false + # -- Annotations for all HTTPRoute resources created by this chart + annotations: {} + # -- Extra labels for all HTTPRoute resources created by this chart + labels: {} + # -- parentRefs attach HTTPRoutes to an existing Gateway (or other supported parent). + # Required when `gatewayApi.enabled` is true. + # [Gateway API parent reference](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ParentReference) + parentRefs: [] + # - name: example-gateway + # namespace: gateway-namespace + # kind: Gateway + # group: gateway.networking.k8s.io + # -- Same shape as `ingress.hosts`. Each entry becomes one HTTPRoute; omit or use empty `paths` to skip an entry. + hosts: [] + # - host: chart-example.local + # paths: + # - / + # # or path: /api + # # pathType: Prefix + serviceAccount: # -- Whether to create a [Service Account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) create: true diff --git a/charts/rstudio-workbench/Chart.lock b/charts/rstudio-workbench/Chart.lock index 937b5a356..aee0b7340 100644 --- a/charts/rstudio-workbench/Chart.lock +++ b/charts/rstudio-workbench/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: rstudio-library repository: https://helm.rstudio.com - version: 0.1.35 -digest: sha256:59fe5e712690610495d2ff32c6c78cc136e9685a785151d4cdba4b914d110f87 -generated: "2025-10-09T13:37:30.250316-05:00" + version: 0.1.37 +digest: sha256:43574c2b3fcee11a2ad66364bdb49510315e447caf4a5d829019adf53782f478 +generated: "2025-03-23T00:00:00Z" diff --git a/charts/rstudio-workbench/Chart.yaml b/charts/rstudio-workbench/Chart.yaml index 266f67037..8a9672d47 100644 --- a/charts/rstudio-workbench/Chart.yaml +++ b/charts/rstudio-workbench/Chart.yaml @@ -1,6 +1,6 @@ name: rstudio-workbench description: Official Helm chart for Posit Workbench -version: 0.11.2 +version: 0.11.3 apiVersion: v2 appVersion: 2026.04.0 icon: @@ -14,7 +14,7 @@ maintainers: url: https://github.com/sol-eng dependencies: - name: rstudio-library - version: 0.1.35 + version: 0.1.37 repository: https://helm.rstudio.com annotations: artifacthub.io/images: | diff --git a/charts/rstudio-workbench/Makefile b/charts/rstudio-workbench/Makefile index 58c53defc..de244b780 100644 --- a/charts/rstudio-workbench/Makefile +++ b/charts/rstudio-workbench/Makefile @@ -1,6 +1,7 @@ lint: helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./ci/complex-values.yaml . helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./ci/simple-values.yaml . + helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./lint/gateway-api-values.yaml . helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./ci/empty-values.yaml . helm lint --strict --set service.name=example --set service.version=0.0.1 -f ./ci/overrides-values.yaml . diff --git a/charts/rstudio-workbench/NEWS.md b/charts/rstudio-workbench/NEWS.md index 65eb64ba5..608e23e95 100644 --- a/charts/rstudio-workbench/NEWS.md +++ b/charts/rstudio-workbench/NEWS.md @@ -1,6 +1,11 @@ # Changelog +## 0.11.3 + +- Document shared Gateway API examples (`examples/gateway-api/aws`, `examples/gateway-api/kgateway`) in the README. +- Add optional Gateway API support (`HTTPRoute` via `gatewayApi` values), independent of `ingress`. + ## 0.11.2 - Lower the default `revisionHistoryLimit` from `10` to `3` to prevent old ReplicaSets and their completed pods from accumulating across rolling updates. Operators can override via `revisionHistoryLimit` in values. diff --git a/charts/rstudio-workbench/README.md b/charts/rstudio-workbench/README.md index c84eb1053..fa2db5fcd 100644 --- a/charts/rstudio-workbench/README.md +++ b/charts/rstudio-workbench/README.md @@ -1,6 +1,6 @@ # Posit Workbench -![Version: 0.11.2](https://img.shields.io/badge/Version-0.11.2-informational?style=flat-square) ![AppVersion: 2026.04.0](https://img.shields.io/badge/AppVersion-2026.04.0-informational?style=flat-square) +![Version: 0.11.3](https://img.shields.io/badge/Version-0.11.3-informational?style=flat-square) ![AppVersion: 2026.04.0](https://img.shields.io/badge/AppVersion-2026.04.0-informational?style=flat-square) #### _Official Helm chart for Posit Workbench_ @@ -24,11 +24,11 @@ To ensure a stable production deployment: ## Installing the chart -To install the chart with the release name `my-release` at version 0.11.2: +To install the chart with the release name `my-release` at version 0.11.3: ```{.bash} helm repo add rstudio https://helm.rstudio.com -helm upgrade --install my-release rstudio/rstudio-workbench --version=0.11.2 +helm upgrade --install my-release rstudio/rstudio-workbench --version=0.11.3 ``` To explore other chart versions, look at: @@ -608,6 +608,37 @@ To activate the use of `SealedSecret` templates instead of `Secret` templates in Use of [Sealed secrets](https://github.com/bitnami-labs/sealed-secrets) disables the chart's auto-generation and reuse capabilities for `launcherPem` and `secureCookieKey`. `launcherPem` is an RSA private key, which can be generated via an RSA tool such as Helm's [`genPrivateKey`](https://helm.sh/docs/chart_template_guide/function_list/#genprivatekey) function. `secureCookieKey` is typically a UUID, which can be generated via a UUID generator such as Helm's [`uuidv4`](https://helm.sh/docs/chart_template_guide/function_list/#uuid-functions) function. +## Gateway API + +This chart can optionally create Kubernetes [Gateway API](https://gateway-api.sigs.k8s.io/) `HTTPRoute` resources that point at the chart `Service`. This is controlled with `gatewayApi.enabled` and is **independent** of the built-in `Ingress` (`ingress.enabled`); you may enable one, both, or neither. + +**Prerequisites:** Install the Gateway API CRDs in your cluster and provision a `Gateway` (and `GatewayClass`) appropriate for your ingress controller. This chart does not create a `Gateway` resource; set `gatewayApi.parentRefs` to attach each `HTTPRoute` to your existing `Gateway`. + +**TLS:** Termination is typically configured on the `Gateway` listener or by your controller, not on `HTTPRoute`. This chart does not mirror `ingress.tls` onto Gateway API resources. + +**Cross-namespace parents:** If the `Gateway` lives in another namespace, ensure your controller requirements are met (for example a [`ReferenceGrant`](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ReferenceGrant)). + +Example: + +```yaml +gatewayApi: + enabled: true + parentRefs: + - name: contour + namespace: projectcontour + kind: Gateway + group: gateway.networking.k8s.io + hosts: + - host: workbench.example.com + paths: + - path: / + pathType: Prefix +``` + +Path entries use the same shape as `ingress.hosts` paths: a string or an object with `path` and optional `pathType` (`Prefix`, `Exact`, or `ImplementationSpecific`). Each `gatewayApi.hosts` entry becomes one `HTTPRoute`. The backend uses `service.port`, which must be numeric for the Gateway API `backendRef`. + +**Examples:** Shared-gateway walkthroughs for [AWS Load Balancer Controller (ALB)](../../examples/gateway-api/aws/README.md) and [KGateway](../../examples/gateway-api/kgateway/README.md) live under `examples/gateway-api/` in this repository. + ## Values | Key | Type | Default | Description | @@ -667,6 +698,11 @@ Use of [Sealed secrets](https://github.com/bitnami-labs/sealed-secrets) disables | diagnostics | object | `{"directory":"/var/log/rstudio","enabled":false}` | Settings for enabling server diagnostics | | extraObjects | list | `[]` | Extra objects to deploy (value evaluated as a template) | | fullnameOverride | string | `""` | the full name of the release (can be overridden) | +| gatewayApi | object | `{"annotations":{},"enabled":false,"hosts":[],"labels":{},"parentRefs":[]}` | Gateway API (HTTPRoute) resources. Independent of `ingress`; both may be enabled if desired. | +| gatewayApi.annotations | object | `{}` | Annotations for all HTTPRoute resources created by this chart | +| gatewayApi.hosts | list | `[]` | Same shape as `ingress.hosts`. Each entry becomes one HTTPRoute; omit or use empty `paths` to skip an entry. | +| gatewayApi.labels | object | `{}` | Extra labels for all HTTPRoute resources created by this chart | +| gatewayApi.parentRefs | list | `[]` | parentRefs attach HTTPRoutes to an existing Gateway (or other supported parent). Required when `gatewayApi.enabled` is true. [Gateway API parent reference](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ParentReference) | | global.secureCookieKey | object | `{"existingSecret":"","value":""}` | global.secureCookieKey takes precedence over secureCookieKey | | global.secureCookieKey.existingSecret | string | `""` | Secret containing secureCookieKey. Will take precedence over `global.secureCookieKey.value`. Key: 'secure-cookie-key' | | global.secureCookieKey.value | string | `""` | Will only be used if `global.secureCookieKey.existingSecret` is not set | @@ -798,5 +834,5 @@ Use of [Sealed secrets](https://github.com/bitnami-labs/sealed-secrets) disables | xdgConfigDirsExtra | list | `[]` | A list of additional XDG config dir paths | ---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.13.1](https://github.com/norwoodj/helm-docs/releases/v1.13.1) +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/charts/rstudio-workbench/README.md.gotmpl b/charts/rstudio-workbench/README.md.gotmpl index 36dbf5f2e..2348a5577 100644 --- a/charts/rstudio-workbench/README.md.gotmpl +++ b/charts/rstudio-workbench/README.md.gotmpl @@ -554,6 +554,37 @@ To activate the use of `SealedSecret` templates instead of `Secret` templates in Use of [Sealed secrets](https://github.com/bitnami-labs/sealed-secrets) disables the chart's auto-generation and reuse capabilities for `launcherPem` and `secureCookieKey`. `launcherPem` is an RSA private key, which can be generated via an RSA tool such as Helm's [`genPrivateKey`](https://helm.sh/docs/chart_template_guide/function_list/#genprivatekey) function. `secureCookieKey` is typically a UUID, which can be generated via a UUID generator such as Helm's [`uuidv4`](https://helm.sh/docs/chart_template_guide/function_list/#uuid-functions) function. +## Gateway API + +This chart can optionally create Kubernetes [Gateway API](https://gateway-api.sigs.k8s.io/) `HTTPRoute` resources that point at the chart `Service`. This is controlled with `gatewayApi.enabled` and is **independent** of the built-in `Ingress` (`ingress.enabled`); you may enable one, both, or neither. + +**Prerequisites:** Install the Gateway API CRDs in your cluster and provision a `Gateway` (and `GatewayClass`) appropriate for your ingress controller. This chart does not create a `Gateway` resource; set `gatewayApi.parentRefs` to attach each `HTTPRoute` to your existing `Gateway`. + +**TLS:** Termination is typically configured on the `Gateway` listener or by your controller, not on `HTTPRoute`. This chart does not mirror `ingress.tls` onto Gateway API resources. + +**Cross-namespace parents:** If the `Gateway` lives in another namespace, ensure your controller requirements are met (for example a [`ReferenceGrant`](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ReferenceGrant)). + +Example: + +```yaml +gatewayApi: + enabled: true + parentRefs: + - name: contour + namespace: projectcontour + kind: Gateway + group: gateway.networking.k8s.io + hosts: + - host: workbench.example.com + paths: + - path: / + pathType: Prefix +``` + +Path entries use the same shape as `ingress.hosts` paths: a string or an object with `path` and optional `pathType` (`Prefix`, `Exact`, or `ImplementationSpecific`). Each `gatewayApi.hosts` entry becomes one `HTTPRoute`. The backend uses `service.port`, which must be numeric for the Gateway API `backendRef`. + +**Examples:** Shared-gateway walkthroughs for [AWS Load Balancer Controller (ALB)](../../examples/gateway-api/aws/README.md) and [KGateway](../../examples/gateway-api/kgateway/README.md) live under `examples/gateway-api/` in this repository. + {{ template "chart.valuesSection" . }} {{ template "helm-docs.versionFooter" . }} diff --git a/charts/rstudio-workbench/lint/gateway-api-values.yaml b/charts/rstudio-workbench/lint/gateway-api-values.yaml new file mode 100644 index 000000000..ddd0b6732 --- /dev/null +++ b/charts/rstudio-workbench/lint/gateway-api-values.yaml @@ -0,0 +1,21 @@ +license: + key: test +replicas: 1 +rbac: + create: true +homeStorage: + create: true +userCreate: true + +securityContext: + privileged: false +gatewayApi: + enabled: true + parentRefs: + - name: example-gateway + kind: Gateway + group: gateway.networking.k8s.io + hosts: + - host: workbench.example.com + paths: + - / diff --git a/charts/rstudio-workbench/templates/httproute.yaml b/charts/rstudio-workbench/templates/httproute.yaml new file mode 100644 index 000000000..c393b1489 --- /dev/null +++ b/charts/rstudio-workbench/templates/httproute.yaml @@ -0,0 +1,37 @@ +{{- if and .Values.gatewayApi.enabled .Values.gatewayApi.hosts -}} +{{- $apiVersion := include "rstudio-library.gateway.apiVersion" . -}} +{{- $fullName := include "rstudio-workbench.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- $root := . -}} +{{- range $i, $h := .Values.gatewayApi.hosts }} +{{- if and $h.paths (gt (len $h.paths) 0) }} +--- +apiVersion: {{ $apiVersion }} +kind: HTTPRoute +metadata: + name: {{ include "rstudio-library.gateway.httpRouteName" (dict "fullName" $fullName "index" $i) }} + labels: + {{- include "rstudio-workbench.labels" $root | nindent 4 }} + {{- with $root.Values.gatewayApi.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with $root.Values.gatewayApi.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + parentRefs: + {{- toYaml $root.Values.gatewayApi.parentRefs | nindent 4 }} + hostnames: + - {{ $h.host | quote }} + rules: + - matches: + {{- range $h.paths }} + - path: + {{- include "rstudio-library.gateway.httpPathMatchBody" (dict "pathData" .) | nindent 12 }} + {{- end }} + backendRefs: + {{- include "rstudio-library.gateway.serviceBackendRef" (dict "svcName" $fullName "svcPort" $svcPort) | nindent 8 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/rstudio-workbench/tests/gateway_api_test.yaml b/charts/rstudio-workbench/tests/gateway_api_test.yaml new file mode 100644 index 000000000..1244f7fbf --- /dev/null +++ b/charts/rstudio-workbench/tests/gateway_api_test.yaml @@ -0,0 +1,84 @@ +suite: Workbench Gateway API +templates: + - httproute.yaml +tests: + - it: should not create HTTPRoute when gatewayApi is disabled + template: httproute.yaml + asserts: + - hasDocuments: + count: 0 + - it: should not create HTTPRoute when enabled but hosts is empty + template: httproute.yaml + set: + gatewayApi: + enabled: true + parentRefs: + - name: gw + kind: Gateway + group: gateway.networking.k8s.io + hosts: [] + asserts: + - hasDocuments: + count: 0 + - it: should create HTTPRoute when enabled with hosts and parentRefs + template: httproute.yaml + set: + gatewayApi: + enabled: true + annotations: + test.io/route: "true" + labels: + test.io/kind: httproute + parentRefs: + - name: test-gateway + namespace: gw-ns + kind: Gateway + group: gateway.networking.k8s.io + hosts: + - host: example.com + paths: + - / + - path: /api + pathType: Prefix + asserts: + - hasDocuments: + count: 1 + - isKind: + of: HTTPRoute + apiVersion: gateway.networking.k8s.io/v1 + - equal: + path: metadata.name + value: RELEASE-NAME-rstudio-workbench-gw-0 + - equal: + path: metadata.annotations["test.io/route"] + value: "true" + - equal: + path: metadata.labels["test.io/kind"] + value: httproute + - equal: + path: spec.parentRefs[0].name + value: test-gateway + - equal: + path: spec.parentRefs[0].namespace + value: gw-ns + - equal: + path: spec.hostnames[0] + value: example.com + - equal: + path: spec.rules[0].matches[0].path.type + value: PathPrefix + - equal: + path: spec.rules[0].matches[0].path.value + value: / + - equal: + path: spec.rules[0].matches[1].path.type + value: PathPrefix + - equal: + path: spec.rules[0].matches[1].path.value + value: /api + - equal: + path: spec.rules[0].backendRefs[0].name + value: RELEASE-NAME-rstudio-workbench + - equal: + path: spec.rules[0].backendRefs[0].port + value: 80 diff --git a/charts/rstudio-workbench/values.yaml b/charts/rstudio-workbench/values.yaml index 42984531f..3f6b52e63 100644 --- a/charts/rstudio-workbench/values.yaml +++ b/charts/rstudio-workbench/values.yaml @@ -258,6 +258,29 @@ ingress: # hosts: # - chart-example.local +# -- Gateway API (HTTPRoute) resources. Independent of `ingress`; both may be enabled if desired. +gatewayApi: + enabled: false + # -- Annotations for all HTTPRoute resources created by this chart + annotations: {} + # -- Extra labels for all HTTPRoute resources created by this chart + labels: {} + # -- parentRefs attach HTTPRoutes to an existing Gateway (or other supported parent). + # Required when `gatewayApi.enabled` is true. + # [Gateway API parent reference](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ParentReference) + parentRefs: [] + # - name: example-gateway + # namespace: gateway-namespace + # kind: Gateway + # group: gateway.networking.k8s.io + # -- Same shape as `ingress.hosts`. Each entry becomes one HTTPRoute; omit or use empty `paths` to skip an entry. + hosts: [] + # - host: chart-example.local + # paths: + # - / + # # or path: /api + # # pathType: Prefix + # -- whether to provide `shareProcessNamespace` to the pod. shareProcessNamespace: false diff --git a/examples/connect/ingress/aws-alb.qmd b/examples/connect/ingress/aws-alb.qmd index 7e226d32a..7a09142ab 100644 --- a/examples/connect/ingress/aws-alb.qmd +++ b/examples/connect/ingress/aws-alb.qmd @@ -10,6 +10,12 @@ This example is provided to show how to set annotations to enabled session affin The AWS Load Balancer Controller has a variety of settings and modes of operation. Please visit the [AWS documentation](https://kubernetes-sigs.github.io/aws-load-balancer-controller/) for more details specific to your use case. +## Sharing one ALB across multiple Ingresses + +Separate Ingress objects can each provision a separate ALB. To merge **multiple** Ingresses onto **one** ALB, set the same [`alb.ingress.kubernetes.io/group.name`](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/ingress/annotations/#group.name) annotation on every Ingress (IngressGroup). The example `values.yaml` below includes a commented `group.name` line you can enable consistently across Connect, Package Manager, and Workbench releases. + +For a **single load balancer** using **Gateway API** (`Gateway` + chart `HTTPRoute` values) instead of Ingress, see the repository [gateway-api/aws example](../../gateway-api/aws/README.md). + {{< include ../_prereqs.qmd >}} ```{.yaml include="rstudio-connect-alb-ingress.yaml" filename="values.yaml"} diff --git a/examples/connect/ingress/rstudio-connect-alb-ingress.yaml b/examples/connect/ingress/rstudio-connect-alb-ingress.yaml index b384ed760..704402b78 100644 --- a/examples/connect/ingress/rstudio-connect-alb-ingress.yaml +++ b/examples/connect/ingress/rstudio-connect-alb-ingress.yaml @@ -21,6 +21,9 @@ ingress: enabled: true ingressClassName: "alb" # TODO: Fill in your desired ingressClassName for the ingress resource. If blank it will use the cluster default. annotations: + # Optional: set the same group name on every Posit Ingress to merge them onto one ALB (IngressGroup). + # https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/ingress/annotations/#group.name + # alb.ingress.kubernetes.io/group.name: posit-shared alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true,stickiness.lb_cookie.duration_seconds=86400 # required for session affinity alb.ingress.kubernetes.io/target-type: ip # target-type: ip is required to work with sticky sessions alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' diff --git a/examples/gateway-api/README.md b/examples/gateway-api/README.md new file mode 100644 index 000000000..729dfeb5d --- /dev/null +++ b/examples/gateway-api/README.md @@ -0,0 +1,14 @@ +# Gateway API examples (shared gateway) + +These examples show how to front **Posit Connect**, **Package Manager**, and **Workbench** with a **single** Kubernetes [Gateway API](https://gateway-api.sigs.k8s.io/) `Gateway` and one external load balancer / proxy, while the Helm charts create only `HTTPRoute` resources (`gatewayApi` values). + +Pick the track that matches your ingress implementation: + +| Directory | Controller / dataplane | Notes | +|-----------|------------------------|--------| +| [aws](./aws/) | [AWS Load Balancer Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller/) (ALB) | AWS-specific `LoadBalancerConfiguration`, ACM certificate ARNs, subnet tagging | +| [kgateway](./kgateway/) | [KGateway](https://kgateway.dev/) (Envoy) | Cloud-agnostic Gateway API; install KGateway first, then apply the example `Gateway` | + +For classic **Ingress** on AWS (multiple `Ingress` objects, one ALB), see the [IngressGroup / `group.name`](../connect/ingress/aws-alb.qmd) notes in the per-product ALB examples. + +The product charts do not render `Gateway` or `GatewayClass`; apply the manifests in these directories (or your own equivalents), then set `gatewayApi.parentRefs` on each Helm release as shown in each track’s `values-gateway-api.yaml`. diff --git a/examples/gateway-api/aws/README.md b/examples/gateway-api/aws/README.md new file mode 100644 index 000000000..e82a16a35 --- /dev/null +++ b/examples/gateway-api/aws/README.md @@ -0,0 +1,45 @@ +# Shared AWS ALB via Gateway API + +This walkthrough provisions **one** Application Load Balancer for **Connect**, **Package Manager**, and **Workbench** using the [AWS Load Balancer Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller/) (LBC) **Layer 7 Gateway API** support. Each product Helm release attaches `HTTPRoute` objects to the same `Gateway` via `gatewayApi.parentRefs`. + +## Validation matrix (verify-aws-lbc) + +Confirm versions against [LBC Gateway API documentation](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/gateway/gateway/) (upstream moves with releases): + +| Requirement | Typical minimum / note | +|---------------|-------------------------| +| AWS Load Balancer Controller | **≥ v2.14.0** for ALB + `HTTPRoute` | +| Gateway API CRDs | **v1.5.0** standard install (per LBC docs) | +| LBC Gateway CRDs | `gateway-crds.yaml` from the [LBC repo](https://github.com/kubernetes-sigs/aws-load-balancer-controller) (includes `LoadBalancerConfiguration`, etc.) | +| `GatewayClass.spec.controllerName` | `gateway.k8s.aws/alb` | + +**AWS-specific behavior:** ALB Gateway does **not** use `ListenerTLSConfig.certificateRefs` on the `Gateway`; TLS uses **`LoadBalancerConfiguration`** (`defaultCertificate` ACM ARN). See [L7 gateway guide](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/gateway/l7gateway/). + +**Cross-namespace routes:** If each product runs in a different namespace than the `Gateway`, set `listeners[].allowedRoutes.namespaces.from: All` (or a `Selector` that includes those namespaces) **and** create a [`ReferenceGrant`](https://gateway-api.sigs.k8s.io/api-types/referencegrant/) in the **Gateway’s namespace** so `HTTPRoute`s in product namespaces may attach to the `Gateway`. Example: [`referencegrant.yaml`](./referencegrant.yaml). + +**Same namespace:** If the `Gateway` and all products share one namespace, you can use `allowedRoutes.namespaces.from: Same` and omit `ReferenceGrant`. + +**Subnet tags, security groups, target type:** Follow LBC [subnet discovery](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/deploy/subnet_discovery/) and [Gateway API](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/gateway/gateway/) notes. For pod IP targeting and stickiness similar to the Ingress ALB examples, use [`TargetGroupConfiguration`](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/gateway/customization/) (`targetType: ip`) per Service as needed. + +## Apply order + +1. Install Gateway API CRDs and LBC Gateway CRDs (see LBC prerequisites). +2. Edit and apply [`gatewayclass.yaml`](./gatewayclass.yaml). +3. Edit **ACM ARN** (and namespace) in [`loadbalancerconfiguration.yaml`](./loadbalancerconfiguration.yaml). +4. Edit namespace/name consistency and apply [`gateway.yaml`](./gateway.yaml). +5. If routes are cross-namespace, edit namespaces in [`referencegrant.yaml`](./referencegrant.yaml) and apply it in the **Gateway** namespace. +6. Install or upgrade each product chart with the matching fragment from [`values-gateway-api.yaml`](./values-gateway-api.yaml). + +## `parentRefs` and HTTP + HTTPS + +The AWS LBC example attaches an `HTTPRoute` to **both** `http` and `https` listeners via `sectionName`. The charts pass `parentRefs` through verbatim, so list **two** parent refs (same `name` / `namespace`, different `sectionName`) as in `values-gateway-api.yaml`. + +## Files + +| File | Purpose | +|------|---------| +| `gatewayclass.yaml` | `GatewayClass` with `controllerName: gateway.k8s.aws/alb` | +| `loadbalancerconfiguration.yaml` | ACM certificate on HTTPS listener | +| `gateway.yaml` | Shared `Gateway` with HTTP/HTTPS listeners and `allowedRoutes` | +| `referencegrant.yaml` | Optional cross-namespace attachment for `HTTPRoute` → `Gateway` | +| `values-gateway-api.yaml` | `gatewayApi` Helm values for Connect, PM, and Workbench | diff --git a/examples/gateway-api/aws/gateway.yaml b/examples/gateway-api/aws/gateway.yaml new file mode 100644 index 000000000..1ba877144 --- /dev/null +++ b/examples/gateway-api/aws/gateway.yaml @@ -0,0 +1,26 @@ +# Single ALB for all attached HTTPRoutes. Namespace must match LoadBalancerConfiguration. +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: posit-shared-alb + namespace: posit-gateway +spec: + gatewayClassName: aws-alb + infrastructure: + parametersRef: + group: gateway.k8s.aws + kind: LoadBalancerConfiguration + name: posit-shared-alb-lbconfig + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All + - name: https + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: All diff --git a/examples/gateway-api/aws/gatewayclass.yaml b/examples/gateway-api/aws/gatewayclass.yaml new file mode 100644 index 000000000..6e4243b6a --- /dev/null +++ b/examples/gateway-api/aws/gatewayclass.yaml @@ -0,0 +1,9 @@ +# GatewayClass for AWS Load Balancer Controller (Layer 7 / ALB). +# https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/gateway/l7gateway/ +apiVersion: gateway.networking.k8s.io/v1 +kind: GatewayClass +metadata: + name: aws-alb +spec: + controllerName: gateway.k8s.aws/alb + description: ALB-backed Gateway API (HTTPRoute) for shared Posit ingress. diff --git a/examples/gateway-api/aws/loadbalancerconfiguration.yaml b/examples/gateway-api/aws/loadbalancerconfiguration.yaml new file mode 100644 index 000000000..818fccd90 --- /dev/null +++ b/examples/gateway-api/aws/loadbalancerconfiguration.yaml @@ -0,0 +1,13 @@ +# TLS for HTTPS:443 uses ACM (not Gateway listener certificateRefs) per AWS LBC. +# Replace the ARN and namespace to match your Gateway. +# https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/gateway/l7gateway/ +apiVersion: gateway.k8s.aws/v1beta1 +kind: LoadBalancerConfiguration +metadata: + name: posit-shared-alb-lbconfig + namespace: posit-gateway +spec: + scheme: internet-facing + listenerConfigurations: + - protocolPort: HTTPS:443 + defaultCertificate: arn:aws:acm:REGION:ACCOUNT_ID:certificate/CERT_ID diff --git a/examples/gateway-api/aws/referencegrant.yaml b/examples/gateway-api/aws/referencegrant.yaml new file mode 100644 index 000000000..03b2094be --- /dev/null +++ b/examples/gateway-api/aws/referencegrant.yaml @@ -0,0 +1,22 @@ +# Install in the Gateway namespace (here: posit-gateway). +# Adjust .spec.from[].namespace to the namespaces where Connect, PM, and Workbench HTTPRoutes are created. +# https://gateway-api.sigs.k8s.io/api-types/referencegrant/ +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: ReferenceGrant +metadata: + name: posit-products-to-shared-gateway + namespace: posit-gateway +spec: + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: rstudio-connect + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: rstudio-pm + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: rstudio-workbench + to: + - group: gateway.networking.k8s.io + kind: Gateway diff --git a/examples/gateway-api/aws/values-gateway-api.yaml b/examples/gateway-api/aws/values-gateway-api.yaml new file mode 100644 index 000000000..a5878066d --- /dev/null +++ b/examples/gateway-api/aws/values-gateway-api.yaml @@ -0,0 +1,62 @@ +# ----------------------------------------------------------------------------- +# Posit Connect — add under your values (or merge). HTTPRoute attaches to shared ALB Gateway. +# ----------------------------------------------------------------------------- +# gatewayApi: +# enabled: true +# parentRefs: +# - group: gateway.networking.k8s.io +# kind: Gateway +# name: posit-shared-alb +# namespace: posit-gateway +# sectionName: http +# - group: gateway.networking.k8s.io +# kind: Gateway +# name: posit-shared-alb +# namespace: posit-gateway +# sectionName: https +# hosts: +# - host: connect.example.com +# paths: +# - / + +# ----------------------------------------------------------------------------- +# Posit Package Manager +# ----------------------------------------------------------------------------- +# gatewayApi: +# enabled: true +# parentRefs: +# - group: gateway.networking.k8s.io +# kind: Gateway +# name: posit-shared-alb +# namespace: posit-gateway +# sectionName: http +# - group: gateway.networking.k8s.io +# kind: Gateway +# name: posit-shared-alb +# namespace: posit-gateway +# sectionName: https +# hosts: +# - host: packagemanager.example.com +# paths: +# - / + +# ----------------------------------------------------------------------------- +# Posit Workbench +# ----------------------------------------------------------------------------- +# gatewayApi: +# enabled: true +# parentRefs: +# - group: gateway.networking.k8s.io +# kind: Gateway +# name: posit-shared-alb +# namespace: posit-gateway +# sectionName: http +# - group: gateway.networking.k8s.io +# kind: Gateway +# name: posit-shared-alb +# namespace: posit-gateway +# sectionName: https +# hosts: +# - host: workbench.example.com +# paths: +# - / diff --git a/examples/gateway-api/kgateway/README.md b/examples/gateway-api/kgateway/README.md new file mode 100644 index 000000000..4d517cda2 --- /dev/null +++ b/examples/gateway-api/kgateway/README.md @@ -0,0 +1,31 @@ +# Shared gateway with KGateway (Gateway API only) + +This track is **not** tied to AWS. It assumes you run [KGateway](https://kgateway.dev/) (Envoy-based Kubernetes Gateway API) in your cluster. Install KGateway and the Gateway API CRDs using the [project documentation](https://kgateway.dev/docs/envoy/latest/) for your release. + +When you install KGateway, a `GatewayClass` named **`kgateway`** with `controllerName: kgateway.dev/kgateway` is typically created for you. This example adds a **single shared `Gateway`** that multiple Posit Helm releases attach to via `gatewayApi.parentRefs`. + +## TLS + +The example [`gateway.yaml`](./gateway.yaml) terminates HTTPS using a Kubernetes `tls` **Secret** referenced from the listener (`certificateRefs`), which is portable across clouds. Create the secret in the same namespace as the `Gateway` (for example with `kubectl create secret tls posit-gateway-tls --cert=... --key=...`). + +If you use HTTP only in a lab environment, you can remove the `https` listener and keep a single `http` listener; adjust `gatewayApi.parentRefs` in [`values-gateway-api.yaml`](./values-gateway-api.yaml) to reference only that listener’s `sectionName`. + +## Cross-namespace routes + +If product releases run in namespaces other than the `Gateway` namespace, keep `listeners[].allowedRoutes.namespaces.from: All` (or a selector that includes them) and apply [`referencegrant.yaml`](./referencegrant.yaml) in the **Gateway** namespace. For a single shared namespace, you can use `from: Same` on listeners and omit the `ReferenceGrant`. + +## Apply + +1. Install KGateway per upstream docs. +2. Create TLS secret if using HTTPS (see above). +3. Apply [`gateway.yaml`](./gateway.yaml) (edit namespace / names as needed). +4. Optionally apply [`referencegrant.yaml`](./referencegrant.yaml). +5. Enable `gatewayApi` on each chart using [`values-gateway-api.yaml`](./values-gateway-api.yaml). + +## Files + +| File | Purpose | +|------|---------| +| `gateway.yaml` | Shared `Gateway` using `gatewayClassName: kgateway` | +| `referencegrant.yaml` | Optional cross-namespace `HTTPRoute` → `Gateway` | +| `values-gateway-api.yaml` | `gatewayApi` fragments for Connect, PM, Workbench | diff --git a/examples/gateway-api/kgateway/gateway.yaml b/examples/gateway-api/kgateway/gateway.yaml new file mode 100644 index 000000000..b9196ca36 --- /dev/null +++ b/examples/gateway-api/kgateway/gateway.yaml @@ -0,0 +1,28 @@ +# Shared Envoy gateway (one proxy / LB path) for multiple HTTPRoutes. +# Requires KGateway installed and GatewayClass "kgateway" (controllerName: kgateway.dev/kgateway). +# https://kgateway.dev/docs/envoy/latest/setup/default/ +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: posit-shared + namespace: kgateway-system +spec: + gatewayClassName: kgateway + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All + - name: https + protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + name: posit-gateway-tls + allowedRoutes: + namespaces: + from: All diff --git a/examples/gateway-api/kgateway/referencegrant.yaml b/examples/gateway-api/kgateway/referencegrant.yaml new file mode 100644 index 000000000..0e1e61be6 --- /dev/null +++ b/examples/gateway-api/kgateway/referencegrant.yaml @@ -0,0 +1,21 @@ +# Install in the Gateway namespace (here: kgateway-system). +# Set .spec.from[].namespace to each namespace that will contain Posit HTTPRoutes. +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: ReferenceGrant +metadata: + name: posit-products-to-shared-gateway + namespace: kgateway-system +spec: + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: rstudio-connect + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: rstudio-pm + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: rstudio-workbench + to: + - group: gateway.networking.k8s.io + kind: Gateway diff --git a/examples/gateway-api/kgateway/values-gateway-api.yaml b/examples/gateway-api/kgateway/values-gateway-api.yaml new file mode 100644 index 000000000..45e117b73 --- /dev/null +++ b/examples/gateway-api/kgateway/values-gateway-api.yaml @@ -0,0 +1,62 @@ +# ----------------------------------------------------------------------------- +# Posit Connect — merge into values. Gateway in namespace kgateway-system. +# ----------------------------------------------------------------------------- +# gatewayApi: +# enabled: true +# parentRefs: +# - group: gateway.networking.k8s.io +# kind: Gateway +# name: posit-shared +# namespace: kgateway-system +# sectionName: http +# - group: gateway.networking.k8s.io +# kind: Gateway +# name: posit-shared +# namespace: kgateway-system +# sectionName: https +# hosts: +# - host: connect.example.com +# paths: +# - / + +# ----------------------------------------------------------------------------- +# Posit Package Manager +# ----------------------------------------------------------------------------- +# gatewayApi: +# enabled: true +# parentRefs: +# - group: gateway.networking.k8s.io +# kind: Gateway +# name: posit-shared +# namespace: kgateway-system +# sectionName: http +# - group: gateway.networking.k8s.io +# kind: Gateway +# name: posit-shared +# namespace: kgateway-system +# sectionName: https +# hosts: +# - host: packagemanager.example.com +# paths: +# - / + +# ----------------------------------------------------------------------------- +# Posit Workbench +# ----------------------------------------------------------------------------- +# gatewayApi: +# enabled: true +# parentRefs: +# - group: gateway.networking.k8s.io +# kind: Gateway +# name: posit-shared +# namespace: kgateway-system +# sectionName: http +# - group: gateway.networking.k8s.io +# kind: Gateway +# name: posit-shared +# namespace: kgateway-system +# sectionName: https +# hosts: +# - host: workbench.example.com +# paths: +# - / diff --git a/examples/package-manager/ingress/aws-alb.qmd b/examples/package-manager/ingress/aws-alb.qmd index e8f8689f8..a6da1f200 100644 --- a/examples/package-manager/ingress/aws-alb.qmd +++ b/examples/package-manager/ingress/aws-alb.qmd @@ -9,6 +9,12 @@ This example is provided to show how to set annotations to redirect HTTP traffic The AWS Load Balancer Controller has a variety of settings and modes of operation. Please visit the [AWS documentation](https://kubernetes-sigs.github.io/aws-load-balancer-controller/) for more details specific to your use case. +## Sharing one ALB across multiple Ingresses + +Separate Ingress objects can each provision a separate ALB. To merge **multiple** Ingresses onto **one** ALB, set the same [`alb.ingress.kubernetes.io/group.name`](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/ingress/annotations/#group.name) annotation on every Ingress (IngressGroup). The example `values.yaml` below includes a commented `group.name` line you can enable consistently across Connect, Package Manager, and Workbench releases. + +For a **single load balancer** using **Gateway API** instead of Ingress, see the repository [gateway-api/aws example](../../gateway-api/aws/README.md). + {{< include ../_prereqs.qmd >}} ```{.yaml include="rstudio-pm-alb-ingress.yaml" filename="values.yaml"} diff --git a/examples/package-manager/ingress/rstudio-pm-alb-ingress.yaml b/examples/package-manager/ingress/rstudio-pm-alb-ingress.yaml index 591aaf2a1..4e991f1a3 100644 --- a/examples/package-manager/ingress/rstudio-pm-alb-ingress.yaml +++ b/examples/package-manager/ingress/rstudio-pm-alb-ingress.yaml @@ -22,6 +22,9 @@ ingress: enabled: true ingressClassName: "alb" # TODO: Fill in your desired ingressClassName for the ingress resource. If blank it will use the cluster default. annotations: + # Optional: same group name on each Posit Ingress merges rules onto one ALB (IngressGroup). + # https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/ingress/annotations/#group.name + # alb.ingress.kubernetes.io/group.name: posit-shared alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' alb.ingress.kubernetes.io/ssl-redirect: '443' diff --git a/examples/workbench/ingress/aws-alb.qmd b/examples/workbench/ingress/aws-alb.qmd index 8c2810e47..be301a7a8 100644 --- a/examples/workbench/ingress/aws-alb.qmd +++ b/examples/workbench/ingress/aws-alb.qmd @@ -9,6 +9,12 @@ This example is provided to show how to set annotations to enable session affini The AWS Load Balancer Controller has a variety of settings and modes of operation. Please visit the [AWS documentation](https://kubernetes-sigs.github.io/aws-load-balancer-controller/) for more details specific to your use case. +## Sharing one ALB across multiple Ingresses + +Separate Ingress objects can each provision a separate ALB. To merge **multiple** Ingresses onto **one** ALB, set the same [`alb.ingress.kubernetes.io/group.name`](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/ingress/annotations/#group.name) annotation on every Ingress (IngressGroup). The example `values.yaml` below includes a commented `group.name` line you can enable consistently across Connect, Package Manager, and Workbench releases. + +For a **single load balancer** using **Gateway API** instead of Ingress, see the repository [gateway-api/aws example](../../gateway-api/aws/README.md). + {{< include ../_prereqs.qmd >}} ```{.yaml include="rstudio-workbench-alb-ingress.yaml" filename="values.yaml"} diff --git a/examples/workbench/ingress/rstudio-workbench-alb-ingress.yaml b/examples/workbench/ingress/rstudio-workbench-alb-ingress.yaml index 87ac8edc5..31fb5c770 100644 --- a/examples/workbench/ingress/rstudio-workbench-alb-ingress.yaml +++ b/examples/workbench/ingress/rstudio-workbench-alb-ingress.yaml @@ -29,6 +29,9 @@ ingress: enabled: true ingressClassName: "alb" # TODO: Fill in your desired ingressClassName for the ingress resource. If blank it will use the cluster default. annotations: + # Optional: same group name on each Posit Ingress merges rules onto one ALB (IngressGroup). + # https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/ingress/annotations/#group.name + # alb.ingress.kubernetes.io/group.name: posit-shared alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true,stickiness.lb_cookie.duration_seconds=86400 alb.ingress.kubernetes.io/target-type: ip # target-type: ip is required to work with sticky sessions alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' diff --git a/other-charts/prepull-daemonset/README.md b/other-charts/prepull-daemonset/README.md index 837aac3cf..f43b7562b 100644 --- a/other-charts/prepull-daemonset/README.md +++ b/other-charts/prepull-daemonset/README.md @@ -54,5 +54,5 @@ kubectl rollout restart daemonset/prepull-daemonset | updateStrategy | object | `{}` | | ---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.13.1](https://github.com/norwoodj/helm-docs/releases/v1.13.1) +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/other-charts/rstudio-library-test/README.md b/other-charts/rstudio-library-test/README.md index cc879933d..8bbb659af 100644 --- a/other-charts/rstudio-library-test/README.md +++ b/other-charts/rstudio-library-test/README.md @@ -94,4 +94,4 @@ Test harness for rstudio-library templates | testTplvalues.templateValue | string | `"{{ .Release.Name }}-suffix"` | | ---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.13.1](https://github.com/norwoodj/helm-docs/releases/v1.13.1) +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2)