Skip to content

Conformance MCS API (ci-mcs-api) #420

Conformance MCS API (ci-mcs-api)

Conformance MCS API (ci-mcs-api) #420

name: Conformance MCS API (ci-mcs-api)
# Any change in triggers needs to be reflected in the concurrency group.
on:
workflow_dispatch:
inputs:
PR-number:
description: "Pull request number."
required: true
context-ref:
description: "Context in which the workflow runs. If PR is from a fork, will be the PR target branch (general case). If PR is NOT from a fork, will be the PR branch itself (this allows committers to test changes to workflows directly from PRs)."
required: true
SHA:
description: "SHA under test (head of the PR branch)."
required: true
base-SHA:
description: "SHA of the base branch (target branch of the PR)."
required: false
extra-args:
description: "[JSON object] Arbitrary arguments passed from the trigger comment via regex capture group. Parse with 'fromJson(inputs.extra-args).argName' in workflow."
required: false
default: "{}"
schedule:
- cron: '0 5/8 * * *'
# By specifying the access of one of the scopes, all of those that are not
# specified are set to 'none'.
permissions:
# To read actions state with cilium/workflow-telemetry-action
actions: read
# To be able to access the repository with actions/checkout
contents: read
# To allow retrieving information from the PR API
pull-requests: read
# To be able to set commit status
statuses: write
concurrency:
# Structure:
# - Workflow name
# - Event type
# - A unique identifier depending on event type:
# - schedule: SHA
# - workflow_dispatch: PR number
#
# This structure ensures a unique concurrency group name is generated for each
# type of testing, such that re-runs will cancel the previous run.
group: |
${{ github.workflow }}
${{ github.event_name }}
${{
(github.event_name == 'push' && github.sha) ||
(github.event_name == 'schedule' && github.sha) ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.PR-number)
}}
cancel-in-progress: true
env:
clusterName1: cluster1-${{ github.run_id }}
clusterName2: cluster2-${{ github.run_id }}
contextName1: kind-cluster1-${{ github.run_id }}
contextName2: kind-cluster2-${{ github.run_id }}
timeout: 5m
jobs:
echo-inputs:
if: ${{ github.event_name == 'workflow_dispatch' }}
name: Echo Workflow Dispatch Inputs
runs-on: ${{ vars.UBUNTU_2404_2CPU_1GB || 'ubuntu-24.04' }}
steps:
- name: Echo Workflow Dispatch Inputs
run: |
echo '${{ tojson(inputs) }}'
commit-status-start:
name: Commit Status Start
runs-on: ${{ vars.UBUNTU_2404_2CPU_1GB || 'ubuntu-24.04' }}
steps:
- name: Set initial commit status
uses: cilium/actions/set-commit-status@fe0702f5df0d8e44d48f1baa226c023b73ff6b5e # main
with:
sha: ${{ inputs.SHA || github.sha }}
wait-for-images:
name: Wait for images
runs-on: ${{ vars.UBUNTU_2404_2CPU_1GB || 'ubuntu-24.04' }}
timeout-minutes: 30
steps:
- name: Checkout context ref (trusted)
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ inputs.context-ref || github.sha }}
persist-credentials: false
- name: Wait for images
uses: ./.github/actions/wait-for-images
with:
SHA: ${{ inputs.SHA || github.sha }}
images: cilium-ci operator-generic-ci clustermesh-apiserver-ci cilium-cli-ci
login-host: ${{ vars.DOCKER_READ_HOST }}
login-username: ${{ vars.DOCKER_READ_USERNAME }}
login-password: ${{ secrets.DOCKER_READ_PASSWORD }}
auth-required: ${{ vars.DOCKER_AUTH_REQUIRED }}
mcs-api-conformance-test:
name: MCS API Conformance Test
env:
job_name: "MCS API Conformance Test"
needs: [wait-for-images]
runs-on: ${{ vars.UBUNTU_2404_4CPU_16GB || 'ubuntu-24.04' }}
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
include:
- name: '1'
steps:
- name: Set commit status to pending
uses: cilium/actions/set-commit-status@fe0702f5df0d8e44d48f1baa226c023b73ff6b5e # main
with:
sha: ${{ inputs.SHA || github.sha }}
- name: Collect Workflow Telemetry
uses: cilium/workflow-telemetry-action@b1a318f80a08acede58027afe1455d037379966f # v2.2.0
with:
comment_on_pr: false
- name: Checkout context ref (trusted)
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ inputs.context-ref || github.sha }}
persist-credentials: false
- name: Set Environment Variables
uses: ./.github/actions/set-env-variables
- name: Get Cilium's default values
id: default_vars
uses: ./.github/actions/helm-default
with:
image-tag: ${{ inputs.SHA || github.sha }}
registry_host: ${{ vars.DOCKER_READ_HOST }}
registry_organization: ${{ vars.DOCKER_READ_ORG }}
chart-dir: ./untrusted/install/kubernetes/cilium
image-pull-secret: "cilium-registry"
- name: Set up job variables for GHA environment
id: vars
run: |
echo sha=${{ steps.default_vars.outputs.sha }} >> $GITHUB_OUTPUT
CILIUM_INSTALL_DEFAULTS="${{ steps.default_vars.outputs.cilium_install_defaults }} \
--helm-set=kubeProxyReplacement=true \
--helm-set=clustermesh.useAPIServer=true \
--helm-set=clustermesh.config.enabled=true \
--helm-set=clustermesh.mcsapi.enabled=true \
--helm-set=clustermesh.mcsapi.corednsAutoConfigure.enabled=true \
--helm-set=clustermesh.enableEndpointSliceSynchronization=true \
"
echo cilium_install_defaults=${CILIUM_INSTALL_DEFAULTS} >> $GITHUB_OUTPUT
# Warning: since this is a privileged workflow, subsequent workflow job
# steps must take care not to execute untrusted code.
- name: Checkout pull request branch (NOT TRUSTED)
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ steps.vars.outputs.sha }}
persist-credentials: false
# Required by checkout v7+ to fetch fork PR code; see the NOT TRUSTED warning above.
allow-unsafe-pr-checkout: true
path: untrusted
sparse-checkout: |
install/kubernetes/cilium
- name: Generate Kind configuration files
run: |
PODCIDR=10.242.0.0/16 \
SVCCIDR=10.243.0.0/16 \
IPFAMILY=ipv4 \
KUBEPROXYMODE=none \
envsubst < ./.github/kind-config.yaml.tmpl > ./.github/kind-config-cluster1.yaml
PODCIDR=10.244.0.0/16 \
SVCCIDR=10.245.0.0/16 \
IPFAMILY=ipv4 \
KUBEPROXYMODE=none \
envsubst < ./.github/kind-config.yaml.tmpl > ./.github/kind-config-cluster2.yaml
- name: Create Kind cluster 1
uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0
with:
cluster_name: ${{ env.clusterName1 }}
version: ${{ env.KIND_VERSION }}
node_image: ${{ env.KIND_K8S_IMAGE }}
kubectl_version: ${{ env.KIND_K8S_VERSION }}
config: ./.github/kind-config-cluster1.yaml
wait: 0 # The control-plane never becomes ready, since no CNI is present
- name: Create Kind cluster 2
uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0
with:
cluster_name: ${{ env.clusterName2 }}
version: ${{ env.KIND_VERSION }}
node_image: ${{ env.KIND_K8S_IMAGE }}
kubectl_version: ${{ env.KIND_K8S_VERSION }}
config: ./.github/kind-config-cluster2.yaml
wait: 0 # The control-plane never becomes ready, since no CNI is present
- name: Create imagePullSecrets
if: ${{ vars.DOCKER_AUTH_REQUIRED == 'true' }}
run: |
for context in ${{ env.contextName1 }} ${{ env.contextName2 }}; do
kubectl --context $context create secret docker-registry cilium-registry \
--namespace kube-system \
--docker-server=${{ vars.DOCKER_READ_HOST }} \
--docker-username="${{ vars.DOCKER_READ_USERNAME }}" \
--docker-password="${{ secrets.DOCKER_READ_PASSWORD }}"
done
- name: Install Cilium CLI
uses: cilium/cilium-cli@7ca7fc53c20275f5c10ef5f3557076691fd1d720 # v0.19.7
with:
skip-build: ${{ env.CILIUM_CLI_SKIP_BUILD }}
image-repo: ${{ env.CILIUM_CLI_IMAGE_REPO }}
image-tag: ${{ steps.vars.outputs.sha }}
repository: ${{ env.CILIUM_CLI_RELEASE_REPO }}
release-version: ${{ env.CILIUM_CLI_VERSION }}
- name: Install Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
# renovate: datasource=golang-version depName=go
go-version: 1.26.5
- name: Install go-junit-report
timeout-minutes: 15
run: |
# renovate: datasource=github-releases depName=cilium/go-junit-report/v2/cmd/go-junit-report
go install github.com/cilium/go-junit-report/v2/cmd/go-junit-report@4cdc5c96cb4e406fccf943536b5bfcae7a0fb826 # v2.3.1
- name: Install Cilium in cluster1
id: install-cilium
run: |
# Let the NodePort to be selected randomly, to prevent the risk of conflicts.
cilium --context ${{ env.contextName1 }} install \
${{ steps.vars.outputs.cilium_install_defaults }} \
--helm-set cluster.name=${{ env.clusterName1 }} \
--helm-set cluster.id=1 \
--helm-set clustermesh.apiserver.service.nodePort=0
- name: Copy the Cilium CA secret to cluster2, as they must match
run: |
kubectl --context ${{ env.contextName1 }} get secret -n kube-system cilium-ca -o yaml |
kubectl --context ${{ env.contextName2 }} create -f -
- name: Install Cilium in cluster2
run: |
# Let the NodePort to be selected randomly, to prevent the risk of conflicts.
cilium --context ${{ env.contextName2 }} install \
${{ steps.vars.outputs.cilium_install_defaults }} \
--helm-set cluster.name=${{ env.clusterName2 }} \
--helm-set cluster.id=2 \
--helm-set clustermesh.apiserver.service.nodePort=0
- name: Wait for Cilium status to be ready
run: |
cilium --context ${{ env.contextName1 }} status --wait --interactive=false
cilium --context ${{ env.contextName2 }} status --wait --interactive=false
cilium --context ${{ env.contextName1 }} clustermesh status --wait
cilium --context ${{ env.contextName2 }} clustermesh status --wait
- name: Connect clusters
run: |
cilium --context ${{ env.contextName1 }} clustermesh connect --destination-context ${{ env.contextName2 }}
- name: Wait for cluster mesh status to be ready
run: |
cilium --context ${{ env.contextName1 }} status --wait --interactive=false
cilium --context ${{ env.contextName2 }} status --wait --interactive=false
cilium --context ${{ env.contextName1 }} clustermesh status --wait
cilium --context ${{ env.contextName2 }} clustermesh status --wait
- name: Run MCS API conformance test
id: mcs-api-conformance
timeout-minutes: 30
run: |
mkdir -p cilium-junits
LOG_CODEOWNERS=1 \
JUNIT_PATH="cilium-junits/${{ env.job_name }} (${{ join(matrix.*, ', ') }}) - mcs-api-conformance.xml" \
CODEOWNERS_PATH="${CILIUM_CLI_CODE_OWNERS_PATHS}" \
MCS_API_TEST_FLAGS="-contexts ${{ env.contextName1 }},${{ env.contextName2 }}" \
make mcs-api-conformance
- name: Run basic CLI tests (${{ join(matrix.*, ', ') }})
shell: bash
id: run-tests
run: |
mkdir -p cilium-junits
cilium connectivity test --include-unsafe-tests --collect-sysdump-on-failure \
--context=${{ env.contextName1 }} --multi-cluster=${{ env.contextName2 }} \
--sysdump-hubble-flows-count=1000000 --sysdump-hubble-flows-timeout=5m \
--sysdump-output-filename "cilium-sysdump-${{ join(matrix.*, '-') }}-<ts>" \
--junit-file "cilium-junits/${{ env.job_name }} (${{ join(matrix.*, ', ') }}).xml" \
--junit-property github_job_step="Run tests (${{ join(matrix.*, ', ') }})" \
--log-code-owners --code-owners=${CILIUM_CLI_CODE_OWNERS_PATHS} \
--exclude-code-owners=${CILIUM_CLI_EXCLUDE_OWNERS} \
--test 'allow-all-except-world,encryption,packet-drops'
- name: Post-test information gathering
if: ${{ !success() && steps.install-cilium.outcome != 'skipped' }}
run: |
cilium --context ${{ env.contextName1 }} status
cilium --context ${{ env.contextName1 }} clustermesh status
cilium --context ${{ env.contextName2 }} status
cilium --context ${{ env.contextName2 }} clustermesh status
kubectl config use-context ${{ env.contextName1 }}
kubectl get pods --all-namespaces -o wide
cilium sysdump --output-filename cilium-sysdump-context1-final-${{ matrix.name }}
kubectl config use-context ${{ env.contextName2 }}
kubectl get pods --all-namespaces -o wide
cilium sysdump --output-filename cilium-sysdump-context2-final-${{ matrix.name }}
shell: bash {0} # Disable default fail-fast behaviour so that all commands run independently
- name: Upload the HTML report artifact
if: ${{ always() && steps.mcs-api-conformance.outcome != 'skipped' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: report-${{ matrix.name }}.html
path: pkg/clustermesh/mcsapi/conformance/report.html
archive: false
retention-days: 5
if-no-files-found: ignore
- name: Upload the yaml report artifact
if: ${{ always() && steps.mcs-api-conformance.outcome != 'skipped' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: report-${{ matrix.name }}.yaml
path: pkg/clustermesh/mcsapi/conformance/report.yaml
archive: false
retention-days: 5
if-no-files-found: ignore
- name: Features tested on cluster 1
uses: ./.github/actions/feature-status
with:
cilium-cli: "cilium --context ${{ env.contextName1 }}"
title: "Summary of all features tested on cluster 1"
json-filename: "${{ env.job_name }} (${{ join(matrix.*, ', ') }}) - cluster 1"
- name: Features tested on cluster 2
uses: ./.github/actions/feature-status
with:
cilium-cli: "cilium --context ${{ env.contextName2 }}"
title: "Summary of all features tested on cluster 2"
json-filename: "${{ env.job_name }} (${{ join(matrix.*, ', ') }}) - cluster 2"
- name: Run common post steps
if: ${{ always() && steps.install-cilium.outcome != 'skipped' }}
uses: ./.github/actions/post-logic
with:
artifacts_suffix: "${{ env.job_name }} (${{ join(matrix.*, ', ') }})"
job_status: "${{ job.status }}"
capture_features_tested: false
merge-upload-and-status:
name: Merge Upload and Status
if: ${{ always() }}
needs: mcs-api-conformance-test
uses: ./.github/workflows/common-post-jobs.yaml
secrets: inherit
with:
context-ref: ${{ inputs.context-ref || github.sha }}
sha: ${{ inputs.SHA || github.sha }}
success: ${{ needs.mcs-api-conformance-test.result == 'success' }}