Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
4ccf6c2
DEVPROD-3580: #feat Adding Gateway API support
pbhardwaj6 Feb 5, 2026
078b31c
DEVPROD-3580: #feat Adding Gateway API support
pbhardwaj6 Feb 5, 2026
ff71aa4
DEVPROD-3580: Kind test fix, for Gateway API
pbhardwaj6 Feb 18, 2026
41dec31
Merge remote-tracking branch 'origin/DEVPROD-3580-add-gateway-api-sup…
pbhardwaj6 Feb 18, 2026
4efa718
DEVPROD-3580: maven unit test fix
pbhardwaj6 Feb 18, 2026
a65eb9f
DEVPROD-3580: openshift test fix
pbhardwaj6 Feb 19, 2026
972e83b
DEVPROD-3580: openshift test fix
pbhardwaj6 Feb 19, 2026
581f544
DEVPROD-3580: service ingress path, confluence Synchrony path fix
pbhardwaj6 Feb 23, 2026
3008bd6
DEVPROD-3580: Session affinity config doc attached
pbhardwaj6 Feb 24, 2026
8fb9616
DEVPROD-3580: e2e-tf-deployment update Gateway API integration
pbhardwaj6 Feb 24, 2026
2fcda43
DEVPROD-3580: Indentation and baseurl removing '/' trimming
pbhardwaj6 Mar 10, 2026
fa0e99d
DEVPROD-3580 Extracted and re-used common logic. (#1094)
amierzwicki Mar 11, 2026
fdb008a
DEVPROD-3580 Introduced common polling logic.
amierzwicki Mar 11, 2026
48aa0a1
DEVPROD-3580 Reverted previous behavior for failure of 'CloudNativePG…
amierzwicki Mar 11, 2026
c290239
DEVPROD-3580 Using wait_for to check if port-forwarding is ready.
amierzwicki Mar 11, 2026
e871f2e
DEVPROD-3580: Addressed PR comments fixes
pbhardwaj6 Mar 13, 2026
648f490
Merge remote-tracking branch 'origin/main' into DEVPROD-3580-add-gate…
pbhardwaj6 Mar 18, 2026
70b30c2
DEVPROD-3580: improved comments and examples for gateway, sync all co…
pbhardwaj6 Mar 18, 2026
e460428
DEVPROD-3580: Adding common port forward for gateway, using in wait_f…
pbhardwaj6 Mar 18, 2026
714267d
DEVPROD-3580: Adding common port forward for gateway, using in wait_f…
pbhardwaj6 Mar 18, 2026
897843b
DEVPROD-3776: Documentation for Gateway API (#1089)
pbhardwaj6 Mar 20, 2026
325ac95
DEVPROD-3580: envoy proxy as NodePort for Kind tests (#1098)
pbhardwaj6 Mar 24, 2026
0d2f15b
Merge remote-tracking branch 'origin/main' into DEVPROD-3580-add-gate…
pbhardwaj6 Mar 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 31 additions & 5 deletions .github/workflows/e2e-tf-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ on:
pull_request_target:
types: [ labeled ]
workflow_dispatch:
inputs:
use_gateway_api:
description: 'Use Gateway API (Envoy Gateway) instead of NGINX Ingress'
required: false
type: boolean
default: false
terraform_branch:
description: 'Terraform repo branch to use (leave empty for latest LTS tag)'
required: false
type: string
default: ''

jobs:
test:
Expand All @@ -40,6 +51,7 @@ jobs:
TF_VAR_crowdstrike_kms_key_name: ${{ secrets.TF_VAR_CROWDSTRIKE_KMS_KEY_NAME }}
TF_VAR_crowdstrike_aws_account_id: ${{ secrets.TF_VAR_CROWDSTRIKE_AWS_ACCOUNT_ID }}
USE_DOMAIN: "true"
USE_GATEWAY_API: ${{ github.event.inputs.use_gateway_api || 'false' }}

steps:
- name: Checkout Helm charts
Expand Down Expand Up @@ -82,11 +94,17 @@ jobs:
- name: Checkout Deployment Automation
run: |
DEPLOYMENT_REPO='https://github.com/atlassian-labs/data-center-terraform.git'
LTS=$(git ls-remote --tags --exit-code --refs "$DEPLOYMENT_REPO" \
| sed -E 's/^[[:xdigit:]]+[[:space:]]+refs\/tags\/(.+)/\1/g' \
| grep '^[0-9]*.[0-9]*.[0-9]*$' | sort -V | tail -1)
echo "Using LTS version('${LTS}') of Deployment Automation to provision the infrastructure for Atlassian DC Products."
git clone -b $LTS $DEPLOYMENT_REPO tf
CUSTOM_BRANCH="${{ github.event.inputs.terraform_branch }}"
if [ -n "$CUSTOM_BRANCH" ]; then
echo "Using custom branch '${CUSTOM_BRANCH}' of Deployment Automation."
git clone -b $CUSTOM_BRANCH $DEPLOYMENT_REPO tf
else
LTS=$(git ls-remote --tags --exit-code --refs "$DEPLOYMENT_REPO" \
| sed -E 's/^[[:xdigit:]]+[[:space:]]+refs\/tags\/(.+)/\1/g' \
| grep '^[0-9]*.[0-9]*.[0-9]*$' | sort -V | tail -1)
echo "Using LTS version('${LTS}') of Deployment Automation to provision the infrastructure for Atlassian DC Products."
git clone -b $LTS $DEPLOYMENT_REPO tf
fi

- name: Setup test environment
uses: actions/setup-go@v3
Expand Down Expand Up @@ -148,6 +166,14 @@ jobs:
crowd_install_local_chart = true
EOF

# Append Gateway API toggle if enabled
if [ "$USE_GATEWAY_API" = "true" ]; then
echo 'use_gateway_api = true' >> ./e2etest/test-config.tfvars.tmpl
echo "Gateway API mode enabled (Envoy Gateway will replace NGINX Ingress)"
else
echo "NGINX Ingress mode (default)"
fi

# Deploy infrastructure, install helm charts, run e2e tests, and cleanup all
# boto3 ignores AWS creds env vars for some reason
mkdir -p ~/.aws
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/kind.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
- name: Verify ${{inputs.dc_app}} status
run: |
source src/test/scripts/kind/deploy_app.sh
verify_ingress
verify_gateway_ingress

- name: Verify ${{inputs.dc_app}} grafana dashboards
run: |
Expand All @@ -90,6 +90,11 @@ jobs:
source src/test/scripts/kind/deploy_app.sh
verify_metrics

- name: Verify Gateway API integration
run: |
source src/test/scripts/kind/deploy_app.sh
verify_gateway

- name: Get debug info
if: always()
run: |
Expand Down
99 changes: 98 additions & 1 deletion .github/workflows/openshift.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,98 @@ jobs:
run: |
oc apply -f src/test/config/openshift/shared-home-pvc.yaml

- name: Install Gateway API + Envoy Gateway
run: |
# Gateway API CRDs
oc apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml
oc apply --server-side=true -f https://raw.githubusercontent.com/envoyproxy/gateway/v1.2.5/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml

oc wait --for condition=established --timeout=60s crd/gateways.gateway.networking.k8s.io
oc wait --for condition=established --timeout=60s crd/httproutes.gateway.networking.k8s.io
oc wait --for condition=established --timeout=60s crd/gatewayclasses.gateway.networking.k8s.io
oc wait --for condition=established --timeout=60s crd/envoyproxies.gateway.envoyproxy.io

# Envoy Gateway (installs into envoy-gateway-system)
# OpenShift admission can reject fixed runAsUser/seccomp settings unless the
# service accounts are allowed to use a more permissive SCC.
oc create namespace envoy-gateway-system --dry-run=client -o yaml | oc apply -f -
# Pre-grant SCCs to all service accounts in the namespace so Helm hooks can run
# even before the chart-created ServiceAccounts exist.
oc adm policy add-scc-to-group anyuid system:serviceaccounts:envoy-gateway-system || true
oc adm policy add-scc-to-group privileged system:serviceaccounts:envoy-gateway-system || true

helm install eg oci://docker.io/envoyproxy/gateway-helm \
--version v1.2.5 \
--namespace envoy-gateway-system \
--set deployment.envoyGateway.resources.requests.cpu=50m \
--set deployment.envoyGateway.resources.requests.memory=100Mi \
--skip-crds \
--timeout=600s \
--wait || { \
oc get all -n envoy-gateway-system || true; \
oc get events -n envoy-gateway-system --sort-by='.lastTimestamp' | tail -n 200 || true; \
exit 1; \
}

oc wait --for=condition=available deployment/envoy-gateway \
--namespace envoy-gateway-system \
--timeout=300s

# EnvoyProxy CR configures the proxy Service as ClusterIP (default for OpenShift; an OpenShift Route will handle external access).
oc apply -f src/test/config/openshift/envoy-proxy.yaml

# GatewayClass references the EnvoyProxy CR via parametersRef
cat << EOF | oc apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: eg
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
parametersRef:
group: gateway.envoyproxy.io
kind: EnvoyProxy
name: openshift-proxy-config
namespace: envoy-gateway-system
EOF
oc wait --for=condition=Accepted gatewayclass/eg --timeout=180s || { oc get gatewayclass/eg -o yaml; oc get pods -n envoy-gateway-system -o wide || true; exit 1; }

# Create test Gateway
oc apply -f src/test/config/openshift/gateway.yaml
oc wait --for=condition=Accepted gateway/atlassian-gateway -n atlassian --timeout=300s || { oc describe gateway/atlassian-gateway -n atlassian; oc get events -n atlassian --sort-by='.lastTimestamp' | tail -n 200 || true; exit 1; }

# Wait for data-plane
oc wait --for=condition=Available deployment \
-n envoy-gateway-system \
-l gateway.envoyproxy.io/owning-gateway-name=atlassian-gateway \
--timeout=300s || { \
oc get deployments -n envoy-gateway-system -o wide; \
oc get pods -n envoy-gateway-system -o wide; \
oc describe deployment -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-name=atlassian-gateway || true; \
oc get events -n envoy-gateway-system --sort-by='.lastTimestamp' | tail -n 200 || true; \
exit 1; \
}

# Create an OpenShift Route so atlassian.apps.crc.testing reaches the
# Envoy proxy Service without port-forward or Host headers.
ENVOY_SVC=$(oc get svc -n envoy-gateway-system \
-l gateway.envoyproxy.io/owning-gateway-name=atlassian-gateway \
-o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)

if [ -z "${ENVOY_SVC}" ]; then
echo "[ERROR]: Envoy Gateway proxy service not found"
oc get svc -n envoy-gateway-system -o wide || true
exit 1
fi

oc -n envoy-gateway-system expose svc/${ENVOY_SVC} \
--name atlassian-gateway-proxy \
--hostname atlassian.apps.crc.testing || true

# Log the Route and Endpoint details for debugging
oc -n envoy-gateway-system get route atlassian-gateway-proxy -o yaml || true
oc -n envoy-gateway-system get endpoints ${ENVOY_SVC} -o yaml || true

- name: Deploy postgres database
run: |
source src/test/scripts/kind/deploy_app.sh
Expand All @@ -117,7 +209,7 @@ jobs:
run: |
export OPENSHIFT_VALUES="1"
source src/test/scripts/kind/deploy_app.sh
verify_ingress
verify_gateway_ingress

- name: Verify ${{inputs.dc_app}} metrics availability
run: |
Expand All @@ -129,6 +221,11 @@ jobs:
source src/test/scripts/kind/deploy_app.sh
verify_openshift_analytics

- name: Verify Gateway API integration
run: |
source src/test/scripts/kind/deploy_app.sh
verify_gateway

- name: Get debug info
if: always()
run: |
Expand Down
16 changes: 16 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,22 @@ For any pull requests, code owners should review the changes thoroughly and make

For external contributions, any Github action workflow related changes are not acceptable.

## Windows Users

This repository uses **symlinks** to share common Helm templates across product charts
(see `src/main/charts/common_templates/`). Git on Windows doesn't enable symlinks by default — without them,
Helm template rendering will fail.

To enable symlinks on Windows:

1. Enable **Developer Mode** in Windows Settings (Settings → Update & Security → For Developers), or run Git as Administrator
2. Configure Git to create real symlinks:
```
git config --global core.symlinks true
```
3. Re-clone the repository after changing this setting (existing clones won't retroactively fix symlinks)


### How to run E2E tests

The Data Center Helm Charts uses the latest release of [Deployment Automation for Atlassian DC on K8s](https://github.com/atlassian-labs/data-center-terraform#deployment-automation-for-atlassian-dc-on-k8s) for end-to-end testing. Internal reviewers can run the tests by adding `e2e` label on a pull request (for external contributions, be mindful of the changes as it will run on internal cloud environment).
23 changes: 19 additions & 4 deletions docs/docs/examples/ingress/CONTROLLERS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
# Provisioning an Ingress controller
In order for the provided Ingress resource to work, your Kubernetes cluster must have an ingress controller running. The Atlassian Helm charts have been tested with the [NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/){.external}, however [alternatives can also be used](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/#additional-controllers){.external}.
# Provisioning a traffic entry controller

Here is an example of how these controllers can be installed and configured for use with the Atlassian Helm charts:
To expose an Atlassian DC product outside your Kubernetes cluster, you must run **one** of the following:

* [NGINX Ingress Controller](INGRESS_NGINX.md)
- an **Ingress controller** (to process Kubernetes `Ingress` resources), or
- a **Gateway API controller** (to process Kubernetes Gateway API resources, such as `HTTPRoute`).

The Helm charts can render either:

- a Kubernetes `Ingress` when `ingress.create: true`, or
- a Kubernetes Gateway API `HTTPRoute` when `gateway.create: true`.

These options are **mutually exclusive** (you cannot enable both `ingress.create` and `gateway.create`).

!!!note "Sticky sessions are required"
Atlassian DC products require **session stickiness** ("sticky sessions") for high availability. With NGINX Ingress this is handled via controller annotations. With Gateway API you must configure stickiness using your chosen Gateway implementation.

## Example guides

- [NGINX Ingress Controller (Ingress)](INGRESS_NGINX.md)
- [Gateway API controller (Gateway API)](GATEWAY_API.md)
99 changes: 99 additions & 0 deletions docs/docs/examples/ingress/GATEWAY_API.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Gateway API controller (HTTPRoute)

The Atlassian DC Helm charts support exposing products via the **Kubernetes Gateway API** by rendering a `HTTPRoute` resource when `gateway.create: true`.

To use this, your cluster must have:

- Gateway API CRDs installed
- a Gateway API controller installed (for example, Envoy Gateway, Istio, etc.)
- a `Gateway` resource that allows routes from your product namespace

!!!note "What the charts create"
The charts create a **`HTTPRoute`** only. You must provision the **`GatewayClass`**, **`Gateway`**, and (optionally) **TLS certificates** in your cluster.

## 1. Install a Gateway API controller

Follow your chosen implementation's installation instructions:

- Gateway API overview: <https://gateway-api.sigs.k8s.io/>
- Implementations: <https://gateway-api.sigs.k8s.io/implementations/>

## 2. Create a Gateway

Create a `Gateway` that will accept `HTTPRoute` attachments from the namespace where you install the Atlassian product.

The exact `gatewayClassName`, listener configuration, and TLS configuration depend on your chosen implementation.

## 3. Configure the Helm chart

Disable `ingress.create` and enable `gateway.create`. Provide a **parentRef** pointing to your `Gateway` and at least one **hostname**.

```yaml
ingress:
create: false

gateway:
create: true
hostnames:
- confluence.example.com
https: true
parentRefs:
- name: atlassian-gateway
namespace: gateway-system # optional, defaults to release namespace
sectionName: https # optional, target a specific Gateway listener
```

!!!info "TLS termination"
With Gateway API, TLS termination is configured on the `Gateway` listeners (not on the `HTTPRoute`). The `gateway.https` value controls the product's proxy/URL settings (e.g., generating HTTPS links), but it does not provision certificates by itself.

## Gateway values reference

The `gateway` stanza is split into two groups:

**Product configuration** (always active when `gateway.hostnames` is set):

| Value | Description | Default |
|-------|-------------|---------|
| `gateway.create` | Create an `HTTPRoute` resource | `false` |
| `gateway.hostnames` | Hostnames to route; first entry is used as the canonical hostname for base URL and proxy settings | `[]` |
| `gateway.https` | Whether users access the application over HTTPS | `true` |
| `gateway.externalPort` | Port users connect on; only set for non-standard ports | `443` (https) / `80` (http) |
| `gateway.path` | Base path; falls back to `<product>.service.contextPath` when empty | (empty) |

**HTTPRoute configuration** (only applies when `gateway.create: true`):

| Value | Description | Default |
|-------|-------------|---------|
| `gateway.parentRefs` | List of [ParentReference](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ParentReference){.external} objects (`name`, `namespace`, `sectionName`, etc.) | `[]` (required) |
| `gateway.pathType` | Path matching type: `PathPrefix`, `Exact`, or `RegularExpression` | `PathPrefix` |
| `gateway.annotations` | Annotations to add to the HTTPRoute | `{}` |
| `gateway.labels` | Labels to add to the HTTPRoute | `{}` |
| `gateway.filters` | [HTTPRouteFilter](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteFilter){.external} list (header modification, redirects, URL rewrites) | `[]` |
| `gateway.timeouts.request` | Total request timeout | `60s` |
| `gateway.timeouts.backendRequest` | Backend request timeout | `60s` |
| `gateway.additionalRules` | Extra [HTTPRouteRule](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteRule){.external} entries for advanced routing | `[]` |

!!!note "Using gateway config without creating an HTTPRoute"
Setting `gateway.hostnames` activates gateway mode for the product's proxy and base-URL configuration **even when `gateway.create` is false**. This is useful when you have a pre-existing Gateway or external proxy/load balancer and only need the Helm chart to configure the product itself, without creating any Kubernetes routing resource.

## 4. Timeouts

The `gateway.timeouts` block replaces the Ingress-style `proxyReadTimeout` / `proxySendTimeout` settings:

```yaml
gateway:
timeouts:
request: "60s" # total request timeout
backendRequest: "60s" # backend request timeout
```

!!!warning "No Gateway API equivalents"
There is no standard Gateway API equivalent for `proxyConnectTimeout` or `maxBodySize`. If you need those, configure them through controller-specific policies (e.g. Envoy Gateway `BackendTrafficPolicy`).


## Configure session affinity (sticky sessions)

Session affinity is **required** for Atlassian DC products and is **not** part of the standard `HTTPRoute` API.

See [Session affinity with Gateway API](GATEWAY_API_SESSION_AFFINITY.md) for implementation-specific examples (cookie-based) and links for further reading.

Loading
Loading