Skip to content

Set ipv6-access-type=INTERNAL for create-subnetwork #16

Set ipv6-access-type=INTERNAL for create-subnetwork

Set ipv6-access-type=INTERNAL for create-subnetwork #16

Workflow file for this run

name: IPv6-Only Testing

Check failure on line 1 in .github/workflows/nfr-ipv6-only.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/nfr-ipv6-only.yml

Invalid workflow file

(Line: 164, Col: 19): Unexpected symbol: 'image_tag§'. Located at position 54 within expression: inputs.image_tag == 'plus' && 'nginx-plus' || inputs.image_tag§
on:
workflow_dispatch:
inputs:
version:
description: Version of NGF under test
required: true
default: edge
image_tag:
description: Tag of the NGF and NGINX Docker images
required: true
default: edge
type:
description: Type of NGINX image to test
required: true
default: both
type: choice
options: [oss, plus, both]
schedule:
- cron: "0 16 1,15 * *" # Run on the 1st and 15th of every month at 16:00 UTC
defaults:
run:
shell: bash
env:
PLUS_USAGE_ENDPOINT: ${{ secrets.JWT_PLUS_REPORTING_ENDPOINT }}
permissions:
contents: read
jobs:
vars:
name: Set up vars
runs-on: ubuntu-24.04
outputs:
version: ${{ github.event.inputs.version || 'edge' }}
image_tag: ${{ github.event.inputs.image_tag || 'edge' }}
types: ${{ steps.var.outputs.types }}
permissions:
contents: read
steps:
- name: Set vars
id: var
run: |
if ${{ github.event.inputs.type == 'both' || github.event_name == 'schedule' }}; then
echo 'types=["oss","plus"]' >> $GITHUB_OUTPUT
else
echo 'types=["${{ github.event.inputs.type }}"]' >> $GITHUB_OUTPUT
fi
setup-and-run-tests:
name: Run IPv6-Only Tests
runs-on: ubuntu-24.04
permissions:
contents: read
id-token: write # needed for authenticating to GCP
needs: vars
strategy:
fail-fast: false
matrix:
type: ${{ fromJson(needs.vars.outputs.types) }}
if: ${{ !github.event.pull_request.head.repo.fork || inputs.image != 'plus' }}
env:
DOCKER_BUILD_SUMMARY: false
steps:
- name: Checkout Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
### Authenticate to GCP and set up gcloud, kubectl, and Docker
- name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
with:
token_format: access_token
workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY }}
service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
- name: Login to GAR
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with:
registry: us-docker.pkg.dev
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3.0.1
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
install_components: kubectl
###
- name: Setup dotenv file
working-directory: ./tests/scripts
run: |
echo "RESOURCE_NAME=nfr-tests-${{ github.run_id }}-${{ matrix.type }}" >> vars.env
echo "TAG=${{ needs.vars.outputs.image_tag }}" >> vars.env
echo "PREFIX=ghcr.io/nginx/nginx-gateway-fabric" >> vars.env
echo "NGINX_PREFIX=ghcr.io/nginx/nginx-gateway-fabric/nginx" >> vars.env
echo "NGINX_PLUS_PREFIX=us-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/nginx-gateway-fabric/nginx-plus" >> vars.env
echo "GKE_CLUSTER_NAME=nfr-tests-${{ github.run_id }}-${{ matrix.type }}" >> vars.env
echo "GKE_CLUSTER_ZONE=us-west1-b" >> vars.env
echo "GKE_CLUSTER_REGION=us-west1" >> vars.env
echo "GKE_PROJECT=${{ secrets.GCP_PROJECT_ID }}" >> vars.env
echo "GKE_SVC_ACCOUNT=${{ secrets.GCP_SERVICE_ACCOUNT }}" >> vars.env
echo "GKE_NODES_SERVICE_ACCOUNT=${{ secrets.GKE_NODES_SERVICE_ACCOUNT }}" >> vars.env
echo "NETWORK_TAGS=nfr-tests-${{ github.run_id }}-${{ matrix.type }}" >> vars.env
echo "NGF_BRANCH=${{ github.ref_name }}" >> vars.env
echo "SOURCE_IP_RANGE=$(curl -sS -4 icanhazip.com)/32" >> vars.env
echo "ADD_VM_IP_AUTH_NETWORKS=true" >> vars.env
echo "PLUS_ENABLED=${{ matrix.type == 'plus' }}" >> vars.env
echo "GINKGO_LABEL=" >> vars.env
echo "NGF_VERSION=${{ needs.vars.outputs.version }}" >> vars.env
echo "GKE_NUM_NODES=1" >> vars.env
echo "GKE_MACHINE_TYPE=n2d-standard-16" >> vars.env
echo "IPV6_ENABLED=true" >> vars.env
echo "PLUS_USAGE_ENDPOINT=${{ secrets.JWT_PLUS_REPORTING_ENDPOINT }}" >> vars.env
- name: Setup license file for plus
if: matrix.type == 'plus'
env:
PLUS_LICENSE: ${{ secrets.JWT_PLUS_REPORTING }}
run: echo "${PLUS_LICENSE}" > license.jwt
- name: Create GKE cluster
working-directory: ./tests
run: make create-gke-cluster CI=true
- name: Create and setup VM
working-directory: ./tests
run: make create-and-setup-vm
- name: Create and setup Router
working-directory: ./tests
run: make create-gke-router || true
- name: Setup Golang Environment
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: stable
- name: Set GOPATH
run: echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
- name: Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: NGF Docker meta
id: ngf-meta
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
with:
images: |
name=ghcr.io/nginx/nginx-gateway-fabric
tags: |
type=semver,pattern={{version}}
type=schedule
type=edge
type=ref,event=pr
type=ref,event=branch,suffix=-rc,enable=${{ startsWith(github.ref, 'refs/heads/release') }}
- name: NGINX Docker meta
id: nginx-meta
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
with:
images: |
name=ghcr.io/nginx/nginx-gateway-fabric/${{ inputs.image_tag == 'plus' && 'nginx-plus' || inputs.image_tag§ }}
tags: |
type=semver,pattern={{version}}
type=edge
type=schedule
type=ref,event=pr
type=ref,event=branch,suffix=-rc,enable=${{ startsWith(github.ref, 'refs/heads/release') }}
# - name: Build binary
# uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
# with:
# version: v2.11.2 # renovate: datasource=github-tags depName=goreleaser/goreleaser
# args: build --single-target --snapshot --clean
# env:
# TELEMETRY_ENDPOINT: otel-collector-opentelemetry-collector.collector.svc.cluster.local:4317
# TELEMETRY_ENDPOINT_INSECURE: "true"
# - name: Build NGF Docker Image
# uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
# with:
# file: build/Dockerfile
# tags: ${{ steps.ngf-meta.outputs.tags }}
# context: "."
# load: true
# cache-from: type=gha,scope=ngf-ipv6
# pull: true
# target: goreleaser
# - name: Build NGINX Docker Image
# uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
# with:
# file: build/Dockerfile${{ inputs.image == 'nginx' && '.nginx' || '' }}${{ inputs.image == 'plus' && '.nginxplus' || ''}}
# tags: ${{ steps.nginx-meta.outputs.tags }}
# context: "."
# load: true
# cache-from: type=gha,scope=${{ inputs.image }}-ipv6
# pull: true
# build-args: |
# NJS_DIR=internal/controller/nginx/modules/src
# NGINX_CONF_DIR=internal/controller/nginx/conf
# BUILD_AGENT=gha
# - name: Deploy IPv6-Only Kubernetes
# id: k8s
# run: |
# # Enable IPv6 and container network options
# sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0
# sudo sysctl -w net.ipv6.conf.all.forwarding=1
# # Create IPv6-only kind cluster
# kind create cluster \
# --name ${{ github.run_id }}-ipv6 \
# --image=kindest/node:${{ inputs.k8s-version }} \
# --config=config/cluster/kind-cluster-ipv6-only.yaml
# # Load images into the cluster
# kind load docker-image ${{ join(fromJSON(steps.ngf-meta.outputs.json).tags, ' ') }} ${{ join(fromJSON(steps.nginx-meta.outputs.json).tags, ' ') }} --name ${{ github.run_id }}-ipv6
- name: Install NGF with IPv6 Configuration
run: |
ngf_prefix=ghcr.io/nginx/nginx-gateway-fabric
ngf_tag=${{ steps.ngf-meta.outputs.version }}
# Install with IPv6-specific configuration
# HELM_PARAMETERS="--set nginx.config.ipFamily=ipv6 --set nginx.service.type=ClusterIP" \
# make helm-install-local${{ inputs.image == 'plus' && '-with-plus' || ''}} PREFIX=${ngf_prefix} TAG=${ngf_tag}
working-directory: ./tests
- name: Deploy Test Applications
run: |
kubectl apply -f tests/manifests/ipv6-test-app.yaml
- name: Wait for NGF and Applications to be Ready
run: |
echo "Waiting for NGF to be ready..."
kubectl wait --for=condition=available --timeout=300s deployment/nginx-gateway -n nginx-gateway
echo "Waiting for test applications to be ready..."
kubectl wait --for=condition=available --timeout=300s deployment/test-app-ipv6
- name: Deploy IPv6 Test Client
run: |
kubectl apply -f tests/manifests/test-client-ipv6.yaml
kubectl wait --for=condition=ready --timeout=300s pod/ipv6-test-client
- name: Get NGF IPv6 Address
id: ngf-address
run: |
# Get the NGF service IPv6 address
NGF_IPV6=$(kubectl get service nginx-gateway -n nginx-gateway -o jsonpath='{.spec.clusterIP}')
echo "NGF IPv6 Address: $NGF_IPV6"
echo "ngf_ipv6=$NGF_IPV6" >> $GITHUB_OUTPUT
- name: Run IPv6 Connectivity Tests
run: |
echo "=== Running IPv6-Only Tests ==="
# Test 1: Basic connectivity test using test client pod
echo "Test 1: Basic IPv6 connectivity"
kubectl exec ipv6-test-client -- curl --version
kubectl exec ipv6-test-client -- nslookup nginx-gateway.nginx-gateway.svc.cluster.local
# Test 2: Test NGF service directly via IPv6
echo "Test 2: NGF Service IPv6 connectivity"
kubectl exec ipv6-test-client -- curl -6 --connect-timeout 30 --max-time 60 -v \
-H "Host: ipv6-test.example.com" \
"http://[${{ steps.ngf-address.outputs.ngf_ipv6 }}]:80/" || echo "Direct NGF test failed"
# Test 3: Test via service DNS
echo "Test 3: Service DNS IPv6 connectivity"
kubectl exec ipv6-test-client -- curl -6 --connect-timeout 30 --max-time 60 -v \
-H "Host: ipv6-test.example.com" \
"http://nginx-gateway.nginx-gateway.svc.cluster.local:80/" || echo "Service DNS test failed"
- name: Validate IPv6-Only Configuration
run: |
echo "=== Validating IPv6-Only Configuration ==="
# Check NGF configuration
echo "NGF Pod IPv6 addresses:"
kubectl get pods -n nginx-gateway -o wide
echo "NGF Service configuration:"
kubectl get service nginx-gateway -n nginx-gateway -o yaml
echo "Gateway and HTTPRoute status:"
kubectl get gateway,httproute -A -o wide
echo "Test application service configuration:"
kubectl get service test-app-ipv6-service -o yaml
- name: Collect Logs
if: always()
run: |
echo "=== Collecting logs for debugging ==="
echo "NGF Controller logs:"
kubectl logs -n nginx-gateway deployment/nginx-gateway -c nginx-gateway-controller --tail=100 || true
echo "NGINX logs:"
kubectl logs -n nginx-gateway deployment/nginx-gateway -c nginx --tail=100 || true
echo "Test client logs:"
kubectl logs ipv6-test-client --tail=100 || true
echo "Cluster events:"
kubectl get events --sort-by='.lastTimestamp' --all-namespaces --tail=50 || true
- name: Cleanup
working-directory: ./tests
if: always()
run: |
bash scripts/cleanup-vm.sh true
bash scripts/cleanup-router.sh true
make delete-gke-cluster
rm -rf scripts/vars.env