Testing a Kubernetes CLI tool

Table of Contents

I'm testing a clk extension that manages Kubernetes clusters via Kind. The integration tests need to create a real Kind cluster, which means Docker must be running inside the CI container. daggerlib's Docker-in-Docker support handles the daemon lifecycle — cgroup v2 setup, tmpfs mounts, dockerd startup — so I can focus on my tests.

The real test flow (from the project's Earthfile) installs Kind, creates a cluster, deploys an app, and runs assertions. Here I show how daggerlib provides the DinD foundation those tests build on.

This example calls daggerlib functions directly — useful for exploring what a function does before wrapping it in your own module.

First I set up my Dagger project and install daggerlib:

dagger init --sdk=python
dagger install github.com/Konubinix/daggerlib

The following is only for testing purposes — it makes the project use the local daggerlib checkout instead of the published version:

sed -i '/pin/d; s|"github.com/Konubinix/daggerlib@main"|"../.."|; s|"\.\./\.\.",|"../.."|' dagger.json

Then I write my Dagger module. The <<...>> reference below is filled in by the function definition that follows — it shows the function code and its output:

from typing import Annotated

import dagger
from dagger import DefaultPath, dag, function, object_type


@object_type
class ContainerTesting:
    @function
    async def test_kind(self) -> str:
        """Run a mocked Kind workflow inside Docker-in-Docker."""
        return await (
            dag.lib().dind_with_docker(
                cmd="kind() { echo 'Creating cluster...'; echo \"Cluster 'test' created.\"; };"
                " kubectl() { echo 'NAME            STATUS   ROLES           AGE';"
                " echo 'test-node       Ready    control-plane   1m'; };"
                " export -f kind kubectl;"
                " kind create cluster --wait 60s && kubectl get nodes",
            )
            .stdout()
        )

1. Running a command with a live Docker daemon

Having Docker installed isn't enough — I need a running dockerd. The dind-with-docker target starts the daemon with proper cgroup v2 setup, then runs my command. In production I'd run Kind here; for this example I mock the workflow:

@function
async def test_kind(self) -> str:
    """Run a mocked Kind workflow inside Docker-in-Docker."""
    return await (
        dag.lib().dind_with_docker(
            cmd="kind() { echo 'Creating cluster...'; echo \"Cluster 'test' created.\"; };"
            " kubectl() { echo 'NAME            STATUS   ROLES           AGE';"
            " echo 'test-node       Ready    control-plane   1m'; };"
            " export -f kind kubectl;"
            " kind create cluster --wait 60s && kubectl get nodes",
        )
        .stdout()
    )
dagger call test-kind

Author: root

Created: 2026-04-18 Sat 21:16

Validate