Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

directresponse: Address several follow-up changes #10009

Merged
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
6 changes: 6 additions & 0 deletions changelog/v1.18.0-beta21/direct-response-follow-ups.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
changelog:
- type: NON_USER_FACING
issueLink: https://github.com/solo-io/gloo/issues/9774
resolvesIssue: false
description: >-
Address several follow-up items after the initial direct response PRs were merged.
76 changes: 21 additions & 55 deletions projects/gateway2/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,114 +259,74 @@ func (c *controllerBuilder) watchGwClass(_ context.Context) error {
}

func (c *controllerBuilder) watchHttpRoute(_ context.Context) error {
err := ctrl.NewControllerManagedBy(c.cfg.Mgr).
return ctrl.NewControllerManagedBy(c.cfg.Mgr).
WithEventFilter(predicate.GenerationChangedPredicate{}).
For(&apiv1.HTTPRoute{}).
Complete(reconcile.Func(c.reconciler.ReconcileHttpRoutes))
if err != nil {
return err
}
return nil
}

func (c *controllerBuilder) watchReferenceGrant(_ context.Context) error {
err := ctrl.NewControllerManagedBy(c.cfg.Mgr).
return ctrl.NewControllerManagedBy(c.cfg.Mgr).
WithEventFilter(predicate.GenerationChangedPredicate{}).
For(&apiv1beta1.ReferenceGrant{}).
Complete(reconcile.Func(c.reconciler.ReconcileReferenceGrants))
if err != nil {
return err
}
return nil
}

func (c *controllerBuilder) watchNamespaces(_ context.Context) error {
err := ctrl.NewControllerManagedBy(c.cfg.Mgr).
return ctrl.NewControllerManagedBy(c.cfg.Mgr).
For(&corev1.Namespace{}).
Complete(reconcile.Func(c.reconciler.ReconcileNamespaces))
if err != nil {
return err
}
return nil
}

func (c *controllerBuilder) watchHttpListenerOptions(_ context.Context) error {
err := ctrl.NewControllerManagedBy(c.cfg.Mgr).
return ctrl.NewControllerManagedBy(c.cfg.Mgr).
WithEventFilter(predicate.GenerationChangedPredicate{}).
For(&sologatewayv1.HttpListenerOption{}).
Complete(reconcile.Func(c.reconciler.ReconcileHttpListenerOptions))
if err != nil {
return err
}
return nil
}

func (c *controllerBuilder) watchListenerOptions(_ context.Context) error {
err := ctrl.NewControllerManagedBy(c.cfg.Mgr).
return ctrl.NewControllerManagedBy(c.cfg.Mgr).
WithEventFilter(predicate.GenerationChangedPredicate{}).
For(&sologatewayv1.ListenerOption{}).
Complete(reconcile.Func(c.reconciler.ReconcileListenerOptions))
if err != nil {
return err
}
return nil
}

func (c *controllerBuilder) watchRouteOptions(_ context.Context) error {
err := ctrl.NewControllerManagedBy(c.cfg.Mgr).
return ctrl.NewControllerManagedBy(c.cfg.Mgr).
WithEventFilter(predicate.GenerationChangedPredicate{}).
For(&sologatewayv1.RouteOption{}).
Complete(reconcile.Func(c.reconciler.ReconcileRouteOptions))
if err != nil {
return err
}
return nil
}

func (c *controllerBuilder) watchVirtualHostOptions(_ context.Context) error {
err := ctrl.NewControllerManagedBy(c.cfg.Mgr).
return ctrl.NewControllerManagedBy(c.cfg.Mgr).
WithEventFilter(predicate.GenerationChangedPredicate{}).
For(&sologatewayv1.VirtualHostOption{}).
Complete(reconcile.Func(c.reconciler.ReconcileVirtualHostOptions))
if err != nil {
return err
}
return nil
}

func (c *controllerBuilder) watchUpstreams(_ context.Context) error {
err := ctrl.NewControllerManagedBy(c.cfg.Mgr).
return ctrl.NewControllerManagedBy(c.cfg.Mgr).
WithEventFilter(predicate.GenerationChangedPredicate{}).
For(&gloov1.Upstream{}).
Complete(reconcile.Func(c.reconciler.ReconcileUpstreams))
if err != nil {
return err
}
return nil
}

func (c *controllerBuilder) watchServices(_ context.Context) error {
err := ctrl.NewControllerManagedBy(c.cfg.Mgr).
return ctrl.NewControllerManagedBy(c.cfg.Mgr).
WithEventFilter(predicate.GenerationChangedPredicate{}).
For(&corev1.Service{}).
Complete(reconcile.Func(c.reconciler.ReconcileServices))
if err != nil {
return err
}
return nil
}

