diff --git a/controllers/gateway/controllers/gateway_controller.go b/controllers/gateway/controllers/gateway_controller.go index b5bdecc556..de45288796 100644 --- a/controllers/gateway/controllers/gateway_controller.go +++ b/controllers/gateway/controllers/gateway_controller.go @@ -20,7 +20,10 @@ import ( "context" "errors" ossv1 "github.com/labring/laf/controllers/oss/api/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/util/retry" "laf/pkg/util" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" @@ -59,50 +62,15 @@ func (r *GatewayReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct if err := r.Get(ctx, req.NamespacedName, gateway); err != nil { return ctrl.Result{}, client.IgnoreNotFound(err) } - if !gateway.DeletionTimestamp.IsZero() { - return r.delete(ctx, gateway) + if gateway.DeletionTimestamp.IsZero() { + return r.apply(ctx, gateway) } - - return r.apply(ctx, gateway) -} - -func (r *GatewayReconciler) delete(ctx context.Context, gateway *gatewayv1.Gateway) (ctrl.Result, error) { - _log := log.FromContext(ctx) - - // delete app route - if _, err := r.deleteApp(ctx, gateway); err != nil { - return ctrl.Result{}, err - } - - // delete bucket route - if _, err := r.deleteBuckets(ctx, gateway, nil); err != nil { - return ctrl.Result{}, err - } - - // remove finalizer - gateway.Finalizers = util.RemoveString(gateway.Finalizers, gatewayFinalizer) - if err := r.Update(ctx, gateway); err != nil { - return ctrl.Result{}, err - } - - _log.Info("delete gateway: v success", "v", gateway.Name) - return ctrl.Result{}, nil } func (r *GatewayReconciler) apply(ctx context.Context, gateway *gatewayv1.Gateway) (ctrl.Result, error) { _log := log.FromContext(ctx) - _log.Info("apply gateway", "v", gateway.Name) - - // add finalizer - if !util.ContainsString(gateway.Finalizers, gatewayFinalizer) { - gateway.Finalizers = append(gateway.Finalizers, gatewayFinalizer) - if err := r.Update(ctx, gateway); err != nil { - return ctrl.Result{}, err - } - } - if gateway.Status.AppRoute == nil { result, err := r.applyApp(ctx, gateway) if err != nil { @@ -116,6 +84,8 @@ func (r *GatewayReconciler) apply(ctx context.Context, gateway *gatewayv1.Gatewa return result, err } + _log.Info("apply gateway: name success", "name", gateway.Name) + return ctrl.Result{}, nil } @@ -159,44 +129,22 @@ func (r *GatewayReconciler) applyApp(ctx context.Context, gateway *gatewayv1.Gat }, }, } - if err := r.Create(ctx, appRoute); err != nil { - if !apierrors.IsAlreadyExists(err) { - return ctrl.Result{}, nil + + if _, err := controllerutil.CreateOrUpdate(ctx, r.Client, appRoute, func() error { + if err := controllerutil.SetControllerReference(gateway, appRoute, r.Scheme); err != nil { + return err } + return nil + }); err != nil { return ctrl.Result{}, err } // update gateway status gateway.Status.AppRoute = routeStatus - if err := r.Status().Update(ctx, gateway); err != nil { - return ctrl.Result{}, err - } - return ctrl.Result{}, nil -} -// deleteApp delete app -func (r *GatewayReconciler) deleteApp(ctx context.Context, gateway *gatewayv1.Gateway) (ctrl.Result, error) { - _log := log.FromContext(ctx) - - _log.Info("delete app route", "v", gateway.Name) - - // delete app route - appRoute := &gatewayv1.Route{} - - if err := r.Get(ctx, client.ObjectKey{Name: "app", Namespace: gateway.Spec.AppId}, appRoute); err != nil { - if apierrors.IsNotFound(err) { - return ctrl.Result{}, nil - } + if err = r.updateStatus(ctx, types.NamespacedName{Name: gateway.Name, Namespace: gateway.Namespace}, gateway.Status.DeepCopy()); err != nil { return ctrl.Result{}, err } - - if err := r.Delete(ctx, appRoute); err != nil { - if apierrors.IsNotFound(err) { - return ctrl.Result{}, nil - } - return ctrl.Result{}, err - } - return ctrl.Result{}, nil } @@ -234,6 +182,7 @@ func (r *GatewayReconciler) applyBucket(ctx context.Context, gateway *gatewayv1. return ctrl.Result{}, nil } +// addBuckets add buckets func (r *GatewayReconciler) addBuckets(ctx context.Context, gateway *gatewayv1.Gateway, buckets []string) (ctrl.Result, error) { _log := log.FromContext(ctx) @@ -301,16 +250,18 @@ func (r *GatewayReconciler) addBuckets(ctx context.Context, gateway *gatewayv1.G PassHost: bucketName + "." + user.Status.Endpoint, }, } - if err := r.Create(ctx, bucketRoute); err != nil { - if apierrors.IsAlreadyExists(err) { - continue + + if _, err := controllerutil.CreateOrUpdate(ctx, r.Client, bucketRoute, func() error { + if err := controllerutil.SetControllerReference(gateway, bucketRoute, r.Scheme); err != nil { + return err } + return nil + }); err != nil { return ctrl.Result{}, err } - gateway.Status.BucketRoutes[bucketName] = routeStatus - // update gateway status - if err := r.Status().Update(ctx, gateway); err != nil { + + if err = r.updateStatus(ctx, types.NamespacedName{Name: gateway.Name, Namespace: gateway.Namespace}, gateway.Status.DeepCopy()); err != nil { return ctrl.Result{}, err } } @@ -318,29 +269,16 @@ func (r *GatewayReconciler) addBuckets(ctx context.Context, gateway *gatewayv1.G return ctrl.Result{}, nil } -// deleteBucket delete bucket +// deleteBuckets delete buckets func (r *GatewayReconciler) deleteBuckets(ctx context.Context, gateway *gatewayv1.Gateway, buckets []string) (ctrl.Result, error) { _ = log.FromContext(ctx) - // if buckets is nil, add all buckets - if buckets == nil { - buckets = make([]string, 0) - for bucketName := range gateway.Status.BucketRoutes { - buckets = append(buckets, bucketName) - } - } - // find deleted bucket, remote route and finalizer for _, bucketName := range buckets { // delete route route := &gatewayv1.Route{} // 删除名称为test的route - err := r.Get(ctx, client.ObjectKey{Namespace: gateway.Spec.AppId, Name: "bucket-" + bucketName}, route) - if err != nil { - - } - if err := r.Get(ctx, client.ObjectKey{Namespace: gateway.Spec.AppId, Name: "bucket-" + bucketName}, route); err != nil { if apierrors.IsNotFound(err) { continue @@ -357,7 +295,7 @@ func (r *GatewayReconciler) deleteBuckets(ctx context.Context, gateway *gatewayv // delete bucket route delete(gateway.Status.BucketRoutes, bucketName) - if err := r.Status().Update(ctx, gateway); err != nil { + if err := r.updateStatus(ctx, types.NamespacedName{Name: gateway.Name, Namespace: gateway.Namespace}, gateway.Status.DeepCopy()); err != nil { return ctrl.Result{}, err } } @@ -388,6 +326,23 @@ func (r *GatewayReconciler) selectDomain(ctx context.Context, backendType gatewa return nil, nil } +func (r *GatewayReconciler) updateStatus(ctx context.Context, nn types.NamespacedName, status *gatewayv1.GatewayStatus) error { + if err := retry.RetryOnConflict(retry.DefaultRetry, func() error { + original := &gatewayv1.Gateway{} + if err := r.Get(ctx, nn, original); err != nil { + return err + } + original.Status = *status + if err := r.Client.Status().Update(ctx, original); err != nil { + return err + } + return nil + }); err != nil { + return err + } + return nil +} + // SetupWithManager sets up the controller with the Manager. func (r *GatewayReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). diff --git a/controllers/gateway/controllers/route_controller.go b/controllers/gateway/controllers/route_controller.go index b9f3df8b95..16e1e95004 100644 --- a/controllers/gateway/controllers/route_controller.go +++ b/controllers/gateway/controllers/route_controller.go @@ -20,7 +20,8 @@ import ( "context" "github.com/labring/laf/controllers/gateway/apisix" "k8s.io/apimachinery/pkg/types" - "laf/pkg/util" + "k8s.io/client-go/util/retry" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "strconv" "time" @@ -80,12 +81,10 @@ func (r *RouteReconciler) applyRoute(ctx context.Context, route *gatewayv1.Route _log := log.FromContext(ctx) // add finalizer if not present - if !util.ContainsString(route.ObjectMeta.Finalizers, routeFinalizer) { - route.ObjectMeta.Finalizers = append(route.ObjectMeta.Finalizers, routeFinalizer) + if controllerutil.AddFinalizer(route, routeFinalizer) { if err := r.Update(ctx, route); err != nil { return ctrl.Result{}, err } - _log.Info("add finalizer to route") } // get route id @@ -145,7 +144,7 @@ func (r *RouteReconciler) applyRoute(ctx context.Context, route *gatewayv1.Route // update route status if route.Status.Domain == "" { route.Status.Domain = route.Spec.Domain - if err := r.Status().Update(ctx, route); err != nil { + if err := r.updateStatus(ctx, types.NamespacedName{Namespace: route.Namespace, Name: route.Name}, route.Status.DeepCopy()); err != nil { return ctrl.Result{}, err } } @@ -160,14 +159,16 @@ func (r *RouteReconciler) deleteRoute(ctx context.Context, route *gatewayv1.Rout routeId := getRouteId(route) err := cluster.Route.Delete(routeId) if err != nil { - return ctrl.Result{RequeueAfter: time.Minute * 15}, err + return ctrl.Result{RequeueAfter: time.Minute * 1}, err } // remove the finalizer - route.ObjectMeta.Finalizers = util.RemoveString(route.ObjectMeta.Finalizers, routeFinalizer) - if err := r.Update(ctx, route); err != nil { - return ctrl.Result{}, err + if controllerutil.RemoveFinalizer(route, routeFinalizer) { + if err := r.Update(ctx, route); err != nil { + return ctrl.Result{}, err + } } + _log.Info("route deleted: " + routeId) return ctrl.Result{}, nil } @@ -182,6 +183,23 @@ func (r *RouteReconciler) getGatewayCluster(ctx context.Context, route *gatewayv return cluster, nil } +func (r *RouteReconciler) updateStatus(ctx context.Context, nn types.NamespacedName, status *gatewayv1.RouteStatus) error { + if err := retry.RetryOnConflict(retry.DefaultRetry, func() error { + original := &gatewayv1.Route{} + if err := r.Get(ctx, nn, original); err != nil { + return err + } + original.Status = *status + if err := r.Client.Status().Update(ctx, original); err != nil { + return err + } + return nil + }); err != nil { + return err + } + return nil +} + func getRouteId(route *gatewayv1.Route) string { return route.Namespace + "-" + route.Name }