Repository: kubernetes-sigs/cluster-api
Pull request #6207 (2022-02-25 07:02:36)

🌱 tilt: remove unused options
Signed-off-by: Stefan Büringer buringerst@vmware.com

<!-- please add a icon to the title of this PR (see https://sigs.k8s.io/cluster-api/VERSIONING.md), and delete this line and similar ones -->
<!-- the icon will be either ⚠️ (:warning:, major or breaking changes), ✨ (:sparkles:, feature additions), 🐛 (:bug:, patch and bugfixes), 📖 (:book:, documentation or proposals), or 🌱 (:seedling:, minor or other) -->

**What this PR does / why we need it**:
`preload_images_for_kind` and `kind_cluster_name` are not used anymore (probably since a while).
Right now we're always preloading cert-manager images based on `CAPI_KIND_CLUSTER_NAME`.
I think if there is demand to run tilt with a non-kind cluster we can reconsider our current handling 
and maybe just auto-discover if the current cluster is a kind cluster and act accordingly.

The last few months since we had this hard dependency to kind nobody complained.

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #



Patch:
diff --git a/Makefile b/Makefile
index 5f34da4be..a0f5d24e7 100644
--- a/Makefile
+++ b/Makefile
@@ -316,7 +316,7 @@ APIDIFF_OLD_COMMIT ?= $(shell git rev-parse origin/main)
 apidiff: $(GO_APIDIFF) ## Check for API differences
 	$(GO_APIDIFF) $(APIDIFF_OLD_COMMIT) --print-compatible
 
-ALL_VERIFY_CHECKS = doctoc boilerplate shellcheck tiltfile modules gen conversions docker-provider
+ALL_VERIFY_CHECKS = doctoc boilerplate shellcheck tiltfile modules gen conversions docker-provider book-links
 
 .PHONY: verify
 verify: $(addprefix verify-,$(ALL_VERIFY_CHECKS)) ## Run all verify-* targets
@@ -364,6 +364,10 @@ verify-docker-provider:
 	@echo "Verifying CAPD"
 	cd $(CAPD_DIR); $(MAKE) verify
 
+.PHONY: verify-book-links
+verify-book-links: ## Verify book links
+	$(MAKE) -C docs/book verify
+
 ## --------------------------------------
 ## Binaries
 ## --------------------------------------
@@ -431,10 +435,6 @@ docker-build-kubeadm-control-plane: ## Build the docker image for kubeadm contro
 e2e-framework: ## Builds the CAPI e2e framework
 	cd $(E2E_FRAMEWORK_DIR); go build ./...
 
-.PHONY: build-book
-build-book: ## Build the book
-	$(MAKE) -C docs/book build
-
 .PHONY: serve-book
 serve-book: ## Build and serve the book (with live-reload)
 	$(MAKE) -C docs/book serve
diff --git a/Tiltfile b/Tiltfile
index d7cc2bf1f..a2bb4c7f2 100644
--- a/Tiltfile
+++ b/Tiltfile
@@ -4,9 +4,7 @@ version_settings(True, ">=0.22.2")
 
 settings = {
     "deploy_cert_manager": True,
-    "preload_images_for_kind": True,
     "enable_providers": ["docker"],
-    "kind_cluster_name": "kind",
     "debug": {},
 }
 
diff --git a/bootstrap/kubeadm/main.go b/bootstrap/kubeadm/main.go
index 49349b37a..46320bfac 100644
--- a/bootstrap/kubeadm/main.go
+++ b/bootstrap/kubeadm/main.go
@@ -150,11 +150,14 @@ func main() {
 		os.Exit(1)
 	}
 
-	// Set the Klog format, as the Serialize format shouldn't be used anymore.
-	// This makes sure that the logs are formatted correctly, i.e.:
-	// * JSON logging format: msg isn't serialized twice
-	// * text logging format: values are formatted with their .String() func.
-	ctrl.SetLogger(klogr.NewWithOptions(klogr.WithFormat(klogr.FormatKlog)))
+	// The JSON log format requires the Klog format in klog, otherwise log lines
+	// are serialized twice, e.g.:
+	// { ... "msg":"controller/cluster \"msg\"=\"Starting workers\"\n"}
+	if logOptions.Config.Format == logs.JSONLogFormat {
+		ctrl.SetLogger(klogr.NewWithOptions(klogr.WithFormat(klogr.FormatKlog)))
+	} else {
+		ctrl.SetLogger(klogr.New())
+	}
 
 	if profilerAddress != "" {
 		klog.Infof("Profiler listening for requests at %s", profilerAddress)
diff --git a/controlplane/kubeadm/internal/workload_cluster.go b/controlplane/kubeadm/internal/workload_cluster.go
index a46051897..6b18651cb 100644
--- a/controlplane/kubeadm/internal/workload_cluster.go
+++ b/controlplane/kubeadm/internal/workload_cluster.go
@@ -75,12 +75,6 @@ var (
 	// NOTE: The following assumes that kubeadm version equals to Kubernetes version.
 	minVerKubeletSystemdDriver = semver.MustParse("1.21.0")
 
-	// Starting from v1.24.0 kubeadm uses "kubelet-config" a ConfigMap name for KubeletConfiguration,
-	// Dropping the X-Y suffix.
-	//
-	// NOTE: The following assumes that kubeadm version equals to Kubernetes version.
-	minVerUnversionedKubeletConfig = semver.MustParse("1.24.0")
-
 	// ErrControlPlaneMinNodes signals that a cluster doesn't meet the minimum required nodes
 	// to remove an etcd member.
 	ErrControlPlaneMinNodes = errors.New("cluster has fewer than 2 control plane nodes; removing an etcd member is not supported")
@@ -185,7 +179,7 @@ func (w *Workload) UpdateKubernetesVersionInKubeadmConfigMap(ctx context.Context
 // This is a necessary process for upgrades.
 func (w *Workload) UpdateKubeletConfigMap(ctx context.Context, version semver.Version) error {
 	// Check if the desired configmap already exists
-	desiredKubeletConfigMapName := generateKubeletConfigName(version)
+	desiredKubeletConfigMapName := fmt.Sprintf("kubelet-config-%d.%d", version.Major, version.Minor)
 	configMapKey := ctrlclient.ObjectKey{Name: desiredKubeletConfigMapName, Namespace: metav1.NamespaceSystem}
 	_, err := w.getConfigMap(ctx, configMapKey)
 	if err == nil {
@@ -196,14 +190,7 @@ func (w *Workload) UpdateKubeletConfigMap(ctx context.Context, version semver.Ve
 		return errors.Wrapf(err, "error determining if kubelet configmap %s exists", desiredKubeletConfigMapName)
 	}
 
-	previousMinorVersionKubeletConfigMapName := generateKubeletConfigName(semver.Version{Major: version.Major, Minor: version.Minor - 1})
-
-	// If desired and previous ConfigMap name are the same it means we already completed the transition
-	// to the unified KubeletConfigMap name in the previous upgrade; no additional operations are required.
-	if desiredKubeletConfigMapName == previousMinorVersionKubeletConfigMapName {
-		return nil
-	}
-
+	previousMinorVersionKubeletConfigMapName := fmt.Sprintf("kubelet-config-%d.%d", version.Major, version.Minor-1)
 	configMapKey = ctrlclient.ObjectKey{Name: previousMinorVersionKubeletConfigMapName, Namespace: metav1.NamespaceSystem}
 	// Returns a copy
 	cm, err := w.getConfigMap(ctx, configMapKey)
diff --git a/controlplane/kubeadm/internal/workload_cluster_rbac.go b/controlplane/kubeadm/internal/workload_cluster_rbac.go
index d714c6329..0b3d667ca 100644
--- a/controlplane/kubeadm/internal/workload_cluster_rbac.go
+++ b/controlplane/kubeadm/internal/workload_cluster_rbac.go
@@ -41,11 +41,8 @@ const (
 	// KubeletConfigMapRolePrefix defines base kubelet configuration ConfigMap role prefix.
 	KubeletConfigMapRolePrefix = "kubeadm:"
 
-	// KubeletConfigMapName defines base kubelet configuration ConfigMap name for kubeadm < 1.24.
+	// KubeletConfigMapName defines base kubelet configuration ConfigMap name.
 	KubeletConfigMapName = "kubelet-config-%d.%d"
-
-	// UnversionedKubeletConfigMapName defines base kubelet configuration ConfigMap for kubeadm >= 1.24.
-	UnversionedKubeletConfigMapName = "kubelet-config"
 )
 
 // EnsureResource creates a resoutce if the target resource doesn't exist. If the resource exists already, this function will ignore the resource instead.
@@ -104,10 +101,6 @@ func (w *Workload) AllowBootstrapTokensToGetNodes(ctx context.Context) error {
 }
 
 func generateKubeletConfigName(version semver.Version) string {
-	majorMinor := semver.Version{Major: version.Major, Minor: version.Minor}
-	if majorMinor.GTE(minVerUnversionedKubeletConfig) {
-		return UnversionedKubeletConfigMapName
-	}
 	return fmt.Sprintf(KubeletConfigMapName, version.Major, version.Minor)
 }
 
diff --git a/controlplane/kubeadm/main.go b/controlplane/kubeadm/main.go
index 15c6b403c..696f0a5c0 100644
--- a/controlplane/kubeadm/main.go
+++ b/controlplane/kubeadm/main.go
@@ -153,11 +153,14 @@ func main() {
 		os.Exit(1)
 	}
 
-	// Set the Klog format, as the Serialize format shouldn't be used anymore.
-	// This makes sure that the logs are formatted correctly, i.e.:
-	// * JSON logging format: msg isn't serialized twice
-	// * text logging format: values are formatted with their .String() func.
-	ctrl.SetLogger(klogr.NewWithOptions(klogr.WithFormat(klogr.FormatKlog)))
+	// The JSON log format requires the Klog format in klog, otherwise log lines
+	// are serialized twice, e.g.:
+	// { ... "msg":"controller/cluster \"msg\"=\"Starting workers\"\n"}
+	if logOptions.Config.Format == logs.JSONLogFormat {
+		ctrl.SetLogger(klogr.NewWithOptions(klogr.WithFormat(klogr.FormatKlog)))
+	} else {
+		ctrl.SetLogger(klogr.New())
+	}
 
 	if profilerAddress != "" {
 		klog.Infof("Profiler listening for requests at %s", profilerAddress)
diff --git a/docs/book/Makefile b/docs/book/Makefile
index 7a8314093..250e5c9e1 100644
--- a/docs/book/Makefile
+++ b/docs/book/Makefile
@@ -38,10 +38,18 @@ MDBOOK := $(TOOLS_BIN_DIR)/mdbook
 $(MDBOOK):
 	$(CRATE_INSTALL) --git rust-lang/mdBook --tag v0.4.11 --to $(TOOLS_BIN_DIR) --force
 
+MDBOOK_LINKCHECK := $(TOOLS_BIN_DIR)/mdbook-linkcheck
+$(MDBOOK_LINKCHECK):
+	$(CRATE_INSTALL) --git Michael-F-Bryan/mdbook-linkcheck --tag v0.7.0 --to $(TOOLS_BIN_DIR) --force
+
 .PHONY: serve
-serve: $(MDBOOK) $(TABULATE) $(EMBED) $(RELEASELINK)
+serve: $(MDBOOK) $(TABULATE) $(EMBED) $(RELEASELINK) $(MDBOOK_LINKCHECK)
 	$(MDBOOK) serve
 
 .PHONY: build
-build: $(MDBOOK) $(TABULATE) $(EMBED) $(RELEASELINK)
+build: $(MDBOOK) $(TABULATE) $(EMBED) $(RELEASELINK) $(MDBOOK_LINKCHECK)
+	$(MDBOOK) build
+
+.PHONY: verify
+verify: $(MDBOOK) $(TABULATE) $(EMBED) $(RELEASELINK) $(MDBOOK_LINKCHECK)
 	$(MDBOOK) build
diff --git a/docs/book/src/developer/providers/v1.1-to-v1.2.md b/docs/book/src/developer/providers/v1.1-to-v1.2.md
index 2db2e5f7b..b46eb5cd6 100644
--- a/docs/book/src/developer/providers/v1.1-to-v1.2.md
+++ b/docs/book/src/developer/providers/v1.1-to-v1.2.md
@@ -34,43 +34,4 @@ in ClusterAPI are kept in sync with the versions used by `sigs.k8s.io/controller
 
 ### Other
 
-- Logging:
-    - To align with the upstream Kubernetes community CAPI now configures logging via `component-base/logs`. 
-      This provides advantages like support for the JSON logging format (via `--logging-format=json`) and automatic
-      deprecation of klog flags aligned to the upstream Kubernetes deprecation period.
-      <details>
-      <summary>View <code>main.go</code> diff</summary>
-
-      ```diff
-      var (
-      	...
-      +	logOptions = logs.NewOptions()
-      )
-
-      func init() {
-      -	klog.InitFlags(nil)
-
-      func InitFlags(fs *pflag.FlagSet) {
-      +	logs.AddFlags(fs, logs.SkipLoggingConfigurationFlags())
-      +	logOptions.AddFlags(fs)
-      
-      func main() {
-      	...
-      	pflag.Parse()
-      
-      +	if err := logOptions.ValidateAndApply(); err != nil {
-      +		setupLog.Error(err, "unable to start manager")
-      +		os.Exit(1)
-      +	}
-      +
-      +	// Set the Klog format, as the Serialize format shouldn't be used anymore.
-      +	// This makes sure that the logs are formatted correctly, i.e.:
-      +	// * JSON logging format: msg isn't serialized twice
-      +	// * text logging format: values are formatted with their .String() func.
-      +	ctrl.SetLogger(klogr.NewWithOptions(klogr.WithFormat(klogr.FormatKlog)))
-      -	ctrl.SetLogger(klogr.New())
-      ```
-      </details>
-
-      This change has been introduced in CAPI in the following PRs: [#6072](https://github.com/kubernetes-sigs/cluster-api/pull/6072), [#6190](https://github.com/kubernetes-sigs/cluster-api/pull/6190).</br>
-      **Note**: This change is not mandatory for providers, but highly recommended.
+-
diff --git a/docs/book/src/developer/tilt.md b/docs/book/src/developer/tilt.md
index 133f9e3fd..995d9df0b 100644
--- a/docs/book/src/developer/tilt.md
+++ b/docs/book/src/developer/tilt.md
@@ -8,8 +8,7 @@ workflow that offers easy deployments and rapid iterative builds.
 ## Prerequisites
 
 1. [Docker](https://docs.docker.com/install/): v19.03 or newer
-1. [kind](https://kind.sigs.k8s.io): v0.9 or newer (other clusters can be
-   used if `preload_images_for_kind` is set to false)
+1. [kind](https://kind.sigs.k8s.io): v0.9 or newer
 1. [Tilt](https://docs.tilt.dev/install.html): v0.22.2 or newer
 1. [kustomize](https://github.com/kubernetes-sigs/kustomize): provided via `make kustomize`
 1. [envsubst](https://github.com/drone/envsubst): provided via `make envsubst`
@@ -70,8 +69,6 @@ documentation](https://docs.tilt.dev/api.html#api.default_registry) for more det
 **enable_providers** (Array[]String, default=['docker']): A list of the providers to enable. See [available providers](#available-providers)
 for more details.
 
-**kind_cluster_name** (String, default="kind"): The name of the kind cluster to use when preloading images.
-
 **kustomize_substitutions** (Map{String: String}, default={}): An optional map of substitutions for `${}`-style placeholders in the
 provider's yaml.
 
@@ -216,8 +213,6 @@ kustomize_substitutions:
 
 **deploy_cert_manager** (Boolean, default=`true`): Deploys cert-manager into the cluster for use for webhook registration.
 
-**preload_images_for_kind** (Boolean, default=`true`): Uses `kind load docker-image` to preload images into a kind cluster.
-
 **trigger_mode** (String, default=`auto`): Optional setting to configure if tilt should automatically rebuild on changes.
 Set to `manual` to disable auto-rebuilding and require users to trigger rebuilds of individual changed components through the UI.
 
diff --git a/go.mod b/go.mod
index 89e11c027..f56a276d9 100644
--- a/go.mod
+++ b/go.mod
@@ -8,7 +8,7 @@ require (
 	github.com/blang/semver v3.5.1+incompatible
 	github.com/coredns/corefile-migration v1.0.14
 	github.com/davecgh/go-spew v1.1.1
-	github.com/docker/distribution v2.8.0+incompatible
+	github.com/docker/distribution v2.7.1+incompatible
 	github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46
 	github.com/evanphx/json-patch/v5 v5.6.0
 	github.com/fatih/color v1.13.0
diff --git a/go.sum b/go.sum
index 8e89d9bc0..7944b9a02 100644
--- a/go.sum
+++ b/go.sum
@@ -165,9 +165,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
+github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
 github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/distribution v2.8.0+incompatible h1:l9EaZDICImO1ngI+uTifW+ZYvvz7fKISBAKpg+MbWbY=
-github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
 github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 h1:7QPwrLT79GlD5sizHf27aoY2RTvw62mO6x7mxkScNk0=
 github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46/go.mod h1:esf2rsHFNlZlxsqsZDojNBcnNs5REqIvRrWRHqX0vEU=
diff --git a/hack/tools/go.mod b/hack/tools/go.mod
index 8e37e3540..601109698 100644
--- a/hack/tools/go.mod
+++ b/hack/tools/go.mod
@@ -60,7 +60,7 @@ require (
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/dnephin/pflag v1.0.7 // indirect
 	github.com/docker/cli v20.10.11+incompatible // indirect
-	github.com/docker/distribution v2.8.0+incompatible // indirect
+	github.com/docker/distribution v2.7.1+incompatible // indirect
 	github.com/docker/docker v20.10.12+incompatible // indirect
 	github.com/docker/docker-credential-helpers v0.6.4 // indirect
 	github.com/docker/go-connections v0.4.0 // indirect
diff --git a/hack/tools/go.sum b/hack/tools/go.sum
index 193a7a6f9..972691e0f 100644
--- a/hack/tools/go.sum
+++ b/hack/tools/go.sum
@@ -374,9 +374,8 @@ github.com/docker/cli v20.10.11+incompatible h1:tXU1ezXcruZQRrMP8RN2z9N91h+6egZT
 github.com/docker/cli v20.10.11+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
 github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
 github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
+github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
 github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/distribution v2.8.0+incompatible h1:l9EaZDICImO1ngI+uTifW+ZYvvz7fKISBAKpg+MbWbY=
-github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
 github.com/docker/docker v20.10.11+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/docker v20.10.12+incompatible h1:CEeNmFM0QZIsJCZKMkZx0ZcahTiewkrgiwfYD+dfl1U=
 github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
diff --git a/internal/controllers/machine/machine_controller.go b/internal/controllers/machine/machine_controller.go
index 0dfa2d5e6..90ce87705 100644
--- a/internal/controllers/machine/machine_controller.go
+++ b/internal/controllers/machine/machine_controller.go
@@ -545,7 +545,7 @@ func (r *Reconciler) drainNode(ctx context.Context, cluster *clusterv1.Cluster,
 		},
 		Out: writer{log.Info},
 		ErrOut: writer{func(msg string, keysAndValues ...interface{}) {
-			log.Error(nil, msg, keysAndValues...)
+			log.Error(nil, msg, keysAndValues)
 		}},
 	}
 
diff --git a/main.go b/main.go
index 762341fe8..3f2ed449d 100644
--- a/main.go
+++ b/main.go
@@ -192,11 +192,14 @@ func main() {
 		os.Exit(1)
 	}
 
-	// Set the Klog format, as the Serialize format shouldn't be used anymore.
-	// This makes sure that the logs are formatted correctly, i.e.:
-	// * JSON logging format: msg isn't serialized twice
-	// * text logging format: values are formatted with their .String() func.
-	ctrl.SetLogger(klogr.NewWithOptions(klogr.WithFormat(klogr.FormatKlog)))
+	// The JSON log format requires the Klog format in klog, otherwise log lines
+	// are serialized twice, e.g.:
+	// { ... "msg":"controller/cluster \"msg\"=\"Starting workers\"\n"}
+	if logOptions.Config.Format == logs.JSONLogFormat {
+		ctrl.SetLogger(klogr.NewWithOptions(klogr.WithFormat(klogr.FormatKlog)))
+	} else {
+		ctrl.SetLogger(klogr.New())
+	}
 
 	if profilerAddress != "" {
 		klog.Infof("Profiler listening for requests at %s", profilerAddress)
diff --git a/scripts/ci-build.sh b/scripts/ci-build.sh
index f0c46017b..128f5c23e 100755
--- a/scripts/ci-build.sh
+++ b/scripts/ci-build.sh
@@ -21,7 +21,7 @@ set -o pipefail
 REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
 
 # Core Cluster API
-cd "${REPO_ROOT}" && make managers clusterctl e2e-framework build-book
+cd "${REPO_ROOT}" && make managers clusterctl e2e-framework
 
 echo "*** Building Cluster API Provider Docker ***"
 # Docker provider


Test patch:
diff --git a/controlplane/kubeadm/internal/workload_cluster_rbac_test.go b/controlplane/kubeadm/internal/workload_cluster_rbac_test.go
index f4f93e3d6..9154384ff 100644
--- a/controlplane/kubeadm/internal/workload_cluster_rbac_test.go
+++ b/controlplane/kubeadm/internal/workload_cluster_rbac_test.go
@@ -24,86 +24,32 @@ import (
 	. "github.com/onsi/gomega"
 	rbacv1 "k8s.io/api/rbac/v1"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
-	"sigs.k8s.io/controller-runtime/pkg/client/fake"
 )
 
 func TestCluster_ReconcileKubeletRBACBinding_NoError(t *testing.T) {
-	type wantRBAC struct {
-		role        ctrlclient.ObjectKey
-		roleBinding ctrlclient.ObjectKey
-	}
 	tests := []struct {
-		name    string
-		client  ctrlclient.Client
-		version semver.Version
-		want    *wantRBAC
+		name   string
+		client ctrlclient.Client
 	}{
 		{
-			name:    "creates role and role binding for Kubernetes/kubeadm < v1.24",
-			client:  fake.NewClientBuilder().Build(),
-			version: semver.MustParse("1.23.3"),
-			want: &wantRBAC{
-				role:        ctrlclient.ObjectKey{Namespace: metav1.NamespaceSystem, Name: "kubeadm:kubelet-config-1.23"},
-				roleBinding: ctrlclient.ObjectKey{Namespace: metav1.NamespaceSystem, Name: "kubeadm:kubelet-config-1.23"},
-			},
-		},
-		{
-			name: "tolerates existing role binding for Kubernetes/kubeadm < v1.24",
-			client: fake.NewClientBuilder().WithObjects(
-				&rbacv1.RoleBinding{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "kubeadm:kubelet-config-1.23"}, RoleRef: rbacv1.RoleRef{
-					Name: "kubeadm:kubelet-config-1.23",
-				}},
-				&rbacv1.Role{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "kubeadm:kubelet-config-1.23"}, Rules: []rbacv1.PolicyRule{{
-					Verbs:         []string{"get"},
-					APIGroups:     []string{""},
-					Resources:     []string{"configmaps"},
-					ResourceNames: []string{"kubelet-config-1.23"},
-				}}},
-			).Build(),
-			version: semver.MustParse("1.23.3"),
-			want: &wantRBAC{
-				role:        ctrlclient.ObjectKey{Namespace: metav1.NamespaceSystem, Name: "kubeadm:kubelet-config-1.23"},
-				roleBinding: ctrlclient.ObjectKey{Namespace: metav1.NamespaceSystem, Name: "kubeadm:kubelet-config-1.23"},
-			},
-		},
-		{
-			name:    "creates role and role binding for Kubernetes/kubeadm >= v1.24",
-			client:  fake.NewClientBuilder().Build(),
-			version: semver.MustParse("1.24.0"),
-			want: &wantRBAC{
-				role:        ctrlclient.ObjectKey{Namespace: metav1.NamespaceSystem, Name: "kubeadm:kubelet-config"},
-				roleBinding: ctrlclient.ObjectKey{Namespace: metav1.NamespaceSystem, Name: "kubeadm:kubelet-config"},
+			name: "role binding and role already exist",
+			client: &fakeClient{
+				get: map[string]interface{}{
+					"kube-system/kubeadm:kubelet-config-1.12": &rbacv1.RoleBinding{},
+					"kube-system/kubeadm:kubelet-config-1.13": &rbacv1.Role{},
+				},
 			},
 		},
 		{
-			name:    "creates role and role binding for Kubernetes/kubeadm >= v1.24 ignoring pre-release and build tags",
-			client:  fake.NewClientBuilder().Build(),
-			version: semver.MustParse("1.24.0-alpha.1+xyz.1"),
-			want: &wantRBAC{
-				role:        ctrlclient.ObjectKey{Namespace: metav1.NamespaceSystem, Name: "kubeadm:kubelet-config"},
-				roleBinding: ctrlclient.ObjectKey{Namespace: metav1.NamespaceSystem, Name: "kubeadm:kubelet-config"},
-			},
+			name:   "role binding and role don't exist",
+			client: &fakeClient{},
 		},
 		{
-			name: "tolerates existing role binding for Kubernetes/kubeadm >= v1.24",
-			client: fake.NewClientBuilder().WithObjects(
-				&rbacv1.RoleBinding{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "kubeadm:kubelet-config"}, RoleRef: rbacv1.RoleRef{
-					Name: "kubeadm:kubelet-config",
-				}},
-				&rbacv1.Role{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "kubeadm:kubelet-config"}, Rules: []rbacv1.PolicyRule{{
-					Verbs:         []string{"get"},
-					APIGroups:     []string{""},
-					Resources:     []string{"configmaps"},
-					ResourceNames: []string{"kubelet-config"},
-				}}},
-			).Build(),
-			version: semver.MustParse("1.24.1"),
-			want: &wantRBAC{
-				role:        ctrlclient.ObjectKey{Namespace: metav1.NamespaceSystem, Name: "kubeadm:kubelet-config"},
-				roleBinding: ctrlclient.ObjectKey{Namespace: metav1.NamespaceSystem, Name: "kubeadm:kubelet-config"},
+			name: "create returns an already exists error",
+			client: &fakeClient{
+				createErr: apierrors.NewAlreadyExists(schema.GroupResource{}, ""),
 			},
 		},
 	}
@@ -115,27 +61,8 @@ func TestCluster_ReconcileKubeletRBACBinding_NoError(t *testing.T) {
 			c := &Workload{
 				Client: tt.client,
 			}
-			g.Expect(c.ReconcileKubeletRBACBinding(ctx, tt.version)).To(Succeed())
-			g.Expect(c.ReconcileKubeletRBACRole(ctx, tt.version)).To(Succeed())
-			if tt.want != nil {
-				r := &rbacv1.Role{}
-				// Role exists
-				g.Expect(tt.client.Get(ctx, tt.want.role, r)).To(Succeed())
-				// Role ensure grants for the KubeletConfig config map
-				g.Expect(r.Rules).To(Equal([]rbacv1.PolicyRule{
-					{
-						Verbs:         []string{"get"},
-						APIGroups:     []string{""},
-						Resources:     []string{"configmaps"},
-						ResourceNames: []string{generateKubeletConfigName(tt.version)},
-					},
-				}))
-				// RoleBinding exists
-				b := &rbacv1.RoleBinding{}
-				// RoleBinding refers to the role
-				g.Expect(tt.client.Get(ctx, tt.want.roleBinding, b)).To(Succeed())
-				g.Expect(b.RoleRef.Name).To(Equal(tt.want.role.Name))
-			}
+			g.Expect(c.ReconcileKubeletRBACBinding(ctx, semver.MustParse("1.12.3"))).To(Succeed())
+			g.Expect(c.ReconcileKubeletRBACRole(ctx, semver.MustParse("1.13.3"))).To(Succeed())
 		})
 	}
 }
diff --git a/controlplane/kubeadm/internal/workload_cluster_test.go b/controlplane/kubeadm/internal/workload_cluster_test.go
index caa160533..704e91096 100644
--- a/controlplane/kubeadm/internal/workload_cluster_test.go
+++ b/controlplane/kubeadm/internal/workload_cluster_test.go
@@ -19,6 +19,7 @@ package internal
 import (
 	"context"
 	"errors"
+	"fmt"
 	"testing"
 
 	"github.com/blang/semver"
@@ -364,10 +365,9 @@ func TestUpdateKubeletConfigMap(t *testing.T) {
 		objs               []client.Object
 		expectErr          bool
 		expectCgroupDriver string
-		expectNewConfigMap bool
 	}{
 		{
-			name:    "create new config map for 1.19 --> 1.20 (anything < 1.24); config map for previous version is copied",
+			name:    "create new config map",
 			version: semver.Version{Major: 1, Minor: 20},
 			objs: []client.Object{&corev1.ConfigMap{
 				ObjectMeta: metav1.ObjectMeta{
@@ -379,51 +379,14 @@ func TestUpdateKubeletConfigMap(t *testing.T) {
 					kubeletConfigKey: yaml.Raw(`
 						apiVersion: kubelet.config.k8s.io/v1beta1
 						kind: KubeletConfiguration
-						foo: bar
 						`),
 				},
 			}},
-			expectNewConfigMap: true,
+			expectErr:          false,
+			expectCgroupDriver: "",
 		},
 		{
-			name:    "create new config map 1.23 --> 1.24; config map for previous version is copied",
-			version: semver.Version{Major: 1, Minor: 24},
-			objs: []client.Object{&corev1.ConfigMap{
-				ObjectMeta: metav1.ObjectMeta{
-					Name:            "kubelet-config-1.23",
-					Namespace:       metav1.NamespaceSystem,
-					ResourceVersion: "some-resource-version",
-				},
-				Data: map[string]string{
-					kubeletConfigKey: yaml.Raw(`
-						apiVersion: kubelet.config.k8s.io/v1beta1
-						kind: KubeletConfiguration
-						foo: bar
-						`),
-				},
-			}},
-			expectNewConfigMap: true,
-		},
-		{
-			name:    "create new config map >=1.24 --> next; no op",
-			version: semver.Version{Major: 1, Minor: 25},
-			objs: []client.Object{&corev1.ConfigMap{
-				ObjectMeta: metav1.ObjectMeta{
-					Name:            "kubelet-config",
-					Namespace:       metav1.NamespaceSystem,
-					ResourceVersion: "some-resource-version",
-				},
-				Data: map[string]string{
-					kubeletConfigKey: yaml.Raw(`
-						apiVersion: kubelet.config.k8s.io/v1beta1
-						kind: KubeletConfiguration
-						foo: bar
-						`),
-				},
-			}},
-		},
-		{
-			name:    "1.20 --> 1.21 sets the cgroupDriver if empty",
+			name:    "KubeletConfig 1.21 gets the cgroupDriver set if empty",
 			version: semver.Version{Major: 1, Minor: 21},
 			objs: []client.Object{&corev1.ConfigMap{
 				ObjectMeta: metav1.ObjectMeta{
@@ -434,16 +397,14 @@ func TestUpdateKubeletConfigMap(t *testing.T) {
 				Data: map[string]string{
 					kubeletConfigKey: yaml.Raw(`
 						apiVersion: kubelet.config.k8s.io/v1beta1
-						kind: KubeletConfiguration
-						foo: bar
-						`),
+						kind: KubeletConfiguration`),
 				},
 			}},
+			expectErr:          false,
 			expectCgroupDriver: "systemd",
-			expectNewConfigMap: true,
 		},
 		{
-			name:    "1.20 --> 1.21 preserves cgroupDriver if already set",
+			name:    "KubeletConfig 1.21 preserves cgroupDriver if already set",
 			version: semver.Version{Major: 1, Minor: 21},
 			objs: []client.Object{&corev1.ConfigMap{
 				ObjectMeta: metav1.ObjectMeta{
@@ -455,18 +416,18 @@ func TestUpdateKubeletConfigMap(t *testing.T) {
 					kubeletConfigKey: yaml.Raw(`
 						apiVersion: kubelet.config.k8s.io/v1beta1
 						kind: KubeletConfiguration
-						cgroupDriver: cgroupfs
-						foo: bar
-					`),
+						cgroupDriver: foo`),
 				},
 			}},
-			expectCgroupDriver: "cgroupfs",
-			expectNewConfigMap: true,
+			expectErr:          false,
+			expectCgroupDriver: "foo",
 		},
 		{
-			name:      "returns error if cannot find previous config map",
-			version:   semver.Version{Major: 1, Minor: 21},
-			expectErr: true,
+			name:               "returns error if cannot find previous config map",
+			version:            semver.Version{Major: 1, Minor: 21},
+			objs:               nil,
+			expectErr:          true,
+			expectCgroupDriver: "",
 		},
 	}
 
@@ -483,24 +444,14 @@ func TestUpdateKubeletConfigMap(t *testing.T) {
 				return
 			}
 			g.Expect(err).ToNot(HaveOccurred())
-
-			// Check if the resulting ConfigMap exists
 			var actualConfig corev1.ConfigMap
 			g.Expect(w.Client.Get(
 				ctx,
-				client.ObjectKey{Name: generateKubeletConfigName(tt.version), Namespace: metav1.NamespaceSystem},
+				client.ObjectKey{Name: fmt.Sprintf("kubelet-config-%d.%d", tt.version.Major, tt.version.Minor), Namespace: metav1.NamespaceSystem},
 				&actualConfig,
 			)).To(Succeed())
-			// Check other values are carried over for previous config map
-			g.Expect(actualConfig.Data[kubeletConfigKey]).To(ContainSubstring("foo"))
-			// Check the cgroupvalue has the expected value
+			g.Expect(actualConfig.ResourceVersion).ToNot(Equal("some-resource-version"))
 			g.Expect(actualConfig.Data[kubeletConfigKey]).To(ContainSubstring(tt.expectCgroupDriver))
-			// check if the config map is new
-			if tt.expectNewConfigMap {
-				g.Expect(actualConfig.ResourceVersion).ToNot(Equal("some-resource-version"))
-			} else {
-				g.Expect(actualConfig.ResourceVersion).To(Equal("some-resource-version"))
-			}
 		})
 	}
 }
diff --git a/test/go.mod b/test/go.mod
index d7d25a6ff..e296dce8f 100644
--- a/test/go.mod
+++ b/test/go.mod
@@ -49,7 +49,7 @@ require (
 	github.com/coreos/go-semver v0.3.0 // indirect
 	github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
-	github.com/docker/distribution v2.8.0+incompatible // indirect
+	github.com/docker/distribution v2.7.1+incompatible // indirect
 	github.com/docker/go-units v0.4.0 // indirect
 	github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 // indirect
 	github.com/evanphx/json-patch v4.12.0+incompatible // indirect
diff --git a/test/go.sum b/test/go.sum
index 792edd9ec..e2ac515c2 100644
--- a/test/go.sum
+++ b/test/go.sum
@@ -310,9 +310,8 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8
 github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
 github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
 github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
+github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
 github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/distribution v2.8.0+incompatible h1:l9EaZDICImO1ngI+uTifW+ZYvvz7fKISBAKpg+MbWbY=
-github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
 github.com/docker/docker v20.10.12+incompatible h1:CEeNmFM0QZIsJCZKMkZx0ZcahTiewkrgiwfYD+dfl1U=
 github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
diff --git a/test/infrastructure/docker/main.go b/test/infrastructure/docker/main.go
index 7b539a5d1..16d970623 100644
--- a/test/infrastructure/docker/main.go
+++ b/test/infrastructure/docker/main.go
@@ -123,11 +123,14 @@ func main() {
 		os.Exit(1)
 	}
 
-	// Set the Klog format, as the Serialize format shouldn't be used anymore.
-	// This makes sure that the logs are formatted correctly, i.e.:
-	// * JSON logging format: msg isn't serialized twice
-	// * text logging format: values are formatted with their .String() func.
-	ctrl.SetLogger(klogr.NewWithOptions(klogr.WithFormat(klogr.FormatKlog)))
+	// The JSON log format requires the Klog format in klog, otherwise log lines
+	// are serialized twice, e.g.:
+	// { ... "msg":"controller/cluster \"msg\"=\"Starting workers\"\n"}
+	if logOptions.Config.Format == logs.JSONLogFormat {
+		ctrl.SetLogger(klogr.NewWithOptions(klogr.WithFormat(klogr.FormatKlog)))
+	} else {
+		ctrl.SetLogger(klogr.New())
+	}
 
 	if profilerAddress != "" {
 		klog.Infof("Profiler listening for requests at %s", profilerAddress)