@@ -3,18 +3,26 @@ package controller
33import (
44 "context"
55 "fmt"
6+ "time"
67
78 "github.com/go-logr/logr"
89 meta "k8s.io/apimachinery/pkg/apis/meta/v1"
910 "k8s.io/apimachinery/pkg/runtime"
11+ "k8s.io/apimachinery/pkg/types"
12+ "k8s.io/client-go/tools/record"
1013 ctrl "sigs.k8s.io/controller-runtime"
1114 "sigs.k8s.io/controller-runtime/pkg/client"
15+ "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
1216 "sigs.k8s.io/controller-runtime/pkg/predicate"
1317 gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
1418
1519 "github.com/api7/api7-ingress-controller/internal/controller/config"
1620)
1721
22+ const (
23+ FinalizerGatewayClassProtection = "apisix.apache.org/gc-protection"
24+ )
25+
1826// +kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gatewayclasses,verbs=get;list;watch;update
1927// +kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gatewayclasses/status,verbs=get;update
2028
@@ -23,11 +31,13 @@ type GatewayClassReconciler struct { //nolint:revive
2331 client.Client
2432 Scheme * runtime.Scheme
2533
34+ record.EventRecorder
2635 Log logr.Logger
2736}
2837
2938// SetupWithManager sets up the controller with the Manager.
3039func (r * GatewayClassReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
40+ r .EventRecorder = mgr .GetEventRecorderFor ("gatewayclass-controller" )
3141 return ctrl .NewControllerManagedBy (mgr ).
3242 For (& gatewayv1.GatewayClass {}).
3343 WithEventFilter (predicate .NewPredicateFuncs (r .GatewayClassFilter )).
@@ -41,6 +51,43 @@ func (r *GatewayClassReconciler) Reconcile(ctx context.Context, req ctrl.Request
4151 return ctrl.Result {}, client .IgnoreNotFound (err )
4252 }
4353
54+ if gc .GetDeletionTimestamp ().IsZero () {
55+ if ! controllerutil .ContainsFinalizer (gc , FinalizerGatewayClassProtection ) {
56+ controllerutil .AddFinalizer (gc , FinalizerGatewayClassProtection )
57+ if err := r .Update (ctx , gc ); err != nil {
58+ return ctrl.Result {}, err
59+ }
60+ }
61+ } else {
62+ if controllerutil .ContainsFinalizer (gc , FinalizerGatewayClassProtection ) {
63+ var gatewayList gatewayv1.GatewayList
64+ if err := r .List (ctx , & gatewayList ); err != nil {
65+ r .Log .Error (err , "failed to list gateways" )
66+ return ctrl.Result {}, err
67+ }
68+ var gateways []types.NamespacedName
69+ for _ , gateway := range gatewayList .Items {
70+ if string (gateway .Spec .GatewayClassName ) == gc .GetName () {
71+ gateways = append (gateways , types.NamespacedName {
72+ Namespace : gateway .GetNamespace (),
73+ Name : gateway .GetName (),
74+ })
75+ }
76+ }
77+ if len (gateways ) > 0 {
78+ r .Eventf (gc , "Warning" , "DeletionBlocked" , "the GatewayClass is still in using by Gateways: %v" , gateways )
79+ return ctrl.Result {RequeueAfter : 5 * time .Second }, nil
80+ } else {
81+ controllerutil .RemoveFinalizer (gc , FinalizerGatewayClassProtection )
82+ if err := r .Update (ctx , gc ); err != nil {
83+ return ctrl.Result {}, err
84+ }
85+ }
86+ }
87+
88+ return ctrl.Result {}, nil
89+ }
90+
4491 condition := meta.Condition {
4592 Type : string (gatewayv1 .GatewayClassConditionStatusAccepted ),
4693 Status : meta .ConditionTrue ,
0 commit comments