ci: enable selective x86 E2E execution #24077
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build x86 Image | |
| run-name: ${{ github.event_name == 'workflow_dispatch' && format('x86-e2e pr={0} head={1} approval={2} generation={3} mode={4} groups={5} labels={6} full={7}', inputs.prNumber, inputs.headSHA, inputs.approvalGeneration, inputs.dispatchGeneration, inputs.automatic && 'automatic' || 'approved', inputs.requestedGroupNames, inputs.controlledLabelNames, inputs.full && '1' || '0') || '' }} | |
| permissions: | |
| contents: read | |
| packages: read | |
| defaults: | |
| run: | |
| shell: >- | |
| /usr/bin/env -u ACTIONS_RUNTIME_TOKEN -u ACTIONS_RUNTIME_URL -u ACTIONS_RESULTS_URL | |
| -u ACTIONS_CACHE_URL -u ACTIONS_ID_TOKEN_REQUEST_TOKEN -u ACTIONS_ID_TOKEN_REQUEST_URL | |
| -u LD_PRELOAD -u LD_LIBRARY_PATH -u BASH_ENV -u ENV -u PYTHONPATH -u PYTHONHOME | |
| -u NODE_OPTIONS -u PERL5OPT -u RUBYOPT -u GIT_CONFIG_COUNT | |
| python3 -c "import os,pathlib,shutil,subprocess,sys,tempfile; | |
| realEnv=os.environ['GITHUB_ENV']; shadowDir=tempfile.mkdtemp(); | |
| os.environ['GITHUB_ENV']=shadowDir+'/env'; os.environ['GITHUB_PATH']=shadowDir+'/path'; | |
| pathlib.Path(os.environ['GITHUB_ENV']).touch(); pathlib.Path(os.environ['GITHUB_PATH']).touch(); | |
| result=subprocess.run(['bash','--noprofile','--norc','-e','-o','pipefail',sys.argv[1]],env=os.environ); | |
| allowed=('TAG','GO_VERSION','E2E_DIR','VERSION','DEBUG_WRAPPER'); | |
| lines=[line for line in pathlib.Path(os.environ['GITHUB_ENV']).read_text().splitlines() if line.partition('=')[0] in allowed]; | |
| open(realEnv,'a').write(('\n'.join(lines)+'\n') if lines else ''); | |
| shutil.rmtree(shadowDir); sys.exit(result.returncode)" {0} | |
| on: | |
| pull_request: | |
| branches: | |
| - master | |
| - release-* | |
| paths-ignore: | |
| - 'docs/**' | |
| - '**.md' | |
| push: | |
| branches: | |
| - master | |
| - release-* | |
| paths-ignore: | |
| - 'docs/**' | |
| - '**.md' | |
| workflow_dispatch: | |
| inputs: | |
| prNumber: | |
| description: Open pull request number | |
| required: true | |
| type: number | |
| headSHA: | |
| description: Exact current pull request HEAD SHA | |
| required: true | |
| type: string | |
| baseSHA: | |
| description: Exact trusted pull request base SHA | |
| required: true | |
| type: string | |
| approvalGeneration: | |
| description: Durable authorized comment generation | |
| required: true | |
| type: number | |
| automatic: | |
| description: Execute automatic smoke or fail-closed full coverage | |
| required: true | |
| default: false | |
| type: boolean | |
| dispatchGeneration: | |
| description: Unique trusted reducer run generation | |
| required: true | |
| type: number | |
| requestedGroups: | |
| description: JSON array of explicitly requested stable groups | |
| required: true | |
| default: '[]' | |
| type: string | |
| requestedGroupNames: | |
| description: Canonical comma-separated groups, or a single dash | |
| required: true | |
| default: '-' | |
| type: string | |
| controlledLabels: | |
| description: JSON array of trusted persistent E2E labels | |
| required: true | |
| default: '[]' | |
| type: string | |
| controlledLabelNames: | |
| description: Canonical comma-separated controlled labels, or a single dash | |
| required: true | |
| default: '-' | |
| type: string | |
| full: | |
| description: Run the complete x86 E2E suite | |
| required: true | |
| default: false | |
| type: boolean | |
| requestKey: | |
| description: Dispatcher-generated idempotency key | |
| required: true | |
| type: string | |
| catalogRevision: | |
| description: Trusted E2E catalog revision bound by the dispatcher | |
| required: true | |
| type: string | |
| concurrency: | |
| group: ${{ github.event_name == 'workflow_dispatch' && format('{0}-{1}', github.workflow, inputs.requestKey) || format('{0}-{1}', github.workflow, github.ref) }} | |
| cancel-in-progress: true | |
| env: | |
| EXECUTION_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || inputs.headSHA || github.sha }} | |
| # renovate: datasource=github-releases depName=kind packageName=kubernetes-sigs/kind | |
| KIND_VERSION: v0.32.0 | |
| # renovate: datasource=github-releases depName=golangci-lint packageName=golangci/golangci-lint | |
| GOLANGCI_LINT_VERSION: v2.12.2 | |
| # renovate: datasource=github-releases depName=helm packageName=helm/helm | |
| HELM_VERSION: v4.2.4 | |
| # renovate: datasource=github-releases depName=submariner packageName=submariner-io/submariner | |
| SUBMARINER_VERSION: 0.24.0 | |
| # renovate: datasource=github-releases depName=talos packageName=siderolabs/talos | |
| TALOS_VERSION: v1.13.8 | |
| jobs: | |
| e2e-selection: | |
| name: x86 E2E Selection | |
| if: github.event_name != 'workflow_dispatch' || github.actor == 'github-actions[bot]' | |
| runs-on: ubuntu-24.04 | |
| env: | |
| GH_TOKEN: ${{ github.event_name == 'workflow_dispatch' && github.token || '' }} | |
| PYTHONDONTWRITEBYTECODE: "1" | |
| outputs: | |
| executionJobIds: ${{ steps.outputs.outputs.executionJobIds }} | |
| k8sConformanceMatrix: ${{ steps.outputs.outputs.k8sConformanceMatrix || steps.fallbackMatrices.outputs.k8sConformanceMatrix }} | |
| kubeOvnConformanceMatrix: ${{ steps.outputs.outputs.kubeOvnConformanceMatrix || steps.fallbackMatrices.outputs.kubeOvnConformanceMatrix }} | |
| headSHA: ${{ steps.context.outputs.headSHA }} | |
| baseSHA: ${{ steps.context.outputs.baseSHA }} | |
| prNumber: ${{ steps.context.outputs.prNumber }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.baseSHA || github.sha }} | |
| persist-credentials: false | |
| fetch-depth: 0 | |
| - name: Initialize fail-closed conformance matrices | |
| id: fallbackMatrices | |
| if: always() | |
| run: | | |
| matrix='{"include":[{"ip-family":"ipv4","mode":"overlay"},{"ip-family":"ipv4","mode":"underlay"},{"ip-family":"ipv6","mode":"overlay"},{"ip-family":"ipv6","mode":"underlay"},{"ip-family":"dual","mode":"overlay"},{"ip-family":"dual","mode":"underlay"}]}' | |
| echo "k8sConformanceMatrix=$matrix" >> "$GITHUB_OUTPUT" | |
| echo "kubeOvnConformanceMatrix=$matrix" >> "$GITHUB_OUTPUT" | |
| - name: Collect trusted selection context | |
| id: context | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| INPUT_HEAD_SHA: ${{ inputs.headSHA }} | |
| INPUT_BASE_SHA: ${{ inputs.baseSHA }} | |
| INPUT_AUTOMATIC: ${{ inputs.automatic }} | |
| INPUT_CONTROLLED_LABELS: ${{ inputs.controlledLabels }} | |
| INPUT_CONTROLLED_LABEL_NAMES: ${{ inputs.controlledLabelNames }} | |
| INPUT_PR_NUMBER: ${{ inputs.prNumber }} | |
| INPUT_REQUESTED_GROUPS: ${{ inputs.requestedGroups }} | |
| INPUT_REQUESTED_GROUP_NAMES: ${{ inputs.requestedGroupNames }} | |
| INPUT_CATALOG_REVISION: ${{ inputs.catalogRevision }} | |
| INPUT_FULL: ${{ inputs.full }} | |
| PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: | | |
| set -euo pipefail | |
| printf '{}' > selector-event.json | |
| : > changed-paths.txt | |
| requestFull=false | |
| forceFullReason='' | |
| requestedGroups='[]' | |
| headSHA="$GITHUB_SHA" | |
| baseSHA="$GITHUB_SHA" | |
| prNumber=0 | |
| checkedOutSHA=$(git rev-parse HEAD) | |
| if [ "$EVENT_NAME" = workflow_dispatch ] && [ "$checkedOutSHA" != "$INPUT_BASE_SHA" ]; then | |
| echo 'trusted selector checkout does not match the approved base revision' >&2 | |
| exit 1 | |
| fi | |
| if [ "$EVENT_NAME" = pull_request ]; then | |
| git diff --name-status --diff-filter=ACDMRT -z -M \ | |
| "$PR_BASE_SHA...$PR_HEAD_SHA" > changed-name-status.bin | |
| python3 - <<'PY' | |
| import sys | |
| from pathlib import Path | |
| sys.path.insert(0, "hack") | |
| import e2e_selector as e2eSelector | |
| paths = e2eSelector.changedPathsFromNameStatus( | |
| Path("changed-name-status.bin").read_bytes() | |
| ) | |
| Path("changed-paths.txt").write_bytes( | |
| b"".join(path.encode("utf-8", errors="surrogateescape") + b"\0" for path in paths) | |
| ) | |
| PY | |
| cp "$GITHUB_EVENT_PATH" selector-event.json | |
| python3 - <<'PY' | |
| import json | |
| from pathlib import Path | |
| event = json.loads(Path("selector-event.json").read_text()) | |
| event["pull_request"]["labels"] = [] | |
| Path("selector-event.json").write_text(json.dumps(event)) | |
| PY | |
| headSHA="$PR_HEAD_SHA" | |
| baseSHA="$PR_BASE_SHA" | |
| prNumber="$PR_NUMBER" | |
| elif [ "$EVENT_NAME" = workflow_dispatch ]; then | |
| gh api "repos/$GITHUB_REPOSITORY/pulls/$INPUT_PR_NUMBER" > pull-request.json | |
| python3 - "$INPUT_HEAD_SHA" "$INPUT_BASE_SHA" "$GITHUB_REF_NAME" "$GITHUB_SHA" <<'PY' | |
| import json | |
| import os | |
| import re | |
| import sys | |
| from pathlib import Path | |
| pullRequest = json.loads(Path("pull-request.json").read_text()) | |
| if pullRequest.get("state") != "open": | |
| raise SystemExit("pull request is not open") | |
| if not re.fullmatch(r"[0-9a-f]{40}", sys.argv[1]): | |
| raise SystemExit("invalid requested HEAD SHA") | |
| if pullRequest["head"]["sha"] != sys.argv[1]: | |
| raise SystemExit("pull request HEAD changed; dispatch again") | |
| if pullRequest["base"]["sha"] != sys.argv[2]: | |
| raise SystemExit("pull request base revision changed; dispatch again") | |
| if pullRequest["base"]["ref"] != sys.argv[3]: | |
| raise SystemExit("executor must run from the pull request base branch") | |
| if sys.argv[4] != sys.argv[2]: | |
| raise SystemExit("executor workflow revision does not match the approved base") | |
| controlledLabels = json.loads(os.environ["INPUT_CONTROLLED_LABELS"]) | |
| if not isinstance(controlledLabels, list) or any( | |
| not isinstance(label, str) for label in controlledLabels | |
| ): | |
| raise SystemExit("controlledLabels must be a JSON array of strings") | |
| if os.environ["INPUT_AUTOMATIC"] != "true": | |
| controlledLabels = [] | |
| pullRequest["labels"] = [{"name": label} for label in controlledLabels] | |
| Path("selector-event.json").write_text(json.dumps({"pull_request": pullRequest})) | |
| PY | |
| gh api --paginate --slurp \ | |
| "repos/$GITHUB_REPOSITORY/pulls/$INPUT_PR_NUMBER/files?per_page=100" > pull-request-files.json | |
| python3 - <<'PY' | |
| import json | |
| from pathlib import Path | |
| pullRequest = json.loads(Path("pull-request.json").read_text()) | |
| pages = json.loads(Path("pull-request-files.json").read_text()) | |
| changedFiles = [changedFile for page in pages for changedFile in page] | |
| expectedCount = pullRequest.get("changed_files") | |
| if ( | |
| not isinstance(expectedCount, int) | |
| or expectedCount >= 3000 | |
| or expectedCount != len(changedFiles) | |
| ): | |
| Path("force-full-reason.txt").write_text( | |
| "pull request file list is incomplete; the full suite is required" | |
| ) | |
| with Path("changed-paths.txt").open("wb") as stream: | |
| for changedFile in changedFiles: | |
| for field in ("previous_filename", "filename"): | |
| if field in changedFile: | |
| stream.write(changedFile[field].encode() + b"\0") | |
| PY | |
| if [ -s force-full-reason.txt ]; then | |
| forceFullReason=$(cat force-full-reason.txt) | |
| fi | |
| python3 - "$INPUT_REQUESTED_GROUPS" "$INPUT_REQUESTED_GROUP_NAMES" "$INPUT_CATALOG_REVISION" "$INPUT_CONTROLLED_LABELS" "$INPUT_CONTROLLED_LABEL_NAMES" "$INPUT_AUTOMATIC" "$INPUT_FULL" <<'PY' | |
| import hashlib | |
| import json | |
| import sys | |
| from pathlib import Path | |
| groups = json.loads(sys.argv[1]) | |
| if not isinstance(groups, list) or any(not isinstance(group, str) for group in groups): | |
| raise SystemExit("requestedGroups must be a JSON array of strings") | |
| canonicalGroups = sorted(set(groups)) | |
| catalog = json.loads(Path(".github/e2e-selection.json").read_text()) | |
| catalogRevision = hashlib.sha256( | |
| json.dumps(catalog, sort_keys=True, separators=(",", ":")).encode() | |
| ).hexdigest() | |
| if catalogRevision != sys.argv[3]: | |
| raise SystemExit("executor catalog revision does not match dispatcher") | |
| unknownGroups = sorted(set(canonicalGroups) - set(catalog["groups"])) | |
| if unknownGroups: | |
| raise SystemExit(f"unknown requested E2E group: {unknownGroups[0]}") | |
| canonical = ",".join(canonicalGroups) or "-" | |
| if canonical != sys.argv[2]: | |
| raise SystemExit("requested group names do not match requestedGroups") | |
| labels = json.loads(sys.argv[4]) | |
| knownLabels = {"e2e:full"} | {f"e2e:{group}" for group in catalog["groups"]} | |
| if ( | |
| not isinstance(labels, list) | |
| or any(not isinstance(label, str) for label in labels) | |
| or set(labels) - knownLabels | |
| ): | |
| raise SystemExit("controlledLabels contains an unknown label") | |
| canonicalLabels = ",".join(sorted(set(labels))) or "-" | |
| if canonicalLabels != sys.argv[5]: | |
| raise SystemExit("controlled label names do not match controlledLabels") | |
| automatic = sys.argv[6] == "true" | |
| if automatic and (canonicalGroups or sys.argv[7] == "true"): | |
| raise SystemExit("automatic execution cannot contain an approved request") | |
| if not automatic and labels: | |
| raise SystemExit("approved execution cannot carry automatic controlled labels") | |
| PY | |
| headSHA="$INPUT_HEAD_SHA" | |
| baseSHA="$INPUT_BASE_SHA" | |
| prNumber="$INPUT_PR_NUMBER" | |
| requestedGroups="$INPUT_REQUESTED_GROUPS" | |
| requestFull="$INPUT_FULL" | |
| else | |
| forceFullReason='push events always run the full x86 E2E suite' | |
| fi | |
| echo "headSHA=$headSHA" >> "$GITHUB_OUTPUT" | |
| echo "baseSHA=$baseSHA" >> "$GITHUB_OUTPUT" | |
| echo "prNumber=$prNumber" >> "$GITHUB_OUTPUT" | |
| echo "requestFull=$requestFull" >> "$GITHUB_OUTPUT" | |
| echo "forceFullReason=$forceFullReason" >> "$GITHUB_OUTPUT" | |
| echo "requestedGroups=$requestedGroups" >> "$GITHUB_OUTPUT" | |
| - name: Compute the selection plan | |
| env: | |
| FORCE_FULL_REASON: ${{ steps.context.outputs.forceFullReason }} | |
| HEAD_SHA: ${{ steps.context.outputs.headSHA }} | |
| REQUESTED_FULL: ${{ steps.context.outputs.requestFull }} | |
| REQUESTED_GROUPS: ${{ steps.context.outputs.requestedGroups }} | |
| run: | | |
| args=( | |
| --paths-file changed-paths.txt | |
| --event-file selector-event.json | |
| --request-groups-json "$REQUESTED_GROUPS" | |
| --head-sha "$HEAD_SHA" | |
| --base-sha "${{ steps.context.outputs.baseSHA }}" | |
| --pr-number "${{ steps.context.outputs.prNumber }}" | |
| --force-full-reason "$FORCE_FULL_REASON" | |
| --plan-file e2e-selection-plan.json | |
| --summary-file e2e-selection-summary.md | |
| ) | |
| if [ "$REQUESTED_FULL" = true ]; then | |
| args+=(--request-full) | |
| fi | |
| python3 hack/e2e_selector.py "${args[@]}" | |
| - name: Export executor job IDs | |
| id: outputs | |
| env: | |
| EVENT_NAME: ${{ inputs.automatic && 'pull_request' || github.event_name }} | |
| run: | | |
| python3 - <<'PY' | |
| import json | |
| import os | |
| import sys | |
| from pathlib import Path | |
| sys.path.insert(0, "hack") | |
| import e2e_selector as e2eSelector | |
| try: | |
| catalog = e2eSelector.loadCatalog(".github/e2e-selection.json") | |
| except Exception as error: | |
| print(f"failed to reload the E2E catalog: {error}", file=sys.stderr) | |
| catalog = None | |
| plan = json.loads(Path("e2e-selection-plan.json").read_text()) | |
| executionPlan = e2eSelector.executionPlan(catalog, plan, os.environ["EVENT_NAME"]) | |
| e2eSelector.writePlan( | |
| executionPlan, | |
| e2eSelector.readPaths("changed-paths.txt"), | |
| "e2e-selection-plan.json", | |
| "e2e-selection-summary.md", | |
| ) | |
| jobIds = sorted({entry["job"] for entry in executionPlan["matrix"]}) | |
| matrices = { | |
| "k8sConformanceMatrix": e2eSelector.jobMatrix( | |
| executionPlan, | |
| "k8s-conformance-e2e", | |
| ), | |
| "kubeOvnConformanceMatrix": e2eSelector.jobMatrix( | |
| executionPlan, | |
| "kube-ovn-conformance-e2e", | |
| ), | |
| } | |
| with Path(os.environ["GITHUB_OUTPUT"]).open("a") as stream: | |
| stream.write("executionJobIds=" + json.dumps(jobIds, separators=(",", ":")) + "\n") | |
| for name, matrix in matrices.items(): | |
| stream.write(name + "=" + json.dumps(matrix, separators=(",", ":")) + "\n") | |
| PY | |
| cat e2e-selection-summary.md >> "$GITHUB_STEP_SUMMARY" | |
| - name: Upload the selection plan | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: x86-e2e-selection-${{ steps.context.outputs.prNumber }}-${{ steps.context.outputs.headSHA }}-${{ github.run_id }}-${{ github.run_attempt }} | |
| path: | | |
| changed-paths.txt | |
| e2e-selection-plan.json | |
| e2e-selection-summary.md | |
| retention-days: 30 | |
| e2e-control-validation: | |
| name: Validate x86 E2E control modules | |
| if: github.event_name != 'workflow_dispatch' || github.actor == 'github-actions[bot]' | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.baseSHA || github.sha }} | |
| persist-credentials: false | |
| - name: Run control module tests | |
| run: python3 -m unittest hack/test_e2e_selector.py hack/test_e2e_control.py | |
| prepare-kind-node-images: | |
| name: Prepare private Kind node image (${{ matrix.k8s-version }}) | |
| if: >- | |
| (github.event_name == 'workflow_dispatch' && github.actor == 'github-actions[bot]') || | |
| github.event_name == 'push' | |
| needs: e2e-selection | |
| permissions: | |
| contents: read | |
| packages: read | |
| runs-on: ubuntu-24.04 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| k8s-version: | |
| - v1.36.1 | |
| - v1.29.14 | |
| steps: | |
| - name: Pull private Kind node image with trusted token | |
| env: | |
| GHCR_TOKEN: ${{ github.token }} | |
| K8S_VERSION: ${{ matrix.k8s-version }} | |
| run: | | |
| set -euo pipefail | |
| dockerConfig=$(mktemp -d) | |
| trap 'rm -rf "$dockerConfig"' EXIT | |
| export DOCKER_CONFIG="$dockerConfig" | |
| printf '%s' "$GHCR_TOKEN" | docker login ghcr.io -u github-actions --password-stdin | |
| docker pull "ghcr.io/kubeovn/kindest-node:$K8S_VERSION" | |
| docker tag "ghcr.io/kubeovn/kindest-node:$K8S_VERSION" "kindest/node:$K8S_VERSION" | |
| docker save "kindest/node:$K8S_VERSION" -o "kind-node-$K8S_VERSION.tar" | |
| - name: Upload private Kind node image without credentials | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: kind-node-${{ matrix.k8s-version }} | |
| path: kind-node-${{ matrix.k8s-version }}.tar | |
| retention-days: 2 | |
| build-kube-ovn-base: | |
| name: Build kube-ovn-base | |
| if: github.event_name != 'workflow_dispatch' || github.actor == 'github-actions[bot]' | |
| runs-on: ubuntu-24.04 | |
| outputs: | |
| build-base: ${{ steps.check.outputs.build-base }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| fetch-depth: 0 | |
| - id: check | |
| run: | | |
| if [ ${{ github.event_name }} != 'pull_request' ]; then | |
| exit | |
| fi | |
| tmp_dir=`mktemp -d` | |
| cat > "$tmp_dir/on_changes.txt" <<EOF | |
| dist/images/Dockerfile.base | |
| dist/images/OpenBFDD-compile.patch | |
| dist/images/patches/ | |
| dist/images/go-deps/download-go-deps.sh | |
| dist/images/go-deps/rebuild-go-deps.sh | |
| EOF | |
| if git diff --name-only "${{ github.event.pull_request.base.sha }}...${{ github.event.pull_request.head.sha }}" | grep -Ff "$tmp_dir/on_changes.txt"; then | |
| echo build-base=1 >> "$GITHUB_OUTPUT" | |
| fi | |
| rm -frv "$tmp_dir" | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| if: steps.check.outputs.build-base == 1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: docker/setup-buildx-action@v4 | |
| if: steps.check.outputs.build-base == 1 | |
| with: | |
| driver-opts: env.BUILDKIT_STEP_LOG_MAX_SIZE=50000000 | |
| - uses: actions/setup-go@v7 | |
| if: steps.check.outputs.build-base == 1 | |
| id: setup-go | |
| with: | |
| go-version-file: go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Build kube-ovn-base image | |
| id: build | |
| if: steps.check.outputs.build-base == 1 | |
| env: | |
| GO_VERSION: ${{ steps.setup-go.outputs.go-version }} | |
| run: | | |
| make base-amd64 | |
| make base-tar-amd64 | |
| - name: Upload base images to artifact | |
| if: steps.check.outputs.build-base == 1 | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: kube-ovn-base | |
| path: image-amd64.tar | |
| build-kube-ovn-dpdk-base: | |
| name: Build kube-ovn-dpdk-base | |
| if: github.event_name != 'workflow_dispatch' || github.actor == 'github-actions[bot]' | |
| runs-on: ubuntu-24.04 | |
| outputs: | |
| build-dpdk-base: ${{ steps.check.outputs.build-dpdk-base }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| fetch-depth: 0 | |
| - id: check | |
| run: | | |
| if [ ${{ github.event_name }} != 'pull_request' ]; then | |
| exit | |
| fi | |
| tmp_dir=`mktemp -d` | |
| cat > "$tmp_dir/on_changes.txt" <<EOF | |
| dist/images/Dockerfile.base-dpdk | |
| dist/images/patches/ | |
| EOF | |
| if git diff --name-only "${{ github.event.pull_request.base.sha }}...${{ github.event.pull_request.head.sha }}" | grep -Ff "$tmp_dir/on_changes.txt"; then | |
| echo build-dpdk-base=1 >> "$GITHUB_OUTPUT" | |
| fi | |
| rm -frv "$tmp_dir" | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| if: steps.check.outputs.build-dpdk-base == 1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: docker/setup-buildx-action@v4 | |
| if: steps.check.outputs.build-dpdk-base == 1 | |
| - name: Build kube-ovn-dpdk-base image | |
| id: build | |
| if: steps.check.outputs.build-dpdk-base == 1 | |
| run: | | |
| make base-amd64-dpdk | |
| make base-tar-amd64-dpdk | |
| - name: Upload dpdk base images to artifact | |
| if: steps.check.outputs.build-dpdk-base == 1 | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: kube-ovn-dpdk-base | |
| path: image-amd64-dpdk.tar | |
| build-kube-ovn: | |
| name: Build kube-ovn | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| - e2e-selection | |
| - prepare-kind-node-images | |
| - build-kube-ovn-base | |
| - build-kube-ovn-dpdk-base | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - uses: docker/setup-buildx-action@v4 | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Setup environment variables | |
| run: | | |
| echo "TAG=$(cat VERSION)" >> "$GITHUB_ENV" | |
| echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| if: github.event_name == 'push' | |
| uses: actions/cache@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles('**/go.sum') }} | |
| restore-keys: | | |
| ${{ runner.os }}-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Unit test | |
| run: make ut | |
| - uses: shogo82148/actions-goveralls@v1 | |
| continue-on-error: true | |
| with: | |
| path-to-profile: profile.cov | |
| - name: Install golangci-lint | |
| run: | | |
| curl -sSfL https://golangci-lint.run/install.sh | sh -s -- -b $(go env GOPATH)/bin $GOLANGCI_LINT_VERSION | |
| - name: Download base images | |
| if: needs.build-kube-ovn-base.outputs.build-base == 1 | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn-base | |
| - name: Load base images | |
| if: needs.build-kube-ovn-base.outputs.build-base == 1 | |
| run: | | |
| docker load --input image-amd64.tar | |
| docker tag kubeovn/kube-ovn-base:$TAG-amd64 kubeovn/kube-ovn-base:$TAG | |
| docker tag kubeovn/kube-ovn-base:$TAG-debug-amd64 kubeovn/kube-ovn-base:$TAG-debug | |
| - name: Download dpdk base images | |
| if: needs.build-kube-ovn-dpdk-base.outputs.build-dpdk-base == 1 | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn-dpdk-base | |
| - name: Load dpdk base images | |
| if: needs.build-kube-ovn-dpdk-base.outputs.build-dpdk-base == 1 | |
| run: | | |
| docker load --input image-amd64-dpdk.tar | |
| docker tag kubeovn/kube-ovn-base:$TAG-amd64-dpdk kubeovn/kube-ovn-base:$TAG-dpdk | |
| - name: Scan base image | |
| uses: aquasecurity/trivy-action@v0.36.0 | |
| env: | |
| TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2 | |
| with: | |
| scan-type: image | |
| scanners: vuln | |
| image-ref: docker.io/kubeovn/kube-ovn-base:${{ env.TAG }} | |
| format: json | |
| output: trivy-result.json | |
| ignore-unfixed: true | |
| trivyignores: .trivyignore | |
| vuln-type: library | |
| - name: Build kubectl and CNI plugins from source | |
| env: | |
| CGO_ENABLED: "0" | |
| GO_INSTALL: "go install -v -mod=mod -trimpath" | |
| run: | | |
| go mod tidy | |
| cat trivy-result.json | |
| dockerfile=${{ github.workspace }}/dist/images/Dockerfile | |
| export GOBIN=`dirname "$dockerfile"` | |
| cni_plugins_version=`go list -m -f '{{.Version}}' github.com/containernetworking/plugins` | |
| cni_plugins_build_flags="-ldflags '-extldflags -static -X github.com/containernetworking/plugins/pkg/utils/buildversion.BuildVersion=$cni_plugins_version'" | |
| jq -r '.Results[] | select((.Type=="gobinary") and (.Vulnerabilities!=null)) | .Target' trivy-result.json | while read f; do | |
| bin=`basename $f` | |
| case $bin in | |
| loopback|macvlan|ipvlan) | |
| echo "Building $bin@$cni_plugins_version from source..." | |
| sh -c "$GO_INSTALL $cni_plugins_build_flags github.com/containernetworking/plugins/plugins/main/$bin" | |
| echo "COPY $bin /$f" >> "$dockerfile" | |
| ;; | |
| portmap) | |
| echo "Building $bin@$cni_plugins_version from source..." | |
| sh -c "$GO_INSTALL $cni_plugins_build_flags github.com/containernetworking/plugins/plugins/meta/$bin" | |
| echo "COPY $bin /$f" >> "$dockerfile" | |
| ;; | |
| kubectl) | |
| version=`go list -m -f '{{.Version}}' k8s.io/kubernetes` | |
| mod_dir=`go list -m -f '{{.Dir}}' k8s.io/kubernetes` | |
| source "$mod_dir/hack/lib/util.sh" | |
| source "$mod_dir/hack/lib/logging.sh" | |
| source "$mod_dir/hack/lib/version.sh" | |
| repo=kubernetes/kubernetes | |
| commit=unknown | |
| read type tag_sha < <(echo $(curl -s "https://api.github.com/repos/$repo/git/ref/tags/$version" | | |
| jq -r '.object.type,.object.sha')) | |
| if [ $type = "commit" ]; then | |
| commit=$tag_sha | |
| else | |
| commit=$(curl -s "https://api.github.com/repos/$repo/git/tags/$tag_sha" | jq -r '.object.sha') | |
| fi | |
| export KUBE_GIT_COMMIT="${commit}" | |
| export KUBE_GIT_TREE_STATE='clean' | |
| export KUBE_GIT_VERSION="${version}" | |
| export KUBE_GIT_MAJOR=`echo $KUBE_GIT_VERSION | cut -d. -f1 | sed 's/$v//'` | |
| export KUBE_GIT_MINOR=`echo $KUBE_GIT_VERSION | cut -d. -f2` | |
| goldflags="all=$(kube::version::ldflags) -s -w" | |
| echo "Building $bin@$version from source..." | |
| $GO_INSTALL -ldflags="${goldflags}" k8s.io/kubernetes/cmd/kubectl | |
| echo "COPY $bin /$f" >> "$dockerfile" | |
| ;; | |
| gobgp) | |
| version=`go list -m -f '{{.Version}}' github.com/osrg/gobgp/v4` | |
| echo "Building $bin@$version from source..." | |
| $GO_INSTALL github.com/osrg/gobgp/v4/cmd/$bin | |
| echo "COPY $bin /$f" >> "$dockerfile" | |
| ;; | |
| *) | |
| ;; | |
| esac | |
| done | |
| - name: Build | |
| run: | | |
| go mod tidy | |
| git diff --exit-code -- go.mod go.sum | |
| make verify-crd | |
| make lint | |
| if [ ${{ needs.build-kube-ovn-base.outputs.build-base || 0 }} = 1 ]; then | |
| make build-kube-ovn | |
| else | |
| make image-kube-ovn | |
| fi | |
| make tar-kube-ovn | |
| - name: Build dpdk | |
| run: | | |
| if [ ${{ needs.build-kube-ovn-dpdk-base.outputs.build-dpdk-base || 0 }} = 1 ]; then | |
| make build-kube-ovn-dpdk | |
| else | |
| make image-kube-ovn-dpdk | |
| fi | |
| make tar-kube-ovn-dpdk | |
| - name: Upload images to artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: kube-ovn | |
| path: kube-ovn.tar | |
| - name: Upload dpdk images to artifact | |
| uses: actions/upload-artifact@v7 | |
| if: github.event_name != 'pull_request' | |
| with: | |
| name: kube-ovn-dpdk | |
| path: kube-ovn-dpdk.tar | |
| build-vpc-nat-gateway: | |
| name: Build vpc-nat-gateway | |
| needs: e2e-selection | |
| if: github.event_name != 'workflow_dispatch' || github.actor == 'github-actions[bot]' | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Build | |
| run: | | |
| make image-vpc-nat-gateway | |
| make tar-vpc-nat-gateway | |
| - name: Upload image to artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: vpc-nat-gateway | |
| path: vpc-nat-gateway.tar | |
| build-e2e-binaries: | |
| name: Build E2E Binaries | |
| needs: e2e-selection | |
| if: github.event_name != 'workflow_dispatch' || github.actor == 'github-actions[bot]' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Lookup Go cache | |
| id: lookup-go-cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| lookup-only: true | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| if: steps.lookup-go-cache.outputs.cache-hit != 'true' | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - name: Go cache | |
| if: steps.lookup-go-cache.outputs.cache-hit != 'true' && github.event_name == 'push' | |
| uses: actions/cache@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - run: make e2e-build | |
| if: steps.lookup-go-cache.outputs.cache-hit != 'true' | |
| working-directory: ${{ env.E2E_DIR }} | |
| k8s-conformance-e2e: | |
| name: Kubernetes Conformance E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'k8s-conformance-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 25 | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJSON(needs.e2e-selection.outputs.k8sConformanceMatrix) }} | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - name: Remove DNS search domain | |
| run: | | |
| sudo sed -i '/^search/d' /etc/resolv.conf | |
| sudo systemctl restart docker | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Set environment variables | |
| run: | | |
| if [ $(($RANDOM%2)) -ne 0 ]; then | |
| # run as root and use valgrind to debug memory leak | |
| echo "VERSION=$(cat VERSION)-debug" >> "$GITHUB_ENV" | |
| echo "DEBUG_WRAPPER=valgrind" >> "$GITHUB_ENV" | |
| fi | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init-${{ matrix.ip-family }} | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install-${{ matrix.mode }}-${{ matrix.ip-family }} | |
| - name: Run E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| E2E_IP_FAMILY: ${{ matrix.ip-family }} | |
| E2E_NETWORK_MODE: ${{ matrix.mode }} | |
| run: make k8s-conformance-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > k8s-conformance-e2e-${{ matrix.ip-family }}-${{ matrix.mode }}-events.yaml | |
| tar zcf k8s-conformance-e2e-${{ matrix.ip-family }}-${{ matrix.mode }}-events.tar.gz k8s-conformance-e2e-${{ matrix.ip-family }}-${{ matrix.mode }}-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: k8s-conformance-e2e-${{ matrix.ip-family }}-${{ matrix.mode }}-events | |
| path: k8s-conformance-e2e-${{ matrix.ip-family }}-${{ matrix.mode }}-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf k8s-conformance-e2e-${{ matrix.ip-family }}-${{ matrix.mode }}-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: k8s-conformance-e2e-${{ matrix.ip-family }}-${{ matrix.mode }}-audit-log | |
| path: k8s-conformance-e2e-${{ matrix.ip-family }}-${{ matrix.mode }}-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz k8s-conformance-e2e-${{ matrix.ip-family }}-${{ matrix.mode }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: k8s-conformance-e2e-${{ matrix.ip-family }}-${{ matrix.mode }}-ko-log | |
| path: k8s-conformance-e2e-${{ matrix.ip-family }}-${{ matrix.mode }}-ko-log.tar.gz | |
| - name: Check valgrind result | |
| run: | | |
| if [ "x$DEBUG_WRAPPER" != "xvalgrind" ]; then | |
| exit | |
| fi | |
| kubectl -n kube-system rollout restart ds ovs-ovn | |
| kubectl -n kube-system rollout status ds ovs-ovn | |
| sleep 10 | |
| kubectl -n kube-system rollout restart deploy ovn-central | |
| kubectl -n kube-system rollout status deploy ovn-central | |
| while true; do | |
| if [ $(kubectl -n kube-system get pod -l app=ovs -o name | wc -l) -eq $(kubectl get node -o name | wc -l) ]; then | |
| break | |
| fi | |
| sleep 1 | |
| done | |
| kubectl ko log ovn | |
| kubectl ko log ovs | |
| for daemon in ovsdb-nb ovsdb-sb ovn-northd ovn-controller ovsdb-server ovs-vswitchd; do | |
| echo "Checking if valgrind log file for $daemon exists..." | |
| find kubectl-ko-log -type f -name "$daemon.valgrind.log.[[:digit:]]*" -exec false {} + && exit 1 | |
| done | |
| find kubectl-ko-log -type f -name '*.valgrind.log.*' | while read f; do | |
| if grep -qw 'definitely lost' "$f"; then | |
| echo "Memory leak detected in $(basename $f | awk -F. '{print $1}')." | |
| echo $f | |
| cat "$f" | |
| exit 1 | |
| fi; | |
| done | |
| k8s-netpol-e2e: | |
| name: Kubernetes Network Policy E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'k8s-netpol-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 90 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ip-family: | |
| - ipv4 | |
| - ipv6 | |
| - dual | |
| np-enforcement: | |
| - standard | |
| - lax | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - name: Remove DNS search domain | |
| run: | | |
| sudo sed -i '/^search/d' /etc/resolv.conf | |
| sudo systemctl restart docker | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| env: | |
| NP_ENFORCEMENT: "${{ matrix.np-enforcement }}" | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Set environment variables | |
| run: | | |
| if [ $(($RANDOM%2)) -ne 0 ]; then | |
| # run as root and use valgrind to debug memory leak | |
| echo "VERSION=$(cat VERSION)-debug" >> "$GITHUB_ENV" | |
| echo "DEBUG_WRAPPER=valgrind" >> "$GITHUB_ENV" | |
| fi | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init-${{ matrix.ip-family }} | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install-${{ matrix.ip-family }} | |
| - name: Run E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| run: make k8s-netpol-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > k8s-netpol-e2e-${{ matrix.ip-family }}-events.yaml | |
| tar zcf k8s-netpol-e2e-${{ matrix.ip-family }}-events.tar.gz k8s-netpol-e2e-${{ matrix.ip-family }}-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: k8s-netpol-e2e-${{ matrix.ip-family }}-events | |
| path: k8s-netpol-e2e-${{ matrix.ip-family }}-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf k8s-netpol-e2e-${{ matrix.ip-family }}-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: k8s-netpol-e2e-${{ matrix.ip-family }}-audit-log | |
| path: k8s-netpol-e2e-${{ matrix.ip-family }}-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz k8s-netpol-e2e-${{ matrix.ip-family }}-${{ matrix.np-enforcement }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: k8s-netpol-e2e-${{ matrix.ip-family }}-${{ matrix.np-enforcement }}-ko-log | |
| path: k8s-netpol-e2e-${{ matrix.ip-family }}-${{ matrix.np-enforcement }}-ko-log.tar.gz | |
| - name: Check valgrind result | |
| run: | | |
| if [ "x$DEBUG_WRAPPER" != "xvalgrind" ]; then | |
| exit | |
| fi | |
| kubectl -n kube-system rollout restart ds ovs-ovn | |
| kubectl -n kube-system rollout status ds ovs-ovn | |
| sleep 10 | |
| kubectl -n kube-system rollout restart deploy ovn-central | |
| kubectl -n kube-system rollout status deploy ovn-central | |
| while true; do | |
| if [ $(kubectl -n kube-system get pod -l app=ovs -o name | wc -l) -eq $(kubectl get node -o name | wc -l) ]; then | |
| break | |
| fi | |
| sleep 1 | |
| done | |
| kubectl ko log ovn | |
| kubectl ko log ovs | |
| for daemon in ovsdb-nb ovsdb-sb ovn-northd ovn-controller ovsdb-server ovs-vswitchd; do | |
| echo "Checking if valgrind log file for $daemon exists..." | |
| find kubectl-ko-log -type f -name "$daemon.valgrind.log.[[:digit:]]*" -exec false {} + && exit 1 | |
| done | |
| find kubectl-ko-log -type f -name '*.valgrind.log.*' | while read f; do | |
| if grep -qw 'definitely lost' "$f"; then | |
| echo "Memory leak detected in $(basename $f | awk -F. '{print $1}')." | |
| echo $f | |
| cat "$f" | |
| exit 1 | |
| fi; | |
| done | |
| cyclonus-netpol-e2e: | |
| name: Cyclonus Network Policy E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'cyclonus-netpol-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ip-family: | |
| - ipv4 | |
| - ipv6 | |
| - dual | |
| np-enforcement: | |
| - standard | |
| - lax | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Set environment variables | |
| run: | | |
| if [ $(($RANDOM%2)) -ne 0 ]; then | |
| # run as root and use valgrind to debug memory leak | |
| echo "VERSION=$(cat VERSION)-debug" >> "$GITHUB_ENV" | |
| echo "DEBUG_WRAPPER=valgrind" >> "$GITHUB_ENV" | |
| fi | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init-${{ matrix.ip-family }} | |
| - name: Install Kube-OVN | |
| env: | |
| NP_ENFORCEMENT: "${{ matrix.np-enforcement }}" | |
| id: install | |
| run: make kind-install-${{ matrix.ip-family }} | |
| - name: Run E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| run: make cyclonus-netpol-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > cyclonus-netpol-e2e-${{ matrix.ip-family }}-events.yaml | |
| tar zcf cyclonus-netpol-e2e-${{ matrix.ip-family }}-events.tar.gz cyclonus-netpol-e2e-${{ matrix.ip-family }}-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: cyclonus-netpol-e2e-${{ matrix.ip-family }}-events | |
| path: cyclonus-netpol-e2e-${{ matrix.ip-family }}-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf cyclonus-netpol-e2e-${{ matrix.ip-family }}-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: cyclonus-netpol-e2e-${{ matrix.ip-family }}-audit-log | |
| path: cyclonus-netpol-e2e-${{ matrix.ip-family }}-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz cyclonus-netpol-e2e-${{ matrix.ip-family }}-${{ matrix.np-enforcement }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: cyclonus-netpol-e2e-${{ matrix.ip-family }}-${{ matrix.np-enforcement }}-ko-log | |
| path: cyclonus-netpol-e2e-${{ matrix.ip-family }}-${{ matrix.np-enforcement }}-ko-log.tar.gz | |
| - name: Check valgrind result | |
| run: | | |
| if [ "x$DEBUG_WRAPPER" != "xvalgrind" ]; then | |
| exit | |
| fi | |
| kubectl -n kube-system rollout restart ds ovs-ovn | |
| kubectl -n kube-system rollout status ds ovs-ovn | |
| sleep 10 | |
| kubectl -n kube-system rollout restart deploy ovn-central | |
| kubectl -n kube-system rollout status deploy ovn-central | |
| while true; do | |
| if [ $(kubectl -n kube-system get pod -l app=ovs -o name | wc -l) -eq $(kubectl get node -o name | wc -l) ]; then | |
| break | |
| fi | |
| sleep 1 | |
| done | |
| kubectl ko log ovn | |
| kubectl ko log ovs | |
| for daemon in ovsdb-nb ovsdb-sb ovn-northd ovn-controller ovsdb-server ovs-vswitchd; do | |
| echo "Checking if valgrind log file for $daemon exists..." | |
| find kubectl-ko-log -type f -name "$daemon.valgrind.log.[[:digit:]]*" -exec false {} + && exit 1 | |
| done | |
| find kubectl-ko-log -type f -name '*.valgrind.log.*' | while read f; do | |
| if grep -qw 'definitely lost' "$f"; then | |
| echo "Memory leak detected in $(basename $f | awk -F. '{print $1}')." | |
| echo $f | |
| cat "$f" | |
| exit 1 | |
| fi; | |
| done | |
| kube-ovn-conformance-e2e: | |
| name: Kube-OVN Conformance E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'kube-ovn-conformance-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 50 | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJSON(needs.e2e-selection.outputs.kubeOvnConformanceMatrix) }} | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Set environment variables | |
| run: | | |
| if [ $(($RANDOM%2)) -ne 0 ]; then | |
| # run as root and use valgrind to debug memory leak | |
| echo "VERSION=$(cat VERSION)-debug" >> "$GITHUB_ENV" | |
| echo "DEBUG_WRAPPER=valgrind" >> "$GITHUB_ENV" | |
| fi | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init-${{ matrix.ip-family }} | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install-${{ matrix.mode }}-${{ matrix.ip-family }} | |
| - name: Run E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| E2E_IP_FAMILY: ${{ matrix.ip-family }} | |
| E2E_NETWORK_MODE: ${{ matrix.mode }} | |
| run: | | |
| make kube-ovn-conformance-e2e | |
| make kind-install-multus | |
| make kind-install-kubevirt | |
| make kube-ovn-kubevirt-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > kube-ovn-conformance-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.yaml | |
| tar zcf kube-ovn-conformance-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.tar.gz kube-ovn-conformance-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-conformance-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events | |
| path: kube-ovn-conformance-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf kube-ovn-conformance-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-conformance-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-audit-log | |
| path: kube-ovn-conformance-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz kube-ovn-conformance-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-conformance-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-ko-log | |
| path: kube-ovn-conformance-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-ko-log.tar.gz | |
| - name: Check valgrind result | |
| run: | | |
| if [ "x$DEBUG_WRAPPER" != "xvalgrind" ]; then | |
| exit | |
| fi | |
| kubectl -n kube-system rollout restart ds ovs-ovn | |
| kubectl -n kube-system rollout status ds ovs-ovn | |
| sleep 10 | |
| kubectl -n kube-system rollout restart deploy ovn-central | |
| kubectl -n kube-system rollout status deploy ovn-central | |
| while true; do | |
| if [ $(kubectl -n kube-system get pod -l app=ovs -o name | wc -l) -eq $(kubectl get node -o name | wc -l) ]; then | |
| break | |
| fi | |
| sleep 1 | |
| done | |
| kubectl ko log ovn | |
| kubectl ko log ovs | |
| for daemon in ovsdb-nb ovsdb-sb ovn-northd ovn-controller ovsdb-server ovs-vswitchd; do | |
| echo "Checking if valgrind log file for $daemon exists..." | |
| find kubectl-ko-log -type f -name "$daemon.valgrind.log.[[:digit:]]*" -exec false {} + && exit 1 | |
| done | |
| find kubectl-ko-log -type f -name '*.valgrind.log.*' | while read f; do | |
| if grep -qw 'definitely lost' "$f"; then | |
| echo "Memory leak detected in $(basename $f | awk -F. '{print $1}')." | |
| echo $f | |
| cat "$f" | |
| exit 1 | |
| fi; | |
| done | |
| - name: Cleanup | |
| run: timeout -k 10 180 sh -x dist/images/cleanup.sh | |
| kube-ovn-ic-conformance-e2e: | |
| name: Kube-OVN IC Conformance E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'kube-ovn-ic-conformance-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ip-family: | |
| - ipv4 | |
| - ipv6 | |
| - dual | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init-ovn-ic-${{ matrix.ip-family }} | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install-ovn-ic-${{ matrix.ip-family }} | |
| - name: Run E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| E2E_IP_FAMILY: ${{ matrix.ip-family }} | |
| run: make kube-ovn-ic-conformance-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| for cluster in `kind get clusters`; do | |
| kubectl config use-context kind-$cluster | |
| kubectl get events -A -o yaml > kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-$cluster-events.yaml | |
| done | |
| tar zcf kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-events.tar.gz \ | |
| `kind get clusters | xargs -I {} echo kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-{}-events.yaml` | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-events | |
| path: kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| for cluster in `kind get clusters`; do | |
| docker cp $cluster-control-plane:/var/log/kubernetes/kube-apiserver-audit.log \ | |
| ./kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-$cluster-kube-apiserver-audit.log | |
| done | |
| tar zcvf kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-audit-log.tar.gz \ | |
| `kind get clusters | xargs -I {} echo kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-{}-kube-apiserver-audit.log` | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-audit-log | |
| path: kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| for cluster in `kind get clusters`; do | |
| kubectl config use-context kind-$cluster | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-$cluster-ko-log.tar.gz | |
| done | |
| tar zcvf kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-ko-log.tar.gz \ | |
| `kind get clusters | xargs -I {} echo kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-{}-ko-log.tar.gz` | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-ko-log | |
| path: kube-ovn-ic-conformance-e2e-${{ matrix.ip-family }}-ko-log.tar.gz | |
| multus-conformance-e2e: | |
| name: Multus Conformance E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'multus-conformance-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ip-family: | |
| - ipv4 | |
| - ipv6 | |
| - dual | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download kube-ovn image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load images | |
| run: docker load -i kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init-${{ matrix.ip-family }} | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install-${{ matrix.ip-family }} | |
| - name: Install Multus | |
| run: make kind-install-multus | |
| - name: Run E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| E2E_IP_FAMILY: ${{ matrix.ip-family }} | |
| run: make kube-ovn-multus-conformance-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > multus-conformance-e2e-${{ matrix.ip-family }}-events.yaml | |
| tar zcf multus-conformance-e2e-${{ matrix.ip-family }}-events.tar.gz multus-conformance-e2e-${{ matrix.ip-family }}-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: multus-conformance-e2e-${{ matrix.ip-family }}-events | |
| path: multus-conformance-e2e-${{ matrix.ip-family }}-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf multus-conformance-e2e-${{ matrix.ip-family }}-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: multus-conformance-e2e-${{ matrix.ip-family }}-audit-log | |
| path: multus-conformance-e2e-${{ matrix.ip-family }}-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz multus-conformance-e2e-${{ matrix.ip-family }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: multus-conformance-e2e-${{ matrix.ip-family }}-ko-log | |
| path: multus-conformance-e2e-${{ matrix.ip-family }}-ko-log.tar.gz | |
| non-primary-cni-e2e: | |
| name: Non-Primary CNI E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'non-primary-cni-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ip-family: | |
| - ipv4 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - name: Remove DNS search domain | |
| run: | | |
| sudo sed -i '/^search/d' /etc/resolv.conf | |
| sudo systemctl restart docker | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Download vpc-nat-gateway image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: vpc-nat-gateway | |
| - name: Load image | |
| run: | | |
| docker load --input kube-ovn.tar | |
| docker load --input vpc-nat-gateway.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init-${{ matrix.ip-family }} | |
| - name: Load vpc-nat-gateway image into kind cluster | |
| run: make kind-load-image-vpc-nat-gateway | |
| - name: Install Mults-CNI, Cilium, and Kube-OVN | |
| id: install | |
| run: make kind-install-multus-cilium-kubeovn-non-primary-${{ matrix.ip-family }} | |
| - name: Run non-primary CNI e2e | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| E2E_IP_FAMILY: ${{ matrix.ip-family }} | |
| E2E_NETWORK_MODE: overlay | |
| KUBE_OVN_PRIMARY_CNI: "false" | |
| run: make kube-ovn-non-primary-cni-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > non-primary-cni-e2e-${{ matrix.ip-family }}-events.yaml | |
| tar zcf non-primary-cni-e2e-${{ matrix.ip-family }}-events.tar.gz non-primary-cni-e2e-${{ matrix.ip-family }}-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: non-primary-cni-e2e-${{ matrix.ip-family }}-events | |
| path: non-primary-cni-e2e-${{ matrix.ip-family }}-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf non-primary-cni-e2e-${{ matrix.ip-family }}-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: non-primary-cni-e2e-${{ matrix.ip-family }}-audit-log | |
| path: non-primary-cni-e2e-${{ matrix.ip-family }}-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz non-primary-cni-e2e-${{ matrix.ip-family }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: non-primary-cni-e2e-${{ matrix.ip-family }}-ko-log | |
| path: non-primary-cni-e2e-${{ matrix.ip-family }}-ko-log.tar.gz | |
| bgp-speaker-e2e: | |
| name: BGP Speaker E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'bgp-speaker-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download kube-ovn image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load kube-ovn image | |
| run: docker load -i kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create BGP kind and containerlab topology | |
| id: setup | |
| run: | | |
| pipx install jinjanator | |
| make kind-init-bgp | |
| - name: Install Kube-OVN and BGP speakers | |
| id: install | |
| run: make kind-install-bgp | |
| - name: Run BGP speaker E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| E2E_IP_FAMILY: ipv4 | |
| E2E_NETWORK_MODE: overlay | |
| run: make kube-ovn-bgp-speaker-e2e | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: Collect BGP diagnostics | |
| if: failure() && (steps.setup.conclusion == 'failure' || steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| mkdir -p bgp-speaker-e2e-diagnostics | |
| docker exec clab-bgp-router vtysh -c "show bgp ipv4 unicast summary json" > bgp-speaker-e2e-diagnostics/frr-summary.json || true | |
| docker exec clab-bgp-router vtysh -c "show bgp ipv4 unicast json" > bgp-speaker-e2e-diagnostics/frr-routes.json || true | |
| kubectl -n kube-system get ds kube-ovn-speaker -o yaml > bgp-speaker-e2e-diagnostics/speaker-daemonset.yaml || true | |
| kubectl -n kube-system get pods -l app=kube-ovn-speaker -o wide > bgp-speaker-e2e-diagnostics/speaker-pods.txt || true | |
| kubectl -n kube-system logs -l app=kube-ovn-speaker --all-containers --prefix > bgp-speaker-e2e-diagnostics/speaker.log || true | |
| kubectl get events -A -o yaml > bgp-speaker-e2e-diagnostics/events.yaml || true | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log bgp-speaker-e2e-diagnostics/ || true | |
| tar zcf bgp-speaker-e2e-diagnostics.tar.gz bgp-speaker-e2e-diagnostics | |
| - name: Upload BGP diagnostics | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.setup.conclusion == 'failure' || steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: bgp-speaker-e2e-diagnostics | |
| path: bgp-speaker-e2e-diagnostics.tar.gz | |
| - name: kubectl ko log | |
| if: failure() && (steps.setup.conclusion == 'failure' || steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| if make kubectl-ko-log && test -f kubectl-ko-log.tar.gz; then | |
| mv kubectl-ko-log.tar.gz bgp-speaker-e2e-ko-log.tar.gz | |
| else | |
| echo "kubectl ko log was unavailable because the BGP test cluster did not become usable." > bgp-speaker-e2e-ko-log-unavailable.txt | |
| tar zcf bgp-speaker-e2e-ko-log.tar.gz bgp-speaker-e2e-ko-log-unavailable.txt | |
| fi | |
| - name: Upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.setup.conclusion == 'failure' || steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: bgp-speaker-e2e-ko-log | |
| path: bgp-speaker-e2e-ko-log.tar.gz | |
| - name: Clean BGP topology | |
| if: always() | |
| run: make kind-clean-bgp | |
| kube-ovn-hosted-ovn-central-e2e: | |
| name: Kube-OVN Hosted OVN Central E2E (${{ matrix.ip-family }}, ${{ matrix.tenant-control-plane }} control-plane) | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'kube-ovn-hosted-ovn-central-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 60 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - ip-family: ipv4 | |
| tenant-control-plane: single | |
| tenant-control-plane-replicas: 1 | |
| - ip-family: ipv6 | |
| tenant-control-plane: single | |
| tenant-control-plane-replicas: 1 | |
| - ip-family: dual | |
| tenant-control-plane: single | |
| tenant-control-plane-replicas: 1 | |
| - ip-family: ipv4 | |
| tenant-control-plane: ha | |
| tenant-control-plane-replicas: 3 | |
| - ip-family: ipv6 | |
| tenant-control-plane: ha | |
| tenant-control-plane-replicas: 3 | |
| - ip-family: dual | |
| tenant-control-plane: ha | |
| tenant-control-plane-replicas: 3 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Remove DNS search domain | |
| run: | | |
| sudo sed -i '/^search/d' /etc/resolv.conf | |
| sudo systemctl restart docker | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles('**/go.sum') }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: | | |
| docker load --input kube-ovn.tar | |
| docker tag "kubeovn/kube-ovn:$(cat VERSION)" kubeovn/kube-ovn:dev | |
| - name: Verify hosted OVN central values | |
| run: bash hack/kamaji-e2e-test.sh | |
| - name: Create hosted OVN central environment | |
| id: install | |
| env: | |
| E2E_IP_FAMILY: ${{ matrix.ip-family }} | |
| TENANT_CONTROL_PLANE_REPLICAS: ${{ matrix.tenant-control-plane-replicas }} | |
| run: make kind-install-kamaji | |
| - name: Run hosted OVN central E2E | |
| id: e2e | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| E2E_IP_FAMILY: ${{ matrix.ip-family }} | |
| E2E_NETWORK_MODE: overlay | |
| run: make kube-ovn-kamaji-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| kubectl --context kind-mgmt get events -A -o yaml > hcp-e2e-mgmt-events.yaml || true | |
| tenant_kubeconfig="$(./hack/kamaji-e2e.sh kubeconfig)" | |
| if [ -s "$tenant_kubeconfig" ]; then | |
| KUBECONFIG="$tenant_kubeconfig" kubectl get events -A -o yaml > hcp-e2e-tenant-events.yaml || true | |
| fi | |
| tar zcf hcp-e2e-${{ matrix.ip-family }}-${{ matrix.tenant-control-plane }}-events.tar.gz hcp-e2e-*-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: hcp-e2e-${{ matrix.ip-family }}-${{ matrix.tenant-control-plane }}-events | |
| path: hcp-e2e-${{ matrix.ip-family }}-${{ matrix.tenant-control-plane }}-events.tar.gz | |
| - name: Collect hosted OVN central diagnostics | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| job_dir="${JOB_DIR:-/tmp/kamaji-e2e}" | |
| if [ -d "$job_dir/diagnostics" ]; then | |
| tar -C "$job_dir" -zcf hcp-e2e-${{ matrix.ip-family }}-${{ matrix.tenant-control-plane }}-diagnostics.tar.gz diagnostics | |
| fi | |
| - name: Upload hosted OVN central diagnostics | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: hcp-e2e-${{ matrix.ip-family }}-${{ matrix.tenant-control-plane }}-diagnostics | |
| path: hcp-e2e-${{ matrix.ip-family }}-${{ matrix.tenant-control-plane }}-diagnostics.tar.gz | |
| if-no-files-found: ignore | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| tenant_kubeconfig="$(./hack/kamaji-e2e.sh kubeconfig)" | |
| if [ -s "$tenant_kubeconfig" ]; then | |
| KUBECONFIG="$tenant_kubeconfig" make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz hcp-e2e-${{ matrix.ip-family }}-${{ matrix.tenant-control-plane }}-ko-log.tar.gz | |
| fi | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: hcp-e2e-${{ matrix.ip-family }}-${{ matrix.tenant-control-plane }}-ko-log | |
| path: hcp-e2e-${{ matrix.ip-family }}-${{ matrix.tenant-control-plane }}-ko-log.tar.gz | |
| if-no-files-found: ignore | |
| - name: Clean hosted OVN central environment | |
| if: always() | |
| run: make kind-clean-kamaji | |
| chart-test: | |
| name: Chart Installation/Uninstallation Test | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'chart-test') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| runs-on: ubuntu-24.04 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ssl: | |
| - "true" | |
| - "false" | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init | |
| - name: Install Kube-OVN | |
| id: install | |
| env: | |
| ENABLE_SSL: "${{ matrix.ssl }}" | |
| run: make kind-install-chart | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && steps.install.conclusion == 'failure') }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz chart-test-${{ matrix.ssl }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: chart-test-${{ matrix.ssl }}-ko-log | |
| path: chart-test-${{ matrix.ssl }}-ko-log.tar.gz | |
| - name: Uninstall Kube-OVN | |
| run: make uninstall-chart | |
| underlay-logical-gateway-installation-test: | |
| name: Underlay Logical Gateway Installation Test | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'underlay-logical-gateway-installation-test') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init-dual | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install-underlay-logical-gateway-dual | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && steps.install.conclusion == 'failure') }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz underlay-logical-gateway-installation-test-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: underlay-logical-gateway-installation-test-ko-log | |
| path: underlay-logical-gateway-installation-test-ko-log.tar.gz | |
| - name: Cleanup | |
| run: timeout -k 10 180 sh -x dist/images/cleanup.sh | |
| no-ovn-lb-test: | |
| name: Disable OVN LB Test | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'no-ovn-lb-test') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init | |
| - name: Install Kube-OVN without LoadBalancer | |
| id: install | |
| env: | |
| ENABLE_LB: "false" | |
| run: make kind-install | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && steps.install.conclusion == 'failure') }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz no-ovn-lb-test-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: no-ovn-lb-test-ko-log | |
| path: no-ovn-lb-test-ko-log.tar.gz | |
| - name: Cleanup | |
| run: timeout -k 10 180 sh -x dist/images/cleanup.sh | |
| no-np-test: | |
| name: Disable Network Policy Test | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'no-np-test') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init | |
| - name: Install Kube-OVN | |
| id: install | |
| env: | |
| ENABLE_NP: "false" | |
| run: make kind-install | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && steps.install.conclusion == 'failure') }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz no-np-test-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: no-np-test-ko-log | |
| path: no-np-test-ko-log.tar.gz | |
| - name: Cleanup | |
| run: timeout -k 10 180 sh -x dist/images/cleanup.sh | |
| lb-svc-e2e: | |
| name: LB Service E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'lb-svc-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-vpc-nat-gateway | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download kube-ovn image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Download vpc-nat-gateway image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: vpc-nat-gateway | |
| - name: Load images | |
| run: | | |
| docker load -i kube-ovn.tar | |
| docker load -i vpc-nat-gateway.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init | |
| - name: Install Multus and Kube-OVN | |
| id: install | |
| run: make kind-install-lb-svc | |
| - name: Run E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| run: make kube-ovn-lb-svc-conformance-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > lb-svc-e2e-events.yaml | |
| tar zcf lb-svc-e2e-events.tar.gz lb-svc-e2e-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: lb-svc-e2e-events | |
| path: lb-svc-e2e-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf lb-svc-e2e-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: lb-svc-e2e-audit-log | |
| path: lb-svc-e2e-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz lb-svc-e2e-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: lb-svc-e2e-ko-log | |
| path: lb-svc-e2e-ko-log.tar.gz | |
| webhook-e2e: | |
| name: Webhook E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'webhook-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download kube-ovn image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load images | |
| run: | | |
| docker load -i kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init | |
| - name: Install Kube-OVN with webhook | |
| id: install | |
| run: make kind-install-webhook | |
| - name: Run E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| run: make kube-ovn-webhook-e2e | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz webhook-e2e-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: webhook-e2e-ko-log | |
| path: webhook-e2e-ko-log.tar.gz | |
| installation-compatibility-test: | |
| name: Installation Compatibility Test | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'installation-compatibility-test') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| k8s-version: | |
| - v1.29.14 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.29.14 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.29.14.tar | |
| - name: Create kind cluster | |
| env: | |
| K8S_VERSION: ${{ matrix.k8s-version }} | |
| run: | | |
| pipx install jinjanator | |
| make kind-init | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && steps.install.conclusion == 'failure') }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz installation-compatibility-test-${{ matrix.k8s-version }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: installation-compatibility-test-${{ matrix.k8s-version }}-ko-log | |
| path: installation-compatibility-test-${{ matrix.k8s-version }}-ko-log.tar.gz | |
| - name: Cleanup | |
| run: timeout -k 10 180 sh -x dist/images/cleanup.sh | |
| talos-installation-test: | |
| name: Talos Installation Test | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'talos-installation-test') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| runs-on: larger-runner | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ip-family: | |
| - ipv4 | |
| - ipv6 | |
| - dual | |
| mode: | |
| - overlay | |
| - underlay | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Install talosctl | |
| run: | | |
| curl -sLo install-talosctl.sh https://talos.dev/install | |
| sed -i "s|/latest/download/|/download/${{ env.TALOS_VERSION }}/|g" install-talosctl.sh | |
| sed -i "s|/latest/|/${{ env.TALOS_VERSION }}/|g" install-talosctl.sh | |
| sh install-talosctl.sh | |
| - name: Install KVM and libvirt | |
| run: | | |
| sudo apt update | |
| sudo apt install qemu-kvm libvirt-daemon-system | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Create Talos cluster | |
| run: | | |
| pipx install jinjanator | |
| make talos-init-${{ matrix.ip-family }} | |
| kubectl describe node | |
| - name: Install Kube-OVN | |
| id: install | |
| run: | | |
| make talos-install-${{ matrix.mode }}-${{ matrix.ip-family }} | |
| kubectl -n kube-system rollout status ds/kube-ovn-pinger | |
| kubectl -n kube-system rollout restart deploy/coredns | |
| kubectl -n kube-system rollout status deploy/coredns | |
| kubectl get pod -o wide -A | |
| kubectl get endpointslice -A | |
| kubectl get subnet -o wide | |
| if [ "${{ matrix.mode }}" = "underlay" ]; then | |
| kubectl get provider-network -o wide | |
| kubectl get vlan -o wide | |
| fi | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && steps.install.conclusion == 'failure') }} | |
| run: make check-kube-ovn-pod-restarts || make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz talos-installation-test-${{ matrix.ip-family }}-${{ matrix.mode }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: talos-installation-test-${{ matrix.ip-family }}-${{ matrix.mode }}-ko-log | |
| path: talos-installation-test-${{ matrix.ip-family }}-${{ matrix.mode }}-ko-log.tar.gz | |
| kube-ovn-cnp-domain-e2e: | |
| name: Kube-OVN CNP Domain E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'kube-ovn-cnp-domain-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ip-family: | |
| - ipv4 | |
| mode: | |
| - overlay | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Set environment variables | |
| run: | | |
| if [ $(($RANDOM%2)) -ne 0 ]; then | |
| # run as root and use valgrind to debug memory leak | |
| echo "VERSION=$(cat VERSION)-debug" >> "$GITHUB_ENV" | |
| echo "DEBUG_WRAPPER=valgrind" >> "$GITHUB_ENV" | |
| fi | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init-${{ matrix.ip-family }} | |
| - name: Clone DNSNameResolver repository | |
| run: | | |
| git clone https://github.com/kubeovn/dnsnameresolver.git | |
| cd dnsnameresolver | |
| make build | |
| docker save kubeovn/dnsnameresolver:dev -o dnsnameresolver.tar | |
| docker load --input dnsnameresolver.tar | |
| make install | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install-anp-dns-resolver | |
| - name: Run CNP Domain E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| E2E_IP_FAMILY: ${{ matrix.ip-family }} | |
| E2E_NETWORK_MODE: ${{ matrix.mode }} | |
| run: make kube-ovn-cnp-domain-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > kube-ovn-cnp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.yaml | |
| tar zcf kube-ovn-cnp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.tar.gz kube-ovn-cnp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-cnp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events | |
| path: kube-ovn-cnp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz kube-ovn-cnp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-cnp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-ko-log | |
| path: kube-ovn-cnp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-ko-log.tar.gz | |
| kube-ovn-anp-domain-e2e: | |
| name: Kube-OVN ANP Domain E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'kube-ovn-anp-domain-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ip-family: | |
| - ipv4 | |
| mode: | |
| - overlay | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Set environment variables | |
| run: | | |
| if [ $(($RANDOM%2)) -ne 0 ]; then | |
| # run as root and use valgrind to debug memory leak | |
| echo "VERSION=$(cat VERSION)-debug" >> "$GITHUB_ENV" | |
| echo "DEBUG_WRAPPER=valgrind" >> "$GITHUB_ENV" | |
| fi | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init-${{ matrix.ip-family }} | |
| - name: Clone DNSNameResolver repository | |
| run: | | |
| git clone https://github.com/kubeovn/dnsnameresolver.git | |
| cd dnsnameresolver | |
| make build | |
| docker save kubeovn/dnsnameresolver:dev -o dnsnameresolver.tar | |
| docker load --input dnsnameresolver.tar | |
| make install | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install-anp-dns-resolver | |
| - name: Run ANP Domain E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| E2E_IP_FAMILY: ${{ matrix.ip-family }} | |
| E2E_NETWORK_MODE: ${{ matrix.mode }} | |
| run: make kube-ovn-anp-domain-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > kube-ovn-anp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.yaml | |
| tar zcf kube-ovn-anp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.tar.gz kube-ovn-anp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-anp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events | |
| path: kube-ovn-anp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz kube-ovn-anp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-anp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-ko-log | |
| path: kube-ovn-anp-domain-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-ko-log.tar.gz | |
| cilium-chaining-e2e: | |
| name: Cilium Chaining E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'cilium-chaining-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ip-family: | |
| - ipv4 | |
| # - ipv6 | |
| # - dual | |
| mode: | |
| - overlay | |
| - underlay | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - uses: azure/setup-helm@v5.0.1 | |
| with: | |
| version: '${{ env.HELM_VERSION }}' | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - name: Configure docker | |
| run: | | |
| # enable addition of ip6tables rules | |
| sudo sh -c "echo '{\"experimental\": true, \"ip6tables\": true}' > /etc/docker/daemon.json" | |
| # remove DNS search domain | |
| sudo sed -i '/^search/d' /etc/resolv.conf | |
| # restart docker | |
| sudo systemctl restart docker | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init-cilium-chaining-${{ matrix.ip-family }} | |
| - name: Install Kube-OVN with Cilium chaining | |
| id: install | |
| run: make kind-install-cilium-chaining-${{ matrix.mode }}-${{ matrix.ip-family }} | |
| - name: Run E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_CILIUM_CHAINING: "true" | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| E2E_IP_FAMILY: ${{ matrix.ip-family }} | |
| E2E_NETWORK_MODE: ${{ matrix.mode }} | |
| run: make k8s-conformance-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > cilium-chaining-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.yaml | |
| tar zcf cilium-chaining-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.tar.gz cilium-chaining-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: cilium-chaining-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events | |
| path: cilium-chaining-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf cilium-chaining-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: cilium-chaining-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-audit-log | |
| path: cilium-chaining-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz cilium-chaining-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: cilium-chaining-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-ko-log | |
| path: cilium-chaining-e2e-${{ matrix.mode }}-${{ matrix.ip-family }}-ko-log.tar.gz | |
| - name: Cleanup | |
| run: timeout -k 10 180 sh -x dist/images/cleanup.sh | |
| kube-ovn-ha-e2e: | |
| name: Kube-OVN HA E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'kube-ovn-ha-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ssl: | |
| - "true" | |
| - "false" | |
| bind-local: | |
| - "true" | |
| - "false" | |
| ip-family: | |
| - ipv4 | |
| - ipv6 | |
| - dual | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init-ha-${{ matrix.ip-family }} | |
| - name: Install Kube-OVN | |
| id: install | |
| env: | |
| NET_STACK: "${{ matrix.ip-family }}" | |
| ENABLE_SSL: "${{ matrix.ssl }}" | |
| ENABLE_BIND_LOCAL_IP: "${{ matrix.bind-local }}" | |
| TLS_MIN_VERSION: "${{ matrix.ssl == 'true' && 'TLS12' || '' }}" | |
| TLS_MAX_VERSION: "${{ matrix.ssl == 'true' && 'TLS13' || '' }}" | |
| TLS_CIPHER_SUITES: "${{ matrix.ssl == 'true' && 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_AES_256_GCM_SHA384' || '' }}" | |
| run: make kind-install-chart | |
| - name: Run E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| E2E_IP_FAMILY: ${{ matrix.ip-family }} | |
| run: | | |
| make kube-ovn-security-e2e | |
| make kube-ovn-ha-e2e | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz kube-ovn-ha-e2e-${{ matrix.ssl }}-${{ matrix.bind-local }}-${{ matrix.ip-family }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-ha-e2e-${{ matrix.ssl }}-${{ matrix.bind-local }}-${{ matrix.ip-family }}-ko-log | |
| path: kube-ovn-ha-e2e-${{ matrix.ssl }}-${{ matrix.bind-local }}-${{ matrix.ip-family }}-ko-log.tar.gz | |
| - name: Cleanup | |
| run: timeout -k 10 180 sh -x dist/images/cleanup.sh | |
| kube-ovn-submariner-conformance-e2e: | |
| name: Kube-OVN Submariner Conformance E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'kube-ovn-submariner-conformance-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 60 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Install submariner subctl | |
| env: | |
| VERSION: v${{ env.SUBMARINER_VERSION }} | |
| DESTDIR: /usr/local/bin | |
| run: curl -Ls https://get.submariner.io | bash | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init-ovn-submariner | |
| - name: Install Kube-OVN and Submariner | |
| id: install | |
| run: make kind-install-ovn-submariner | |
| - name: Run E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| run: make kube-ovn-submariner-conformance-e2e | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz kube-ovn-submariner-conformance-e2e-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-submariner-conformance-e2e-ko-log | |
| path: kube-ovn-submariner-conformance-e2e-ko-log.tar.gz | |
| - name: Cleanup | |
| run: timeout -k 10 180 sh -x dist/images/cleanup.sh | |
| vpc-egress-gateway-e2e: | |
| name: VPC Egress Gateway E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'vpc-egress-gateway-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ip-family: | |
| - ipv4 | |
| - ipv6 | |
| - dual | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load image | |
| run: docker load --input kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| n_worker=2 make kind-init-${{ matrix.ip-family }} | |
| - name: Install Kube-OVN | |
| id: install | |
| env: | |
| UNTAINT_CONTROL_PLANE: "false" | |
| run: make kind-install-debug-valgrind-${{ matrix.ip-family }} | |
| - name: Install Multus | |
| run: make kind-install-multus | |
| - name: Run E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| E2E_IP_FAMILY: ${{ matrix.ip-family }} | |
| run: make vpc-egress-gateway-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > vpc-egress-gateway-e2e-${{ matrix.ip-family }}-events.yaml | |
| tar zcf vpc-egress-gateway-e2e-${{ matrix.ip-family }}-events.tar.gz vpc-egress-gateway-e2e-${{ matrix.ip-family }}-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: vpc-egress-gateway-e2e-${{ matrix.ip-family }}-events | |
| path: vpc-egress-gateway-e2e-${{ matrix.ip-family }}-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf vpc-egress-gateway-e2e-${{ matrix.ip-family }}-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: vpc-egress-gateway-e2e-${{ matrix.ip-family }}-audit-log | |
| path: vpc-egress-gateway-e2e-${{ matrix.ip-family }}-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz vpc-egress-gateway-e2e-${{ matrix.ip-family }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: vpc-egress-gateway-e2e-${{ matrix.ip-family }}-ko-log | |
| path: vpc-egress-gateway-e2e-${{ matrix.ip-family }}-ko-log.tar.gz | |
| - name: Check valgrind result | |
| run: | | |
| kubectl -n kube-system rollout restart ds ovs-ovn | |
| kubectl -n kube-system rollout status ds ovs-ovn | |
| sleep 10 | |
| kubectl -n kube-system rollout restart deploy ovn-central | |
| kubectl -n kube-system rollout status deploy ovn-central | |
| while true; do | |
| if [ $(kubectl -n kube-system get pod -l app=ovs -o name | wc -l) -eq $(kubectl get node -o name | wc -l) ]; then | |
| break | |
| fi | |
| sleep 1 | |
| done | |
| kubectl ko log ovn | |
| kubectl ko log ovs | |
| for daemon in ovsdb-nb ovsdb-sb ovn-northd ovn-controller ovsdb-server ovs-vswitchd; do | |
| echo "Checking if valgrind log file for $daemon exists..." | |
| find kubectl-ko-log -type f -name "$daemon.valgrind.log.[[:digit:]]*" -exec false {} + && exit 1 | |
| done | |
| find kubectl-ko-log -type f -name '*.valgrind.log.*' | while read f; do | |
| if grep -qw 'definitely lost' "$f"; then | |
| echo "Memory leak detected in $(basename $f | awk -F. '{print $1}')." | |
| echo $f | |
| cat "$f" | |
| exit 1 | |
| fi; | |
| done | |
| - name: Cleanup | |
| run: timeout -k 10 180 sh -x dist/images/cleanup.sh | |
| iptables-vpc-nat-gw-conformance-e2e: | |
| name: Iptables VPC NAT Gateway E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'iptables-vpc-nat-gw-conformance-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-vpc-nat-gateway | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download kube-ovn image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Download vpc-nat-gateway image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: vpc-nat-gateway | |
| - name: Load images | |
| run: | | |
| docker load -i kube-ovn.tar | |
| docker load -i vpc-nat-gateway.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init | |
| - name: Install Kube-OVN with VPC NAT gateway enabled | |
| id: install | |
| run: make kind-install-vpc-nat-gw | |
| - name: Run E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| run: make iptables-vpc-nat-gw-conformance-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > iptables-vpc-nat-gw-conformance-e2e-events.yaml | |
| tar zcf iptables-vpc-nat-gw-conformance-e2e-events.tar.gz iptables-vpc-nat-gw-conformance-e2e-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: iptables-vpc-nat-gw-conformance-e2e-events | |
| path: iptables-vpc-nat-gw-conformance-e2e-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf iptables-vpc-nat-gw-conformance-e2e-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: iptables-vpc-nat-gw-conformance-e2e-audit-log | |
| path: iptables-vpc-nat-gw-conformance-e2e-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz iptables-vpc-nat-gw-conformance-e2e-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: iptables-vpc-nat-gw-conformance-e2e-ko-log | |
| path: iptables-vpc-nat-gw-conformance-e2e-ko-log.tar.gz | |
| ovn-vpc-nat-gw-conformance-e2e: | |
| name: OVN VPC NAT Gateway E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'ovn-vpc-nat-gw-conformance-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download kube-ovn image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load images | |
| run: docker load -i kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install | |
| - name: Run Vip E2E | |
| id: vip-e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| run: make vip-conformance-e2e | |
| - name: Run Ovn VPC NAT GW E2E | |
| id: vpc-e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| run: make ovn-vpc-nat-gw-conformance-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.vip-e2e.conclusion == 'failure' || steps.vpc-e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > ovn-vpc-nat-gw-conformance-e2e-events.yaml | |
| tar zcf ovn-vpc-nat-gw-conformance-e2e-events.tar.gz ovn-vpc-nat-gw-conformance-e2e-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.vip-e2e.conclusion == 'failure' || steps.vpc-e2e.conclusion == 'failure') | |
| with: | |
| name: ovn-vpc-nat-gw-conformance-e2e-events | |
| path: ovn-vpc-nat-gw-conformance-e2e-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.vip-e2e.conclusion == 'failure' || steps.vpc-e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf ovn-vpc-nat-gw-conformance-e2e-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.vip-e2e.conclusion == 'failure' || steps.vpc-e2e.conclusion == 'failure') | |
| with: | |
| name: ovn-vpc-nat-gw-conformance-e2e-audit-log | |
| path: ovn-vpc-nat-gw-conformance-e2e-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.vip-e2e.conclusion == 'failure' || steps.vpc-e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.vip-e2e.conclusion == 'failure' || steps.vpc-e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz ovn-vpc-nat-gw-conformance-e2e-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.vip-e2e.conclusion == 'failure' || steps.vpc-e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: ovn-vpc-nat-gw-conformance-e2e-ko-log | |
| path: ovn-vpc-nat-gw-conformance-e2e-ko-log.tar.gz | |
| kube-ovn-ipsec-e2e: | |
| name: OVN IPSEC E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'kube-ovn-ipsec-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download kube-ovn image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load images | |
| run: docker load -i kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install-ovn-ipsec | |
| - name: Run Ovn IPSEC E2E | |
| id: kube-ovn-ipsec-e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| run: make kube-ovn-ipsec-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-ipsec-e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > kube-ovn-ipsec-e2e-events.yaml | |
| tar zcf kube-ovn-ipsec-e2e-events.tar.gz kube-ovn-ipsec-e2e-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-ipsec-e2e.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-ipsec-e2e-events | |
| path: kube-ovn-ipsec-e2e-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-ipsec-e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf kube-ovn-ipsec-e2e-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-ipsec-e2e.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-ipsec-e2e-audit-log | |
| path: kube-ovn-ipsec-e2e-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-ipsec-e2e.conclusion == 'failure')) }} | |
| env: | |
| IGNORABLE_PODS: app=kube-ovn-pinger | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-ipsec-e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz kube-ovn-ipsec-e2e-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-ipsec-e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-ipsec-e2e-ko-log | |
| path: kube-ovn-ipsec-e2e-ko-log.tar.gz | |
| kube-ovn-ipsec-cert-mgr-e2e: | |
| name: OVN IPSEC E2E CERT MANAGER | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'kube-ovn-ipsec-cert-mgr-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download kube-ovn image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load images | |
| run: docker load -i kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install-ovn-ipsec-cert-manager | |
| - name: Run Ovn IPSEC cert-manager E2E | |
| id: kube-ovn-ipsec-cert-mgr-e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| run: make kube-ovn-ipsec-cert-mgr-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-ipsec-cert-mgr-e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > kube-ovn-ipsec-cert-mgr-e2e-events.yaml | |
| tar zcf kube-ovn-ipsec-cert-mgr-e2e-events.tar.gz kube-ovn-ipsec-cert-mgr-e2e-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-ipsec-cert-mgr-e2e.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-ipsec-cert-mgr-e2e-events | |
| path: kube-ovn-ipsec-cert-mgr-e2e-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-ipsec-cert-mgr-e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf kube-ovn-ipsec-cert-mgr-e2e-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-ipsec-cert-mgr-e2e.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-ipsec-cert-mgr-e2e-audit-log | |
| path: kube-ovn-ipsec-cert-mgr-e2e-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-ipsec-cert-mgr-e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-ipsec-cert-mgr-e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz kube-ovn-ipsec-cert-mgr-e2e-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-ipsec-cert-mgr-e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-ipsec-cert-mgr-e2e-ko-log | |
| path: kube-ovn-ipsec-cert-mgr-e2e-ko-log.tar.gz | |
| kube-ovn-connectivity-test: | |
| name: Kube-OVN Connectivity E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'kube-ovn-connectivity-test') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| mode: | |
| - overlay | |
| - underlay | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download kube-ovn image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load images | |
| run: docker load -i kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install-${{ matrix.mode }} | |
| - name: Run E2E | |
| id: e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| run: make kube-ovn-connectivity-e2e | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz kube-ovn-connectivity-e2e-${{ matrix.mode }}-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.e2e.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-connectivity-e2e-${{ matrix.mode }}-ko-log | |
| path: kube-ovn-connectivity-e2e-${{ matrix.mode }}-ko-log.tar.gz | |
| kube-ovn-underlay-metallb-e2e: | |
| name: OVN METALLB E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'kube-ovn-underlay-metallb-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ip-family: | |
| - ipv4 | |
| - ipv6 | |
| - dual | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download kube-ovn image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load images | |
| run: docker load -i kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| n_worker=2 make kind-init-${{ matrix.ip-family }} | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install-metallb-pool-from-underlay-${{ matrix.ip-family }} | |
| - name: Run Ovn Metallb and Kube-OVN Combine E2E | |
| id: kube-ovn-underlay-metallb-e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| E2E_IP_FAMILY: ${{ matrix.ip-family }} | |
| run: make kube-ovn-underlay-metallb-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-underlay-metallb-e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > kube-ovn-underlay-metallb-${{ matrix.ip-family }}-e2e-events.yaml | |
| tar zcf kube-ovn-underlay-metallb-${{ matrix.ip-family }}-e2e-events.tar.gz kube-ovn-underlay-metallb-${{ matrix.ip-family }}-e2e-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-underlay-metallb-e2e.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-underlay-metallb-${{ matrix.ip-family }}-e2e-events | |
| path: kube-ovn-underlay-metallb-${{ matrix.ip-family }}-e2e-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-underlay-metallb-e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf kube-ovn-underlay-metallb-${{ matrix.ip-family }}-e2e-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-underlay-metallb-e2e.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-underlay-metallb-${{ matrix.ip-family }}-e2e-audit-log | |
| path: kube-ovn-underlay-metallb-${{ matrix.ip-family }}-e2e-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-underlay-metallb-e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-underlay-metallb-e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz kube-ovn-underlay-metallb-${{ matrix.ip-family }}-e2e-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.kube-ovn-underlay-metallb-e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: kube-ovn-underlay-metallb-${{ matrix.ip-family }}-e2e-ko-log | |
| path: kube-ovn-underlay-metallb-${{ matrix.ip-family }}-e2e-ko-log.tar.gz | |
| router-lb-rule-e2e: | |
| name: Router LB Rule E2E | |
| if: contains(fromJSON(needs.e2e-selection.outputs.executionJobIds), 'router-lb-rule-e2e') | |
| needs: | |
| - e2e-selection | |
| - build-kube-ovn | |
| - build-e2e-binaries | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Create the default branch directory | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| run: mkdir -p test/e2e/source | |
| - name: Check out the default branch | |
| if: (github.base_ref || github.ref_name) != github.event.repository.default_branch | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| persist-credentials: false | |
| fetch-depth: 1 | |
| path: test/e2e/source | |
| - name: Export E2E directory | |
| run: | | |
| if [ '${{ github.base_ref || github.ref_name }}' = '${{ github.event.repository.default_branch }}' ]; then | |
| echo "E2E_DIR=." >> "$GITHUB_ENV" | |
| else | |
| echo "E2E_DIR=test/e2e/source" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/setup-go@v7 | |
| id: setup-go | |
| with: | |
| go-version-file: ${{ env.E2E_DIR }}/go.mod | |
| check-latest: true | |
| cache: false | |
| - name: Export Go full version | |
| run: echo "GO_VERSION=${{ steps.setup-go.outputs.go-version }}" >> "$GITHUB_ENV" | |
| - name: Go cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}-${{ hashFiles(format('{0}/**/go.sum', env.E2E_DIR)) }} | |
| restore-keys: | | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.ref_name }}- | |
| ${{ runner.os }}-e2e-go-${{ env.GO_VERSION }}-x86-${{ github.base_ref }}- | |
| - name: Install kind | |
| uses: helm/kind-action@v1.14.0 | |
| with: | |
| version: ${{ env.KIND_VERSION }} | |
| install_only: true | |
| - name: Download kube-ovn image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Load images | |
| run: docker load -i kube-ovn.tar | |
| - name: Download private Kind node image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kind-node-v1.36.1 | |
| - name: Load private Kind node image | |
| run: docker load --input kind-node-v1.36.1.tar | |
| - name: Create kind cluster | |
| run: | | |
| pipx install jinjanator | |
| make kind-init | |
| - name: Install Kube-OVN | |
| id: install | |
| run: make kind-install | |
| - name: Run Router LB Rule E2E | |
| id: rlr-e2e | |
| working-directory: ${{ env.E2E_DIR }} | |
| env: | |
| E2E_BRANCH: ${{ github.base_ref || github.ref_name }} | |
| run: make kube-ovn-rlr-e2e | |
| - name: Collect k8s events | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.rlr-e2e.conclusion == 'failure') | |
| run: | | |
| kubectl get events -A -o yaml > router-lb-rule-e2e-events.yaml | |
| tar zcf router-lb-rule-e2e-events.tar.gz router-lb-rule-e2e-events.yaml | |
| - name: Upload k8s events | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.rlr-e2e.conclusion == 'failure') | |
| with: | |
| name: router-lb-rule-e2e-events | |
| path: router-lb-rule-e2e-events.tar.gz | |
| - name: Collect apiserver audit logs | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.rlr-e2e.conclusion == 'failure') | |
| run: | | |
| docker cp kube-ovn-control-plane:/var/log/kubernetes/kube-apiserver-audit.log . | |
| tar zcf router-lb-rule-e2e-audit-log.tar.gz kube-apiserver-audit.log | |
| - name: Upload apiserver audit logs | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.rlr-e2e.conclusion == 'failure') | |
| with: | |
| name: router-lb-rule-e2e-audit-log | |
| path: router-lb-rule-e2e-audit-log.tar.gz | |
| - name: Check kube ovn pod restarts | |
| id: check-restarts | |
| if: ${{ success() || (failure() && (steps.install.conclusion == 'failure' || steps.rlr-e2e.conclusion == 'failure')) }} | |
| run: make check-kube-ovn-pod-restarts | |
| - name: kubectl ko log | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.rlr-e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| run: | | |
| make kubectl-ko-log | |
| mv kubectl-ko-log.tar.gz router-lb-rule-e2e-ko-log.tar.gz | |
| - name: upload kubectl ko log | |
| uses: actions/upload-artifact@v7 | |
| if: failure() && (steps.install.conclusion == 'failure' || steps.rlr-e2e.conclusion == 'failure' || steps.check-restarts.conclusion == 'failure') | |
| with: | |
| name: router-lb-rule-e2e-ko-log | |
| path: router-lb-rule-e2e-ko-log.tar.gz | |
| e2e-executor-result: | |
| name: x86 E2E Selected Result | |
| if: always() && github.event_name != 'pull_request' | |
| permissions: {} | |
| needs: | |
| - e2e-selection | |
| - e2e-control-validation | |
| - bgp-speaker-e2e | |
| - chart-test | |
| - cilium-chaining-e2e | |
| - cyclonus-netpol-e2e | |
| - installation-compatibility-test | |
| - iptables-vpc-nat-gw-conformance-e2e | |
| - k8s-conformance-e2e | |
| - k8s-netpol-e2e | |
| - kube-ovn-anp-domain-e2e | |
| - kube-ovn-cnp-domain-e2e | |
| - kube-ovn-conformance-e2e | |
| - kube-ovn-connectivity-test | |
| - kube-ovn-ha-e2e | |
| - kube-ovn-hosted-ovn-central-e2e | |
| - kube-ovn-ic-conformance-e2e | |
| - kube-ovn-ipsec-cert-mgr-e2e | |
| - kube-ovn-ipsec-e2e | |
| - kube-ovn-submariner-conformance-e2e | |
| - kube-ovn-underlay-metallb-e2e | |
| - lb-svc-e2e | |
| - multus-conformance-e2e | |
| - no-np-test | |
| - no-ovn-lb-test | |
| - non-primary-cni-e2e | |
| - ovn-vpc-nat-gw-conformance-e2e | |
| - router-lb-rule-e2e | |
| - talos-installation-test | |
| - underlay-logical-gateway-installation-test | |
| - vpc-egress-gateway-e2e | |
| - webhook-e2e | |
| runs-on: ubuntu-24.04 | |
| env: | |
| NEEDS_JSON: ${{ toJSON(needs) }} | |
| SELECTED_JOB_IDS: ${{ needs.e2e-selection.outputs.executionJobIds }} | |
| steps: | |
| - name: Verify every selected test Job succeeded | |
| run: | | |
| python3 - <<'PY' | |
| import json | |
| import os | |
| needs = json.loads(os.environ["NEEDS_JSON"]) | |
| selectedJobIds = json.loads(os.environ["SELECTED_JOB_IDS"]) | |
| requiredJobIds = ["e2e-selection", "e2e-control-validation"] + selectedJobIds | |
| incomplete = { | |
| jobId: needs.get(jobId, {}).get("result", "missing") | |
| for jobId in requiredJobIds | |
| if needs.get(jobId, {}).get("result") != "success" | |
| } | |
| if incomplete: | |
| raise SystemExit(f"required x86 E2E Jobs did not succeed: {incomplete}") | |
| print(f"Verified {len(requiredJobIds)} required x86 E2E Jobs.") | |
| PY | |
| push: | |
| name: Push Images | |
| needs: | |
| - e2e-executor-result | |
| if: github.event_name == 'push' && needs.e2e-executor-result.result == 'success' | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: jlumbroso/free-disk-space@v1.3.1 | |
| with: | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: false | |
| large-packages: false | |
| tool-cache: false | |
| swap-storage: false | |
| - uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ env.EXECUTION_SHA }} | |
| persist-credentials: false | |
| - name: Download kube-ovn image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: kube-ovn | |
| - name: Download kube-ovn-dpdk image | |
| uses: actions/download-artifact@v8 | |
| if: github.event_name != 'pull_request' | |
| with: | |
| name: kube-ovn-dpdk | |
| - name: Download vpc-nat-gateway image | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: vpc-nat-gateway | |
| - name: Load image | |
| run: | | |
| docker load --input kube-ovn.tar | |
| docker load --input vpc-nat-gateway.tar | |
| if [ '${{ github.event_name }}' != 'pull_request' ]; then | |
| docker load --input kube-ovn-dpdk.tar | |
| fi | |
| - name: Security Scan | |
| env: | |
| TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2 | |
| run: | | |
| sudo apt-get install wget apt-transport-https gnupg lsb-release | |
| wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add - | |
| echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list | |
| sudo apt-get update | |
| sudo apt-get install trivy | |
| make scan | |
| - name: Push | |
| if: github.ref_name == github.event.repository.default_branch || startsWith(github.ref_name, 'release-') | |
| env: | |
| DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} | |
| DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} | |
| COMMIT: ${{ github.sha }} | |
| run: | | |
| cat VERSION | |
| TAG=$(cat VERSION) | |
| echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin | |
| docker tag kubeovn/kube-ovn:$TAG kubeovn/kube-ovn-dev:$COMMIT-x86 | |
| docker tag kubeovn/kube-ovn:$TAG kubeovn/kube-ovn:$TAG-x86 | |
| docker tag kubeovn/kube-ovn:$TAG-debug kubeovn/kube-ovn:$TAG-debug-x86 | |
| docker tag kubeovn/kube-ovn:$TAG-dpdk kubeovn/kube-ovn:$TAG-dpdk-x86 | |
| docker tag kubeovn/vpc-nat-gateway:$TAG kubeovn/vpc-nat-gateway-dev:$COMMIT-x86 | |
| docker tag kubeovn/vpc-nat-gateway:$TAG kubeovn/vpc-nat-gateway:$TAG-x86 | |
| docker images | |
| docker push kubeovn/kube-ovn:$TAG-x86 | |
| docker push kubeovn/kube-ovn:$TAG-amd64-legacy | |
| docker push kubeovn/kube-ovn-dev:$COMMIT-x86 | |
| docker push kubeovn/kube-ovn:$TAG-debug-x86 | |
| docker push kubeovn/kube-ovn:$TAG-dpdk-x86 | |
| docker push kubeovn/vpc-nat-gateway:$TAG-x86 | |
| docker push kubeovn/vpc-nat-gateway-dev:$COMMIT-x86 |