kindkit

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 15, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

README

kindkit

Go Reference CI

Go library for managing Kind clusters in test workflows.

Why kindkit?

Go test suites that run against Kind clusters often shell out to the kind CLI for cluster lifecycle, making failure handling, cleanup, and debugging harder to keep consistent.

Even when using Kind's Go packages directly, projects tend to reimplement the same helpers: readiness checks, kubeconfig handling, reuse logic, and teardown.

kindkit provides a small, focused API for these lifecycle operations, so you can manage clusters directly from Go test code without rebuilding the same plumbing each time.

Prerequisites

The kind CLI is not required. kindkit manages clusters through Kind's Go packages.

Install

go get github.com/IrvingMg/kindkit

Quick example

Create a Kind cluster, get a REST config, and load images — all from Go:

ctx := context.Background()

cluster, err := kindkit.Create(ctx, "my-test-cluster",
    kindkit.WithWaitForReady(3*time.Minute),
)
if err != nil {
    // Partial failure: creation failed but a cluster was returned.
    // Export logs for debugging, then clean up.
    if cluster != nil {
        _ = cluster.ExportLogs(ctx, "./test-logs")
        _ = cluster.Delete(ctx)
    }
    log.Fatal(err)
}
defer cluster.Delete(ctx)

restCfg, err := cluster.RESTConfig()
if err != nil {
    log.Fatal(err)
}

if err := cluster.LoadImages(ctx, "my-app:latest"); err != nil {
    log.Fatal(err)
}

API

The public API covers cluster creation, configuration access, and common operations:

Function Description
Create(ctx, name, opts...) Create a cluster. Returns both *Cluster and error on partial failure.
CreateOrReuse(ctx, name, opts...) Reuse an existing cluster if reachable, otherwise create a new one.
Cluster.Delete(ctx) Delete the cluster. Idempotent.
Cluster.RESTConfig() Get a *rest.Config for the cluster.
Cluster.KubeconfigPath() Write kubeconfig to a temp file and return its path.
Cluster.LoadImages(ctx, images...) Load local Docker images into all cluster nodes.
Cluster.ExportLogs(ctx, dir) Export cluster logs to a directory for debugging.
Cluster.ApplyManifests(ctx, yaml) Apply multi-document Kubernetes YAML via server-side apply.
WithNodeImage(image) Option: set the Kind node image.
WithWaitForReady(d) Option: set the readiness timeout.
WithRawConfig(raw) Option: pass raw Kind cluster config YAML for full control over cluster topology. Mutually exclusive with WithConfigFile.
WithConfigFile(path) Option: load Kind cluster config from a file path. Mutually exclusive with WithRawConfig.

Examples

Complete runnable examples are available in the examples/ directory:

Run all examples with:

make test-examples # Requires Docker

Compatibility

kindkit is tested against the Kind versions that target currently-supported Kubernetes releases. Each Kind release supports multiple Kubernetes versions — see the Kind releases page for details.

The exact Kind versions tested are defined in the CI workflow.

Running tests

The project includes unit and end-to-end tests. E2e tests create real Kind clusters and require Docker.

make test          # unit + e2e tests
make test-unit     # unit tests only
make test-e2e      # e2e tests only (requires Docker)

Contributing

Feedback and contributions are welcome — open an issue, start a discussion, or submit a pull request.

License

This project is licensed under the Apache License 2.0.

Documentation

Overview

Package kindkit creates and manages Kind (Kubernetes in Docker) clusters from Go code.

Context handling

Create, CreateOrReuse, Cluster.Delete, and Cluster.ExportLogs accept a context argument, but Kind's underlying API does not support cancellation, so the context is ignored. Cluster.LoadImages and Cluster.ApplyManifests do honor the supplied context.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Cluster

type Cluster struct {
	// contains filtered or unexported fields
}

Cluster is a handle to a Kind cluster managed by kindkit. Obtain one from Create or CreateOrReuse, then use its methods to work with the cluster.

Cluster.Delete is idempotent and safe to call more than once. When Create or CreateOrReuse return a partial failure (a non-nil *Cluster together with an error), the returned handle is still valid for Cluster.ExportLogs and Cluster.Delete so callers can diagnose and clean up.

func Create

func Create(ctx context.Context, name string, opts ...Option) (*Cluster, error)

Create creates a Kind cluster and, if WithWaitForReady was supplied, blocks until it is ready. On partial failure, both a non-nil *Cluster and an error may be returned so the caller can still inspect or clean up.

Example

ExampleCreate shows the full cluster lifecycle, including the partial-failure contract: on error, the returned *Cluster may still be non-nil and usable for log export and cleanup.

package main

import (
	"context"
	"log"
	"time"

	"github.com/IrvingMg/kindkit"
)

func main() {
	ctx := context.Background()

	cluster, err := kindkit.Create(ctx, "my-cluster",
		kindkit.WithWaitForReady(3*time.Minute),
	)
	if err != nil {
		if cluster != nil {
			_ = cluster.ExportLogs(ctx, "./logs")
			_ = cluster.Delete(ctx)
		}
		log.Fatal(err)
	}
	defer func() { _ = cluster.Delete(ctx) }()

	// Use cluster.RESTConfig() for client-go, cluster.KubeconfigPath()
	// for kubectl, etc.
}

