Skip to content

Commit

Permalink
feat: add new flag to specific Gateway
Browse files Browse the repository at this point in the history
Signed-off-by: Jintao Zhang <zhangjintao9020@gmail.com>

Co-authored-by: Grzegorz Burzyński <czeslavo@gmail.com>
Co-authored-by: Tao Yi  <tao.yi@konghq.com>
  • Loading branch information
3 people committed Jan 17, 2024
1 parent 789f80d commit 1e33cc3
Show file tree
Hide file tree
Showing 16 changed files with 270 additions and 11 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ Adding a new version? You'll need three changes:
[#5354](https://github.com/Kong/kubernetes-ingress-controller/pull/5354)
[#5384](https://github.com/Kong/kubernetes-ingress-controller/pull/5384)
[#5435](https://github.com/Kong/kubernetes-ingress-controller/pull/5435)
- Added flag `--gateway-to-reconcile` to set KIC to only reconcile
the specified Gateway resource in Kubernetes.
[#5405](https://github.com/Kong/kubernetes-ingress-controller/pull/5405)

### Fixed

Expand Down
1 change: 1 addition & 0 deletions docs/cli-arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
| `--feature-gates` | `list of string=bool` | A set of comma separated key=value pairs that describe feature gates for alpha/beta/experimental features. See the Feature Gates documentation for information and available options: https://github.com/Kong/kubernetes-ingress-controller/blob/main/FEATURE_GATES.md. | |
| `--gateway-api-controller-name` | `string` | The controller name to match on Gateway API resources. | `konghq.com/kic-gateway-controller` |
| `--gateway-discovery-dns-strategy` | `dns-strategy` | DNS strategy to use when creating Gateway's Admin API addresses. One of: ip, service, pod. | `"ip"` |
| `--gateway-to-reconcile` | `namespaced-name` | Gateway namespaced name in "namespace/name" format. Makes KIC reconcile only the specified Gateway. | |
| `--health-probe-bind-address` | `string` | The address the probe endpoint binds to. | `:10254` |
| `--ingress-class` | `string` | Name of the ingress class to route through this controller. | `kong` |
| `--init-cache-sync-duration` | `duration` | The initial delay to wait for Kubernetes object caches to be synced before the initial configuration. | `5s` |
Expand Down
4 changes: 4 additions & 0 deletions internal/controllers/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ package controllers

import (
"github.com/go-logr/logr"
"github.com/samber/mo"
k8stypes "k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
)

type Reconciler interface {
SetupWithManager(ctrl.Manager) error
SetLogger(logr.Logger)
}

type OptionalNamespacedName = mo.Option[k8stypes.NamespacedName]
20 changes: 20 additions & 0 deletions internal/controllers/gateway/gateway_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ type GatewayReconciler struct { //nolint:revive
// to invalidate or allow cross-namespace TLSConfigs in gateways.
// It's resolved on SetupWithManager call.
enableReferenceGrant bool

// If GatewayNN is set,
// only resources managed by the specified Gateway are reconciled.
GatewayNN controllers.OptionalNamespacedName
}

// SetupWithManager sets up the controller with the Manager.
Expand Down Expand Up @@ -173,6 +177,15 @@ func (r *GatewayReconciler) gatewayHasMatchingGatewayClass(obj client.Object) bo
)
return false
}

// If the flag `--gateway-to-reconcile` is set, KIC will only reconcile the specified gateway.
// https://github.com/Kong/kubernetes-ingress-controller/issues/5322
if gatewayToReconcile, ok := r.GatewayNN.Get(); ok {
if gatewayToReconcile.Namespace != gateway.Namespace || gatewayToReconcile.Name != gateway.Name {
return false
}
}

gatewayClass := &gatewayapi.GatewayClass{}
if err := r.Client.Get(context.Background(), client.ObjectKey{Name: string(gateway.Spec.GatewayClassName)}, gatewayClass); err != nil {
r.Log.Error(err, "Could not retrieve gatewayclass", "gatewayclass", gateway.Spec.GatewayClassName)
Expand Down Expand Up @@ -327,6 +340,13 @@ func referenceGrantHasGatewayFrom(obj client.Object) bool {
func (r *GatewayReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := r.Log.WithValues("GatewayV1Gateway", req.NamespacedName)

if gatewayToReconcile, ok := r.GatewayNN.Get(); ok {
if req.Namespace != gatewayToReconcile.Namespace || req.Name != gatewayToReconcile.Name {
r.Log.V(util.DebugLevel).Info("The request does not match the specified Gateway and will be skipped.", "gateway", gatewayToReconcile.String())
return ctrl.Result{}, nil
}
}

// gather the gateway object based on the reconciliation trigger. It's possible for the object
// to be gone at this point in which case it will be ignored.
gateway := new(gatewayapi.Gateway)
Expand Down
22 changes: 21 additions & 1 deletion internal/controllers/gateway/grpcroute_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ type GRPCRouteReconciler struct {
// If it is false, referencing backend in different namespace will be rejected.
EnableReferenceGrant bool
CacheSyncTimeout time.Duration

// If GatewayNN is set,
// only resources managed by the specified Gateway are reconciled.
GatewayNN controllers.OptionalNamespacedName
}

// SetupWithManager sets up the controller with the Manager.
Expand Down Expand Up @@ -143,6 +147,14 @@ func (r *GRPCRouteReconciler) listGRPCRoutesForGatewayClass(ctx context.Context,
gateways := make(map[string]map[string]struct{})
for _, gateway := range gatewayList.Items {
if string(gateway.Spec.GatewayClassName) == gwc.Name {
// If the flag `--gateway-to-reconcile` is set, KIC will only reconcile the specified gateway.
// https://github.com/Kong/kubernetes-ingress-controller/issues/5322
if gatewayToReconcile, ok := r.GatewayNN.Get(); ok {
if gatewayToReconcile.Namespace != gateway.Namespace || gatewayToReconcile.Name != gateway.Name {
continue
}
}

_, ok := gateways[gateway.Namespace]
if !ok {
gateways[gateway.Namespace] = make(map[string]struct{})
Expand Down Expand Up @@ -217,6 +229,14 @@ func (r *GRPCRouteReconciler) listGRPCRoutesForGateway(ctx context.Context, obj
return nil
}

// If the flag `--gateway-to-reconcile` is set, KIC will only reconcile the specified gateway.
// https://github.com/Kong/kubernetes-ingress-controller/issues/5322
if gatewayToReconcile, ok := r.GatewayNN.Get(); ok {
if gatewayToReconcile.Namespace != gw.Namespace || gatewayToReconcile.Name != gw.Name {
return nil
}
}

// map all GRPCRoute objects
grpcrouteList := gatewayapi.GRPCRouteList{}
if err := r.Client.List(ctx, &grpcrouteList); err != nil {
Expand Down Expand Up @@ -293,7 +313,7 @@ func (r *GRPCRouteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
// we need to pull the Gateway parent objects for the grpcroute to verify
// routing behavior and ensure compatibility with Gateway configurations.
debug(log, grpcroute, "Retrieving GatewayClass and Gateway for route")
gateways, err := getSupportedGatewayForRoute(ctx, log, r.Client, grpcroute)
gateways, err := getSupportedGatewayForRoute(ctx, log, r.Client, grpcroute, r.GatewayNN)
if err != nil {
if err.Error() == unsupportedGW {
debug(log, grpcroute, "Unsupported route found, processing to verify whether it was ever supported")
Expand Down
22 changes: 21 additions & 1 deletion internal/controllers/gateway/httproute_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ type HTTPRouteReconciler struct {
// If it is false, referencing backend in different namespace will be rejected.
// It's resolved on SetupWithManager call.
enableReferenceGrant bool

// If GatewayNN is set,
// only resources managed by the specified Gateway are reconciled.
GatewayNN controllers.OptionalNamespacedName
}

// SetupWithManager sets up the controller with the Manager.
Expand Down Expand Up @@ -217,6 +221,14 @@ func (r *HTTPRouteReconciler) listHTTPRoutesForGatewayClass(ctx context.Context,
gateways := make(map[string]map[string]struct{})
for _, gateway := range gatewayList.Items {
if string(gateway.Spec.GatewayClassName) == gwc.Name {
// If the flag `--gateway-to-reconcile` is set, KIC will only reconcile the specified gateway.
// https://github.com/Kong/kubernetes-ingress-controller/issues/5322
if gatewayToReconcile, ok := r.GatewayNN.Get(); ok {
if gatewayToReconcile.Namespace != gateway.Namespace || gatewayToReconcile.Name != gateway.Name {
continue
}
}

_, ok := gateways[gateway.Namespace]
if !ok {
gateways[gateway.Namespace] = make(map[string]struct{})
Expand Down Expand Up @@ -291,6 +303,14 @@ func (r *HTTPRouteReconciler) listHTTPRoutesForGateway(ctx context.Context, obj
return nil
}

// If the flag `--gateway-to-reconcile` is set, KIC will only reconcile the specified gateway.
// https://github.com/Kong/kubernetes-ingress-controller/issues/5322
if gatewayToReconcile, ok := r.GatewayNN.Get(); ok {
if gatewayToReconcile.Namespace != gw.Namespace || gatewayToReconcile.Name != gw.Name {
return nil
}
}

// map all HTTPRoute objects
httprouteList := gatewayapi.HTTPRouteList{}
if err := r.Client.List(ctx, &httprouteList); err != nil {
Expand Down Expand Up @@ -368,7 +388,7 @@ func (r *HTTPRouteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
// we need to pull the Gateway parent objects for the HTTPRoute to verify
// routing behavior and ensure compatibility with Gateway configurations.
debug(log, httproute, "Retrieving GatewayClass and Gateway for route")
gateways, err := getSupportedGatewayForRoute(ctx, log, r.Client, httproute)
gateways, err := getSupportedGatewayForRoute(ctx, log, r.Client, httproute, r.GatewayNN)
if err != nil {
if err.Error() == unsupportedGW {
debug(log, httproute, "Unsupported route found, processing to verify whether it was ever supported")
Expand Down
13 changes: 12 additions & 1 deletion internal/controllers/gateway/route_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"

"github.com/kong/kubernetes-ingress-controller/v3/internal/controllers"
"github.com/kong/kubernetes-ingress-controller/v3/internal/gatewayapi"
"github.com/kong/kubernetes-ingress-controller/v3/internal/util"
)
Expand Down Expand Up @@ -125,7 +126,9 @@ func parentRefsForRoute[T gatewayapi.RouteT](route T) ([]gatewayapi.ParentRefere
// Gateway APIs route object (e.g. HTTPRoute, TCPRoute, e.t.c.) from the provided cached
// client if they match this controller. If there are no gateways present for this route
// OR the present gateways are references to missing objects, this will return a unsupportedGW error.
func getSupportedGatewayForRoute[T gatewayapi.RouteT](ctx context.Context, logger logr.Logger, mgrc client.Client, route T) ([]supportedGatewayWithCondition, error) {
//
// There is a parameter `specifiedGW` here, which is used to specific the gateway.
func getSupportedGatewayForRoute[T gatewayapi.RouteT](ctx context.Context, logger logr.Logger, mgrc client.Client, route T, specifiedGW controllers.OptionalNamespacedName) ([]supportedGatewayWithCondition, error) {
// gather the parentrefs for this route object
parentRefs, err := parentRefsForRoute(route)
if err != nil {
Expand All @@ -145,6 +148,14 @@ func getSupportedGatewayForRoute[T gatewayapi.RouteT](ctx context.Context, logge
}
name := string(parentRef.Name)

// If the flag `--gateway-to-reconcile` is set, KIC will only reconcile the specified gateway.
// https://github.com/Kong/kubernetes-ingress-controller/issues/5322
if gatewayToReconcile, ok := specifiedGW.Get(); ok {
namespace = gatewayToReconcile.Namespace
name = gatewayToReconcile.Name

}

// pull the Gateway object from the cached client
gateway := gatewayapi.Gateway{}
if err := mgrc.Get(ctx, client.ObjectKey{
Expand Down
11 changes: 6 additions & 5 deletions internal/controllers/gateway/route_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"

"github.com/kong/kubernetes-ingress-controller/v3/internal/controllers"
"github.com/kong/kubernetes-ingress-controller/v3/internal/gatewayapi"
"github.com/kong/kubernetes-ingress-controller/v3/internal/util"
"github.com/kong/kubernetes-ingress-controller/v3/internal/util/builder"
Expand Down Expand Up @@ -542,7 +543,7 @@ func TestGetSupportedGatewayForRoute(t *testing.T) {
WithObjects(tt.objects...).
Build()

got, err := getSupportedGatewayForRoute(context.Background(), logr.Discard(), fakeClient, tt.route)
got, err := getSupportedGatewayForRoute(context.Background(), logr.Discard(), fakeClient, tt.route, controllers.OptionalNamespacedName{})
require.NoError(t, err)
require.Len(t, got, len(tt.expected))

Expand Down Expand Up @@ -813,7 +814,7 @@ func TestGetSupportedGatewayForRoute(t *testing.T) {
WithObjects(tt.objects...).
Build()

got, err := getSupportedGatewayForRoute(context.Background(), logr.Discard(), fakeClient, tt.route)
got, err := getSupportedGatewayForRoute(context.Background(), logr.Discard(), fakeClient, tt.route, controllers.OptionalNamespacedName{})
require.NoError(t, err)
require.Len(t, got, 1)
match := got[0]
Expand Down Expand Up @@ -1048,7 +1049,7 @@ func TestGetSupportedGatewayForRoute(t *testing.T) {
WithObjects(tt.objects...).
Build()

got, err := getSupportedGatewayForRoute(context.Background(), logr.Discard(), fakeClient, tt.route)
got, err := getSupportedGatewayForRoute(context.Background(), logr.Discard(), fakeClient, tt.route, controllers.OptionalNamespacedName{})
require.NoError(t, err)
require.Len(t, got, 1)
match := got[0]
Expand Down Expand Up @@ -1270,7 +1271,7 @@ func TestGetSupportedGatewayForRoute(t *testing.T) {
WithObjects(tt.objects...).
Build()

got, err := getSupportedGatewayForRoute(context.Background(), logr.Discard(), fakeClient, tt.route)
got, err := getSupportedGatewayForRoute(context.Background(), logr.Discard(), fakeClient, tt.route, controllers.OptionalNamespacedName{})
require.NoError(t, err)
require.Len(t, got, len(tt.expected))

Expand Down Expand Up @@ -1300,7 +1301,7 @@ func TestGetSupportedGatewayForRoute(t *testing.T) {
WithScheme(scheme.Scheme).
Build()

_, err := getSupportedGatewayForRoute(context.Background(), logr.Discard(), fakeClient, bustedParentHTTPRoute)
_, err := getSupportedGatewayForRoute(context.Background(), logr.Discard(), fakeClient, bustedParentHTTPRoute, controllers.OptionalNamespacedName{})
require.Equal(t, fmt.Errorf("unsupported parent kind %s/%s", string(badGroup), string(badKind)), err)
})
}
Expand Down
22 changes: 21 additions & 1 deletion internal/controllers/gateway/tcproute_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ type TCPRouteReconciler struct {
DataplaneClient controllers.DataPlane
CacheSyncTimeout time.Duration
StatusQueue *status.Queue

// If GatewayNN is set,
// only resources managed by the specified Gateway are reconciled.
GatewayNN controllers.OptionalNamespacedName
}

// SetupWithManager sets up the controller with the Manager.
Expand Down Expand Up @@ -140,6 +144,14 @@ func (r *TCPRouteReconciler) listTCPRoutesForGatewayClass(ctx context.Context, o
gateways := make(map[string]map[string]struct{})
for _, gateway := range gatewayList.Items {
if string(gateway.Spec.GatewayClassName) == gwc.Name {
// If the flag `--gateway-to-reconcile` is set, KIC will only reconcile the specified gateway.
// https://github.com/Kong/kubernetes-ingress-controller/issues/5322
if gatewayToReconcile, ok := r.GatewayNN.Get(); ok {
if gatewayToReconcile.Namespace != gateway.Namespace || gatewayToReconcile.Name != gateway.Name {
continue
}
}

_, ok := gateways[gateway.Namespace]
if !ok {
gateways[gateway.Namespace] = make(map[string]struct{})
Expand Down Expand Up @@ -214,6 +226,14 @@ func (r *TCPRouteReconciler) listTCPRoutesForGateway(ctx context.Context, obj cl
return nil
}

// If the flag `--gateway-to-reconcile` is set, KIC will only reconcile the specified gateway.
// https://github.com/Kong/kubernetes-ingress-controller/issues/5322
if gatewayToReconcile, ok := r.GatewayNN.Get(); ok {
if gatewayToReconcile.Namespace != gw.Namespace || gatewayToReconcile.Name != gw.Name {
return nil
}
}

// map all TCPRoute objects
tcprouteList := gatewayapi.TCPRouteList{}
if err := r.Client.List(ctx, &tcprouteList); err != nil {
Expand Down Expand Up @@ -290,7 +310,7 @@ func (r *TCPRouteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
// we need to pull the Gateway parent objects for the TCPRoute to verify
// routing behavior and ensure compatibility with Gateway configurations.
debug(log, tcproute, "Retrieving GatewayClass and Gateway for route")
gateways, err := getSupportedGatewayForRoute(ctx, log, r.Client, tcproute)
gateways, err := getSupportedGatewayForRoute(ctx, log, r.Client, tcproute, r.GatewayNN)
if err != nil {
if err.Error() == unsupportedGW {
debug(log, tcproute, "Unsupported route found, processing to verify whether it was ever supported")
Expand Down
22 changes: 21 additions & 1 deletion internal/controllers/gateway/tlsroute_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ type TLSRouteReconciler struct {
DataplaneClient controllers.DataPlane
CacheSyncTimeout time.Duration
StatusQueue *status.Queue

// If GatewayNN is set,
// only resources managed by the specified Gateway are reconciled.
GatewayNN controllers.OptionalNamespacedName
}

// SetupWithManager sets up the controller with the Manager.
Expand Down Expand Up @@ -139,6 +143,14 @@ func (r *TLSRouteReconciler) listTLSRoutesForGatewayClass(ctx context.Context, o
gateways := make(map[string]map[string]struct{})
for _, gateway := range gatewayList.Items {
if string(gateway.Spec.GatewayClassName) == gwc.Name {
// If the flag `--gateway-to-reconcile` is set, KIC will only reconcile the specified gateway.
// https://github.com/Kong/kubernetes-ingress-controller/issues/5322
if gatewayToReconcile, ok := r.GatewayNN.Get(); ok {
if gatewayToReconcile.Namespace != gateway.Namespace || gatewayToReconcile.Name != gateway.Name {
continue
}
}

_, ok := gateways[gateway.Namespace]
if !ok {
gateways[gateway.Namespace] = make(map[string]struct{})
Expand Down Expand Up @@ -213,6 +225,14 @@ func (r *TLSRouteReconciler) listTLSRoutesForGateway(ctx context.Context, obj cl
return nil
}

// If the flag `--gateway-to-reconcile` is set, KIC will only reconcile the specified gateway.
// https://github.com/Kong/kubernetes-ingress-controller/issues/5322
if gatewayToReconcile, ok := r.GatewayNN.Get(); ok {
if gatewayToReconcile.Namespace != gw.Namespace || gatewayToReconcile.Name != gw.Name {
return nil
}
}

// map all TLSRoute objects
tlsrouteList := gatewayapi.TLSRouteList{}
if err := r.Client.List(ctx, &tlsrouteList); err != nil {
Expand Down Expand Up @@ -289,7 +309,7 @@ func (r *TLSRouteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
// we need to pull the Gateway parent objects for the TLSRoute to verify
// routing behavior and ensure compatibility with Gateway configurations.
debug(log, tlsroute, "Retrieving GatewayClass and Gateway for route")
gateways, err := getSupportedGatewayForRoute(ctx, log, r.Client, tlsroute)
gateways, err := getSupportedGatewayForRoute(ctx, log, r.Client, tlsroute, r.GatewayNN)
if err != nil {
if err.Error() == unsupportedGW {
debug(log, tlsroute, "Unsupported route found, processing to verify whether it was ever supported")
Expand Down

0 comments on commit 1e33cc3

Please sign in to comment.