These tests run against Headlamp deployed in-cluster, across two
clusters whose kubectl contexts are named test and test2.
Those names are not arbitrary. The specs hardcode them: podsPage.spec.ts
navigates to /c/test/pods, and multiCluster.spec.ts asserts a home page
listing both test and test2. headlamp.spec.ts also asserts on a
headlamp-admin service account and on the headlamp Service, both of which
come from the in-cluster deployment rather than from a dev server.
The setup below mirrors what CI does in .github/workflows/build-container.yml,
which is the reference if anything here drifts.
Install the test dependencies:
cd e2e-tests
npm ci
npx playwright installCreate the two clusters and rename their contexts to what the specs expect:
kind create cluster --name test
kubectl config rename-context kind-test test
kind create cluster --name test2
kubectl config rename-context kind-test2 test2Give each cluster a headlamp-admin service account with cluster-admin:
for ctx in test test2; do
kubectl --context="$ctx" -n kube-system create serviceaccount headlamp-admin
kubectl --context="$ctx" create clusterrolebinding headlamp-admin \
--serviceaccount=kube-system:headlamp-admin --clusterrole=cluster-admin
doneBuild the images and load them into the test cluster. The plugins image is
used as an init container by the manifest below:
# from the repository root
DOCKER_IMAGE_VERSION=latest make image
DOCKER_IMAGE_VERSION=latest DOCKER_PLUGINS_IMAGE_NAME=headlamp-plugins-test make build-plugins-container
kind load docker-image ghcr.io/headlamp-k8s/headlamp:latest --name test
kind load docker-image ghcr.io/headlamp-k8s/headlamp-plugins-test:latest --name testDeploy Headlamp into the test cluster. The manifest is templated, so the
cluster addresses and CA data have to be substituted in:
kubectl config use-context test
export TEST_CA_DATA=$(kubectl config view --raw --minify -o jsonpath='{.clusters[0].cluster.certificate-authority-data}')
export TEST_SERVER="https://$(kubectl get nodes -o=jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}'):6443"
kubectl config use-context test2
export TEST2_CA_DATA=$(kubectl config view --raw --minify -o jsonpath='{.clusters[0].cluster.certificate-authority-data}')
export TEST2_SERVER="https://$(kubectl get nodes -o=jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}'):6443"
kubectl config use-context test
envsubst < e2e-tests/kubernetes-headlamp-ci.yaml | kubectl --context=test apply -f -
kubectl wait deployment -n kube-system headlamp --for condition=Available=True --timeout=180sFinally, export the URL and the tokens the specs read:
export HEADLAMP_TEST_URL="http://<address of the headlamp Service>"
export HEADLAMP_TEST_TOKEN=$(kubectl --context=test create token headlamp-admin --duration 24h -n kube-system)
export HEADLAMP_TEST2_TOKEN=$(kubectl --context=test2 create token headlamp-admin --duration 24h -n kube-system)CI reaches the Service on its NodePort, at
http://<node InternalIP>:<nodePort>. That address is reachable from the host
on Linux, but not on every platform; if it is not reachable on yours, any means
of exposing the Service will do, as long as HEADLAMP_TEST_URL points at it.
HEADLAMP_TEST_URL defaults to http://localhost:3000 if unset
(playwright.config.ts), so an unset variable shows up as connection errors
rather than as an obvious configuration problem.
dynamicCluster.spec.ts reads your kubeconfig with kubectl config view, which
redacts embedded certificate-authority-data and the client certificate fields,
and then reads the referenced files from disk. If those fields are embedded
rather than file paths, six tests in that file fail with ENOENT.
CI works around this by rewriting the kubeconfig so the certificates live in files. If you hit those failures, do the same, and note that the paths must be absolute, because the test resolves them relative to its own working directory:
mkdir -p ~/headlamp-e2e-certs
kubectl config view --raw --minify --context=test -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' | base64 --decode > ~/headlamp-e2e-certs/ca.crt
kubectl config set-cluster kind-test --certificate-authority="$HOME/headlamp-e2e-certs/ca.crt" --embed-certs=false
kubectl config unset clusters.kind-test.certificate-authority-dataDo the same for the client-certificate-data and client-key-data fields on
the user entry. To update the second cluster, use --context=test2 and the
kind-test2 cluster entry.
tests/incluster-api.spec.ts tests a separate Headlamp deployment running in
in-cluster mode. CI runs it in a dedicated step after deploying
kubernetes-headlamp-incluster-ci.yaml to the test2 cluster. To reproduce
that setup locally:
kubectl config use-context test2
kubectl create serviceaccount headlamp --namespace kube-system
kubectl create clusterrolebinding headlamp \
--serviceaccount=kube-system:headlamp --clusterrole=cluster-admin
kubectl apply -f e2e-tests/kubernetes-headlamp-incluster-ci.yaml
kubectl wait deployment -n kube-system headlamp \
--for condition=Available=True --timeout=120s
kubectl port-forward -n kube-system service/headlamp 8080:80Leave the port-forward running, then use a second terminal to set the URL and service account token before running the spec:
export HEADLAMP_TEST_URL=http://localhost:8080
export HEADLAMP_SA_TOKEN=$(kubectl create token headlamp --duration=1h -n kube-system)
cd e2e-tests
npx playwright test tests/incluster-api.spec.tstests/clusterInventory.spec.ts requires Headlamp to be configured with a
working cluster inventory source. It is skipped unless explicitly enabled and
is not run in CI:
export HEADLAMP_CLUSTER_INVENTORY_E2E=true
# Optional. This defaults to "headlamp".
export HEADLAMP_TEST_BACKEND_TOKEN=...
cd e2e-tests
npx playwright test tests/clusterInventory.spec.tsIMPORTANT: Make sure that the following npx commands are run in the same terminal session as the environment variables were set.
-
from the terminal navigate to the e2e-tests directory within the headlamp repository
cd headlamp/e2e-tests -
run the following command
npx playwright testYou can run a single test with the grep flag:
-
from the terminal navigate to the e2e-tests directory within the headlamp repository
cd headlamp/e2e-tests -
run the following command
npx playwright test -g "404 page is present"- You can run a single test in a real browser with the
--headedflag, this can be useful if you want to troubleshoot errors with a visual of the test.
npx playwright test -g "404 page is present" --headed-
The Playwright UI mode is similar to the VSCode extension where you are able to see the tests run in real-time and can be a great way to troubleshoot issues with the tests. (for more information see: https://playwright.dev/docs/test-ui-mode)
-
You can run the tests in UI mode by adding the
--uiflag to the command.- command
npx playwright test --ui
- command
-
This will open a browser window that will show the test running in real-time, this can be ran as a substitute or in pair with the VS code extension.
-
If you wish to see the test run in a real browser, you can add the
--headedflag to the command. -
You can also modify the playwright.config.ts file to change the browser that is used for the tests. You must be sure not to add this change to the repository when you push.
- within the playwright.config.ts file locate the
const config: PlaywrightTestConfigobject. within the object, modify the use object to contain a field for headless set to false ex.use: { ..., headless: false }property to run the tests in a real browser.
- within the playwright.config.ts file locate the
- You can modify the playwright.config.ts file to slow down the tests. You must be sure not to add this change to the repository when you push.
- within the playwright.config.ts file locate the
const config: PlaywrightTestConfigobject. within the object, modify the use object to contain a field forlaunchOptions: { slowMo: }set to a number of milliseconds ex.use: { ..., launchOptions: { slowMo: 1000 }property to slow down the tests to take 1 second between each step.
- within the playwright.config.ts file locate the
Note: this section predates the two-cluster kind setup described above and has not been updated for it. It still refers to a single minikube cluster and to
kubernetes-headlamp-ci.yml, which is nowkubernetes-headlamp-ci.yaml.
- Open a new Ubuntu terminal window.
- Verify the installation of Azure CLI on your machine by typing:
az version - Log into your Azure account with the following command:
az login
- Verify the installation of Azure CLI on your machine by typing:
-
Open another terminal window.
- Before running the script, replace
VM_NAMEandRESOURCE_GROUPwith your specific values. You can find the default script template or use a GitHub gist link.
- Before running the script, replace
-
Modify and run the script:
- Replace the placeholders in the script with actual values for
VM_NAMEandRESOURCE_GROUP. - Execute the script using the following command:
curl -sSfL https://headlamp.dev/blog/2024/04/user-added-cluster-support-in-shared-headlamp-deployments/create-azurevm.sh | bash
- Replace the placeholders in the script with actual values for
- Use a web browser to access the Azure portal.
- Navigate to the resource page and search for the
VM_NAMEyou used in the script to check if the VM was successfully created.
- Navigate to the resource page and search for the
-
SSH into the newly created VM.
- Use this command to connect:
ssh your-username@your-vm-ip
- Use this command to connect:
-
Install essential tools on the VM:
- Install Docker:
You can find more details on the official Docker installation guide.
sudo apt install docker.io - Install Git:
sudo apt install git - Clone the Headlamp repository:
git clone https://github.com/kubernetes-sigs/headlamp
- Install Docker:
-
Navigate to the workflow file and build the Headlamp image:
- Inside
.github/workflows/build-container.ymlis the source line we need, locate the step for building the image and run in your terminal:DOCKER_IMAGE_VERSION=latest npm run image:build
- Inside
-
Tag and push the Docker image to a registry (e.g., ttl.sh):
- Tag your Docker image and push it using ttl.sh:
docker tag headlamp-k8s/headlamp ttl.sh/headlamp-k8s/headlamp docker push ttl.sh/headlamp-k8s/headlamp
- Tag your Docker image and push it using ttl.sh:
-
Pull the Docker image to your local machine:
- After pushing, exit back to your local machine and pull the image:
docker pull ttl.sh/headlamp-k8s/headlamp
- After pushing, exit back to your local machine and pull the image:
-
Ensure Minikube is running on your local machine.
-
Update the Kubernetes Headlamp CI configuration:
- Navigate to
e2e-tests/kubernetes-headlamp-ci.yml. - Change the
imagefield underspec.containersto match the Docker image you pulled:image: ttl.sh/headlamp-k8s/headlamp
- Navigate to
-
Deploy to the cluster and run end-to-end tests:
- Follow the steps outlined in
Deploy to clusterandRun e2e testssections to execute these actions on your local machine.
- Follow the steps outlined in