Skip to content

Commit

Permalink
Init watch on ManagedCluster in gateway controller
Browse files Browse the repository at this point in the history
Adds the watch for ManagedCluster resources to the gateway controller
and adds an additional step in the reconcile (reconcileClusterLabels) to
map the kuadrant.io labels from cluster(s) to gateway.

reconcileClusterLabels - Not Implemented
  • Loading branch information
mikenairn committed Jan 17, 2024
1 parent b91d493 commit a4f3e81
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 1 deletion.
72 changes: 72 additions & 0 deletions pkg/controllers/events/cluster_eventmapper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package events

import (
"context"
"encoding/json"

"github.com/go-logr/logr"

"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1"

"github.com/Kuadrant/multicluster-gateway-controller/pkg/_internal/metadata"
"github.com/Kuadrant/multicluster-gateway-controller/pkg/_internal/slice"
)

// ClusterEventMapper is an EventHandler that maps Cluster object events to gateway events.
//
// Cluster object can be anything that represents a cluster and has mgc attribute labels applied to (e.g. OCM ManagedCluster)
type ClusterEventMapper struct {
Logger logr.Logger
Client client.Client
}

func NewClusterEventMapper(logger logr.Logger, client client.Client) *ClusterEventMapper {
log := logger.WithName("ClusterEventMapper")
return &ClusterEventMapper{
Logger: log,
Client: client,
}
}

func (m *ClusterEventMapper) MapToGateway(ctx context.Context, obj client.Object) []reconcile.Request {
return m.mapToGatewayRequest(ctx, obj)
}

func (m *ClusterEventMapper) mapToGatewayRequest(ctx context.Context, obj client.Object) []reconcile.Request {
logger := m.Logger.V(1).WithValues("object", client.ObjectKeyFromObject(obj))

if obj.GetDeletionTimestamp() != nil {
// Ignore ManagedCluster delete events.
// Create/Update events are OK as ManagedCluster custom attributes may change, affecting DNSPolicies.
// However, deleting a ManagedCluster shouldn't affect the DNSPolicy directly until the related
// Gateway is deleted from that ManagedCluster (and reconciled then via watching Gateways, not ManagedClusters)
return []reconcile.Request{}
}

clusterName := obj.GetName()

allGwList := &gatewayapiv1.GatewayList{}
err := m.Client.List(ctx, allGwList)
if err != nil {
logger.Info("mapToPolicyRequest:", "error", "failed to get gateways")
return []reconcile.Request{}
}

requests := make([]reconcile.Request, 0)
for _, gw := range allGwList.Items {
val := metadata.GetAnnotation(&gw, "kuadrant.io/gateway-clusters")
if val == "" {
continue
}
var clusters []string
if err = json.Unmarshal([]byte(val), &clusters); err == nil {
if slice.ContainsString(clusters, clusterName) {
requests = append(requests, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(&gw)})
}
}
}

return requests
}
25 changes: 24 additions & 1 deletion pkg/controllers/gateway/gateway_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"reflect"
"time"

clusterv1 "open-cluster-management.io/api/cluster/v1"
clusterv1beta2 "open-cluster-management.io/api/cluster/v1beta1"
workv1 "open-cluster-management.io/api/work/v1"

Expand All @@ -49,6 +50,7 @@ import (
"github.com/Kuadrant/multicluster-gateway-controller/pkg/_internal/gracePeriod"
"github.com/Kuadrant/multicluster-gateway-controller/pkg/_internal/metadata"
"github.com/Kuadrant/multicluster-gateway-controller/pkg/_internal/slice"
"github.com/Kuadrant/multicluster-gateway-controller/pkg/controllers/events"
"github.com/Kuadrant/multicluster-gateway-controller/pkg/policysync"
"github.com/Kuadrant/multicluster-gateway-controller/pkg/utils"
)
Expand Down Expand Up @@ -195,6 +197,12 @@ func (r *GatewayReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
}
metadata.AddAnnotation(upstreamGateway, GatewayClustersAnnotation, string(serialized))

// Map cluster labels onto the gateway
err = r.reconcileClusterLabels(ctx, upstreamGateway, clusters)
if err != nil {
return ctrl.Result{}, err
}

if reconcileErr == nil && !reflect.DeepEqual(upstreamGateway, previous) {
log.Info("updating upstream gateway")
return reconcile.Result{}, r.Update(ctx, upstreamGateway)
Expand Down Expand Up @@ -264,6 +272,17 @@ func (r *GatewayReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl.Result{}, reconcileErr
}

func (r *GatewayReconciler) reconcileClusterLabels(ctx context.Context, gateway *gatewayapiv1.Gateway, clusters []string) error {
//ToDo Implement me !!

//Iterate clusters and for each find the ManagedCluster resource, get its labels and convert all "kuadrant.io/" labels to a cluster specific label and add it to the gateway
// (cluster kind-mgc-workload-1 label) kuadrant.io/lb-attribute-custom-weight=AWS = (gateway label) kuadrant.io/kind-mgc-workload-1_lb-attribute-custom-weight=AWS
// (cluster kind-mgc-workload-2 label) kuadrant.io/lb-attribute-geo-code=ES = (gateway label) kuadrant.io/kind-mgc-workload-2_lb-attribute-geo-code=ES
// etc ...

return nil
}

// reconcileDownstreamGateway takes the upstream definition and transforms it as needed to apply it to the downstream spokes
func (r *GatewayReconciler) reconcileDownstreamFromUpstreamGateway(ctx context.Context, upstreamGateway *gatewayapiv1.Gateway, params *Params) (bool, metav1.ConditionStatus, []string, error) {
log := crlog.FromContext(ctx)
Expand Down Expand Up @@ -475,7 +494,7 @@ func buildAcceptedCondition(generation int64, acceptedStatus metav1.ConditionSta
// SetupWithManager sets up the controller with the Manager.
func (r *GatewayReconciler) SetupWithManager(mgr ctrl.Manager, ctx context.Context) error {
log := crlog.FromContext(ctx)

clusterEventMapper := events.NewClusterEventMapper(log, mgr.GetClient())
//TODO need to trigger gateway reconcile when gatewayclass params changes
return ctrl.NewControllerManagedBy(mgr).
For(&gatewayapiv1.Gateway{}).
Expand Down Expand Up @@ -517,6 +536,10 @@ func (r *GatewayReconciler) SetupWithManager(mgr ctrl.Manager, ctx context.Conte
return req
})).
Watches(&corev1.Secret{}, &ClusterEventHandler{client: r.Client}).
Watches(
&clusterv1.ManagedCluster{},
handler.EnqueueRequestsFromMapFunc(clusterEventMapper.MapToGateway),
).
WithEventFilter(predicate.NewPredicateFuncs(func(object client.Object) bool {
gateway, ok := object.(*gatewayapiv1.Gateway)
if ok {
Expand Down

0 comments on commit a4f3e81

Please sign in to comment.