How torloejborg/easykube works
1. What this repo is
- Easykube is a Go CLI for creating and managing a local Kubernetes development environment.
- It combines a Kind-based cluster, a Zot pull-through registry, and an addon system that lets users compose stacks of Kubernetes app logic.
2. Primary entrypoint and CLI surface
- main.go and cmd/root.go define the binary and command tree.
- The subcommands in cmd/ are the user-facing operations: boot, start, stop, destroy, add, remove, list, status, config, skaffold, and version.
- This is a classic CLI boundary: command parsing stays at the edge, while orchestration and domain logic live below it.
3. Orchestration layer
- pkg/core is the central coordination layer.
- It models the repository’s domain concepts: addons, stacks, task execution, and dependency resolution.
- This is where the project decides *what* to do with a cluster or addon, without directly embedding tool-specific details.
4. Addon model and dependency graph
- Addons appear to be the core unit of composition.
- pkg/core/dependency_resolver.go, pkg/core/addon.go, and pkg/core/stack.go suggest addons can depend on one another, form stacks, and be executed in dependency order.
- The test_addons/ fixtures include circular, diamond, and broken dependency cases, showing that dependency correctness is an important architectural concern.
5. Scripted addon execution boundary
- pkg/js is the execution/runtime boundary for addon behavior.
- Easykube uses Goja to run JavaScript addon scripts, exposing a curated API such as Helm, Kustomize, Kubernetes operations, environment access, Git checkout, HTTP, skopeo, image preloading, secret creation, deployment waiting, and process execution.
- This means addon authors write behavior in JS, while Go provides the host runtime and safe integration points.
6. External tool abstraction
- pkg/ez is a helper/integration layer around local and cluster-facing tooling.
- It contains wrappers for Kubernetes utilities, container runtime detection, skaffold handling, OS/version detection, and cluster/config helpers.
- Architecturally, this is the “tooling adapter” layer that isolates the rest of the code from direct dependence on binaries like docker, kubectl, helm, kustomize, and skaffold.
7. Bootstrap and cluster lifecycle
- The boot command is the most infrastructure-heavy flow.
- README indicates it creates a Kind cluster named easykube-kind and a companion Zot registry configured as a pull-through cache.
- The cluster lifecycle commands (boot, start, stop, destroy, status) are distinct from addon operations, but both converge on the same underlying environment/config state.
8. Configuration and persistent state
- cmd/config* and pkg/ez/config_utils.go handle generation, editing, and use of configuration.
- The repo intentionally keeps its own config separate from the user’s existing kubeconfig, using a dedicated config directory under ~/.config/easykube and a separate kubeconfig under ~/.kube/easykube.
- This separation is an important boundary for diagrams: Easykube owns its own state and does not directly mutate the user’s primary Kubernetes context.
9. Templates and bundled runtime assets
- pkg/resources/data/ contains the static assets that bootstrap the environment: cluster/config templates, Coredns data, certs, skaffold manifests, and Zot config templates.
- These assets are embedded into the binary and then materialized into files or cluster resources during setup.
- The repo therefore has a “compiled-in defaults” architecture rather than relying entirely on external config files.
10. Certificates and local HTTPS support
- cert/ and pkg/resources/data/cert/ contain a local CA and generated cert material used for secure local access.
- The certificate subsystem supports the local development story, especially because many addons expect HTTPS and registry access.
- In diagrams, this is part of the bootstrap infrastructure, not a standalone application feature.
11. Skaffold and application deployment path
- The skaffold command and the pkg/resources/data/skaffold/ bundle indicate a dedicated path for deploying/managing app workloads using Skaffold alongside Kustomize manifests.
- This is likely the bridge from addon definitions to running application resources in the cluster.
- The presence of pkg/js/ek_skaffold.go and related JS helpers suggests addon scripts can trigger deployment workflows rather than only declaratively defining them.
12. Testing and verification
- Tests are split across helper-layer tests (pkg/ez, pkg/js) and fixture-based addon tests (test_addons/).
- There is also a mock/ package for interface-based mocking, suggesting core orchestration depends on abstractions rather than hard-coded binaries.
- CI includes Go tests and CodeQL, reinforcing that the repo’s correctness depends heavily on dependency resolution, scripting runtime behavior, and tool integration.
13. External dependencies and runtime assumptions
- The runtime assumes the presence of local developer tools: Docker or Podman, Kind via Docker, Kubernetes clients, Helm, Kustomize, and optionally Skaffold.
- External services may be mirrored locally through Zot, and private registries can be configured in the Easykube config.
- Easykube is therefore not a hosted service; it is a local orchestration tool that stitches together local binaries, local cluster state, and addon scripts.
14. High-level data flow
- User command enters cmd/ → command logic calls pkg/core orchestration → pkg/ez resolves local tooling/config/cluster details → pkg/js executes addon scripts → scripts call back into Kubernetes/tool helpers → external binaries and the Kind/Zot/Kubernetes environment perform the actual work.
- The main architectural boundary is between CLI/orchestration code and the external local dev environment it controls.
Main entry points: task_manager.go Task manager · root.go Root cmd · ek_helm.go Addon ops · cluster_utils.go Cluster utils
Components 24
CLI
User-facing command tree and binary entrypoints.
- main.go · Binary entrypoint that hands off into the command tree.
main.go - Root cmd · Top-level command wiring and shared CLI setup.
cmd/root.go - Cluster cmds · Boot, start, stop, destroy, status commands for managing the local Kubernetes environment.
cmd/boot.go - Addon cmds · Add, remove, list, and config operations for addon composition.
cmd/add.go - Skaffold cmd · CLI surface for skaffold-driven workload management.
cmd/skaffold.go - Version cmd · Prints binary and environment version information.
cmd/version.go
Core
Orchestration, addon model, dependency resolution, and task execution.
- Addon model · Represents an addon as a unit of composition and execution.
pkg/core/addon.go - Stacks · Groups addons into ordered stacks for coordinated execution.
pkg/core/stack.go - Resolver · Resolves addon dependencies and execution order, including cycle handling.
pkg/core/dependency_resolver.go - Task manager · Runs coordinated operations across addons and cluster actions.
pkg/core/task_manager.go - Core APIs · Shared interfaces used to decouple orchestration from concrete tooling.
pkg/core/interfaces.go
Runtime
JavaScript addon execution and host API surface.
- JS runner · Executes addon scripts through Goja and bridges host APIs into JavaScript.
pkg/js/jsrunner.go - Host API · Exports the Easykube JS surface and shared script helpers.
pkg/js/easykube.go - Addon ops · Representative JS helpers for Helm, Kustomize, Git, HTTP, secrets, image preload, and process/deployment actions.
pkg/js/ek_helm.go
Tooling
Adapters around Kubernetes, cluster, and local developer tools.
- Config · Owns Easykube configuration, paths, and persistent environment state.
pkg/ez/config_utils.go - Cluster utils · Wraps Kind, kubeconfig, and cluster lifecycle helpers.
pkg/ez/cluster_utils.go - K8s utils · Helpers for Kubernetes client operations and cluster-facing actions.
pkg/ez/k8s_utils.go - Runtime tools · Detects container runtime, OS details, skaffold availability, and external binary behavior.
pkg/ez/container_runtime.go - Status builder · Builds status views from cluster and addon state.
pkg/ez/status_builder.go
Assets
Embedded templates, manifests, certificates, and bundled runtime data.
- Bundled data · Embedded templates and manifests for cluster config, DNS, certificates, skaffold, and Zot.
pkg/resources/data - Skaffold assets · Bundled skaffold manifest set used to deploy example workloads.
pkg/resources/data/skaffold/ek.js - Cert assets · Local CA and certificate material for HTTPS-enabled local development.
pkg/resources/data/cert/localtest.me.crt
Fixtures
Representative addon fixtures used to verify dependency and execution behavior.
- Dep fixtures · Fixture addon graphs for dependency validation, including diamond and circular cases.
test_addons/diamond/a/a.ek.js - Exec fixtures · Fixture addons that exercise execution, manifests, and port configuration behavior.
test_addons/exec/a/a.ek.js
Connections 31
- main.go → Root cmd: starts · The binary initializes the root command tree.
- Root cmd → Cluster cmds: wires · Root command exposes cluster lifecycle subcommands.
- Root cmd → Addon cmds: wires · Root command exposes addon composition subcommands.
- Root cmd → Skaffold cmd: wires · Root command exposes skaffold-specific operations.
- Root cmd → Version cmd: wires · Root command exposes version reporting.
- Cluster cmds → Task manager: calls · Cluster operations delegate into orchestration.
- Addon cmds → Task manager: calls · Addon operations delegate into orchestration.
- Skaffold cmd → Runtime tools: uses · Skaffold command depends on external tool detection and execution helpers.
- Task manager → Addon model: operates on · Task execution is centered on addon units.
- Task manager → Stacks: organizes · Tasks work across addon stacks.
- Task manager → Resolver: orders · Dependency resolution determines execution sequence.
- Task manager → Core APIs: depends on · Task orchestration is abstracted through interfaces.
- Resolver → Addon model: analyzes · The resolver inspects addon dependency metadata.
- Stacks → Addon model: contains · Stacks are composed from addons.
- Addon model → JS runner: executes in · Addon behavior is implemented as JS scripts.
- JS runner → Host API: exposes · The runtime publishes the Easykube host API to scripts.
- Host API → Addon ops: binds · Host API includes integrations for cluster and tooling actions.
- Addon ops → K8s utils: uses · JS helpers call into Kubernetes utilities.
- Addon ops → Cluster utils: uses · JS helpers rely on cluster lifecycle and environment helpers.
- Addon ops → Runtime tools: uses · JS helpers can invoke local tools and runtime-dependent operations.
- Cluster utils → Config: reads · Cluster lifecycle is driven by Easykube configuration and state.
- K8s utils → Config: reads · Kubernetes helpers use Easykube config and paths.
- Runtime tools → Config: reads · Runtime/tool detection depends on configuration and environment state.
- Status builder → Cluster utils: summarizes · Status views are built from cluster lifecycle state.
- Status builder → K8s utils: summarizes · Status views incorporate Kubernetes resource state.
- Config → Bundled data: materializes · Configuration and bootstrap state are generated from embedded templates.
- Cluster utils → Bundled data: uses · Cluster bootstrap relies on embedded cluster and Zot assets.
- Bundled data → Skaffold assets: includes · Bundled runtime data includes skaffold manifests and script entrypoints.
- Bundled data → Cert assets: includes · Bundled runtime data includes local certificate material.
- Dep fixtures → Resolver: verifies · Dependency fixtures exercise ordering and cycle resolution.
- Exec fixtures → JS runner: verifies · Execution fixtures exercise JS addon runtime behavior.