Repository: kubernetes-sigs/cluster-api
Pull request #8017 (2023-01-30 07:19:08)

🌱 make ensure scripts fail if GOPATH/bin not in PATH
ensure-kind.sh and ensure-kubectl.sh install binaries into $GOPATH/bin, but nowhere it checks that $GOPATH/bin is in user's PATH. In this case, the newly installed binaries won't be found later on.


k8s-ci-robot: Hi @tuminoid. Thanks for your PR.

I'm waiting for a [kubernetes-sigs](https://github.com/orgs/kubernetes-sigs/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://git.k8s.io/community/community-membership.md#member) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fcluster-api).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
**Once this PR has been reviewed and has the lgtm label**, please assign cecilerobertmichon for approval by writing `/assign @cecilerobertmichon` in a comment. For more information see [the Kubernetes Code Review Process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process).

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fcluster-api).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubernetes-sigs/cluster-api/blob/main/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["cecilerobertmichon"]} -->
sbueringer: /lgtm
tuminoid: /assign @cecilerobertmichon
k8s-ci-robot: New changes are detected. LGTM label has been removed.
sbueringer: /lgtm
k8s-ci-robot: LGTM label has been added.  <details>Git tree hash: be59b7912822e64ebb578166035ade2726127c80</details>
k8s-ci-robot: New changes are detected. LGTM label has been removed.
tuminoid: Moved the logic to `ensure-go.sh`, which is called before other ensure scripts.
k8s-ci-robot: @tuminoid: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-cluster-api-test-main | 128a27b47d3e3af08038bb100412ad8a83664705 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/8017/pull-cluster-api-test-main/1620387621962256384) | true | `/test pull-cluster-api-test-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=8017). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Atuminoid). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @tuminoid: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-cluster-api-test-main | 128a27b47d3e3af08038bb100412ad8a83664705 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/8017/pull-cluster-api-test-main/1620387621962256384) | true | `/test pull-cluster-api-test-main`
pull-cluster-api-test-mink8s-main | 128a27b47d3e3af08038bb100412ad8a83664705 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/8017/pull-cluster-api-test-mink8s-main/1620387622012588032) | true | `/test pull-cluster-api-test-mink8s-main`
pull-cluster-api-e2e-main | 128a27b47d3e3af08038bb100412ad8a83664705 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/8017/pull-cluster-api-e2e-main/1620387622067113984) | true | `/test pull-cluster-api-e2e-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=8017). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Atuminoid). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @tuminoid: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-cluster-api-test-main | 128a27b47d3e3af08038bb100412ad8a83664705 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/8017/pull-cluster-api-test-main/1620387621962256384) | true | `/test pull-cluster-api-test-main`
pull-cluster-api-test-mink8s-main | 128a27b47d3e3af08038bb100412ad8a83664705 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/8017/pull-cluster-api-test-mink8s-main/1620387622012588032) | true | `/test pull-cluster-api-test-mink8s-main`
pull-cluster-api-e2e-main | 128a27b47d3e3af08038bb100412ad8a83664705 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/8017/pull-cluster-api-e2e-main/1620387622067113984) | true | `/test pull-cluster-api-e2e-main`
pull-cluster-api-e2e-informing-main | 128a27b47d3e3af08038bb100412ad8a83664705 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/8017/pull-cluster-api-e2e-informing-main/1620387622117445632) | false | `/test pull-cluster-api-e2e-informing-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=8017). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Atuminoid). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tuminoid: Move logic to function in `utils.sh`, called by `ensure-*.sh` if they install binary to `GOPATH_BIN`.
k8s-ci-robot: @tuminoid: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-cluster-api-test-main | 128a27b47d3e3af08038bb100412ad8a83664705 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/8017/pull-cluster-api-test-main/1620387621962256384) | true | `/test pull-cluster-api-test-main`
pull-cluster-api-test-mink8s-main | 128a27b47d3e3af08038bb100412ad8a83664705 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/8017/pull-cluster-api-test-mink8s-main/1620387622012588032) | true | `/test pull-cluster-api-test-mink8s-main`
pull-cluster-api-e2e-main | 128a27b47d3e3af08038bb100412ad8a83664705 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/8017/pull-cluster-api-e2e-main/1620387622067113984) | true | `/test pull-cluster-api-e2e-main`
pull-cluster-api-e2e-informing-main | 128a27b47d3e3af08038bb100412ad8a83664705 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/8017/pull-cluster-api-e2e-informing-main/1620387622117445632) | false | `/test pull-cluster-api-e2e-informing-main`
pull-cluster-api-e2e-informing-ipv6-main | 128a27b47d3e3af08038bb100412ad8a83664705 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/8017/pull-cluster-api-e2e-informing-ipv6-main/1620387622297800704) | false | `/test pull-cluster-api-e2e-informing-ipv6-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=8017). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Atuminoid). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml
index 5a28cecd6..574547bac 100644
--- a/.github/workflows/dependabot.yml
+++ b/.github/workflows/dependabot.yml
@@ -26,7 +26,7 @@ jobs:
       uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # tag=v3.5.0
       with:
         go-version: ${{ steps.vars.outputs.go_version }}
-    - uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920 # tag=v3.2.4
+    - uses: actions/cache@58c146cc91c5b9e778e71775dfe9bf1442ad9a12 # tag=v3.2.3
       name: Restore go cache
       with:
         path: |
diff --git a/Makefile b/Makefile
index dc475c56c..2c94b6bda 100644
--- a/Makefile
+++ b/Makefile
@@ -111,7 +111,7 @@ SETUP_ENVTEST_BIN := setup-envtest
 SETUP_ENVTEST := $(abspath $(TOOLS_BIN_DIR)/$(SETUP_ENVTEST_BIN)-$(SETUP_ENVTEST_VER))
 SETUP_ENVTEST_PKG := sigs.k8s.io/controller-runtime/tools/setup-envtest
 
-CONTROLLER_GEN_VER := v0.11.2
+CONTROLLER_GEN_VER := v0.11.1
 CONTROLLER_GEN_BIN := controller-gen
 CONTROLLER_GEN := $(abspath $(TOOLS_BIN_DIR)/$(CONTROLLER_GEN_BIN)-$(CONTROLLER_GEN_VER))
 CONTROLLER_GEN_PKG := sigs.k8s.io/controller-tools/cmd/controller-gen
diff --git a/api/v1beta1/condition_consts.go b/api/v1beta1/condition_consts.go
index 5c100e779..559f4df34 100644
--- a/api/v1beta1/condition_consts.go
+++ b/api/v1beta1/condition_consts.go
@@ -59,9 +59,9 @@ const (
 
 const (
 	// ControlPlaneInitializedCondition reports if the cluster's control plane has been initialized such that the
-	// cluster's apiserver is reachable. If no Control Plane provider is in use this condition reports that at least one
-	// control plane Machine has a node reference. Once this Condition is marked true, its value is never changed. See
-	// the ControlPlaneReady condition for an indication of the current readiness of the cluster's control plane.
+	// cluster's apiserver is reachable and at least one control plane Machine has a node reference. Once this
+	// condition is marked true, its value is never changed. See the ControlPlaneReady condition for an indication of
+	// the current readiness of the cluster's control plane.
 	ControlPlaneInitializedCondition ConditionType = "ControlPlaneInitialized"
 
 	// MissingNodeRefReason (Severity=Info) documents a cluster waiting for at least one control plane Machine to have
diff --git a/bootstrap/kubeadm/api/v1alpha3/conversion.go b/bootstrap/kubeadm/api/v1alpha3/conversion.go
index 5a73bb040..ed148fa86 100644
--- a/bootstrap/kubeadm/api/v1alpha3/conversion.go
+++ b/bootstrap/kubeadm/api/v1alpha3/conversion.go
@@ -79,20 +79,6 @@ func (src *KubeadmConfig) ConvertTo(dstRaw conversion.Hub) error {
 		dst.Spec.JoinConfiguration.SkipPhases = restored.Spec.JoinConfiguration.SkipPhases
 	}
 
-	if restored.Spec.JoinConfiguration != nil && restored.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy != "" {
-		if dst.Spec.JoinConfiguration == nil {
-			dst.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{}
-		}
-		dst.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy
-	}
-
-	if restored.Spec.InitConfiguration != nil && restored.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy != "" {
-		if dst.Spec.InitConfiguration == nil {
-			dst.Spec.InitConfiguration = &bootstrapv1.InitConfiguration{}
-		}
-		dst.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy
-	}
-
 	return nil
 }
 
@@ -177,20 +163,6 @@ func (src *KubeadmConfigTemplate) ConvertTo(dstRaw conversion.Hub) error {
 		dst.Spec.Template.Spec.JoinConfiguration.SkipPhases = restored.Spec.Template.Spec.JoinConfiguration.SkipPhases
 	}
 
-	if restored.Spec.Template.Spec.JoinConfiguration != nil && restored.Spec.Template.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy != "" {
-		if dst.Spec.Template.Spec.JoinConfiguration == nil {
-			dst.Spec.Template.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{}
-		}
-		dst.Spec.Template.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.Template.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy
-	}
-
-	if restored.Spec.Template.Spec.InitConfiguration != nil && restored.Spec.Template.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy != "" {
-		if dst.Spec.Template.Spec.InitConfiguration == nil {
-			dst.Spec.Template.Spec.InitConfiguration = &bootstrapv1.InitConfiguration{}
-		}
-		dst.Spec.Template.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.Template.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy
-	}
-
 	return nil
 }
 
diff --git a/bootstrap/kubeadm/api/v1alpha4/conversion.go b/bootstrap/kubeadm/api/v1alpha4/conversion.go
index bd3074d27..58ec2acb9 100644
--- a/bootstrap/kubeadm/api/v1alpha4/conversion.go
+++ b/bootstrap/kubeadm/api/v1alpha4/conversion.go
@@ -64,20 +64,6 @@ func (src *KubeadmConfig) ConvertTo(dstRaw conversion.Hub) error {
 		dst.Spec.JoinConfiguration.SkipPhases = restored.Spec.JoinConfiguration.SkipPhases
 	}
 
-	if restored.Spec.JoinConfiguration != nil && restored.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy != "" {
-		if dst.Spec.JoinConfiguration == nil {
-			dst.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{}
-		}
-		dst.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy
-	}
-
-	if restored.Spec.InitConfiguration != nil && restored.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy != "" {
-		if dst.Spec.InitConfiguration == nil {
-			dst.Spec.InitConfiguration = &bootstrapv1.InitConfiguration{}
-		}
-		dst.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy
-	}
-
 	return nil
 }
 
@@ -143,20 +129,6 @@ func (src *KubeadmConfigTemplate) ConvertTo(dstRaw conversion.Hub) error {
 		dst.Spec.Template.Spec.JoinConfiguration.SkipPhases = restored.Spec.Template.Spec.JoinConfiguration.SkipPhases
 	}
 
-	if restored.Spec.Template.Spec.JoinConfiguration != nil && restored.Spec.Template.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy != "" {
-		if dst.Spec.Template.Spec.JoinConfiguration == nil {
-			dst.Spec.Template.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{}
-		}
-		dst.Spec.Template.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.Template.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy
-	}
-
-	if restored.Spec.Template.Spec.InitConfiguration != nil && restored.Spec.Template.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy != "" {
-		if dst.Spec.Template.Spec.InitConfiguration == nil {
-			dst.Spec.Template.Spec.InitConfiguration = &bootstrapv1.InitConfiguration{}
-		}
-		dst.Spec.Template.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.Template.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy
-	}
-
 	return nil
 }
 
