diff --git a/docs/deploy/gcp/prompt.md b/docs/deploy/gcp/prompt.md index dd904bc023..dd9b0d0d77 100644 --- a/docs/deploy/gcp/prompt.md +++ b/docs/deploy/gcp/prompt.md @@ -39,7 +39,7 @@ Agent-created resource names and defaults (change if required): - Cloud SQL instance name: GCP Cloud SQL resource to create, default `openwork-ee-mysql`. - Cloud SQL database name: MySQL database to create inside Cloud SQL, default `openwork_den`. - Cloud SQL user: MySQL user to create for OpenWork, default `openwork`. -- Reserved global address name: GCP resource name for the static global IPv4 address used by the HTTPS load balancer, default `openwork-ee-ip`. This is not the IP address; the agent creates the address and reports the allocated IP. +- Reserved global address names: GCP resource names for the two static global IPv4 addresses used by the web and API HTTPS load balancers (GKE gives each Ingress its own load balancer, so they cannot share one address). Defaults `openwork-ee-web-ip` and `openwork-ee-api-ip`. These are not the IP addresses; the agent creates the addresses and reports both allocated IPs. Operating rules: @@ -67,7 +67,7 @@ Provision and deploy according to the GCP runbook: - Create or reuse private services access for the target VPC. - Create a regional GKE Autopilot cluster using the requested/default cluster name. - Create Cloud SQL for MySQL 8 with private IP, backups enabled, and public IP disabled unless the docs require otherwise. -- Reserve a global IPv4 address. +- Reserve two global IPv4 addresses, one for the web hostname and one for the API hostname. - Apply the documented GKE `BackendConfig` and `ManagedCertificate` resources. - Create the namespace and runtime Secret. - Install the Helm release using GCP ingress values and the requested/default release name. @@ -76,7 +76,7 @@ Provision and deploy according to the GCP runbook: DNS handoff: -- After the reserved global IP exists, pause and tell me the exact DNS records to create for `{{WEB_HOSTNAME}}` and `{{API_HOSTNAME}}`. +- After both reserved global IPs exist, pause and tell me the exact DNS records to create for `{{WEB_HOSTNAME}}` (pointing at the web address) and `{{API_HOSTNAME}}` (pointing at the API address). - Wait for my confirmation that DNS is updated. - Verify public DNS resolution yourself before continuing. - Do not claim HTTPS is ready until the managed certificate is active and `openssl` or equivalent external checks show trusted certificates for both hostnames. @@ -102,5 +102,5 @@ Track any reusable documentation gaps, failed commands, unclear values, required Final report: -Report `Passed`, `Incomplete`, or `Failed`, plus chart/app version, resources created, reserved IP, DNS records, Cloud SQL tier/region/private-IP/backup state, GKE type/region, Helm revision/status, migration result, pod readiness, backend health, certificate status, external readiness checks, administrator setup result, replay/signup rejection result, sign-out/sign-in result, browser handoffs completed by the operator, non-secret commands run, deviations from docs, documentation PRs, ongoing cost items, and exact cleanup commands. +Report `Passed`, `Incomplete`, or `Failed`, plus chart/app version, resources created, reserved IPs (web and API), DNS records, Cloud SQL tier/region/private-IP/backup state, GKE type/region, Helm revision/status, migration result, pod readiness, backend health, certificate status, external readiness checks, administrator setup result, replay/signup rejection result, sign-out/sign-in result, browser handoffs completed by the operator, non-secret commands run, deviations from docs, documentation PRs, ongoing cost items, and exact cleanup commands. ``` diff --git a/docs/gcp-gke-helm.md b/docs/gcp-gke-helm.md index b447e2511d..0168c53553 100644 --- a/docs/gcp-gke-helm.md +++ b/docs/gcp-gke-helm.md @@ -5,8 +5,9 @@ Related: `packaging/helm/openwork-ee`, `packaging/helm/openwork-ee/examples/valu This is the recommended Google Cloud path for a first production-like OpenWork EE self-host install. Use Helm on GKE Autopilot with Cloud SQL for MySQL. For -web/API exposure, use GKE Ingress with Google-managed certificates, a reserved -global IP address, and explicit backend health checks. +web/API exposure, use two GKE Ingresses (one per host) with a shared +Google-managed certificate, one reserved global IP address per Ingress, and +explicit backend health checks. Google recommends Gateway API for new L7 traffic management, and GKE Ingress is in maintenance mode. The current OpenWork chart emits Ingress resources, so GKE @@ -25,13 +26,14 @@ balancing, host routing, managed certificates, and backend health checks. - optional inference service, disabled by default - one Cloud SQL for MySQL database - one single-org OpenWork deployment -- one external GKE Ingress backed by a Google Cloud Application Load Balancer +- one external GKE Ingress per host (web and API), each backed by its own + Google Cloud Application Load Balancer - one Google-managed certificate covering web and API hosts Google Cloud owns the GKE cluster, Autopilot compute lifecycle, VPC networking, Cloud Load Balancing, managed certificates, Cloud SQL, IAM, and firewall rules. The OpenWork Helm chart owns OpenWork Deployments, Services, ConfigMaps, -Secrets, health probes, the optional Ingress, and the database migration Job. +Secrets, health probes, the optional Ingresses, and the database migration Job. The `BackendConfig` and `ManagedCertificate` resources in this guide are GKE-specific platform resources applied alongside the chart. @@ -197,15 +199,23 @@ kubectl run mysql-client \ --execute "select 1" ``` -## 3. Reserve a global IP and create GKE resources +## 3. Reserve global IPs and create GKE resources -Reserve a global IP address for the HTTPS load balancer: +GKE gives each Ingress its own load balancer, so the web and API Ingresses +each need their own reserved global IP; reusing one static IP name for both +means only one Ingress can bind its forwarding rule and the other never +reconciles. Reserve one address per host: ```bash -gcloud compute addresses create openwork-ee-ip \ +gcloud compute addresses create openwork-ee-web-ip \ + --global +gcloud compute addresses create openwork-ee-api-ip \ --global -gcloud compute addresses describe openwork-ee-ip \ +gcloud compute addresses describe openwork-ee-web-ip \ + --global \ + --format='value(address)' +gcloud compute addresses describe openwork-ee-api-ip \ --global \ --format='value(address)' ``` @@ -407,24 +417,27 @@ migrations: backoffLimit: 2 ``` -## 7. Point DNS at the global load balancer IP +## 7. Point DNS at the global load balancer IPs -Get the reserved IP address: +Get the reserved IP addresses: ```bash -gcloud compute addresses describe openwork-ee-ip \ +gcloud compute addresses describe openwork-ee-web-ip \ + --global \ + --format='value(address)' +gcloud compute addresses describe openwork-ee-api-ip \ --global \ --format='value(address)' ``` Create DNS records: -- `openwork.example.com` -> the reserved global IP address. -- `api.openwork.example.com` -> the reserved global IP address. +- `openwork.example.com` -> the reserved `openwork-ee-web-ip` address. +- `api.openwork.example.com` -> the reserved `openwork-ee-api-ip` address. -GKE can take several minutes to provision the load balancer. Google-managed -certificates can take up to an hour to become active after DNS points at the -load balancer. +GKE can take several minutes to provision each load balancer. Google-managed +certificates can take up to an hour to become active after DNS points at both +load balancers. Check status: @@ -542,7 +555,7 @@ single organization. Password sign-in for that organization is rejected. | Ingress does not reconcile | HTTP load balancing add-on is disabled or Ingress annotation is wrong | Keep HTTP load balancing enabled and use `kubernetes.io/ingress.class: gce` | | Backends are unhealthy | GKE load balancer health checks do not match OpenWork readiness endpoints | Apply the `BackendConfig` resources and keep the service annotations from the starter values | | Ingress events report `TimeoutSec should be less than checkIntervalSec` | The backend health-check timeout is greater than or equal to its effective interval | Set `checkIntervalSec: 15` and `timeoutSec: 5` on both `BackendConfig` resources | -| Managed certificate is not `Active` | DNS does not point at the load balancer or provisioning is still running | Point both hosts at the reserved global IP and wait; check `kubectl describe managedcertificate` | +| Managed certificate is not `Active` | DNS does not point at the corresponding load balancer or provisioning is still running | Point each host at its own reserved global IP and wait; check `kubectl describe managedcertificate` | | Migration Job fails to connect to MySQL | Private services access, VPC, credentials, IP, or TLS mode are wrong | Test from `mysql-client`, confirm the private IP, and confirm GKE and Cloud SQL share VPC reachability | | Migration Job logs show `self-signed certificate in certificate chain` | Strict certificate verification is being used without the cloud MySQL CA bundle | Use `?sslaccept=accept` for the smoke path or mount/configure the CA bundle before strict verification | | `ImagePullBackOff` from GHCR | Private image or missing pull token | Add `imagePullSecrets` | @@ -556,7 +569,8 @@ For a disposable test: ```bash helm uninstall openwork-ee -n openwork-ee -gcloud compute addresses delete openwork-ee-ip --global +gcloud compute addresses delete openwork-ee-web-ip --global +gcloud compute addresses delete openwork-ee-api-ip --global gcloud container clusters delete "$GKE_CLUSTER" --location "$GCP_REGION" gcloud sql instances delete "$SQL_INSTANCE" ``` diff --git a/packages/docs/self-host/deploy-to-your-cloud/google-cloud.mdx b/packages/docs/self-host/deploy-to-your-cloud/google-cloud.mdx index d7cfd538a8..0bd7272bbd 100644 --- a/packages/docs/self-host/deploy-to-your-cloud/google-cloud.mdx +++ b/packages/docs/self-host/deploy-to-your-cloud/google-cloud.mdx @@ -3,7 +3,7 @@ title: "Deploy on Google Cloud" description: "Run OpenWork on GKE Autopilot with Cloud SQL for MySQL." --- -The recommended Google Cloud path is Helm on a regional GKE Autopilot cluster with Cloud SQL for MySQL. Use GKE Ingress, a reserved global IP address, Google-managed certificates, and explicit backend health checks for Den web and Den API. +The recommended Google Cloud path is Helm on a regional GKE Autopilot cluster with Cloud SQL for MySQL. Use two GKE Ingresses (one for Den web, one for Den API), each with its own reserved global IP address, a shared Google-managed certificate, and explicit backend health checks. ## What Google Cloud manages @@ -12,17 +12,17 @@ The recommended Google Cloud path is Helm on a regional GKE Autopilot cluster wi - Cloud SQL for MySQL, encryption, backups, and failover - Cloud DNS and Google-managed certificates when you use those services -The OpenWork chart manages Deployments, Services, ConfigMaps, Secret references, probes, the Ingress, and the database migration Job. GKE `BackendConfig` and `ManagedCertificate` resources are applied alongside the chart. +The OpenWork chart manages Deployments, Services, ConfigMaps, Secret references, probes, the two Ingresses, and the database migration Job. GKE `BackendConfig` and `ManagedCertificate` resources are applied alongside the chart. ## Google Cloud checklist 1. Enable the Kubernetes Engine, Compute Engine, Cloud SQL Admin, and Service Networking APIs. 2. Create a regional GKE Autopilot cluster and install `gke-gcloud-auth-plugin` if your Cloud SDK does not include it. 3. Configure private services access and create Cloud SQL for MySQL with a private IP. -4. Reserve a global IPv4 address and create the GKE health-check and certificate resources. +4. Reserve two global IPv4 addresses (one for each hostname) and create the GKE health-check and certificate resources. 5. Store `DATABASE_URL`, `BETTER_AUTH_SECRET`, and `DEN_DB_ENCRYPTION_KEY` in a Kubernetes Secret. 6. Start from the chart's `values.gcp-ingress.yaml` example, install the chart, and verify migrations and readiness. -7. Point both hostnames at the reserved address and wait for the managed certificate to become active. +7. Point each hostname at its own reserved address and wait for the managed certificate to become active. For exact `gcloud` commands, values, health checks, migration troubleshooting, verification, and cleanup, follow the [GKE operator runbook](https://github.com/different-ai/openwork/blob/dev/docs/gcp-gke-helm.md). diff --git a/packaging/helm/openwork-ee/README.md b/packaging/helm/openwork-ee/README.md index c08681a693..9cd48c184e 100644 --- a/packaging/helm/openwork-ee/README.md +++ b/packaging/helm/openwork-ee/README.md @@ -405,8 +405,9 @@ Provider-specific starter guides: - Google Cloud GKE: [guide](../../../docs/gcp-gke-helm.md), [`examples/values.gcp-ingress.yaml`](examples/values.gcp-ingress.yaml). - The recommended first GCP path is GKE Ingress with a reserved global IP, - Google-managed certificate, and BackendConfig health checks. + The recommended first GCP path is two GKE Ingresses (one per host) each + with its own reserved global IP, a shared Google-managed certificate, and + BackendConfig health checks. `ingress.enabled=true` only emits Kubernetes `Ingress` resources; it does not install an ingress controller. Use it only when the cluster already has a diff --git a/packaging/helm/openwork-ee/examples/values.gcp-ingress.yaml b/packaging/helm/openwork-ee/examples/values.gcp-ingress.yaml index 902dfc3602..732edec838 100644 --- a/packaging/helm/openwork-ee/examples/values.gcp-ingress.yaml +++ b/packaging/helm/openwork-ee/examples/values.gcp-ingress.yaml @@ -94,12 +94,20 @@ migrations: ingress: enabled: true className: "" + # Shared across both Ingress objects: the managed certificate covers both + # hosts, so it is safe to reuse here. The reserved static IP is NOT — GKE + # gives each Ingress its own GCLB, so two Ingresses referencing the same + # global-static-ip-name would fight over one forwarding rule and only one + # would reconcile. Each host therefore gets its own reserved IP below. annotations: kubernetes.io/ingress.class: gce - kubernetes.io/ingress.global-static-ip-name: REPLACE_GLOBAL_STATIC_IP_NAME networking.gke.io/managed-certificates: REPLACE_MANAGED_CERTIFICATE_NAME web: host: REPLACE_WEB_HOST + annotations: + kubernetes.io/ingress.global-static-ip-name: REPLACE_WEB_GLOBAL_STATIC_IP_NAME api: enabled: true host: REPLACE_API_HOST + annotations: + kubernetes.io/ingress.global-static-ip-name: REPLACE_API_GLOBAL_STATIC_IP_NAME diff --git a/packaging/helm/openwork-ee/templates/ingress-api.yaml b/packaging/helm/openwork-ee/templates/ingress-api.yaml new file mode 100644 index 0000000000..511340a0ee --- /dev/null +++ b/packaging/helm/openwork-ee/templates/ingress-api.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.ingress.enabled .Values.ingress.api.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "openwork-ee.fullname" . }}-api + namespace: {{ include "openwork-ee.namespace" . }} + labels: + {{- include "openwork-ee.labels" . | nindent 4 }} + {{- $apiAnnotations := mergeOverwrite (deepCopy .Values.ingress.annotations) .Values.ingress.api.annotations }} + {{- with $apiAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.className }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- with .Values.ingress.tls }} + tls: + {{- toYaml . | nindent 4 }} + {{- end }} + rules: + - host: {{ .Values.ingress.api.host | quote }} + http: + paths: + - path: {{ .Values.ingress.api.path }} + pathType: {{ .Values.ingress.api.pathType }} + backend: + service: + name: {{ include "openwork-ee.denApiServiceName" . }} + port: + name: http +{{- end }} diff --git a/packaging/helm/openwork-ee/templates/ingress.yaml b/packaging/helm/openwork-ee/templates/ingress-den.yaml similarity index 66% rename from packaging/helm/openwork-ee/templates/ingress.yaml rename to packaging/helm/openwork-ee/templates/ingress-den.yaml index a1a01855b8..ae36ae66af 100644 --- a/packaging/helm/openwork-ee/templates/ingress.yaml +++ b/packaging/helm/openwork-ee/templates/ingress-den.yaml @@ -6,7 +6,8 @@ metadata: namespace: {{ include "openwork-ee.namespace" . }} labels: {{- include "openwork-ee.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} + {{- $webAnnotations := mergeOverwrite (deepCopy .Values.ingress.annotations) .Values.ingress.web.annotations }} + {{- with $webAnnotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} @@ -29,16 +30,4 @@ spec: name: {{ include "openwork-ee.denWebServiceName" . }} port: name: http - {{- if .Values.ingress.api.enabled }} - - host: {{ .Values.ingress.api.host | quote }} - http: - paths: - - path: {{ .Values.ingress.api.path }} - pathType: {{ .Values.ingress.api.pathType }} - backend: - service: - name: {{ include "openwork-ee.denApiServiceName" . }} - port: - name: http - {{- end }} {{- end }} diff --git a/packaging/helm/openwork-ee/tests/ingress-split.sh b/packaging/helm/openwork-ee/tests/ingress-split.sh new file mode 100755 index 0000000000..9d509c1f0a --- /dev/null +++ b/packaging/helm/openwork-ee/tests/ingress-split.sh @@ -0,0 +1,149 @@ +#!/usr/bin/env bash +set -euo pipefail + +chart_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +tmp_dir="$(mktemp -d)" +trap 'rm -rf "$tmp_dir"' EXIT + +assert_count() { + local file="$1" + local needle="$2" + local expected="$3" + local count + count="$(grep -F -c -- "$needle" "$file" || true)" + if [[ "$count" != "$expected" ]]; then + printf 'Expected %s occurrences of %s, found %s\n' "$expected" "$needle" "$count" >&2 + return 1 + fi +} + +assert_source_contains() { + local file="$1" + local source="$2" + local needle="$3" + local in_source=0 + local found=0 + local line + + while IFS= read -r line; do + if [[ "$line" == '# Source: openwork-ee/templates/'* ]]; then + if [[ "$line" == "# Source: openwork-ee/templates/$source" ]]; then + in_source=1 + else + in_source=0 + fi + fi + if [[ "$in_source" == 1 && "$line" == *"$needle"* ]]; then + found=1 + break + fi + done < "$file" + + if [[ "$found" != 1 ]]; then + printf 'Expected %s to contain %s\n' "$source" "$needle" >&2 + return 1 + fi +} + +assert_source_not_contains() { + local file="$1" + local source="$2" + local needle="$3" + local in_source=0 + local line + + while IFS= read -r line; do + if [[ "$line" == '# Source: openwork-ee/templates/'* ]]; then + if [[ "$line" == "# Source: openwork-ee/templates/$source" ]]; then + in_source=1 + else + in_source=0 + fi + fi + if [[ "$in_source" == 1 && "$line" == *"$needle"* ]]; then + printf 'Expected %s not to contain %s\n' "$source" "$needle" >&2 + return 1 + fi + done < "$file" +} + +# Disabled by default: neither Ingress renders. +disabled_rendered="$tmp_dir/disabled.yaml" +helm template openwork-ee "$chart_dir" > "$disabled_rendered" +assert_count "$disabled_rendered" 'kind: Ingress' 0 + +# Enabled with API disabled: only the web (den-web) Ingress renders. +api_disabled_values="$tmp_dir/api-disabled-values.yaml" +cat > "$api_disabled_values" <<'YAML' +ingress: + enabled: true + api: + enabled: false +YAML +api_disabled_rendered="$tmp_dir/api-disabled.yaml" +helm template openwork-ee "$chart_dir" -f "$api_disabled_values" > "$api_disabled_rendered" +assert_count "$api_disabled_rendered" 'kind: Ingress' 1 +assert_count "$api_disabled_rendered" 'name: openwork-ee-api' 0 +assert_source_contains "$api_disabled_rendered" 'ingress-den.yaml' 'name: openwork-ee' +assert_source_contains "$api_disabled_rendered" 'ingress-den.yaml' 'host: "openwork.example.com"' +assert_source_contains "$api_disabled_rendered" 'ingress-den.yaml' 'name: openwork-ee-den-web' + +# Enabled with API also enabled (the default `ingress.api.enabled`): two +# independently named Ingresses, each with its own host and backend service. +split_values="$tmp_dir/split-values.yaml" +cat > "$split_values" <<'YAML' +ingress: + enabled: true + annotations: + shared-only: shared-value + shared-and-overridden: shared-value + web: + host: web.example.com + annotations: + web-only: web-value + shared-and-overridden: web-override + api: + host: api.example.com + annotations: + api-only: api-value +YAML +split_rendered="$tmp_dir/split.yaml" +helm template openwork-ee "$chart_dir" -f "$split_values" > "$split_rendered" + +# Two Ingresses, independently named. +assert_count "$split_rendered" 'kind: Ingress' 2 +assert_source_contains "$split_rendered" 'ingress-den.yaml' 'name: openwork-ee' +assert_source_not_contains "$split_rendered" 'ingress-den.yaml' 'name: openwork-ee-api' +assert_source_contains "$split_rendered" 'ingress-api.yaml' 'name: openwork-ee-api' + +# Each Ingress rules to its own host and its own backend Service; neither +# leaks the other's host or Service name into its own render source. +assert_source_contains "$split_rendered" 'ingress-den.yaml' 'host: "web.example.com"' +assert_source_contains "$split_rendered" 'ingress-den.yaml' 'name: openwork-ee-den-web' +assert_source_not_contains "$split_rendered" 'ingress-den.yaml' 'host: "api.example.com"' +assert_source_not_contains "$split_rendered" 'ingress-den.yaml' 'name: openwork-ee-den-api' + +assert_source_contains "$split_rendered" 'ingress-api.yaml' 'host: "api.example.com"' +assert_source_contains "$split_rendered" 'ingress-api.yaml' 'name: openwork-ee-den-api' +assert_source_not_contains "$split_rendered" 'ingress-api.yaml' 'host: "web.example.com"' +assert_source_not_contains "$split_rendered" 'ingress-api.yaml' 'name: openwork-ee-den-web' + +# Shared annotations land on both Ingresses. +assert_source_contains "$split_rendered" 'ingress-den.yaml' 'shared-only: shared-value' +assert_source_contains "$split_rendered" 'ingress-api.yaml' 'shared-only: shared-value' + +# Per-Ingress-only annotations land on exactly one Ingress each. +assert_source_contains "$split_rendered" 'ingress-den.yaml' 'web-only: web-value' +assert_source_not_contains "$split_rendered" 'ingress-api.yaml' 'web-only: web-value' +assert_source_contains "$split_rendered" 'ingress-api.yaml' 'api-only: api-value' +assert_source_not_contains "$split_rendered" 'ingress-den.yaml' 'api-only: api-value' + +# A key set on both the shared and the web-specific annotation maps resolves +# to the web-specific value on the web Ingress (override wins), but keeps the +# shared value on the API Ingress (which set no override for that key). +assert_source_contains "$split_rendered" 'ingress-den.yaml' 'shared-and-overridden: web-override' +assert_source_not_contains "$split_rendered" 'ingress-den.yaml' 'shared-and-overridden: shared-value' +assert_source_contains "$split_rendered" 'ingress-api.yaml' 'shared-and-overridden: shared-value' +assert_source_not_contains "$split_rendered" 'ingress-api.yaml' 'shared-and-overridden: web-override' + +printf 'ingress-split chart checks passed\n' diff --git a/packaging/helm/openwork-ee/tests/namespace.sh b/packaging/helm/openwork-ee/tests/namespace.sh index 2497c4db12..ee39fb14b8 100755 --- a/packaging/helm/openwork-ee/tests/namespace.sh +++ b/packaging/helm/openwork-ee/tests/namespace.sh @@ -156,12 +156,13 @@ assert_count "$legacy_argocd_migration_rendered" 'helm.sh/hook": pre-install,pre # outside this release is not silently adopted. # Full render (ingress + inference + createNamespace all enabled): Namespace + -# 11 namespaced resources. +# 12 namespaced resources (ingress.enabled=true also renders the API Ingress, +# since ingress.api.enabled defaults to true). full_rendered="$tmp_dir/full.yaml" helm template openwork-ee "$chart_dir" \ --set createNamespace=true --set ingress.enabled=true --set inference.enabled=true > "$full_rendered" assert_count "$full_rendered" 'kind: Namespace' 1 -assert_count "$full_rendered" ' namespace: "openwork"' 11 +assert_count "$full_rendered" ' namespace: "openwork"' 12 # Explicit override wins on every resource. override_rendered="$tmp_dir/override.yaml" diff --git a/packaging/helm/openwork-ee/values.yaml b/packaging/helm/openwork-ee/values.yaml index 4019078be5..765cef06ec 100644 --- a/packaging/helm/openwork-ee/values.yaml +++ b/packaging/helm/openwork-ee/values.yaml @@ -464,14 +464,27 @@ migrations: ingress: enabled: false className: "" + # Annotations applied to both the web and API Ingress objects. Keep only + # values that are safe to duplicate across two separate Ingress resources + # here (e.g. ingress class). Provider annotations that must be unique per + # Ingress (GKE's kubernetes.io/ingress.global-static-ip-name, per-host + # healthcheck paths, etc.) belong in ingress.web.annotations / + # ingress.api.annotations instead, since two Ingresses sharing one of those + # would make one of them fail to reconcile. annotations: {} web: host: openwork.example.com path: / pathType: Prefix + # Annotations applied only to the web (den-web) Ingress, merged over + # ingress.annotations. + annotations: {} api: enabled: true host: api.openwork.example.com path: / pathType: Prefix + # Annotations applied only to the API (den-api) Ingress, merged over + # ingress.annotations. + annotations: {} tls: []