Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
67 changes: 35 additions & 32 deletions internal/controller/httproute_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func (r *HTTPRouteReconciler) SetupWithManager(mgr ctrl.Manager) error {
DeleteFunc: func(e event.DeleteEvent) bool {
return true
},
UpdateFunc: r.httpRoutePolicyPredicateOnUpdate,
UpdateFunc: httpRoutePolicyPredicateOnUpdate(r.genericEvent, "HTTPRoute"),
GenericFunc: func(e event.GenericEvent) bool {
return false
},
Expand Down Expand Up @@ -400,7 +400,7 @@ func (r *HTTPRouteReconciler) listHTTPRouteByHTTPRoutePolicy(ctx context.Context
}

var httpRoute gatewayv1.HTTPRoute
if err := r.Get(ctx, client.ObjectKey{Namespace: key.Namespace, Name: key.Name}, &httpRoute); err != nil {
if err := r.Get(ctx, key, &httpRoute); err != nil {
r.Log.Error(err, "failed to get HTTPRoute by HTTPRoutePolicy targetRef", "namespace", key.Namespace, "name", key.Name)
continue
}
Expand All @@ -418,12 +418,7 @@ func (r *HTTPRouteReconciler) listHTTPRouteByHTTPRoutePolicy(ctx context.Context
}
}
keys[key] = struct{}{}
requests = append(requests, reconcile.Request{
NamespacedName: types.NamespacedName{
Namespace: key.Namespace,
Name: key.Name,
},
})
requests = append(requests, reconcile.Request{NamespacedName: key})
}

return requests
Expand Down Expand Up @@ -466,14 +461,14 @@ func (r *HTTPRouteReconciler) listHTTPRouteForGenericEvent(ctx context.Context,
if _, ok := namespacedNameMap[namespacedName]; !ok {
namespacedNameMap[namespacedName] = struct{}{}
if err := r.Get(ctx, namespacedName, new(gatewayv1.HTTPRoute)); err != nil {
r.Log.Info("failed to Get HTTPRoute", "namespace", namespacedName.Namespace, "name", namespacedName.Name)
r.Log.Error(err, "failed to Get HTTPRoute", "namespace", namespacedName.Namespace, "name", namespacedName.Name)
continue
}
requests = append(requests, reconcile.Request{NamespacedName: namespacedName})
}
}
default:
r.Log.Error(fmt.Errorf("unexpected object type"), "failed to convert object to BackendTrafficPolicy")
r.Log.Error(fmt.Errorf("unexpected object type"), "failed to convert object to BackendTrafficPolicy or HTTPRoutePolicy")
}
return requests
}
Expand Down Expand Up @@ -595,28 +590,36 @@ func (r *HTTPRouteReconciler) processHTTPRoute(tctx *provider.TranslateContext,
return terror
}

