Repository: kubernetes-sigs/cluster-api-provider-vsphere
Pull request #2461 (2023-10-25 06:18:46)

✨ Prepare main branch for release-1.9 development
<!--  Thanks for sending a pull request! Please add a icon to the title of this PR (see https://sigs.k8s.io/cluster-api-provider-vsphere/CONTRIBUTING.md#contributing-a-patch), and delete this line and similar ones -->
<!-- the icon will be either ⚠️ (:warning:, major or breaking changes), ✨ (:sparkles:, feature additions), 🐛 (:bug:, patch and bugfixes), 📖 (:book:, documentation or proposals), or 🌱 (:seedling:, minor or other)
Here are some other tips for you:
1. If this is your first time, read our contributor guidelines https://git.k8s.io/community/contributors/guide/pull-requests.md#the-pull-request-submit-process and developer guide https://git.k8s.io/community/contributors/devel/development.md#development-guide
2. If you want *faster* PR reviews, read how: https://git.k8s.io/community/contributors/guide/pull-requests.md#best-practices-for-faster-reviews
3. Follow the instructions for writing a release note: https://git.k8s.io/community/contributors/guide/release-notes.md
4. If the PR is unfinished, see how to mark it: https://git.k8s.io/community/contributors/guide/pull-requests.md#marking-unfinished-pull-requests
5. If this PR changes image versions, please title this PR "Bump <image name> from x.x.x to y.y.y."
-->

**What this PR does / why we need it**:
This PR addresses following to prepare main branch for release-1.9:
[Prepare main branch for development of the new release](https://github.com/kubernetes-sigs/cluster-api-provider-vsphere/blob/main/docs/release/release-tasks.md#prepare-main-branch-for-development-of-the-new-release)

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Part of #2207 


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 [vincepri](https://github.com/vincepri) for approval. 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-provider-vsphere).

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

- **[OWNERS](https://github.com/kubernetes-sigs/cluster-api-provider-vsphere/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":["vincepri"]} -->
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/kubernetes-sigs/cluster-api-provider-vsphere/pull/2461?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubernetes-sigs) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Comparison is base [(`fda92b9`)](https://app.codecov.io/gh/kubernetes-sigs/cluster-api-provider-vsphere/commit/fda92b95f435edbae254fdb6258e62b0633222fd?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubernetes-sigs) 62.61% compared to head [(`58c1e99`)](https://app.codecov.io/gh/kubernetes-sigs/cluster-api-provider-vsphere/pull/2461?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubernetes-sigs) 62.83%.
> Report is 2 commits behind head on main.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #2461      +/-   ##
==========================================
+ Coverage   62.61%   62.83%   +0.22%     
==========================================
  Files         122      122              
  Lines        8770     8763       -7     
==========================================
+ Hits         5491     5506      +15     
+ Misses       2880     2864      -16     
+ Partials      399      393       -6     
```


[see 16 files with indirect coverage changes](https://app.codecov.io/gh/kubernetes-sigs/cluster-api-provider-vsphere/pull/2461/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubernetes-sigs)


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/kubernetes-sigs/cluster-api-provider-vsphere/pull/2461?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubernetes-sigs).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubernetes-sigs).


Patch:
diff --git a/clusterctl-settings.json b/clusterctl-settings.json
index 4fa08f01..06d51188 100644
--- a/clusterctl-settings.json
+++ b/clusterctl-settings.json
@@ -2,6 +2,6 @@
   "name": "infrastructure-vsphere",
   "config": {
     "componentsFile": "infrastructure-components.yaml",
-    "nextVersion": "v1.8.0"
+    "nextVersion": "v1.9.99"
   }
 }
diff --git a/controllers/vspheredeploymentzone_controller.go b/controllers/vspheredeploymentzone_controller.go
index d1496d8a..703752b3 100644
--- a/controllers/vspheredeploymentzone_controller.go
+++ b/controllers/vspheredeploymentzone_controller.go
@@ -129,7 +129,7 @@ func (r vsphereDeploymentZoneReconciler) Reconcile(ctx context.Context, request
 		PatchHelper:           patchHelper,
 	}
 	defer func() {
-		if err := vsphereDeploymentZoneContext.Patch(ctx); err != nil {
+		if err := vsphereDeploymentZoneContext.Patch(); err != nil {
 			reterr = kerrors.NewAggregate([]error{reterr, err})
 		}
 	}()
@@ -233,7 +233,7 @@ func (r vsphereDeploymentZoneReconciler) getVCenterSession(ctx context.Context,
 		}
 		logger.Info("using server credentials to create the authenticated session")
 		params = params.WithUserInfo(creds.Username, creds.Password)
-		return session.GetOrCreate(ctx,
+		return session.GetOrCreate(r.Context,
 			params)
 	}
 
diff --git a/controllers/vspherevm_controller.go b/controllers/vspherevm_controller.go
index 0746e2c0..216dff59 100644
--- a/controllers/vspherevm_controller.go
+++ b/controllers/vspherevm_controller.go
@@ -258,7 +258,7 @@ func (r vmReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.R
 		)
 
 		// Patch the VSphereVM resource.
-		if err := vmContext.Patch(ctx); err != nil {
+		if err := vmContext.Patch(); err != nil {
 			reterr = kerrors.NewAggregate([]error{reterr, err})
 		}
 	}()
diff --git a/main.go b/main.go
index f7d14de3..5ea3182b 100644
--- a/main.go
+++ b/main.go
@@ -256,7 +256,7 @@ func main() {
 
 	// Create a function that adds all the controllers and webhooks to the manager.
 	addToManager := func(ctx context.Context, controllerCtx *capvcontext.ControllerManagerContext, mgr ctrlmgr.Manager) error {
-		tracker, err := setupRemoteClusterCacheTracker(ctx, mgr)
+		tracker, err := setupRemoteClusterCacheTracker(controllerCtx, mgr)
 		if err != nil {
 			return perrors.Wrapf(err, "unable to create remote cluster cache tracker")
 		}
@@ -319,7 +319,7 @@ func main() {
 	}
 
 	// initialize notifier for capv-manager-bootstrap-credentials
-	watch, err := manager.InitializeWatch(mgr.GetControllerManagerContext(), &managerOpts)
+	watch, err := manager.InitializeWatch(mgr.GetContext(), &managerOpts)
 	if err != nil {
 		setupLog.Error(err, "failed to initialize watch on CAPV credentials file")
 		os.Exit(1)
@@ -422,7 +422,7 @@ func concurrency(c int) controller.Options {
 	return controller.Options{MaxConcurrentReconciles: c}
 }
 
-func setupRemoteClusterCacheTracker(ctx context.Context, mgr ctrlmgr.Manager) (*remote.ClusterCacheTracker, error) {
+func setupRemoteClusterCacheTracker(controllerCtx *capvcontext.ControllerManagerContext, mgr ctrlmgr.Manager) (*remote.ClusterCacheTracker, error) {
 	secretCachingClient, err := client.New(mgr.GetConfig(), client.Options{
 		HTTPClient: mgr.GetHTTPClient(),
 		Cache: &client.CacheOptions{
@@ -452,7 +452,7 @@ func setupRemoteClusterCacheTracker(ctx context.Context, mgr ctrlmgr.Manager) (*
 		Client:           mgr.GetClient(),
 		Tracker:          tracker,
 		WatchFilterValue: managerOpts.WatchFilterValue,
-	}).SetupWithManager(ctx, mgr, concurrency(clusterCacheTrackerConcurrency)); err != nil {
+	}).SetupWithManager(controllerCtx, mgr, concurrency(clusterCacheTrackerConcurrency)); err != nil {
 		return nil, perrors.Wrapf(err, "unable to create ClusterCacheReconciler controller")
 	}
 
diff --git a/metadata.yaml b/metadata.yaml
index 9b50dea4..ebbbeb45 100644
--- a/metadata.yaml
+++ b/metadata.yaml
@@ -30,3 +30,6 @@ releaseSeries:
   - major: 1
     minor: 8
     contract: v1beta1
+  - major: 1
+    minor: 9
+    contract: v1beta1
diff --git a/pkg/clustermodule/util.go b/pkg/clustermodule/util.go
index 292a7ac8..a64b9632 100644
--- a/pkg/clustermodule/util.go
+++ b/pkg/clustermodule/util.go
@@ -22,7 +22,7 @@ import (
 	"github.com/blang/semver"
 
 	infrav1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1"
-	capvcontext "sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
+	"sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
 )
 
 // Compare returns whether both the cluster module slices are the same.
@@ -50,8 +50,8 @@ func Compare(oldMods, newMods []infrav1.ClusterModule) bool {
 }
 
 // IsClusterCompatible checks if the VCenterVersion is compatibly with CAPV. Only version 7 and over are supported.
-func IsClusterCompatible(clusterCtx *capvcontext.ClusterContext) bool {
-	version := clusterCtx.VSphereCluster.Status.VCenterVersion
+func IsClusterCompatible(ctx *context.ClusterContext) bool {
+	version := ctx.VSphereCluster.Status.VCenterVersion
 	if version == "" {
 		return false
 	}
diff --git a/pkg/context/controller_manager_context.go b/pkg/context/controller_manager_context.go
index 29049cb7..d0576e2c 100644
--- a/pkg/context/controller_manager_context.go
+++ b/pkg/context/controller_manager_context.go
@@ -17,6 +17,7 @@ limitations under the License.
 package context
 
 import (
+	"context"
 	"sync"
 	"time"
 
@@ -32,6 +33,8 @@ import (
 // ControllerManagerContext is the context of the controller that owns the
 // controllers.
 type ControllerManagerContext struct {
+	context.Context //nolint:containedctx
+
 	// Namespace is the namespace in which the resource is located responsible
 	// for running the controller manager.
 	Namespace string
diff --git a/pkg/context/fake/fake_cluster_context.go b/pkg/context/fake/fake_cluster_context.go
index 6ff70af6..9fed6837 100644
--- a/pkg/context/fake/fake_cluster_context.go
+++ b/pkg/context/fake/fake_cluster_context.go
@@ -17,31 +17,29 @@ limitations under the License.
 package fake
 
 import (
-	"context"
-
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
 
 	infrav1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1"
-	capvcontext "sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
+	"sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
 )
 
 // NewClusterContext returns a fake ClusterContext for unit testing
 // reconcilers with a fake client.
-func NewClusterContext(ctx context.Context, controllerCtx *capvcontext.ControllerContext) *capvcontext.ClusterContext {
+func NewClusterContext(ctx *context.ControllerContext) *context.ClusterContext {
 	// Create the cluster resources.
 	cluster := newClusterV1()
 	vsphereCluster := newVSphereCluster(cluster)
 
 	// Add the cluster resources to the fake cluster client.
-	if err := controllerCtx.Client.Create(ctx, &cluster); err != nil {
+	if err := ctx.Client.Create(ctx, &cluster); err != nil {
 		panic(err)
 	}
-	if err := controllerCtx.Client.Create(ctx, &vsphereCluster); err != nil {
+	if err := ctx.Client.Create(ctx, &vsphereCluster); err != nil {
 		panic(err)
 	}
 
-	return &capvcontext.ClusterContext{
+	return &context.ClusterContext{
 		Cluster:        &cluster,
 		VSphereCluster: &vsphereCluster,
 	}
diff --git a/pkg/context/fake/fake_controller_context.go b/pkg/context/fake/fake_controller_context.go
index 5adf97b4..21971ee8 100644
--- a/pkg/context/fake/fake_controller_context.go
+++ b/pkg/context/fake/fake_controller_context.go
@@ -19,17 +19,17 @@ package fake
 import (
 	clientrecord "k8s.io/client-go/tools/record"
 
-	capvcontext "sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
+	"sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
 	"sigs.k8s.io/cluster-api-provider-vsphere/pkg/record"
 )
 
 // NewControllerContext returns a fake ControllerContext for unit testing
 // reconcilers with a fake client.
-func NewControllerContext(controllerManagerCtx *capvcontext.ControllerManagerContext) *capvcontext.ControllerContext {
-	return &capvcontext.ControllerContext{
-		ControllerManagerContext: controllerManagerCtx,
+func NewControllerContext(ctx *context.ControllerManagerContext) *context.ControllerContext {
+	return &context.ControllerContext{
+		ControllerManagerContext: ctx,
 		Name:                     ControllerName,
-		Logger:                   controllerManagerCtx.Logger.WithName(ControllerName),
+		Logger:                   ctx.Logger.WithName(ControllerName),
 		Recorder:                 record.New(clientrecord.NewFakeRecorder(1024)),
 	}
 }
diff --git a/pkg/context/fake/fake_controller_manager_context.go b/pkg/context/fake/fake_controller_manager_context.go
index ec5bf34a..b9787880 100644
--- a/pkg/context/fake/fake_controller_manager_context.go
+++ b/pkg/context/fake/fake_controller_manager_context.go
@@ -17,6 +17,8 @@ limitations under the License.
 package fake
 
 import (
+	"context"
+
 	vmoprv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha1"
 	"k8s.io/apimachinery/pkg/runtime"
 	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
@@ -54,6 +56,7 @@ func NewControllerManagerContext(initObjects ...client.Object) *capvcontext.Cont
 	).WithObjects(initObjects...).Build()
 
 	return &capvcontext.ControllerManagerContext{
+		Context:                 context.Background(),
 		Client:                  clientWithObjects,
 		Logger:                  ctrllog.Log.WithName(ControllerManagerName),
 		Scheme:                  scheme,
diff --git a/pkg/context/fake/fake_machine_context.go b/pkg/context/fake/fake_machine_context.go
index 1a2bae5f..0949d7cb 100644
--- a/pkg/context/fake/fake_machine_context.go
+++ b/pkg/context/fake/fake_machine_context.go
@@ -28,16 +28,16 @@ import (
 
 // NewMachineContext returns a fake VIMMachineContext for unit testing
 // reconcilers with a fake client.
-func NewMachineContext(ctx context.Context, clusterCtx *capvcontext.ClusterContext, controllerCtx *capvcontext.ControllerContext) *capvcontext.VIMMachineContext {
+func NewMachineContext(clusterCtx *capvcontext.ClusterContext, controllerCtx *capvcontext.ControllerContext) *capvcontext.VIMMachineContext {
 	// Create the machine resources.
 	machine := newMachineV1a4()
 	vsphereMachine := newVSphereMachine(machine)
 
 	// Add the cluster resources to the fake cluster client.
-	if err := controllerCtx.Client.Create(ctx, &machine); err != nil {
+	if err := controllerCtx.Client.Create(context.TODO(), &machine); err != nil {
 		panic(err)
 	}
-	if err := controllerCtx.Client.Create(ctx, &vsphereMachine); err != nil {
+	if err := controllerCtx.Client.Create(context.TODO(), &vsphereMachine); err != nil {
 		panic(err)
 	}
 
diff --git a/pkg/context/fake/fake_vm_context.go b/pkg/context/fake/fake_vm_context.go
index f4074e77..1567580d 100644
--- a/pkg/context/fake/fake_vm_context.go
+++ b/pkg/context/fake/fake_vm_context.go
@@ -17,35 +17,33 @@ limitations under the License.
 package fake
 
 import (
-	"context"
-
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"sigs.k8s.io/cluster-api/util/patch"
 
 	infrav1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1"
-	capvcontext "sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
+	"sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
 )
 
 // NewVMContext returns a fake VMContext for unit testing
 // reconcilers with a fake client.
-func NewVMContext(ctx context.Context, controllerCtx *capvcontext.ControllerContext) *capvcontext.VMContext {
+func NewVMContext(ctx *context.ControllerContext) *context.VMContext {
 	// Create the resources.
 	vsphereVM := newVSphereVM()
 
 	// Add the resources to the fake client.
-	if err := controllerCtx.Client.Create(ctx, &vsphereVM); err != nil {
+	if err := ctx.Client.Create(ctx, &vsphereVM); err != nil {
 		panic(err)
 	}
 
-	helper, err := patch.NewHelper(&vsphereVM, controllerCtx.Client)
+	helper, err := patch.NewHelper(&vsphereVM, ctx.Client)
 	if err != nil {
 		panic(err)
 	}
 
-	return &capvcontext.VMContext{
-		ControllerContext: controllerCtx,
+	return &context.VMContext{
+		ControllerContext: ctx,
 		VSphereVM:         &vsphereVM,
-		Logger:            controllerCtx.Logger.WithName(vsphereVM.Name),
+		Logger:            ctx.Logger.WithName(vsphereVM.Name),
 		PatchHelper:       helper,
 	}
 }
diff --git a/pkg/context/fake/fake_vmware_cluster_context.go b/pkg/context/fake/fake_vmware_cluster_context.go
index a216871f..e572da3c 100644
--- a/pkg/context/fake/fake_vmware_cluster_context.go
+++ b/pkg/context/fake/fake_vmware_cluster_context.go
@@ -26,7 +26,7 @@ import (
 
 // NewVmwareClusterContext returns a fake ClusterContext for unit testing
 // reconcilers with a fake client.
-func NewVmwareClusterContext(ctx context.Context, controllerCtx *capvcontext.ControllerContext, namespace string, vsphereCluster *vmwarev1.VSphereCluster) *vmware.ClusterContext {
+func NewVmwareClusterContext(controllerCtx *capvcontext.ControllerContext, namespace string, vsphereCluster *vmwarev1.VSphereCluster) *vmware.ClusterContext {
 	// Create the cluster resources.
 	cluster := newClusterV1()
 	if vsphereCluster == nil {
@@ -35,10 +35,10 @@ func NewVmwareClusterContext(ctx context.Context, controllerCtx *capvcontext.Con
 	}
 
 	// Add the cluster resources to the fake cluster client.
-	if err := controllerCtx.Client.Create(ctx, &cluster); err != nil {
+	if err := controllerCtx.Client.Create(context.TODO(), &cluster); err != nil {
 		panic(err)
 	}
-	if err := controllerCtx.Client.Create(ctx, vsphereCluster); err != nil {
+	if err := controllerCtx.Client.Create(context.TODO(), vsphereCluster); err != nil {
 		panic(err)
 	}
 
diff --git a/pkg/context/vm_context.go b/pkg/context/vm_context.go
index c384153a..6cf34856 100644
--- a/pkg/context/vm_context.go
+++ b/pkg/context/vm_context.go
@@ -18,7 +18,6 @@ limitations under the License.
 package context
 
 import (
-	"context"
 	"fmt"
 
 	"github.com/go-logr/logr"
@@ -45,8 +44,8 @@ func (c *VMContext) String() string {
 }
 
 // Patch updates the object and its status on the API server.
-func (c *VMContext) Patch(ctx context.Context) error {
-	return c.PatchHelper.Patch(ctx, c.VSphereVM)
+func (c *VMContext) Patch() error {
+	return c.PatchHelper.Patch(c, c.VSphereVM)
 }
 
 // GetLogger returns this context's logger.
diff --git a/pkg/context/vspheredeploymentzone_context.go b/pkg/context/vspheredeploymentzone_context.go
index be78910b..ca3ec273 100644
--- a/pkg/context/vspheredeploymentzone_context.go
+++ b/pkg/context/vspheredeploymentzone_context.go
@@ -17,7 +17,6 @@ limitations under the License.
 package context
 
 import (
-	"context"
 	"fmt"
 
 	"github.com/go-logr/logr"
@@ -38,7 +37,7 @@ type VSphereDeploymentZoneContext struct {
 }
 
 // Patch patches the VSphereDeploymentZone.
-func (c *VSphereDeploymentZoneContext) Patch(ctx context.Context) error {
+func (c *VSphereDeploymentZoneContext) Patch() error {
 	conditions.SetSummary(c.VSphereDeploymentZone,
 		conditions.WithConditions(
 			infrav1.VCenterAvailableCondition,
@@ -46,7 +45,7 @@ func (c *VSphereDeploymentZoneContext) Patch(ctx context.Context) error {
 			infrav1.PlacementConstraintMetCondition,
 		),
 	)
-	return c.PatchHelper.Patch(ctx, c.VSphereDeploymentZone)
+	return c.PatchHelper.Patch(c, c.VSphereDeploymentZone)
 }
 
 // String returns a string with the GroupVersionKind and name of the VSphereDeploymentZone.
diff --git a/pkg/manager/manager.go b/pkg/manager/manager.go
index ad9f260e..85ab5bd4 100644
--- a/pkg/manager/manager.go
+++ b/pkg/manager/manager.go
@@ -44,8 +44,8 @@ import (
 type Manager interface {
 	ctrl.Manager
 
-	// GetControllerManagerContext returns the controller manager's context.
-	GetControllerManagerContext() *capvcontext.ControllerManagerContext
+	// GetContext returns the controller manager's context.
+	GetContext() *capvcontext.ControllerManagerContext
 }
 
 // New returns a new CAPV controller manager.
@@ -78,6 +78,7 @@ func New(ctx context.Context, opts Options) (Manager, error) {
 
 	// Build the controller manager context.
 	controllerManagerContext := &capvcontext.ControllerManagerContext{
+		Context:                 context.Background(),
 		WatchNamespaces:         opts.Cache.Namespaces,
 		Namespace:               opts.PodNamespace,
 		Name:                    opts.PodName,
@@ -101,18 +102,18 @@ func New(ctx context.Context, opts Options) (Manager, error) {
 	}
 
 	return &manager{
-		Manager:              mgr,
-		controllerManagerCtx: controllerManagerContext,
+		Manager:       mgr,
+		controllerCtx: controllerManagerContext,
 	}, nil
 }
 
 type manager struct {
 	ctrl.Manager
-	controllerManagerCtx *capvcontext.ControllerManagerContext
+	controllerCtx *capvcontext.ControllerManagerContext
 }
 
-func (m *manager) GetControllerManagerContext() *capvcontext.ControllerManagerContext {
-	return m.controllerManagerCtx
+func (m *manager) GetContext() *capvcontext.ControllerManagerContext {
+	return m.controllerCtx
 }
 
 // UpdateCredentials reads and updates credentials from the credentials file.
diff --git a/pkg/services/govmomi/cluster/service.go b/pkg/services/govmomi/cluster/service.go
index 85093183..5424e724 100644
--- a/pkg/services/govmomi/cluster/service.go
+++ b/pkg/services/govmomi/cluster/service.go
@@ -27,6 +27,9 @@ import (
 )
 
 type computeClusterContext interface {
+	// TODO(zhanggbj): remove context.Context in this interface after refactoring context for all controllers.
+	context.Context
+
 	GetSession() *session.Session
 }
 
diff --git a/pkg/services/govmomi/context.go b/pkg/services/govmomi/context.go
index bde225b6..798a0a15 100644
--- a/pkg/services/govmomi/context.go
+++ b/pkg/services/govmomi/context.go
@@ -21,11 +21,11 @@ import (
 	"github.com/vmware/govmomi/vim25/types"
 
 	infrav1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1"
-	capvcontext "sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
+	"sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
 )
 
 type virtualMachineContext struct {
-	capvcontext.VMContext
+	context.VMContext
 	Ref       types.ManagedObjectReference
 	Obj       *object.VirtualMachine
 	State     *infrav1.VirtualMachine
diff --git a/pkg/services/govmomi/service.go b/pkg/services/govmomi/service.go
index a1df27fc..0c18458f 100644
--- a/pkg/services/govmomi/service.go
+++ b/pkg/services/govmomi/service.go
@@ -245,7 +245,7 @@ func (vms *VMService) DestroyVM(ctx context.Context, vmCtx *capvcontext.VMContex
 		}
 
 		virtualMachineCtx.VSphereVM.Status.TaskRef = task.Reference().Value
-		if err = virtualMachineCtx.Patch(ctx); err != nil {
+		if err = virtualMachineCtx.Patch(); err != nil {
 			vmCtx.Logger.Error(err, "patch failed", "vm", virtualMachineCtx.String())
 			return reconcile.Result{}, vm, err
 		}
@@ -351,7 +351,7 @@ func (vms *VMService) reconcilePowerState(ctx context.Context, virtualMachineCtx
 
 		// Update the VSphereVM.Status.TaskRef to track the power-on task.
 		virtualMachineCtx.VSphereVM.Status.TaskRef = task.Reference().Value
-		if err = virtualMachineCtx.Patch(ctx); err != nil {
+		if err = virtualMachineCtx.Patch(); err != nil {
 			virtualMachineCtx.Logger.Error(err, "patch failed", "vm", virtualMachineCtx.String())
 			return false, err
 		}
diff --git a/pkg/services/govmomi/util.go b/pkg/services/govmomi/util.go
index 1bf1d2c2..f2e6774e 100644
--- a/pkg/services/govmomi/util.go
+++ b/pkg/services/govmomi/util.go
@@ -180,6 +180,7 @@ func checkAndRetryTask(vmCtx *capvcontext.VMContext, task *mo.Task) (bool, error
 
 func reconcileVSphereVMWhenNetworkIsReady(ctx context.Context, virtualMachineCtx *virtualMachineContext, powerOnTask *object.Task) {
 	reconcileVSphereVMOnChannel(
+		ctx,
 		&virtualMachineCtx.VMContext,
 		func() (<-chan []interface{}, <-chan error, error) {
 			// Wait for the VM to be powered on.
@@ -295,7 +296,7 @@ func reconcileVSphereVMOnFuncCompletion(_ context.Context, vmCtx *capvcontext.VM
 	}()
 }
 
-func reconcileVSphereVMOnChannel(vmCtx *capvcontext.VMContext, waitFn func() (<-chan []interface{}, <-chan error, error)) {
+func reconcileVSphereVMOnChannel(_ context.Context, vmCtx *capvcontext.VMContext, waitFn func() (<-chan []interface{}, <-chan error, error)) {
 	obj := vmCtx.VSphereVM.DeepCopy()
 	gvk := obj.GetObjectKind().GroupVersionKind()
 
@@ -328,6 +329,8 @@ func reconcileVSphereVMOnChannel(vmCtx *capvcontext.VMContext, waitFn func() (<-
 					vmCtx.Logger.Error(err, "error occurred while waiting to trigger a generic event")
 				}
 				return
+			case <-vmCtx.Done():
+				return
 			}
 		}
 	}()
diff --git a/pkg/services/govmomi/vcenter/clone.go b/pkg/services/govmomi/vcenter/clone.go
index 16e3bc41..c6ec8643 100644
--- a/pkg/services/govmomi/vcenter/clone.go
+++ b/pkg/services/govmomi/vcenter/clone.go
@@ -302,7 +302,7 @@ func Clone(ctx context.Context, vmCtx *capvcontext.VMContext, bootstrapData []by
 	// patch the vsphereVM early to ensure that the task is
 	// reflected in the status right away, this avoid situations
 	// of concurrent clones
-	if err := vmCtx.Patch(ctx); err != nil {
+	if err := vmCtx.Patch(); err != nil {
 		vmCtx.Logger.Error(err, "patch failed", "vspherevm", vmCtx.VSphereVM)
 	}
 	return nil


Test patch:
diff --git a/controllers/clustermodule_reconciler_test.go b/controllers/clustermodule_reconciler_test.go
index 8988d8f8..dd80233a 100644
--- a/controllers/clustermodule_reconciler_test.go
+++ b/controllers/clustermodule_reconciler_test.go
@@ -410,7 +410,7 @@ func TestReconciler_Reconcile(t *testing.T) {
 				tt.beforeFn(md)
 			}
 			controllerCtx := fake.NewControllerContext(fake.NewControllerManagerContext(kcp, md))
-			clusterCtx := fake.NewClusterContext(ctx, controllerCtx)
+			clusterCtx := fake.NewClusterContext(controllerCtx)
 			clusterCtx.VSphereCluster.Spec.ClusterModules = tt.clusterModules
 			clusterCtx.VSphereCluster.Status = infrav1.VSphereClusterStatus{VCenterVersion: infrav1.NewVCenterVersion("7.0.0")}
 
@@ -486,7 +486,7 @@ func TestReconciler_fetchMachineOwnerObjects(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			g := gomega.NewWithT(t)
 			controllerCtx := fake.NewControllerContext(fake.NewControllerManagerContext(tt.initObjs...))
-			clusterCtx := fake.NewClusterContext(ctx, controllerCtx)
+			clusterCtx := fake.NewClusterContext(controllerCtx)
 			r := Reconciler{Client: controllerCtx.Client}
 			objMap, err := r.fetchMachineOwnerObjects(ctx, clusterCtx)
 			if tt.hasError {
@@ -511,7 +511,7 @@ func TestReconciler_fetchMachineOwnerObjects(t *testing.T) {
 			machineDeployment("foo", metav1.NamespaceDefault, fake.Clusterv1a2Name),
 			mdToBeDeleted,
 		))
-		clusterCtx := fake.NewClusterContext(ctx, controllerCtx)
+		clusterCtx := fake.NewClusterContext(controllerCtx)
 		objMap, err := Reconciler{Client: controllerCtx.Client}.fetchMachineOwnerObjects(ctx, clusterCtx)
 		g.Expect(err).NotTo(gomega.HaveOccurred())
 		g.Expect(objMap).To(gomega.HaveLen(2))
diff --git a/controllers/controllers_suite_test.go b/controllers/controllers_suite_test.go
index 8dbb2a6b..c4d8c84e 100644
--- a/controllers/controllers_suite_test.go
+++ b/controllers/controllers_suite_test.go
@@ -93,31 +93,31 @@ func setup() {
 		panic(fmt.Sprintf("unable to create ClusterCacheReconciler controller: %v", err))
 	}
 
-	if err := AddClusterControllerToManager(ctx, testEnv.GetControllerManagerContext(), testEnv.Manager, &infrav1.VSphereCluster{}, controllerOpts); err != nil {
+	if err := AddClusterControllerToManager(ctx, testEnv.GetContext(), testEnv.Manager, &infrav1.VSphereCluster{}, controllerOpts); err != nil {
 		panic(fmt.Sprintf("unable to setup VsphereCluster controller: %v", err))
 	}
-	if err := AddMachineControllerToManager(ctx, testEnv.GetControllerManagerContext(), testEnv.Manager, &infrav1.VSphereMachine{}, controllerOpts); err != nil {
+	if err := AddMachineControllerToManager(ctx, testEnv.GetContext(), testEnv.Manager, &infrav1.VSphereMachine{}, controllerOpts); err != nil {
 		panic(fmt.Sprintf("unable to setup VsphereMachine controller: %v", err))
 	}
-	if err := AddVMControllerToManager(ctx, testEnv.GetControllerManagerContext(), testEnv.Manager, tracker, controllerOpts); err != nil {
+	if err := AddVMControllerToManager(ctx, testEnv.GetContext(), testEnv.Manager, tracker, controllerOpts); err != nil {
 		panic(fmt.Sprintf("unable to setup VsphereVM controller: %v", err))
 	}
-	if err := AddVsphereClusterIdentityControllerToManager(ctx, testEnv.GetControllerManagerContext(), testEnv.Manager, controllerOpts); err != nil {
+	if err := AddVsphereClusterIdentityControllerToManager(ctx, testEnv.GetContext(), testEnv.Manager, controllerOpts); err != nil {
 		panic(fmt.Sprintf("unable to setup VSphereClusterIdentity controller: %v", err))
 	}
-	if err := AddVSphereDeploymentZoneControllerToManager(ctx, testEnv.GetControllerManagerContext(), testEnv.Manager, controllerOpts); err != nil {
+	if err := AddVSphereDeploymentZoneControllerToManager(ctx, testEnv.GetContext(), testEnv.Manager, controllerOpts); err != nil {
 		panic(fmt.Sprintf("unable to setup VSphereDeploymentZone controller: %v", err))
 	}
-	if err := AddServiceAccountProviderControllerToManager(ctx, testEnv.GetControllerManagerContext(), testEnv.Manager, tracker, controllerOpts); err != nil {
+	if err := AddServiceAccountProviderControllerToManager(ctx, testEnv.GetContext(), testEnv.Manager, tracker, controllerOpts); err != nil {
 		panic(fmt.Sprintf("unable to setup ServiceAccount controller: %v", err))
 	}
-	if err := AddServiceDiscoveryControllerToManager(ctx, testEnv.GetControllerManagerContext(), testEnv.Manager, tracker, controllerOpts); err != nil {
+	if err := AddServiceDiscoveryControllerToManager(ctx, testEnv.GetContext(), testEnv.Manager, tracker, controllerOpts); err != nil {
 		panic(fmt.Sprintf("unable to setup SvcDiscovery controller: %v", err))
 	}
 
 	go func() {
 		fmt.Println("Starting the manager")
-		if err := testEnv.StartManager(ctx); err != nil {
+		if err := testEnv.StartManager(testEnv.GetContext()); err != nil {
 			panic(fmt.Sprintf("failed to start the envtest manager: %v", err))
 		}
 	}()
@@ -132,7 +132,7 @@ func setup() {
 			Name: manager.DefaultPodNamespace,
 		},
 	}
-	if err := testEnv.Create(ctx, ns); err != nil {
+	if err := testEnv.Create(testEnv.GetContext(), ns); err != nil {
 		panic("unable to create controller namespace")
 	}
 }
diff --git a/controllers/serviceaccount_controller_intg_test.go b/controllers/serviceaccount_controller_intg_test.go
index b4772316..a3fea31b 100644
--- a/controllers/serviceaccount_controller_intg_test.go
+++ b/controllers/serviceaccount_controller_intg_test.go
@@ -46,7 +46,7 @@ var _ = Describe("ProviderServiceAccount controller integration tests", func() {
 		intCtx = helpers.NewIntegrationTestContextWithClusters(ctx, testEnv.Manager.GetClient())
 		testSystemSvcAcctCM := "test-system-svc-acct-cm"
 		cfgMap := getSystemServiceAccountsConfigMap(intCtx.VSphereCluster.Namespace, testSystemSvcAcctCM)
-		Expect(intCtx.Client.Create(ctx, cfgMap)).To(Succeed())
+		Expect(intCtx.Client.Create(intCtx, cfgMap)).To(Succeed())
 		_ = os.Setenv("SERVICE_ACCOUNTS_CM_NAMESPACE", intCtx.VSphereCluster.Namespace)
 		_ = os.Setenv("SERVICE_ACCOUNTS_CM_NAME", testSystemSvcAcctCM)
 	})
@@ -62,13 +62,13 @@ var _ = Describe("ProviderServiceAccount controller integration tests", func() {
 		)
 		BeforeEach(func() {
 			pSvcAccount = getTestProviderServiceAccount(intCtx.Namespace, intCtx.VSphereCluster)
-			createTestResource(ctx, intCtx.Client, pSvcAccount)
-			assertEventuallyExistsInNamespace(ctx, intCtx.Client, intCtx.Namespace, pSvcAccount.GetName(), pSvcAccount)
+			createTestResource(intCtx, intCtx.Client, pSvcAccount)
+			assertEventuallyExistsInNamespace(intCtx, intCtx.Client, intCtx.Namespace, pSvcAccount.GetName(), pSvcAccount)
 		})
 		AfterEach(func() {
 			// Deleting the provider service account is not strictly required as the context itself
 			// gets teared down but keeping it for clarity.
-			deleteTestResource(ctx, intCtx.Client, pSvcAccount)
+			deleteTestResource(intCtx, intCtx.Client, pSvcAccount)
 		})
 
 		Context("When serviceaccount secret is created", func() {
@@ -77,7 +77,7 @@ var _ = Describe("ProviderServiceAccount controller integration tests", func() {
 				// to create a secret containing the bearer token, cert etc for a service account. We need to
 				// simulate the job of the token controller by waiting for the service account creation and then updating it
 				// with a prototype secret.
-				assertServiceAccountAndUpdateSecret(ctx, intCtx.Client, intCtx.Namespace, pSvcAccount.GetName())
+				assertServiceAccountAndUpdateSecret(intCtx, intCtx.Client, intCtx.Namespace, pSvcAccount.GetName())
 			})
 
 			It("should create the role and role binding", func() {
@@ -102,7 +102,7 @@ var _ = Describe("ProviderServiceAccount controller integration tests", func() {
 
 			It("Should reconcile", func() {
 				By("Creating the target secret in the target namespace")
-				assertTargetSecret(ctx, intCtx.GuestClient, pSvcAccount.Spec.TargetNamespace, testTargetSecret)
+				assertTargetSecret(intCtx, intCtx.GuestClient, pSvcAccount.Spec.TargetNamespace, testTargetSecret)
 			})
 		})
 
@@ -113,16 +113,16 @@ var _ = Describe("ProviderServiceAccount controller integration tests", func() {
 						Name: pSvcAccount.Spec.TargetNamespace,
 					},
 				}
-				Expect(intCtx.GuestClient.Create(ctx, targetNSObj)).To(Succeed())
-				createTargetSecretWithInvalidToken(ctx, intCtx.GuestClient, pSvcAccount.Spec.TargetNamespace)
-				assertServiceAccountAndUpdateSecret(ctx, intCtx.Client, intCtx.Namespace, pSvcAccount.GetName())
+				Expect(intCtx.GuestClient.Create(intCtx, targetNSObj)).To(Succeed())
+				createTargetSecretWithInvalidToken(intCtx, intCtx.GuestClient, pSvcAccount.Spec.TargetNamespace)
+				assertServiceAccountAndUpdateSecret(intCtx, intCtx.Client, intCtx.Namespace, pSvcAccount.GetName())
 			})
 			AfterEach(func() {
-				deleteTestResource(ctx, intCtx.GuestClient, targetNSObj)
+				deleteTestResource(intCtx, intCtx.GuestClient, targetNSObj)
 			})
 			It("Should reconcile", func() {
 				By("Updating the target secret in the target namespace")
-				assertTargetSecret(ctx, intCtx.GuestClient, pSvcAccount.Spec.TargetNamespace, testTargetSecret)
+				assertTargetSecret(intCtx, intCtx.GuestClient, pSvcAccount.Spec.TargetNamespace, testTargetSecret)
 			})
 		})
 	})
@@ -134,20 +134,20 @@ var _ = Describe("ProviderServiceAccount controller integration tests", func() {
 				Expect(ok).To(BeTrue())
 				cluster := &clusterv1.Cluster{}
 				key := client.ObjectKey{Namespace: intCtx.Namespace, Name: clusterName}
-				Expect(intCtx.Client.Get(ctx, key, cluster)).To(Succeed())
-				Expect(intCtx.Client.Delete(ctx, cluster)).To(Succeed())
+				Expect(intCtx.Client.Get(intCtx, key, cluster)).To(Succeed())
+				Expect(intCtx.Client.Delete(intCtx, cluster)).To(Succeed())
 			})
 
 			By("Creating the ProviderServiceAccount", func() {
 				pSvcAccount := getTestProviderServiceAccount(intCtx.Namespace, intCtx.VSphereCluster)
-				createTestResource(ctx, intCtx.Client, pSvcAccount)
-				assertEventuallyExistsInNamespace(ctx, intCtx.Client, intCtx.Namespace, pSvcAccount.GetName(), pSvcAccount)
+				createTestResource(intCtx, intCtx.Client, pSvcAccount)
+				assertEventuallyExistsInNamespace(intCtx, intCtx.Client, intCtx.Namespace, pSvcAccount.GetName(), pSvcAccount)
 			})
 
 			By("ProviderServiceAccountsReady Condition is not set", func() {
 				vsphereCluster := &vmwarev1.VSphereCluster{}
 				key := client.ObjectKey{Namespace: intCtx.Namespace, Name: intCtx.VSphereCluster.GetName()}
-				Expect(intCtx.Client.Get(ctx, key, vsphereCluster)).To(Succeed())
+				Expect(intCtx.Client.Get(intCtx, key, vsphereCluster)).To(Succeed())
 				Expect(conditions.Has(vsphereCluster, vmwarev1.ProviderServiceAccountsReadyCondition)).To(BeFalse())
 			})
 		})
@@ -164,19 +164,19 @@ var _ = Describe("ProviderServiceAccount controller integration tests", func() {
 						Name:      fmt.Sprintf("%s-kubeconfig", clusterName),
 					},
 				}
-				Expect(intCtx.Client.Delete(ctx, secret)).To(Succeed())
+				Expect(intCtx.Client.Delete(intCtx, secret)).To(Succeed())
 			})
 
 			By("Creating the ProviderServiceAccount", func() {
 				pSvcAccount := getTestProviderServiceAccount(intCtx.Namespace, intCtx.VSphereCluster)
-				createTestResource(ctx, intCtx.Client, pSvcAccount)
-				assertEventuallyExistsInNamespace(ctx, intCtx.Client, intCtx.Namespace, pSvcAccount.GetName(), pSvcAccount)
+				createTestResource(intCtx, intCtx.Client, pSvcAccount)
+				assertEventuallyExistsInNamespace(intCtx, intCtx.Client, intCtx.Namespace, pSvcAccount.GetName(), pSvcAccount)
 			})
 
 			By("ProviderServiceAccountsReady Condition is not set", func() {
 				vsphereCluster := &vmwarev1.VSphereCluster{}
 				key := client.ObjectKey{Namespace: intCtx.Namespace, Name: intCtx.VSphereCluster.GetName()}
-				Expect(intCtx.Client.Get(ctx, key, vsphereCluster)).To(Succeed())
+				Expect(intCtx.Client.Get(intCtx, key, vsphereCluster)).To(Succeed())
 				Expect(conditions.Has(vsphereCluster, vmwarev1.ProviderServiceAccountsReadyCondition)).To(BeFalse())
 			})
 		})
@@ -193,7 +193,7 @@ var _ = Describe("ProviderServiceAccount controller integration tests", func() {
 			pSvcAccount.ObjectMeta.Annotations = map[string]string{
 				"cluster.x-k8s.io/paused": "true",
 			}
-			createTestResource(ctx, intCtx.Client, pSvcAccount)
+			createTestResource(intCtx, intCtx.Client, pSvcAccount)
 			oldOwnerUID := uuid.New().String()
 
 			role = &rbacv1.Role{
@@ -246,9 +246,9 @@ var _ = Describe("ProviderServiceAccount controller integration tests", func() {
 				},
 			}
 
-			createTestResource(ctx, intCtx.Client, role)
-			createTestResource(ctx, intCtx.Client, roleBinding)
-			assertEventuallyExistsInNamespace(ctx, intCtx.Client, intCtx.Namespace, pSvcAccount.GetName(), pSvcAccount)
+			createTestResource(intCtx, intCtx.Client, role)
+			createTestResource(intCtx, intCtx.Client, roleBinding)
+			assertEventuallyExistsInNamespace(intCtx, intCtx.Client, intCtx.Namespace, pSvcAccount.GetName(), pSvcAccount)
 			svcAccountPatcher, err := patch.NewHelper(pSvcAccount, intCtx.Client)
 			Expect(err).ToNot(HaveOccurred())
 			// Unpause the ProviderServiceAccount so we can reconcile
@@ -256,9 +256,9 @@ var _ = Describe("ProviderServiceAccount controller integration tests", func() {
 			Expect(svcAccountPatcher.Patch(ctx, pSvcAccount)).To(Succeed())
 		})
 		AfterEach(func() {
-			deleteTestResource(ctx, intCtx.Client, pSvcAccount)
-			deleteTestResource(ctx, intCtx.Client, role)
-			deleteTestResource(ctx, intCtx.Client, roleBinding)
+			deleteTestResource(intCtx, intCtx.Client, pSvcAccount)
+			deleteTestResource(intCtx, intCtx.Client, role)
+			deleteTestResource(intCtx, intCtx.Client, roleBinding)
 		})
 
 		It("should fully reconciles dependent resources", func() {
diff --git a/controllers/serviceaccount_controller_suite_test.go b/controllers/serviceaccount_controller_suite_test.go
index 4dc971f6..9347ceab 100644
--- a/controllers/serviceaccount_controller_suite_test.go
+++ b/controllers/serviceaccount_controller_suite_test.go
@@ -32,6 +32,7 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
 	vmwarev1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/vmware/v1beta1"
+	helpers "sigs.k8s.io/cluster-api-provider-vsphere/test/helpers/vmware"
 )
 
 const (
@@ -139,12 +140,12 @@ func assertRoleWithGetPVC(ctx context.Context, ctrlClient client.Client, namespa
 	}))
 }
 
-func assertRoleBinding(ctx context.Context, ctrlClient client.Client, namespace, name string) {
+func assertRoleBinding(_ *helpers.UnitTestContextForController, ctrlClient client.Client, namespace, name string) {
 	var roleBindingList rbacv1.RoleBindingList
 	opts := &client.ListOptions{
 		Namespace: namespace,
 	}
-	err := ctrlClient.List(ctx, &roleBindingList, opts)
+	err := ctrlClient.List(context.TODO(), &roleBindingList, opts)
 	Expect(err).ShouldNot(HaveOccurred())
 	Expect(roleBindingList.Items).To(HaveLen(1))
 	Expect(roleBindingList.Items[0].Name).To(Equal(name))
diff --git a/controllers/serviceaccount_controller_unit_test.go b/controllers/serviceaccount_controller_unit_test.go
index 24434bdc..ed19a24a 100644
--- a/controllers/serviceaccount_controller_unit_test.go
+++ b/controllers/serviceaccount_controller_unit_test.go
@@ -44,7 +44,7 @@ func unitTestsReconcileNormal() {
 	)
 
 	JustBeforeEach(func() {
-		controllerCtx = helpers.NewUnitTestContextForController(ctx, namespace, vsphereCluster, false, initObjects, nil)
+		controllerCtx = helpers.NewUnitTestContextForController(namespace, vsphereCluster, false, initObjects, nil)
 		// Note: The service account provider requires a reference to the vSphereCluster hence the need to create
 		// a fake vSphereCluster in the test and pass it to during context setup.
 		reconciler = ServiceAccountReconciler{
@@ -128,7 +128,7 @@ func unitTestsReconcileNormal() {
 				initObjects = append(initObjects, getTestRoleBindingWithInvalidRoleRef(namespace, vsphereCluster.GetName()))
 			})
 			It("Should update rolebinding", func() {
-				assertRoleBinding(ctx, controllerCtx.ControllerContext.Client, namespace, vsphereCluster.GetName())
+				assertRoleBinding(controllerCtx, controllerCtx.ControllerContext.Client, namespace, vsphereCluster.GetName())
 				assertProviderServiceAccountsCondition(controllerCtx.VSphereCluster, corev1.ConditionTrue, "", "", "")
 			})
 		})
diff --git a/controllers/servicediscovery_controller_intg_test.go b/controllers/servicediscovery_controller_intg_test.go
index 98b704ff..fe5c9fb2 100644
--- a/controllers/servicediscovery_controller_intg_test.go
+++ b/controllers/servicediscovery_controller_intg_test.go
@@ -42,17 +42,17 @@ var _ = Describe("Service Discovery controller integration tests", func() {
 			initObjects = []client.Object{
 				newTestSupervisorLBServiceWithIPStatus(),
 			}
-			createObjects(ctx, intCtx.Client, initObjects)
+			createObjects(intCtx, intCtx.Client, initObjects)
 			Expect(intCtx.Client.Status().Update(ctx, newTestSupervisorLBServiceWithIPStatus())).To(Succeed())
 		})
 		AfterEach(func() {
-			deleteObjects(ctx, intCtx.Client, initObjects)
+			deleteObjects(intCtx, intCtx.Client, initObjects)
 		})
 		It("Should reconcile headless svc", func() {
 			By("creating a service and endpoints using the VIP in the guest cluster")
 			headlessSvc := &corev1.Service{}
-			assertEventuallyExistsInNamespace(ctx, intCtx.Client, "kube-system", "kube-apiserver-lb-svc", headlessSvc)
-			assertHeadlessSvcWithVIPEndpoints(ctx, intCtx.GuestClient, supervisorHeadlessSvcNamespace, supervisorHeadlessSvcName)
+			assertEventuallyExistsInNamespace(intCtx, intCtx.Client, "kube-system", "kube-apiserver-lb-svc", headlessSvc)
+			assertHeadlessSvcWithVIPEndpoints(intCtx, intCtx.GuestClient, supervisorHeadlessSvcNamespace, supervisorHeadlessSvcName)
 		})
 	})
 
@@ -60,33 +60,33 @@ var _ = Describe("Service Discovery controller integration tests", func() {
 		BeforeEach(func() {
 			initObjects = []client.Object{
 				newTestConfigMapWithHost(testSupervisorAPIServerFIP)}
-			createObjects(ctx, intCtx.Client, initObjects)
+			createObjects(intCtx, intCtx.Client, initObjects)
 		})
 		AfterEach(func() {
-			deleteObjects(ctx, intCtx.Client, initObjects)
+			deleteObjects(intCtx, intCtx.Client, initObjects)
 		})
 		It("Should reconcile headless svc", func() {
 			By("creating a service and endpoints using the FIP in the guest cluster")
-			assertHeadlessSvcWithFIPEndpoints(ctx, intCtx.GuestClient, supervisorHeadlessSvcNamespace, supervisorHeadlessSvcName)
+			assertHeadlessSvcWithFIPEndpoints(intCtx, intCtx.GuestClient, supervisorHeadlessSvcNamespace, supervisorHeadlessSvcName)
 		})
 	})
 	Context("When headless svc and endpoints already exists", func() {
 		BeforeEach(func() {
 			// Create the svc & endpoint objects in guest cluster
-			createObjects(ctx, intCtx.GuestClient, newTestHeadlessSvcEndpoints())
+			createObjects(intCtx, intCtx.GuestClient, newTestHeadlessSvcEndpoints())
 			// Init objects in the supervisor cluster
 			initObjects = []client.Object{
 				newTestSupervisorLBServiceWithIPStatus()}
-			createObjects(ctx, intCtx.Client, initObjects)
+			createObjects(intCtx, intCtx.Client, initObjects)
 			Expect(intCtx.Client.Status().Update(ctx, newTestSupervisorLBServiceWithIPStatus())).To(Succeed())
 		})
 		AfterEach(func() {
-			deleteObjects(ctx, intCtx.Client, initObjects)
+			deleteObjects(intCtx, intCtx.Client, initObjects)
 			// Note: No need to delete guest cluster objects as a new guest cluster testenv endpoint is created for each test.
 		})
 		It("Should reconcile headless svc", func() {
 			By("updating the service and endpoints using the VIP in the guest cluster")
-			assertHeadlessSvcWithUpdatedVIPEndpoints(ctx, intCtx.GuestClient, supervisorHeadlessSvcNamespace, supervisorHeadlessSvcName)
+			assertHeadlessSvcWithUpdatedVIPEndpoints(intCtx, intCtx.GuestClient, supervisorHeadlessSvcNamespace, supervisorHeadlessSvcName)
 		})
 	})
 })
diff --git a/controllers/servicediscovery_controller_unit_test.go b/controllers/servicediscovery_controller_unit_test.go
index 19b22495..a631dc82 100644
--- a/controllers/servicediscovery_controller_unit_test.go
+++ b/controllers/servicediscovery_controller_unit_test.go
@@ -42,7 +42,7 @@ func serviceDiscoveryUnitTestsReconcileNormal() {
 	namespace := capiutil.RandomString(6)
 	JustBeforeEach(func() {
 		vsphereCluster = fake.NewVSphereCluster(namespace)
-		controllerCtx = helpers.NewUnitTestContextForController(ctx, namespace, &vsphereCluster, false, initObjects, nil)
+		controllerCtx = helpers.NewUnitTestContextForController(namespace, &vsphereCluster, false, initObjects, nil)
 		reconciler = serviceDiscoveryReconciler{
 			Client:   controllerCtx.ControllerContext.Client,
 			Recorder: controllerCtx.ControllerContext.Recorder,
diff --git a/controllers/vmware/vspherecluster_reconciler_test.go b/controllers/vmware/vspherecluster_reconciler_test.go
index 3d74f556..a7199f18 100644
--- a/controllers/vmware/vspherecluster_reconciler_test.go
+++ b/controllers/vmware/vspherecluster_reconciler_test.go
@@ -17,6 +17,7 @@ limitations under the License.
 package vmware
 
 import (
+	"context"
 	"testing"
 
 	. "github.com/onsi/ginkgo/v2"
@@ -84,13 +85,13 @@ var _ = Describe("Cluster Controller Tests", func() {
 	// Ensure that the mechanism for reconciling clusters when a control plane machine gets an IP works
 	Context("Test controlPlaneMachineToCluster", func() {
 		It("Returns nil if there is no IP address", func() {
-			request := reconciler.VSphereMachineToCluster(ctx, vsphereMachine)
+			request := reconciler.VSphereMachineToCluster(context.Background(), vsphereMachine)
 			Expect(request).Should(BeNil())
 		})
 
 		It("Returns valid request with IP address", func() {
 			vsphereMachine.Status.IPAddr = testIP
-			request := reconciler.VSphereMachineToCluster(ctx, vsphereMachine)
+			request := reconciler.VSphereMachineToCluster(context.Background(), vsphereMachine)
 			Expect(request).ShouldNot(BeNil())
 			Expect(request[0].Namespace).Should(Equal(cluster.Namespace))
 			Expect(request[0].Name).Should(Equal(cluster.Name))
diff --git a/controllers/vspherecluster_reconciler_test.go b/controllers/vspherecluster_reconciler_test.go
index bd5ea5b4..003df5d1 100644
--- a/controllers/vspherecluster_reconciler_test.go
+++ b/controllers/vspherecluster_reconciler_test.go
@@ -162,6 +162,7 @@ var _ = Describe("VIM based VSphere ClusterReconciler", func() {
 
 		It("should error if secret is already owned by a different cluster", func() {
 			ctx := context.Background()
+
 			capiCluster := &clusterv1.Cluster{
 				ObjectMeta: metav1.ObjectMeta{
 					GenerateName: "test1-",
@@ -245,6 +246,7 @@ var _ = Describe("VIM based VSphere ClusterReconciler", func() {
 	})
 	Context("Reconcile delete", func() {
 		var (
+			ctx             context.Context
 			secret          *corev1.Secret
 			capiCluster     *clusterv1.Cluster
 			instance        *infrav1.VSphereCluster
@@ -252,7 +254,7 @@ var _ = Describe("VIM based VSphere ClusterReconciler", func() {
 			key             client.ObjectKey
 		)
 		It("should remove legacy finalizer if present during the cluster deletion", func() {
-			ctx := context.Background()
+			ctx = context.Background()
 			capiCluster = &clusterv1.Cluster{
 				ObjectMeta: metav1.ObjectMeta{
 					GenerateName: "test1-",
@@ -356,6 +358,7 @@ var _ = Describe("VIM based VSphere ClusterReconciler", func() {
 
 	It("should remove vspherecluster finalizer if the secret does not exist", func() {
 		ctx := context.Background()
+
 		capiCluster := &clusterv1.Cluster{
 			ObjectMeta: metav1.ObjectMeta{
 				GenerateName: "test1-",
@@ -697,7 +700,7 @@ func TestClusterReconciler_ReconcileDeploymentZones(t *testing.T) {
 			t.Run(tt.name, func(t *testing.T) {
 				g := NewWithT(t)
 				controllerCtx := fake.NewControllerContext(fake.NewControllerManagerContext(tt.initObjs...))
-				clusterCtx := fake.NewClusterContext(ctx, controllerCtx)
+				clusterCtx := fake.NewClusterContext(controllerCtx)
 				clusterCtx.VSphereCluster.Spec.Server = server
 
 				r := clusterReconciler{
@@ -769,7 +772,7 @@ func TestClusterReconciler_ReconcileDeploymentZones(t *testing.T) {
 			t.Run(tt.name, func(t *testing.T) {
 				g := NewWithT(t)
 				controllerCtx := fake.NewControllerContext(fake.NewControllerManagerContext(tt.initObjs...))
-				clusterCtx := fake.NewClusterContext(ctx, controllerCtx)
+				clusterCtx := fake.NewClusterContext(controllerCtx)
 				clusterCtx.VSphereCluster.Spec.Server = server
 				clusterCtx.VSphereCluster.Spec.FailureDomainSelector = &metav1.LabelSelector{MatchLabels: map[string]string{}}
 
@@ -805,7 +808,7 @@ func TestClusterReconciler_ReconcileDeploymentZones(t *testing.T) {
 
 		assertNumberOfZones := func(selector *metav1.LabelSelector, selectedZones int) {
 			controllerCtx := fake.NewControllerContext(fake.NewControllerManagerContext(zoneOne, zoneTwo, zoneThree))
-			clusterCtx := fake.NewClusterContext(ctx, controllerCtx)
+			clusterCtx := fake.NewClusterContext(controllerCtx)
 			clusterCtx.VSphereCluster.Spec.Server = server
 			clusterCtx.VSphereCluster.Spec.FailureDomainSelector = selector
 
diff --git a/controllers/vsphereclusteridentity_controller_test.go b/controllers/vsphereclusteridentity_controller_test.go
index 77dcb9b0..82075031 100644
--- a/controllers/vsphereclusteridentity_controller_test.go
+++ b/controllers/vsphereclusteridentity_controller_test.go
@@ -29,7 +29,7 @@ import (
 )
 
 var _ = Describe("VSphereClusterIdentity Reconciler", func() {
-	controllerNamespace := testEnv.Manager.GetControllerManagerContext().Namespace
+	controllerNamespace := testEnv.Manager.GetContext().Namespace
 
 	Context("Reconcile Normal", func() {
 		It("should set the ownerRef on a secret and set Ready condition", func() {
diff --git a/controllers/vspheredeploymentzone_controller_domain_test.go b/controllers/vspheredeploymentzone_controller_domain_test.go
index 9fde52fc..6fc93dff 100644
--- a/controllers/vspheredeploymentzone_controller_domain_test.go
+++ b/controllers/vspheredeploymentzone_controller_domain_test.go
@@ -62,7 +62,7 @@ func TestVsphereDeploymentZoneReconciler_Reconcile_VerifyFailureDomain_ComputeCl
 		WithServer(simr.ServerURL().Host).
 		WithUserInfo(simr.Username(), simr.Password()).
 		WithDatacenter("*")
-	authSession, err := session.GetOrCreate(ctx, params)
+	authSession, err := session.GetOrCreate(controllerCtx, params)
 	g.Expect(err).NotTo(HaveOccurred())
 
 	vsphereFailureDomain := &infrav1.VSphereFailureDomain{
diff --git a/controllers/vspheredeploymentzone_controller_test.go b/controllers/vspheredeploymentzone_controller_test.go
index e0bf5ef0..5a74a72c 100644
--- a/controllers/vspheredeploymentzone_controller_test.go
+++ b/controllers/vspheredeploymentzone_controller_test.go
@@ -17,6 +17,7 @@ limitations under the License.
 package controllers
 
 import (
+	"context"
 	"testing"
 
 	"github.com/go-logr/logr"
@@ -616,7 +617,7 @@ func TestVsphereDeploymentZone_Failed_ReconcilePlacementConstraint(t *testing.T)
 			mgmtContext.Password = pass
 
 			controllerCtx := fake.NewControllerContext(mgmtContext)
-			Expect(controllerCtx.Client.Create(ctx, &infrav1.VSphereFailureDomain{
+			Expect(controllerCtx.Client.Create(controllerCtx, &infrav1.VSphereFailureDomain{
 				ObjectMeta: metav1.ObjectMeta{
 					Name: "blah",
 				},
@@ -791,7 +792,7 @@ func TestVSphereDeploymentZoneReconciler_ReconcileDelete(t *testing.T) {
 			g.Expect(err).NotTo(HaveOccurred())
 
 			fetchedFailureDomain := &infrav1.VSphereFailureDomain{}
-			g.Expect(mgmtContext.Client.Get(ctx, client.ObjectKey{Name: vsphereFailureDomain.Name}, fetchedFailureDomain)).To(Succeed())
+			g.Expect(mgmtContext.Client.Get(context.Background(), client.ObjectKey{Name: vsphereFailureDomain.Name}, fetchedFailureDomain)).To(Succeed())
 			g.Expect(fetchedFailureDomain.OwnerReferences).To(HaveLen(1))
 		})
 	})
diff --git a/controllers/vspherevm_controller_test.go b/controllers/vspherevm_controller_test.go
index b0d8c8cc..02508078 100644
--- a/controllers/vspherevm_controller_test.go
+++ b/controllers/vspherevm_controller_test.go
@@ -370,7 +370,7 @@ func TestVmReconciler_WaitingForStaticIPAllocation(t *testing.T) {
 	}
 
 	controllerCtx := fake.NewControllerContext(fake.NewControllerManagerContext())
-	vmContext := fake.NewVMContext(context.Background(), controllerCtx)
+	vmContext := fake.NewVMContext(controllerCtx)
 	r := vmReconciler{ControllerContext: controllerCtx}
 
 	for _, tt := range tests {
diff --git a/controllers/vspherevm_ipaddress_reconciler_test.go b/controllers/vspherevm_ipaddress_reconciler_test.go
index 063df2a9..66b83974 100644
--- a/controllers/vspherevm_ipaddress_reconciler_test.go
+++ b/controllers/vspherevm_ipaddress_reconciler_test.go
@@ -40,14 +40,13 @@ import (
 func Test_vmReconciler_reconcileIPAddressClaims(t *testing.T) {
 	name, namespace := "test-vm", "my-namespace"
 	setup := func(vsphereVM *infrav1.VSphereVM, initObjects ...client.Object) *capvcontext.VMContext {
-		controllerCtx := fake.NewControllerContext(fake.NewControllerManagerContext(initObjects...))
+		ctx := fake.NewControllerContext(fake.NewControllerManagerContext(initObjects...))
 		return &capvcontext.VMContext{
-			ControllerContext: controllerCtx,
+			ControllerContext: ctx,
 			VSphereVM:         vsphereVM,
 			Logger:            logr.Discard(),
 		}
 	}
-	ctx := context.Background()
 
 	t.Run("when VSphereVM Spec has address pool references", func(t *testing.T) {
 		vsphereVM := &infrav1.VSphereVM{
@@ -85,7 +84,7 @@ func Test_vmReconciler_reconcileIPAddressClaims(t *testing.T) {
 			g.Expect(err).ToNot(gomega.HaveOccurred())
 
 			ipAddrClaimList := &ipamv1.IPAddressClaimList{}
-			g.Expect(testCtx.Client.List(ctx, ipAddrClaimList)).To(gomega.Succeed())
+			g.Expect(testCtx.Client.List(context.TODO(), ipAddrClaimList)).To(gomega.Succeed())
 			g.Expect(ipAddrClaimList.Items).To(gomega.HaveLen(3))
 
 			for idx := range ipAddrClaimList.Items {
@@ -134,7 +133,7 @@ func Test_vmReconciler_reconcileIPAddressClaims(t *testing.T) {
 			g.Expect(claimedCondition.Message).To(gomega.Equal("3/3 claims being processed"))
 
 			ipAddrClaimList := &ipamv1.IPAddressClaimList{}
-			g.Expect(testCtx.Client.List(ctx, ipAddrClaimList)).To(gomega.Succeed())
+			g.Expect(testCtx.Client.List(context.TODO(), ipAddrClaimList)).To(gomega.Succeed())
 
 			for idx := range ipAddrClaimList.Items {
 				claim := ipAddrClaimList.Items[idx]
@@ -168,7 +167,7 @@ func Test_vmReconciler_reconcileIPAddressClaims(t *testing.T) {
 			g.Expect(claimedCondition.Status).To(gomega.Equal(corev1.ConditionTrue))
 
 			ipAddrClaimList := &ipamv1.IPAddressClaimList{}
-			g.Expect(testCtx.Client.List(ctx, ipAddrClaimList)).To(gomega.Succeed())
+			g.Expect(testCtx.Client.List(context.TODO(), ipAddrClaimList)).To(gomega.Succeed())
 
 			for idx := range ipAddrClaimList.Items {
 				claim := ipAddrClaimList.Items[idx]
diff --git a/pkg/clustermodule/service_test.go b/pkg/clustermodule/service_test.go
index 6737f7aa..8fdaaa17 100644
--- a/pkg/clustermodule/service_test.go
+++ b/pkg/clustermodule/service_test.go
@@ -32,7 +32,6 @@ import (
 
 func TestService_Create(t *testing.T) {
 	t.Run("creation is skipped", func(t *testing.T) {
-		ctx := context.Background()
 		t.Run("when wrapper points to template != VSphereMachineTemplate", func(t *testing.T) {
 			md := machineDeployment("md", fake.Namespace, fake.Clusterv1a2Name)
 			md.Spec.Template.Spec.InfrastructureRef = corev1.ObjectReference{
@@ -43,10 +42,10 @@ func TestService_Create(t *testing.T) {
 
 			g := gomega.NewWithT(t)
 			controllerCtx := fake.NewControllerContext(fake.NewControllerManagerContext(md))
-			clusterCtx := fake.NewClusterContext(ctx, controllerCtx)
+			clusterCtx := fake.NewClusterContext(controllerCtx)
 			svc := NewService(controllerCtx.ControllerManagerContext, controllerCtx.Client)
 
-			moduleUUID, err := svc.Create(ctx, clusterCtx, mdWrapper{md})
+			moduleUUID, err := svc.Create(context.Background(), clusterCtx, mdWrapper{md})
 			g.Expect(err).ToNot(gomega.HaveOccurred())
 			g.Expect(moduleUUID).To(gomega.BeEmpty())
 		})
@@ -74,10 +73,10 @@ func TestService_Create(t *testing.T) {
 
 			g := gomega.NewWithT(t)
 			controllerCtx := fake.NewControllerContext(fake.NewControllerManagerContext(md, machineTemplate))
-			clusterCtx := fake.NewClusterContext(ctx, controllerCtx)
+			clusterCtx := fake.NewClusterContext(controllerCtx)
 			svc := NewService(controllerCtx.ControllerManagerContext, controllerCtx.Client)
 
-			moduleUUID, err := svc.Create(ctx, clusterCtx, mdWrapper{md})
+			moduleUUID, err := svc.Create(context.Background(), clusterCtx, mdWrapper{md})
 			g.Expect(err).ToNot(gomega.HaveOccurred())
 			g.Expect(moduleUUID).To(gomega.BeEmpty())
 		})
diff --git a/pkg/clustermodule/util_test.go b/pkg/clustermodule/util_test.go
index c2d76cc0..531c5cae 100644
--- a/pkg/clustermodule/util_test.go
+++ b/pkg/clustermodule/util_test.go
@@ -23,7 +23,7 @@ import (
 	"github.com/onsi/gomega"
 
 	infrav1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1"
-	capvcontext "sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
+	"sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
 )
 
 func Test_IsCompatible(t *testing.T) {
@@ -65,7 +65,7 @@ func Test_IsCompatible(t *testing.T) {
 			}
 
 			g := gomega.NewWithT(t)
-			isCompatible := IsClusterCompatible(&capvcontext.ClusterContext{
+			isCompatible := IsClusterCompatible(&context.ClusterContext{
 				VSphereCluster: cluster,
 			})
 			g.Expect(isCompatible).To(gomega.Equal(tt.isCompatible))
diff --git a/pkg/services/govmomi/cluster/cluster_suite_test.go b/pkg/services/govmomi/cluster/cluster_suite_test.go
index 5187c9ec..d872a74c 100644
--- a/pkg/services/govmomi/cluster/cluster_suite_test.go
+++ b/pkg/services/govmomi/cluster/cluster_suite_test.go
@@ -17,6 +17,7 @@ limitations under the License.
 package cluster
 
 import (
+	"context"
 	"testing"
 
 	. "github.com/onsi/ginkgo/v2"
@@ -32,7 +33,8 @@ func TestCluster(t *testing.T) {
 }
 
 type testComputeClusterCtx struct {
-	finder *find.Finder
+	context.Context //nolint:containedctx
+	finder          *find.Finder
 }
 
 func (t testComputeClusterCtx) GetSession() *session.Session {
diff --git a/pkg/services/govmomi/cluster/rule_test.go b/pkg/services/govmomi/cluster/rule_test.go
index 1aef90c0..05b14b6b 100644
--- a/pkg/services/govmomi/cluster/rule_test.go
+++ b/pkg/services/govmomi/cluster/rule_test.go
@@ -47,7 +47,8 @@ func TestVerifyAffinityRule(t *testing.T) {
 	finder.SetDatacenter(dc)
 
 	computeClusterCtx := testComputeClusterCtx{
-		finder: finder,
+		Context: context.Background(),
+		finder:  finder,
 	}
 
 	rule, err := VerifyAffinityRule(ctx, computeClusterCtx, "DC0_C0", "blah-host-group", "blah-vm-group")
diff --git a/pkg/services/govmomi/cluster/service_test.go b/pkg/services/govmomi/cluster/service_test.go
index 403e9101..027d303e 100644
--- a/pkg/services/govmomi/cluster/service_test.go
+++ b/pkg/services/govmomi/cluster/service_test.go
@@ -38,25 +38,24 @@ func TestListHostsFromGroup(t *testing.T) {
 	}
 	defer sim.Destroy()
 
-	ctx := context.Background()
-	client, _ := govmomi.NewClient(ctx, sim.ServerURL(), true)
+	client, _ := govmomi.NewClient(context.Background(), sim.ServerURL(), true)
 	finder := find.NewFinder(client.Client, false)
 
-	dc, _ := finder.DatacenterOrDefault(ctx, "DC0")
+	dc, _ := finder.DatacenterOrDefault(context.Background(), "DC0")
 	finder.SetDatacenter(dc)
 
-	ccr, err := finder.ClusterComputeResource(ctx, "DC0_C0")
+	ccr, err := finder.ClusterComputeResource(context.Background(), "DC0_C0")
 	g.Expect(err).NotTo(HaveOccurred())
 
-	refs, err := ListHostsFromGroup(ctx, ccr, "test_grp_1")
+	refs, err := ListHostsFromGroup(context.Background(), ccr, "test_grp_1")
 	g.Expect(err).NotTo(HaveOccurred())
 	g.Expect(refs).To(HaveLen(2))
 
-	refs, err = ListHostsFromGroup(ctx, ccr, "test_grp_2")
+	refs, err = ListHostsFromGroup(context.Background(), ccr, "test_grp_2")
 	g.Expect(err).NotTo(HaveOccurred())
 	g.Expect(refs).To(HaveLen(1))
 
-	refs, err = ListHostsFromGroup(ctx, ccr, "blah")
+	refs, err = ListHostsFromGroup(context.Background(), ccr, "blah")
 	g.Expect(err).NotTo(HaveOccurred())
 	g.Expect(refs).To(BeEmpty())
 }
diff --git a/pkg/services/govmomi/cluster/vmgroup_test.go b/pkg/services/govmomi/cluster/vmgroup_test.go
index d2d82068..a61be9e5 100644
--- a/pkg/services/govmomi/cluster/vmgroup_test.go
+++ b/pkg/services/govmomi/cluster/vmgroup_test.go
@@ -43,7 +43,8 @@ func Test_VMGroup(t *testing.T) {
 	finder.SetDatacenter(dc)
 
 	computeClusterCtx := testComputeClusterCtx{
-		finder: finder,
+		Context: context.Background(),
+		finder:  finder,
 	}
 
 	computeClusterName := "DC0_C0"
@@ -61,7 +62,7 @@ func Test_VMGroup(t *testing.T) {
 	g.Expect(err).NotTo(HaveOccurred())
 	g.Expect(hasVM).To(BeFalse())
 
-	task, err := vmGrp.Add(ctx, vmRef)
+	task, err := vmGrp.Add(computeClusterCtx, vmRef)
 	g.Expect(err).NotTo(HaveOccurred())
 	g.Expect(task.Wait(ctx)).To(Succeed())
 	g.Expect(vmGrp.listVMs()).To(HaveLen(3))
diff --git a/pkg/services/govmomi/create_test.go b/pkg/services/govmomi/create_test.go
index 2ef46e5a..ebf26bd7 100644
--- a/pkg/services/govmomi/create_test.go
+++ b/pkg/services/govmomi/create_test.go
@@ -40,12 +40,11 @@ func TestCreate(t *testing.T) {
 	}
 	defer simr.Destroy()
 
-	ctx := context.Background()
-	vmContext := fake.NewVMContext(ctx, fake.NewControllerContext(fake.NewControllerManagerContext()))
+	vmContext := fake.NewVMContext(fake.NewControllerContext(fake.NewControllerManagerContext()))
 	vmContext.VSphereVM.Spec.Server = simr.ServerURL().Host
 
 	authSession, err := session.GetOrCreate(
-		ctx,
+		vmContext.Context,
 		session.NewParams().
 			WithServer(vmContext.VSphereVM.Spec.Server).
 			WithUserInfo(simr.Username(), simr.Password()).
@@ -64,6 +63,7 @@ func TestCreate(t *testing.T) {
 
 	disk := object.VirtualDeviceList(vm.Config.Hardware.Device).SelectByType((*types.VirtualDisk)(nil))[0].(*types.VirtualDisk)
 	disk.CapacityInKB = int64(vmContext.VSphereVM.Spec.DiskGiB) * 1024 * 1024
+	ctx := context.Background()
 
 	if err := createVM(ctx, vmContext, []byte(""), ""); err != nil {
 		t.Fatal(err)
@@ -73,12 +73,12 @@ func TestCreate(t *testing.T) {
 		Type:  morefTypeTask,
 		Value: vmContext.VSphereVM.Status.TaskRef,
 	}
-	vimClient, err := vim25.NewClient(ctx, vmContext.Session.RoundTripper)
+	vimClient, err := vim25.NewClient(vmContext, vmContext.Session.RoundTripper)
 	if err != nil {
 		t.Fatal("could not make vim25 client.")
 	}
 	task := object.NewTask(vimClient, taskRef)
-	err = task.Wait(ctx)
+	err = task.Wait(vmContext)
 	if err != nil {
 		t.Fatal("error waiting for task:", err)
 	}
diff --git a/pkg/services/govmomi/ipam/status_test.go b/pkg/services/govmomi/ipam/status_test.go
index 9aeec95b..407f6601 100644
--- a/pkg/services/govmomi/ipam/status_test.go
+++ b/pkg/services/govmomi/ipam/status_test.go
@@ -49,8 +49,8 @@ func Test_buildIPAMDeviceConfigs(t *testing.T) {
 	)
 
 	before := func() {
+		vmCtx = *fake.NewVMContext(fake.NewControllerContext(fake.NewControllerManagerContext()))
 		ctx = context.Background()
-		vmCtx = *fake.NewVMContext(ctx, fake.NewControllerContext(fake.NewControllerManagerContext()))
 		networkStatus = []infrav1.NetworkStatus{
 			{Connected: true, MACAddr: devMAC},
 		}
@@ -251,7 +251,7 @@ func Test_BuildState(t *testing.T) {
 
 	before := func() {
 		ctx = context.Background()
-		vmCtx = *fake.NewVMContext(ctx, fake.NewControllerContext(fake.NewControllerManagerContext()))
+		vmCtx = *fake.NewVMContext(fake.NewControllerContext(fake.NewControllerManagerContext()))
 		networkStatus = []infrav1.NetworkStatus{
 			{Connected: true, MACAddr: devMAC},
 		}
diff --git a/pkg/services/govmomi/metadata/metadata_suite_test.go b/pkg/services/govmomi/metadata/metadata_suite_test.go
index 5c20e3a2..016b7e93 100644
--- a/pkg/services/govmomi/metadata/metadata_suite_test.go
+++ b/pkg/services/govmomi/metadata/metadata_suite_test.go
@@ -54,7 +54,7 @@ var (
 )
 
 var _ = BeforeSuite(func() {
-	Expect(configureSimulatorAndContext(ctx)).To(Succeed())
+	Expect(configureSimulatorAndContext()).To(Succeed())
 	Expect(createTagsAndCategories()).To(Succeed())
 })
 
@@ -135,13 +135,13 @@ var _ = Describe("Metadata_CreateTag", func() {
 	})
 })
 
-func configureSimulatorAndContext(ctx context.Context) (err error) {
+func configureSimulatorAndContext() (err error) {
 	sim, err = vcsim.NewBuilder().Build()
 	if err != nil {
 		return
 	}
 
-	vmCtx = fake.NewVMContext(ctx, fake.NewControllerContext(fake.NewControllerManagerContext()))
+	vmCtx = fake.NewVMContext(fake.NewControllerContext(fake.NewControllerManagerContext()))
 	vmCtx.VSphereVM.Spec.Server = sim.ServerURL().Host
 
 	authSession, err := session.GetOrCreate(
diff --git a/pkg/services/govmomi/service_test.go b/pkg/services/govmomi/service_test.go
index 011e6c34..8be3f404 100644
--- a/pkg/services/govmomi/service_test.go
+++ b/pkg/services/govmomi/service_test.go
@@ -39,7 +39,9 @@ func emptyVirtualMachineContext() *virtualMachineContext {
 		VMContext: capvcontext.VMContext{
 			Logger: logr.Discard(),
 			ControllerContext: &capvcontext.ControllerContext{
-				ControllerManagerContext: &capvcontext.ControllerManagerContext{},
+				ControllerManagerContext: &capvcontext.ControllerManagerContext{
+					Context: context.TODO(),
+				},
 			},
 		},
 	}
diff --git a/pkg/services/govmomi/vcenter/clone_test.go b/pkg/services/govmomi/vcenter/clone_test.go
index 292dc00b..67c93853 100644
--- a/pkg/services/govmomi/vcenter/clone_test.go
+++ b/pkg/services/govmomi/vcenter/clone_test.go
@@ -27,7 +27,7 @@ import (
 	"github.com/vmware/govmomi/vim25/types"
 
 	infrav1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1"
-	capvcontext "sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
+	"sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
 	"sigs.k8s.io/cluster-api-provider-vsphere/pkg/session"
 )
 
@@ -120,7 +120,7 @@ func TestGetDiskSpec(t *testing.T) {
 					VirtualMachineCloneSpec: cloneSpec,
 				},
 			}
-			vmContext := &capvcontext.VMContext{VSphereVM: vsphereVM}
+			vmContext := &context.VMContext{VSphereVM: vsphereVM}
 			devices, err := getDiskSpec(vmContext, tc.disks)
 			if (tc.err != "" && err == nil) || (tc.err == "" && err != nil) || (err != nil && tc.err != err.Error()) {
 				t.Fatalf("Expected to get '%v' error from getDiskSpec, got: '%v'", tc.err, err)
diff --git a/pkg/services/vimmachine_test.go b/pkg/services/vimmachine_test.go
index f9403989..6734af5d 100644
--- a/pkg/services/vimmachine_test.go
+++ b/pkg/services/vimmachine_test.go
@@ -27,7 +27,7 @@ import (
 	clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
 
 	infrav1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1"
-	capvcontext "sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
+	"sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
 	"sigs.k8s.io/cluster-api-provider-vsphere/pkg/context/fake"
 )
 
@@ -60,14 +60,14 @@ var _ = Describe("VimMachineService_GenerateOverrideFunc", func() {
 		}
 	}
 	var (
-		controllerCtx     *capvcontext.ControllerContext
-		machineCtx        *capvcontext.VIMMachineContext
+		controllerCtx     *context.ControllerContext
+		machineCtx        *context.VIMMachineContext
 		vimMachineService *VimMachineService
 	)
 
 	BeforeEach(func() {
 		controllerCtx = fake.NewControllerContext(fake.NewControllerManagerContext(deplZone("one"), deplZone("two"), failureDomain("one"), failureDomain("two")))
-		machineCtx = fake.NewMachineContext(ctx, fake.NewClusterContext(ctx, controllerCtx), controllerCtx)
+		machineCtx = fake.NewMachineContext(fake.NewClusterContext(controllerCtx), controllerCtx)
 		vimMachineService = &VimMachineService{controllerCtx.Client}
 	})
 
@@ -188,8 +188,8 @@ var _ = Describe("VimMachineService_GenerateOverrideFunc", func() {
 
 var _ = Describe("VimMachineService_GetHostInfo", func() {
 	var (
-		controllerCtx     *capvcontext.ControllerContext
-		machineCtx        *capvcontext.VIMMachineContext
+		controllerCtx     *context.ControllerContext
+		machineCtx        *context.VIMMachineContext
 		vimMachineService = &VimMachineService{}
 		hostAddr          = "1.2.3.4"
 	)
@@ -215,7 +215,7 @@ var _ = Describe("VimMachineService_GetHostInfo", func() {
 	Context("When VMProvisioned Condition is set", func() {
 		BeforeEach(func() {
 			controllerCtx = fake.NewControllerContext(fake.NewControllerManagerContext(getVSphereVM(hostAddr, corev1.ConditionTrue)))
-			machineCtx = fake.NewMachineContext(ctx, fake.NewClusterContext(ctx, controllerCtx), controllerCtx)
+			machineCtx = fake.NewMachineContext(fake.NewClusterContext(controllerCtx), controllerCtx)
 			vimMachineService = &VimMachineService{controllerCtx.Client}
 		})
 		It("Fetches host address from the VSphereVM object", func() {
@@ -228,7 +228,7 @@ var _ = Describe("VimMachineService_GetHostInfo", func() {
 	Context("When VMProvisioned Condition is unset", func() {
 		BeforeEach(func() {
 			controllerCtx = fake.NewControllerContext(fake.NewControllerManagerContext(getVSphereVM(hostAddr, corev1.ConditionFalse)))
-			machineCtx = fake.NewMachineContext(ctx, fake.NewClusterContext(ctx, controllerCtx), controllerCtx)
+			machineCtx = fake.NewMachineContext(fake.NewClusterContext(controllerCtx), controllerCtx)
 			vimMachineService = &VimMachineService{controllerCtx.Client}
 		})
 		It("returns empty string", func() {
@@ -242,8 +242,8 @@ var _ = Describe("VimMachineService_GetHostInfo", func() {
 
 var _ = Describe("VimMachineService_createOrPatchVSphereVM", func() {
 	var (
-		controllerCtx       *capvcontext.ControllerContext
-		machineCtx          *capvcontext.VIMMachineContext
+		controllerCtx       *context.ControllerContext
+		machineCtx          *context.VIMMachineContext
 		vimMachineService   *VimMachineService
 		hostAddr            = "1.2.3.4"
 		fakeLongClusterName = "fake-long-clustername"
@@ -268,7 +268,7 @@ var _ = Describe("VimMachineService_createOrPatchVSphereVM", func() {
 	}
 
 	controllerCtx = fake.NewControllerContext(fake.NewControllerManagerContext(getVSphereVM(hostAddr, corev1.ConditionTrue)))
-	machineCtx = fake.NewMachineContext(ctx, fake.NewClusterContext(ctx, controllerCtx), controllerCtx)
+	machineCtx = fake.NewMachineContext(fake.NewClusterContext(controllerCtx), controllerCtx)
 	machineCtx.Machine.SetName(fakeLongClusterName)
 	vimMachineService = &VimMachineService{controllerCtx.Client}
 
diff --git a/pkg/session/session_test.go b/pkg/session/session_test.go
index de7549a7..028e5308 100644
--- a/pkg/session/session_test.go
+++ b/pkg/session/session_test.go
@@ -53,31 +53,30 @@ func TestGetSession(t *testing.T) {
 		WithUserInfo(simr.Username(), simr.Password()).WithDatacenter("*")
 
 	// Get first session
-	ctx := context.Background()
-	s, err := GetOrCreate(ctx, params)
+	s, err := GetOrCreate(context.Background(), params)
 	g.Expect(err).ToNot(HaveOccurred())
 	g.Expect(s).ToNot(BeNil())
 	assertSessionCountEqualTo(g, simr, 1)
 
 	// Get session key
-	sessionInfo, err := s.SessionManager.UserSession(ctx)
+	sessionInfo, err := s.SessionManager.UserSession(context.Background())
 	g.Expect(err).ToNot(HaveOccurred())
 	g.Expect(sessionInfo).ToNot(BeNil())
 	firstSession := sessionInfo.Key
 
 	// remove session expect no session
-	g.Expect(s.TagManager.Logout(ctx)).To(Succeed())
+	g.Expect(s.TagManager.Logout(context.Background())).To(Succeed())
 	g.Expect(simr.Run(fmt.Sprintf("session.rm %s", firstSession))).To(Succeed())
 	assertSessionCountEqualTo(g, simr, 0)
 
-	// request session again should be a new and different session
-	s, err = GetOrCreate(ctx, params)
+	// request sesion again should be a new and different session
+	s, err = GetOrCreate(context.Background(), params)
 	g.Expect(err).ToNot(HaveOccurred())
 	g.Expect(s).ToNot(BeNil())
 
 	// Get session info, session key should be different from
 	// last session
-	sessionInfo, err = s.SessionManager.UserSession(ctx)
+	sessionInfo, err = s.SessionManager.UserSession(context.Background())
 	g.Expect(sessionInfo).ToNot(BeNil())
 	g.Expect(err).ToNot(HaveOccurred())
 	g.Expect(sessionInfo.Key).ToNot(BeEquivalentTo(firstSession))
@@ -133,14 +132,13 @@ func TestGetSessionWithKeepAlive(t *testing.T) {
 		WithDatacenter("*")
 
 	// Get first Session
-	ctx := context.Background()
-	s, err := GetOrCreate(ctx, params)
+	s, err := GetOrCreate(context.Background(), params)
 	g.Expect(err).ToNot(HaveOccurred())
 	g.Expect(s).ToNot(BeNil())
 	assertSessionCountEqualTo(g, simr, 1)
 
 	// Get session key
-	sessionInfo, err := s.SessionManager.UserSession(ctx)
+	sessionInfo, err := s.SessionManager.UserSession(context.Background())
 	g.Expect(err).ToNot(HaveOccurred())
 	g.Expect(sessionInfo).ToNot(BeNil())
 	firstSession := sessionInfo.Key
@@ -148,25 +146,25 @@ func TestGetSessionWithKeepAlive(t *testing.T) {
 	// Get the session again
 	// as keep alive is enabled and session is
 	// not expired we must get the same cached session
-	s, err = GetOrCreate(ctx, params)
+	s, err = GetOrCreate(context.Background(), params)
 	g.Expect(err).ToNot(HaveOccurred())
 	g.Expect(s).ToNot(BeNil())
-	sessionInfo, err = s.SessionManager.UserSession(ctx)
+	sessionInfo, err = s.SessionManager.UserSession(context.Background())
 	g.Expect(err).ToNot(HaveOccurred())
 	g.Expect(sessionInfo).ToNot(BeNil())
 	g.Expect(sessionInfo.Key).To(BeEquivalentTo(firstSession))
 	assertSessionCountEqualTo(g, simr, 1)
 
 	// Try to remove vim session
-	g.Expect(s.Logout(ctx)).To(Succeed())
+	g.Expect(s.Logout(context.Background())).To(Succeed())
 
 	// after logging out old session must be deleted,
 	// we must get a new different session
 	// total session count must remain 1
-	s, err = GetOrCreate(ctx, params)
+	s, err = GetOrCreate(context.Background(), params)
 	g.Expect(err).ToNot(HaveOccurred())
 	g.Expect(s).ToNot(BeNil())
-	sessionInfo, err = s.SessionManager.UserSession(ctx)
+	sessionInfo, err = s.SessionManager.UserSession(context.Background())
 	g.Expect(err).ToNot(HaveOccurred())
 	g.Expect(sessionInfo).ToNot(BeNil())
 	g.Expect(sessionInfo.Key).ToNot(BeEquivalentTo(firstSession))
diff --git a/pkg/util/testutil.go b/pkg/util/testutil.go
index e889aa02..e3ab7c7f 100644
--- a/pkg/util/testutil.go
+++ b/pkg/util/testutil.go
@@ -17,6 +17,8 @@ limitations under the License.
 package util
 
 import (
+	"context"
+
 	netopv1 "github.com/vmware-tanzu/net-operator-api/api/v1alpha1"
 	vmoprv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha1"
 	ncpv1 "github.com/vmware-tanzu/vm-operator/external/ncp/api/v1alpha1"
@@ -150,8 +152,9 @@ func createScheme() *runtime.Scheme {
 func CreateClusterContext(cluster *clusterv1.Cluster, vsphereCluster *vmwarev1.VSphereCluster) (*vmware.ClusterContext, *capvcontext.ControllerContext) {
 	scheme := createScheme()
 	controllerManagerContext := &capvcontext.ControllerManagerContext{
-		Logger: klog.Background().WithName("controller-manager-logger"),
-		Scheme: scheme,
+		Context: context.Background(),
+		Logger:  klog.Background().WithName("controller-manager-logger"),
+		Scheme:  scheme,
 		Client: testclient.NewClientBuilder().WithScheme(scheme).WithStatusSubresource(
 			&vmoprv1.VirtualMachineService{},
 			&vmoprv1.VirtualMachine{},
diff --git a/test/helpers/vmware/intg_test_context.go b/test/helpers/vmware/intg_test_context.go
index 9a77e501..b19351bc 100644
--- a/test/helpers/vmware/intg_test_context.go
+++ b/test/helpers/vmware/intg_test_context.go
@@ -40,6 +40,7 @@ import (
 // IntegrationTestContext is used for integration testing
 // Supervisor controllers.
 type IntegrationTestContext struct {
+	context.Context   //nolint:containedctx
 	Client            client.Client
 	GuestClient       client.Client
 	Namespace         string
@@ -62,7 +63,7 @@ func (ctx *IntegrationTestContext) AfterEach() {
 		},
 	}
 	By("Destroying integration test namespace")
-	Expect(ctx.Client.Delete(context.Background(), namespace)).To(Succeed())
+	Expect(ctx.Client.Delete(ctx, namespace)).To(Succeed())
 
 	if ctx.envTest != nil {
 		By("Shutting down guest cluster control plane")
@@ -83,7 +84,8 @@ func (ctx *IntegrationTestContext) AfterEach() {
 // with the IntegrationTestContext returned by this function.
 func NewIntegrationTestContextWithClusters(ctx context.Context, integrationTestClient client.Client) *IntegrationTestContext {
 	testCtx := &IntegrationTestContext{
-		Client: integrationTestClient,
+		Context: ctx,
+		Client:  integrationTestClient,
 	}
 
 	By("Creating a temporary namespace", func() {
diff --git a/test/helpers/vmware/unit_test_context.go b/test/helpers/vmware/unit_test_context.go
index daddea61..d3b0ff02 100644
--- a/test/helpers/vmware/unit_test_context.go
+++ b/test/helpers/vmware/unit_test_context.go
@@ -49,20 +49,20 @@ type UnitTestContextForController struct {
 // NewUnitTestContextForController returns a new UnitTestContextForController
 // with an optional prototype cluster for unit testing controllers that do not
 // invoke the VSphereCluster spec controller.
-func NewUnitTestContextForController(ctx context.Context, namespace string, vSphereCluster *vmwarev1.VSphereCluster,
+func NewUnitTestContextForController( /*newReconcilerFn NewReconcilerFunc, */ namespace string, vSphereCluster *vmwarev1.VSphereCluster,
 	prototypeCluster bool, initObjects, gcInitObjects []client.Object) *UnitTestContextForController {
 	controllerCtx := fake.NewControllerContext(fake.NewControllerManagerContext(initObjects...))
 
-	unitTestCtx := &UnitTestContextForController{
-		GuestClusterContext: fake.NewGuestClusterContext(ctx, fake.NewVmwareClusterContext(ctx, controllerCtx, namespace, vSphereCluster),
+	ctx := &UnitTestContextForController{
+		GuestClusterContext: fake.NewGuestClusterContext(context.TODO(), fake.NewVmwareClusterContext(controllerCtx, namespace, vSphereCluster),
 			controllerCtx, prototypeCluster, gcInitObjects...),
 		ControllerContext: controllerCtx,
 	}
-	unitTestCtx.Key = client.ObjectKey{Namespace: unitTestCtx.VSphereCluster.Namespace, Name: unitTestCtx.VSphereCluster.Name}
+	ctx.Key = client.ObjectKey{Namespace: ctx.VSphereCluster.Namespace, Name: ctx.VSphereCluster.Name}
 
-	CreatePrototypePrereqs(ctx, controllerCtx.Client)
+	CreatePrototypePrereqs(context.TODO(), controllerCtx.Client)
 
-	return unitTestCtx
+	return ctx
 }
 
 func CreatePrototypePrereqs(ctx context.Context, c client.Client) {