Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/kind/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func main() {
corev1.EventTypeNormal,
"ConfigMapFound",
"ConfigMapReconcile",
"ConfigMap found in cluster "+req.ClusterName,
"ConfigMap found in cluster "+req.ClusterName.String(),
)

log.Info("ConfigMap found", "namespace", cm.Namespace, "name", cm.Name, "cluster", req.ClusterName)
Expand Down
3 changes: 2 additions & 1 deletion pkg/builder/forked_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
mccontroller "sigs.k8s.io/multicluster-runtime/pkg/controller"
mchandler "sigs.k8s.io/multicluster-runtime/pkg/handler"
mcmanager "sigs.k8s.io/multicluster-runtime/pkg/manager"
"sigs.k8s.io/multicluster-runtime/pkg/multicluster"
mcreconcile "sigs.k8s.io/multicluster-runtime/pkg/reconcile"
mcsource "sigs.k8s.io/multicluster-runtime/pkg/source"
)
Expand Down Expand Up @@ -382,7 +383,7 @@ func (blder *TypedBuilder[request]) doWatch() error {
opts = append(opts, handler.OnlyControllerOwner())
}

hdler := func(clusterName string, cl cluster.Cluster) handler.TypedEventHandler[client.Object, request] {
hdler := func(clusterName multicluster.ClusterName, cl cluster.Cluster) handler.TypedEventHandler[client.Object, request] {
var hdler handler.TypedEventHandler[client.Object, request]
reflect.ValueOf(&hdler).Elem().Set(reflect.ValueOf(mchandler.ForCluster(handler.WithLowPriorityWhenUnchanged(handler.EnqueueRequestForOwner(
blder.mgr.GetLocalManager().GetScheme(), cl.GetRESTMapper(),
Expand Down
5 changes: 3 additions & 2 deletions pkg/builder/forked_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import (
mccontroller "sigs.k8s.io/multicluster-runtime/pkg/controller"
mchandler "sigs.k8s.io/multicluster-runtime/pkg/handler"
mcmanager "sigs.k8s.io/multicluster-runtime/pkg/manager"
"sigs.k8s.io/multicluster-runtime/pkg/multicluster"
mcreconcile "sigs.k8s.io/multicluster-runtime/pkg/reconcile"
mcsource "sigs.k8s.io/multicluster-runtime/pkg/source"
"sigs.k8s.io/multicluster-runtime/providers/clusters"
Expand Down Expand Up @@ -625,7 +626,7 @@ var _ = Describe("application", func() {
By("adding a controller to the manager", func() {
err := ControllerManagedBy(mgr).
For(&appsv1.Deployment{},
WithClusterFilter(func(clusterName string, cluster cluster.Cluster) bool {
WithClusterFilter(func(clusterName multicluster.ClusterName, cluster cluster.Cluster) bool {
// this filter should be applied
filterFunctionCalled.Store(true)
return false
Expand Down Expand Up @@ -690,7 +691,7 @@ var _ = Describe("application", func() {
By("adding a controller to the manager", func() {
err := ControllerManagedBy(mgr).
For(&appsv1.Deployment{},
WithClusterFilter(func(clusterName string, cluster cluster.Cluster) bool {
WithClusterFilter(func(clusterName multicluster.ClusterName, cluster cluster.Cluster) bool {
// this filter should be applied
filterFunctionCalled.Store(true)
return true
Expand Down
2 changes: 1 addition & 1 deletion pkg/builder/multicluster_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func WithClusterFilter(filter ClusterFilterFunc) EngageOptions {
// If is a helper function that wraps WithClusterFilter and has the
// same constraints and mutually exclusive.
func WithClustersFromProvider(ctx context.Context, provider multicluster.Provider) EngageOptions {
var fn ClusterFilterFunc = func(clusterName string, cluster cluster.Cluster) bool {
var fn ClusterFilterFunc = func(clusterName multicluster.ClusterName, cluster cluster.Cluster) bool {
cl, err := provider.Get(ctx, clusterName)
if err != nil {
return false
Expand Down
22 changes: 11 additions & 11 deletions pkg/clusters/clusters.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ type Clusters[T cluster.Cluster] struct {
WaitCacheTimeout time.Duration

lock sync.RWMutex
clusters map[string]T
cancels map[string]context.CancelFunc
clusters map[multicluster.ClusterName]T
cancels map[multicluster.ClusterName]context.CancelFunc
// Indexers holds representations of all indexes that were applied
// and should be applied to clusters that are added.
indexers []Index
Expand All @@ -71,27 +71,27 @@ func New[T cluster.Cluster]() Clusters[T] {
return Clusters[T]{
EqualClusters: EqualClusters[T],
WaitCacheTimeout: 30 * time.Second,
clusters: make(map[string]T),
cancels: make(map[string]context.CancelFunc),
clusters: make(map[multicluster.ClusterName]T),
cancels: make(map[multicluster.ClusterName]context.CancelFunc),
indexers: []Index{},
}
}

// ClusterNames returns the names of all clusters in a sorted order.
func (c *Clusters[T]) ClusterNames() []string {
func (c *Clusters[T]) ClusterNames() []multicluster.ClusterName {
c.lock.RLock()
defer c.lock.RUnlock()
return slices.Sorted(maps.Keys(c.clusters))
}

// Get returns the cluster with the given name as a cluster.Cluster.
// It implements the Get method from the Provider interface.
func (c *Clusters[T]) Get(ctx context.Context, clusterName string) (cluster.Cluster, error) {
func (c *Clusters[T]) Get(ctx context.Context, clusterName multicluster.ClusterName) (cluster.Cluster, error) {
return c.GetTyped(ctx, clusterName)
}

// GetTyped returns the cluster with the given name.
func (c *Clusters[T]) GetTyped(_ context.Context, clusterName string) (T, error) {
func (c *Clusters[T]) GetTyped(_ context.Context, clusterName multicluster.ClusterName) (T, error) {
c.lock.RLock()
defer c.lock.RUnlock()

Expand All @@ -105,7 +105,7 @@ func (c *Clusters[T]) GetTyped(_ context.Context, clusterName string) (T, error)

// Add adds a new cluster.
// If a cluster with the given name already exists, it returns an error.
func (c *Clusters[T]) Add(ctx context.Context, clusterName string, cl T, aware multicluster.Aware) error {
func (c *Clusters[T]) Add(ctx context.Context, clusterName multicluster.ClusterName, cl T, aware multicluster.Aware) error {
ctx, err := c.add(ctx, clusterName, cl)
if err != nil {
return err
Expand Down Expand Up @@ -148,7 +148,7 @@ func (c *Clusters[T]) Add(ctx context.Context, clusterName string, cl T, aware m
return nil
}

func (c *Clusters[T]) add(ctx context.Context, clusterName string, cl T) (context.Context, error) {
func (c *Clusters[T]) add(ctx context.Context, clusterName multicluster.ClusterName, cl T) (context.Context, error) {
c.lock.Lock()
defer c.lock.Unlock()

Expand All @@ -163,7 +163,7 @@ func (c *Clusters[T]) add(ctx context.Context, clusterName string, cl T) (contex
}

// Remove removes a cluster by name.
func (c *Clusters[T]) Remove(clusterName string) {
func (c *Clusters[T]) Remove(clusterName multicluster.ClusterName) {
c.lock.Lock()
defer c.lock.Unlock()

Expand All @@ -185,7 +185,7 @@ func EqualClusters[T cluster.Cluster](a, b T) bool {
// If a cluster with the name already exists it compares the
// configuration as returned by cluster.GetConfig() to compare
// clusters.
func (c *Clusters[T]) AddOrReplace(ctx context.Context, clusterName string, cl T, aware multicluster.Aware) error {
func (c *Clusters[T]) AddOrReplace(ctx context.Context, clusterName multicluster.ClusterName, cl T, aware multicluster.Aware) error {
existing, err := c.GetTyped(ctx, clusterName)
if err != nil {
// Cluster does not exist, add it
Expand Down
7 changes: 4 additions & 3 deletions pkg/context/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"sigs.k8s.io/controller-runtime/pkg/reconcile"

"sigs.k8s.io/multicluster-runtime/pkg/multicluster"
mcreconcile "sigs.k8s.io/multicluster-runtime/pkg/reconcile"
)

Expand All @@ -32,13 +33,13 @@ type clusterKeyType string
const clusterKey clusterKeyType = "cluster"

// WithCluster returns a new context with the given cluster.
func WithCluster(ctx context.Context, cluster string) context.Context {
func WithCluster(ctx context.Context, cluster multicluster.ClusterName) context.Context {
return context.WithValue(ctx, clusterKey, cluster)
}

// ClusterFrom returns the cluster from the context.
func ClusterFrom(ctx context.Context) (string, bool) {
cluster, ok := ctx.Value(clusterKey).(string)
func ClusterFrom(ctx context.Context) (multicluster.ClusterName, bool) {
cluster, ok := ctx.Value(clusterKey).(multicluster.ClusterName)
return cluster, ok
}

Expand Down
10 changes: 5 additions & 5 deletions pkg/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func NewTypedUnmanaged[request mcreconcile.ClusterAware[request]](name string, m
}
return &mcController[request]{
TypedController: c,
clusters: make(map[string]*engagedCluster),
clusters: make(map[multicluster.ClusterName]*engagedCluster),
}, nil
}

Expand All @@ -101,18 +101,18 @@ type mcController[request mcreconcile.ClusterAware[request]] struct {
controller.TypedController[request]

lock sync.Mutex
clusters map[string]*engagedCluster
clusters map[multicluster.ClusterName]*engagedCluster
sources []mcsource.TypedSource[client.Object, request]
}

type engagedCluster struct {
name string
name multicluster.ClusterName
cluster cluster.Cluster
ctx context.Context
cancel context.CancelFunc
}

func (c *mcController[request]) Engage(ctx context.Context, name string, cl cluster.Cluster) error {
func (c *mcController[request]) Engage(ctx context.Context, name multicluster.ClusterName, cl cluster.Cluster) error {
c.lock.Lock()
defer c.lock.Unlock()

Expand Down Expand Up @@ -162,7 +162,7 @@ func (c *mcController[request]) Engage(ctx context.Context, name string, cl clus
cancel: cancel,
}
c.clusters[name] = ec
go func(ctx context.Context, key string, token *engagedCluster) {
go func(ctx context.Context, key multicluster.ClusterName, token *engagedCluster) {
<-ctx.Done()
c.lock.Lock()
defer c.lock.Unlock()
Expand Down
5 changes: 3 additions & 2 deletions pkg/handler/enqueue.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ import (
"sigs.k8s.io/controller-runtime/pkg/cluster"
"sigs.k8s.io/controller-runtime/pkg/handler"

"sigs.k8s.io/multicluster-runtime/pkg/multicluster"
mcreconcile "sigs.k8s.io/multicluster-runtime/pkg/reconcile"
)

// EnqueueRequestForObject wraps a controller-runtime handler.EnqueueRequestForOwner
// to be compatible with multi-cluster.
func EnqueueRequestForObject(clusterName string, cl cluster.Cluster) handler.TypedEventHandler[client.Object, mcreconcile.Request] {
func EnqueueRequestForObject(clusterName multicluster.ClusterName, cl cluster.Cluster) handler.TypedEventHandler[client.Object, mcreconcile.Request] {
return Lift(&handler.EnqueueRequestForObject{})(clusterName, cl)
}

Expand All @@ -39,7 +40,7 @@ func TypedEnqueueRequestForObject[object client.Object]() TypedEventHandlerFunc[
// WithLowPriorityWhenUnchanged wraps a controller-runtime handler.WithLowPriorityWhenUnchanged
// to be compatible with multi-cluster.
func WithLowPriorityWhenUnchanged[object client.Object, request mcreconcile.ClusterAware[request]](u TypedEventHandlerFunc[object, request]) TypedEventHandlerFunc[object, request] {
return func(clusterName string, cl cluster.Cluster) handler.TypedEventHandler[object, request] {
return func(clusterName multicluster.ClusterName, cl cluster.Cluster) handler.TypedEventHandler[object, request] {
return handler.WithLowPriorityWhenUnchanged[object, request](u(clusterName, cl))
}
}
5 changes: 3 additions & 2 deletions pkg/handler/enqueue_owner.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,22 @@ import (
"sigs.k8s.io/controller-runtime/pkg/cluster"
"sigs.k8s.io/controller-runtime/pkg/handler"

"sigs.k8s.io/multicluster-runtime/pkg/multicluster"
mcreconcile "sigs.k8s.io/multicluster-runtime/pkg/reconcile"
)

// EnqueueRequestForOwner wraps handler.EnqueueRequestForOwner to be compatible
// with multi-cluster.
func EnqueueRequestForOwner(ownerType client.Object, opts ...handler.OwnerOption) EventHandlerFunc {
return func(clusterName string, cl cluster.Cluster) EventHandler {
return func(clusterName multicluster.ClusterName, cl cluster.Cluster) EventHandler {
return Lift(handler.EnqueueRequestForOwner(cl.GetScheme(), cl.GetRESTMapper(), ownerType, opts...))(clusterName, cl)
}
}

// TypedEnqueueRequestForOwner wraps handler.TypedEnqueueRequestForOwner to be
// compatible with multi-cluster.
func TypedEnqueueRequestForOwner[object client.Object](ownerType client.Object, opts ...handler.OwnerOption) TypedEventHandlerFunc[object, mcreconcile.Request] {
return func(clusterName string, cl cluster.Cluster) handler.TypedEventHandler[object, mcreconcile.Request] {
return func(clusterName multicluster.ClusterName, cl cluster.Cluster) handler.TypedEventHandler[object, mcreconcile.Request] {
return TypedLift[object](handler.TypedEnqueueRequestForOwner[object](cl.GetScheme(), cl.GetRESTMapper(), ownerType, opts...))(clusterName, cl)
}
}
7 changes: 4 additions & 3 deletions pkg/handler/inject.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ import (
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"

"sigs.k8s.io/multicluster-runtime/pkg/multicluster"
mcreconcile "sigs.k8s.io/multicluster-runtime/pkg/reconcile"
)

// TypedInjectCluster wraps a handler.TypedEventHandler with a cluster-aware
// request type and injects the cluster name. In contrast to TypeWithCluster,
// this function does not lift the type to cluster-awareness.
func TypedInjectCluster[object client.Object, request mcreconcile.ClusterAware[request]](h handler.TypedEventHandler[object, request]) TypedEventHandlerFunc[object, request] {
return func(clusterName string, cl cluster.Cluster) handler.TypedEventHandler[object, request] {
return func(clusterName multicluster.ClusterName, cl cluster.Cluster) handler.TypedEventHandler[object, request] {
return &clusterInjectingHandler[object, request]{h: h, clusterName: clusterName}
}
}
Expand All @@ -43,7 +44,7 @@ var _ handler.TypedEventHandler[client.Object, mcreconcile.Request] = &clusterHa

type clusterInjectingHandler[object client.Object, request mcreconcile.ClusterAware[request]] struct {
h handler.TypedEventHandler[object, request]
clusterName string
clusterName multicluster.ClusterName
}

// Create implements EventHandler.
Expand All @@ -70,7 +71,7 @@ var _ workqueue.TypedRateLimitingInterface[mcreconcile.Request] = &clusterInject

type clusterInjectingQueue[request mcreconcile.ClusterAware[request]] struct {
q workqueue.TypedRateLimitingInterface[request]
cl string
cl multicluster.ClusterName
}

func (c clusterInjectingQueue[request]) Add(item request) {
Expand Down
15 changes: 8 additions & 7 deletions pkg/handler/lift.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,25 @@ import (
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

"sigs.k8s.io/multicluster-runtime/pkg/multicluster"
mcreconcile "sigs.k8s.io/multicluster-runtime/pkg/reconcile"
)

// EventHandlerFunc produces a handler.EventHandler for a cluster.
type EventHandlerFunc = func(string, cluster.Cluster) EventHandler
type EventHandlerFunc = func(multicluster.ClusterName, cluster.Cluster) EventHandler

// TypedEventHandlerFunc produces a handler.TypedEventHandler for a cluster.
type TypedEventHandlerFunc[object client.Object, request mcreconcile.ClusterAware[request]] func(string, cluster.Cluster) handler.TypedEventHandler[object, request]
type TypedEventHandlerFunc[object client.Object, request mcreconcile.ClusterAware[request]] func(multicluster.ClusterName, cluster.Cluster) handler.TypedEventHandler[object, request]

// ForCluster wraps a handler.EventHandler without multi-cluster support for one
// concrete cluster.
func ForCluster(h handler.EventHandler, clusterName string) EventHandler {
func ForCluster(h handler.EventHandler, clusterName multicluster.ClusterName) EventHandler {
return &clusterHandler[client.Object]{h: h, clusterName: clusterName}
}

// TypedForCluster wraps a handler.TypedEventHandler without multi-cluster
// support for one concrete cluster.
func TypedForCluster[object client.Object](h handler.TypedEventHandler[object, reconcile.Request], clusterName string) handler.TypedEventHandler[object, mcreconcile.Request] {
func TypedForCluster[object client.Object](h handler.TypedEventHandler[object, reconcile.Request], clusterName multicluster.ClusterName) handler.TypedEventHandler[object, mcreconcile.Request] {
return &clusterHandler[object]{h: h, clusterName: clusterName}
}

Expand All @@ -58,7 +59,7 @@ func Lift(h handler.EventHandler) EventHandlerFunc {
// TypedLift wraps a handler.TypedEventHandler without multi-cluster
// support to be compatible with multi-cluster by injecting the cluster name.
func TypedLift[object client.Object](h handler.TypedEventHandler[object, reconcile.Request]) TypedEventHandlerFunc[object, mcreconcile.Request] {
return func(clusterName string, cl cluster.Cluster) handler.TypedEventHandler[object, mcreconcile.Request] {
return func(clusterName multicluster.ClusterName, cl cluster.Cluster) handler.TypedEventHandler[object, mcreconcile.Request] {
return &clusterHandler[object]{h: h, clusterName: clusterName}
}
}
Expand All @@ -67,7 +68,7 @@ var _ handler.TypedEventHandler[client.Object, mcreconcile.Request] = &clusterHa

type clusterHandler[object client.Object] struct {
h handler.TypedEventHandler[object, reconcile.Request]
clusterName string
clusterName multicluster.ClusterName
}

// Create implements EventHandler.
Expand All @@ -94,7 +95,7 @@ var _ workqueue.TypedRateLimitingInterface[reconcile.Request] = &clusterQueue{}

type clusterQueue struct {
q workqueue.TypedRateLimitingInterface[mcreconcile.Request]
cl string
cl multicluster.ClusterName
}

func (c clusterQueue) Add(item reconcile.Request) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/manager/coordinator.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type Coordinator interface {
// The coordinator may start or delay runnables for this cluster based on
// its policy. ctx is cancelled when the cluster is removed; implementations
// should stop per-cluster work promptly on cancellation.
Engage(ctx context.Context, name string, cl cluster.Cluster) error
Engage(ctx context.Context, name multicluster.ClusterName, cl cluster.Cluster) error

// Runnable returns an optional background Runnable driving coordination
// (e.g., membership refresh, fencing). Return nil if no background work
Expand Down
2 changes: 1 addition & 1 deletion pkg/manager/coordinator/basic/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func (c *Coordinator) AddRunnable(r multicluster.Aware) {
}

// Engage runs Engage on all registered runnables for this cluster.
func (c *Coordinator) Engage(ctx context.Context, name string, cl cluster.Cluster) error {
func (c *Coordinator) Engage(ctx context.Context, name multicluster.ClusterName, cl cluster.Cluster) error {
c.mu.Lock()
rs := append([]multicluster.Aware(nil), c.runnables...)
c.mu.Unlock()
Expand Down
Loading
Loading