@@ -207,9 +179,3 @@ func Convert_v1beta1_User_To_v1alpha4_User(in *bootstrapv1.User, out *User, s ap
 	// User.PasswdFrom does not exist in kubeadm v1alpha4 API.
 	return autoConvert_v1beta1_User_To_v1alpha4_User(in, out, s)
 }
-
-func Convert_v1beta1_NodeRegistrationOptions_To_v1alpha4_NodeRegistrationOptions(in *bootstrapv1.NodeRegistrationOptions, out *NodeRegistrationOptions, s apiconversion.Scope) error {
-	// NodeRegistrationOptions.ImagePullPolicy does not exit in
-	// kubeadm v1alpha4 API.
-	return autoConvert_v1beta1_NodeRegistrationOptions_To_v1alpha4_NodeRegistrationOptions(in, out, s)
-}
diff --git a/bootstrap/kubeadm/api/v1alpha4/zz_generated.conversion.go b/bootstrap/kubeadm/api/v1alpha4/zz_generated.conversion.go
index 1ff8a4faf..8b75fbf18 100644
--- a/bootstrap/kubeadm/api/v1alpha4/zz_generated.conversion.go
+++ b/bootstrap/kubeadm/api/v1alpha4/zz_generated.conversion.go
@@ -355,6 +355,11 @@ func RegisterConversions(s *runtime.Scheme) error {
 	}); err != nil {
 		return err
 	}
+	if err := s.AddGeneratedConversionFunc((*v1beta1.NodeRegistrationOptions)(nil), (*NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_NodeRegistrationOptions_To_v1alpha4_NodeRegistrationOptions(a.(*v1beta1.NodeRegistrationOptions), b.(*NodeRegistrationOptions), scope)
+	}); err != nil {
+		return err
+	}
 	if err := s.AddGeneratedConversionFunc((*Partition)(nil), (*v1beta1.Partition)(nil), func(a, b interface{}, scope conversion.Scope) error {
 		return Convert_v1alpha4_Partition_To_v1beta1_Partition(a.(*Partition), b.(*v1beta1.Partition), scope)
 	}); err != nil {
@@ -400,11 +405,6 @@ func RegisterConversions(s *runtime.Scheme) error {
 	}); err != nil {
 		return err
 	}
-	if err := s.AddConversionFunc((*v1beta1.NodeRegistrationOptions)(nil), (*NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
-		return Convert_v1beta1_NodeRegistrationOptions_To_v1alpha4_NodeRegistrationOptions(a.(*v1beta1.NodeRegistrationOptions), b.(*NodeRegistrationOptions), scope)
-	}); err != nil {
-		return err
-	}
 	if err := s.AddConversionFunc((*v1beta1.User)(nil), (*User)(nil), func(a, b interface{}, scope conversion.Scope) error {
 		return Convert_v1beta1_User_To_v1alpha4_User(a.(*v1beta1.User), b.(*User), scope)
 	}); err != nil {
@@ -1455,10 +1455,14 @@ func autoConvert_v1beta1_NodeRegistrationOptions_To_v1alpha4_NodeRegistrationOpt
 	out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
 	out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
 	out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors))
-	// WARNING: in.ImagePullPolicy requires manual conversion: does not exist in peer-type
 	return nil
 }
 
+// Convert_v1beta1_NodeRegistrationOptions_To_v1alpha4_NodeRegistrationOptions is an autogenerated conversion function.
+func Convert_v1beta1_NodeRegistrationOptions_To_v1alpha4_NodeRegistrationOptions(in *v1beta1.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error {
+	return autoConvert_v1beta1_NodeRegistrationOptions_To_v1alpha4_NodeRegistrationOptions(in, out, s)
+}
+
 func autoConvert_v1alpha4_Partition_To_v1beta1_Partition(in *Partition, out *v1beta1.Partition, s conversion.Scope) error {
 	out.Device = in.Device
 	out.Layout = in.Layout
diff --git a/bootstrap/kubeadm/api/v1beta1/kubeadm_types.go b/bootstrap/kubeadm/api/v1beta1/kubeadm_types.go
index f54df29dd..dc2bb6087 100644
--- a/bootstrap/kubeadm/api/v1beta1/kubeadm_types.go
+++ b/bootstrap/kubeadm/api/v1beta1/kubeadm_types.go
@@ -251,16 +251,6 @@ type NodeRegistrationOptions struct {
 	// IgnorePreflightErrors provides a slice of pre-flight errors to be ignored when the current node is registered.
 	// +optional
 	IgnorePreflightErrors []string `json:"ignorePreflightErrors,omitempty"`
-
-	// ImagePullPolicy specifies the policy for image pulling
-	// during kubeadm "init" and "join" operations. The value of
-	// this field must be one of "Always", "IfNotPresent" or
-	// "Never". Defaults to "IfNotPresent". This can be used only
-	// with Kubernetes version equal to 1.22 and later.
-	// +kubebuilder:validation:Enum=Always;IfNotPresent;Never
-	// +kubebuilder:default=IfNotPresent
-	// +optional
-	ImagePullPolicy string `json:"imagePullPolicy,omitempty"`
 }
 
 // MarshalJSON marshals NodeRegistrationOptions in a way that an empty slice in Taints is preserved.
@@ -281,14 +271,12 @@ func (n *NodeRegistrationOptions) MarshalJSON() ([]byte, error) {
 			Taints                []corev1.Taint    `json:"taints"`
 			KubeletExtraArgs      map[string]string `json:"kubeletExtraArgs,omitempty"`
 			IgnorePreflightErrors []string          `json:"ignorePreflightErrors,omitempty"`
-			ImagePullPolicy       string            `json:"imagePullPolicy,omitempty"`
 		}{
 			Name:                  n.Name,
 			CRISocket:             n.CRISocket,
 			Taints:                n.Taints,
 			KubeletExtraArgs:      n.KubeletExtraArgs,
 			IgnorePreflightErrors: n.IgnorePreflightErrors,
-			ImagePullPolicy:       n.ImagePullPolicy,
 		})
 	}
 
@@ -299,14 +287,12 @@ func (n *NodeRegistrationOptions) MarshalJSON() ([]byte, error) {
 		Taints                []corev1.Taint    `json:"taints,omitempty"`
 		KubeletExtraArgs      map[string]string `json:"kubeletExtraArgs,omitempty"`
 		IgnorePreflightErrors []string          `json:"ignorePreflightErrors,omitempty"`
-		ImagePullPolicy       string            `json:"imagePullPolicy,omitempty"`
 	}{
 		Name:                  n.Name,
 		CRISocket:             n.CRISocket,
 		Taints:                n.Taints,
 		KubeletExtraArgs:      n.KubeletExtraArgs,
 		IgnorePreflightErrors: n.IgnorePreflightErrors,
-		ImagePullPolicy:       n.ImagePullPolicy,
 	})
 }
 
diff --git a/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigs.yaml b/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigs.yaml
index 33a1b3ca5..6075efcf9 100644
--- a/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigs.yaml
+++ b/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: kubeadmconfigs.bootstrap.cluster.x-k8s.io
 spec:
@@ -2598,18 +2598,6 @@ spec:
                         items:
                           type: string
                         type: array
-                      imagePullPolicy:
-                        default: IfNotPresent
-                        description: ImagePullPolicy specifies the policy for image
-                          pulling during kubeadm "init" and "join" operations. The
-                          value of this field must be one of "Always", "IfNotPresent"
-                          or "Never". Defaults to "IfNotPresent". This can be used
-                          only with Kubernetes version equal to 1.22 and later.
-                        enum:
-                        - Always
-                        - IfNotPresent
-                        - Never
-                        type: string
                       kubeletExtraArgs:
                         additionalProperties:
                           type: string
@@ -2821,18 +2809,6 @@ spec:
                         items:
                           type: string
                         type: array
-                      imagePullPolicy:
-                        default: IfNotPresent
-                        description: ImagePullPolicy specifies the policy for image
-                          pulling during kubeadm "init" and "join" operations. The
-                          value of this field must be one of "Always", "IfNotPresent"
-                          or "Never". Defaults to "IfNotPresent". This can be used
-                          only with Kubernetes version equal to 1.22 and later.
-                        enum:
-                        - Always
-                        - IfNotPresent
-                        - Never
-                        type: string
                       kubeletExtraArgs:
                         additionalProperties:
                           type: string
diff --git a/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigtemplates.yaml b/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigtemplates.yaml
index 7eafff7b1..b2737f59b 100644
--- a/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigtemplates.yaml
+++ b/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigtemplates.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: kubeadmconfigtemplates.bootstrap.cluster.x-k8s.io
 spec:
@@ -2626,19 +2626,6 @@ spec:
                                 items:
                                   type: string
                                 type: array
-                              imagePullPolicy:
-                                default: IfNotPresent
-                                description: ImagePullPolicy specifies the policy
-                                  for image pulling during kubeadm "init" and "join"
-                                  operations. The value of this field must be one
-                                  of "Always", "IfNotPresent" or "Never". Defaults
-                                  to "IfNotPresent". This can be used only with Kubernetes
-                                  version equal to 1.22 and later.
-                                enum:
-                                - Always
-                                - IfNotPresent
-                                - Never
-                                type: string
                               kubeletExtraArgs:
                                 additionalProperties:
                                   type: string
@@ -2865,19 +2852,6 @@ spec:
                                 items:
                                   type: string
                                 type: array
-                              imagePullPolicy:
-                                default: IfNotPresent
-                                description: ImagePullPolicy specifies the policy
-                                  for image pulling during kubeadm "init" and "join"
-                                  operations. The value of this field must be one
-                                  of "Always", "IfNotPresent" or "Never". Defaults
-                                  to "IfNotPresent". This can be used only with Kubernetes
-                                  version equal to 1.22 and later.
-                                enum:
-                                - Always
-                                - IfNotPresent
-                                - Never
-                                type: string
                               kubeletExtraArgs:
                                 additionalProperties:
                                   type: string