func (r *HTTPRouteReconciler) httpRoutePolicyPredicateOnUpdate(e event.UpdateEvent) bool {
oldPolicy, ok0 := e.ObjectOld.(*v1alpha1.HTTPRoutePolicy)
newPolicy, ok1 := e.ObjectNew.(*v1alpha1.HTTPRoutePolicy)
if !ok0 || !ok1 {
return false
}
var discardsRefs = make(map[string]v1alpha2.LocalPolicyTargetReferenceWithSectionName)
for _, ref := range oldPolicy.Spec.TargetRefs {
key := indexer.GenHTTPRoutePolicyIndexKey(string(ref.Group), string(ref.Kind), e.ObjectOld.GetNamespace(), string(ref.Name), "")
discardsRefs[key] = ref
}
for _, ref := range newPolicy.Spec.TargetRefs {
key := indexer.GenHTTPRoutePolicyIndexKey(string(ref.Group), string(ref.Kind), e.ObjectOld.GetNamespace(), string(ref.Name), "")
delete(discardsRefs, key)
}
if len(discardsRefs) > 0 {
dump := oldPolicy.DeepCopy()
dump.Spec.TargetRefs = make([]v1alpha2.LocalPolicyTargetReferenceWithSectionName, 0, len(discardsRefs))
for _, ref := range discardsRefs {
dump.Spec.TargetRefs = append(dump.Spec.TargetRefs, ref)
func httpRoutePolicyPredicateOnUpdate(c chan event.GenericEvent, kind string) func(e event.UpdateEvent) bool {
return func(e event.UpdateEvent) bool {
oldPolicy, ok0 := e.ObjectOld.(*v1alpha1.HTTPRoutePolicy)
newPolicy, ok1 := e.ObjectNew.(*v1alpha1.HTTPRoutePolicy)
if !ok0 || !ok1 {
return false
}
var discardsRefs = make(map[string]v1alpha2.LocalPolicyTargetReferenceWithSectionName)
for _, ref := range oldPolicy.Spec.TargetRefs {
if string(ref.Kind) != kind {
continue
}
key := indexer.GenHTTPRoutePolicyIndexKey(string(ref.Group), string(ref.Kind), e.ObjectOld.GetNamespace(), string(ref.Name), "")
discardsRefs[key] = ref
}
for _, ref := range newPolicy.Spec.TargetRefs {
if string(ref.Kind) != kind {
continue
}
key := indexer.GenHTTPRoutePolicyIndexKey(string(ref.Group), string(ref.Kind), e.ObjectOld.GetNamespace(), string(ref.Name), "")
delete(discardsRefs, key)
}
if len(discardsRefs) > 0 {
dump := oldPolicy.DeepCopy()
dump.Spec.TargetRefs = make([]v1alpha2.LocalPolicyTargetReferenceWithSectionName, 0, len(discardsRefs))
for _, ref := range discardsRefs {
dump.Spec.TargetRefs = append(dump.Spec.TargetRefs, ref)
}
c <- event.GenericEvent{Object: dump}
}
r.genericEvent <- event.GenericEvent{Object: dump}
return true
}
return true
}
44 changes: 37 additions & 7 deletions internal/controller/httproutepolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"time"

networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -19,8 +20,8 @@ func (r *HTTPRouteReconciler) processHTTPRoutePolicies(tctx *provider.TranslateC
// list HTTPRoutePolices which sectionName is not specified
var (
checker = conflictChecker{
httpRoute: httpRoute,
policies: make(map[targetRefKey][]v1alpha1.HTTPRoutePolicy),
object: httpRoute,
policies: make(map[targetRefKey][]v1alpha1.HTTPRoutePolicy),
}
listForAllRules v1alpha1.HTTPRoutePolicyList
key = indexer.GenHTTPRoutePolicyIndexKey(gatewayv1.GroupName, "HTTPRoute", httpRoute.GetNamespace(), httpRoute.GetName(), "")
Expand Down Expand Up @@ -111,10 +112,39 @@ func (r *HTTPRouteReconciler) modifyHTTPRoutePolicyStatus(httpRoute *gatewayv1.H
_ = SetAncestors(&policy.Status, httpRoute.Spec.ParentRefs, condition)
}

func (r *IngressReconciler) processHTTPRoutePolicies(tctx *provider.TranslateContext, ingress *networkingv1.Ingress) error {
var (
checker = conflictChecker{
object: ingress,
policies: make(map[targetRefKey][]v1alpha1.HTTPRoutePolicy),
conflict: false,
}
list v1alpha1.HTTPRoutePolicyList
key = indexer.GenHTTPRoutePolicyIndexKey(networkingv1.GroupName, "Ingress", ingress.GetNamespace(), ingress.GetName(), "")
)
if err := r.List(context.Background(), &list, client.MatchingFields{indexer.PolicyTargetRefs: key}); err != nil {
return err
}

for _, item := range list.Items {
checker.append("", item)
tctx.HTTPRoutePolicies["*"] = append(tctx.HTTPRoutePolicies["*"], item)
}

if checker.conflict {
// clear HTTPRoutePolicies from TranslateContext
tctx.HTTPRoutePolicies = make(map[string][]v1alpha1.HTTPRoutePolicy)
}

// todo: handle HTTPRoutePolicy status

return nil
}

type conflictChecker struct {
httpRoute *gatewayv1.HTTPRoute
policies map[targetRefKey][]v1alpha1.HTTPRoutePolicy
conflict bool
object client.Object
policies map[targetRefKey][]v1alpha1.HTTPRoutePolicy
conflict bool
}

type targetRefKey struct {
Expand All @@ -127,8 +157,8 @@ type targetRefKey struct {
func (c *conflictChecker) append(sectionName string, policy v1alpha1.HTTPRoutePolicy) {
key := targetRefKey{
Group: gatewayv1.GroupName,
Namespace: gatewayv1.Namespace(c.httpRoute.GetNamespace()),
Name: gatewayv1.ObjectName(c.httpRoute.GetName()),
Namespace: gatewayv1.Namespace(c.object.GetNamespace()),
Name: gatewayv1.ObjectName(c.object.GetName()),
SectionName: gatewayv1.SectionName(sectionName),
}
c.policies[key] = append(c.policies[key], policy)
Expand Down
15 changes: 15 additions & 0 deletions internal/controller/indexer/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
IngressClassRef = "ingressClassRef"
ConsumerGatewayRef = "consumerGatewayRef"
PolicyTargetRefs = "targetRefs"
PolicyTargetRefIng = "targetRefIng"
)

func SetupIndexer(mgr ctrl.Manager) error {
Expand Down Expand Up @@ -189,6 +190,16 @@ func setupIngressIndexer(mgr ctrl.Manager) error {
return err
}

// create HTTPRoutePolicy index
if err := mgr.GetFieldIndexer().IndexField(
context.Background(),
&v1alpha1.HTTPRoutePolicy{},
PolicyTargetRefIng,
IngressHTTPRouteIndexFunc,
); err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -256,6 +267,10 @@ func IngressSecretIndexFunc(rawObj client.Object) []string {
return secrets
}

func IngressHTTPRouteIndexFunc(rawObj client.Object) []string {
return []string{GenHTTPRoutePolicyIndexKey(networkingv1.GroupName, "Ingress", rawObj.GetNamespace(), rawObj.GetName(), "")}
}

func GenIndexKeyWithGK(group, kind, namespace, name string) string {
gvk := schema.GroupKind{
Group: group,
Expand Down
100 changes: 95 additions & 5 deletions internal/controller/ingress_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ import (
"fmt"
"reflect"

"github.com/api7/api7-ingress-controller/api/v1alpha1"
"github.com/api7/api7-ingress-controller/internal/controller/config"
"github.com/api7/api7-ingress-controller/internal/controller/indexer"
"github.com/api7/api7-ingress-controller/internal/provider"
"github.com/api7/gopkg/pkg/log"
"github.com/go-logr/logr"
"go.uber.org/zap"
corev1 "k8s.io/api/core/v1"
Expand All @@ -22,9 +17,17 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/controller-runtime/pkg/source"

"github.com/api7/api7-ingress-controller/api/v1alpha1"
"github.com/api7/api7-ingress-controller/internal/controller/config"
"github.com/api7/api7-ingress-controller/internal/controller/indexer"
"github.com/api7/api7-ingress-controller/internal/provider"
"github.com/api7/gopkg/pkg/log"
)

// IngressReconciler reconciles a Ingress object.
Expand All @@ -34,10 +37,14 @@ type IngressReconciler struct { //nolint:revive
Log logr.Logger

Provider provider.Provider

genericEvent chan event.GenericEvent
}

// SetupWithManager sets up the controller with the Manager.
func (r *IngressReconciler) SetupWithManager(mgr ctrl.Manager) error {
r.genericEvent = make(chan event.GenericEvent, 100)

return ctrl.NewControllerManagedBy(mgr).
For(&networkingv1.Ingress{},
builder.WithPredicates(
Expand Down Expand Up @@ -65,6 +72,29 @@ func (r *IngressReconciler) SetupWithManager(mgr ctrl.Manager) error {
&corev1.Secret{},
handler.EnqueueRequestsFromMapFunc(r.listIngressesBySecret),
).
Watches(&v1alpha1.HTTPRoutePolicy{},
handler.EnqueueRequestsFromMapFunc(r.listIngressesByHTTPRoutePolicy),
builder.WithPredicates(
predicate.Funcs{
CreateFunc: func(e event.CreateEvent) bool {
return true
},
DeleteFunc: func(e event.DeleteEvent) bool {
return true
},
UpdateFunc: httpRoutePolicyPredicateOnUpdate(r.genericEvent, "Ingress"),
GenericFunc: func(e event.GenericEvent) bool {
return false
},
},
),
).
WatchesRawSource(
source.Channel(
r.genericEvent,
handler.EnqueueRequestsFromMapFunc(r.listIngressesForGenericEvent),
),
).
Complete(r)
}

Expand Down Expand Up @@ -121,6 +151,12 @@ func (r *IngressReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl.Result{}, err
}

// process HTTPRoutePolicy
if err := r.processHTTPRoutePolicies(tctx, ingress); err != nil {
r.Log.Error(err, "failed to process HTTPRoutePolicy", "ingress", ingress.Name)
return ctrl.Result{}, err
}

// update the ingress resources
if err := r.Provider.Update(ctx, tctx, ingress); err != nil {
r.Log.Error(err, "failed to update ingress resources", "ingress", ingress.Name)
Expand Down Expand Up @@ -341,6 +377,60 @@ func (r *IngressReconciler) listIngressesBySecret(ctx context.Context, obj clien
return requests
}

func (r *IngressReconciler) listIngressesByHTTPRoutePolicy(ctx context.Context, obj client.Object) (requests []reconcile.Request) {
httpRoutePolicy, ok := obj.(*v1alpha1.HTTPRoutePolicy)
if !ok {
r.Log.Error(fmt.Errorf("unexpected object type"), "failed to convert object to HTTPRoutePolicy")
return nil
}

var keys = make(map[types.NamespacedName]struct{})
for _, ref := range httpRoutePolicy.Spec.TargetRefs {
if ref.Kind != "Ingress" {
continue
}
key := types.NamespacedName{
Namespace: obj.GetNamespace(),
Name: string(ref.Name),
}
if _, ok := keys[key]; ok {
continue
}

var ingress networkingv1.Ingress
if err := r.Get(ctx, key, &ingress); err != nil {
r.Log.Error(err, "failed to get Ingress By HTTPRoutePolicy targetRef", "namespace", key.Namespace, "name", key.Name)
continue
}
keys[key] = struct{}{}
requests = append(requests, reconcile.Request{NamespacedName: key})
}
return
}

func (r *IngressReconciler) listIngressesForGenericEvent(ctx context.Context, obj client.Object) (requests []reconcile.Request) {
var namespacedNameMap = make(map[types.NamespacedName]struct{})

switch v := obj.(type) {
case *v1alpha1.HTTPRoutePolicy:
for _, ref := range v.Spec.TargetRefs {
namespacedName := types.NamespacedName{Namespace: v.GetNamespace(), Name: string(ref.Name)}
if _, ok := namespacedNameMap[namespacedName]; !ok {
namespacedNameMap[namespacedName] = struct{}{}
if err := r.Get(ctx, namespacedName, new(networkingv1.Ingress)); err != nil {
r.Log.Error(err, "failed to Get Ingress", "namespace", namespacedName.Namespace, "name", namespacedName.Name)
continue
}
requests = append(requests, reconcile.Request{NamespacedName: namespacedName})
}
}
default:
r.Log.Error(fmt.Errorf("unexpected object type"), "failed to convert object to HTTPRoutePolicy")
}

return
}

// processTLS process the TLS configuration of the ingress
func (r *IngressReconciler) processTLS(tctx *provider.TranslateContext, ingress *networkingv1.Ingress) error {
for _, tls := range ingress.Spec.TLS {
Expand Down
Loading
Loading