func CreateOrReuse

func CreateOrReuse(ctx context.Context, name string, opts ...Option) (*Cluster, error)

CreateOrReuse returns an existing cluster if its API server is reachable, otherwise creates a new one. Options only apply on create. Like Create, both a non-nil *Cluster and an error may be returned.

func (*Cluster) ApplyManifests

func (c *Cluster) ApplyManifests(ctx context.Context, manifests []byte) error

ApplyManifests applies multi-document Kubernetes YAML to the cluster using server-side apply with field manager "kindkit". Documents are applied in the order they appear; documents with no kind are skipped, and namespaced resources without a metadata.namespace default to "default".

When a document is a CustomResourceDefinition, ApplyManifests waits for Kubernetes to mark the CRD as Established before applying the next document, so a single call can install a CRD together with the custom resources that use it.

Example

ExampleCluster_ApplyManifests applies a Kubernetes manifest to the cluster using server-side apply.

package main

import (
	"context"
	"log"
	"time"

	"github.com/IrvingMg/kindkit"
)

func main() {
	ctx := context.Background()

	cluster, err := kindkit.Create(ctx, "my-cluster",
		kindkit.WithWaitForReady(3*time.Minute),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer func() { _ = cluster.Delete(ctx) }()

	manifest := []byte(`
apiVersion: v1
kind: Namespace
metadata:
  name: demo
`)
	if err := cluster.ApplyManifests(ctx, manifest); err != nil {
		log.Fatal(err)
	}
}

func (*Cluster) Delete

func (c *Cluster) Delete(ctx context.Context) error

Delete deletes the cluster. It is safe to call on an already-deleted cluster.

func (*Cluster) ExportLogs

func (c *Cluster) ExportLogs(ctx context.Context, dir string) error

ExportLogs exports cluster logs to the given directory for debugging.

func (*Cluster) KubeconfigPath

func (c *Cluster) KubeconfigPath() (string, error)

KubeconfigPath writes the kubeconfig to a temporary file and returns its path, suitable for tools that read a kubeconfig file such as kubectl or helm. The caller is responsible for removing the file.

Example

ExampleCluster_KubeconfigPath writes the kubeconfig to a temporary file so external tools like kubectl or helm can be invoked against the cluster.

package main

import (
	"context"
	"log"
	"os"
	"os/exec"
	"time"

	"github.com/IrvingMg/kindkit"
)

func main() {
	ctx := context.Background()

	cluster, err := kindkit.Create(ctx, "my-cluster",
		kindkit.WithWaitForReady(3*time.Minute),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer func() { _ = cluster.Delete(ctx) }()

	path, err := cluster.KubeconfigPath()
	if err != nil {
		log.Fatal(err)
	}
	defer func() { _ = os.Remove(path) }()

	cmd := exec.CommandContext(ctx, "kubectl", "--kubeconfig", path, "get", "nodes")
	if err := cmd.Run(); err != nil {
		log.Fatal(err)
	}
}

func (*Cluster) LoadImages

func (c *Cluster) LoadImages(ctx context.Context, images ...string) error

LoadImages loads images from the local Docker daemon into all cluster nodes. The images must already exist locally. On a multi-node cluster, per-node failures are collected and returned together via errors.Join.

Example

ExampleCluster_LoadImages loads locally-built images into every cluster node so Pods can reference them without a registry.

package main

import (
	"context"
	"log"
	"time"

	"github.com/IrvingMg/kindkit"
)

func main() {
	ctx := context.Background()

	cluster, err := kindkit.Create(ctx, "my-cluster",
		kindkit.WithWaitForReady(3*time.Minute),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer func() { _ = cluster.Delete(ctx) }()

	if err := cluster.LoadImages(ctx, "my-app:latest", "my-sidecar:latest"); err != nil {
		log.Fatal(err)
	}
}

func (*Cluster) Name

func (c *Cluster) Name() string

Name returns the cluster name.

func (*Cluster) RESTConfig

func (c *Cluster) RESTConfig() (*rest.Config, error)

RESTConfig returns a *rest.Config for the cluster, suitable for use with client-go, controller-runtime, and similar in-process Kubernetes clients.

type Option

type Option func(*options)

Option configures cluster creation. Options are passed to Create and CreateOrReuse.

func WithConfigFile

func WithConfigFile(path string) Option

WithConfigFile loads a Kind cluster configuration from a file path. Mutually exclusive with WithRawConfig.

func WithNodeImage

func WithNodeImage(image string) Option

WithNodeImage sets the node Docker image (e.g. "kindest/node:v1.31.0"). When unset, Kind uses the default node image built into its library (the specific image varies by Kind version).

func WithRawConfig

func WithRawConfig(raw []byte) Option

WithRawConfig passes a raw Kind cluster configuration YAML (kind: Cluster, apiVersion: kind.x-k8s.io/v1alpha4) to Kind. Mutually exclusive with WithConfigFile.

func WithWaitForReady

func WithWaitForReady(d time.Duration) Option

WithWaitForReady sets the timeout for waiting for the cluster to be ready. When unset, Create returns as soon as Kind finishes provisioning the node containers, without waiting for the control plane to accept requests; callers that use the cluster immediately should supply a non-zero duration.

Directories

Path Synopsis
test

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL