Dependency Management

Kubebuilder uses dep to manage dependencies.Different dependency management tasks can be done using the dep ensurecommand.

Adding new dependencies

Kubernetes Dependencies

Kubebuilder-generated projects depends on a number of Kubernetesdependencies internally. Kubebuilder (using the controller-runtimelibrary) makes sure that the parts of these dependencies that are exposedin the Kubebuilder API remain stable.

It's recommended not to make use of most of these libraries directly, sincethey change frequently in incompatible ways. The k8s.io/api repository isthe exception to this, and it's reccomended that you rely on the version thatkubebuilder requires, instead of listing it as a direct dependency inGopkg.toml.

However, if you do add direct dependencies on any of these libraries yourself,be aware that you may encounter dependency conflicts. See the problem withkubernetes libraries below for moreinformation.

Dep manages dependency constraints using the Gopkg.toml file. You can addnew dependencies by adding new [[constraint]] stanzas to that file.Alternatively, if you're not using kubebuilderupdate, you can use the dep ensure -addcommand to add new dependencies to your Gopkg.toml.

  1. # edit Gopkg.toml OR perform the following:
  2. dep ensure -add github.com/pkg/errors

Updating existing dependencies

Update dependencies for your project to the latest minor and patch versions.

  1. dep ensure -update sigs.k8s.io/controller-runtime sigs.k8s.io/controller-tools

Repopulating your vendor directory

Dependency source code is stored in the vendor directory. If it ever getsdeleted, you can repopulate it using the exact dependency versions stored inGopkg.lock.

  1. dep ensure

How Kubebuilder's Dependencies Work

Under the Hood

The information in this section details how Kubebuilder's dependency graphworks. It's not necessary for day-to-day use of Kubebuilder, but can be usefulif you want to understand how a particular version of Kubebuilder relates toa particular version of Kubernetes.

TL;DR

As of Kubebuilder 1.0.2:

  • Projects generated with Kubebuilder list a semantic version ofcontroller-runtime and controller-tools as their only directdependencies. All other Kubernetes-related libraries are transativedependencies.

  • controller-runtime and controller-tools each list a specific, identicalset of dependencies on Kubernetes libraries and related libraries.

  • Once you've updated your dependencies with kubebuilder update vendor,you'll be able to run dep ensure and dep ensure —update sigs.k8s.io/controller-runtime sigs.k8s.io/controller-tools to safelyupdate all your dependencies in the future.

  • You can depend on controller-runtime to follow semantic versioningguarantees — we won't break your code withoutintroducing a new major version, for both the interfaces incontroller-runtime, and the bits of the kubernetes libraries thatcontroller-runtime actually exposes.

The Problem with Kubernetes libraries

The kubernetes project exports a collection of libraries (which we'll callthe k8s-deps from now on) that expose common functionality used whenbuilding applications that consume Kubernetes APIs (e.g. clients,informers, etc). Due to the way Kubrenetes is versioned(non-semantically), all of these dependencies must closely match —differing versions can cause strange compilation or runtime errors.

Beyond this, these libraries have their own set of dependencies which arenot always the latest versions, or are occaisionally in-between versions.

Collecting the correct set of dependencies for any given Kubernetesproject can thus be tricky.

Using Prebaked Manifests (Kubebuilder pre-1.0.2)

Before version 1.0.2, Kubebuilder shipped a pre-baked manifest of thecorrect dependencies. When scaffolding out at new project usingkubebuilder init (a kb-project), it would copy over a Gopkg.tomlfile containing the exact dependency versions required for the project(which could then be used by dep dependency management tool to actuallyfetch the dependencies).

In addition to the Kubernetes dependencies required, this also specifiedthat all kb-projects use the master branch of the controller-runtimelibrary, which provides the abstractions that Kubebuilder is built upon.Because controller-runtime wraps and consumes Kubernetes, it also needsspecific versions of the k8s-deps, and those version must match the oneslisted in the kb-project's Gopkg.toml, otherwise we'd have conflictingdependencies.

The Problem with Prebaked Manifests

Using the master branch as the target version of controller-runtime madeit impossible to make breaking changes to controller-runtime. However,even when using a specific version of controller-runtime, it's stilldifficult to make changes.

Since kb-projects must use an identical set of dependencies tocontroller-runtime, any update to the controller-runtime dependencies(say, to pull in a new feature) would have caused immediate dependencyversion conflicts. Effectively, any update to the dependencies had to betreated as a major version revision, and there would have been no way totell the difference between "this release includes breaking API changes"and "this release simply switches to a newer version of the k8s-deps".

Transitive Dependencies (Kubebuilder 1.0.2+)

As noted above, any dependency version in kb-projects must matchdependency versions listed in controller-runtime, exactly. Furthermore, itturns out, by design, the set of k8s-deps used in controller-runtime isa superset of the set of dependencies actually imported by kb-projects.

Therefore, in kb-projects generated with Kubebuilder 1.0.2+, nodependencies are listed besides controller-runtime (and controller-tools).All of the k8s-deps become transitive dependencies, whose versions aredetermined when dep (the dependency management tool) looks at theversions required by controller-runtime.

controller-runtime is semantically versioned, so any changes to either theinterfaces in controller-runtime, or the pieces of the k8s-deps that areexposed as part of those interfaces, means a new major version ofcontroller-runtime will be released. Any other changes (new features, bugfixes, updates to k8s-deps which don't break interfaces) yield minor orpatch versions (as per semver), which can easily andsafely be updated to by kb-projects.

controller-tools Dependencies

controller-tools is the library used to generate CRD and RBAC manifestsfor kb-projects. With Kubebuilder 1.0.2+, it does not directly depend oncontroller-runtime, but shares the same set of dependencies. It thereforemust be updated in lockstep with controller-runtime. This is mostlya concern of the controller-tools/controller-runtime maintainers, and willnot affect users. Like controller-runtime, controller-tools uses semver.