// watchDirectResponses watches for DirectResponses and triggers
// reconciliation of the Gateway that references them.
func (c *controllerBuilder) watchDirectResponses(_ context.Context) error {
err := ctrl.NewControllerManagedBy(c.cfg.Mgr).
return ctrl.NewControllerManagedBy(c.cfg.Mgr).
WithEventFilter(predicate.GenerationChangedPredicate{}).
For(&v1alpha1.DirectResponse{}).
Complete(reconcile.Func(c.reconciler.ReconcileDirectResponses))
if err != nil {
return err
}
return nil
}

type controllerReconciler struct {
Expand All @@ -377,48 +337,56 @@ type controllerReconciler struct {

func (r *controllerReconciler) ReconcileHttpListenerOptions(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// eventually reconcile only effected routes/listeners etc
// https://github.com/solo-io/gloo/issues/9997.
r.kick(ctx)
return ctrl.Result{}, nil
}

func (r *controllerReconciler) ReconcileListenerOptions(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// eventually reconcile only effected routes/listeners etc
// https://github.com/solo-io/gloo/issues/9997.
r.kick(ctx)
return ctrl.Result{}, nil
}

func (r *controllerReconciler) ReconcileRouteOptions(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// eventually reconcile only effected routes/listeners etc
// https://github.com/solo-io/gloo/issues/9997.
r.kick(ctx)
return ctrl.Result{}, nil
}

func (r *controllerReconciler) ReconcileDirectResponses(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// TODO(tim): eventually reconcile only effected routes.
// https://github.com/solo-io/gloo/issues/9997.
r.kick(ctx)
return ctrl.Result{}, nil
}

func (r *controllerReconciler) ReconcileVirtualHostOptions(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// eventually reconcile only effected listeners etc
// https://github.com/solo-io/gloo/issues/9997.
r.kick(ctx)
return ctrl.Result{}, nil
}

func (r *controllerReconciler) ReconcileUpstreams(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// eventually reconcile only effected listeners etc
// https://github.com/solo-io/gloo/issues/9997.
r.kick(ctx)
return ctrl.Result{}, nil
}

func (r *controllerReconciler) ReconcileServices(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// eventually reconcile only effected listeners etc
// https://github.com/solo-io/gloo/issues/9997.
r.kick(ctx)
return ctrl.Result{}, nil
}

func (r *controllerReconciler) ReconcileNamespaces(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// reconcile all gateways with namespace selector
// https://github.com/solo-io/gloo/issues/9997.
r.kick(ctx)
return ctrl.Result{}, nil
}
Expand All @@ -435,7 +403,7 @@ func (r *controllerReconciler) ReconcileHttpRoutes(ctx context.Context, req ctrl
}

func (r *controllerReconciler) ReconcileReferenceGrants(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// reconcile all things?!
// reconcile all things?! https://github.com/solo-io/gloo/issues/9997
r.kick(ctx)
return ctrl.Result{}, nil
}
Expand All @@ -444,8 +412,7 @@ func (r *controllerReconciler) ReconcileGatewayClasses(ctx context.Context, req
log := log.FromContext(ctx).WithValues("gwclass", req.NamespacedName)

gwclass := &apiv1.GatewayClass{}
err := r.cli.Get(ctx, req.NamespacedName, gwclass)
if err != nil {
if err := r.cli.Get(ctx, req.NamespacedName, gwclass); err != nil {
// NOTE: if this reconciliation is a result of a DELETE event, this err will be a NotFound,
// therefore we will return a nil error here and thus skip any additional reconciliation below.
// At the time of writing this comment, the retrieved GWClass object is only used to update the status,
Expand Down Expand Up @@ -474,8 +441,7 @@ func (r *controllerReconciler) ReconcileGatewayClasses(ctx context.Context, req
}
meta.SetStatusCondition(&gwclass.Status.Conditions, supportedVersionCondition)

err = r.cli.Status().Update(ctx, gwclass)
if err != nil {
if err := r.cli.Status().Update(ctx, gwclass); err != nil {
return ctrl.Result{}, err
}
log.Info("updated gateway class status")
Expand Down
96 changes: 75 additions & 21 deletions projects/gateway2/translator/httproute/translate_httproute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@ import (
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/solo-io/solo-kit/pkg/api/v2/reporter"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
gwv1 "sigs.k8s.io/gateway-api/apis/v1"

"github.com/solo-io/solo-kit/pkg/api/v1/clients/factory"
"github.com/solo-io/solo-kit/pkg/api/v1/clients/memory"
"github.com/solo-io/solo-kit/pkg/api/v1/resources"
"github.com/solo-io/solo-kit/pkg/api/v1/resources/core"
"github.com/solo-io/solo-kit/pkg/api/v2/reporter"

"github.com/solo-io/gloo/pkg/utils/statusutils"
sologatewayv1 "github.com/solo-io/gloo/projects/gateway/pkg/api/v1"
"github.com/solo-io/gloo/projects/gateway2/api/v1alpha1"
Expand All @@ -30,10 +35,6 @@ import (
v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1"
"github.com/solo-io/gloo/projects/gloo/pkg/api/v1/core/matchers"
"github.com/solo-io/gloo/projects/gloo/pkg/defaults"
"github.com/solo-io/solo-kit/pkg/api/v1/clients/factory"
"github.com/solo-io/solo-kit/pkg/api/v1/clients/memory"
"github.com/solo-io/solo-kit/pkg/api/v1/resources"
"github.com/solo-io/solo-kit/pkg/api/v1/resources/core"
)

var _ = Describe("GatewayHttpRouteTranslator", func() {
Expand Down Expand Up @@ -204,10 +205,16 @@ var _ = Describe("GatewayHttpRouteTranslator", func() {
routeStatus := reportsMap.BuildRouteStatus(ctx, route, "")
Expect(routeStatus).NotTo(BeNil())
Expect(routeStatus.Parents).To(HaveLen(1))
resolvedRefs := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionAccepted))
By("verifying the route was accepted")
accepted := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionAccepted))
Expect(accepted).NotTo(BeNil())
Expect(accepted.Status).To(Equal(metav1.ConditionTrue))
Expect(accepted.Reason).To(BeEquivalentTo(gwv1.RouteReasonAccepted))
By("verifying the route was resolved correctly")
resolvedRefs := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionResolvedRefs))
Expect(resolvedRefs).NotTo(BeNil())
Expect(resolvedRefs.Status).To(Equal(metav1.ConditionTrue))
Expect(resolvedRefs.Reason).To(BeEquivalentTo(gwv1.RouteReasonAccepted))
Expect(resolvedRefs.Reason).To(BeEquivalentTo(gwv1.RouteReasonResolvedRefs))
})
})

Expand Down Expand Up @@ -251,10 +258,16 @@ var _ = Describe("GatewayHttpRouteTranslator", func() {
routeStatus := reportsMap.BuildRouteStatus(ctx, route, "")
Expect(routeStatus).NotTo(BeNil())
Expect(routeStatus.Parents).To(HaveLen(1))
resolvedRefs := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionAccepted))
By("verifying the route was accepted")
accepted := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionAccepted))
Expect(accepted).NotTo(BeNil())
Expect(accepted.Status).To(Equal(metav1.ConditionTrue))
Expect(accepted.Reason).To(BeEquivalentTo(gwv1.RouteConditionAccepted))
By("verifying the route was not able to resolve the backend")
resolvedRefs := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionResolvedRefs))
Expect(resolvedRefs).NotTo(BeNil())
Expect(resolvedRefs.Status).To(Equal(metav1.ConditionTrue))
Expect(resolvedRefs.Reason).To(BeEquivalentTo(gwv1.RouteConditionAccepted))
Expect(resolvedRefs.Status).To(Equal(metav1.ConditionFalse))
Expect(resolvedRefs.Reason).To(BeEquivalentTo(gwv1.RouteReasonBackendNotFound))
})
})
})
Expand Down Expand Up @@ -316,15 +329,33 @@ var _ = Describe("GatewayHttpRouteTranslator", func() {
})

