Skip to content

build: derive default Capabilities.KubeVersion from client-go - #1868

Open
norman-zon wants to merge 2 commits into
hashicorp:mainfrom
norman-zon:fix/default-kube-version-from-client-go
Open

build: derive default Capabilities.KubeVersion from client-go#1868
norman-zon wants to merge 2 commits into
hashicorp:mainfrom
norman-zon:fix/default-kube-version-from-client-go

Conversation

@norman-zon

Copy link
Copy Markdown

Description

data.helm_template reports the rendering cluster as Kubernetes v1.20.0, so any chart declaring a kubeVersion constraint above 1.20 cannot be rendered at all.

The cause is a missing pair of linker flags rather than anything in the provider's Go code.

Helm's pkg/chartutil/capabilities.go declares the default as build-time overridable variables, with deliberately stale in-source values:

// The Kubernetes version can be set by LDFLAGS. In order to do that the value
// must be a string.
k8sVersionMajor = "1"
k8sVersionMinor = "20"

Helm's own Makefile replaces both at link time, deriving them from the k8s.io/client-go version it builds against:

K8S_MODULES_VER=$(subst ., ,$(subst v,,$(shell go list -f '{{.Version}}' -m k8s.io/client-go)))
K8S_MODULES_MAJOR_VER=$(shell echo $$(($(firstword $(K8S_MODULES_VER)) + 1)))
K8S_MODULES_MINOR_VER=$(word 2,$(K8S_MODULES_VER))

LDFLAGS += -X helm.sh/helm/v3/pkg/chartutil.k8sVersionMajor=$(K8S_MODULES_MAJOR_VER)
LDFLAGS += -X helm.sh/helm/v3/pkg/chartutil.k8sVersionMinor=$(K8S_MODULES_MINOR_VER)

This provider sets no such flags in either build path, so it links the library with the literal source values and chartutil.DefaultCapabilities.KubeVersion resolves to v1.20.0. data.helm_template sets ClientOnly (unless validate = true), which is exactly the path that falls back to DefaultCapabilities — so every offline render claims v1.20.0.

The resulting error points at the wrong thing. It names a Kubernetes version that exists nowhere in the user's infrastructure, which makes it read as a cluster or chart problem:

Error: Error running Helm install

  with data.helm_template.crds,
  on main.tf line 4, in data "helm_template" "crds":
   4: data "helm_template" "crds" {

Error running Helm install: chart requires kubeVersion: >=1.29.0-0 which is
incompatible with Kubernetes v1.20.0

The same chart renders fine with helm template, because the CLI is the one build where the flags are set. That divergence is what makes this hard to diagnose from the outside — see #1253, where a user hit this on EKS 1.27, was advised to try installing with helm (which works, for this reason), and the report was eventually closed by the stale bot with the cause never identified.

Fix

Set the two flags in both build paths, mirroring Helm's Makefile:

  • .github/workflows/build.yml — the release build via hashicorp/actions-go-build. This is the one that determines what registry users get.
  • GNUmakefilebuild and packages, so local and cross builds behave like released ones. Introduces an LDFLAGS variable, as there was none.

k8s.io/client-go v0.x.y corresponds to Kubernetes v1.x.y, hence the +1 on the major. With the currently pinned k8s.io/client-go v0.35.1 the default becomes v1.35.0, and it will track the dependency automatically from here on rather than needing a manual bump.

Verification

Default capability, before and after, linking the same tree:

$ go run ./probe                       # DefaultCapabilities.KubeVersion
v1.20.0
$ go run -ldflags "-X helm.sh/helm/v3/pkg/chartutil.k8sVersionMajor=1 \
                   -X helm.sh/helm/v3/pkg/chartutil.k8sVersionMinor=35" ./probe
v1.35.0

Both build paths resolve the values correctly:

$ make -n build | grep 'go build'
go build -v -ldflags "-X helm.sh/helm/v3/pkg/chartutil.k8sVersionMajor=1 -X helm.sh/helm/v3/pkg/chartutil.k8sVersionMinor=35" .

$ # workflow derivation, run standalone
$ go list -f '{{.Version}}' -m k8s.io/client-go
v0.35.1
$ echo "major=$K8S_MODULES_MAJOR_VER minor=$K8S_MODULES_MINOR_VER"
major=1 minor=35

End to end against a real chart with a kubeVersion floor (cloudnative-pg declares kubeVersion: ">=1.29.0-0"), using this exact config with no kube_version argument:

data "helm_template" "crds" {
  name       = "cnpg-crds"
  namespace  = "cnpg-system"
  repository = "oci://ghcr.io/cloudnative-pg/charts"
  chart      = "cloudnative-pg"
  version    = "0.29.0"
  show_only  = ["templates/crds/crds.yaml"]
  values     = [yamlencode({ crds = { create = true } })]
}
Provider Result
released 3.2.0 Error running Helm install: chart requires kubeVersion: >=1.29.0-0 which is incompatible with Kubernetes v1.20.0
this branch (dev_overrides) Read complete after 1s — all 11 CRDs rendered

Notes

Relates to #1253, which reported this symptom and was closed without the cause being found.

Helm's chartutil declares k8sVersionMajor/Minor as build-time overridable
variables whose in-source values are "1" and "20". Helm's own Makefile
replaces them via -ldflags, deriving them from the k8s.io/client-go version
it builds against, so the helm CLI reports a current default. This provider
builds with no -ldflags for them, so it inherits the literal source values
and DefaultCapabilities.KubeVersion resolves to v1.20.0.

That surfaces in data.helm_template, which renders with ClientOnly and
therefore falls back to DefaultCapabilities. Any chart declaring a
kubeVersion constraint above 1.20 refuses to render, and the error names the
bogus version rather than the constraint's real problem:

  Error running Helm install: chart requires kubeVersion: >=1.29.0-0
  which is incompatible with Kubernetes v1.20.0

The same chart renders fine with the helm CLI, because that binary is the
one build where the ldflags are set.

Set the two flags in both build paths, mirroring Helm's Makefile: the
release build in .github/workflows/build.yml, and the GNUmakefile so local
builds behave like released ones. client-go v0.x.y corresponds to Kubernetes
v1.x.y, hence the +1 on the major.

With k8s.io/client-go v0.35.1 the default becomes v1.35.0.
@norman-zon
norman-zon requested review from a team, iam404 and rigalGit as code owners August 11, 2026 09:56
@hashicorp-cla-app

Copy link
Copy Markdown

CLA assistant check

Thank you for your submission! We require that all contributors sign our Contributor License Agreement ("CLA") before we can accept the contribution. Read and sign the agreement

Learn more about why HashiCorp requires a CLA and what the CLA includes

Have you signed the CLA already but the status is still pending? Recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant