Kubernetes Dependency Management in KubeVirt#
KubeVirt tracks Kubernetes releases by upgrading k8s.io/* modules (e.g., api, apimachinery, client-go, apiextensions-apiserver) in lock-step across its three-module Go workspace. Because KubeVirt embeds staging directories that are themselves Go modules, all Kubernetes dependency versions must be kept in sync using replace directives in go.work.
A version bump typically requires:
- Updating
replaceblocks ingo.work(and matching entries ingo.mod) - Adapting code to upstream API changes (e.g., new method signatures, removed/promoted beta types)
- Regenerating typed client code and mock files via
make generate
The current Kubernetes dependency baseline is v0.34.2 across go.work with most direct go.mod dependencies at v0.34.3 .
Module Structure & Version Pinning#
The repo uses a Go workspace (go.work) spanning three modules:
.— main KubeVirt module./staging/src/kubevirt.io/api./staging/src/kubevirt.io/client-go
Every k8s.io/* module is pinned to the same version via replace directives in go.work . This is the single source of truth for the Kubernetes version in use — it overrides whatever version go.mod specifies for indirect dependencies. A separate entry pins k8s.io/kube-openapi to a dated commit hash rather than a semantic version .
Workaround for checksum mismatches: When an indirect transitive dependency pulled in by k8s.io/* modules (e.g., github.com/envoyproxy/go-control-plane/envoy via k8s.io/apiextensions-apiserver → grpc) causes Go checksum verification errors, a temporary replace is added to go.work with a TODO comment marking it for removal upon the next k8s.io upgrade to v0.35 .
Dependency Update Process#
All dependency commands run inside Docker via hack/dockerized to ensure a reproducible toolchain environment.
Makefile targets :
| Target | Effect |
|---|---|
make deps-update-patch | go get -u=patch ./... across all modules + Bazel regeneration |
make deps-update | go get ./... (latest minor/patch) + Bazel regeneration |
make deps-sync | go mod tidy only (no version upgrade) + Bazel regeneration |
All three delegate to hack/dep-update.sh, which:
- Runs
go get+go mod tidyin each staging module (api,client-go,client-go/examples/listvms) - Runs
go mod tidyat the repo root - Runs
go work vendor+go work syncto update the vendor directory
Manual Kubernetes version bumps (e.g., v0.33 → v0.34) require directly editing the replace blocks in both go.work and go.mod, then running the full make generate pipeline . The automated deps-update targets do not modify replace directives.
Code Generation Pipeline#
make generate is the top-level target. It runs, in order:
hack/build-ginkgo.sh— builds the test framework binaryhack/generate.sh— all Kubernetes code-generator invocations (see below)hack/bazel-generate.sh+hack/bazel-fmt.sh— regenerates Bazel BUILD fileshack/sync-kubevirtci.sh, common instance type sync, virt-template sync./hack/update-generated-api-testdata.sh
hack/generate.sh orchestrates all code generation:
| Tool | Output | Lines |
|---|---|---|
swagger-doc | In-line Swagger comments | 12–25 |
deepcopy-gen | deepcopy_generated.go per API package | 27–43 |
defaulter-gen | zz_generated.defaults.go | 45–48 |
openapi-gen | openapi_generated.go in client-go/api/ | 50–74 |
conversion-gen | conversion_generated.go for instancetype | 76–79 |
client-gen | Typed clientsets for kubevirt, CDI, Prometheus, NAD, snapshotter | 90–124 |
controller-gen | CRD validation manifests | 136–178 |
mockgen | gRPC/protobuf mocks | 239–242 |
Generated typed clients live under staging/src/kubevirt.io/client-go. The primary KubevirtClient mock is generated_mock_kubevirt.go in staging/src/kubevirt.io/client-go/kubecli/. It is generated by a separate mockgen command (not inside generate.sh) targeting the KubevirtClient interface .
Run make generate-verify after changes to confirm no uncommitted diffs remain .
Builder Image & Code-Generator Versions#
Code-generator tools are baked into the builder Docker image at hack/builder/Dockerfile . Current installed versions:
| Tool | Source | Version |
|---|---|---|
conversion-gen, deepcopy-gen, defaulter-gen, client-gen | k8s.io/code-generator | v0.32.5 |
openapi-gen | k8s.io/kube-openapi | dated commit |
mockgen | go.uber.org/mock | v0.6.0 |
Note: The k8s.io/code-generator version in the builder (v0.32.5) is intentionally independent of the k8s.io/* runtime version (v0.34.x). The code-generator version controls the shape of generated client code; bumping it requires updating hack/builder/Dockerfile and the builder image tag referenced in hack/dockerized .
After changing the builder image, run make generate to regenerate all typed clients and mocks with the new tooling.
Common Breakage Patterns & Fixes#
Mock interface mismatch: When a k8s.io/client-go version adds new methods to kubernetes.Interface, MockKubevirtClient fails to compile with an error like:
*MockKubevirtClient does not implement KubevirtClient (missing method ResourceV1beta2)
Fix: regenerate generated_mock_kubevirt.go using the mockgen command at the top of the file , or run make generate .
WatchErrorHandler signature change: Newer k8s.io/client-go versions added a context.Context parameter to cache.DefaultWatchErrorHandler. Update all call sites in controllers (e.g., pkg/virt-controller/watch/application.go, pkg/virt-api/api.go) accordingly .
Beta API promotion: When an upstream API graduates from beta to GA (e.g., DRA ResourceSlice from resource/v1beta1 → resource/v1 in k8s 1.34), update imports in pkg/virt-controller/watch/dra/dra.go and informer registrations in pkg/controller/virtinformers.go .
Checksum verification errors: Transitive k8s.io indirect dependencies may introduce checksum mismatches in the Go module proxy. Short-term fix: add a replace directive in go.work to pin the offending module. Mark with a TODO for removal when the next k8s major bump occurs .