diff --git a/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go b/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go
index e12305a9c..e8ebe12a5 100644
--- a/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go
+++ b/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go
@@ -368,7 +368,7 @@ func (r *KubeadmConfigReconciler) handleClusterNotInitialized(ctx context.Contex
 
 	// if the machine has not ClusterConfiguration and InitConfiguration, requeue
 	if scope.Config.Spec.InitConfiguration == nil && scope.Config.Spec.ClusterConfiguration == nil {
-		scope.Info("Control plane is not ready, requeuing joining control planes until ready.")
+		scope.Info("Control plane is not ready, requeing joining control planes until ready.")
 		return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
 	}
 
@@ -381,7 +381,7 @@ func (r *KubeadmConfigReconciler) handleClusterNotInitialized(ctx context.Contex
 	// as control plane get processed here
 	// if not the first, requeue
 	if !r.KubeadmInitLock.Lock(ctx, scope.Cluster, machine) {
-		scope.Info("A control plane is already being initialized, requeuing until control plane is ready")
+		scope.Info("A control plane is already being initialized, requeing until control plane is ready")
 		return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
 	}
 
diff --git a/bootstrap/kubeadm/types/upstreamv1beta1/zz_generated.conversion.go b/bootstrap/kubeadm/types/upstreamv1beta1/zz_generated.conversion.go
index 0497d927b..b340245f6 100644
--- a/bootstrap/kubeadm/types/upstreamv1beta1/zz_generated.conversion.go
+++ b/bootstrap/kubeadm/types/upstreamv1beta1/zz_generated.conversion.go
@@ -806,6 +806,5 @@ func autoConvert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta1_NodeRegistra
 	out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
 	out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
 	// WARNING: in.IgnorePreflightErrors requires manual conversion: does not exist in peer-type
-	// WARNING: in.ImagePullPolicy requires manual conversion: does not exist in peer-type
 	return nil
 }
diff --git a/bootstrap/kubeadm/types/upstreamv1beta2/conversion.go b/bootstrap/kubeadm/types/upstreamv1beta2/conversion.go
index fc95ca21d..efbb99b7e 100644
--- a/bootstrap/kubeadm/types/upstreamv1beta2/conversion.go
+++ b/bootstrap/kubeadm/types/upstreamv1beta2/conversion.go
@@ -92,9 +92,3 @@ func Convert_v1beta1_JoinConfiguration_To_upstreamv1beta2_JoinConfiguration(in *
 	// JoinConfiguration.Patches does not exist in kubeadm v1beta2 API
 	return autoConvert_v1beta1_JoinConfiguration_To_upstreamv1beta2_JoinConfiguration(in, out, s)
 }
-
-func Convert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta2_NodeRegistrationOptions(in *bootstrapv1.NodeRegistrationOptions, out *NodeRegistrationOptions, s apimachineryconversion.Scope) error {
-	// NodeRegistrationOptions.ImagePullPolicy does not exit in
-	// kubeadm v1beta2 API.
-	return autoConvert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta2_NodeRegistrationOptions(in, out, s)
-}
diff --git a/bootstrap/kubeadm/types/upstreamv1beta2/zz_generated.conversion.go b/bootstrap/kubeadm/types/upstreamv1beta2/zz_generated.conversion.go
index 9a40da3b2..5000842ff 100644
--- a/bootstrap/kubeadm/types/upstreamv1beta2/zz_generated.conversion.go
+++ b/bootstrap/kubeadm/types/upstreamv1beta2/zz_generated.conversion.go
@@ -213,6 +213,11 @@ func RegisterConversions(s *runtime.Scheme) error {
 	}); err != nil {
 		return err
 	}
+	if err := s.AddGeneratedConversionFunc((*v1beta1.NodeRegistrationOptions)(nil), (*NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta2_NodeRegistrationOptions(a.(*v1beta1.NodeRegistrationOptions), b.(*NodeRegistrationOptions), scope)
+	}); err != nil {
+		return err
+	}
 	if err := s.AddConversionFunc((*ClusterConfiguration)(nil), (*v1beta1.ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
 		return Convert_upstreamv1beta2_ClusterConfiguration_To_v1beta1_ClusterConfiguration(a.(*ClusterConfiguration), b.(*v1beta1.ClusterConfiguration), scope)
 	}); err != nil {
@@ -243,11 +248,6 @@ func RegisterConversions(s *runtime.Scheme) error {
 	}); err != nil {
 		return err
 	}
-	if err := s.AddConversionFunc((*v1beta1.NodeRegistrationOptions)(nil), (*NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
-		return Convert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta2_NodeRegistrationOptions(a.(*v1beta1.NodeRegistrationOptions), b.(*NodeRegistrationOptions), scope)
-	}); err != nil {
-		return err
-	}
 	return nil
 }
 
@@ -815,6 +815,10 @@ func autoConvert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta2_NodeRegistra
 	out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
 	out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
 	out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors))
-	// WARNING: in.ImagePullPolicy requires manual conversion: does not exist in peer-type
 	return nil
 }
+
+// Convert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta2_NodeRegistrationOptions is an autogenerated conversion function.
+func Convert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta2_NodeRegistrationOptions(in *v1beta1.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error {
+	return autoConvert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta2_NodeRegistrationOptions(in, out, s)
+}
diff --git a/bootstrap/kubeadm/types/upstreamv1beta3/types.go b/bootstrap/kubeadm/types/upstreamv1beta3/types.go
index abc993a88..1959b8039 100644
--- a/bootstrap/kubeadm/types/upstreamv1beta3/types.go
+++ b/bootstrap/kubeadm/types/upstreamv1beta3/types.go
@@ -225,13 +225,6 @@ type NodeRegistrationOptions struct {
 	// IgnorePreflightErrors provides a slice of pre-flight errors to be ignored when the current node is registered.
 	// +optional
 	IgnorePreflightErrors []string `json:"ignorePreflightErrors,omitempty"`
-
-	// ImagePullPolicy specifies the policy for image pulling
-	// during kubeadm "init" and "join" operations. The value of
-	// this field must be one of "Always", "IfNotPresent" or
-	// "Never". Defaults to "IfNotPresent".
-	// +optional
-	ImagePullPolicy string `json:"imagePullPolicy,omitempty"`
 }
 
 // Networking contains elements describing cluster's networking configuration.
diff --git a/bootstrap/kubeadm/types/upstreamv1beta3/zz_generated.conversion.go b/bootstrap/kubeadm/types/upstreamv1beta3/zz_generated.conversion.go
index d849616cb..19f5bd3a6 100644
--- a/bootstrap/kubeadm/types/upstreamv1beta3/zz_generated.conversion.go
+++ b/bootstrap/kubeadm/types/upstreamv1beta3/zz_generated.conversion.go
@@ -798,7 +798,6 @@ func autoConvert_upstreamv1beta3_NodeRegistrationOptions_To_v1beta1_NodeRegistra
 	out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
 	out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
 	out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors))
-	out.ImagePullPolicy = in.ImagePullPolicy
 	return nil
 }
 
@@ -808,7 +807,6 @@ func autoConvert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta3_NodeRegistra
 	out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
 	out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
 	out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors))
-	out.ImagePullPolicy = in.ImagePullPolicy
 	return nil
 }
 
diff --git a/cmd/clusterctl/client/client.go b/cmd/clusterctl/client/client.go
index 05d229503..32d42dfac 100644
--- a/cmd/clusterctl/client/client.go
+++ b/cmd/clusterctl/client/client.go
@@ -79,13 +79,13 @@ type Client interface {
 // AlphaClient exposes the alpha features in clusterctl high-level client library.
 type AlphaClient interface {
 	// RolloutRestart provides rollout restart of cluster-api resources
-	RolloutRestart(options RolloutRestartOptions) error
+	RolloutRestart(options RolloutOptions) error
 	// RolloutPause provides rollout pause of cluster-api resources
-	RolloutPause(options RolloutPauseOptions) error
+	RolloutPause(options RolloutOptions) error
 	// RolloutResume provides rollout resume of paused cluster-api resources
-	RolloutResume(options RolloutResumeOptions) error
+	RolloutResume(options RolloutOptions) error
 	// RolloutUndo provides rollout rollback of cluster-api resources
-	RolloutUndo(options RolloutUndoOptions) error
+	RolloutUndo(options RolloutOptions) error
 	// TopologyPlan dry runs the topology reconciler
 	TopologyPlan(options TopologyPlanOptions) (*TopologyPlanOutput, error)
 }
diff --git a/cmd/clusterctl/client/rollout.go b/cmd/clusterctl/client/rollout.go
index c69ef2eda..2a932f82e 100644
--- a/cmd/clusterctl/client/rollout.go
+++ b/cmd/clusterctl/client/rollout.go
@@ -26,50 +26,8 @@ import (
 	"sigs.k8s.io/cluster-api/cmd/clusterctl/internal/util"
 )
 
-// RolloutRestartOptions carries the options supported by RolloutRestart.
-type RolloutRestartOptions struct {
-	// Kubeconfig defines the kubeconfig to use for accessing the management cluster. If empty,
-	// default rules for kubeconfig discovery will be used.
-	Kubeconfig Kubeconfig
-
-	// Resources for the rollout command
-	Resources []string
-
-	// Namespace where the resource(s) live. If unspecified, the namespace name will be inferred
-	// from the current configuration.
-	Namespace string
-}
-
-// RolloutPauseOptions carries the options supported by RolloutPause.
-type RolloutPauseOptions struct {
-	// Kubeconfig defines the kubeconfig to use for accessing the management cluster. If empty,
-	// default rules for kubeconfig discovery will be used.
-	Kubeconfig Kubeconfig
-
-	// Resources for the rollout command
-	Resources []string
-
-	// Namespace where the resource(s) live. If unspecified, the namespace name will be inferred
-	// from the current configuration.
-	Namespace string
-}
-
-// RolloutResumeOptions carries the options supported by RolloutResume.
-type RolloutResumeOptions struct {
-	// Kubeconfig defines the kubeconfig to use for accessing the management cluster. If empty,
-	// default rules for kubeconfig discovery will be used.
-	Kubeconfig Kubeconfig
-
-	// Resources for the rollout command
-	Resources []string
-
-	// Namespace where the resource(s) live. If unspecified, the namespace name will be inferred
-	// from the current configuration.
-	Namespace string
-}
-
-// RolloutUndoOptions carries the options supported by RolloutUndo.
-type RolloutUndoOptions struct {
+// RolloutOptions carries the base set of options supported by rollout command.
+type RolloutOptions struct {
 	// Kubeconfig defines the kubeconfig to use for accessing the management cluster. If empty,
 	// default rules for kubeconfig discovery will be used.
 	Kubeconfig Kubeconfig
@@ -82,15 +40,16 @@ type RolloutUndoOptions struct {
 	Namespace string
 
 	// Revision number to rollback to when issuing the undo command.
+	// Revision number of a specific revision when issuing the history command.
 	ToRevision int64
 }
 
-func (c *clusterctlClient) RolloutRestart(options RolloutRestartOptions) error {
+func (c *clusterctlClient) RolloutRestart(options RolloutOptions) error {
 	clusterClient, err := c.clusterClientFactory(ClusterClientFactoryInput{Kubeconfig: options.Kubeconfig})
 	if err != nil {
 		return err
 	}
-	objRefs, err := getObjectRefs(clusterClient, options.Namespace, options.Resources)
+	objRefs, err := getObjectRefs(clusterClient, options)
 	if err != nil {
 		return err
 	}
@@ -102,12 +61,12 @@ func (c *clusterctlClient) RolloutRestart(options RolloutRestartOptions) error {
 	return nil
 }
 
-func (c *clusterctlClient) RolloutPause(options RolloutPauseOptions) error {
+func (c *clusterctlClient) RolloutPause(options RolloutOptions) error {
 	clusterClient, err := c.clusterClientFactory(ClusterClientFactoryInput{Kubeconfig: options.Kubeconfig})
 	if err != nil {
 		return err
 	}
-	objRefs, err := getObjectRefs(clusterClient, options.Namespace, options.Resources)
+	objRefs, err := getObjectRefs(clusterClient, options)
 	if err != nil {
 		return err
 	}
@@ -119,12 +78,12 @@ func (c *clusterctlClient) RolloutPause(options RolloutPauseOptions) error {
 	return nil
 }
 
-func (c *clusterctlClient) RolloutResume(options RolloutResumeOptions) error {
+func (c *clusterctlClient) RolloutResume(options RolloutOptions) error {
 	clusterClient, err := c.clusterClientFactory(ClusterClientFactoryInput{Kubeconfig: options.Kubeconfig})
 	if err != nil {
 		return err
 	}
-	objRefs, err := getObjectRefs(clusterClient, options.Namespace, options.Resources)
+	objRefs, err := getObjectRefs(clusterClient, options)
 	if err != nil {
 		return err
 	}
@@ -136,12 +95,12 @@ func (c *clusterctlClient) RolloutResume(options RolloutResumeOptions) error {
 	return nil
 }
 
-func (c *clusterctlClient) RolloutUndo(options RolloutUndoOptions) error {
+func (c *clusterctlClient) RolloutUndo(options RolloutOptions) error {
 	clusterClient, err := c.clusterClientFactory(ClusterClientFactoryInput{Kubeconfig: options.Kubeconfig})
 	if err != nil {
 		return err
 	}
-	objRefs, err := getObjectRefs(clusterClient, options.Namespace, options.Resources)
+	objRefs, err := getObjectRefs(clusterClient, options)
 	if err != nil {
 		return err
 	}
@@ -153,21 +112,21 @@ func (c *clusterctlClient) RolloutUndo(options RolloutUndoOptions) error {
 	return nil
 }
 
-func getObjectRefs(clusterClient cluster.Client, namespace string, resources []string) ([]corev1.ObjectReference, error) {
+func getObjectRefs(clusterClient cluster.Client, options RolloutOptions) ([]corev1.ObjectReference, error) {
 	// If the option specifying the Namespace is empty, try to detect it.
-	if namespace == "" {
+	if options.Namespace == "" {
 		currentNamespace, err := clusterClient.Proxy().CurrentNamespace()
 		if err != nil {
 			return []corev1.ObjectReference{}, err
 		}
-		namespace = currentNamespace
+		options.Namespace = currentNamespace
 	}
 
-	if len(resources) == 0 {
+	if len(options.Resources) == 0 {
 		return []corev1.ObjectReference{}, fmt.Errorf("required resource not specified")
 	}
-	normalized := normalizeResources(resources)
-	objRefs, err := util.GetObjectReferences(namespace, normalized...)
+	normalized := normalizeResources(options.Resources)
+	objRefs, err := util.GetObjectReferences(options.Namespace, normalized...)
 	if err != nil {
 		return []corev1.ObjectReference{}, err
 	}
diff --git a/cmd/clusterctl/cmd/rollout/pause.go b/cmd/clusterctl/cmd/rollout/pause.go
index 8e29ed200..958fe494c 100644
--- a/cmd/clusterctl/cmd/rollout/pause.go
+++ b/cmd/clusterctl/cmd/rollout/pause.go
@@ -77,7 +77,7 @@ func runPause(cfgFile string, args []string) error {
 		return err
 	}
 
-	return c.RolloutPause(client.RolloutPauseOptions{
+	return c.RolloutPause(client.RolloutOptions{
 		Kubeconfig: client.Kubeconfig{Path: pauseOpt.kubeconfig, Context: pauseOpt.kubeconfigContext},
 		Namespace:  pauseOpt.namespace,
 		Resources:  pauseOpt.resources,
diff --git a/cmd/clusterctl/cmd/rollout/restart.go b/cmd/clusterctl/cmd/rollout/restart.go
index 7f46fac31..e6d85cc4c 100644
--- a/cmd/clusterctl/cmd/rollout/restart.go
+++ b/cmd/clusterctl/cmd/rollout/restart.go
@@ -76,7 +76,7 @@ func runRestart(cfgFile string, _ *cobra.Command, args []string) error {
 		return err
 	}
 
-	return c.RolloutRestart(client.RolloutRestartOptions{
+	return c.RolloutRestart(client.RolloutOptions{
 		Kubeconfig: client.Kubeconfig{Path: restartOpt.kubeconfig, Context: restartOpt.kubeconfigContext},
 		Namespace:  restartOpt.namespace,
 		Resources:  restartOpt.resources,
diff --git a/cmd/clusterctl/cmd/rollout/resume.go b/cmd/clusterctl/cmd/rollout/resume.go
index 07dc4bc1f..ee5c803c9 100644
--- a/cmd/clusterctl/cmd/rollout/resume.go
+++ b/cmd/clusterctl/cmd/rollout/resume.go
@@ -76,7 +76,7 @@ func runResume(cfgFile string, args []string) error {
 		return err
 	}
 
-	return c.RolloutResume(client.RolloutResumeOptions{
+	return c.RolloutResume(client.RolloutOptions{
 		Kubeconfig: client.Kubeconfig{Path: resumeOpt.kubeconfig, Context: resumeOpt.kubeconfigContext},
 		Namespace:  resumeOpt.namespace,
 		Resources:  resumeOpt.resources,
diff --git a/cmd/clusterctl/cmd/rollout/undo.go b/cmd/clusterctl/cmd/rollout/undo.go
index cfa660300..7e40c4bb7 100644
--- a/cmd/clusterctl/cmd/rollout/undo.go
+++ b/cmd/clusterctl/cmd/rollout/undo.go
@@ -76,7 +76,7 @@ func runUndo(cfgFile string, args []string) error {
 		return err
 	}
 
-	return c.RolloutUndo(client.RolloutUndoOptions{
+	return c.RolloutUndo(client.RolloutOptions{
 		Kubeconfig: client.Kubeconfig{Path: undoOpt.kubeconfig, Context: undoOpt.kubeconfigContext},
 		Namespace:  undoOpt.namespace,
 		Resources:  undoOpt.resources,
diff --git a/cmd/clusterctl/config/crd/bases/clusterctl.cluster.x-k8s.io_metadata.yaml b/cmd/clusterctl/config/crd/bases/clusterctl.cluster.x-k8s.io_metadata.yaml
index bfc784bdd..a7bc6faae 100644
--- a/cmd/clusterctl/config/crd/bases/clusterctl.cluster.x-k8s.io_metadata.yaml
+++ b/cmd/clusterctl/config/crd/bases/clusterctl.cluster.x-k8s.io_metadata.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: metadata.clusterctl.cluster.x-k8s.io
 spec:
diff --git a/cmd/clusterctl/config/crd/bases/clusterctl.cluster.x-k8s.io_providers.yaml b/cmd/clusterctl/config/crd/bases/clusterctl.cluster.x-k8s.io_providers.yaml
index 3d1917e23..ed30f3434 100644
--- a/cmd/clusterctl/config/crd/bases/clusterctl.cluster.x-k8s.io_providers.yaml
+++ b/cmd/clusterctl/config/crd/bases/clusterctl.cluster.x-k8s.io_providers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: providers.clusterctl.cluster.x-k8s.io
 spec:
diff --git a/cmd/clusterctl/config/manifest/clusterctl-api.yaml b/cmd/clusterctl/config/manifest/clusterctl-api.yaml
index 39f8b3b41..8625909e2 100644
--- a/cmd/clusterctl/config/manifest/clusterctl-api.yaml
+++ b/cmd/clusterctl/config/manifest/clusterctl-api.yaml
@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: providers.clusterctl.cluster.x-k8s.io
 spec:
diff --git a/config/crd/bases/addons.cluster.x-k8s.io_clusterresourcesetbindings.yaml b/config/crd/bases/addons.cluster.x-k8s.io_clusterresourcesetbindings.yaml
index 33ebf3760..d8f1629a0 100644
--- a/config/crd/bases/addons.cluster.x-k8s.io_clusterresourcesetbindings.yaml
+++ b/config/crd/bases/addons.cluster.x-k8s.io_clusterresourcesetbindings.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: clusterresourcesetbindings.addons.cluster.x-k8s.io
 spec:
diff --git a/config/crd/bases/addons.cluster.x-k8s.io_clusterresourcesets.yaml b/config/crd/bases/addons.cluster.x-k8s.io_clusterresourcesets.yaml
index c2ccab2d5..bfb0ec207 100644
--- a/config/crd/bases/addons.cluster.x-k8s.io_clusterresourcesets.yaml
+++ b/config/crd/bases/addons.cluster.x-k8s.io_clusterresourcesets.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: clusterresourcesets.addons.cluster.x-k8s.io
 spec:
diff --git a/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml b/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml
index a3084d5e2..b36946222 100644
--- a/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml
+++ b/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: clusterclasses.cluster.x-k8s.io
 spec:
diff --git a/config/crd/bases/cluster.x-k8s.io_clusters.yaml b/config/crd/bases/cluster.x-k8s.io_clusters.yaml
index 56d2f94bb..227e10093 100644
--- a/config/crd/bases/cluster.x-k8s.io_clusters.yaml
+++ b/config/crd/bases/cluster.x-k8s.io_clusters.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: clusters.cluster.x-k8s.io
 spec:
diff --git a/config/crd/bases/cluster.x-k8s.io_machinedeployments.yaml b/config/crd/bases/cluster.x-k8s.io_machinedeployments.yaml
index bfb949d4b..0db04ab50 100644
--- a/config/crd/bases/cluster.x-k8s.io_machinedeployments.yaml
+++ b/config/crd/bases/cluster.x-k8s.io_machinedeployments.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: machinedeployments.cluster.x-k8s.io
 spec:
diff --git a/config/crd/bases/cluster.x-k8s.io_machinehealthchecks.yaml b/config/crd/bases/cluster.x-k8s.io_machinehealthchecks.yaml
index f8b8494a5..99b6fdf54 100644
--- a/config/crd/bases/cluster.x-k8s.io_machinehealthchecks.yaml
+++ b/config/crd/bases/cluster.x-k8s.io_machinehealthchecks.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: machinehealthchecks.cluster.x-k8s.io
 spec:
diff --git a/config/crd/bases/cluster.x-k8s.io_machinepools.yaml b/config/crd/bases/cluster.x-k8s.io_machinepools.yaml
index ca3d38695..68e2d0d3a 100644
--- a/config/crd/bases/cluster.x-k8s.io_machinepools.yaml
+++ b/config/crd/bases/cluster.x-k8s.io_machinepools.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: machinepools.cluster.x-k8s.io
 spec:
diff --git a/config/crd/bases/cluster.x-k8s.io_machines.yaml b/config/crd/bases/cluster.x-k8s.io_machines.yaml
index e88a5220b..4fdd74ec3 100644
--- a/config/crd/bases/cluster.x-k8s.io_machines.yaml
+++ b/config/crd/bases/cluster.x-k8s.io_machines.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: machines.cluster.x-k8s.io
 spec:
diff --git a/config/crd/bases/cluster.x-k8s.io_machinesets.yaml b/config/crd/bases/cluster.x-k8s.io_machinesets.yaml
index 548010bff..bc02a0794 100644
--- a/config/crd/bases/cluster.x-k8s.io_machinesets.yaml
+++ b/config/crd/bases/cluster.x-k8s.io_machinesets.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: machinesets.cluster.x-k8s.io
 spec:
diff --git a/config/crd/bases/ipam.cluster.x-k8s.io_ipaddressclaims.yaml b/config/crd/bases/ipam.cluster.x-k8s.io_ipaddressclaims.yaml
index ce5a6e3e6..539dcfae4 100644
--- a/config/crd/bases/ipam.cluster.x-k8s.io_ipaddressclaims.yaml
+++ b/config/crd/bases/ipam.cluster.x-k8s.io_ipaddressclaims.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: ipaddressclaims.ipam.cluster.x-k8s.io
 spec:
diff --git a/config/crd/bases/ipam.cluster.x-k8s.io_ipaddresses.yaml b/config/crd/bases/ipam.cluster.x-k8s.io_ipaddresses.yaml
index d60ed805b..4587244d5 100644
--- a/config/crd/bases/ipam.cluster.x-k8s.io_ipaddresses.yaml
+++ b/config/crd/bases/ipam.cluster.x-k8s.io_ipaddresses.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: ipaddresses.ipam.cluster.x-k8s.io
 spec:
diff --git a/config/crd/bases/runtime.cluster.x-k8s.io_extensionconfigs.yaml b/config/crd/bases/runtime.cluster.x-k8s.io_extensionconfigs.yaml
index 8ca0e31d1..3b8de2eff 100644
--- a/config/crd/bases/runtime.cluster.x-k8s.io_extensionconfigs.yaml
+++ b/config/crd/bases/runtime.cluster.x-k8s.io_extensionconfigs.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: extensionconfigs.runtime.cluster.x-k8s.io
 spec:
diff --git a/controlplane/kubeadm/api/v1alpha3/conversion.go b/controlplane/kubeadm/api/v1alpha3/conversion.go
index 0061e6331..dd0b04c5e 100644
--- a/controlplane/kubeadm/api/v1alpha3/conversion.go
+++ b/controlplane/kubeadm/api/v1alpha3/conversion.go
@@ -85,20 +85,6 @@ func (src *KubeadmControlPlane) ConvertTo(dstRaw conversion.Hub) error {
 
 	dst.Spec.RolloutBefore = restored.Spec.RolloutBefore
 
-	if restored.Spec.KubeadmConfigSpec.JoinConfiguration != nil && restored.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy != "" {
-		if dst.Spec.KubeadmConfigSpec.JoinConfiguration == nil {
-			dst.Spec.KubeadmConfigSpec.JoinConfiguration = &bootstrapv1.JoinConfiguration{}
-		}
-		dst.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy
-	}
-
-	if restored.Spec.KubeadmConfigSpec.InitConfiguration != nil && restored.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy != "" {
-		if dst.Spec.KubeadmConfigSpec.InitConfiguration == nil {
-			dst.Spec.KubeadmConfigSpec.InitConfiguration = &bootstrapv1.InitConfiguration{}
-		}
-		dst.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy
-	}
-
 	return nil
 }
 
diff --git a/controlplane/kubeadm/api/v1alpha4/conversion.go b/controlplane/kubeadm/api/v1alpha4/conversion.go
index 9fae7f390..9eaebf63b 100644
--- a/controlplane/kubeadm/api/v1alpha4/conversion.go
+++ b/controlplane/kubeadm/api/v1alpha4/conversion.go
@@ -70,20 +70,6 @@ func (src *KubeadmControlPlane) ConvertTo(dstRaw conversion.Hub) error {
 	dst.Spec.RolloutBefore = restored.Spec.RolloutBefore
 	dst.Spec.MachineTemplate.NodeVolumeDetachTimeout = restored.Spec.MachineTemplate.NodeVolumeDetachTimeout
 
-	if restored.Spec.KubeadmConfigSpec.JoinConfiguration != nil && restored.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy != "" {
-		if dst.Spec.KubeadmConfigSpec.JoinConfiguration == nil {
-			dst.Spec.KubeadmConfigSpec.JoinConfiguration = &bootstrapv1.JoinConfiguration{}
-		}
-		dst.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy
-	}
-
-	if restored.Spec.KubeadmConfigSpec.InitConfiguration != nil && restored.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy != "" {
-		if dst.Spec.KubeadmConfigSpec.InitConfiguration == nil {
-			dst.Spec.KubeadmConfigSpec.InitConfiguration = &bootstrapv1.InitConfiguration{}
-		}
-		dst.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy
-	}
-
 	return nil
 }
 
@@ -159,20 +145,6 @@ func (src *KubeadmControlPlaneTemplate) ConvertTo(dstRaw conversion.Hub) error {
 
 	dst.Spec.Template.Spec.RolloutBefore = restored.Spec.Template.Spec.RolloutBefore
 
-	if restored.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration != nil && restored.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy != "" {
-		if dst.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration == nil {
-			dst.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration = &bootstrapv1.JoinConfiguration{}
-		}
-		dst.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy
-	}
-
-	if restored.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration != nil && restored.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy != "" {
-		if dst.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration == nil {
-			dst.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration = &bootstrapv1.InitConfiguration{}
-		}
-		dst.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy
-	}
-
 	return nil
 }
 
diff --git a/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanes.yaml b/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanes.yaml
index da79fa45d..ed855c19a 100644
--- a/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanes.yaml
+++ b/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanes.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: kubeadmcontrolplanes.controlplane.cluster.x-k8s.io
 spec:
@@ -3070,19 +3070,6 @@ spec:
                             items:
                               type: string
                             type: array
-                          imagePullPolicy:
-                            default: IfNotPresent
-                            description: ImagePullPolicy specifies the policy for
-                              image pulling during kubeadm "init" and "join" operations.
-                              The value of this field must be one of "Always", "IfNotPresent"
-                              or "Never". Defaults to "IfNotPresent". This can be
-                              used only with Kubernetes version equal to 1.22 and
-                              later.
-                            enum:
-                            - Always
-                            - IfNotPresent
-                            - Never
-                            type: string
                           kubeletExtraArgs:
                             additionalProperties:
                               type: string
@@ -3303,19 +3290,6 @@ spec:
                             items:
                               type: string
                             type: array
-                          imagePullPolicy:
-                            default: IfNotPresent
-                            description: ImagePullPolicy specifies the policy for
-                              image pulling during kubeadm "init" and "join" operations.
-                              The value of this field must be one of "Always", "IfNotPresent"
-                              or "Never". Defaults to "IfNotPresent". This can be
-                              used only with Kubernetes version equal to 1.22 and
-                              later.
-                            enum:
-                            - Always
-                            - IfNotPresent
-                            - Never
-                            type: string
                           kubeletExtraArgs:
                             additionalProperties:
                               type: string
diff --git a/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanetemplates.yaml b/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanetemplates.yaml
index a70a55892..668c5f5be 100644
--- a/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanetemplates.yaml
+++ b/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanetemplates.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: kubeadmcontrolplanetemplates.controlplane.cluster.x-k8s.io
 spec:
@@ -1860,20 +1860,6 @@ spec:
                                     items:
                                       type: string
                                     type: array
-                                  imagePullPolicy:
-                                    default: IfNotPresent
-                                    description: ImagePullPolicy specifies the policy
-                                      for image pulling during kubeadm "init" and
-                                      "join" operations. The value of this field must
-                                      be one of "Always", "IfNotPresent" or "Never".
-                                      Defaults to "IfNotPresent". This can be used
-                                      only with Kubernetes version equal to 1.22 and
-                                      later.
-                                    enum:
-                                    - Always
-                                    - IfNotPresent
-                                    - Never
-                                    type: string
                                   kubeletExtraArgs:
                                     additionalProperties:
                                       type: string
@@ -2110,20 +2096,6 @@ spec:
                                     items:
                                       type: string
                                     type: array
-                                  imagePullPolicy:
-                                    default: IfNotPresent
-                                    description: ImagePullPolicy specifies the policy
-                                      for image pulling during kubeadm "init" and
-                                      "join" operations. The value of this field must
-                                      be one of "Always", "IfNotPresent" or "Never".
-                                      Defaults to "IfNotPresent". This can be used
-                                      only with Kubernetes version equal to 1.22 and
-                                      later.
-                                    enum:
-                                    - Always
-                                    - IfNotPresent
-                                    - Never
-                                    type: string
                                   kubeletExtraArgs:
                                     additionalProperties:
                                       type: string
diff --git a/controlplane/kubeadm/internal/controllers/controller.go b/controlplane/kubeadm/internal/controllers/controller.go
index 42be67d9e..c29b46fb3 100644
--- a/controlplane/kubeadm/internal/controllers/controller.go
+++ b/controlplane/kubeadm/internal/controllers/controller.go
@@ -211,7 +211,7 @@ func (r *KubeadmControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.
 		// Requeue if the reconcile failed because the ClusterCacheTracker was locked for
 		// the current cluster because of concurrent access.
 		if errors.Is(err, remote.ErrClusterLocked) {
-			log.V(5).Info("Requeuing because another worker has the lock on the ClusterCacheTracker")
+			log.V(5).Info("Requeueing because another worker has the lock on the ClusterCacheTracker")
 			return ctrl.Result{Requeue: true}, nil
 		}
 		return res, err
@@ -222,7 +222,7 @@ func (r *KubeadmControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.
 	// Requeue if the reconcile failed because the ClusterCacheTracker was locked for
 	// the current cluster because of concurrent access.
 	if errors.Is(err, remote.ErrClusterLocked) {
-		log.V(5).Info("Requeuing because another worker has the lock on the ClusterCacheTracker")
+		log.V(5).Info("Requeueing because another worker has the lock on the ClusterCacheTracker")
 		return ctrl.Result{Requeue: true}, nil
 	}
 	return res, err
diff --git a/docs/book/src/developer/providers/v1.3-to-v1.4.md b/docs/book/src/developer/providers/v1.3-to-v1.4.md
index ef339f3ec..c1125535f 100644
--- a/docs/book/src/developer/providers/v1.3-to-v1.4.md
+++ b/docs/book/src/developer/providers/v1.3-to-v1.4.md
@@ -36,20 +36,6 @@ maintainers of providers and consumers of our Go API.
 
 - `Backup(options BackupOptions) error` in the Client interface has been removed.
 - `Restore(options RestoreOptions) error` in the Client interface has been removed.
-- `cmd/clusterctl/client.RolloutOptions` has been removed, `RolloutRestartOptions`, `RolloutPauseOptions` , `RolloutResumeOptions`, and `RolloutUndoOptions` have been added instead.
-- Annotation constant `DisableMachineCreate` has been updated to `DisableMachineCreateAnnotation`
-- Below Label constant have been updated
-  - `ClusterLabelName` to `ClusterNameLabel`
-  - `ClusterTopologyMachineDeploymentLabelName` to `ClusterTopologyMachineDeploymentNameLabel`
-  - `ProviderLabelName` to `ProviderNameLabel`
-  - `MachineControlPlaneLabelName` to `MachineControlPlaneLabel`
-  - `MachineSetLabelName` to `MachineSetNameLabel`
-  - `MachineDeploymentLabelName` to `MachineDeploymentNameLabel`
-- Below Condition and Reason constants have been updated
-  - `ExternalRemediationTemplateAvailable` to `ExternalRemediationTemplateAvailableCondition`
-  - `ExternalRemediationTemplateNotFound` to `ExternalRemediationTemplateNotFoundReason`
-  - `ExternalRemediationRequestAvailable` to  `ExternalRemediationRequestAvailableCondition`
-  - `ExternalRemediationRequestCreationFailed` to `ExternalRemediationRequestCreationFailedReason`
 
 ### Other
 
diff --git a/docs/proposals/20191017-kubeadm-based-control-plane.md b/docs/proposals/20191017-kubeadm-based-control-plane.md
index 3bc2f35f1..487911a5e 100644
--- a/docs/proposals/20191017-kubeadm-based-control-plane.md
+++ b/docs/proposals/20191017-kubeadm-based-control-plane.md
@@ -479,8 +479,7 @@ When `MaxSurge` is set to 0 the rollout algorithm is as follows:
     replacement for the previous machine is not yet created. 
   - The cluster MUST have no machines with a deletion timestamp. This rule prevents KCP taking actions while the cluster is in a transitional state.
   - Remediation MUST preserve etcd quorum. This rule ensures that we will not remove a member that would result in etcd
-    losing a majority of members and thus become unable to field new requests (note: this rule applies only to CP already
-    initialized and with managed etcd)
+    losing a majority of members and thus become unable to field new requests (note: this rule applies only to CP with at least replicas)
 
 - Additionally following opt-in safeguards will be put in place:
   - If we are remediating the same machine (delete, re-create, replacement machine gets unhealthy), it will be possible
diff --git a/exp/addons/internal/controllers/clusterresourceset_controller.go b/exp/addons/internal/controllers/clusterresourceset_controller.go
index 6d28c3047..513609224 100644
--- a/exp/addons/internal/controllers/clusterresourceset_controller.go
+++ b/exp/addons/internal/controllers/clusterresourceset_controller.go
@@ -155,7 +155,7 @@ func (r *ClusterResourceSetReconciler) Reconcile(ctx context.Context, req ctrl.R
 			// Requeue if the reconcile failed because the ClusterCacheTracker was locked for
 			// the current cluster because of concurrent access.
 			if errors.Is(err, remote.ErrClusterLocked) {
-				log.V(5).Info("Requeuing because another worker has the lock on the ClusterCacheTracker")
+				log.V(5).Info("Requeueing because another worker has the lock on the ClusterCacheTracker")
 				return ctrl.Result{Requeue: true}, nil
 			}
 			return ctrl.Result{}, err
diff --git a/go.mod b/go.mod
index 920fc50b8..1cde8a224 100644
--- a/go.mod
+++ b/go.mod
@@ -20,8 +20,8 @@ require (
 	github.com/google/go-github/v48 v48.2.0
 	github.com/google/gofuzz v1.2.0
 	github.com/mattn/go-runewidth v0.0.14 // indirect
-	github.com/onsi/ginkgo/v2 v2.8.0
-	github.com/onsi/gomega v1.26.0
+	github.com/onsi/ginkgo/v2 v2.7.0
+	github.com/onsi/gomega v1.25.0
 	github.com/pkg/errors v0.9.1
 	github.com/spf13/cobra v1.6.1
 	github.com/spf13/pflag v1.0.5
diff --git a/go.sum b/go.sum
index 981a9948a..d695222e5 100644
--- a/go.sum
+++ b/go.sum
@@ -411,10 +411,10 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW
 github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
 github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
 github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
-github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI=
-github.com/onsi/ginkgo/v2 v2.8.0/go.mod h1:6JsQiECmxCa3V5st74AL/AmsV482EDdVrGaVW6z3oYU=
-github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q=
-github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
+github.com/onsi/ginkgo/v2 v2.7.0 h1:/XxtEV3I3Eif/HobnVx9YmJgk8ENdRsuUmM+fLCFNow=
+github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo=
+github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y=
+github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
 github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
diff --git a/hack/ensure-go.sh b/hack/ensure-go.sh
index c2288c9ec..3c84f2568 100755
--- a/hack/ensure-go.sh
+++ b/hack/ensure-go.sh
@@ -22,6 +22,9 @@ if [[ "${TRACE-0}" == "1" ]]; then
     set -o xtrace
 fi
 
+# shellcheck source=./hack/utils.sh
+source "$(dirname "${BASH_SOURCE[0]}")/utils.sh"
+
 # Ensure the go tool exists and is a viable version.
 verify_go_version() {
   if [[ -z "$(command -v go)" ]]; then
@@ -46,7 +49,9 @@ EOF
   fi
 }
 
+
 verify_go_version
+verify_gopath_bin
 
 # Explicitly opt into go modules, even though we're inside a GOPATH directory
 export GO111MODULE=on
diff --git a/hack/ensure-kind.sh b/hack/ensure-kind.sh
index dc3cd008f..123dd8841 100755
--- a/hack/ensure-kind.sh
+++ b/hack/ensure-kind.sh
@@ -22,6 +22,9 @@ if [[ "${TRACE-0}" == "1" ]]; then
     set -o xtrace
 fi
 
+# shellcheck source=./hack/utils.sh
+source "$(dirname "${BASH_SOURCE[0]}")/utils.sh"
+
 GOPATH_BIN="$(go env GOPATH)/bin"
 MINIMUM_KIND_VERSION=v0.17.0
 goarch="$(go env GOARCH)"
@@ -39,6 +42,7 @@ verify_kind_version() {
       fi
       curl -sLo "${GOPATH_BIN}/kind" "https://github.com/kubernetes-sigs/kind/releases/download/${MINIMUM_KIND_VERSION}/kind-${goos}-${goarch}"
       chmod +x "${GOPATH_BIN}/kind"
+      verify_gopath_bin
     else
       echo "Missing required binary in path: kind"
       return 2
diff --git a/hack/ensure-kubectl.sh b/hack/ensure-kubectl.sh
index b1a031c52..86b318461 100755
--- a/hack/ensure-kubectl.sh
+++ b/hack/ensure-kubectl.sh
@@ -22,6 +22,10 @@ if [[ "${TRACE-0}" == "1" ]]; then
     set -o xtrace
 fi
 
+
+# shellcheck source=./hack/utils.sh
+source "$(dirname "${BASH_SOURCE[0]}")/utils.sh"
+
 GOPATH_BIN="$(go env GOPATH)/bin/"
 MINIMUM_KUBECTL_VERSION=v1.19.0
 goarch="$(go env GOARCH)"
@@ -39,6 +43,7 @@ verify_kubectl_version() {
       echo 'kubectl not found, installing'
       curl -sLo "${GOPATH_BIN}/kubectl" "https://dl.k8s.io/release/${MINIMUM_KUBECTL_VERSION}/bin/${goos}/${goarch}/kubectl"
       chmod +x "${GOPATH_BIN}/kubectl"
+      verify_gopath_bin
     else
       echo "Missing required binary in path: kubectl"
       return 2
diff --git a/hack/tools/go.mod b/hack/tools/go.mod
index 1a29b5bd4..3453bfe06 100644
--- a/hack/tools/go.mod
+++ b/hack/tools/go.mod
@@ -108,7 +108,7 @@ require (
 	github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
 	github.com/morikuni/aec v1.0.0 // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
-	github.com/onsi/gomega v1.26.0 // indirect
+	github.com/onsi/gomega v1.25.0 // indirect
 	github.com/opencontainers/go-digest v1.0.0 // indirect
 	github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
 	github.com/pelletier/go-toml/v2 v2.0.6 // indirect
diff --git a/hack/tools/go.sum b/hack/tools/go.sum
index 3baf09f5d..826f0569f 100644
--- a/hack/tools/go.sum
+++ b/hack/tools/go.sum
@@ -424,9 +424,9 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW
 github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
 github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
 github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
-github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI=
-github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q=
-github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
+github.com/onsi/ginkgo/v2 v2.7.0 h1:/XxtEV3I3Eif/HobnVx9YmJgk8ENdRsuUmM+fLCFNow=
+github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y=
+github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
 github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
 github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec=
diff --git a/hack/utils.sh b/hack/utils.sh
index 38f792c3a..678d37e85 100644
--- a/hack/utils.sh
+++ b/hack/utils.sh
@@ -32,3 +32,18 @@ get_capd_root_path() {
 cd_capd_root_path() {
     cd "$(get_capd_root_path)" || exit
 }
+
+# ensure GOPATH/bin is in PATH as we may install binaries to that directory in
+# other ensure-* scripts, and expect them to be found in PATH later on
+verify_gopath_bin() {
+    local gopath_bin
+
+    gopath_bin="$(go env GOPATH)/bin"
+    if ! printenv PATH | grep -q "${gopath_bin}"; then
+        cat <<EOF
+error: \$GOPATH/bin=${gopath_bin} is not in your PATH.
+See https://go.dev/doc/gopath_code for more instructions.
+EOF
+        return 2
+    fi
+}
diff --git a/internal/controllers/machine/machine_controller.go b/internal/controllers/machine/machine_controller.go
index fc7159c98..00c302f17 100644
--- a/internal/controllers/machine/machine_controller.go
+++ b/internal/controllers/machine/machine_controller.go
@@ -216,7 +216,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re
 		// Requeue if the reconcile failed because the ClusterCacheTracker was locked for
 		// the current cluster because of concurrent access.
 		if errors.Is(err, remote.ErrClusterLocked) {
-			log.V(5).Info("Requeuing because another worker has the lock on the ClusterCacheTracker")
+			log.V(5).Info("Requeueing because another worker has the lock on the ClusterCacheTracker")
 			return ctrl.Result{Requeue: true}, nil
 		}
 		return res, err
@@ -227,7 +227,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re
 	// Requeue if the reconcile failed because the ClusterCacheTracker was locked for
 	// the current cluster because of concurrent access.
 	if errors.Is(err, remote.ErrClusterLocked) {
-		log.V(5).Info("Requeuing because another worker has the lock on the ClusterCacheTracker")
+		log.V(5).Info("Requeueing because another worker has the lock on the ClusterCacheTracker")
 		return ctrl.Result{Requeue: true}, nil
 	}
 	return res, err
diff --git a/internal/controllers/machine/machine_controller_phases.go b/internal/controllers/machine/machine_controller_phases.go
index ec4d66b17..db961bd4e 100644
--- a/internal/controllers/machine/machine_controller_phases.go
+++ b/internal/controllers/machine/machine_controller_phases.go
@@ -98,7 +98,7 @@ func (r *Reconciler) reconcileExternal(ctx context.Context, cluster *clusterv1.C
 	obj, err := external.Get(ctx, r.Client, ref, m.Namespace)
 	if err != nil {
 		if apierrors.IsNotFound(errors.Cause(err)) {
-			log.Info("could not find external ref, requeuing", ref.Kind, klog.KRef(m.Namespace, ref.Name))
+			log.Info("could not find external ref, requeueing", ref.Kind, klog.KRef(m.Namespace, ref.Name))
 			return external.ReconcileOutput{RequeueAfter: externalReadyWait}, nil
 		}
 		return external.ReconcileOutput{}, err
@@ -251,7 +251,7 @@ func (r *Reconciler) reconcileInfrastructure(ctx context.Context, cluster *clust
 			m.Status.FailureReason = capierrors.MachineStatusErrorPtr(capierrors.InvalidConfigurationMachineError)
 			m.Status.FailureMessage = pointer.String(fmt.Sprintf("Machine infrastructure resource %v with name %q has been deleted after being ready",
 				m.Spec.InfrastructureRef.GroupVersionKind(), m.Spec.InfrastructureRef.Name))
-			return ctrl.Result{}, errors.Errorf("could not find %v %q for Machine %q in namespace %q, requeuing", m.Spec.InfrastructureRef.GroupVersionKind().String(), m.Spec.InfrastructureRef.Name, m.Name, m.Namespace)
+			return ctrl.Result{}, errors.Errorf("could not find %v %q for Machine %q in namespace %q, requeueing", m.Spec.InfrastructureRef.GroupVersionKind().String(), m.Spec.InfrastructureRef.Name, m.Name, m.Namespace)
 		}
 		return ctrl.Result{RequeueAfter: infraReconcileResult.RequeueAfter}, nil
 	}
diff --git a/internal/controllers/machinehealthcheck/machinehealthcheck_controller.go b/internal/controllers/machinehealthcheck/machinehealthcheck_controller.go
index f2b98f34b..14117c3c1 100644
--- a/internal/controllers/machinehealthcheck/machinehealthcheck_controller.go
+++ b/internal/controllers/machinehealthcheck/machinehealthcheck_controller.go
@@ -177,7 +177,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re
 		// Requeue if the reconcile failed because the ClusterCacheTracker was locked for
 		// the current cluster because of concurrent access.
 		if errors.Is(err, remote.ErrClusterLocked) {
-			log.V(5).Info("Requeuing because another worker has the lock on the ClusterCacheTracker")
+			log.V(5).Info("Requeueing because another worker has the lock on the ClusterCacheTracker")
 			return ctrl.Result{Requeue: true}, nil
 		}
 		log.Error(err, "Failed to reconcile MachineHealthCheck")
@@ -322,7 +322,7 @@ func (r *Reconciler) reconcile(ctx context.Context, logger logr.Logger, cluster
 
 	// handle update errors
 	if len(errList) > 0 {
-		logger.V(3).Info("Error(s) marking machine, requeuing")
+		logger.V(3).Info("Error(s) marking machine, requeueing")
 		return reconcile.Result{}, kerrors.NewAggregate(errList)
 	}
 
diff --git a/internal/controllers/machineset/machineset_controller.go b/internal/controllers/machineset/machineset_controller.go
index 08499025b..01dcde08e 100644
--- a/internal/controllers/machineset/machineset_controller.go
+++ b/internal/controllers/machineset/machineset_controller.go
@@ -176,7 +176,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re
 		// Requeue if the reconcile failed because the ClusterCacheTracker was locked for
 		// the current cluster because of concurrent access.
 		if errors.Is(err, remote.ErrClusterLocked) {
-			log.V(5).Info("Requeuing because another worker has the lock on the ClusterCacheTracker")
+			log.V(5).Info("Requeueing because another worker has the lock on the ClusterCacheTracker")
 			return ctrl.Result{Requeue: true}, nil
 		}
 		log.Error(err, "Failed to reconcile MachineSet")


Test patch:
diff --git a/bootstrap/kubeadm/types/upstreamv1beta1/conversion_test.go b/bootstrap/kubeadm/types/upstreamv1beta1/conversion_test.go
index 13d1f1831..80a8b3232 100644
--- a/bootstrap/kubeadm/types/upstreamv1beta1/conversion_test.go
+++ b/bootstrap/kubeadm/types/upstreamv1beta1/conversion_test.go
@@ -88,11 +88,6 @@ func kubeadmNodeRegistrationOptionsFuzzer(obj *bootstrapv1.NodeRegistrationOptio
 	// NodeRegistrationOptions.IgnorePreflightErrors does not exist in kubeadm v1beta1 API, so setting it to nil in order to avoid
 	// v1alpha4 --> v1beta1 -> v1alpha4 round trip errors.
 	obj.IgnorePreflightErrors = nil
-
-	// NodeRegistrationOptions.ImagePullPolicy does not exist in
-	// kubeadm v1beta1 API, so setting it to empty in order to
-	// avoid round trip errors.
-	obj.ImagePullPolicy = ""
 }
 
 func kubeadmInitConfigurationFuzzer(obj *bootstrapv1.InitConfiguration, c fuzz.Continue) {
diff --git a/bootstrap/kubeadm/types/upstreamv1beta2/conversion_test.go b/bootstrap/kubeadm/types/upstreamv1beta2/conversion_test.go
index 9ad0feaa7..d5b72b1f7 100644
--- a/bootstrap/kubeadm/types/upstreamv1beta2/conversion_test.go
+++ b/bootstrap/kubeadm/types/upstreamv1beta2/conversion_test.go
@@ -66,7 +66,6 @@ func fuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} {
 		clusterConfigurationFuzzer,
 		kubeadmInitConfigurationFuzzer,
 		kubeadmJoinConfigurationFuzzer,
-		kubeadmNodeRegistrationOptionsFuzzer,
 	}
 }
 
@@ -121,12 +120,3 @@ func kubeadmJoinConfigurationFuzzer(obj *bootstrapv1.JoinConfiguration, c fuzz.C
 	// v1beta1 --> upstream v1beta2 -> v1beta1 round trip errors.
 	obj.SkipPhases = nil
 }
-
-func kubeadmNodeRegistrationOptionsFuzzer(obj *bootstrapv1.NodeRegistrationOptions, c fuzz.Continue) {
-	c.FuzzNoCustom(obj)
-
-	// NodeRegistrationOptions.ImagePullPolicy does not exist in
-	// kubeadm v1beta2 API, so setting it to empty in order to
-	// avoid round trip errors.
-	obj.ImagePullPolicy = ""
-}
diff --git a/cmd/clusterctl/client/client_test.go b/cmd/clusterctl/client/client_test.go
index b1374b805..486384a2e 100644
--- a/cmd/clusterctl/client/client_test.go
+++ b/cmd/clusterctl/client/client_test.go
@@ -124,7 +124,7 @@ func (f fakeClient) ProcessYAML(options ProcessYAMLOptions) (YamlPrinter, error)
 	return f.internalClient.ProcessYAML(options)
 }
 
-func (f fakeClient) RolloutRestart(options RolloutRestartOptions) error {
+func (f fakeClient) RolloutRestart(options RolloutOptions) error {
 	return f.internalClient.RolloutRestart(options)
 }
 
@@ -132,15 +132,15 @@ func (f fakeClient) DescribeCluster(options DescribeClusterOptions) (*tree.Objec
 	return f.internalClient.DescribeCluster(options)
 }
 
-func (f fakeClient) RolloutPause(options RolloutPauseOptions) error {
+func (f fakeClient) RolloutPause(options RolloutOptions) error {
 	return f.internalClient.RolloutPause(options)
 }
 
-func (f fakeClient) RolloutResume(options RolloutResumeOptions) error {
+func (f fakeClient) RolloutResume(options RolloutOptions) error {
 	return f.internalClient.RolloutResume(options)
 }
 
-func (f fakeClient) RolloutUndo(options RolloutUndoOptions) error {
+func (f fakeClient) RolloutUndo(options RolloutOptions) error {
 	return f.internalClient.RolloutUndo(options)
 }
 
diff --git a/cmd/clusterctl/client/rollout_test.go b/cmd/clusterctl/client/rollout_test.go
index 00a7a77d2..d4c21926e 100644
--- a/cmd/clusterctl/client/rollout_test.go
+++ b/cmd/clusterctl/client/rollout_test.go
@@ -28,65 +28,29 @@ import (
 	"sigs.k8s.io/cluster-api/cmd/clusterctl/client/config"
 )
 
-func fakeClientForRollout() *fakeClient {
-	core := config.NewProvider("cluster-api", "https://somewhere.com", clusterctlv1.CoreProviderType)
-	infra := config.NewProvider("infra", "https://somewhere.com", clusterctlv1.InfrastructureProviderType)
-	md1 := &clusterv1.MachineDeployment{
-		TypeMeta: metav1.TypeMeta{
-			Kind:       "MachineDeployment",
-			APIVersion: "cluster.x-k8s.io/v1beta1",
-		},
-		ObjectMeta: metav1.ObjectMeta{
-			Namespace: "default",
-			Name:      "md-1",
-		},
-	}
-	md2 := &clusterv1.MachineDeployment{
-		TypeMeta: metav1.TypeMeta{
-			Kind:       "MachineDeployment",
-			APIVersion: "cluster.x-k8s.io/v1beta1",
-		},
-		ObjectMeta: metav1.ObjectMeta{
-			Namespace: "default",
-			Name:      "md-2",
-		},
-	}
-	config1 := newFakeConfig().
-		WithProvider(core).
-		WithProvider(infra)
-
-	cluster1 := newFakeCluster(cluster.Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"}, config1).
-		WithProviderInventory(core.Name(), core.Type(), "v1.0.0", "cluster-api-system").
-		WithProviderInventory(infra.Name(), infra.Type(), "v2.0.0", "infra-system").
-		WithObjs(md1).
-		WithObjs(md2)
-
-	client := newFakeClient(config1).
-		WithCluster(cluster1)
-
-	return client
+type rolloutTest struct {
+	name    string
+	fields  fields
+	args    args
+	wantErr bool
+}
+type fields struct {
+	client *fakeClient
+}
+type args struct {
+	options RolloutOptions
 }
 
-func Test_clusterctlClient_RolloutRestart(t *testing.T) {
-	type fields struct {
-		client *fakeClient
-	}
-	type args struct {
-		options RolloutRestartOptions
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		wantErr bool
-	}{
+// genericTestCases are test cases that can be passed to any of the rollout subcommands.
+func genericTestCases() []rolloutTest {
+	return []rolloutTest{
 		{
 			name: "return an error if machinedeployment is not found",
 			fields: fields{
 				client: fakeClientForRollout(),
 			},
 			args: args{
-				options: RolloutRestartOptions{
+				options: RolloutOptions{
 					Kubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
 					Resources:  []string{"machinedeployment/foo"},
 					Namespace:  "default",
@@ -100,7 +64,7 @@ func Test_clusterctlClient_RolloutRestart(t *testing.T) {
 				client: fakeClientForRollout(),
 			},
 			args: args{
-				options: RolloutRestartOptions{
+				options: RolloutOptions{
 					Kubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
 					Resources:  []string{"machinedeployment/md-1", "machinedeployment/md-does-not-exist"},
 					Namespace:  "default",
@@ -114,7 +78,7 @@ func Test_clusterctlClient_RolloutRestart(t *testing.T) {
 				client: fakeClientForRollout(),
 			},
 			args: args{
-				options: RolloutRestartOptions{
+				options: RolloutOptions{
 					Kubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
 					Resources:  []string{"foo/bar"},
 					Namespace:  "default",
@@ -128,20 +92,65 @@ func Test_clusterctlClient_RolloutRestart(t *testing.T) {
 				client: fakeClientForRollout(),
 			},
 			args: args{
-				options: RolloutRestartOptions{
+				options: RolloutOptions{
 					Kubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
 					Namespace:  "default",
 				},
 			},
 			wantErr: true,
 		},
+	}
+}
+
+func fakeClientForRollout() *fakeClient {
+	core := config.NewProvider("cluster-api", "https://somewhere.com", clusterctlv1.CoreProviderType)
+	infra := config.NewProvider("infra", "https://somewhere.com", clusterctlv1.InfrastructureProviderType)
+	md1 := &clusterv1.MachineDeployment{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "MachineDeployment",
+			APIVersion: "cluster.x-k8s.io/v1beta1",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "default",
+			Name:      "md-1",
+		},
+	}
+	md2 := &clusterv1.MachineDeployment{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "MachineDeployment",
+			APIVersion: "cluster.x-k8s.io/v1beta1",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "default",
+			Name:      "md-2",
+		},
+	}
+	config1 := newFakeConfig().
+		WithProvider(core).
+		WithProvider(infra)
+
+	cluster1 := newFakeCluster(cluster.Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"}, config1).
+		WithProviderInventory(core.Name(), core.Type(), "v1.0.0", "cluster-api-system").
+		WithProviderInventory(infra.Name(), infra.Type(), "v2.0.0", "infra-system").
+		WithObjs(md1).
+		WithObjs(md2)
+
+	client := newFakeClient(config1).
+		WithCluster(cluster1)
+
+	return client
+}
+
+func Test_clusterctlClient_RolloutRestart(t *testing.T) {
+	tests := genericTestCases()
+	additionalTests := []rolloutTest{
 		{
 			name: "do not return error if machinedeployment found",
 			fields: fields{
 				client: fakeClientForRollout(),
 			},
 			args: args{
-				options: RolloutRestartOptions{
+				options: RolloutOptions{
 					Kubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
 					Resources:  []string{"machinedeployment/md-1"},
 					Namespace:  "default",
@@ -155,7 +164,7 @@ func Test_clusterctlClient_RolloutRestart(t *testing.T) {
 				client: fakeClientForRollout(),
 			},
 			args: args{
-				options: RolloutRestartOptions{
+				options: RolloutOptions{
 					Kubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
 					Resources:  []string{"machinedeployment/md-1", "machinedeployment/md-2"},
 					Namespace:  "default",
@@ -165,6 +174,8 @@ func Test_clusterctlClient_RolloutRestart(t *testing.T) {
 		},
 	}
 
+	tests = append(tests, additionalTests...)
+
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			g := NewWithT(t)
@@ -180,74 +191,7 @@ func Test_clusterctlClient_RolloutRestart(t *testing.T) {
 }
 
 func Test_clusterctlClient_RolloutPause(t *testing.T) {
-	type fields struct {
-		client *fakeClient
-	}
-	type args struct {
-		options RolloutPauseOptions
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		wantErr bool
-	}{
-		{
-			name: "return an error if machinedeployment is not found",
-			fields: fields{
-				client: fakeClientForRollout(),
-			},
-			args: args{
-				options: RolloutPauseOptions{
-					Kubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
-					Resources:  []string{"machinedeployment/foo"},
-					Namespace:  "default",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "return error if one of the machinedeployments is not found",
-			fields: fields{
-				client: fakeClientForRollout(),
-			},
-			args: args{
-				options: RolloutPauseOptions{
-					Kubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
-					Resources:  []string{"machinedeployment/md-1", "machinedeployment/md-does-not-exist"},
-					Namespace:  "default",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "return error if unknown resource specified",
-			fields: fields{
-				client: fakeClientForRollout(),
-			},
-			args: args{
-				options: RolloutPauseOptions{
-					Kubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
-					Resources:  []string{"foo/bar"},
-					Namespace:  "default",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "return error if no resource specified",
-			fields: fields{
-				client: fakeClientForRollout(),
-			},
-			args: args{
-				options: RolloutPauseOptions{
-					Kubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
-					Namespace:  "default",
-				},
-			},
-			wantErr: true,
-		},
-	}
+	tests := genericTestCases()
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			g := NewWithT(t)
@@ -263,74 +207,7 @@ func Test_clusterctlClient_RolloutPause(t *testing.T) {
 }
 
 func Test_clusterctlClient_RolloutResume(t *testing.T) {
-	type fields struct {
-		client *fakeClient
-	}
-	type args struct {
-		options RolloutResumeOptions
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		wantErr bool
-	}{
-		{
-			name: "return an error if machinedeployment is not found",
-			fields: fields{
-				client: fakeClientForRollout(),
-			},
-			args: args{
-				options: RolloutResumeOptions{
-					Kubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
-					Resources:  []string{"machinedeployment/foo"},
-					Namespace:  "default",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "return error if one of the machinedeployments is not found",
-			fields: fields{
-				client: fakeClientForRollout(),
-			},
-			args: args{
-				options: RolloutResumeOptions{
-					Kubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
-					Resources:  []string{"machinedeployment/md-1", "machinedeployment/md-does-not-exist"},
-					Namespace:  "default",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "return error if unknown resource specified",
-			fields: fields{
-				client: fakeClientForRollout(),
-			},
-			args: args{
-				options: RolloutResumeOptions{
-					Kubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
-					Resources:  []string{"foo/bar"},
-					Namespace:  "default",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "return error if no resource specified",
-			fields: fields{
-				client: fakeClientForRollout(),
-			},
-			args: args{
-				options: RolloutResumeOptions{
-					Kubeconfig: Kubeconfig{Path: "kubeconfig", Context: "mgmt-context"},
-					Namespace:  "default",
-				},
-			},
-			wantErr: true,
-		},
-	}
+	tests := genericTestCases()
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			g := NewWithT(t)
diff --git a/exp/runtime/topologymutation/walker_test.go b/exp/runtime/topologymutation/walkler_test.go
similarity index 98%
rename from exp/runtime/topologymutation/walker_test.go
rename to exp/runtime/topologymutation/walkler_test.go
index 52c0e60fb..7644ef1ab 100644
--- a/exp/runtime/topologymutation/walker_test.go
+++ b/exp/runtime/topologymutation/walkler_test.go
@@ -130,7 +130,7 @@ func Test_WalkTemplates(t *testing.T) {
 				CommonResponse: runtimehooksv1.CommonResponse{
 					Status: runtimehooksv1.ResponseStatusFailure,
 					Message: "no kind \"Unknown\" is registered for version \"controlplane.cluster.x-k8s." +
-						"io/v1beta1\" in scheme",
+						"io/v1beta1\" in scheme \"pkg/runtime/scheme.go:100\"",
 				},
 			},
 			options: []WalkTemplatesOption{
@@ -225,7 +225,7 @@ func Test_WalkTemplates(t *testing.T) {
 			WalkTemplates(context.Background(), decoder, request, response, mutatingFunc, tt.options...)
 
 			g.Expect(response.Status).To(Equal(tt.expectedResponse.Status))
-			g.Expect(response.Message).To(ContainSubstring(tt.expectedResponse.Message))
+			g.Expect(response.Message).To(Equal(tt.expectedResponse.Message))
 			for i, item := range response.Items {
 				expectedItem := tt.expectedResponse.Items[i]
 				g.Expect(item.PatchType).To(Equal(expectedItem.PatchType))
diff --git a/test/go.mod b/test/go.mod
index 5f049d2c8..c1fd4f347 100644
--- a/test/go.mod
+++ b/test/go.mod
@@ -10,8 +10,8 @@ require (
 	github.com/docker/go-connections v0.4.0
 	github.com/flatcar/ignition v0.36.2
 	github.com/go-logr/logr v1.2.3
-	github.com/onsi/ginkgo/v2 v2.8.0
-	github.com/onsi/gomega v1.26.0
+	github.com/onsi/ginkgo/v2 v2.7.0
+	github.com/onsi/gomega v1.25.0
 	github.com/pkg/errors v0.9.1
 	github.com/spf13/pflag v1.0.5
 	github.com/vincent-petithory/dataurl v1.0.0
diff --git a/test/go.sum b/test/go.sum
index 3dd19a6a0..7a210f788 100644
--- a/test/go.sum
+++ b/test/go.sum
@@ -381,10 +381,10 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
-github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI=
-github.com/onsi/ginkgo/v2 v2.8.0/go.mod h1:6JsQiECmxCa3V5st74AL/AmsV482EDdVrGaVW6z3oYU=
-github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q=
-github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
+github.com/onsi/ginkgo/v2 v2.7.0 h1:/XxtEV3I3Eif/HobnVx9YmJgk8ENdRsuUmM+fLCFNow=
+github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo=
+github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y=
+github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
 github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
 github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
diff --git a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockerclusters.yaml b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockerclusters.yaml
index 98cc5947b..a2ed0cb08 100644
--- a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockerclusters.yaml
+++ b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockerclusters.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: dockerclusters.infrastructure.cluster.x-k8s.io
 spec:
diff --git a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockerclustertemplates.yaml b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockerclustertemplates.yaml
index 0d0df13dd..496b50da6 100644
--- a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockerclustertemplates.yaml
+++ b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockerclustertemplates.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: dockerclustertemplates.infrastructure.cluster.x-k8s.io
 spec:
diff --git a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinepools.yaml b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinepools.yaml
index 8893482ce..1752fc535 100644
--- a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinepools.yaml
+++ b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinepools.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: dockermachinepools.infrastructure.cluster.x-k8s.io
 spec:
diff --git a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachines.yaml b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachines.yaml
index 6c25858ef..1c2b99831 100644
--- a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachines.yaml
+++ b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachines.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: dockermachines.infrastructure.cluster.x-k8s.io
 spec:
diff --git a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinetemplates.yaml b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinetemplates.yaml
index ae37cf6c2..80ec348e6 100644
--- a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinetemplates.yaml
+++ b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinetemplates.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.11.2
+    controller-gen.kubebuilder.io/version: v0.11.1
   creationTimestamp: null
   name: dockermachinetemplates.infrastructure.cluster.x-k8s.io
 spec:
diff --git a/test/infrastructure/docker/exp/internal/controllers/dockermachinepool_controller.go b/test/infrastructure/docker/exp/internal/controllers/dockermachinepool_controller.go
index e6d5938d5..9c59ccd53 100644
--- a/test/infrastructure/docker/exp/internal/controllers/dockermachinepool_controller.go
+++ b/test/infrastructure/docker/exp/internal/controllers/dockermachinepool_controller.go
@@ -132,7 +132,7 @@ func (r *DockerMachinePoolReconciler) Reconcile(ctx context.Context, req ctrl.Re
 	// Requeue if the reconcile failed because the ClusterCacheTracker was locked for
 	// the current cluster because of concurrent access.
 	if errors.Is(err, remote.ErrClusterLocked) {
-		log.V(5).Info("Requeuing because another worker has the lock on the ClusterCacheTracker")
+		log.V(5).Info("Requeueing because another worker has the lock on the ClusterCacheTracker")
 		return ctrl.Result{Requeue: true}, nil
 	}
 	return res, err
diff --git a/test/infrastructure/docker/internal/controllers/dockermachine_controller.go b/test/infrastructure/docker/internal/controllers/dockermachine_controller.go
index edc90b423..2724a81dd 100644
--- a/test/infrastructure/docker/internal/controllers/dockermachine_controller.go
+++ b/test/infrastructure/docker/internal/controllers/dockermachine_controller.go
@@ -171,7 +171,7 @@ func (r *DockerMachineReconciler) Reconcile(ctx context.Context, req ctrl.Reques
 	// Requeue if the reconcile failed because the ClusterCacheTracker was locked for
 	// the current cluster because of concurrent access.
 	if errors.Is(err, remote.ErrClusterLocked) {
-		log.V(5).Info("Requeuing because another worker has the lock on the ClusterCacheTracker")
+		log.V(5).Info("Requeueing because another worker has the lock on the ClusterCacheTracker")
 		return ctrl.Result{Requeue: true}, nil
 	}
 	return res, err