Skip to content

Kubernetes integration test suite #148

Kubernetes integration test suite

Kubernetes integration test suite #148

name: Operator Integration Test
on:
workflow_dispatch:
pull_request:
branches:
- main
paths:
- 'gateway/**'
- 'kubernetes/**'
- '.github/workflows/operator-integration-test.yml'
env:
DOCKER_REGISTRY: localhost
VERSION: test
KIND_CLUSTER_NAME: operator-test
jobs:
integration-test:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: linux/amd64,linux/arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Create Kind cluster
uses: helm/kind-action@v1
with:
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
wait: 300s
- name: Build Gateway Controller image
run: |
cd gateway/gateway-controller
DOCKER_REGISTRY=${{ env.DOCKER_REGISTRY }} VERSION=${{ env.VERSION }} make build-local
- name: Build Policy Engine image
run: |
cd gateway/policy-engine
DOCKER_REGISTRY=${{ env.DOCKER_REGISTRY }} VERSION=${{ env.VERSION }} make build-local
- name: Build Router image
run: |
cd gateway/router
DOCKER_REGISTRY=${{ env.DOCKER_REGISTRY }} VERSION=${{ env.VERSION }} make build-local
- name: Build Operator image
run: |
cd kubernetes/gateway-operator
IMG=${{ env.DOCKER_REGISTRY }}/gateway-operator:${{ env.VERSION }} make docker-build
- name: Build Mock JWKS image
run: |
cd tests/mock-servers/mock-jwks
docker build -t ${{ env.DOCKER_REGISTRY }}/mock-jwks:${{ env.VERSION }} .
- name: Load images into Kind
run: |
kind load docker-image ${{ env.DOCKER_REGISTRY }}/gateway-controller:${{ env.VERSION }} --name ${{ env.KIND_CLUSTER_NAME }}
kind load docker-image ${{ env.DOCKER_REGISTRY }}/policy-engine:${{ env.VERSION }} --name ${{ env.KIND_CLUSTER_NAME }}
kind load docker-image ${{ env.DOCKER_REGISTRY }}/gateway-router:${{ env.VERSION }} --name ${{ env.KIND_CLUSTER_NAME }}
kind load docker-image ${{ env.DOCKER_REGISTRY }}/gateway-operator:${{ env.VERSION }} --name ${{ env.KIND_CLUSTER_NAME }}
kind load docker-image ${{ env.DOCKER_REGISTRY }}/mock-jwks:${{ env.VERSION }} --name ${{ env.KIND_CLUSTER_NAME }}
- name: Deploy OCI Registry (HTTP)
run: |
# Create namespace
kubectl create namespace registry
# Deploy registry without TLS (plain HTTP for testing)
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: registry
namespace: registry
spec:
replicas: 1
selector:
matchLabels:
app: registry
template:
metadata:
labels:
app: registry
spec:
containers:
- name: registry
image: registry:2
ports:
- containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
name: registry
namespace: registry
spec:
selector:
app: registry
ports:
- port: 5000
targetPort: 5000
EOF
kubectl wait --for=condition=available deployment/registry -n registry --timeout=120s
kubectl wait --for=condition=ready pod -l app=registry -n registry --timeout=120s
- name: Package and push Gateway Helm chart to OCI Registry
run: |
cd kubernetes/helm/gateway-helm-chart
helm package . --version 0.0.0-test
# Port forward registry to push chart (plain HTTP)
kubectl port-forward svc/registry -n registry 5000:5000 &
sleep 5
# Push chart to OCI registry (plain HTTP, use insecure flag)
helm push gateway-0.0.0-test.tgz oci://localhost:5000/charts --plain-http
# Kill port forward
pkill -f "kubectl port-forward.*registry" || true
- name: Deploy mock httpbin backend
run: |
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
template:
metadata:
labels:
app: httpbin
spec:
containers:
- name: httpbin
image: kennethreitz/httpbin:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
namespace: default
spec:
selector:
app: httpbin
ports:
- port: 80
targetPort: 80
EOF
kubectl wait --for=condition=ready pod -l app=httpbin --timeout=120s
- name: Deploy Mock JWKS Service
run: |
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: mock-jwks
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: mock-jwks
template:
metadata:
labels:
app: mock-jwks
spec:
containers:
- name: mock-jwks
image: ${{ env.DOCKER_REGISTRY }}/mock-jwks:${{ env.VERSION }}
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: mock-jwks
namespace: default
spec:
selector:
app: mock-jwks
ports:
- port: 8080
targetPort: 8080
EOF
kubectl wait --for=condition=ready pod -l app=mock-jwks --timeout=120s
- name: Install cert-manager
run: |
helm upgrade --install cert-manager oci://quay.io/jetstack/charts/cert-manager \
--version v1.17.2 \
--namespace cert-manager \
--create-namespace \
--set crds.enabled=true \
--wait --timeout 5m
- name: Run Operator Integration Tests
run: |
set -o pipefail
cd kubernetes/it
echo "Running Cucumber integration tests..."
GOWORK=off go run ./cmd/... 2>&1 | tee test-output.log
env:
# Configuration for the test suite
DOCKER_REGISTRY: ${{ env.DOCKER_REGISTRY }}
IMAGE_TAG: ${{ env.VERSION }}
OPERATOR_CHART_PATH: ${{ github.workspace }}/kubernetes/helm/operator-helm-chart
GATEWAY_CHART_PATH: ${{ github.workspace }}/kubernetes/helm/gateway-helm-chart
GATEWAY_CHART_NAME: oci://registry.registry.svc.cluster.local:5000/charts/gateway
GATEWAY_CHART_VERSION: 0.0.0-test
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: integration-test-results
path: kubernetes/it/test-output.log
- name: Debug on failure - Dump logs
if: failure()
run: |
echo "=== Operator Logs ==="
kubectl logs -n operator -l app.kubernetes.io/name=gateway-operator --tail=200 || true
echo ""
echo "=== Scoped Operator Logs ==="
kubectl logs -n scoped-test -l app.kubernetes.io/name=gateway-operator --tail=200 || true
echo ""
echo "=== Gateway Status ==="
kubectl describe gateway test-gateway || true
echo ""
echo "=== Scoped Gateway Status ==="
kubectl describe gateway scoped-gateway -n scoped-test || true
echo ""
echo "=== RestApi Status ==="
kubectl describe restapi test-api || true
echo ""
echo "=== Scoped RestApi Status ==="
kubectl describe restapi scoped-api -n scoped-test || true
echo ""
echo "=== All Pods Description ==="
kubectl describe pods --all-namespaces || true
echo ""
echo "=== Gateway Controller Logs ==="
kubectl logs -l app.kubernetes.io/component=controller --tail=200 || true
echo ""
echo "=== Scoped Gateway Controller Logs ==="
kubectl logs -n scoped-test -l app.kubernetes.io/component=controller --tail=200 || true
echo ""
echo "=== Router Logs ==="
kubectl logs -l app.kubernetes.io/component=router --tail=200 || true
echo ""
echo "=== Scoped Router Logs ==="
kubectl logs -n scoped-test -l app.kubernetes.io/component=router --tail=200 || true
echo ""
echo "=== Policy Engine Logs ==="
kubectl logs -l app.kubernetes.io/component=policy-engine --tail=200 || true
echo ""
echo "=== Scoped Policy Engine Logs ==="
kubectl logs -n scoped-test -l app.kubernetes.io/component=policy-engine --tail=200 || true
echo ""
echo "=== All Pods ==="
kubectl get pods -A
echo ""
echo "=== All Services ==="
kubectl get svc -A