When("an HTTPRoute configures the backendRef and direct response actions", func() {
var (
backingSvc *corev1.Service
)
BeforeEach(func() {
backingSvc = &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "bar",
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{{
Name: "http",
Port: 8080,
}},
},
}

dr := createDirectResponse("test", "bar", 200)
deps = append(deps, dr)

backendRefs := []gwv1.HTTPBackendRef{{
BackendRef: gwv1.BackendRef{
BackendObjectReference: gwv1.BackendObjectReference{
Name: "httpbin",
Port: ptr.To(gwv1.PortNumber(8000)),
Name: gwv1.ObjectName(backingSvc.GetName()),
Namespace: ptr.To(gwv1.Namespace(backingSvc.GetNamespace())),
Kind: ptr.To(gwv1.Kind("Service")),
Port: ptr.To(gwv1.PortNumber(backingSvc.Spec.Ports[0].Port)),
},
},
}}
Expand All @@ -339,7 +370,12 @@ var _ = Describe("GatewayHttpRouteTranslator", func() {
}}

route = createHTTPRoute(backendRefs, filters)
routeInfo = &query.HTTPRouteInfo{HTTPRoute: route}
backends := query.NewBackendMap[client.Object]()
backends.Add(route.Spec.Rules[0].BackendRefs[0].BackendObjectReference, backingSvc)
routeInfo = &query.HTTPRouteInfo{
HTTPRoute: route,
Backends: backends,
}
parentRefReporter = baseReporter.Route(&route).ParentRef(&gwv1.ParentReference{Name: "my-gw"})
})

Expand All @@ -351,10 +387,16 @@ var _ = Describe("GatewayHttpRouteTranslator", func() {
routeStatus := reportsMap.BuildRouteStatus(ctx, route, "")
Expect(routeStatus).NotTo(BeNil())
Expect(routeStatus.Parents).To(HaveLen(1))
resolvedRefs := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionAccepted))
By("verifying the route was not accepted")
accepted := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionAccepted))
Expect(accepted).NotTo(BeNil())
Expect(accepted.Status).To(Equal(metav1.ConditionFalse))
Expect(accepted.Reason).To(BeEquivalentTo(gwv1.RouteReasonIncompatibleFilters))
By("verifying the route was resolved correctly")
resolvedRefs := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionResolvedRefs))
Expect(resolvedRefs).NotTo(BeNil())
Expect(resolvedRefs.Status).To(Equal(metav1.ConditionFalse))
Expect(resolvedRefs.Reason).To(BeEquivalentTo(gwv1.RouteReasonIncompatibleFilters))
Expect(resolvedRefs.Status).To(Equal(metav1.ConditionTrue))
Expect(resolvedRefs.Reason).To(BeEquivalentTo(gwv1.RouteReasonResolvedRefs))
})
})

Expand Down Expand Up @@ -394,10 +436,16 @@ var _ = Describe("GatewayHttpRouteTranslator", func() {
routeStatus := reportsMap.BuildRouteStatus(ctx, route, "")
Expect(routeStatus).NotTo(BeNil())
Expect(routeStatus.Parents).To(HaveLen(1))
resolvedRefs := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionAccepted))
By("verifying the route was not accepted due to incompatible filters")
accepted := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionAccepted))
Expect(accepted).NotTo(BeNil())
Expect(accepted.Status).To(Equal(metav1.ConditionFalse))
Expect(accepted.Reason).To(BeEquivalentTo(gwv1.RouteReasonIncompatibleFilters))
By("verifying the route was resolved correctly")
resolvedRefs := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionResolvedRefs))
Expect(resolvedRefs).NotTo(BeNil())
Expect(resolvedRefs.Status).To(Equal(metav1.ConditionFalse))
Expect(resolvedRefs.Reason).To(BeEquivalentTo(gwv1.RouteReasonIncompatibleFilters))
Expect(resolvedRefs.Status).To(Equal(metav1.ConditionTrue))
Expect(resolvedRefs.Reason).To(BeEquivalentTo(gwv1.RouteReasonResolvedRefs))
})
})

Expand Down Expand Up @@ -478,10 +526,16 @@ var _ = Describe("GatewayHttpRouteTranslator", func() {
routeStatus := reportsMap.BuildRouteStatus(ctx, route, "")
Expect(routeStatus).NotTo(BeNil())
Expect(routeStatus.Parents).To(HaveLen(1))
resolvedRefs := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionAccepted))
By("verifying the route was accepted")
accepted := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionAccepted))
Expect(accepted).NotTo(BeNil())
Expect(accepted.Status).To(Equal(metav1.ConditionTrue))
Expect(accepted.Reason).To(BeEquivalentTo(gwv1.RouteReasonAccepted))
By("verifying the route was resolved correctly")
resolvedRefs := meta.FindStatusCondition(routeStatus.Parents[0].Conditions, string(gwv1.RouteConditionResolvedRefs))
Expect(resolvedRefs).NotTo(BeNil())
Expect(resolvedRefs.Status).To(Equal(metav1.ConditionTrue))
Expect(resolvedRefs.Reason).To(BeEquivalentTo(gwv1.RouteReasonAccepted))
Expect(resolvedRefs.Reason).To(BeEquivalentTo(gwv1.RouteReasonResolvedRefs))
})
})
})
Expand Down
Loading
Loading