Repository: submariner-io/submariner (2026-04-09T16:41:41Z)

Issue:
Pass Context parameter to event Handler Stop and Uninstall methods
...so callers can impose a deadline and/or cancel internal operations.


Discussion:
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further
activity occurs. Thank you for your contributions.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further
activity occurs. Thank you for your contributions.



Patch:
diff --git a/pkg/event/controller/controller.go b/pkg/event/controller/controller.go
index 8d3fc9263..41a470f99 100644
--- a/pkg/event/controller/controller.go
+++ b/pkg/event/controller/controller.go
@@ -19,6 +19,7 @@ limitations under the License.
 package controller
 
 import (
+	"context"
 	"fmt"
 	"os"
 	"sync"
@@ -159,10 +160,10 @@ func (c *Controller) Start(stopCh <-chan struct{}) error {
 	return nil
 }
 
-func (c *Controller) Stop() {
+func (c *Controller) Stop(ctx context.Context) {
 	logger.Info("Event controller stopping")
 
-	if err := c.handlers.StopHandlers(); err != nil {
+	if err := c.handlers.StopHandlers(ctx); err != nil {
 		logger.Warningf("In Event Controller, StopHandlers returned error: %v", err)
 	}
 }
diff --git a/pkg/event/handler.go b/pkg/event/handler.go
index 1f582ba83..d9c4a578f 100644
--- a/pkg/event/handler.go
+++ b/pkg/event/handler.go
@@ -98,10 +98,10 @@ type Handler interface {
 	GetNetworkPlugins() []string
 
 	// Stop is called once during shutdown to let the handler perform any cleanup.
-	Stop() error
+	Stop(ctx context.Context) error
 
 	// Uninstall is called once after shutdown to let the handler process a Submariner uninstallation.
-	Uninstall() error
+	Uninstall(ctx context.Context) error
 
 	EndpointHandler
 }
@@ -128,11 +128,11 @@ func (ev *HandlerBase) State() HandlerState {
 	return hs.(HandlerState)
 }
 
-func (ev *HandlerBase) Stop() error {
+func (ev *HandlerBase) Stop(_ context.Context) error {
 	return nil
 }
 
-func (ev *HandlerBase) Uninstall() error {
+func (ev *HandlerBase) Uninstall(_ context.Context) error {
 	return nil
 }
 
diff --git a/pkg/event/registry.go b/pkg/event/registry.go
index f5d3dfce6..80ab911d0 100644
--- a/pkg/event/registry.go
+++ b/pkg/event/registry.go
@@ -88,15 +88,15 @@ func (er *Registry) GetHandlers() []Handler {
 	return er.eventHandlers
 }
 
-func (er *Registry) StopHandlers() error {
+func (er *Registry) StopHandlers(ctx context.Context) error {
 	return er.invokeHandlers("Stop", func(h Handler) error {
-		return h.Stop()
+		return h.Stop(ctx)
 	})
 }
 
-func (er *Registry) Uninstall() error {
+func (er *Registry) Uninstall(ctx context.Context) error {
 	return er.invokeHandlers("Uninstall", func(h Handler) error {
-		return h.Uninstall()
+		return h.Uninstall(ctx)
 	})
 }
 
diff --git a/pkg/globalnet/controllers/base_controllers.go b/pkg/globalnet/controllers/base_controllers.go
index ced9ca040..9fcac8a99 100644
--- a/pkg/globalnet/controllers/base_controllers.go
+++ b/pkg/globalnet/controllers/base_controllers.go
@@ -51,7 +51,7 @@ func newBaseController() *baseController {
 	}
 }
 
-func (c *baseController) Stop() {
+func (c *baseController) Stop(_ context.Context) {
 	close(c.stopCh)
 }
 
@@ -69,24 +69,24 @@ func newBaseIPAllocationController(pool *ipam.IPPool, pfIface pfiface.Interface)
 	}
 }
 
-func (c *baseSyncerController) Start() error {
+func (c *baseSyncerController) Start(_ context.Context) error {
 	return c.resourceSyncer.Start(c.stopCh) //nolint:wrapcheck  // Let the caller wrap it
 }
 
-func (c *baseSyncerController) Stop() {
-	c.baseController.Stop()
+func (c *baseSyncerController) Stop(ctx context.Context) {
+	c.baseController.Stop(ctx)
 
-	err := c.resourceSyncer.AwaitStopped(context.TODO())
+	err := c.resourceSyncer.AwaitStopped(ctx)
 	if err != nil {
 		logger.Warning(err.Error())
 	}
 }
 
-func (c *baseSyncerController) reconcile(client dynamic.ResourceInterface, labelSelector, fieldSelector string,
+func (c *baseSyncerController) reconcile(ctx context.Context, client dynamic.ResourceInterface, labelSelector, fieldSelector string,
 	transform func(obj *unstructured.Unstructured) runtime.Object,
 ) {
 	c.resourceSyncer.Reconcile(func() []runtime.Object {
-		objList, err := client.List(context.TODO(), metav1.ListOptions{
+		objList, err := client.List(ctx, metav1.ListOptions{
 			LabelSelector: labelSelector,
 			FieldSelector: fieldSelector,
 		})
@@ -108,11 +108,10 @@ func (c *baseSyncerController) reconcile(client dynamic.ResourceInterface, label
 	})
 }
 
-func (c *baseIPAllocationController) reserveAllocatedIPs(federator federate.Federator, obj *unstructured.Unstructured,
-	postReserve func(allocatedIPs []string) error,
+func (c *baseIPAllocationController) reserveAllocatedIPs(ctx context.Context, federator federate.Federator, obj *unstructured.Unstructured,
+	postReserve func(ctx context.Context, allocatedIPs []string) error,
 ) error {
 	var reservedIPs []string
-
 	clearAllocatedIPs := func() {}
 
 	ips, ok, _ := unstructured.NestedStringSlice(obj.Object, "status", "allocatedIPs")
@@ -152,14 +151,14 @@ func (c *baseIPAllocationController) reserveAllocatedIPs(federator federate.Fede
 
 		logger.Infof("Updating %q: %#v", key, obj)
 
-		return federator.Distribute(context.TODO(), obj) //nolint:wrapcheck  // Let the caller wrap it
+		return federator.Distribute(ctx, obj) //nolint:wrapcheck  // Let the caller wrap it
 	}
 
 	if len(reservedIPs) == 0 {
 		return nil
 	}
 
-	err = postReserve(reservedIPs)
+	err = postReserve(ctx, reservedIPs)
 	if err != nil {
 		return err
 	}
@@ -223,10 +222,9 @@ func checkStatusChanged(oldStatus, newStatus any, retObj runtime.Object) runtime
 	return retObj
 }
 
-func getService(name, namespace string,
-	client dynamic.NamespaceableResourceInterface, scheme *runtime.Scheme,
+func getService(ctx context.Context, name, namespace string, client dynamic.NamespaceableResourceInterface, scheme *runtime.Scheme,
 ) (*corev1.Service, bool, error) {
-	obj, err := client.Namespace(namespace).Get(context.TODO(), name, metav1.GetOptions{})
+	obj, err := client.Namespace(namespace).Get(ctx, name, metav1.GetOptions{})
 	if apierrors.IsNotFound(err) {
 		return nil, false, nil
 	}
@@ -245,10 +243,8 @@ func getService(name, namespace string,
 	return service, true, nil
 }
 
-func deleteService(namespace, name string,
-	client dynamic.NamespaceableResourceInterface,
-) error {
-	err := client.Namespace(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
+func deleteService(ctx context.Context, namespace, name string, client dynamic.NamespaceableResourceInterface) error {
+	err := client.Namespace(namespace).Delete(ctx, name, metav1.DeleteOptions{})
 	if apierrors.IsNotFound(err) {
 		logger.Warningf("Could not find Service %s/%s to delete", namespace, name)
 		return nil
@@ -265,10 +261,8 @@ func GetInternalSvcName(name string) string {
 	return strings.ToLower(svcName)
 }
 
-func deleteEndpoints(namespace, name string,
-	client dynamic.NamespaceableResourceInterface,
-) error {
-	err := client.Namespace(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
+func deleteEndpoints(ctx context.Context, namespace, name string, client dynamic.NamespaceableResourceInterface) error {
+	err := client.Namespace(namespace).Delete(ctx, name, metav1.DeleteOptions{})
 	if apierrors.IsNotFound(err) {
 		logger.Warningf("Could not find Endpoints %s/%s to delete", namespace, name)
 		return nil
diff --git a/pkg/globalnet/controllers/cluster_egressip_controller.go b/pkg/globalnet/controllers/cluster_egressip_controller.go
index 2b8a2ca62..a5f521c7a 100644
--- a/pkg/globalnet/controllers/cluster_egressip_controller.go
+++ b/pkg/globalnet/controllers/cluster_egressip_controller.go
@@ -43,7 +43,7 @@ import (
 	"k8s.io/utils/ptr"
 )
 
-func NewClusterGlobalEgressIPController(config *syncer.ResourceSyncerConfig, localSubnets []string,
+func NewClusterGlobalEgressIPController(ctx context.Context, config *syncer.ResourceSyncerConfig, localSubnets []string,
 	pool *ipam.IPPool,
 ) (Interface, error) {
 	// We'll panic if config is nil, this is intentional
@@ -79,11 +79,11 @@ func NewClusterGlobalEgressIPController(config *syncer.ResourceSyncerConfig, loc
 
 	client := config.SourceClient.Resource(*gvr)
 
-	obj, err := client.Get(context.TODO(), defaultEgressIP.Name, metav1.GetOptions{})
+	obj, err := client.Get(ctx, defaultEgressIP.Name, metav1.GetOptions{})
 	if apierrors.IsNotFound(err) {
 		logger.Infof("Creating ClusterGlobalEgressIP resource %q", defaultEgressIP.Name)
 
-		_, err = client.Create(context.TODO(), defaultEgressIPObj, metav1.CreateOptions{})
+		_, err = client.Create(ctx, defaultEgressIPObj, metav1.CreateOptions{})
 		if err != nil {
 			return nil, errors.Wrapf(err, "error creating ClusterGlobalEgressIP resource %q", defaultEgressIP.Name)
 		}
@@ -92,7 +92,7 @@ func NewClusterGlobalEgressIPController(config *syncer.ResourceSyncerConfig, loc
 	}
 
 	if obj != nil {
-		err := controller.reserveAllocatedIPs(federator, obj, func(reservedIPs []string) error {
+		err := controller.reserveAllocatedIPs(ctx, federator, obj, func(_ context.Context, reservedIPs []string) error {
 			metrics.RecordAllocateClusterGlobalEgressIPs(pool.GetCIDR(), len(reservedIPs))
 			return controller.programClusterGlobalEgressRules(reservedIPs)
 		})
diff --git a/pkg/globalnet/controllers/endpoints_controller.go b/pkg/globalnet/controllers/endpoints_controller.go
index e4c931412..9bb6d2115 100644
--- a/pkg/globalnet/controllers/endpoints_controller.go
+++ b/pkg/globalnet/controllers/endpoints_controller.go
@@ -19,6 +19,7 @@ limitations under the License.
 package controllers
 
 import (
+	"context"
 	"reflect"
 
 	"github.com/pkg/errors"
@@ -36,7 +37,9 @@ import (
 	"k8s.io/client-go/tools/cache"
 )
 
-func startEndpointsController(name, namespace string, config *syncer.ResourceSyncerConfig) (*endpointsController, error) {
+func startEndpointsController(ctx context.Context, name, namespace string,
+	config *syncer.ResourceSyncerConfig,
+) (*endpointsController, error) {
 	// We'll panic if config is nil, this is intentional
 	var err error
 
@@ -77,26 +80,13 @@ func startEndpointsController(name, namespace string, config *syncer.ResourceSyn
 		return nil, errors.Wrap(err, "error creating the syncer")
 	}
 
-	if err := controller.Start(); err != nil {
+	if err := controller.Start(ctx); err != nil {
 		return nil, err
 	}
 
 	return controller, nil
 }
 
-func (c *endpointsController) Stop() {
-	c.baseController.Stop()
-}
-
-func (c *endpointsController) Start() error {
-	err := c.baseSyncerController.Start()
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
 func (c *endpointsController) process(from runtime.Object, _ int, op syncer.Operation) (runtime.Object, bool) {
 	ep := from.(*corev1.Endpoints)
 
diff --git a/pkg/globalnet/controllers/gateway_controller.go b/pkg/globalnet/controllers/gateway_controller.go
index 3bbf8dbf3..930f0348a 100644
--- a/pkg/globalnet/controllers/gateway_controller.go
+++ b/pkg/globalnet/controllers/gateway_controller.go
@@ -36,8 +36,8 @@ import (
 	"k8s.io/client-go/tools/cache"
 )
 
-func NewGatewayController(config *syncer.ResourceSyncerConfig, informer cache.SharedInformer, pool *ipam.IPPool, hostName,
-	namespace, cniIP string,
+func NewGatewayController(ctx context.Context, config *syncer.ResourceSyncerConfig, informer cache.SharedInformer, pool *ipam.IPPool,
+	hostName, namespace, cniIP string,
 ) (Interface, error) {
 	// We'll panic if config is nil, this is intentional
 	var err error
@@ -80,13 +80,13 @@ func NewGatewayController(config *syncer.ResourceSyncerConfig, informer cache.Sh
 	// Gateways retain their allocated global IPs regardless of their HA status (active or passive) so reserve the global IPs
 	// for all the Gateways.
 
-	gateways, err := gatewayClient.List(context.TODO(), metav1.ListOptions{})
+	gateways, err := gatewayClient.List(ctx, metav1.ListOptions{})
 	if err != nil {
 		return nil, errors.Wrap(err, "error listing Gateways")
 	}
 
 	for i := range gateways.Items {
-		if err := controller.reserveAllocatedIP(config.Federator, &gateways.Items[i]); err != nil {
+		if err := controller.reserveAllocatedIP(ctx, config.Federator, &gateways.Items[i]); err != nil {
 			return nil, err
 		}
 	}
@@ -165,7 +165,7 @@ func (n *gatewayController) allocateIP(gateway *submarinerv1.Gateway) (runtime.O
 	return updateGlobalIPAnnotation(gateway, globalIP), false
 }
 
-func (n *gatewayController) reserveAllocatedIP(federator federate.Federator, obj *unstructured.Unstructured) error {
+func (n *gatewayController) reserveAllocatedIP(ctx context.Context, federator federate.Federator, obj *unstructured.Unstructured) error {
 	existingGlobalIP := obj.GetAnnotations()[constants.SmGlobalIP]
 	if existingGlobalIP == "" {
 		return nil
@@ -199,7 +199,7 @@ func (n *gatewayController) reserveAllocatedIP(federator federate.Federator, obj
 			logger.Errorf(err, "Error deleting rules for Gateway %q", n.hostName)
 		}
 
-		return errors.Wrap(federator.Distribute(context.TODO(), updateGlobalIPAnnotation(obj, "")),
+		return errors.Wrap(federator.Distribute(ctx, updateGlobalIPAnnotation(obj, "")),
 			"error updating the Gateway global IP annotation")
 	}
 
diff --git a/pkg/globalnet/controllers/gateway_monitor.go b/pkg/globalnet/controllers/gateway_monitor.go
index 2aab2a7d1..0d8086a97 100644
--- a/pkg/globalnet/controllers/gateway_monitor.go
+++ b/pkg/globalnet/controllers/gateway_monitor.go
@@ -140,7 +140,7 @@ func NewGatewayMonitor(ctx context.Context, config *GatewayMonitorConfig) (Inter
 	return &gatewayMonitorInterface{monitor: gatewayMonitor, registry: registry}, nil
 }
 
-func (g *gatewayMonitorInterface) Start() error {
+func (g *gatewayMonitorInterface) Start(ctx context.Context) error {
 	logger.Info("Starting GatewayMonitor to monitor the active Gateway node in the cluster.")
 
 	err := g.monitor.startLocalGatewayCleanupController()
@@ -165,8 +165,8 @@ func (g *gatewayMonitorInterface) Start() error {
 	return eventController.Start(g.monitor.stopCh) //nolint // No need to wrap
 }
 
-func (g *gatewayMonitorInterface) Stop() {
-	_ = g.monitor.Stop()
+func (g *gatewayMonitorInterface) Stop(ctx context.Context) {
+	_ = g.monitor.Stop(ctx)
 }
 
 func (g *gatewayMonitor) GetName() string {
@@ -181,17 +181,12 @@ func (g *gatewayMonitor) Init(_ context.Context) error {
 	return g.createNATChain(chains.SmGlobalnetMark)
 }
 
-func (g *gatewayMonitor) Stop() error {
+func (g *gatewayMonitor) Stop(ctx context.Context) error {
 	logger.Info("GatewayMonitor stopping")
 
 	g.shuttingDown.Store(true)
 
-	g.baseController.Stop()
-
-	// stopControllers should be pretty quick but put a deadline on it, so we don't block shutdown for a long time.
-
-	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
-	defer cancel()
+	g.baseController.Stop(ctx)
 
 	g.stopControllers(ctx, true)
 
@@ -296,7 +291,7 @@ func (g *gatewayMonitor) startLeaderElection() {
 		ReleaseOnCancel: true,
 		Callbacks: leaderelection.LeaderCallbacks{
 			OnStartedLeading: func(_ context.Context) {
-				err := g.startControllers() //nolint:contextcheck // Intentional to not pass context
+				err := g.startControllers(context.Background()) //nolint:contextcheck // Intentional to not pass context
 				if err != nil {
 					logger.Error(err, "Error starting the controllers - stopping leader election")
 					leaderElectionInfo.stop()
@@ -322,7 +317,7 @@ func (g *gatewayMonitor) startLeaderElection() {
 }
 
 //nolint:gocyclo // Ignore cyclomatic complexity here
-func (g *gatewayMonitor) startControllers() error {
+func (g *gatewayMonitor) startControllers(ctx context.Context) error {
 	g.controllersMutex.Lock()
 	defer g.controllersMutex.Unlock()
 
@@ -346,14 +341,14 @@ func (g *gatewayMonitor) startControllers() error {
 
 	g.controllers = nil
 
-	c, err := NewClusterGlobalEgressIPController(g.syncerConfig, g.LocalCIDRs, pool)
+	c, err := NewClusterGlobalEgressIPController(ctx, g.syncerConfig, g.LocalCIDRs, pool)
 	if err != nil {
 		return errors.Wrap(err, "error creating the ClusterGlobalEgressIP controller")
 	}
 
 	g.controllers = append(g.controllers, c)
 
-	c, err = NewGlobalEgressIPController(g.syncerConfig, pool)
+	c, err = NewGlobalEgressIPController(ctx, g.syncerConfig, pool)
 	if err != nil {
 		return errors.Wrap(err, "error creating the GlobalEgressIP controller")
 	}
@@ -365,7 +360,7 @@ func (g *gatewayMonitor) startControllers() error {
 	// remains until the finalizer is removed. We have seen that this intermediate state of
 	// the service can potentially create issues in some deployments. Hence, we identify such internal
 	// services and delete them when the Globalnet controller pod comes up.
-	err = RemoveStaleInternalServices(g.syncerConfig)
+	err = RemoveStaleInternalServices(ctx, g.syncerConfig)
 	if err != nil {
 		// Just log an error message as it's non-fatal
 		logger.Errorf(err, "Error removing stale internal services created by Globalnet controller")
@@ -373,7 +368,7 @@ func (g *gatewayMonitor) startControllers() error {
 
 	// The GlobalIngressIP controller needs to be started before the ServiceExport and Service controllers to ensure
 	// reconciliation works properly.
-	gipController, err := NewGlobalIngressIPController(g.syncerConfig, pool)
+	gipController, err := NewGlobalIngressIPController(ctx, g.syncerConfig, pool)
 	if err != nil {
 		return errors.Wrap(err, "error creating the GlobalIngressIP controller")
 	}
@@ -385,7 +380,7 @@ func (g *gatewayMonitor) startControllers() error {
 		return errors.Wrap(err, "error creating the IngressPodControllers")
 	}
 
-	endpointsControllers, err := NewServiceExportEndpointsControllers(g.syncerConfig)
+	endpointsControllers, err := NewServiceExportEndpointsControllers(ctx, g.syncerConfig)
 	if err != nil {
 		return errors.Wrap(err, "error creating the Endpoints controller")
 	}
@@ -411,7 +406,7 @@ func (g *gatewayMonitor) startControllers() error {
 	g.controllers = append(g.controllers, c)
 
 	if g.cniIP != "" {
-		c, err := NewGatewayController(g.syncerConfig, g.gatewaySharedInformer, pool, g.Hostname, g.Spec.Namespace, g.cniIP)
+		c, err := NewGatewayController(ctx, g.syncerConfig, g.gatewaySharedInformer, pool, g.Hostname, g.Spec.Namespace, g.cniIP)
 		if err != nil {
 			return errors.Wrap(err, "error creating the Gateway controller")
 		}
@@ -420,7 +415,7 @@ func (g *gatewayMonitor) startControllers() error {
 	}
 
 	for _, c := range g.controllers {
-		err = c.Start()
+		err = c.Start(ctx)
 		if err != nil {
 			return err //nolint:wrapcheck  // Let the caller wrap it
 		}
@@ -437,7 +432,7 @@ func (g *gatewayMonitor) stopControllers(ctx context.Context, clearGlobalnetChai
 	logger.Infof("Stopping %d controllers", len(g.controllers))
 
 	for _, c := range g.controllers {
-		c.Stop()
+		c.Stop(ctx)
 	}
 
 	g.controllers = nil
diff --git a/pkg/globalnet/controllers/global_egressip_controller.go b/pkg/globalnet/controllers/global_egressip_controller.go
index 8aee27936..b3709a66c 100644
--- a/pkg/globalnet/controllers/global_egressip_controller.go
+++ b/pkg/globalnet/controllers/global_egressip_controller.go
@@ -43,7 +43,7 @@ import (
 	"k8s.io/client-go/tools/cache"
 )
 
-func NewGlobalEgressIPController(config *syncer.ResourceSyncerConfig, pool *ipam.IPPool) (Interface, error) {
+func NewGlobalEgressIPController(ctx context.Context, config *syncer.ResourceSyncerConfig, pool *ipam.IPPool) (Interface, error) {
 	// We'll panic if config is nil, this is intentional
 	var err error
 
@@ -71,7 +71,7 @@ func NewGlobalEgressIPController(config *syncer.ResourceSyncerConfig, pool *ipam
 
 	client := config.SourceClient.Resource(*gvr).Namespace(corev1.NamespaceAll)
 
-	list, err := client.List(context.TODO(), metav1.ListOptions{})
+	list, err := client.List(ctx, metav1.ListOptions{})
 	if err != nil {
 		return nil, errors.Wrap(err, "error listing the resources")
 	}
@@ -79,7 +79,7 @@ func NewGlobalEgressIPController(config *syncer.ResourceSyncerConfig, pool *ipam
 	federator := federate.NewUpdateStatusFederator(config.SourceClient, config.RestMapper, corev1.NamespaceAll)
 
 	for i := range list.Items {
-		err = controller.reserveAllocatedIPs(federator, &list.Items[i], func(reservedIPs []string) error {
+		err = controller.reserveAllocatedIPs(ctx, federator, &list.Items[i], func(ctx context.Context, reservedIPs []string) error {
 			metrics.RecordAllocateGlobalEgressIPs(pool.GetCIDR(), len(reservedIPs))
 
 			specObj := util.GetSpec(&list.Items[i])
@@ -114,8 +114,8 @@ func NewGlobalEgressIPController(config *syncer.ResourceSyncerConfig, pool *ipam
 	return controller, nil
 }
 
-func (c *globalEgressIPController) Stop() {
-	c.baseController.Stop()
+func (c *globalEgressIPController) Stop(ctx context.Context) {
+	c.baseController.Stop(ctx)
 
 	c.Lock()
 	defer c.Unlock()
diff --git a/pkg/globalnet/controllers/global_ingressip_controller.go b/pkg/globalnet/controllers/global_ingressip_controller.go
index 2f7b7bbb5..f0031a918 100644
--- a/pkg/globalnet/controllers/global_ingressip_controller.go
+++ b/pkg/globalnet/controllers/global_ingressip_controller.go
@@ -38,11 +38,13 @@ import (
 	"k8s.io/apimachinery/pkg/api/meta"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/util/wait"
 	"k8s.io/client-go/tools/cache"
 	"k8s.io/utils/ptr"
 )
 
-func NewGlobalIngressIPController(config *syncer.ResourceSyncerConfig, pool *ipam.IPPool) (*globalIngressIPController, error) {
+func NewGlobalIngressIPController(ctx context.Context, config *syncer.ResourceSyncerConfig, pool *ipam.IPPool,
+) (*globalIngressIPController, error) {
 	// We'll panic if config is nil, this is intentional
 	var err error
 
@@ -73,7 +75,7 @@ func NewGlobalIngressIPController(config *syncer.ResourceSyncerConfig, pool *ipa
 
 	client := config.SourceClient.Resource(*gvr)
 
-	list, err := client.Namespace(corev1.NamespaceAll).List(context.TODO(), metav1.ListOptions{})
+	list, err := client.Namespace(corev1.NamespaceAll).List(ctx, metav1.ListOptions{})
 	if err != nil {
 		return nil, errors.Wrap(err, "error listing the resources")
 	}
@@ -84,14 +86,14 @@ func NewGlobalIngressIPController(config *syncer.ResourceSyncerConfig, pool *ipa
 		_ = runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, gip)
 
 		//nolint:wrapcheck  // No need to wrap these errors.
-		err = controller.reserveAllocatedIPs(federator, obj, func(reservedIPs []string) error {
+		err = controller.reserveAllocatedIPs(ctx, federator, obj, func(ctx context.Context, reservedIPs []string) error {
 			var target string
 			var tType pfiface.TargetType
 
 			metrics.RecordAllocateGlobalIngressIPs(pool.GetCIDR(), len(reservedIPs))
 
 			if gip.Spec.Target == submarinerv1.ClusterIPService {
-				return controller.ensureInternalServiceExists(gip)
+				return controller.ensureInternalServiceExists(ctx, gip)
 			} else if gip.Spec.Target == submarinerv1.HeadlessServicePod {
 				target = gip.GetAnnotations()[headlessSvcPodIP]
 				tType = pfiface.PodTarget
@@ -141,6 +143,8 @@ func (c *globalIngressIPController) GetSyncer() syncer.Interface {
 }
 
 func (c *globalIngressIPController) process(from runtime.Object, numRequeues int, op syncer.Operation) (runtime.Object, bool) {
+	ctx := wait.ContextForChannel(c.stopCh)
+
 	ingressIP := from.(*submarinerv1.GlobalIngressIP)
 
 	logger.Infof("Processing %sd %s/%s, TargetRef: %q, %q, Status: %#v", op, ingressIP.Namespace,
@@ -152,22 +156,22 @@ func (c *globalIngressIPController) process(from runtime.Object, numRequeues int
 
 		trimAllocatedStatusCondition(&ingressIP.Status.Conditions)
 
-		requeue := c.onCreate(ingressIP)
+		requeue := c.onCreate(ctx, ingressIP)
 
 		return checkStatusChanged(&prevStatus, &ingressIP.Status, ingressIP), requeue
 	case syncer.Delete:
-		return nil, c.onDelete(ingressIP, numRequeues)
+		return nil, c.onDelete(ctx, ingressIP, numRequeues)
 	case syncer.Update:
 	}
 
 	return nil, false
 }
 
-func (c *globalIngressIPController) onCreate(ingressIP *submarinerv1.GlobalIngressIP) bool {
+func (c *globalIngressIPController) onCreate(ctx context.Context, ingressIP *submarinerv1.GlobalIngressIP) bool {
 	// If the Ingress GlobalIP is already allocated, we may have gotten here due to an underlying service update (eg ports changed) in
 	// which case we need to update the internal service for non-headless.
 	if ingressIP.Status.AllocatedIP != "" {
-		return c.onUpdate(ingressIP)
+		return c.onUpdate(ctx, ingressIP)
 	}
 
 	key, _ := cache.MetaNamespaceKeyFunc(ingressIP)
@@ -191,7 +195,7 @@ func (c *globalIngressIPController) onCreate(ingressIP *submarinerv1.GlobalIngre
 	if ingressIP.Spec.Target == submarinerv1.ClusterIPService {
 		serviceRef := ingressIP.Spec.ServiceRef
 
-		service, exists, err := getService(serviceRef.Name, ingressIP.Namespace, c.services, c.scheme)
+		service, exists, err := getService(ctx, serviceRef.Name, ingressIP.Namespace, c.services, c.scheme)
 		if err != nil || !exists {
 			_ = c.pool.Release(ips...)
 
@@ -205,7 +209,7 @@ func (c *globalIngressIPController) onCreate(ingressIP *submarinerv1.GlobalIngre
 			return false
 		}
 
-		err = c.createOrUpdateInternalService(service, ips[0])
+		err = c.createOrUpdateInternalService(ctx, service, ips[0])
 		if err != nil {
 			_ = c.pool.Release(ips...)
 
@@ -281,7 +285,7 @@ func (c *globalIngressIPController) onCreate(ingressIP *submarinerv1.GlobalIngre
 	return false
 }
 
-func (c *globalIngressIPController) createOrUpdateInternalService(from *corev1.Service, extIP string) error {
+func (c *globalIngressIPController) createOrUpdateInternalService(ctx context.Context, from *corev1.Service, extIP string) error {
 	internalService := &corev1.Service{
 		ObjectMeta: metav1.ObjectMeta{
 			Name: GetInternalSvcName(from.Name),
@@ -300,7 +304,7 @@ func (c *globalIngressIPController) createOrUpdateInternalService(from *corev1.S
 	}
 
 	obj := resource.MustToUnstructured(internalService)
-	result, err := util.CreateOrUpdate(context.TODO(), resource.ForDynamic(c.services.Namespace(from.Namespace)), obj, util.Replace(obj))
+	result, err := util.CreateOrUpdate(ctx, resource.ForDynamic(c.services.Namespace(from.Namespace)), obj, util.Replace(obj))
 
 	if result == util.OperationResultCreated {
 		logger.Infof("Created internal service \"%s/%s\"", from.Namespace, internalService.Name)
@@ -311,12 +315,12 @@ func (c *globalIngressIPController) createOrUpdateInternalService(from *corev1.S
 	return err //nolint:wrapcheck  // No need to wrap here
 }
 
-func (c *globalIngressIPController) onUpdate(ingressIP *submarinerv1.GlobalIngressIP) bool {
+func (c *globalIngressIPController) onUpdate(ctx context.Context, ingressIP *submarinerv1.GlobalIngressIP) bool {
 	if ingressIP.Spec.Target != submarinerv1.ClusterIPService {
 		return false
 	}
 
-	service, exists, err := getService(ingressIP.Spec.ServiceRef.Name, ingressIP.Namespace, c.services, c.scheme)
+	service, exists, err := getService(ctx, ingressIP.Spec.ServiceRef.Name, ingressIP.Namespace, c.services, c.scheme)
 	if !exists {
 		return false
 	}
@@ -328,7 +332,7 @@ func (c *globalIngressIPController) onUpdate(ingressIP *submarinerv1.GlobalIngre
 		return true
 	}
 
-	err = c.createOrUpdateInternalService(service, ingressIP.Status.AllocatedIP)
+	err = c.createOrUpdateInternalService(ctx, service, ingressIP.Status.AllocatedIP)
 	if err != nil {
 		logger.Errorf(err, "Failed to update the internal Service for \"%s/%s\"", ingressIP.Namespace, ingressIP.Name)
 		return true
@@ -338,7 +342,7 @@ func (c *globalIngressIPController) onUpdate(ingressIP *submarinerv1.GlobalIngre
 }
 
 //nolint:wrapcheck  // No need to wrap these errors.
-func (c *globalIngressIPController) onDelete(ingressIP *submarinerv1.GlobalIngressIP, numRequeues int) bool {
+func (c *globalIngressIPController) onDelete(ctx context.Context, ingressIP *submarinerv1.GlobalIngressIP, numRequeues int) bool {
 	if ingressIP.Status.AllocatedIP == "" {
 		return false
 	}
@@ -349,20 +353,20 @@ func (c *globalIngressIPController) onDelete(ingressIP *submarinerv1.GlobalIngre
 		intSvcName := GetInternalSvcName(ingressIP.Spec.ServiceRef.Name)
 		logger.Infof("Deleting the service %q/%q created by Globalnet controller", ingressIP.Namespace, intSvcName)
 
-		intSvc, exists, err := getService(intSvcName, ingressIP.Namespace, c.services, c.scheme)
+		intSvc, exists, err := getService(ctx, intSvcName, ingressIP.Namespace, c.services, c.scheme)
 		if err != nil {
 			logger.Errorf(err, "Error retrieving the internal service created by Globalnet controller %q", key)
 			return shouldRequeue(numRequeues)
 		}
 
 		if exists {
-			if err = finalizer.Remove(context.TODO(), resource.ForDynamic(c.services.Namespace(ingressIP.Namespace)),
+			if err = finalizer.Remove(ctx, resource.ForDynamic(c.services.Namespace(ingressIP.Namespace)),
 				resource.MustToUnstructured(intSvc), InternalServiceFinalizer); err != nil {
 				logger.Errorf(err, "Error while removing the finalizer from service %q", key)
 				return true
 			}
 
-			err = deleteService(ingressIP.Namespace, intSvcName, c.services)
+			err = deleteService(ctx, ingressIP.Namespace, intSvcName, c.services)
 			if err != nil {
 				logger.Errorf(err, "Error while deleting the internal %q", key)
 				return true
@@ -402,12 +406,12 @@ func (c *globalIngressIPController) onDelete(ingressIP *submarinerv1.GlobalIngre
 	}, ingressIP.Status.AllocatedIP)
 }
 
-func (c *globalIngressIPController) ensureInternalServiceExists(ingressIP *submarinerv1.GlobalIngressIP) error {
+func (c *globalIngressIPController) ensureInternalServiceExists(ctx context.Context, ingressIP *submarinerv1.GlobalIngressIP) error {
 	serviceRef := ingressIP.Spec.ServiceRef
 	internalSvc := GetInternalSvcName(serviceRef.Name)
 	key := fmt.Sprintf("%s/%s", ingressIP.Namespace, internalSvc)
 
-	service, exists, err := getService(internalSvc, ingressIP.Namespace, c.services, c.scheme)
+	service, exists, err := getService(ctx, internalSvc, ingressIP.Namespace, c.services, c.scheme)
 	if err != nil {
 		return errors.Wrapf(err, "error retrieving Globalnet ExternalIP service %q for GlobalIngressIP %q", key, ingressIP.Name)
 	}
@@ -424,12 +428,12 @@ func (c *globalIngressIPController) ensureInternalServiceExists(ingressIP *subma
 		// A user is ideally not supposed to modify the external-ip of the Globalnet internal service, but
 		// in-case its done accidentally, as part of controller start/re-start scenario, this code will fix
 		// the issue by deleting and re-creating the internal service with valid configuration.
-		if err := finalizer.Remove(context.TODO(), resource.ForDynamic(c.services.Namespace(ingressIP.Namespace)),
+		if err := finalizer.Remove(ctx, resource.ForDynamic(c.services.Namespace(ingressIP.Namespace)),
 			resource.MustToUnstructured(service), InternalServiceFinalizer); err != nil {
 			return errors.Wrapf(err, "error while removing the finalizer from Globalnet ExternalIP service %q", key)
 		}
 
-		return deleteService(ingressIP.Namespace, internalSvc, c.services)
+		return deleteService(ctx, ingressIP.Namespace, internalSvc, c.services)
 	}
 
 	return nil
diff --git a/pkg/globalnet/controllers/ingress_endpoints_controller.go b/pkg/globalnet/controllers/ingress_endpoints_controller.go
index c73f6b343..44fec6df8 100644
--- a/pkg/globalnet/controllers/ingress_endpoints_controller.go
+++ b/pkg/globalnet/controllers/ingress_endpoints_controller.go
@@ -35,11 +35,14 @@ import (
 	"k8s.io/apimachinery/pkg/fields"
 	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/util/wait"
 	"k8s.io/client-go/tools/cache"
 	k8snet "k8s.io/utils/net"
 )
 
-func startIngressEndpointsController(svc *corev1.Service, config *syncer.ResourceSyncerConfig) (*ingressEndpointsController, error) {
+func startIngressEndpointsController(ctx context.Context, svc *corev1.Service,
+	config *syncer.ResourceSyncerConfig,
+) (*ingressEndpointsController, error) {
 	var err error
 
 	_, gvr, err := util.ToUnstructuredResource(&submarinerv1.GlobalIngressIP{}, config.RestMapper)
@@ -75,12 +78,12 @@ func startIngressEndpointsController(svc *corev1.Service, config *syncer.Resourc
 		return nil, errors.Wrap(err, "error creating the endpoints syncer")
 	}
 
-	if err := controller.Start(); err != nil {
+	if err := controller.Start(ctx); err != nil {
 		return nil, errors.Wrap(err, "error starting the endpoint syncer")
 	}
 
 	ingressIPs := config.SourceClient.Resource(*gvr).Namespace(corev1.NamespaceAll)
-	controller.reconcile(ingressIPs, "" /* labelSelector */, fieldSelector, func(obj *unstructured.Unstructured) runtime.Object {
+	controller.reconcile(ctx, ingressIPs, "" /* labelSelector */, fieldSelector, func(obj *unstructured.Unstructured) runtime.Object {
 		endpointsName, exists, _ := unstructured.NestedString(obj.Object, "spec", "serviceRef", "name")
 		if exists {
 			return &corev1.Endpoints{
@@ -100,19 +103,22 @@ func startIngressEndpointsController(svc *corev1.Service, config *syncer.Resourc
 }
 
 func (c *ingressEndpointsController) process(from runtime.Object, _ int, op syncer.Operation) (runtime.Object, bool) {
+	ctx := wait.ContextForChannel(c.stopCh)
+
 	endpoints := from.(*corev1.Endpoints)
 
 	switch op {
 	case syncer.Create, syncer.Update:
-		return c.onCreateOrUpdate(endpoints, op)
+		return c.onCreateOrUpdate(ctx, endpoints, op)
 	case syncer.Delete:
-		return c.onDelete(endpoints)
+		return c.onDelete(ctx, endpoints)
 	}
 
 	return nil, false
 }
 
-func (c *ingressEndpointsController) onCreateOrUpdate(endpoints *corev1.Endpoints, op syncer.Operation) (runtime.Object, bool) {
+func (c *ingressEndpointsController) onCreateOrUpdate(ctx context.Context, endpoints *corev1.Endpoints, op syncer.Operation,
+) (runtime.Object, bool) {
 	key, _ := cache.MetaNamespaceKeyFunc(endpoints)
 
 	logger.Infof("%q ingress Endpoints %s for service %s", op, key, c.svcName)
@@ -131,7 +137,7 @@ func (c *ingressEndpointsController) onCreateOrUpdate(endpoints *corev1.Endpoint
 	// Get List of existing ingressIPs
 	selector := labels.SelectorFromSet(map[string]string{ServiceRefLabel: endpoints.Name}).String()
 
-	existingIngressIPs, err := c.ingressIPs.Namespace(endpoints.Namespace).List(context.TODO(), metav1.ListOptions{LabelSelector: selector})
+	existingIngressIPs, err := c.ingressIPs.Namespace(endpoints.Namespace).List(ctx, metav1.ListOptions{LabelSelector: selector})
 	if err != nil {
 		return nil, true
 	}
@@ -149,7 +155,7 @@ func (c *ingressEndpointsController) onCreateOrUpdate(endpoints *corev1.Endpoint
 			}
 		}
 
-		err := c.ingressIPs.Namespace(ingressIP.GetNamespace()).Delete(context.TODO(), ingressIP.GetName(), metav1.DeleteOptions{})
+		err := c.ingressIPs.Namespace(ingressIP.GetNamespace()).Delete(ctx, ingressIP.GetName(), metav1.DeleteOptions{})
 		if err != nil {
 			return nil, true
 		}
@@ -173,7 +179,7 @@ func (c *ingressEndpointsController) onCreateOrUpdate(endpoints *corev1.Endpoint
 			return nil, true
 		}
 
-		_, err = c.ingressIPs.Namespace(ingressIP.GetNamespace()).Create(context.TODO(), uIngressIP, metav1.CreateOptions{})
+		_, err = c.ingressIPs.Namespace(ingressIP.GetNamespace()).Create(ctx, uIngressIP, metav1.CreateOptions{})
 		if err != nil {
 			return nil, true
 		}
@@ -182,12 +188,12 @@ func (c *ingressEndpointsController) onCreateOrUpdate(endpoints *corev1.Endpoint
 	return nil, false
 }
 
-func (c *ingressEndpointsController) onDelete(endpoints *corev1.Endpoints) (runtime.Object, bool) {
+func (c *ingressEndpointsController) onDelete(ctx context.Context, endpoints *corev1.Endpoints) (runtime.Object, bool) {
 	key, _ := cache.MetaNamespaceKeyFunc(endpoints)
 
 	selector := labels.SelectorFromSet(map[string]string{ServiceRefLabel: endpoints.Name}).String()
 
-	err := c.ingressIPs.Namespace(endpoints.Namespace).DeleteCollection(context.TODO(), metav1.DeleteOptions{},
+	err := c.ingressIPs.Namespace(endpoints.Namespace).DeleteCollection(ctx, metav1.DeleteOptions{},
 		metav1.ListOptions{LabelSelector: selector})
 	if err != nil {
 		return nil, true
diff --git a/pkg/globalnet/controllers/ingress_endpoints_controllers.go b/pkg/globalnet/controllers/ingress_endpoints_controllers.go
index d451eb779..c61146cfb 100644
--- a/pkg/globalnet/controllers/ingress_endpoints_controllers.go
+++ b/pkg/globalnet/controllers/ingress_endpoints_controllers.go
@@ -45,7 +45,7 @@ func NewIngressEndpointsControllers(config *syncer.ResourceSyncerConfig) (*Ingre
 	}, nil
 }
 
-func (c *IngressEndpointsControllers) start(service *corev1.Service) error {
+func (c *IngressEndpointsControllers) start(ctx context.Context, service *corev1.Service) error {
 	c.mutex.Lock()
 	defer c.mutex.Unlock()
 
@@ -54,7 +54,7 @@ func (c *IngressEndpointsControllers) start(service *corev1.Service) error {
 		return nil
 	}
 
-	controller, err := startIngressEndpointsController(service, &c.config)
+	controller, err := startIngressEndpointsController(ctx, service, &c.config)
 	if err != nil {
 		return err
 	}
@@ -64,18 +64,18 @@ func (c *IngressEndpointsControllers) start(service *corev1.Service) error {
 	return nil
 }
 
-func (c *IngressEndpointsControllers) stopAll() {
+func (c *IngressEndpointsControllers) stopAll(ctx context.Context) {
 	c.mutex.Lock()
 	defer c.mutex.Unlock()
 
 	for _, controller := range c.controllers {
-		controller.Stop()
+		controller.Stop(ctx)
 	}
 
 	c.controllers = map[string]*ingressEndpointsController{}
 }
 
-func (c *IngressEndpointsControllers) stopAndCleanup(serviceName, serviceNamespace string) {
+func (c *IngressEndpointsControllers) stopAndCleanup(ctx context.Context, serviceName, serviceNamespace string) {
 	c.mutex.Lock()
 	defer c.mutex.Unlock()
 
@@ -83,12 +83,12 @@ func (c *IngressEndpointsControllers) stopAndCleanup(serviceName, serviceNamespa
 	controller, exists := c.controllers[key]
 
 	if exists {
-		controller.Stop()
+		controller.Stop(ctx)
 		delete(c.controllers, key)
 	}
 
 	svcSelector := labels.SelectorFromSet(map[string]string{ServiceRefLabel: serviceName}).String()
-	err := c.ingressIPs.Namespace(serviceNamespace).DeleteCollection(context.TODO(), metav1.DeleteOptions{},
+	err := c.ingressIPs.Namespace(serviceNamespace).DeleteCollection(ctx, metav1.DeleteOptions{},
 		metav1.ListOptions{LabelSelector: svcSelector})
 
 	if err != nil && !apierrors.IsNotFound(err) {
diff --git a/pkg/globalnet/controllers/ingress_pod_controller.go b/pkg/globalnet/controllers/ingress_pod_controller.go
index 0670c7e74..25b1a0689 100644
--- a/pkg/globalnet/controllers/ingress_pod_controller.go
+++ b/pkg/globalnet/controllers/ingress_pod_controller.go
@@ -19,6 +19,7 @@ limitations under the License.
 package controllers
 
 import (
+	"context"
 	"fmt"
 
 	"github.com/pkg/errors"
@@ -38,7 +39,9 @@ import (
 	"k8s.io/utils/set"
 )
 
-func startIngressPodController(svc *corev1.Service, config *syncer.ResourceSyncerConfig) (*ingressPodController, error) {
+func startIngressPodController(ctx context.Context, svc *corev1.Service,
+	config *syncer.ResourceSyncerConfig,
+) (*ingressPodController, error) {
 	var err error
 
 	_, gvr, err := util.ToUnstructuredResource(&submarinerv1.GlobalIngressIP{}, config.RestMapper)
@@ -74,7 +77,7 @@ func startIngressPodController(svc *corev1.Service, config *syncer.ResourceSynce
 		return nil, errors.Wrap(err, "error creating the syncer")
 	}
 
-	if err := controller.Start(); err != nil {
+	if err := controller.Start(ctx); err != nil {
 		return nil, errors.Wrap(err, "error starting the syncer")
 	}
 
@@ -84,7 +87,7 @@ func startIngressPodController(svc *corev1.Service, config *syncer.ResourceSynce
 
 	ingressIPSelector := labels.Set(selector).AsSelector().String()
 	ingressIPs := config.SourceClient.Resource(*gvr).Namespace(corev1.NamespaceAll)
-	controller.reconcile(ingressIPs, ingressIPSelector, "" /* fieldSelector*/, func(obj *unstructured.Unstructured) runtime.Object {
+	controller.reconcile(ctx, ingressIPs, ingressIPSelector, "" /* fieldSelector*/, func(obj *unstructured.Unstructured) runtime.Object {
 		podName, exists, _ := unstructured.NestedString(obj.Object, "spec", "podRef", "name")
 		if exists {
 			return &corev1.Pod{
diff --git a/pkg/globalnet/controllers/ingress_pod_controllers.go b/pkg/globalnet/controllers/ingress_pod_controllers.go
index 936ec14a6..bd83d6bb6 100644
--- a/pkg/globalnet/controllers/ingress_pod_controllers.go
+++ b/pkg/globalnet/controllers/ingress_pod_controllers.go
@@ -46,7 +46,7 @@ func NewIngressPodControllers(config *syncer.ResourceSyncerConfig) (*IngressPodC
 	}, nil
 }
 
-func (c *IngressPodControllers) start(service *corev1.Service) error {
+func (c *IngressPodControllers) start(ctx context.Context, service *corev1.Service) error {
 	c.mutex.Lock()
 	defer c.mutex.Unlock()
 
@@ -55,7 +55,7 @@ func (c *IngressPodControllers) start(service *corev1.Service) error {
 		return nil
 	}
 
-	controller, err := startIngressPodController(service, &c.config)
+	controller, err := startIngressPodController(ctx, service, &c.config)
 	if err != nil {
 		return err
 	}
@@ -65,18 +65,18 @@ func (c *IngressPodControllers) start(service *corev1.Service) error {
 	return nil
 }
 
-func (c *IngressPodControllers) stopAll() {
+func (c *IngressPodControllers) stopAll(ctx context.Context) {
 	c.mutex.Lock()
 	defer c.mutex.Unlock()
 
 	for _, controller := range c.controllers {
-		controller.Stop()
+		controller.Stop(ctx)
 	}
 
 	c.controllers = map[string]*ingressPodController{}
 }
 
-func (c *IngressPodControllers) stopAndCleanup(serviceName, serviceNamespace string) {
+func (c *IngressPodControllers) stopAndCleanup(ctx context.Context, serviceName, serviceNamespace string) {
 	c.mutex.Lock()
 	defer c.mutex.Unlock()
 
@@ -84,12 +84,12 @@ func (c *IngressPodControllers) stopAndCleanup(serviceName, serviceNamespace str
 
 	controller, exists := c.controllers[key]
 	if exists {
-		controller.Stop()
+		controller.Stop(ctx)
 		delete(c.controllers, key)
 	}
 
 	svcSelector := labels.SelectorFromSet(map[string]string{ServiceRefLabel: serviceName}).String()
-	err := c.ingressIPs.Namespace(serviceNamespace).DeleteCollection(context.TODO(), metav1.DeleteOptions{},
+	err := c.ingressIPs.Namespace(serviceNamespace).DeleteCollection(ctx, metav1.DeleteOptions{},
 		metav1.ListOptions{LabelSelector: svcSelector})
 
 	if err != nil && !apierrors.IsNotFound(err) {
diff --git a/pkg/globalnet/controllers/service_controller.go b/pkg/globalnet/controllers/service_controller.go
index 97e64b845..e7eaf4a50 100644
--- a/pkg/globalnet/controllers/service_controller.go
+++ b/pkg/globalnet/controllers/service_controller.go
@@ -19,6 +19,8 @@ limitations under the License.
 package controllers
 
 import (
+	"context"
+
 	"github.com/pkg/errors"
 	"github.com/submariner-io/admiral/pkg/federate"
 	"github.com/submariner-io/admiral/pkg/global"
@@ -30,6 +32,7 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/util/wait"
 	"k8s.io/client-go/tools/cache"
 )
 
@@ -74,13 +77,13 @@ func NewServiceController(config *syncer.ResourceSyncerConfig, podControllers *I
 	return controller, nil
 }
 
-func (c *serviceController) Start() error {
-	err := c.baseSyncerController.Start()
+func (c *serviceController) Start(ctx context.Context) error {
+	err := c.baseSyncerController.Start(ctx)
 	if err != nil {
 		return err
 	}
 
-	c.reconcile(c.ingressIPs, "" /* labelSelector */, "", /* fieldSelector */
+	c.reconcile(ctx, c.ingressIPs, "" /* labelSelector */, "", /* fieldSelector */
 		func(obj *unstructured.Unstructured) runtime.Object {
 			name, exists, _ := unstructured.NestedString(obj.Object, "spec", "serviceRef", "name")
 			if exists {
@@ -102,6 +105,8 @@ func (c *serviceController) Start() error {
 }
 
 func (c *serviceController) process(from runtime.Object, _ int, op syncer.Operation) (runtime.Object, bool) {
+	ctx := wait.ContextForChannel(c.stopCh)
+
 	service := from.(*corev1.Service)
 
 	if service.Spec.Type != corev1.ServiceTypeClusterIP {
@@ -116,7 +121,7 @@ func (c *serviceController) process(from runtime.Object, _ int, op syncer.Operat
 		// For Create, requeue the associated ServiceExport, if any, to re-create the GlobalIngressIP.
 		c.serviceExportSyncer.RequeueResource(service.Name, service.Namespace)
 	case syncer.Delete:
-		return c.onDelete(service)
+		return c.onDelete(ctx, service)
 	case syncer.Update:
 		c.gipSyncer.RequeueResource(service.Name, service.Namespace)
 	}
@@ -124,8 +129,8 @@ func (c *serviceController) process(from runtime.Object, _ int, op syncer.Operat
 	return nil, false
 }
 
-func (c *serviceController) onDelete(service *corev1.Service) (runtime.Object, bool) {
-	c.podControllers.stopAndCleanup(service.Name, service.Namespace)
+func (c *serviceController) onDelete(ctx context.Context, service *corev1.Service) (runtime.Object, bool) {
+	c.podControllers.stopAndCleanup(ctx, service.Name, service.Namespace)
 
 	if service.Spec.ClusterIP == corev1.ClusterIPNone {
 		return nil, false
diff --git a/pkg/globalnet/controllers/service_export_controller.go b/pkg/globalnet/controllers/service_export_controller.go
index 6b7c13eb3..2be2448a1 100644
--- a/pkg/globalnet/controllers/service_export_controller.go
+++ b/pkg/globalnet/controllers/service_export_controller.go
@@ -19,6 +19,7 @@ limitations under the License.
 package controllers
 
 import (
+	"context"
 	"slices"
 
 	"github.com/pkg/errors"
@@ -33,6 +34,7 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/util/wait"
 	"k8s.io/client-go/tools/cache"
 	mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
 )
@@ -97,20 +99,20 @@ func (c *serviceExportController) GetSyncer() syncer.Interface {
 	return c.resourceSyncer
 }
 
-func (c *serviceExportController) Stop() {
-	c.baseController.Stop()
-	c.podControllers.stopAll()
-	c.endpointsControllers.stopAll()
-	c.ingressEndpointsControllers.stopAll()
+func (c *serviceExportController) Stop(ctx context.Context) {
+	c.baseController.Stop(ctx)
+	c.podControllers.stopAll(ctx)
+	c.endpointsControllers.stopAll(ctx)
+	c.ingressEndpointsControllers.stopAll(ctx)
 }
 
-func (c *serviceExportController) Start() error {
-	err := c.baseSyncerController.Start()
+func (c *serviceExportController) Start(ctx context.Context) error {
+	err := c.baseSyncerController.Start(ctx)
 	if err != nil {
 		return err
 	}
 
-	c.reconcile(c.ingressIPs, "" /* labelSelector */, "", /* fieldSelector */
+	c.reconcile(ctx, c.ingressIPs, "" /* labelSelector */, "", /* fieldSelector */
 		func(obj *unstructured.Unstructured) runtime.Object {
 			name, exists, _ := unstructured.NestedString(obj.Object, "spec", "serviceRef", "name")
 			if exists {
@@ -129,23 +131,25 @@ func (c *serviceExportController) Start() error {
 }
 
 func (c *serviceExportController) process(from runtime.Object, _ int, op syncer.Operation) (runtime.Object, bool) {
+	ctx := wait.ContextForChannel(c.stopCh)
+
 	serviceExport := from.(*mcsv1a1.ServiceExport)
 
 	switch op {
 	case syncer.Create:
-		return c.onCreate(serviceExport)
+		return c.onCreate(ctx, serviceExport)
 	case syncer.Delete:
-		return c.onDelete(serviceExport)
+		return c.onDelete(ctx, serviceExport)
 	case syncer.Update:
 	}
 
 	return nil, false
 }
 
-func (c *serviceExportController) onCreate(serviceExport *mcsv1a1.ServiceExport) (runtime.Object, bool) {
+func (c *serviceExportController) onCreate(ctx context.Context, serviceExport *mcsv1a1.ServiceExport) (runtime.Object, bool) {
 	key, _ := cache.MetaNamespaceKeyFunc(serviceExport)
 
-	service, exists, err := getService(serviceExport.Name, serviceExport.Namespace, c.services, c.scheme)
+	service, exists, err := getService(ctx, serviceExport.Name, serviceExport.Namespace, c.services, c.scheme)
 	if err != nil || !exists {
 		logger.Infof("Exported Service %q does not exist yet - re-queueing", key)
 		return nil, true
@@ -161,7 +165,7 @@ func (c *serviceExportController) onCreate(serviceExport *mcsv1a1.ServiceExport)
 
 	if len(service.Spec.Selector) == 0 && service.Spec.ClusterIP != corev1.ClusterIPNone {
 		// Service without selector and not headless service
-		err = c.endpointsControllers.start(serviceExport)
+		err = c.endpointsControllers.start(ctx, serviceExport)
 		if err != nil {
 			logger.Errorf(err, "Failed to create endpoints controller for serviceExport %q", key)
 			return nil, true
@@ -171,10 +175,10 @@ func (c *serviceExportController) onCreate(serviceExport *mcsv1a1.ServiceExport)
 	if service.Spec.ClusterIP == corev1.ClusterIPNone {
 		if len(service.Spec.Selector) == 0 {
 			// Headless service without selector
-			return c.onCreateHeadlessWithoutSelector(key, service)
+			return c.onCreateHeadlessWithoutSelector(ctx, key, service)
 		}
 		// Headless service
-		return c.onCreateHeadless(key, service)
+		return c.onCreateHeadless(ctx, key, service)
 	}
 
 	if !slices.Contains(service.Spec.IPFamilies, corev1.IPv4Protocol) {
@@ -198,14 +202,14 @@ func (c *serviceExportController) onCreate(serviceExport *mcsv1a1.ServiceExport)
 	return ingressIP, false
 }
 
-func (c *serviceExportController) onDelete(serviceExport *mcsv1a1.ServiceExport) (runtime.Object, bool) {
+func (c *serviceExportController) onDelete(ctx context.Context, serviceExport *mcsv1a1.ServiceExport) (runtime.Object, bool) {
 	key, _ := cache.MetaNamespaceKeyFunc(serviceExport)
 
 	logger.Infof("ServiceExport %q deleted", key)
 
-	c.podControllers.stopAndCleanup(serviceExport.Name, serviceExport.Namespace)
-	c.endpointsControllers.stopAndCleanup(serviceExport.Name, serviceExport.Namespace)
-	c.ingressEndpointsControllers.stopAndCleanup(serviceExport.Name, serviceExport.Namespace)
+	c.podControllers.stopAndCleanup(ctx, serviceExport.Name, serviceExport.Namespace)
+	c.endpointsControllers.stopAndCleanup(ctx, serviceExport.Name, serviceExport.Namespace)
+	c.ingressEndpointsControllers.stopAndCleanup(ctx, serviceExport.Name, serviceExport.Namespace)
 
 	return &submarinerv1.GlobalIngressIP{
 		ObjectMeta: metav1.ObjectMeta{
@@ -215,8 +219,8 @@ func (c *serviceExportController) onDelete(serviceExport *mcsv1a1.ServiceExport)
 	}, false
 }
 
-func (c *serviceExportController) onCreateHeadless(key string, service *corev1.Service) (runtime.Object, bool) {
-	err := c.podControllers.start(service)
+func (c *serviceExportController) onCreateHeadless(ctx context.Context, key string, service *corev1.Service) (runtime.Object, bool) {
+	err := c.podControllers.start(ctx, service)
 	if err != nil {
 		logger.Errorf(err, "Failed to create pod controller for service %q", key)
 		return nil, true
@@ -225,8 +229,10 @@ func (c *serviceExportController) onCreateHeadless(key string, service *corev1.S
 	return nil, false
 }
 
-func (c *serviceExportController) onCreateHeadlessWithoutSelector(key string, service *corev1.Service) (runtime.Object, bool) {
-	err := c.ingressEndpointsControllers.start(service)
+func (c *serviceExportController) onCreateHeadlessWithoutSelector(ctx context.Context, key string,
+	service *corev1.Service,
+) (runtime.Object, bool) {
+	err := c.ingressEndpointsControllers.start(ctx, service)
 	if err != nil {
 		logger.Errorf(err, "Failed to create endpoints controller for service %q", key)
 		return nil, true
diff --git a/pkg/globalnet/controllers/service_export_endpoints_controllers.go b/pkg/globalnet/controllers/service_export_endpoints_controllers.go
index 61be75ccc..6a4b4a951 100644
--- a/pkg/globalnet/controllers/service_export_endpoints_controllers.go
+++ b/pkg/globalnet/controllers/service_export_endpoints_controllers.go
@@ -31,7 +31,8 @@ import (
 	mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
 )
 
-func NewServiceExportEndpointsControllers(config *syncer.ResourceSyncerConfig) (*ServiceExportEndpointsControllers, error) {
+func NewServiceExportEndpointsControllers(ctx context.Context, config *syncer.ResourceSyncerConfig,
+) (*ServiceExportEndpointsControllers, error) {
 	// We'll panic if config is nil, this is intentional
 	// Ensure that cloned endpoints whose original endpoints are deleted while the controller stops are deleted.
 	_, gvr, err := util.ToUnstructuredResource(&corev1.Endpoints{}, config.RestMapper)
@@ -41,7 +42,7 @@ func NewServiceExportEndpointsControllers(config *syncer.ResourceSyncerConfig) (
 
 	client := config.SourceClient.Resource(*gvr)
 
-	err = ensureClonedHasOriginal(client)
+	err = ensureClonedHasOriginal(ctx, client)
 	if err != nil {
 		return nil, errors.Wrap(err, "error ensuring cloned Endpoints has original")
 	}
@@ -52,7 +53,7 @@ func NewServiceExportEndpointsControllers(config *syncer.ResourceSyncerConfig) (
 	}, nil
 }
 
-func (c *ServiceExportEndpointsControllers) start(se *mcsv1a1.ServiceExport) error {
+func (c *ServiceExportEndpointsControllers) start(ctx context.Context, se *mcsv1a1.ServiceExport) error {
 	c.mutex.Lock()
 	defer c.mutex.Unlock()
 
@@ -61,7 +62,7 @@ func (c *ServiceExportEndpointsControllers) start(se *mcsv1a1.ServiceExport) err
 		return nil
 	}
 
-	controller, err := startEndpointsController(se.Name, se.Namespace, &c.config)
+	controller, err := startEndpointsController(ctx, se.Name, se.Namespace, &c.config)
 	if err != nil {
 		return err
 	}
@@ -71,18 +72,18 @@ func (c *ServiceExportEndpointsControllers) start(se *mcsv1a1.ServiceExport) err
 	return nil
 }
 
-func (c *ServiceExportEndpointsControllers) stopAll() {
+func (c *ServiceExportEndpointsControllers) stopAll(ctx context.Context) {
 	c.mutex.Lock()
 	defer c.mutex.Unlock()
 
 	for _, controller := range c.controllers {
-		controller.Stop()
+		controller.Stop(ctx)
 	}
 
 	c.controllers = map[string]*endpointsController{}
 }
 
-func (c *ServiceExportEndpointsControllers) stopAndCleanup(seName, seNamespace string) {
+func (c *ServiceExportEndpointsControllers) stopAndCleanup(ctx context.Context, seName, seNamespace string) {
 	c.mutex.Lock()
 	defer c.mutex.Unlock()
 
@@ -90,13 +91,13 @@ func (c *ServiceExportEndpointsControllers) stopAndCleanup(seName, seNamespace s
 
 	controller, exists := c.controllers[key]
 	if exists {
-		controller.Stop()
+		controller.Stop(ctx)
 		delete(c.controllers, key)
 	}
 }
 
-func ensureClonedHasOriginal(client dynamic.NamespaceableResourceInterface) error {
-	list, err := client.Namespace(corev1.NamespaceAll).List(context.TODO(), metav1.ListOptions{})
+func ensureClonedHasOriginal(ctx context.Context, client dynamic.NamespaceableResourceInterface) error {
+	list, err := client.Namespace(corev1.NamespaceAll).List(ctx, metav1.ListOptions{})
 	if err != nil {
 		return errors.Wrap(err, "error listing the resources")
 	}
@@ -129,7 +130,7 @@ func ensureClonedHasOriginal(client dynamic.NamespaceableResourceInterface) erro
 		logger.Infof("Deleting cloned Endpoints %s/%s that doesn't have original Endpoints %s/%s",
 			obj1.GetNamespace(), obj1.GetName(), obj1.GetNamespace(), origEp)
 
-		err := deleteEndpoints(obj1.GetNamespace(), obj1.GetName(), client)
+		err := deleteEndpoints(ctx, obj1.GetNamespace(), obj1.GetName(), client)
 		if err != nil {
 			return errors.Wrap(err, "error deleting cloned Endpoints without original")
 		}
diff --git a/pkg/globalnet/controllers/types.go b/pkg/globalnet/controllers/types.go
index fb58922c4..8eb797807 100644
--- a/pkg/globalnet/controllers/types.go
+++ b/pkg/globalnet/controllers/types.go
@@ -80,8 +80,8 @@ const (
 )
 
 type Interface interface {
-	Start() error
-	Stop()
+	Start(ctx context.Context) error
+	Stop(ctx context.Context)
 }
 
 type Specification struct {
diff --git a/pkg/globalnet/controllers/uninstall.go b/pkg/globalnet/controllers/uninstall.go
index 828f45168..9cd18f503 100644
--- a/pkg/globalnet/controllers/uninstall.go
+++ b/pkg/globalnet/controllers/uninstall.go
@@ -89,38 +89,41 @@ func UninstallDataPath() {
 	logError(err, "Error destroying sets")
 }
 
-func DeleteGlobalnetObjects(smClientSet submclient.Interface, dynClient dynamic.Interface) {
-	err := smClientSet.SubmarinerV1().ClusterGlobalEgressIPs(metav1.NamespaceAll).DeleteCollection(context.TODO(), metav1.DeleteOptions{},
+func DeleteGlobalnetObjects(ctx context.Context, smClientSet submclient.Interface, dynClient dynamic.Interface) {
+	err := smClientSet.SubmarinerV1().ClusterGlobalEgressIPs(metav1.NamespaceAll).DeleteCollection(ctx, metav1.DeleteOptions{},
 		metav1.ListOptions{})
 	logError(err, "Error deleting the clusterGlobalEgressIPs")
 
-	err = smClientSet.SubmarinerV1().GlobalEgressIPs(metav1.NamespaceAll).DeleteCollection(context.TODO(), metav1.DeleteOptions{},
+	err = smClientSet.SubmarinerV1().GlobalEgressIPs(metav1.NamespaceAll).DeleteCollection(ctx, metav1.DeleteOptions{},
 		metav1.ListOptions{})
 	logError(err, "Error deleting the globalEgressIPs")
 
-	deleteGlobalIngressIPs(smClientSet, dynClient)
+	deleteGlobalIngressIPs(ctx, smClientSet, dynClient)
 }
 
-func deleteGlobalIngressIPs(smClientSet submclient.Interface, dynClient dynamic.Interface) {
-	defer deleteAllGlobalIngressIPObjs(smClientSet)
-
+func deleteGlobalIngressIPs(ctx context.Context, smClientSet submclient.Interface, dynClient dynamic.Interface) {
 	gvr := schema.GroupVersionResource{
 		Group:    corev1.SchemeGroupVersion.Group,
 		Version:  corev1.SchemeGroupVersion.Version,
 		Resource: "services",
 	}
 
-	giipList, err := smClientSet.SubmarinerV1().GlobalIngressIPs(metav1.NamespaceAll).List(context.TODO(), metav1.ListOptions{})
-	logError(err, "Error listing the globalIngressIP objects")
+	giipList, err := smClientSet.SubmarinerV1().GlobalIngressIPs(metav1.NamespaceAll).List(ctx, metav1.ListOptions{})
+	if err != nil {
+		logError(err, "Error listing the globalIngressIP objects")
+		return
+	}
+
+	defer deleteAllGlobalIngressIPObjs(ctx, smClientSet)
 
 	services := dynClient.Resource(gvr)
 
 	for i := range giipList.Items {
-		deleteInternalService(&giipList.Items[i], services)
+		deleteInternalService(ctx, &giipList.Items[i], services)
 	}
 }
 
-func deleteInternalService(ingressIP *submarinerv1.GlobalIngressIP, services dynamic.NamespaceableResourceInterface) {
+func deleteInternalService(ctx context.Context, ingressIP *submarinerv1.GlobalIngressIP, services dynamic.NamespaceableResourceInterface) {
 	if ingressIP.Spec.ServiceRef == nil {
 		return
 	}
@@ -130,24 +133,29 @@ func deleteInternalService(ingressIP *submarinerv1.GlobalIngressIP, services dyn
 
 	logger.Infof("Deleting the globalnet internal service: %q", key)
 
-	service, exists, _ := getService(internalSvc, ingressIP.Namespace, services, scheme.Scheme)
+	service, exists, err := getService(ctx, internalSvc, ingressIP.Namespace, services, scheme.Scheme)
+	if err != nil {
+		logError(err, "Error retrieving the globalnet internal service %q", key)
+		return
+	}
+
 	if exists {
-		err := finalizer.Remove(context.TODO(), resource.ForDynamic(services.Namespace(ingressIP.Namespace)),
+		err := finalizer.Remove(ctx, resource.ForDynamic(services.Namespace(ingressIP.Namespace)),
 			resource.MustToUnstructured(service), InternalServiceFinalizer)
-		logError(err, "rror while removing the finalizer from globalnet internal service %q", key)
+		logError(err, "Error while removing the finalizer from globalnet internal service %q", key)
 
-		err = deleteService(ingressIP.Namespace, internalSvc, services)
+		err = deleteService(ctx, ingressIP.Namespace, internalSvc, services)
 		logError(err, "Error deleting the service %q/%q", ingressIP.Namespace, internalSvc)
 	}
 }
 
-func deleteAllGlobalIngressIPObjs(smClientSet submclient.Interface) {
-	err := smClientSet.SubmarinerV1().GlobalIngressIPs(metav1.NamespaceAll).DeleteCollection(context.TODO(), metav1.DeleteOptions{},
+func deleteAllGlobalIngressIPObjs(ctx context.Context, smClientSet submclient.Interface) {
+	err := smClientSet.SubmarinerV1().GlobalIngressIPs(metav1.NamespaceAll).DeleteCollection(ctx, metav1.DeleteOptions{},
 		metav1.ListOptions{})
 	logError(err, "Error deleting the globalIngressIPs")
 }
 
-func RemoveStaleInternalServices(config *syncer.ResourceSyncerConfig) error {
+func RemoveStaleInternalServices(ctx context.Context, config *syncer.ResourceSyncerConfig) error {
 	_, gvr, err := util.ToUnstructuredResource(&corev1.Service{}, config.RestMapper)
 	if err != nil {
 		return errors.Wrap(err, "error converting resource")
@@ -155,7 +163,7 @@ func RemoveStaleInternalServices(config *syncer.ResourceSyncerConfig) error {
 
 	services := config.SourceClient.Resource(*gvr)
 
-	svcList, err := services.Namespace(corev1.NamespaceAll).List(context.TODO(), metav1.ListOptions{
+	svcList, err := services.Namespace(corev1.NamespaceAll).List(ctx, metav1.ListOptions{
 		LabelSelector: InternalServiceLabel,
 	})
 	if err != nil {
@@ -167,7 +175,7 @@ func RemoveStaleInternalServices(config *syncer.ResourceSyncerConfig) error {
 		if !svc.GetDeletionTimestamp().IsZero() {
 			logger.Warningf("Globalnet internal service %s/%s has deletionTimestamp set", svc.GetNamespace(), svc.GetName())
 
-			err := finalizer.Remove(context.TODO(), resource.ForDynamic(services.Namespace(svc.GetNamespace())),
+			err := finalizer.Remove(ctx, resource.ForDynamic(services.Namespace(svc.GetNamespace())),
 				resource.MustToUnstructured(svc), InternalServiceFinalizer)
 			if err != nil {
 				return errors.Wrapf(err, "error while removing the finalizer from globalnet internal service %q/%q",
diff --git a/pkg/globalnet/main.go b/pkg/globalnet/main.go
index b96901f70..8850e644c 100644
--- a/pkg/globalnet/main.go
+++ b/pkg/globalnet/main.go
@@ -112,7 +112,7 @@ func main() {
 		logger.Info("Uninstalling submariner-globalnet")
 
 		controllers.UninstallDataPath()
-		controllers.DeleteGlobalnetObjects(submarinerClient, dynClient)
+		controllers.DeleteGlobalnetObjects(ctx, submarinerClient, dynClient)
 
 		return
 	}
@@ -167,13 +167,18 @@ func main() {
 	})
 	logger.FatalOnError(err, "Error creating gatewayMonitor")
 
-	err = gatewayMonitor.Start()
+	err = gatewayMonitor.Start(ctx)
 	logger.FatalOnError(err, "Error starting the gatewayMonitor")
 
 	cleanupLegacyIptables()
 
 	<-ctx.Done()
-	gatewayMonitor.Stop()
+
+	// Stop should be pretty quick but put a deadline on it, so we don't block shutdown indefinitely.
+	stopCtx, cancel := context.WithTimeout(context.Background(), time.Second*30)
+	defer cancel()
+
+	gatewayMonitor.Stop(stopCtx)
 
 	logger.Infof("All controllers stopped or exited. Stopping main loop")
 }
diff --git a/pkg/routeagent_driver/handlers/calico/ippool_handler.go b/pkg/routeagent_driver/handlers/calico/ippool_handler.go
index d35add74d..3e74a8459 100644
--- a/pkg/routeagent_driver/handlers/calico/ippool_handler.go
+++ b/pkg/routeagent_driver/handlers/calico/ippool_handler.go
@@ -144,11 +144,11 @@ func (h *calicoIPPoolHandler) TransitionToGateway() error {
 	return goerrors.Join(retErrors...)
 }
 
-func (h *calicoIPPoolHandler) Uninstall() error {
+func (h *calicoIPPoolHandler) Uninstall(ctx context.Context) error {
 	logger.Info("Uninstalling Calico IPPools used for Submariner")
 
 	labelSelector := labels.SelectorFromSet(map[string]string{SubmarinerIPPool: "true"}).String()
-	err := h.client.ProjectcalicoV3().IPPools().DeleteCollection(context.TODO(), metav1.DeleteOptions{},
+	err := h.client.ProjectcalicoV3().IPPools().DeleteCollection(ctx, metav1.DeleteOptions{},
 		metav1.ListOptions{LabelSelector: labelSelector})
 
 	if err != nil && !apierrors.IsNotFound(err) {
@@ -157,7 +157,7 @@ func (h *calicoIPPoolHandler) Uninstall() error {
 
 	logger.Infof("Successfully delete Calico IPPools using labelSelector %q", labelSelector)
 
-	if err := h.restoreROKSCalicoCfg(); err != nil {
+	if err := h.restoreROKSCalicoCfg(ctx); err != nil {
 		return err
 	}
 
@@ -297,8 +297,8 @@ func (h *calicoIPPoolHandler) updateROKSCalicoCfg(ctx context.Context) error {
 	return errors.Wrapf(err, "failed to update Installation %q", DefaultInstallationName)
 }
 
-func (h *calicoIPPoolHandler) restoreROKSCalicoCfg() error {
-	err := util.Update(context.TODO(), resource.ForDynamic(h.dynClient.Resource(InstallationsGVR)),
+func (h *calicoIPPoolHandler) restoreROKSCalicoCfg(ctx context.Context) error {
+	err := util.Update(ctx, resource.ForDynamic(h.dynClient.Resource(InstallationsGVR)),
 		resource.MustToUnstructured(&tigerav1.Installation{
 			ObjectMeta: metav1.ObjectMeta{
 				Name: DefaultInstallationName,
diff --git a/pkg/routeagent_driver/handlers/healthchecker/healthchecker.go b/pkg/routeagent_driver/handlers/healthchecker/healthchecker.go
index b7db13735..14ef15333 100644
--- a/pkg/routeagent_driver/handlers/healthchecker/healthchecker.go
+++ b/pkg/routeagent_driver/handlers/healthchecker/healthchecker.go
@@ -73,15 +73,14 @@ func New(config *Config, client v1typed.SubmarinerV1Interface) event.Handler {
 	}
 }
 
-func (h *controller) Stop() error {
+func (h *controller) Stop(ctx context.Context) error {
 	h.pingerController.Stop()
 
 	h.stopOnce.Do(func() {
 		close(h.stopCh)
 	})
 
-	err := h.client.Delete(context.TODO(),
-		h.config.LocalNodeName, metav1.DeleteOptions{})
+	err := h.client.Delete(ctx, h.config.LocalNodeName, metav1.DeleteOptions{})
 	if err != nil && !apiError.IsNotFound(err) {
 		return errors.Wrapf(err, "Error deleting RouteAgent: %s", h.config.LocalNodeName)
 	}
diff --git a/pkg/routeagent_driver/handlers/kubeproxy/uninstall.go b/pkg/routeagent_driver/handlers/kubeproxy/uninstall.go
index 1b56e9fcb..5dfbc16b9 100644
--- a/pkg/routeagent_driver/handlers/kubeproxy/uninstall.go
+++ b/pkg/routeagent_driver/handlers/kubeproxy/uninstall.go
@@ -19,6 +19,7 @@ limitations under the License.
 package kubeproxy
 
 import (
+	"context"
 	"net"
 
 	"github.com/submariner-io/admiral/pkg/log"
@@ -30,7 +31,7 @@ import (
 	"github.com/vishvananda/netlink"
 )
 
-func (kp *SyncHandler) Uninstall() error {
+func (kp *SyncHandler) Uninstall(_ context.Context) error {
 	logger.Infof("Uninstalling Submariner changes from the node %q", kp.hostname)
 	logger.Infof("Flushing route table %d entries", constants.RouteAgentHostNetworkTableID)
 
diff --git a/pkg/routeagent_driver/handlers/mtu/mtuhandler.go b/pkg/routeagent_driver/handlers/mtu/mtuhandler.go
index 9715263f6..d87d36cee 100644
--- a/pkg/routeagent_driver/handlers/mtu/mtuhandler.go
+++ b/pkg/routeagent_driver/handlers/mtu/mtuhandler.go
@@ -237,7 +237,7 @@ func (h *mtuHandler) newNamedSetSet(key string) packetfilter.NamedSet {
 	})
 }
 
-func (h *mtuHandler) Uninstall() error {
+func (h *mtuHandler) Uninstall(ctx context.Context) error {
 	logger.Infof("Flushing packetfilter entries in %q chain of table type %q", chains.SmPostRoutingMss, h.tableType.String())
 
 	logError(h.pFilter.ClearChain(h.tableType, chains.SmPostRoutingMss),
diff --git a/pkg/routeagent_driver/handlers/ovn/uninstall.go b/pkg/routeagent_driver/handlers/ovn/uninstall.go
index a65ce467a..37cd6f2ee 100644
--- a/pkg/routeagent_driver/handlers/ovn/uninstall.go
+++ b/pkg/routeagent_driver/handlers/ovn/uninstall.go
@@ -33,7 +33,7 @@ import (
 	k8snet "k8s.io/utils/net"
 )
 
-func (ovn *Handler) Stop() error {
+func (ovn *Handler) Stop(_ context.Context) error {
 	ovn.gatewayRouteController.stop()
 
 	if ovn.nonGatewayRouteController != nil {
@@ -45,7 +45,7 @@ func (ovn *Handler) Stop() error {
 	return nil
 }
 
-func (ovn *Handler) Uninstall() error {
+func (ovn *Handler) Uninstall(ctx context.Context) error {
 	logger.Infof("Uninstalling OVN components from the node")
 
 	err := ovn.cleanupRoutes()
@@ -69,7 +69,7 @@ func (ovn *Handler) Uninstall() error {
 	ovn.deleteIPHookChain(packetfilter.TableTypeFilter, chains.NewForwardingMSSClamp())
 	ovn.deleteIPHookChain(packetfilter.TableTypeNAT, chains.NewPostRouting())
 
-	err = util.Update[*corev1.Node](context.TODO(), ovn.nodeResourceInterface(), &corev1.Node{
+	err = util.Update[*corev1.Node](ctx, ovn.nodeResourceInterface(), &corev1.Node{
 		ObjectMeta: metav1.ObjectMeta{Name: nodeutil.GetLocalNodeName()},
 	}, func(existing *corev1.Node) (*corev1.Node, error) {
 		delete(existing.Annotations, OVNKSNATExcludeSubnetsAnnotation)
diff --git a/pkg/routeagent_driver/main.go b/pkg/routeagent_driver/main.go
index 171dc4c62..80872d566 100644
--- a/pkg/routeagent_driver/main.go
+++ b/pkg/routeagent_driver/main.go
@@ -19,6 +19,7 @@ limitations under the License.
 package main
 
 import (
+	"context"
 	"flag"
 	"io/fs"
 	"os"
@@ -182,7 +183,7 @@ func main() {
 	logger.FatalOnError(err, "Error registering the handlers")
 
 	if env.Uninstall {
-		uninstall(registry)
+		uninstall(ctx, registry)
 
 		for _, family := range cidr.ExtractIPFamilies(env.ClusterCidr) {
 			pFilter, err := packetfilter.New(family)
@@ -216,7 +217,12 @@ func main() {
 	cleanupLegacyIptables(env.ClusterCidr)
 
 	<-stopCh
-	ctl.Stop()
+
+	// Stop should be pretty quick but put a deadline on it, so we don't block shutdown indefinitely.
+	stopCtx, cancel := context.WithTimeout(context.Background(), time.Second*30)
+	defer cancel()
+
+	ctl.Stop(stopCtx)
 
 	logger.Info("All controllers stopped or exited. Stopping submariner-route-agent")
 }
@@ -244,12 +250,12 @@ func getTCPMssValue(localNode *corev1.Node) int {
 	return tcpMssValue
 }
 
-func uninstall(registry *event.Registry) {
-	if err := registry.StopHandlers(); err != nil {
+func uninstall(ctx context.Context, registry *event.Registry) {
+	if err := registry.StopHandlers(ctx); err != nil {
 		logger.Warningf("Error stopping handlers: %v", err)
 	}
 
-	if err := registry.Uninstall(); err != nil {
+	if err := registry.Uninstall(ctx); err != nil {
 		logger.Warningf("Error uninstalling handlers: %v", err)
 	}
 }


Test patch:
diff --git a/pkg/event/registry_test.go b/pkg/event/registry_test.go
index 80cb29397..c8f5d0cf9 100644
--- a/pkg/event/registry_test.go
+++ b/pkg/event/registry_test.go
@@ -165,7 +165,7 @@ var _ = Describe("Event Handler", func() {
 
 func allEvents(registry *event.Registry) map[testing.TestEvent]func() error {
 	return map[testing.TestEvent]func() error{
-		{Name: testing.EvStop}:      func() error { return registry.StopHandlers() },
-		{Name: testing.EvUninstall}: func() error { return registry.Uninstall() },
+		{Name: testing.EvStop}:      func() error { return registry.StopHandlers(context.TODO()) },
+		{Name: testing.EvUninstall}: func() error { return registry.Uninstall(context.TODO()) },
 	}
 }
diff --git a/pkg/event/testing/controller_support.go b/pkg/event/testing/controller_support.go
index 0091dda2b..a7da7657a 100644
--- a/pkg/event/testing/controller_support.go
+++ b/pkg/event/testing/controller_support.go
@@ -92,7 +92,7 @@ func (c *ControllerSupport) Start(handlers ...event.Handler) {
 
 	DeferCleanup(func() {
 		close(stopCh)
-		eventController.Stop()
+		eventController.Stop(context.TODO())
 	})
 }
 
diff --git a/pkg/event/testing/testing.go b/pkg/event/testing/testing.go
index 037477a09..61a529229 100644
--- a/pkg/event/testing/testing.go
+++ b/pkg/event/testing/testing.go
@@ -146,11 +146,11 @@ const (
 	EvInit                       = "Init"
 )
 
-func (t *TestHandlerBase) Stop() error {
+func (t *TestHandlerBase) Stop(_ context.Context) error {
 	return t.addEvent(EvStop, nil)
 }
 
-func (t *TestHandlerBase) Uninstall() error {
+func (t *TestHandlerBase) Uninstall(_ context.Context) error {
 	return t.addEvent(EvUninstall, nil)
 }
 
diff --git a/pkg/globalnet/controllers/cluster_egressip_controller_test.go b/pkg/globalnet/controllers/cluster_egressip_controller_test.go
index b8900c8f5..9513c56b5 100644
--- a/pkg/globalnet/controllers/cluster_egressip_controller_test.go
+++ b/pkg/globalnet/controllers/cluster_egressip_controller_test.go
@@ -42,9 +42,9 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 	t := newClusterGlobalEgressIPControllerTestDriver()
 
 	When("the well-known ClusterGlobalEgressIP does not exist on startup", func() {
-		It("should create it and allocate the default number of global IPs", func() {
-			t.awaitClusterGlobalEgressIPStatusAllocated(controllers.DefaultNumberOfClusterEgressIPs)
-			t.awaitPacketFilterRules(getGlobalEgressIPStatus(t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs...)
+		It("should create it and allocate the default number of global IPs", func(ctx context.Context) {
+			t.awaitClusterGlobalEgressIPStatusAllocated(ctx, controllers.DefaultNumberOfClusterEgressIPs)
+			t.awaitPacketFilterRules(getGlobalEgressIPStatus(ctx, t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs...)
 		})
 	})
 
@@ -62,15 +62,15 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 					t.createClusterGlobalEgressIP(existing)
 				})
 
-				It("should not reallocate the global IPs", func() {
+				It("should not reallocate the global IPs", func(ctx context.Context) {
 					Consistently(func() []string {
-						return getGlobalEgressIPStatus(t.clusterGlobalEgressIPs, existing.Name).AllocatedIPs
+						return getGlobalEgressIPStatus(ctx, t.clusterGlobalEgressIPs, existing.Name).AllocatedIPs
 					}, 200*time.Millisecond).Should(Equal(existing.Status.AllocatedIPs))
 				})
 
-				It("should not update the Status conditions", func() {
+				It("should not update the Status conditions", func(ctx context.Context) {
 					Consistently(func() int {
-						return len(getGlobalEgressIPStatus(t.clusterGlobalEgressIPs, existing.Name).Conditions)
+						return len(getGlobalEgressIPStatus(ctx, t.clusterGlobalEgressIPs, existing.Name).Conditions)
 					}, 200*time.Millisecond).Should(Equal(0))
 				})
 
@@ -90,9 +90,9 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 					t.createClusterGlobalEgressIP(existing)
 				})
 
-				It("should reallocate the global IPs", func() {
-					t.awaitClusterGlobalEgressIPStatusAllocated(*existing.Spec.NumberOfIPs)
-					t.awaitPacketFilterRules(getGlobalEgressIPStatus(t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs...)
+				It("should reallocate the global IPs", func(ctx context.Context) {
+					t.awaitClusterGlobalEgressIPStatusAllocated(ctx, *existing.Spec.NumberOfIPs)
+					t.awaitPacketFilterRules(getGlobalEgressIPStatus(ctx, t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs...)
 				})
 
 				It("should release the previously allocated IPs", func() {
@@ -116,17 +116,18 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 					Expect(t.pool.Reserve(existing.Status.AllocatedIPs...)).To(Succeed())
 				})
 
-				It("should reallocate the global IPs", func() {
-					t.awaitEgressIPStatus(t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName, *existing.Spec.NumberOfIPs, metav1.Condition{
-						Type:   string(submarinerv1.GlobalEgressIPAllocated),
-						Status: metav1.ConditionFalse,
-						Reason: "ReserveAllocatedIPsFailed",
-					}, metav1.Condition{
-						Type:   string(submarinerv1.GlobalEgressIPAllocated),
-						Status: metav1.ConditionTrue,
-					})
-
-					t.awaitPacketFilterRules(getGlobalEgressIPStatus(t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs...)
+				It("should reallocate the global IPs", func(ctx context.Context) {
+					t.awaitEgressIPStatus(ctx, t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName, *existing.Spec.NumberOfIPs,
+						metav1.Condition{
+							Type:   string(submarinerv1.GlobalEgressIPAllocated),
+							Status: metav1.ConditionFalse,
+							Reason: "ReserveAllocatedIPsFailed",
+						}, metav1.Condition{
+							Type:   string(submarinerv1.GlobalEgressIPAllocated),
+							Status: metav1.ConditionTrue,
+						})
+
+					t.awaitPacketFilterRules(getGlobalEgressIPStatus(ctx, t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs...)
 				})
 			})
 
@@ -137,9 +138,9 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 					t.pFilter.AddFailOnAppendRuleMatcher(ContainSubstring(existing.Status.AllocatedIPs[0]))
 				})
 
-				It("should return an error on instantiation and not reallocate the global IPs", func() {
+				It("should return an error on instantiation and not reallocate the global IPs", func(ctx context.Context) {
 					Consistently(func() []string {
-						return getGlobalEgressIPStatus(t.clusterGlobalEgressIPs, existing.Name).AllocatedIPs
+						return getGlobalEgressIPStatus(ctx, t.clusterGlobalEgressIPs, existing.Name).AllocatedIPs
 					}, 200*time.Millisecond).Should(Equal(existing.Status.AllocatedIPs))
 				})
 			})
@@ -150,8 +151,8 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 				t.createClusterGlobalEgressIP(newClusterGlobalEgressIP(constants.ClusterGlobalEgressIPName, -1))
 			})
 
-			It("should add an appropriate Status condition", func() {
-				t.awaitEgressIPStatus(t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName, 0, metav1.Condition{
+			It("should add an appropriate Status condition", func(ctx context.Context) {
+				t.awaitEgressIPStatus(ctx, t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName, 0, metav1.Condition{
 					Type:   string(submarinerv1.GlobalEgressIPAllocated),
 					Status: metav1.ConditionFalse,
 					Reason: "InvalidInput",
@@ -164,8 +165,8 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 				t.createClusterGlobalEgressIP(newClusterGlobalEgressIP(constants.ClusterGlobalEgressIPName, 0))
 			})
 
-			It("should add an appropriate Status condition", func() {
-				t.awaitEgressIPStatus(t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName, 0, metav1.Condition{
+			It("should add an appropriate Status condition", func(ctx context.Context) {
+				t.awaitEgressIPStatus(ctx, t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName, 0, metav1.Condition{
 					Type:   string(submarinerv1.GlobalEgressIPAllocated),
 					Status: metav1.ConditionFalse,
 					Reason: "ZeroInput",
@@ -194,8 +195,8 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 				t.createClusterGlobalEgressIP(existing)
 			})
 
-			It("should trim the Status conditions", func() {
-				t.awaitClusterGlobalEgressIPStatusAllocated(1)
+			It("should trim the Status conditions", func(ctx context.Context) {
+				t.awaitClusterGlobalEgressIPStatusAllocated(ctx, 1)
 			})
 		})
 	})
@@ -220,9 +221,9 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 				numberOfIPs = *existing.Spec.NumberOfIPs + 1
 			})
 
-			It("should reallocate the global IPs", func() {
-				t.awaitClusterGlobalEgressIPStatusAllocated(numberOfIPs)
-				t.awaitPacketFilterRules(getGlobalEgressIPStatus(t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs...)
+			It("should reallocate the global IPs", func(ctx context.Context) {
+				t.awaitClusterGlobalEgressIPStatusAllocated(ctx, numberOfIPs)
+				t.awaitPacketFilterRules(getGlobalEgressIPStatus(ctx, t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs...)
 			})
 
 			It("should release the previously allocated IPs", func() {
@@ -236,9 +237,9 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 				numberOfIPs = *existing.Spec.NumberOfIPs - 1
 			})
 
-			It("should reallocate the global IPs", func() {
-				t.awaitClusterGlobalEgressIPStatusAllocated(numberOfIPs)
-				t.awaitPacketFilterRules(getGlobalEgressIPStatus(t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs...)
+			It("should reallocate the global IPs", func(ctx context.Context) {
+				t.awaitClusterGlobalEgressIPStatusAllocated(ctx, numberOfIPs)
+				t.awaitPacketFilterRules(getGlobalEgressIPStatus(ctx, t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs...)
 			})
 
 			It("should release the previously allocated IPs", func() {
@@ -252,8 +253,8 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 				numberOfIPs = 0
 			})
 
-			It("should update the Status appropriately", func() {
-				t.awaitEgressIPStatus(t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName, 0, metav1.Condition{
+			It("should update the Status appropriately", func(ctx context.Context) {
+				t.awaitEgressIPStatus(ctx, t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName, 0, metav1.Condition{
 					Type:   string(submarinerv1.GlobalEgressIPAllocated),
 					Status: metav1.ConditionFalse,
 					Reason: "ZeroInput",
@@ -272,10 +273,10 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 				t.pFilter.AddFailOnDeleteRuleMatcher(ContainSubstring(existing.Status.AllocatedIPs[0]))
 			})
 
-			It("should eventually cleanup the IP tables and reallocate", func() {
+			It("should eventually cleanup the IP tables and reallocate", func(ctx context.Context) {
 				t.awaitNoPacketFilterRules(existing.Status.AllocatedIPs...)
-				t.awaitClusterGlobalEgressIPStatusAllocated(numberOfIPs)
-				t.awaitPacketFilterRules(getGlobalEgressIPStatus(t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs...)
+				t.awaitClusterGlobalEgressIPStatusAllocated(ctx, numberOfIPs)
+				t.awaitPacketFilterRules(getGlobalEgressIPStatus(ctx, t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs...)
 			})
 		})
 
@@ -285,9 +286,9 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 				t.pFilter.AddFailOnAppendRuleMatcher(Not(ContainSubstring(existing.Status.AllocatedIPs[0])))
 			})
 
-			It("should eventually reallocate the global IPs", func() {
+			It("should eventually reallocate the global IPs", func(ctx context.Context) {
 				t.awaitNoPacketFilterRules(existing.Status.AllocatedIPs...)
-				t.awaitEgressIPStatus(t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName, numberOfIPs, metav1.Condition{
+				t.awaitEgressIPStatus(ctx, t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName, numberOfIPs, metav1.Condition{
 					Type:   string(submarinerv1.GlobalEgressIPAllocated),
 					Status: metav1.ConditionFalse,
 					Reason: "ProgramIPTableRulesFailed",
@@ -295,7 +296,7 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 					Type:   string(submarinerv1.GlobalEgressIPAllocated),
 					Status: metav1.ConditionTrue,
 				})
-				t.awaitPacketFilterRules(getGlobalEgressIPStatus(t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs...)
+				t.awaitPacketFilterRules(getGlobalEgressIPStatus(ctx, t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs...)
 			})
 		})
 
@@ -321,10 +322,10 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 			t.createClusterGlobalEgressIP(newClusterGlobalEgressIP(constants.ClusterGlobalEgressIPName, 1))
 		})
 
-		JustBeforeEach(func() {
-			t.awaitClusterGlobalEgressIPStatusAllocated(1)
-			allocatedIPs = getGlobalEgressIPStatus(t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs
-			Expect(t.clusterGlobalEgressIPs.Delete(context.TODO(), constants.ClusterGlobalEgressIPName, metav1.DeleteOptions{})).
+		JustBeforeEach(func(ctx context.Context) {
+			t.awaitClusterGlobalEgressIPStatusAllocated(ctx, 1)
+			allocatedIPs = getGlobalEgressIPStatus(ctx, t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName).AllocatedIPs
+			Expect(t.clusterGlobalEgressIPs.Delete(ctx, constants.ClusterGlobalEgressIPName, metav1.DeleteOptions{})).
 				To(Succeed())
 		})
 
@@ -338,8 +339,8 @@ var _ = Describe("ClusterGlobalEgressIP controller", func() {
 			t.createClusterGlobalEgressIP(newClusterGlobalEgressIP("other name", 1))
 		})
 
-		It("should not allocate the global IP", func() {
-			t.awaitEgressIPStatus(t.clusterGlobalEgressIPs, "other name", 0, metav1.Condition{
+		It("should not allocate the global IP", func(ctx context.Context) {
+			t.awaitEgressIPStatus(ctx, t.clusterGlobalEgressIPs, "other name", 0, metav1.Condition{
 				Type:   string(submarinerv1.GlobalEgressIPAllocated),
 				Status: metav1.ConditionFalse,
 				Reason: "InvalidInstance",
@@ -365,23 +366,23 @@ func newClusterGlobalEgressIPControllerTestDriver() *clusterGlobalEgressIPContro
 		Expect(err).To(Succeed())
 	})
 
-	JustBeforeEach(func() {
-		t.start()
+	JustBeforeEach(func(ctx context.Context) {
+		t.start(ctx)
 	})
 
-	AfterEach(func() {
-		t.testDriverBase.afterEach()
+	AfterEach(func(ctx context.Context) {
+		t.testDriverBase.afterEach(ctx)
 	})
 
 	return t
 }
 
-func (t *clusterGlobalEgressIPControllerTestDriver) start() {
+func (t *clusterGlobalEgressIPControllerTestDriver) start(ctx context.Context) {
 	var err error
 
 	t.localSubnets = []string{"10.0.0.0/16", "100.0.0.0/16"}
 
-	t.controller, err = controllers.NewClusterGlobalEgressIPController(&syncer.ResourceSyncerConfig{
+	t.controller, err = controllers.NewClusterGlobalEgressIPController(ctx, &syncer.ResourceSyncerConfig{
 		SourceClient: t.dynClient,
 		RestMapper:   t.restMapper,
 		Scheme:       t.scheme,
@@ -393,7 +394,7 @@ func (t *clusterGlobalEgressIPControllerTestDriver) start() {
 	}
 
 	Expect(err).To(Succeed())
-	Expect(t.controller.Start()).To(Succeed())
+	Expect(t.controller.Start(ctx)).To(Succeed())
 
 	testutil.AwaitWatchAction(&t.dynClient.Fake, "clusterglobalegressips")
 }
diff --git a/pkg/globalnet/controllers/controllers_suite_test.go b/pkg/globalnet/controllers/controllers_suite_test.go
index 85aa7d48a..7d7881d89 100644
--- a/pkg/globalnet/controllers/controllers_suite_test.go
+++ b/pkg/globalnet/controllers/controllers_suite_test.go
@@ -168,9 +168,9 @@ func newTestDriverBase() *testDriverBase {
 	return t
 }
 
-func (t *testDriverBase) afterEach() {
+func (t *testDriverBase) afterEach(ctx context.Context) {
 	if t.controller != nil {
-		t.controller.Stop()
+		t.controller.Stop(ctx)
 	}
 }
 
@@ -221,20 +221,20 @@ func (t *testDriverBase) createGlobalIngressIP(ingressIP *submarinerv1.GlobalIng
 }
 
 //nolint:unparam // `name` always receives `globalEgressIPName`
-func (t *testDriverBase) awaitGlobalEgressIPStatusAllocated(name string, expNumIPS int) {
-	t.awaitEgressIPStatusAllocated(t.globalEgressIPs, name, expNumIPS)
+func (t *testDriverBase) awaitGlobalEgressIPStatusAllocated(ctx context.Context, name string, expNumIPS int) {
+	t.awaitEgressIPStatusAllocated(ctx, t.globalEgressIPs, name, expNumIPS)
 }
 
-func (t *testDriverBase) awaitClusterGlobalEgressIPStatusAllocated(expNumIPS int) {
-	t.awaitEgressIPStatusAllocated(t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName, expNumIPS)
+func (t *testDriverBase) awaitClusterGlobalEgressIPStatusAllocated(ctx context.Context, expNumIPS int) {
+	t.awaitEgressIPStatusAllocated(ctx, t.clusterGlobalEgressIPs, constants.ClusterGlobalEgressIPName, expNumIPS)
 }
 
 func (t *testDriverBase) createPod(p *corev1.Pod) *corev1.Pod {
 	return test.CreateResource(t.pods.Namespace(p.Namespace), p)
 }
 
-func (t *testDriverBase) deletePod(p *corev1.Pod) {
-	Expect(t.pods.Namespace(p.Namespace).Delete(context.TODO(), p.Name, metav1.DeleteOptions{})).To(Succeed())
+func (t *testDriverBase) deletePod(ctx context.Context, p *corev1.Pod) {
+	Expect(t.pods.Namespace(p.Namespace).Delete(ctx, p.Name, metav1.DeleteOptions{})).To(Succeed())
 }
 
 func (t *testDriverBase) createEndpoints(ep *corev1.Endpoints) *corev1.Endpoints {
@@ -242,8 +242,8 @@ func (t *testDriverBase) createEndpoints(ep *corev1.Endpoints) *corev1.Endpoints
 	return ep
 }
 
-func (t *testDriverBase) deleteEndpoints(ep *corev1.Endpoints) {
-	err := t.endpoints.Delete(context.TODO(), ep.Name, metav1.DeleteOptions{})
+func (t *testDriverBase) deleteEndpoints(ctx context.Context, ep *corev1.Endpoints) {
+	err := t.endpoints.Delete(ctx, ep.Name, metav1.DeleteOptions{})
 	Expect(err).To(Succeed())
 }
 
@@ -272,9 +272,9 @@ func (t *testDriverBase) createPFilterChain(table packetfilter.TableType, chain
 	})
 }
 
-func (t *testDriverBase) getGlobalIngressIPStatus(name string) *submarinerv1.GlobalIngressIPStatus {
+func (t *testDriverBase) getGlobalIngressIPStatus(ctx context.Context, name string) *submarinerv1.GlobalIngressIPStatus {
 	status := &submarinerv1.GlobalIngressIPStatus{}
-	getStatus(t.globalIngressIPs, name, status)
+	getStatus(ctx, t.globalIngressIPs, name, status)
 
 	return status
 }
@@ -291,20 +291,20 @@ func (t *testDriverBase) createGateway(name, globalIP string) *submarinerv1.Gate
 	return test.CreateResource(t.gateways, gateway)
 }
 
-func (t *testDriverBase) getGatewayGlobalIP(name string) string {
-	obj, err := t.gateways.Get(context.TODO(), name, metav1.GetOptions{})
+func (t *testDriverBase) getGatewayGlobalIP(ctx context.Context, name string) string {
+	obj, err := t.gateways.Get(ctx, name, metav1.GetOptions{})
 	Expect(err).To(Succeed())
 
 	return obj.GetAnnotations()[constants.SmGlobalIP]
 }
 
-func (t *testDriverBase) awaitGatewayGlobalIP(oldIP string) string {
+func (t *testDriverBase) awaitGatewayGlobalIP(ctx context.Context, oldIP string) string {
 	var globalIP string
 
-	Eventually(func() string {
-		globalIP = t.getGatewayGlobalIP(t.hostName)
-		return globalIP
-	}, 5).ShouldNot(Or(BeEmpty(), Equal(oldIP)))
+	Eventually(func(g Gomega, ctx context.Context) {
+		globalIP = t.getGatewayGlobalIP(ctx, t.hostName)
+		g.Expect(globalIP).NotTo(Or(BeEmpty(), Equal(oldIP)))
+	}).Within(5 * time.Second).WithContext(ctx).Should(Succeed())
 
 	Expect(isValidIPForCIDR(t.globalCIDR, globalIP)).To(BeTrue(), "Allocated global IP %q is not valid for CIDR %q",
 		globalIP, t.globalCIDR)
@@ -314,10 +314,10 @@ func (t *testDriverBase) awaitGatewayGlobalIP(oldIP string) string {
 	return globalIP
 }
 
-func (t *testDriverBase) ensureGatewayGlobalIP(name, ip string) {
-	Consistently(func() string {
-		return t.getGatewayGlobalIP(name)
-	}, 500*time.Millisecond).Should(Equal(ip))
+func (t *testDriverBase) ensureGatewayGlobalIP(ctx context.Context, name, ip string) {
+	Consistently(func(ctx context.Context) string {
+		return t.getGatewayGlobalIP(ctx, name)
+	}).Within(500 * time.Millisecond).WithContext(ctx).Should(Equal(ip))
 }
 
 func addAnnotation(obj metav1.Object, key, value string) {
@@ -333,8 +333,8 @@ func addAnnotation(obj metav1.Object, key, value string) {
 	obj.GetAnnotations()[key] = value
 }
 
-func getStatus(client dynamic.ResourceInterface, name string, status any) {
-	obj, err := client.Get(context.TODO(), name, metav1.GetOptions{})
+func getStatus(ctx context.Context, client dynamic.ResourceInterface, name string, status any) {
+	obj, err := client.Get(ctx, name, metav1.GetOptions{})
 	Expect(err).To(Succeed())
 
 	statusObj, ok, err := unstructured.NestedMap(obj.Object, "status")
@@ -347,42 +347,44 @@ func getStatus(client dynamic.ResourceInterface, name string, status any) {
 	Expect(runtime.DefaultUnstructuredConverter.FromUnstructured(statusObj, status)).To(Succeed())
 }
 
-func getGlobalEgressIPStatus(client dynamic.ResourceInterface, name string) *submarinerv1.GlobalEgressIPStatus {
+func getGlobalEgressIPStatus(ctx context.Context, client dynamic.ResourceInterface, name string) *submarinerv1.GlobalEgressIPStatus {
 	status := &submarinerv1.GlobalEgressIPStatus{}
-	getStatus(client, name, status)
+	getStatus(ctx, client, name, status)
 
 	return status
 }
 
-func (t *testDriverBase) awaitEgressIPStatus(client dynamic.ResourceInterface, name string, expNumIPS int, expCond ...metav1.Condition) {
+func (t *testDriverBase) awaitEgressIPStatus(ctx context.Context, client dynamic.ResourceInterface, name string, expNumIPS int,
+	expCond ...metav1.Condition,
+) {
 	t.awaitStatusConditions(client, name, expCond...)
 
 	var status *submarinerv1.GlobalEgressIPStatus
 
-	Eventually(func(g Gomega) {
-		status = getGlobalEgressIPStatus(client, name)
+	Eventually(func(g Gomega, ctx context.Context) {
+		status = getGlobalEgressIPStatus(ctx, client, name)
 		g.Expect(status.AllocatedIPs).To(HaveLen(expNumIPS))
 
 		for _, ip := range status.AllocatedIPs {
 			g.Expect(isValidIPForCIDR(t.globalCIDR, ip)).To(BeTrue(), "Allocated global IP %q is not valid for CIDR %q",
 				ip, t.globalCIDR)
 		}
-	}).Should(Succeed())
+	}).WithContext(ctx).Should(Succeed())
 
 	t.verifyIPsReservedInPool(status.AllocatedIPs...)
 }
 
-func (t *testDriverBase) awaitEgressIPStatusAllocated(client dynamic.ResourceInterface, name string, expNumIPS int) {
-	t.awaitEgressIPStatus(client, name, expNumIPS, metav1.Condition{
+func (t *testDriverBase) awaitEgressIPStatusAllocated(ctx context.Context, client dynamic.ResourceInterface, name string, expNumIPS int) {
+	t.awaitEgressIPStatus(ctx, client, name, expNumIPS, metav1.Condition{
 		Type:   string(submarinerv1.GlobalEgressIPAllocated),
 		Status: metav1.ConditionTrue,
 	})
 }
 
-func (t *testDriverBase) awaitIngressIPStatus(name string, expCond ...metav1.Condition) {
+func (t *testDriverBase) awaitIngressIPStatus(ctx context.Context, name string, expCond ...metav1.Condition) {
 	t.awaitStatusConditions(t.globalIngressIPs, name, expCond...)
 
-	status := t.getGlobalIngressIPStatus(name)
+	status := t.getGlobalIngressIPStatus(ctx, name)
 
 	Expect(status.AllocatedIP).ToNot(BeEmpty())
 	Expect(isValidIPForCIDR(t.globalCIDR, status.AllocatedIP)).To(BeTrue(), "Allocated global IP %q is not valid for CIDR %q",
@@ -391,8 +393,8 @@ func (t *testDriverBase) awaitIngressIPStatus(name string, expCond ...metav1.Con
 	t.verifyIPsReservedInPool(status.AllocatedIP)
 }
 
-func (t *testDriverBase) awaitIngressIPStatusAllocated(name string) {
-	t.awaitIngressIPStatus(name, metav1.Condition{
+func (t *testDriverBase) awaitIngressIPStatusAllocated(ctx context.Context, name string) {
+	t.awaitIngressIPStatus(ctx, name, metav1.Condition{
 		Type:   string(submarinerv1.GlobalEgressIPAllocated),
 		Status: metav1.ConditionTrue,
 	})
@@ -422,9 +424,9 @@ func (t *testDriverBase) ensureNoEndpoints(name string) {
 	testutil.EnsureNoResource(resource.ForDynamic(t.endpoints), name)
 }
 
-func (t *testDriverBase) awaitEndpointsHasIP(name, ip string) {
-	Eventually(func() bool {
-		obj, err := t.endpoints.Get(context.TODO(), name, metav1.GetOptions{})
+func (t *testDriverBase) awaitEndpointsHasIP(ctx context.Context, name, ip string) {
+	Eventually(func(ctx context.Context) bool {
+		obj, err := t.endpoints.Get(ctx, name, metav1.GetOptions{})
 		Expect(err).To(Succeed())
 
 		ep := &corev1.Endpoints{}
@@ -439,11 +441,11 @@ func (t *testDriverBase) awaitEndpointsHasIP(name, ip string) {
 		}
 
 		return false
-	}, 5).Should(BeTrue())
+	}).Within(5 * time.Second).WithContext(ctx).Should(BeTrue())
 }
 
-func (t *testDriverBase) awaitHeadlessGlobalIngressIP(svcName, podName string) *submarinerv1.GlobalIngressIP {
-	ingressIP := getGlobalIngressIP(t, podName, func(gip *submarinerv1.GlobalIngressIP, name string) bool {
+func (t *testDriverBase) awaitHeadlessGlobalIngressIP(ctx context.Context, svcName, podName string) *submarinerv1.GlobalIngressIP {
+	ingressIP := getGlobalIngressIP(ctx, t, podName, func(gip *submarinerv1.GlobalIngressIP, name string) bool {
 		return gip.Spec.PodRef != nil && gip.Spec.PodRef.Name == name
 	})
 
@@ -454,9 +456,10 @@ func (t *testDriverBase) awaitHeadlessGlobalIngressIP(svcName, podName string) *
 	return ingressIP
 }
 
-func (t *testDriverBase) awaitHeadlessGlobalIngressIPForEP(svcName, endpointsName string) *submarinerv1.GlobalIngressIP {
+func (t *testDriverBase) awaitHeadlessGlobalIngressIPForEP(ctx context.Context, svcName, endpointsName string,
+) *submarinerv1.GlobalIngressIP {
 	// Intentionally comparing ServiceRef.Name and endpointsName (they should be the same)
-	ingressIP := getGlobalIngressIP(t, endpointsName, func(gip *submarinerv1.GlobalIngressIP, name string) bool {
+	ingressIP := getGlobalIngressIP(ctx, t, endpointsName, func(gip *submarinerv1.GlobalIngressIP, name string) bool {
 		return gip.Spec.ServiceRef != nil && gip.Spec.ServiceRef.Name == name
 	})
 
@@ -467,25 +470,26 @@ func (t *testDriverBase) awaitHeadlessGlobalIngressIPForEP(svcName, endpointsNam
 	return ingressIP
 }
 
-func getGlobalIngressIP(t *testDriverBase, name string,
-	compFunc func(*submarinerv1.GlobalIngressIP, string) bool,
+func getGlobalIngressIP(ctx context.Context, t *testDriverBase, name string, compFunc func(*submarinerv1.GlobalIngressIP, string) bool,
 ) *submarinerv1.GlobalIngressIP {
 	var ingressIP *submarinerv1.GlobalIngressIP
 
-	Eventually(func() bool {
-		list, _ := t.globalIngressIPs.List(context.TODO(), metav1.ListOptions{})
+	Eventually(func(g Gomega, ctx context.Context) {
+		list, err := t.globalIngressIPs.List(ctx, metav1.ListOptions{})
+		g.Expect(err).NotTo(HaveOccurred())
+
 		for i := range list.Items {
 			gip := &submarinerv1.GlobalIngressIP{}
 			Expect(runtime.DefaultUnstructuredConverter.FromUnstructured(list.Items[i].Object, gip)).To(Succeed())
 
 			if compFunc(gip, name) {
 				ingressIP = gip
-				return true
+				break
 			}
 		}
 
-		return false
-	}, 5).Should(BeTrue(), "GlobalIngressIP not found")
+		g.Expect(ingressIP).NotTo(BeNil(), "GlobalIngressIP not found")
+	}).WithContext(ctx).Within(time.Second * 5).Should(Succeed())
 
 	return ingressIP
 }
@@ -498,11 +502,13 @@ func (t *testDriverBase) ensureNoGlobalIngressIP(name string) {
 	testutil.EnsureNoResource(resource.ForDynamic(t.globalIngressIPs), name)
 }
 
-func (t *testDriverBase) ensureNoGlobalIngressIPs() {
-	Consistently(func() []unstructured.Unstructured {
-		list, _ := t.globalIngressIPs.List(context.TODO(), metav1.ListOptions{})
+func (t *testDriverBase) ensureNoGlobalIngressIPs(ctx context.Context) {
+	Consistently(func(ctx context.Context) []unstructured.Unstructured {
+		list, err := t.globalIngressIPs.List(ctx, metav1.ListOptions{})
+		Expect(err).NotTo(HaveOccurred())
+
 		return list.Items
-	}, time.Millisecond*300).Should(BeEmpty())
+	}).Within(time.Millisecond * 300).WithContext(ctx).Should(BeEmpty())
 }
 
 func (t *testDriverBase) awaitStatusConditions(client dynamic.ResourceInterface, name string, expCond ...metav1.Condition) {
diff --git a/pkg/globalnet/controllers/gateway_controller_test.go b/pkg/globalnet/controllers/gateway_controller_test.go
index 3377daa82..27728e770 100644
--- a/pkg/globalnet/controllers/gateway_controller_test.go
+++ b/pkg/globalnet/controllers/gateway_controller_test.go
@@ -47,8 +47,8 @@ var _ = Describe("Gateway controller", func() {
 				gateway = t.createGateway(t.hostName, "")
 			})
 
-			It("should allocate it and program the relevant iptable rules", func() {
-				t.awaitPacketFilterRules(t.awaitGatewayGlobalIP(""))
+			It("should allocate it and program the relevant iptable rules", func(ctx context.Context) {
+				t.awaitPacketFilterRules(t.awaitGatewayGlobalIP(ctx, ""))
 			})
 
 			Context("and the IP pool is initially exhausted", func() {
@@ -58,11 +58,11 @@ var _ = Describe("Gateway controller", func() {
 					allocatedIPs, _ = t.pool.Allocate(t.pool.Size())
 				})
 
-				It("should eventually allocate a global IP", func() {
+				It("should eventually allocate a global IP", func(ctx context.Context) {
 					time.Sleep(time.Millisecond * 300)
 					Expect(t.pool.Release(allocatedIPs...)).To(Succeed())
 
-					t.awaitGatewayGlobalIP("")
+					t.awaitGatewayGlobalIP(ctx, "")
 				})
 			})
 		})
@@ -91,8 +91,8 @@ var _ = Describe("Gateway controller", func() {
 					Expect(t.pool.Reserve(gateway.GetAnnotations()[constants.SmGlobalIP])).To(Succeed())
 				})
 
-				It("should reallocate the global IP", func() {
-					globalIP := t.awaitGatewayGlobalIP(gateway.GetAnnotations()[constants.SmGlobalIP])
+				It("should reallocate the global IP", func(ctx context.Context) {
+					globalIP := t.awaitGatewayGlobalIP(ctx, gateway.GetAnnotations()[constants.SmGlobalIP])
 					t.awaitPacketFilterRules(globalIP)
 				})
 			})
@@ -105,9 +105,9 @@ var _ = Describe("Gateway controller", func() {
 			t.expectReservedIPs = []string{gateway.GetAnnotations()[constants.SmGlobalIP]}
 		})
 
-		It("should reserve the global IP and preserve the annotation", func() {
+		It("should reserve the global IP and preserve the annotation", func(ctx context.Context) {
 			t.ensureNoPacketFilterRules(gateway.GetAnnotations()[constants.SmGlobalIP])
-			t.ensureGatewayGlobalIP(gateway.Name, gateway.GetAnnotations()[constants.SmGlobalIP])
+			t.ensureGatewayGlobalIP(ctx, gateway.Name, gateway.GetAnnotations()[constants.SmGlobalIP])
 		})
 
 		Context("and is subsequently deleted", func() {
@@ -124,9 +124,9 @@ var _ = Describe("Gateway controller", func() {
 				Expect(t.pool.Reserve(gateway.GetAnnotations()[constants.SmGlobalIP])).To(Succeed())
 			})
 
-			It("should preserve the annotation", func() {
+			It("should preserve the annotation", func(ctx context.Context) {
 				t.ensureNoPacketFilterRules(gateway.GetAnnotations()[constants.SmGlobalIP])
-				t.ensureGatewayGlobalIP(gateway.Name, gateway.GetAnnotations()[constants.SmGlobalIP])
+				t.ensureGatewayGlobalIP(ctx, gateway.Name, gateway.GetAnnotations()[constants.SmGlobalIP])
 			})
 		})
 	})
@@ -154,18 +154,18 @@ func newGatewayControllerTestDriver() *gatewayControllerTestDriver {
 		t.expectReservedIPs = nil
 	})
 
-	JustBeforeEach(func() {
-		t.start()
+	JustBeforeEach(func(ctx context.Context) {
+		t.start(ctx)
 	})
 
-	AfterEach(func() {
-		t.testDriverBase.afterEach()
+	AfterEach(func(ctx context.Context) {
+		t.testDriverBase.afterEach(ctx)
 	})
 
 	return t
 }
 
-func (t *gatewayControllerTestDriver) start() {
+func (t *gatewayControllerTestDriver) start(ctx context.Context) {
 	var err error
 
 	syncerConfig := controllers.NewGatewayResourceSyncerConfig(&syncer.ResourceSyncerConfig{
@@ -183,7 +183,7 @@ func (t *gatewayControllerTestDriver) start() {
 		close(stopCh)
 	})
 
-	t.controller, err = controllers.NewGatewayController(syncerConfig, informer, t.pool, t.hostName, namespace, cniInterfaceIP)
+	t.controller, err = controllers.NewGatewayController(ctx, syncerConfig, informer, t.pool, t.hostName, namespace, cniInterfaceIP)
 	Expect(err).To(Succeed())
 
 	t.verifyIPsReservedInPool(t.expectReservedIPs...)
@@ -192,7 +192,7 @@ func (t *gatewayControllerTestDriver) start() {
 		informer.Run(stopCh)
 	}()
 
-	Expect(t.controller.Start()).To(Succeed())
+	Expect(t.controller.Start(ctx)).To(Succeed())
 
 	testutil.AwaitWatchAction(&t.dynClient.Fake, "gatewaies")
 }
diff --git a/pkg/globalnet/controllers/gateway_monitor_test.go b/pkg/globalnet/controllers/gateway_monitor_test.go
index 5ec09521e..5ae6c367d 100644
--- a/pkg/globalnet/controllers/gateway_monitor_test.go
+++ b/pkg/globalnet/controllers/gateway_monitor_test.go
@@ -83,13 +83,13 @@ func testEndpointMonitoring() {
 				t.awaitGlobalnetChainsCleared()
 			})
 
-			It("should start the controllers", func() {
-				t.awaitControllersStarted()
+			It("should start the controllers", func(ctx context.Context) {
+				t.awaitControllersStarted(ctx)
 
-				t.awaitGlobalEgressIPStatusAllocated(globalEgressIPName, 1)
+				t.awaitGlobalEgressIPStatusAllocated(ctx, globalEgressIPName, 1)
 
 				t.createServiceExport(t.createService(newClusterIPService()))
-				t.awaitIngressIPStatusAllocated(serviceName)
+				t.awaitIngressIPStatusAllocated(ctx, serviceName)
 
 				service := newClusterIPService()
 				service.Name = "headless-nginx"
@@ -98,25 +98,25 @@ func testEndpointMonitoring() {
 				t.createPod(backendPod)
 				t.createServiceExport(t.createService(service))
 
-				Eventually(func(g Gomega) {
-					gip := t.awaitHeadlessGlobalIngressIP(service.Name, backendPod.Name)
+				Eventually(func(g Gomega, ctx context.Context) {
+					gip := t.awaitHeadlessGlobalIngressIP(ctx, service.Name, backendPod.Name)
 					g.Expect(gip.Status.AllocatedIP).NotTo(BeEmpty(), resource.ToJSON(gip))
-				}).To(Succeed())
+				}).WithContext(ctx).To(Succeed())
 
-				t.awaitGatewayGlobalIP("")
+				t.awaitGatewayGlobalIP(ctx, "")
 			})
 		})
 
 		Context("and then deleted and recreated", func() {
-			JustBeforeEach(func() {
-				t.awaitControllersStarted()
+			JustBeforeEach(func(ctx context.Context) {
+				t.awaitControllersStarted(ctx)
 
 				By("Deleting the Endpoint")
 
-				Expect(t.endpoints.Delete(context.TODO(), endpoint.Name, metav1.DeleteOptions{})).To(Succeed())
+				Expect(t.endpoints.Delete(ctx, endpoint.Name, metav1.DeleteOptions{})).To(Succeed())
 			})
 
-			It("should stop and restart the controllers", func() {
+			It("should stop and restart the controllers", func(ctx context.Context) {
 				t.leaderElection.AwaitLeaseReleased()
 				t.awaitGlobalnetChainsCleared()
 				t.ensureControllersStopped()
@@ -129,7 +129,7 @@ func testEndpointMonitoring() {
 				t.leaderElection.AwaitLeaseAcquired()
 				t.awaitGlobalnetChains()
 
-				t.awaitIngressIPStatusAllocated(serviceName)
+				t.awaitIngressIPStatusAllocated(ctx, serviceName)
 			})
 		})
 
@@ -140,8 +140,8 @@ func testEndpointMonitoring() {
 				t.leaderElectionConfig.RetryPeriod = time.Hour
 			})
 
-			JustBeforeEach(func() {
-				t.awaitControllersStarted()
+			JustBeforeEach(func(ctx context.Context) {
+				t.awaitControllersStarted(ctx)
 
 				// Since the RenewDeadline and RetryPeriod are set very high and the leader lock has been acquired, leader election should
 				// not try to renew the leader lock at this point, but we'll wait a bit more just in case to give it plenty of time. After
@@ -166,8 +166,8 @@ func testEndpointMonitoring() {
 				t.leaderElectionConfig.RetryPeriod = time.Millisecond * 20
 			})
 
-			JustBeforeEach(func() {
-				t.awaitControllersStarted()
+			JustBeforeEach(func(ctx context.Context) {
+				t.awaitControllersStarted(ctx)
 
 				By("Setting leases resource updates to fail")
 
@@ -179,7 +179,7 @@ func testEndpointMonitoring() {
 				t.awaitGlobalnetChains()
 			})
 
-			It("should re-acquire the leader lock after the failure is cleared", func() {
+			It("should re-acquire the leader lock after the failure is cleared", func(ctx context.Context) {
 				By("Setting leases resource updates to succeed")
 
 				t.leaderElection.SucceedLease()
@@ -188,7 +188,7 @@ func testEndpointMonitoring() {
 
 				t.leaderElection.AwaitLeaseRenewed()
 
-				t.awaitIngressIPStatusAllocated(serviceName)
+				t.awaitIngressIPStatusAllocated(ctx, serviceName)
 			})
 
 			Context("and then the gateway Endpoint is deleted", func() {
@@ -229,15 +229,15 @@ func testEndpointMonitoring() {
 		})
 
 		Context("and the local Gateway is deleted", func() {
-			It("should remove the ingress rules for its glonal IP", func() {
-				globalIP := t.awaitGatewayGlobalIP("")
+			It("should remove the ingress rules for its glonal IP", func(ctx context.Context) {
+				globalIP := t.awaitGatewayGlobalIP(ctx, "")
 
 				t.pFilter.AwaitRule(packetfilter.TableTypeNAT,
 					chains.SmGlobalnetIngress, And(ContainSubstring(globalIP), ContainSubstring(cniInterfaceIP)))
 
 				By("Deleting local Gateway")
 
-				err := t.gateways.Delete(context.TODO(), t.hostName, metav1.DeleteOptions{})
+				err := t.gateways.Delete(ctx, t.hostName, metav1.DeleteOptions{})
 				Expect(err).To(Succeed())
 
 				t.pFilter.AwaitNoRule(packetfilter.TableTypeNAT,
@@ -251,8 +251,8 @@ func testEndpointMonitoring() {
 					fake.FailOnAction(&t.dynClient.Fake, "clusterglobalegressips", "get", nil, true)
 				})
 
-				It("should eventually start the controllers", func() {
-					t.awaitControllersStarted()
+				It("should eventually start the controllers", func(ctx context.Context) {
+					t.awaitControllersStarted(ctx)
 				})
 			})
 
@@ -285,10 +285,10 @@ func testEndpointMonitoring() {
 						})
 				})
 
-				It("should eventually start the controllers", func() {
+				It("should eventually start the controllers", func(ctx context.Context) {
 					Eventually(leaseFailed).Within(5 * time.Second).Should(BeClosed())
 					t.leaderElection.SucceedLease()
-					t.awaitControllersStarted()
+					t.awaitControllersStarted(ctx)
 				})
 			})
 		})
@@ -385,11 +385,11 @@ func testUninstall() {
 		t.pFilter.AwaitSet("other")
 	})
 
-	Specify("DeleteGlobalnetObjects should delete all Globalnet resources and internal Services", func() {
+	Specify("DeleteGlobalnetObjects should delete all Globalnet resources and internal Services", func(ctx context.Context) {
 		submClient := fakesubmariner.NewSimpleClientset()
 		fake.AddBasicReactors(&submClient.Fake)
 
-		clusterEgressIP, err := submClient.SubmarinerV1().ClusterGlobalEgressIPs("").Create(context.Background(),
+		clusterEgressIP, err := submClient.SubmarinerV1().ClusterGlobalEgressIPs("").Create(ctx,
 			&submarinerv1.ClusterGlobalEgressIP{
 				ObjectMeta: metav1.ObjectMeta{
 					Name: "cluster-egressIP",
@@ -397,7 +397,7 @@ func testUninstall() {
 			}, metav1.CreateOptions{})
 		Expect(err).To(Succeed())
 
-		egressIP, err := submClient.SubmarinerV1().GlobalEgressIPs(namespace).Create(context.Background(),
+		egressIP, err := submClient.SubmarinerV1().GlobalEgressIPs(namespace).Create(ctx,
 			&submarinerv1.GlobalEgressIP{
 				ObjectMeta: metav1.ObjectMeta{
 					Name: "egressIP",
@@ -418,10 +418,10 @@ func testUninstall() {
 			},
 		}
 
-		_, err = t.services.Create(context.Background(), resource.MustToUnstructured(internalService), metav1.CreateOptions{})
+		_, err = t.services.Create(ctx, resource.MustToUnstructured(internalService), metav1.CreateOptions{})
 		Expect(err).To(Succeed())
 
-		ingressIP, err := submClient.SubmarinerV1().GlobalIngressIPs(namespace).Create(context.Background(),
+		ingressIP, err := submClient.SubmarinerV1().GlobalIngressIPs(namespace).Create(ctx,
 			&submarinerv1.GlobalIngressIP{
 				ObjectMeta: metav1.ObjectMeta{
 					Name: "ingressIP",
@@ -432,7 +432,7 @@ func testUninstall() {
 			}, metav1.CreateOptions{})
 		Expect(err).To(Succeed())
 
-		_, err = submClient.SubmarinerV1().GlobalIngressIPs(namespace).Create(context.Background(),
+		_, err = submClient.SubmarinerV1().GlobalIngressIPs(namespace).Create(ctx,
 			&submarinerv1.GlobalIngressIP{
 				ObjectMeta: metav1.ObjectMeta{
 					Name: "ingressIP-no-service-ref",
@@ -440,17 +440,17 @@ func testUninstall() {
 			}, metav1.CreateOptions{})
 		Expect(err).To(Succeed())
 
-		controllers.DeleteGlobalnetObjects(submClient, t.dynClient)
+		controllers.DeleteGlobalnetObjects(ctx, submClient, t.dynClient)
 
-		_, err = submClient.SubmarinerV1().ClusterGlobalEgressIPs("").Get(context.Background(), clusterEgressIP.Name,
+		_, err = submClient.SubmarinerV1().ClusterGlobalEgressIPs("").Get(ctx, clusterEgressIP.Name,
 			metav1.GetOptions{})
 		Expect(apierrors.IsNotFound(err)).To(BeTrue())
 
-		_, err = submClient.SubmarinerV1().GlobalEgressIPs(namespace).Get(context.Background(), egressIP.Name,
+		_, err = submClient.SubmarinerV1().GlobalEgressIPs(namespace).Get(ctx, egressIP.Name,
 			metav1.GetOptions{})
 		Expect(apierrors.IsNotFound(err)).To(BeTrue())
 
-		_, err = submClient.SubmarinerV1().GlobalIngressIPs(namespace).Get(context.Background(), ingressIP.Name,
+		_, err = submClient.SubmarinerV1().GlobalIngressIPs(namespace).Get(ctx, ingressIP.Name,
 			metav1.GetOptions{})
 		Expect(apierrors.IsNotFound(err)).To(BeTrue())
 
@@ -487,24 +487,24 @@ func newGatewayMonitorTestDriver() *gatewayMonitorTestDriver {
 		}
 	})
 
-	JustBeforeEach(func() {
-		t.start()
+	JustBeforeEach(func(ctx context.Context) {
+		t.start(ctx)
 	})
 
-	JustAfterEach(func() {
-		t.testDriverBase.afterEach()
+	JustAfterEach(func(ctx context.Context) {
+		t.testDriverBase.afterEach(ctx)
 	})
 
 	return t
 }
 
-func (t *gatewayMonitorTestDriver) start() {
+func (t *gatewayMonitorTestDriver) start(ctx context.Context) {
 	os.Setenv("NODE_NAME", t.hostName)
 	var err error
 
 	localSubnets := []string{localCIDR}
 
-	t.controller, err = controllers.NewGatewayMonitor(context.TODO(), &controllers.GatewayMonitorConfig{
+	t.controller, err = controllers.NewGatewayMonitor(ctx, &controllers.GatewayMonitorConfig{
 		RestMapper: t.restMapper,
 		Client:     t.dynClient,
 		Scheme:     t.scheme,
@@ -521,7 +521,7 @@ func (t *gatewayMonitorTestDriver) start() {
 	})
 
 	Expect(err).To(Succeed())
-	Expect(t.controller.Start()).To(Succeed())
+	Expect(t.controller.Start(ctx)).To(Succeed())
 
 	t.pFilter.AwaitChain(packetfilter.TableTypeNAT, chains.SmGlobalnetMark)
 }
@@ -540,10 +540,10 @@ func (t *gatewayMonitorTestDriver) createEndpoint(spec *submarinerv1.EndpointSpe
 	return test.CreateResource(t.endpoints, endpoint)
 }
 
-func (t *gatewayMonitorTestDriver) awaitControllersStarted() {
+func (t *gatewayMonitorTestDriver) awaitControllersStarted(ctx context.Context) {
 	t.leaderElection.AwaitLeaseAcquired()
 	t.awaitGlobalnetChains()
-	t.awaitClusterGlobalEgressIPStatusAllocated(controllers.DefaultNumberOfClusterEgressIPs)
+	t.awaitClusterGlobalEgressIPStatusAllocated(ctx, controllers.DefaultNumberOfClusterEgressIPs)
 }
 
 func (t *gatewayMonitorTestDriver) ensureControllersStopped() {
diff --git a/pkg/globalnet/controllers/global_egressip_controller_test.go b/pkg/globalnet/controllers/global_egressip_controller_test.go
index 27f335dee..9b584ab6d 100644
--- a/pkg/globalnet/controllers/global_egressip_controller_test.go
+++ b/pkg/globalnet/controllers/global_egressip_controller_test.go
@@ -91,9 +91,9 @@ func testGlobalEgressIPCreated(t *globalEgressIPControllerTestDriver, podSelecto
 	})
 
 	Context("with the NumberOfIPs unspecified", func() {
-		It("should allocate one global IP and program the necessary IP table rules", func() {
-			t.awaitGlobalEgressIPStatusAllocated(globalEgressIPName, 1)
-			t.awaitPacketFilterRules(egressChain, getGlobalEgressIPStatus(t.globalEgressIPs, globalEgressIPName).AllocatedIPs...)
+		It("should allocate one global IP and program the necessary IP table rules", func(ctx context.Context) {
+			t.awaitGlobalEgressIPStatusAllocated(ctx, globalEgressIPName, 1)
+			t.awaitPacketFilterRules(egressChain, getGlobalEgressIPStatus(ctx, t.globalEgressIPs, globalEgressIPName).AllocatedIPs...)
 		})
 
 		It("should start a Pod watcher", func() {
@@ -107,9 +107,9 @@ func testGlobalEgressIPCreated(t *globalEgressIPControllerTestDriver, podSelecto
 			numberOfIPs = &n
 		})
 
-		It("should allocate the specified number of global IPs and program the necessary IP table rules", func() {
-			t.awaitGlobalEgressIPStatusAllocated(globalEgressIPName, *numberOfIPs)
-			t.awaitPacketFilterRules(egressChain, getGlobalEgressIPStatus(t.globalEgressIPs, globalEgressIPName).AllocatedIPs...)
+		It("should allocate the specified number of global IPs and program the necessary IP table rules", func(ctx context.Context) {
+			t.awaitGlobalEgressIPStatusAllocated(ctx, globalEgressIPName, *numberOfIPs)
+			t.awaitPacketFilterRules(egressChain, getGlobalEgressIPStatus(ctx, t.globalEgressIPs, globalEgressIPName).AllocatedIPs...)
 		})
 	})
 
@@ -119,8 +119,8 @@ func testGlobalEgressIPCreated(t *globalEgressIPControllerTestDriver, podSelecto
 			numberOfIPs = &n
 		})
 
-		It("should add an appropriate Status condition", func() {
-			t.awaitEgressIPStatus(t.globalEgressIPs, globalEgressIPName, 0, metav1.Condition{
+		It("should add an appropriate Status condition", func(ctx context.Context) {
+			t.awaitEgressIPStatus(ctx, t.globalEgressIPs, globalEgressIPName, 0, metav1.Condition{
 				Type:   string(submarinerv1.GlobalEgressIPAllocated),
 				Status: metav1.ConditionFalse,
 				Reason: "InvalidInput",
@@ -134,8 +134,8 @@ func testGlobalEgressIPCreated(t *globalEgressIPControllerTestDriver, podSelecto
 			numberOfIPs = &n
 		})
 
-		It("should add an appropriate Status condition", func() {
-			t.awaitEgressIPStatus(t.globalEgressIPs, globalEgressIPName, 0, metav1.Condition{
+		It("should add an appropriate Status condition", func(ctx context.Context) {
+			t.awaitEgressIPStatus(ctx, t.globalEgressIPs, globalEgressIPName, 0, metav1.Condition{
 				Type:   string(submarinerv1.GlobalEgressIPAllocated),
 				Status: metav1.ConditionFalse,
 				Reason: "ZeroInput",
@@ -153,8 +153,8 @@ func testGlobalEgressIPCreated(t *globalEgressIPControllerTestDriver, podSelecto
 			t.pFilter.AddFailOnCreateSetMatchers(Not(BeEmpty()))
 		})
 
-		It("should eventually allocate the global IP and program the IP table rules", func() {
-			t.awaitEgressIPStatus(t.globalEgressIPs, globalEgressIPName, 1, metav1.Condition{
+		It("should eventually allocate the global IP and program the IP table rules", func(ctx context.Context) {
+			t.awaitEgressIPStatus(ctx, t.globalEgressIPs, globalEgressIPName, 1, metav1.Condition{
 				Type:   string(submarinerv1.GlobalEgressIPAllocated),
 				Status: metav1.ConditionFalse,
 				Reason: "ProgramIPTableRulesFailed",
@@ -163,7 +163,7 @@ func testGlobalEgressIPCreated(t *globalEgressIPControllerTestDriver, podSelecto
 				Status: metav1.ConditionTrue,
 			})
 
-			t.awaitPacketFilterRules(egressChain, getGlobalEgressIPStatus(t.globalEgressIPs, globalEgressIPName).AllocatedIPs...)
+			t.awaitPacketFilterRules(egressChain, getGlobalEgressIPStatus(ctx, t.globalEgressIPs, globalEgressIPName).AllocatedIPs...)
 			t.watches.AwaitWatchStarted("pods")
 		})
 	})
@@ -203,9 +203,9 @@ func testGlobalEgressIPCreated(t *globalEgressIPControllerTestDriver, podSelecto
 		var allocatedIPs []string
 		var namedSetName string
 
-		JustBeforeEach(func() {
-			t.awaitGlobalEgressIPStatusAllocated(globalEgressIPName, 1)
-			allocatedIPs = getGlobalEgressIPStatus(t.globalEgressIPs, globalEgressIPName).AllocatedIPs
+		JustBeforeEach(func(ctx context.Context) {
+			t.awaitGlobalEgressIPStatusAllocated(ctx, globalEgressIPName, 1)
+			allocatedIPs = getGlobalEgressIPStatus(ctx, t.globalEgressIPs, globalEgressIPName).AllocatedIPs
 			namedSetName = t.awaitPacketFilterRules(egressChain, allocatedIPs...)
 		})
 
@@ -254,20 +254,20 @@ func testExistingGlobalEgressIP(t *globalEgressIPControllerTestDriver, podSelect
 			t.createGlobalEgressIP(existing)
 		})
 
-		It("should not reallocate the global IPs", func() {
+		It("should not reallocate the global IPs", func(ctx context.Context) {
 			Consistently(func() []string {
-				return getGlobalEgressIPStatus(t.globalEgressIPs, existing.Name).AllocatedIPs
+				return getGlobalEgressIPStatus(ctx, t.globalEgressIPs, existing.Name).AllocatedIPs
 			}, 200*time.Millisecond).Should(Equal(existing.Status.AllocatedIPs))
 		})
 
-		It("should not update the Status conditions", func() {
+		It("should not update the Status conditions", func(ctx context.Context) {
 			Consistently(func() int {
-				return len(getGlobalEgressIPStatus(t.globalEgressIPs, existing.Name).Conditions)
+				return len(getGlobalEgressIPStatus(ctx, t.globalEgressIPs, existing.Name).Conditions)
 			}, 200*time.Millisecond).Should(Equal(0))
 		})
 
-		It("should reserve the previously allocated IPs", func() {
-			t.verifyIPsReservedInPool(getGlobalEgressIPStatus(t.globalEgressIPs, existing.Name).AllocatedIPs...)
+		It("should reserve the previously allocated IPs", func(ctx context.Context) {
+			t.verifyIPsReservedInPool(getGlobalEgressIPStatus(ctx, t.globalEgressIPs, existing.Name).AllocatedIPs...)
 		})
 
 		It("should program the necessary IP table rules for the allocated IPs", func() {
@@ -286,9 +286,9 @@ func testExistingGlobalEgressIP(t *globalEgressIPControllerTestDriver, podSelect
 			t.createGlobalEgressIP(existing)
 		})
 
-		It("should reallocate the global IPs", func() {
-			t.awaitGlobalEgressIPStatusAllocated(globalEgressIPName, *existing.Spec.NumberOfIPs)
-			t.awaitPacketFilterRules(egressChain, getGlobalEgressIPStatus(t.globalEgressIPs, globalEgressIPName).AllocatedIPs...)
+		It("should reallocate the global IPs", func(ctx context.Context) {
+			t.awaitGlobalEgressIPStatusAllocated(ctx, globalEgressIPName, *existing.Spec.NumberOfIPs)
+			t.awaitPacketFilterRules(egressChain, getGlobalEgressIPStatus(ctx, t.globalEgressIPs, globalEgressIPName).AllocatedIPs...)
 		})
 
 		It("should release the previously allocated IPs", func() {
@@ -316,8 +316,8 @@ func testExistingGlobalEgressIP(t *globalEgressIPControllerTestDriver, podSelect
 			Expect(t.pool.Reserve(existing.Status.AllocatedIPs...)).To(Succeed())
 		})
 
-		It("should reallocate the global IPs", func() {
-			t.awaitEgressIPStatus(t.globalEgressIPs, globalEgressIPName, *existing.Spec.NumberOfIPs, metav1.Condition{
+		It("should reallocate the global IPs", func(ctx context.Context) {
+			t.awaitEgressIPStatus(ctx, t.globalEgressIPs, globalEgressIPName, *existing.Spec.NumberOfIPs, metav1.Condition{
 				Type:   string(submarinerv1.GlobalEgressIPAllocated),
 				Status: metav1.ConditionFalse,
 				Reason: "ReserveAllocatedIPsFailed",
@@ -326,7 +326,7 @@ func testExistingGlobalEgressIP(t *globalEgressIPControllerTestDriver, podSelect
 				Status: metav1.ConditionTrue,
 			})
 
-			t.awaitPacketFilterRules(egressChain, getGlobalEgressIPStatus(t.globalEgressIPs, globalEgressIPName).AllocatedIPs...)
+			t.awaitPacketFilterRules(egressChain, getGlobalEgressIPStatus(ctx, t.globalEgressIPs, globalEgressIPName).AllocatedIPs...)
 		})
 	})
 
@@ -337,9 +337,9 @@ func testExistingGlobalEgressIP(t *globalEgressIPControllerTestDriver, podSelect
 			t.pFilter.AddFailOnAppendRuleMatcher(ContainSubstring(existing.Status.AllocatedIPs[0]))
 		})
 
-		It("should return an error on instantiation and not reallocate the global IPs", func() {
+		It("should return an error on instantiation and not reallocate the global IPs", func(ctx context.Context) {
 			Consistently(func() []string {
-				return getGlobalEgressIPStatus(t.globalEgressIPs, existing.Name).AllocatedIPs
+				return getGlobalEgressIPStatus(ctx, t.globalEgressIPs, existing.Name).AllocatedIPs
 			}, 200*time.Millisecond).Should(Equal(existing.Status.AllocatedIPs))
 		})
 	})
@@ -403,12 +403,12 @@ func testGlobalEgressIPUpdated(t *globalEgressIPControllerTestDriver, podSelecto
 		test.UpdateResource(t.globalEgressIPs, existing)
 	})
 
-	testReallocated := func() {
+	testReallocated := func(ctx context.Context) {
 		t.awaitIPsReleasedFromPool(existing.Status.AllocatedIPs...)
 		t.awaitNoPacketFilterRules(egressChain, existing.Status.AllocatedIPs...)
 
-		t.awaitGlobalEgressIPStatusAllocated(globalEgressIPName, *existing.Spec.NumberOfIPs)
-		t.awaitPacketFilterRules(egressChain, getGlobalEgressIPStatus(t.globalEgressIPs, globalEgressIPName).AllocatedIPs...)
+		t.awaitGlobalEgressIPStatusAllocated(ctx, globalEgressIPName, *existing.Spec.NumberOfIPs)
+		t.awaitPacketFilterRules(egressChain, getGlobalEgressIPStatus(ctx, t.globalEgressIPs, globalEgressIPName).AllocatedIPs...)
 
 		t.watches.AwaitNoWatchStopped("pods")
 	}
@@ -434,11 +434,11 @@ func testGlobalEgressIPUpdated(t *globalEgressIPControllerTestDriver, podSelecto
 			numberOfIPs = 0
 		})
 
-		It("should release the previously allocated IPs and update the status", func() {
+		It("should release the previously allocated IPs and update the status", func(ctx context.Context) {
 			t.awaitIPsReleasedFromPool(existing.Status.AllocatedIPs...)
 			t.awaitNoPacketFilterRules(egressChain, existing.Status.AllocatedIPs...)
 
-			t.awaitEgressIPStatus(t.globalEgressIPs, globalEgressIPName, 0, metav1.Condition{
+			t.awaitEgressIPStatus(ctx, t.globalEgressIPs, globalEgressIPName, 0, metav1.Condition{
 				Type:   string(submarinerv1.GlobalEgressIPAllocated),
 				Status: metav1.ConditionFalse,
 				Reason: "ZeroInput",
@@ -455,8 +455,8 @@ func testGlobalEgressIPUpdated(t *globalEgressIPControllerTestDriver, podSelecto
 			}
 		})
 
-		It("should update the status appropriately", func() {
-			t.awaitEgressIPStatus(t.globalEgressIPs, globalEgressIPName, numberOfIPs, metav1.Condition{
+		It("should update the status appropriately", func(ctx context.Context) {
+			t.awaitEgressIPStatus(ctx, t.globalEgressIPs, globalEgressIPName, numberOfIPs, metav1.Condition{
 				Type:   string(submarinerv1.GlobalEgressIPUpdated),
 				Status: metav1.ConditionFalse,
 				Reason: "PodSelectorUpdateNotSupported",
@@ -481,10 +481,10 @@ func testEgressPodEvents(t *globalEgressIPControllerTestDriver) {
 		egressIP = newGlobalEgressIP(globalEgressIPName, nil, nil)
 	})
 
-	JustBeforeEach(func() {
+	JustBeforeEach(func(ctx context.Context) {
 		t.createGlobalEgressIP(egressIP)
-		t.awaitGlobalEgressIPStatusAllocated(globalEgressIPName, 1)
-		ipSet = t.awaitPacketFilterRules(egressChain, getGlobalEgressIPStatus(t.globalEgressIPs, globalEgressIPName).AllocatedIPs...)
+		t.awaitGlobalEgressIPStatusAllocated(ctx, globalEgressIPName, 1)
+		ipSet = t.awaitPacketFilterRules(egressChain, getGlobalEgressIPStatus(ctx, t.globalEgressIPs, globalEgressIPName).AllocatedIPs...)
 		t.createPod(pod)
 	})
 
@@ -519,9 +519,9 @@ func testEgressPodEvents(t *globalEgressIPControllerTestDriver) {
 		})
 
 		Context("and then deleted", func() {
-			JustBeforeEach(func() {
+			JustBeforeEach(func(ctx context.Context) {
 				t.pFilter.AwaitEntry(ipSet, pod.Status.PodIP)
-				t.deletePod(pod)
+				t.deletePod(ctx, pod)
 			})
 
 			It("should remove the Pod IP from the IP set", func() {
@@ -597,21 +597,21 @@ func newGlobalEgressIPControllerTestDriver() *globalEgressIPControllerTestDriver
 		t.watches = fakeDynClient.NewWatchReactor(&t.dynClient.Fake)
 	})
 
-	JustBeforeEach(func() {
-		t.start()
+	JustBeforeEach(func(ctx context.Context) {
+		t.start(ctx)
 	})
 
-	AfterEach(func() {
-		t.testDriverBase.afterEach()
+	AfterEach(func(ctx context.Context) {
+		t.testDriverBase.afterEach(ctx)
 	})
 
 	return t
 }
 
-func (t *globalEgressIPControllerTestDriver) start() {
+func (t *globalEgressIPControllerTestDriver) start(ctx context.Context) {
 	var err error
 
-	t.controller, err = controllers.NewGlobalEgressIPController(&syncer.ResourceSyncerConfig{
+	t.controller, err = controllers.NewGlobalEgressIPController(ctx, &syncer.ResourceSyncerConfig{
 		SourceClient: t.dynClient,
 		RestMapper:   t.restMapper,
 		Scheme:       t.scheme,
@@ -623,7 +623,7 @@ func (t *globalEgressIPControllerTestDriver) start() {
 	}
 
 	Expect(err).To(Succeed())
-	Expect(t.controller.Start()).To(Succeed())
+	Expect(t.controller.Start(ctx)).To(Succeed())
 
 	testutil.AwaitWatchAction(&t.dynClient.Fake, "globalegressips")
 }
diff --git a/pkg/globalnet/controllers/global_ingressip_controller_test.go b/pkg/globalnet/controllers/global_ingressip_controller_test.go
index 535657a0f..364e12b23 100644
--- a/pkg/globalnet/controllers/global_ingressip_controller_test.go
+++ b/pkg/globalnet/controllers/global_ingressip_controller_test.go
@@ -143,9 +143,9 @@ func testGlobalIngressIPCreatedClusterIPSvc(t *globalIngressIPControllerTestDriv
 		t.createGlobalIngressIP(ingressIP)
 	})
 
-	It("should create an internal submariner service with an allocated global IP", func() {
-		t.awaitIngressIPStatusAllocated(globalIngressIPName)
-		allocatedIP := t.getGlobalIngressIPStatus(globalIngressIPName).AllocatedIP
+	It("should create an internal submariner service with an allocated global IP", func(ctx context.Context) {
+		t.awaitIngressIPStatusAllocated(ctx, globalIngressIPName)
+		allocatedIP := t.getGlobalIngressIPStatus(ctx, globalIngressIPName).AllocatedIP
 		Expect(allocatedIP).ToNot(BeEmpty())
 
 		internalSvcName := controllers.GetInternalSvcName(serviceName)
@@ -190,11 +190,11 @@ func testGlobalIngressIPCreatedClusterIPSvc(t *globalIngressIPControllerTestDriv
 	Context("and then removed", func() {
 		var allocatedIP string
 
-		JustBeforeEach(func() {
-			t.awaitIngressIPStatusAllocated(globalIngressIPName)
-			allocatedIP = t.getGlobalIngressIPStatus(globalIngressIPName).AllocatedIP
+		JustBeforeEach(func(ctx context.Context) {
+			t.awaitIngressIPStatusAllocated(ctx, globalIngressIPName)
+			allocatedIP = t.getGlobalIngressIPStatus(ctx, globalIngressIPName).AllocatedIP
 
-			Expect(t.globalIngressIPs.Delete(context.TODO(), globalIngressIPName, metav1.DeleteOptions{})).To(Succeed())
+			Expect(t.globalIngressIPs.Delete(ctx, globalIngressIPName, metav1.DeleteOptions{})).To(Succeed())
 		})
 
 		It("should release the allocated global IP", func() {
@@ -217,9 +217,9 @@ func testGlobalIngressIPCreatedHeadlessSvc(t *globalIngressIPControllerTestDrive
 		t.createGlobalIngressIP(ingressIP)
 	})
 
-	It("should successfully allocate a global IP", func() {
-		t.awaitIngressIPStatusAllocated(globalIngressIPName)
-		allocatedIP := t.getGlobalIngressIPStatus(globalIngressIPName).AllocatedIP
+	It("should successfully allocate a global IP", func(ctx context.Context) {
+		t.awaitIngressIPStatusAllocated(ctx, globalIngressIPName)
+		allocatedIP := t.getGlobalIngressIPStatus(ctx, globalIngressIPName).AllocatedIP
 		Expect(allocatedIP).ToNot(BeEmpty())
 		awaitPacketFilterRules(allocatedIP)
 	})
@@ -244,7 +244,7 @@ func testGlobalIngressIPCreatedHeadlessSvc(t *globalIngressIPControllerTestDrive
 			t.pFilter.AddFailOnAppendRuleMatcher(ContainSubstring(ruleMatch))
 		})
 
-		It("should eventually allocate a global IP", func() {
+		It("should eventually allocate a global IP", func(ctx context.Context) {
 			t.awaitStatusConditions(t.globalIngressIPs, globalIngressIPName, metav1.Condition{
 				Type:   string(submarinerv1.GlobalEgressIPAllocated),
 				Status: metav1.ConditionFalse,
@@ -254,18 +254,18 @@ func testGlobalIngressIPCreatedHeadlessSvc(t *globalIngressIPControllerTestDrive
 				Status: metav1.ConditionTrue,
 			})
 
-			awaitPacketFilterRules(t.getGlobalIngressIPStatus(globalIngressIPName).AllocatedIP)
+			awaitPacketFilterRules(t.getGlobalIngressIPStatus(ctx, globalIngressIPName).AllocatedIP)
 		})
 	})
 
 	Context("and then removed", func() {
 		var allocatedIP string
 
-		JustBeforeEach(func() {
-			t.awaitIngressIPStatusAllocated(globalIngressIPName)
-			allocatedIP = t.getGlobalIngressIPStatus(globalIngressIPName).AllocatedIP
+		JustBeforeEach(func(ctx context.Context) {
+			t.awaitIngressIPStatusAllocated(ctx, globalIngressIPName)
+			allocatedIP = t.getGlobalIngressIPStatus(ctx, globalIngressIPName).AllocatedIP
 
-			Expect(t.globalIngressIPs.Delete(context.TODO(), globalIngressIPName, metav1.DeleteOptions{})).To(Succeed())
+			Expect(t.globalIngressIPs.Delete(ctx, globalIngressIPName, metav1.DeleteOptions{})).To(Succeed())
 		})
 
 		It("should release the allocated global IP", func() {
@@ -305,20 +305,20 @@ func testExistingGlobalIngressIPClusterIPSvc(t *globalIngressIPControllerTestDri
 			t.createGlobalIngressIP(existing)
 		})
 
-		It("should not reallocate the global IP", func() {
+		It("should not reallocate the global IP", func(ctx context.Context) {
 			Consistently(func() string {
-				return t.getGlobalIngressIPStatus(existing.Name).AllocatedIP
+				return t.getGlobalIngressIPStatus(ctx, existing.Name).AllocatedIP
 			}, 200*time.Millisecond).Should(Equal(existing.Status.AllocatedIP))
 		})
 
-		It("should not update the Status conditions", func() {
+		It("should not update the Status conditions", func(ctx context.Context) {
 			Consistently(func() int {
-				return len(t.getGlobalIngressIPStatus(existing.Name).Conditions)
+				return len(t.getGlobalIngressIPStatus(ctx, existing.Name).Conditions)
 			}, 200*time.Millisecond).Should(Equal(0))
 		})
 
-		It("should reserve the previously allocated IP", func() {
-			t.verifyIPsReservedInPool(t.getGlobalIngressIPStatus(existing.Name).AllocatedIP)
+		It("should reserve the previously allocated IP", func(ctx context.Context) {
+			t.verifyIPsReservedInPool(t.getGlobalIngressIPStatus(ctx, existing.Name).AllocatedIP)
 		})
 
 		Context("and it's already reserved", func() {
@@ -326,8 +326,8 @@ func testExistingGlobalIngressIPClusterIPSvc(t *globalIngressIPControllerTestDri
 				Expect(t.pool.Reserve(existing.Status.AllocatedIP)).To(Succeed())
 			})
 
-			It("should reallocate the global IP", func() {
-				t.awaitIngressIPStatus(globalIngressIPName, metav1.Condition{
+			It("should reallocate the global IP", func(ctx context.Context) {
+				t.awaitIngressIPStatus(ctx, globalIngressIPName, metav1.Condition{
 					Type:   string(submarinerv1.GlobalEgressIPAllocated),
 					Status: metav1.ConditionFalse,
 					Reason: "ReserveAllocatedIPsFailed",
@@ -344,9 +344,9 @@ func testExistingGlobalIngressIPClusterIPSvc(t *globalIngressIPControllerTestDri
 				fake.FailOnAction(&t.dynClient.Fake, "services", "get", nil, true)
 			})
 
-			It("should return an error on instantiation and not reallocate the global IP", func() {
+			It("should return an error on instantiation and not reallocate the global IP", func(ctx context.Context) {
 				Consistently(func() string {
-					return t.getGlobalIngressIPStatus(existing.Name).AllocatedIP
+					return t.getGlobalIngressIPStatus(ctx, existing.Name).AllocatedIP
 				}, 200*time.Millisecond).Should(Equal(existing.Status.AllocatedIP))
 
 				t.verifyIPsReservedInPool(existing.Status.AllocatedIP)
@@ -362,12 +362,12 @@ func testExistingGlobalIngressIPClusterIPSvc(t *globalIngressIPControllerTestDri
 			t.createGlobalIngressIP(existing)
 		})
 
-		It("should create the internal service and not reallocate the global IP", func() {
+		It("should create the internal service and not reallocate the global IP", func(ctx context.Context) {
 			internalSvcName := controllers.GetInternalSvcName(serviceName)
 			intSvc := t.awaitService(internalSvcName)
 			Expect(intSvc.Spec.ExternalIPs).To(HaveExactElements(existing.Status.AllocatedIP))
 
-			status := t.getGlobalIngressIPStatus(existing.Name)
+			status := t.getGlobalIngressIPStatus(ctx, existing.Name)
 			Expect(status.AllocatedIP).To(Equal(existing.Status.AllocatedIP))
 
 			t.verifyIPsReservedInPool(existing.Status.AllocatedIP)
@@ -386,13 +386,13 @@ func testExistingGlobalIngressIPClusterIPSvc(t *globalIngressIPControllerTestDri
 			t.createGlobalIngressIP(existing)
 		})
 
-		It("should recreate the internal service with the allocated global IP", func() {
+		It("should recreate the internal service with the allocated global IP", func(ctx context.Context) {
 			Eventually(func() []string {
 				return t.awaitService(controllers.GetInternalSvcName(serviceName)).Spec.ExternalIPs
 			}).Should(HaveExactElements(existing.Status.AllocatedIP))
 
 			Consistently(func() string {
-				return t.getGlobalIngressIPStatus(existing.Name).AllocatedIP
+				return t.getGlobalIngressIPStatus(ctx, existing.Name).AllocatedIP
 			}, 200*time.Millisecond).Should(Equal(existing.Status.AllocatedIP))
 		})
 	})
@@ -404,9 +404,9 @@ func testExistingGlobalIngressIPClusterIPSvc(t *globalIngressIPControllerTestDri
 			t.createGlobalIngressIP(existing)
 		})
 
-		It("should allocate it", func() {
-			t.awaitIngressIPStatusAllocated(globalIngressIPName)
-			allocatedIP := t.getGlobalIngressIPStatus(globalIngressIPName).AllocatedIP
+		It("should allocate it", func(ctx context.Context) {
+			t.awaitIngressIPStatusAllocated(ctx, globalIngressIPName)
+			allocatedIP := t.getGlobalIngressIPStatus(ctx, globalIngressIPName).AllocatedIP
 			Expect(allocatedIP).ToNot(BeEmpty())
 		})
 
@@ -462,20 +462,20 @@ func testExistingGlobalIngressIPHeadlessSvc(t *globalIngressIPControllerTestDriv
 			t.createGlobalIngressIP(existing)
 		})
 
-		It("should not reallocate the global IP", func() {
+		It("should not reallocate the global IP", func(ctx context.Context) {
 			Consistently(func() string {
-				return t.getGlobalIngressIPStatus(existing.Name).AllocatedIP
+				return t.getGlobalIngressIPStatus(ctx, existing.Name).AllocatedIP
 			}, 200*time.Millisecond).Should(Equal(existing.Status.AllocatedIP))
 		})
 
-		It("should not update the Status conditions", func() {
+		It("should not update the Status conditions", func(ctx context.Context) {
 			Consistently(func() int {
-				return len(t.getGlobalIngressIPStatus(existing.Name).Conditions)
+				return len(t.getGlobalIngressIPStatus(ctx, existing.Name).Conditions)
 			}, 200*time.Millisecond).Should(Equal(0))
 		})
 
-		It("should reserve the previously allocated IP", func() {
-			t.verifyIPsReservedInPool(t.getGlobalIngressIPStatus(existing.Name).AllocatedIP)
+		It("should reserve the previously allocated IP", func(ctx context.Context) {
+			t.verifyIPsReservedInPool(t.getGlobalIngressIPStatus(ctx, existing.Name).AllocatedIP)
 		})
 
 		It("should program the relevant IP table rules", func() {
@@ -487,8 +487,8 @@ func testExistingGlobalIngressIPHeadlessSvc(t *globalIngressIPControllerTestDriv
 				Expect(t.pool.Reserve(existing.Status.AllocatedIP)).To(Succeed())
 			})
 
-			It("should reallocate the global IP", func() {
-				t.awaitIngressIPStatus(globalIngressIPName, metav1.Condition{
+			It("should reallocate the global IP", func(ctx context.Context) {
+				t.awaitIngressIPStatus(ctx, globalIngressIPName, metav1.Condition{
 					Type:   string(submarinerv1.GlobalEgressIPAllocated),
 					Status: metav1.ConditionFalse,
 					Reason: "ReserveAllocatedIPsFailed",
@@ -497,7 +497,7 @@ func testExistingGlobalIngressIPHeadlessSvc(t *globalIngressIPControllerTestDriv
 					Status: metav1.ConditionTrue,
 				})
 
-				awaitPacketFilterRules(t.getGlobalIngressIPStatus(globalIngressIPName).AllocatedIP)
+				awaitPacketFilterRules(t.getGlobalIngressIPStatus(ctx, globalIngressIPName).AllocatedIP)
 			})
 		})
 
@@ -507,9 +507,9 @@ func testExistingGlobalIngressIPHeadlessSvc(t *globalIngressIPControllerTestDriv
 				t.pFilter.AddFailOnAppendRuleMatcher(ContainSubstring(existing.Status.AllocatedIP))
 			})
 
-			It("should return an error on instantiation and not reallocate the global IPs", func() {
+			It("should return an error on instantiation and not reallocate the global IPs", func(ctx context.Context) {
 				Consistently(func() string {
-					return t.getGlobalIngressIPStatus(existing.Name).AllocatedIP
+					return t.getGlobalIngressIPStatus(ctx, existing.Name).AllocatedIP
 				}, 200*time.Millisecond).Should(Equal(existing.Status.AllocatedIP))
 			})
 		})
@@ -520,8 +520,8 @@ func testExistingGlobalIngressIPHeadlessSvc(t *globalIngressIPControllerTestDriv
 			t.createGlobalIngressIP(existing)
 		})
 
-		It("should allocate it and program the relevant IP table rules", func() {
-			t.awaitIngressIPStatusAllocated(globalIngressIPName)
+		It("should allocate it and program the relevant IP table rules", func(ctx context.Context) {
+			t.awaitIngressIPStatusAllocated(ctx, globalIngressIPName)
 			awaitPacketFilterRules(existing.Status.AllocatedIP)
 		})
 	})
@@ -544,19 +544,19 @@ func newGlobalIngressIPControllerDriver() *globalIngressIPControllerTestDriver {
 		Expect(err).To(Succeed())
 	})
 
-	JustBeforeEach(func() {
-		t.start()
+	JustBeforeEach(func(ctx context.Context) {
+		t.start(ctx)
 	})
 
-	AfterEach(func() {
-		t.testDriverBase.afterEach()
+	AfterEach(func(ctx context.Context) {
+		t.testDriverBase.afterEach(ctx)
 	})
 
 	return t
 }
 
-func (t *globalIngressIPControllerTestDriver) start() syncer.Interface {
-	controller, err := controllers.NewGlobalIngressIPController(&syncer.ResourceSyncerConfig{
+func (t *globalIngressIPControllerTestDriver) start(ctx context.Context) syncer.Interface {
+	controller, err := controllers.NewGlobalIngressIPController(ctx, &syncer.ResourceSyncerConfig{
 		SourceClient: t.dynClient,
 		RestMapper:   t.restMapper,
 		Scheme:       t.scheme,
@@ -571,7 +571,7 @@ func (t *globalIngressIPControllerTestDriver) start() syncer.Interface {
 
 	t.controller = controller
 
-	Expect(t.controller.Start()).To(Succeed())
+	Expect(t.controller.Start(ctx)).To(Succeed())
 
 	testutil.AwaitWatchAction(&t.dynClient.Fake, "globalingressips")
 
diff --git a/pkg/globalnet/controllers/service_controller_test.go b/pkg/globalnet/controllers/service_controller_test.go
index 86e9cf918..37ace0661 100644
--- a/pkg/globalnet/controllers/service_controller_test.go
+++ b/pkg/globalnet/controllers/service_controller_test.go
@@ -99,26 +99,27 @@ var _ = Describe("Service controller", func() {
 			t.createServiceExport(t.createService(service))
 		})
 
-		JustBeforeEach(func() {
+		JustBeforeEach(func(ctx context.Context) {
 			t.createPod(backendPod)
-			t.awaitHeadlessGlobalIngressIP(service.Name, backendPod.Name)
+			t.awaitHeadlessGlobalIngressIP(ctx, service.Name, backendPod.Name)
 		})
 
-		It("should delete the GlobalIngressIP objects associated with the backend Pods and then re-create them", func() {
-			By("Deleting the service")
+		It("should delete the GlobalIngressIP objects associated with the backend Pods and then re-create them",
+			func(ctx context.Context) {
+				By("Deleting the service")
 
-			Expect(t.services.Delete(context.TODO(), service.Name, metav1.DeleteOptions{})).To(Succeed())
+				Expect(t.services.Delete(ctx, service.Name, metav1.DeleteOptions{})).To(Succeed())
 
-			Eventually(func() []unstructured.Unstructured {
-				list, _ := t.globalIngressIPs.List(context.TODO(), metav1.ListOptions{})
-				return list.Items
-			}, 5).Should(BeEmpty())
+				Eventually(func() []unstructured.Unstructured {
+					list, _ := t.globalIngressIPs.List(ctx, metav1.ListOptions{})
+					return list.Items
+				}, 5).Should(BeEmpty())
 
-			By("Re-creating the service")
+				By("Re-creating the service")
 
-			t.createService(service)
-			t.awaitHeadlessGlobalIngressIP(service.Name, backendPod.Name)
-		})
+				t.createService(service)
+				t.awaitHeadlessGlobalIngressIP(ctx, service.Name, backendPod.Name)
+			})
 	})
 
 	When("a GlobalIngressIP is stale on startup due to a missed delete event", func() {
@@ -180,32 +181,32 @@ func newServiceControllerTestDriver() *serviceControllerTestDriver {
 		t.testDriverBase.initChains()
 	})
 
-	JustBeforeEach(func() {
-		t.start()
+	JustBeforeEach(func(ctx context.Context) {
+		t.start(ctx)
 	})
 
-	AfterEach(func() {
-		t.testDriverBase.afterEach()
+	AfterEach(func(ctx context.Context) {
+		t.testDriverBase.afterEach(ctx)
 	})
 
 	return t
 }
 
-func (t *serviceControllerTestDriver) start() {
+func (t *serviceControllerTestDriver) start(ctx context.Context) {
 	seTestDriver := &serviceExportControllerTestDriver{}
 	seTestDriver.testDriverBase = t.testDriverBase
-	config, podControllers, sesyncer := seTestDriver.start()
+	config, podControllers, sesyncer := seTestDriver.start(ctx)
 
 	gipTestDriver := &globalIngressIPControllerTestDriver{}
 	gipTestDriver.testDriverBase = t.testDriverBase
-	gipSyncer := gipTestDriver.start()
+	gipSyncer := gipTestDriver.start(ctx)
 
 	var err error
 
 	t.controller, err = controllers.NewServiceController(config, podControllers, sesyncer, gipSyncer)
 
 	Expect(err).To(Succeed())
-	Expect(t.controller.Start()).To(Succeed())
+	Expect(t.controller.Start(ctx)).To(Succeed())
 
 	testutil.AwaitWatchAction(&t.dynClient.Fake, "services")
 }
diff --git a/pkg/globalnet/controllers/service_export_controller_test.go b/pkg/globalnet/controllers/service_export_controller_test.go
index 230228ec1..7c07ffb50 100644
--- a/pkg/globalnet/controllers/service_export_controller_test.go
+++ b/pkg/globalnet/controllers/service_export_controller_test.go
@@ -104,14 +104,14 @@ func testClusterIPService() {
 			t.createServiceExport(t.createService(service))
 		})
 
-		It("should delete the GlobalIngressIP on reconciliation", func() {
+		It("should delete the GlobalIngressIP on reconciliation", func(ctx context.Context) {
 			t.awaitGlobalIngressIP(serviceName)
 
-			t.controller.Stop()
+			t.controller.Stop(ctx)
 			time.Sleep(500 * time.Millisecond)
-			Expect(t.serviceExports.Delete(context.TODO(), serviceName, metav1.DeleteOptions{})).To(Succeed())
+			Expect(t.serviceExports.Delete(ctx, serviceName, metav1.DeleteOptions{})).To(Succeed())
 
-			t.start()
+			t.start(ctx)
 			t.awaitNoGlobalIngressIP(serviceName)
 		})
 	})
@@ -164,14 +164,14 @@ func testHeadlessService() {
 			t.createPod(backendPod)
 		})
 
-		It("should create an appropriate GlobalIngressIP", func() {
-			t.awaitHeadlessGlobalIngressIP(service.Name, backendPod.Name)
+		It("should create an appropriate GlobalIngressIP", func(ctx context.Context) {
+			t.awaitHeadlessGlobalIngressIP(ctx, service.Name, backendPod.Name)
 		})
 
 		Context("and then deleted", func() {
-			It("should delete the GlobalIngressIP", func() {
-				ingressIP := t.awaitHeadlessGlobalIngressIP(service.Name, backendPod.Name)
-				t.deletePod(backendPod)
+			It("should delete the GlobalIngressIP", func(ctx context.Context) {
+				ingressIP := t.awaitHeadlessGlobalIngressIP(ctx, service.Name, backendPod.Name)
+				t.deletePod(ctx, backendPod)
 				t.awaitNoGlobalIngressIP(ingressIP.Name)
 			})
 		})
@@ -183,12 +183,12 @@ func testHeadlessService() {
 			t.createPod(backendPod)
 		})
 
-		It("should eventually create a GlobalIngressIP after the Pod transitions to running", func() {
-			t.ensureNoGlobalIngressIPs()
+		It("should eventually create a GlobalIngressIP after the Pod transitions to running", func(ctx context.Context) {
+			t.ensureNoGlobalIngressIPs(ctx)
 
 			backendPod.Status.Phase = corev1.PodRunning
 			test.UpdateResource(t.pods.Namespace(namespace), backendPod)
-			t.awaitHeadlessGlobalIngressIP(service.Name, backendPod.Name)
+			t.awaitHeadlessGlobalIngressIP(ctx, service.Name, backendPod.Name)
 		})
 
 		Context("and PublishNotReadyAddresses is set to true on the Service", func() {
@@ -196,8 +196,8 @@ func testHeadlessService() {
 				service.Spec.PublishNotReadyAddresses = true
 			})
 
-			It("should create a GlobalIngressIP", func() {
-				t.awaitHeadlessGlobalIngressIP(service.Name, backendPod.Name)
+			It("should create a GlobalIngressIP", func(ctx context.Context) {
+				t.awaitHeadlessGlobalIngressIP(ctx, service.Name, backendPod.Name)
 			})
 		})
 	})
@@ -208,12 +208,12 @@ func testHeadlessService() {
 			t.createPod(backendPod)
 		})
 
-		It("should eventually create a GlobalIngressIP", func() {
-			t.ensureNoGlobalIngressIPs()
+		It("should eventually create a GlobalIngressIP", func(ctx context.Context) {
+			t.ensureNoGlobalIngressIPs(ctx)
 
 			backendPod.Status.PodIP = "154.67.82.2"
 			test.UpdateResource(t.pods.Namespace(namespace), backendPod)
-			t.awaitHeadlessGlobalIngressIP(service.Name, backendPod.Name)
+			t.awaitHeadlessGlobalIngressIP(ctx, service.Name, backendPod.Name)
 		})
 	})
 
@@ -227,11 +227,11 @@ func testHeadlessService() {
 			otherPod = t.createPod(newPod(namespace))
 		})
 
-		It("should delete the GlobalIngressIP objects associated with the backend Pods", func() {
-			ingressIP1 := t.awaitHeadlessGlobalIngressIP(service.Name, backendPod.Name)
-			ingressIP2 := t.awaitHeadlessGlobalIngressIP(service.Name, backendPod2.Name)
+		It("should delete the GlobalIngressIP objects associated with the backend Pods", func(ctx context.Context) {
+			ingressIP1 := t.awaitHeadlessGlobalIngressIP(ctx, service.Name, backendPod.Name)
+			ingressIP2 := t.awaitHeadlessGlobalIngressIP(ctx, service.Name, backendPod2.Name)
 
-			Expect(t.serviceExports.Delete(context.TODO(), service.Name, metav1.DeleteOptions{})).To(Succeed())
+			Expect(t.serviceExports.Delete(ctx, service.Name, metav1.DeleteOptions{})).To(Succeed())
 			t.awaitNoGlobalIngressIP(ingressIP1.Name)
 			t.awaitNoGlobalIngressIP(ingressIP2.Name)
 
@@ -239,7 +239,7 @@ func testHeadlessService() {
 
 			// Ensure GlobalIngressIPs are no longer created for the service.
 			t.createPod(newHeadlessServicePod(service.Name))
-			t.ensureNoGlobalIngressIPs()
+			t.ensureNoGlobalIngressIPs(ctx)
 		})
 	})
 
@@ -248,8 +248,8 @@ func testHeadlessService() {
 			t.createPod(newPod(namespace))
 		})
 
-		It("should not create a GlobalIngressIP", func() {
-			t.ensureNoGlobalIngressIPs()
+		It("should not create a GlobalIngressIP", func(ctx context.Context) {
+			t.ensureNoGlobalIngressIPs(ctx)
 		})
 	})
 
@@ -261,20 +261,21 @@ func testHeadlessService() {
 			backendPod2 = t.createPod(newHeadlessServicePod(service.Name))
 		})
 
-		It("should delete the GlobalIngressIPs on reconciliation", func() {
-			t.awaitHeadlessGlobalIngressIP(service.Name, backendPod.Name)
-			t.awaitHeadlessGlobalIngressIP(service.Name, backendPod2.Name)
+		It("should delete the GlobalIngressIPs on reconciliation", func(ctx context.Context) {
+			t.awaitHeadlessGlobalIngressIP(ctx, service.Name, backendPod.Name)
+			t.awaitHeadlessGlobalIngressIP(ctx, service.Name, backendPod2.Name)
 
-			t.controller.Stop()
+			t.controller.Stop(ctx)
 			time.Sleep(500 * time.Millisecond)
-			Expect(t.serviceExports.Delete(context.TODO(), serviceName, metav1.DeleteOptions{})).To(Succeed())
+			Expect(t.serviceExports.Delete(ctx, serviceName, metav1.DeleteOptions{})).To(Succeed())
 
-			t.start()
+			t.start(ctx)
 
-			Eventually(func() []unstructured.Unstructured {
-				list, _ := t.globalIngressIPs.List(context.TODO(), metav1.ListOptions{})
-				return list.Items
-			}, time.Second*3).Should(BeEmpty())
+			Eventually(func(g Gomega) {
+				list, err := t.globalIngressIPs.List(ctx, metav1.ListOptions{})
+				g.Expect(err).NotTo(HaveOccurred())
+				g.Expect(list.Items).To(BeEmpty())
+			}).Within(time.Second * 3).Should(Succeed())
 		})
 	})
 
@@ -283,18 +284,18 @@ func testHeadlessService() {
 			t.createPod(backendPod)
 		})
 
-		It("should delete the GlobalIngressIPs on reconciliation", func() {
-			t.awaitHeadlessGlobalIngressIP(service.Name, backendPod.Name)
+		It("should delete the GlobalIngressIPs on reconciliation", func(ctx context.Context) {
+			t.awaitHeadlessGlobalIngressIP(ctx, service.Name, backendPod.Name)
 
-			t.controller.Stop()
+			t.controller.Stop(ctx)
 			time.Sleep(500 * time.Millisecond)
-			Expect(t.pods.Namespace(backendPod.Namespace).Delete(context.TODO(), backendPod.Name, metav1.DeleteOptions{})).To(Succeed())
+			Expect(t.pods.Namespace(backendPod.Namespace).Delete(ctx, backendPod.Name, metav1.DeleteOptions{})).To(Succeed())
 
-			t.start()
+			t.start(ctx)
 			Eventually(func() []unstructured.Unstructured {
-				list, _ := t.globalIngressIPs.List(context.TODO(), metav1.ListOptions{})
+				list, _ := t.globalIngressIPs.List(ctx, metav1.ListOptions{})
 				return list.Items
-			}, time.Second*3).Should(BeEmpty())
+			}).Within(time.Second * 3).Should(BeEmpty())
 		})
 	})
 }
@@ -323,31 +324,31 @@ func testServiceWithoutSelector() {
 		})
 
 		Context("and then original Endpoints resource is deleted", func() {
-			It("should delete the cloned endpoints", func() {
+			It("should delete the cloned endpoints", func(ctx context.Context) {
 				t.awaitEndpoints(controllers.GetInternalSvcName(endpoints.Name))
-				t.deleteEndpoints(endpoints)
+				t.deleteEndpoints(ctx, endpoints)
 				t.awaitNoEndpoints(controllers.GetInternalSvcName(endpoints.Name))
 			})
 		})
 
 		Context("and then original Endpoints resource is updated", func() {
-			It("should update the cloned endpoints", func() {
+			It("should update the cloned endpoints", func(ctx context.Context) {
 				oldIP := "172.45.5.6" // defined in newEndpoints()
 				newIP := "172.45.5.7"
 
 				clonedEp := t.awaitEndpoints(controllers.GetInternalSvcName(endpoints.Name))
 
 				// Confirm that both endpoints and clonedEP have oldIP
-				t.awaitEndpointsHasIP(endpoints.Name, oldIP)
-				t.awaitEndpointsHasIP(clonedEp.Name, oldIP)
+				t.awaitEndpointsHasIP(ctx, endpoints.Name, oldIP)
+				t.awaitEndpointsHasIP(ctx, clonedEp.Name, oldIP)
 
 				// Update endpoints to have newIP
 				updatedEp := newEndpoints(endpoints.Name, newIP, endpoints.Labels)
 				updatedEp = t.updateEndpoints(updatedEp)
 
 				// Confirm that both endpoints and clonedEP have newIP
-				t.awaitEndpointsHasIP(updatedEp.Name, newIP)
-				t.awaitEndpointsHasIP(clonedEp.Name, newIP)
+				t.awaitEndpointsHasIP(ctx, updatedEp.Name, newIP)
+				t.awaitEndpointsHasIP(ctx, clonedEp.Name, newIP)
 			})
 		})
 	})
@@ -365,31 +366,31 @@ func testServiceWithoutSelector() {
 		})
 
 		Context("and then original endpoints is deleted", func() {
-			It("should delete the cloned endpoints", func() {
+			It("should delete the cloned endpoints", func(ctx context.Context) {
 				t.awaitEndpoints(controllers.GetInternalSvcName(endpoints.Name))
-				t.deleteEndpoints(endpoints)
+				t.deleteEndpoints(ctx, endpoints)
 				t.awaitNoEndpoints(controllers.GetInternalSvcName(endpoints.Name))
 			})
 		})
 
 		Context("and then original Endpoints resource is updated", func() {
-			It("should update the cloned Endpoints resource", func() {
+			It("should update the cloned Endpoints resource", func(ctx context.Context) {
 				oldIP := "172.45.5.6" // defined in newEndpoints()
 				newIP := "172.45.5.7"
 
 				clonedEp := t.awaitEndpoints(controllers.GetInternalSvcName(endpoints.Name))
 
 				// Confirm that both endpoints and clonedEP have oldIP
-				t.awaitEndpointsHasIP(endpoints.Name, oldIP)
-				t.awaitEndpointsHasIP(clonedEp.Name, oldIP)
+				t.awaitEndpointsHasIP(ctx, endpoints.Name, oldIP)
+				t.awaitEndpointsHasIP(ctx, clonedEp.Name, oldIP)
 
 				// Update endpoints to have newIP
 				updatedEp := newEndpoints(endpoints.Name, newIP, endpoints.Labels)
 				updatedEp = t.updateEndpoints(updatedEp)
 
 				// Confirm that both endpoints and clonedEP have newIP
-				t.awaitEndpointsHasIP(updatedEp.Name, newIP)
-				t.awaitEndpointsHasIP(clonedEp.Name, newIP)
+				t.awaitEndpointsHasIP(ctx, updatedEp.Name, newIP)
+				t.awaitEndpointsHasIP(ctx, clonedEp.Name, newIP)
 			})
 		})
 	})
@@ -404,35 +405,37 @@ func testServiceWithoutSelector() {
 		})
 
 		Context("and then controller is stopped", func() {
-			It("should keep the cloned Endpoints resource on controller restart if the original still exists", func() {
-				t.controller.Stop()
+			It("should keep the cloned Endpoints resource on controller restart if the original still exists",
+				func(ctx context.Context) {
+					t.controller.Stop(ctx)
 
-				time.Sleep(50 * time.Millisecond)
-				t.awaitEndpoints(endpoints.Name)
-				t.awaitEndpoints(controllers.GetInternalSvcName(endpoints.Name))
+					time.Sleep(50 * time.Millisecond)
+					t.awaitEndpoints(endpoints.Name)
+					t.awaitEndpoints(controllers.GetInternalSvcName(endpoints.Name))
 
-				// Restart cotroller
-				t.start()
+					// Restart controller
+					t.start(ctx)
 
-				time.Sleep(50 * time.Millisecond)
-				t.awaitEndpoints(controllers.GetInternalSvcName(endpoints.Name))
-			})
+					time.Sleep(50 * time.Millisecond)
+					t.awaitEndpoints(controllers.GetInternalSvcName(endpoints.Name))
+				})
 
-			It("should delete the cloned Endpoints resource on controller restart if the original has been deleted", func() {
-				t.controller.Stop()
+			It("should delete the cloned Endpoints resource on controller restart if the original has been deleted",
+				func(ctx context.Context) {
+					t.controller.Stop(ctx)
 
-				time.Sleep(50 * time.Millisecond)
-				t.awaitEndpoints(endpoints.Name)
-				t.awaitEndpoints(controllers.GetInternalSvcName(endpoints.Name))
+					time.Sleep(50 * time.Millisecond)
+					t.awaitEndpoints(endpoints.Name)
+					t.awaitEndpoints(controllers.GetInternalSvcName(endpoints.Name))
 
-				// Delete original endpoints before restart controller
-				t.deleteEndpoints(endpoints)
-				t.awaitNoEndpoints(endpoints.Name)
+					// Delete original endpoints before restart controller
+					t.deleteEndpoints(ctx, endpoints)
+					t.awaitNoEndpoints(endpoints.Name)
 
-				t.start()
+					t.start(ctx)
 
-				t.ensureNoEndpoints(controllers.GetInternalSvcName(endpoints.Name))
-			})
+					t.ensureNoEndpoints(controllers.GetInternalSvcName(endpoints.Name))
+				})
 		})
 	})
 }
@@ -454,14 +457,14 @@ func testHeadlessServiceWithoutSelector() {
 			t.createEndpoints(endpoints)
 		})
 
-		It("should create an appropriate GlobalIngressIP", func() {
-			t.awaitHeadlessGlobalIngressIPForEP(service.Name, endpoints.Name)
+		It("should create an appropriate GlobalIngressIP", func(ctx context.Context) {
+			t.awaitHeadlessGlobalIngressIPForEP(ctx, service.Name, endpoints.Name)
 		})
 
 		Context("and then deleted", func() {
-			It("should delete the GlobalIngressIP", func() {
-				ingressIP := t.awaitHeadlessGlobalIngressIPForEP(service.Name, endpoints.Name)
-				t.deleteEndpoints(endpoints)
+			It("should delete the GlobalIngressIP", func(ctx context.Context) {
+				ingressIP := t.awaitHeadlessGlobalIngressIPForEP(ctx, service.Name, endpoints.Name)
+				t.deleteEndpoints(ctx, endpoints)
 				t.awaitNoGlobalIngressIP(ingressIP.Name)
 			})
 		})
@@ -480,18 +483,19 @@ func newServiceExportControllerTestDriver() *serviceExportControllerTestDriver {
 		t.testDriverBase.initChains()
 	})
 
-	JustBeforeEach(func() {
-		t.start()
+	JustBeforeEach(func(ctx context.Context) {
+		t.start(ctx)
 	})
 
-	AfterEach(func() {
-		t.testDriverBase.afterEach()
+	AfterEach(func(ctx context.Context) {
+		t.testDriverBase.afterEach(ctx)
 	})
 
 	return t
 }
 
-func (t *serviceExportControllerTestDriver) start() (*syncer.ResourceSyncerConfig, *controllers.IngressPodControllers, syncer.Interface) {
+func (t *serviceExportControllerTestDriver) start(ctx context.Context,
+) (*syncer.ResourceSyncerConfig, *controllers.IngressPodControllers, syncer.Interface) {
 	var err error
 
 	t.pool, err = ipam.NewIPPool(t.globalCIDR, metrics.GlobalnetMetricsReporter)
@@ -506,7 +510,7 @@ func (t *serviceExportControllerTestDriver) start() (*syncer.ResourceSyncerConfi
 	podControllers, err := controllers.NewIngressPodControllers(config)
 	Expect(err).To(Succeed())
 
-	endpointsControllers, err := controllers.NewServiceExportEndpointsControllers(config)
+	endpointsControllers, err := controllers.NewServiceExportEndpointsControllers(ctx, config)
 	Expect(err).To(Succeed())
 
 	ingressEndpointsControllers, err := controllers.NewIngressEndpointsControllers(config)
@@ -516,7 +520,7 @@ func (t *serviceExportControllerTestDriver) start() (*syncer.ResourceSyncerConfi
 	t.controller = controller
 
 	Expect(err).To(Succeed())
-	Expect(t.controller.Start()).To(Succeed())
+	Expect(t.controller.Start(ctx)).To(Succeed())
 
 	testutil.AwaitWatchAction(&t.dynClient.Fake, "serviceexports")
 
diff --git a/pkg/routeagent_driver/handlers/calico/ippool_handler_test.go b/pkg/routeagent_driver/handlers/calico/ippool_handler_test.go
index 4124c80c1..6f0848a2d 100644
--- a/pkg/routeagent_driver/handlers/calico/ippool_handler_test.go
+++ b/pkg/routeagent_driver/handlers/calico/ippool_handler_test.go
@@ -112,8 +112,8 @@ var _ = Describe("IPPool Handler", func() {
 			Expect(err).To(Succeed())
 		})
 
-		JustBeforeEach(func() {
-			Expect(t.handler.Uninstall()).To(Succeed())
+		JustBeforeEach(func(ctx context.Context) {
+			Expect(t.handler.Uninstall(ctx)).To(Succeed())
 		})
 
 		It("should delete all IPPools", func() {
diff --git a/pkg/routeagent_driver/handlers/healthchecker/healthchecker_test.go b/pkg/routeagent_driver/handlers/healthchecker/healthchecker_test.go
index 100fc9b69..f9d37b655 100644
--- a/pkg/routeagent_driver/handlers/healthchecker/healthchecker_test.go
+++ b/pkg/routeagent_driver/handlers/healthchecker/healthchecker_test.go
@@ -334,13 +334,13 @@ var _ = Describe("Gateway transition", func() {
 var _ = Describe("Stop", func() {
 	t := newTestDriver()
 
-	It("should stop the Pingers and delete the RouteAgent resource", func() {
+	It("should stop the Pingers and delete the RouteAgent resource", func(ctx context.Context) {
 		t.CreateEndpoint(t.newSubmEndpoint(healthCheckIP1))
 		t.pingerMap[healthCheckIP1].AwaitStart()
 
 		t.awaitRouteAgent(nil)
 
-		Expect(t.handler.Stop()).To(Succeed())
+		Expect(t.handler.Stop(ctx)).To(Succeed())
 
 		t.pingerMap[healthCheckIP1].AwaitStop()
 
@@ -349,7 +349,7 @@ var _ = Describe("Stop", func() {
 			g.Expect(apierrors.IsNotFound(err)).To(BeTrue())
 		}).Within(5 * time.Second).Should(Succeed())
 
-		Expect(t.handler.Stop()).To(Succeed())
+		Expect(t.handler.Stop(ctx)).To(Succeed())
 	})
 })
 
diff --git a/pkg/routeagent_driver/handlers/kubeproxy/sync_handler_test.go b/pkg/routeagent_driver/handlers/kubeproxy/sync_handler_test.go
index efec4a035..5f8289cf6 100644
--- a/pkg/routeagent_driver/handlers/kubeproxy/sync_handler_test.go
+++ b/pkg/routeagent_driver/handlers/kubeproxy/sync_handler_test.go
@@ -19,6 +19,8 @@ limitations under the License.
 package kubeproxy_test
 
 import (
+	"context"
+
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
 	"github.com/submariner-io/submariner/pkg/routeagent_driver/constants"
@@ -73,11 +75,11 @@ func testUninstall() {
 	t := newTestDriver()
 
 	Context("on Uninstall", func() {
-		It("should clean up dataplane artifacts", func() {
+		It("should clean up dataplane artifacts", func(ctx context.Context) {
 			t.CreateLocalHostEndpoint()
 			t.netLink.AwaitRule(constants.RouteAgentHostNetworkTableID, "", "")
 
-			Expect(t.handler.Uninstall()).To(Succeed())
+			Expect(t.handler.Uninstall(ctx)).To(Succeed())
 
 			t.netLink.AwaitNoRule(constants.RouteAgentHostNetworkTableID, "", "")
 			t.netLink.AwaitNoLink(kubeproxy.GetVxLANInterfaceName(k8snet.IPv4))
diff --git a/pkg/routeagent_driver/handlers/mtu/mtuhandler_test.go b/pkg/routeagent_driver/handlers/mtu/mtuhandler_test.go
index cb3a2a55c..d9c43365e 100644
--- a/pkg/routeagent_driver/handlers/mtu/mtuhandler_test.go
+++ b/pkg/routeagent_driver/handlers/mtu/mtuhandler_test.go
@@ -211,8 +211,8 @@ func (t *testDriver) testHandler(localCIDR, localCIDRIPSet, remoteCIDRIPSet stri
 		})
 	})
 
-	Specify("Uninstall should remove IP sets and chains", func() {
-		Expect(t.handler.Uninstall()).To(Succeed())
+	Specify("Uninstall should remove IP sets and chains", func(ctx context.Context) {
+		Expect(t.handler.Uninstall(ctx)).To(Succeed())
 
 		t.pFilter.AwaitSetDeleted(localCIDRIPSet)
 		t.pFilter.AwaitSetDeleted(remoteCIDRIPSet)
diff --git a/pkg/routeagent_driver/handlers/ovn/handler_test.go b/pkg/routeagent_driver/handlers/ovn/handler_test.go
index 30d733669..e69df05ec 100644
--- a/pkg/routeagent_driver/handlers/ovn/handler_test.go
+++ b/pkg/routeagent_driver/handlers/ovn/handler_test.go
@@ -742,7 +742,7 @@ func (t *handlerTestDriver) testOVNMgmtInterfaceAddressChange() {
 }
 
 func (t *handlerTestDriver) testUninstall() {
-	It("should delete the table rules and chains", func() {
+	It("should delete the table rules and chains", func(ctx context.Context) {
 		Expect(t.pFilter.ChainExists(packetfilter.TableTypeFilter, chains.SmForward)).To(BeTrue())
 		Expect(t.pFilter.ChainExists(packetfilter.TableTypeFilter, chains.SmForwardMSSClamp)).To(BeTrue())
 		Expect(t.pFilter.ChainExists(packetfilter.TableTypeNAT, chains.SmPostRouting)).To(BeTrue())
@@ -769,7 +769,7 @@ func (t *handlerTestDriver) testUninstall() {
 			MssValue:  "5",
 		})).To(Succeed())
 
-		Expect(t.handler.Uninstall()).To(Succeed())
+		Expect(t.handler.Uninstall(ctx)).To(Succeed())
 
 		t.netLink.AwaitNoRule(constants.RouteAgentHostNetworkTableID, "", "")
 		t.netLink.AwaitNoRule(constants.RouteAgentInterClusterNetworkTableID, "", "")