K8s Integration Tests
Smoke tests that verify tools container images work in a real Kubernetes cluster. Each test creates short-lived pods, checks expected behavior, and cleans up. Tests run automatically on every MR via the Konflux K8s test pipeline.
Test Runner
Tests are executed by ci/run_tests_k8s.sh. For each component it:
- Reads
{component}/tests-k8s.yml - Parses each test entry (YAML -> JSON via Python)
- Runs the
commandblock withkubectlwired to the target cluster - Cleans up labeled resources (
hum-k8s-test=<run-id>) after each test
Running Locally
Test against a local cluster (kind, minikube, or remote):
# Single component with a published image
IMAGE_URL=quay.io/hummingbird-ci/gitlab-ci:latest \
IMAGE_NAME=gitlab-ci--tools \
ci/run_tests_k8s.sh --context kind-kind gitlab-ci--tools
# Single component with a locally-built image
podman build -t localhost/hummingbird-dashboard:dev hummingbird-dashboard/
kind load docker-image localhost/hummingbird-dashboard:dev
IMAGE_URL=localhost/hummingbird-dashboard:dev \
IMAGE_NAME=hummingbird-dashboard--tools \
ci/run_tests_k8s.sh --context kind-kind hummingbird-dashboard--tools
CI Integration
In Konflux, the tools-k8s-test
IntegrationTestScenario
triggers on every MR. The pipeline:
- Checks whether
tests-k8s.ymlexists for the changed component - Provisions an ephemeral EaaS namespace
- Runs
ci/run_tests_k8s.shwith the built image
Components without tests-k8s.yml skip the test (the pipeline exits early
after the check step).
When an MR touches multiple components in one PR-group snapshot, Konflux
runs a single group PipelineRun instead of one per component, invoking the
script once with --group-component-name (repeated) and per-component
IMAGE_URL_<COMPONENT> env vars instead of the single-component
IMAGE_URL/IMAGE_NAME pair. --group-component-name is handled
identically to --component-name.
Adding Tests for a New Component
-
Create
{component}/tests-k8s.ymlwith one or more named tests:--- smoke-test: command: | name="${TEST_GROUP}-smoke-${TEST_RUN_ID}" kubectl run "${name}" --image="${TEST_IMAGE:?}" --restart=Never \ --labels="${TEST_RUN_LABEL}" \ --command -- echo "hello" kubectl wait --for=jsonpath='{.status.phase}'=Succeeded \ "pod/${name}" --timeout=120s || test_fail "Pod did not succeed" kubectl logs "${name}" -
Use
${TEST_IMAGE}for the image under test,${TEST_RUN_ID}and${TEST_RUN_LABEL}for unique naming and cleanup. -
Call
test_fail "message"to fail a test with a clear message. -
Keep tests fast (under 2 minutes) — these are smoke tests, not integration suites.
Common pitfalls
- All lines in
command: |block scalars must be indented relative to thecommandkey. Unindented lines break YAML parsing. - Use
command -vinstead ofwhichto check for commands —whichis not available in all container images. - For multi-statement Python one-liners, use semicolons on a single line:
python3 -c 'import foo; import bar; print("ok")'
Debugging Failures
See the EaaS and Debugging guide for accessing ephemeral namespaces and using Kubearchive for historical PipelineRun data.