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
3 changes: 2 additions & 1 deletion cmd/hub-net-controller-manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ func main() {

klog.V(1).InfoS("Start to setup ServiceImport controller")
if err := (&serviceimport.Reconciler{
Client: mgr.GetClient(),
Client: mgr.GetClient(),
Recorder: mgr.GetEventRecorderFor(serviceimport.ControllerName),
}).SetupWithManager(ctx, mgr); err != nil {
klog.ErrorS(err, "Unable to create ServiceImport controller")
exitWithErrorFunc()
Expand Down
19 changes: 15 additions & 4 deletions pkg/controllers/hub/serviceimport/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import (
"context"
"time"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/equality"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
"k8s.io/klog/v2"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -29,11 +31,15 @@ import (
const (
// fields name used to filter resources
exportedServiceFieldNamespacedName = ".spec.serviceReference.namespacedName"

// ControllerName is the name of the Reconciler.
ControllerName = "serviceimport-controller"
)

// Reconciler reconciles a ServiceImport object.
type Reconciler struct {
client.Client
Recorder record.EventRecorder
}

// statusChange stores the internalServiceExports list whose status needs to be updated.
Expand All @@ -47,6 +53,7 @@ type statusChange struct {
//+kubebuilder:rbac:groups=networking.fleet.azure.com,resources=serviceimports/finalizers,verbs=update
//+kubebuilder:rbac:groups=networking.fleet.azure.com,resources=internalserviceexports,verbs=get;watch;list
//+kubebuilder:rbac:groups=networking.fleet.azure.com,resources=internalserviceexports/status,verbs=get;update;patch
//+kubebuilder:rbac:groups="",resources=events,verbs=create;patch

// Reconcile resolves the service spec when the serviceImport status is empty and updates the status of internalServiceExports.
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
Expand All @@ -64,6 +71,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
}
// If the spec has already present, no need to resolve the service spec.
if len(serviceImport.Status.Clusters) != 0 {
klog.V(4).InfoS("Already resolved the service spec and skipping", "serviceImport", serviceImportKRef)
return ctrl.Result{}, nil
}

Expand All @@ -89,6 +97,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
for i := range internalServiceExportList.Items {
v := internalServiceExportList.Items[i]
if v.DeletionTimestamp != nil { // skip if the resource is in the deleting state
klog.V(4).InfoS("Skipping the internalServiceExport which is in the deleting state", serviceImport, serviceImportKRef, "internalServiceExport", klog.KObj(&v))
continue
}
// skip if the resource is just added which has not been handled by the internalServiceExport controller yet
Expand Down Expand Up @@ -150,11 +159,12 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
updateFunc := func() error {
return r.Status().Update(ctx, &serviceImport)
}
klog.V(2).InfoS("Updating the serviceImport status", "serviceImport", serviceImportKRef, "status", serviceImport.Status)
klog.V(2).InfoS("Updating the serviceImport status", "serviceImport", serviceImportKRef)
if err := apiretry.Do(updateFunc); err != nil {
klog.ErrorS(err, "Failed to update serviceImport status with retry", "serviceImport", serviceImportKRef, "status", serviceImport.Status)
klog.ErrorS(err, "Failed to update serviceImport status with retry", "serviceImport", serviceImportKRef)
return ctrl.Result{}, err
}
r.Recorder.Eventf(&serviceImport, corev1.EventTypeNormal, "SuccessfulUpdateStatus", "Resolved exported service properties and updated %s status", serviceImport.Name)
return ctrl.Result{}, nil
}

Expand All @@ -168,20 +178,21 @@ func (r *Reconciler) updateInternalServiceExportWithRetry(ctx context.Context, i
return nil
}
exportKObj := klog.KObj(internalServiceExport)
oldStatus := internalServiceExport.Status.DeepCopy()
meta.SetStatusCondition(&internalServiceExport.Status.Conditions, desiredCond)

updateFunc := func() error {
return r.Client.Status().Update(ctx, internalServiceExport)
}
if err := apiretry.Do(updateFunc); err != nil {
klog.ErrorS(err, "Failed to update internalServiceExport status with retry", "internalServiceExport", exportKObj, "status", internalServiceExport.Status, "oldStatus", oldStatus)
klog.ErrorS(err, "Failed to update internalServiceExport status with retry", "internalServiceExport", exportKObj)
return err
}
return nil
}

func (r *Reconciler) deleteServiceImport(ctx context.Context, serviceImport *fleetnetv1alpha1.ServiceImport) (ctrl.Result, error) {
r.Recorder.Eventf(serviceImport, corev1.EventTypeNormal, "NoExportedService", "No exported service and deleting serviceImport %s", serviceImport.Name)

serviceImportKObj := klog.KObj(serviceImport)
if err := r.Client.Delete(ctx, serviceImport); err != nil {
klog.ErrorS(err, "Failed to delete serviceImport", "serviceImport", serviceImportKObj)
Expand Down
3 changes: 2 additions & 1 deletion pkg/controllers/hub/serviceimport/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ var _ = BeforeSuite(func() {
Expect(err).NotTo(HaveOccurred())

err = (&Reconciler{
Client: mgr.GetClient(),
Client: mgr.GetClient(),
Recorder: mgr.GetEventRecorderFor(ControllerName),
}).SetupWithManager(ctx, mgr)
Expect(err).ToNot(HaveOccurred())

Expand Down