pkg/controllers/member/internalserviceimport/controller.go (70 lines of code) (raw):
/*
Copyright (c) Microsoft Corporation.
Licensed under the MIT license.
*/
// Package internalserviceimport features the InternalServiceImport controller for reporting back the status from the
// fleet to a member cluster.
package internalserviceimport
import (
"context"
"time"
"k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
fleetnetv1alpha1 "go.goms.io/fleet-networking/api/v1alpha1"
)
// Reconciler reconciles a InternalServiceImport object.
type Reconciler struct {
MemberClient client.Client
HubClient client.Client
}
//+kubebuilder:rbac:groups=networking.fleet.azure.com,resources=internalserviceimports,verbs=get;list;watch;delete
//+kubebuilder:rbac:groups=networking.fleet.azure.com,resources=serviceimports,verbs=get;list
//+kubebuilder:rbac:groups=networking.fleet.azure.com,resources=serviceimports/status,verbs=get;update;patch
// Reconcile reports back ServiceImport status from the fleet to a member cluster.
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
internalSvcImportKRef := klog.KRef(req.Namespace, req.Name)
startTime := time.Now()
klog.V(2).InfoS("Reconciliation starts", "internalServiceImport", internalSvcImportKRef)
defer func() {
latency := time.Since(startTime).Milliseconds()
klog.V(2).InfoS("Reconciliation ends", "internalServiceImport", internalSvcImportKRef, "latency", latency)
}()
// Retrieve the InternalServiceImport object.
var internalSvcImport fleetnetv1alpha1.InternalServiceImport
if err := r.HubClient.Get(ctx, req.NamespacedName, &internalSvcImport); err != nil {
// Skip the reconciliation if the InternalServiceImport does not exist.
if errors.IsNotFound(err) {
klog.V(4).InfoS("Ignoring NotFound internalServiceImport", "internalServiceImport", internalSvcImportKRef)
return ctrl.Result{}, nil
}
klog.ErrorS(err, "Failed to get internal svc import", "internalServiceImport", internalSvcImportKRef)
return ctrl.Result{}, err
}
// Check if the service import exists in the member cluster.
var serviceImport fleetnetv1alpha1.ServiceImport
svcImportName := types.NamespacedName{Namespace: internalSvcImport.Spec.ServiceImportReference.Namespace, Name: internalSvcImport.Spec.ServiceImportReference.Name}
svcImportKRef := klog.KRef(svcImportName.Namespace, svcImportName.Name)
err := r.MemberClient.Get(ctx, svcImportName, &serviceImport)
switch {
case errors.IsNotFound(err):
// Normally this situation will never happen as the ServiceImport controller guarantees, using the cleanup
// finalizer, that a InternalServiceImport should be deleted. In some corner cases,
// however, e.g. the user chooses to remove the finalizer explicitly, a InternalServiceImport can be left over
// in the hub cluster, and it is up to this controller to remove it.
klog.V(2).InfoS("serviceImport does not exist; deleting the internalServiceImport",
"serviceImport", svcImportKRef,
"internalServiceImport", internalSvcImportKRef,
)
if err := r.HubClient.Delete(ctx, &internalSvcImport); err != nil {
klog.ErrorS(err, "Failed to delete internalServiceImport", "internalServiceImport", internalSvcImportKRef)
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
case err != nil:
// An unexpected error occurs.
klog.ErrorS(err, "Failed to get serviceImport", "serviceImport", svcImportKRef)
return ctrl.Result{}, err
}
// no status change
if equality.Semantic.DeepEqual(internalSvcImport.Status, serviceImport.Status) {
return ctrl.Result{}, nil
}
// report back import status
klog.V(2).InfoS("Report back service import status from fleet", "internalServiceImport", internalSvcImportKRef)
oldStatus := serviceImport.Status.DeepCopy()
serviceImport.Status = internalSvcImport.Status
klog.V(2).InfoS("Updating the service import status", "serviceImport", svcImportKRef, "status", serviceImport.Status, "oldStatus", oldStatus)
if err := r.MemberClient.Status().Update(ctx, &serviceImport); err != nil {
klog.ErrorS(err, "Failed to update service import status", "serviceImport", svcImportKRef, "status", serviceImport.Status, "oldStatus", oldStatus)
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
}
// SetupWithManager sets up the controller with the Manager.
func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&fleetnetv1alpha1.InternalServiceImport{}).
Complete(r)
}