Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 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
8 changes: 2 additions & 6 deletions api/v1alpha1/httproutepolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ type HTTPRoutePolicySpec struct {
// TargetRef identifies an API object (enum: HTTPRoute, Ingress) to apply HTTPRoutePolicy to.
//
// target references.
// +listType=map
// +listMapKey=group
// +listMapKey=kind
// +listMapKey=name
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=16
TargetRefs []gatewayv1alpha2.LocalPolicyTargetReferenceWithSectionName `json:"targetRefs"`
Expand All @@ -47,8 +43,8 @@ type HTTPRoutePolicy struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec HTTPRoutePolicySpec `json:"spec,omitempty"`
Status gatewayv1alpha2.PolicyStatus `json:"status,omitempty"`
Spec HTTPRoutePolicySpec `json:"spec,omitempty"`
Status PolicyStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down
2 changes: 1 addition & 1 deletion charts/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ nameOverride: ""
labelsOverride: {}
annotations: {}
podAnnotations: {}
controllerName: gateway.api7.io/api7-ingress-controller
controllerName: gateway.apisix.io/api7-ingress-controller
replicas: 1
admin:
key: '' # Pass the admin key generated for the ingress gateway group
Expand Down
5 changes: 0 additions & 5 deletions config/crd/bases/gateway.apisix.io_httproutepolicies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,6 @@ spec:
maxItems: 16
minItems: 1
type: array
x-kubernetes-list-map-keys:
- group
- kind
- name
x-kubernetes-list-type: map
vars:
items:
x-kubernetes-preserve-unknown-fields: true
Expand Down
2 changes: 1 addition & 1 deletion config/samples/config.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
log_level: "debug" # The log level of the API7 Ingress Controller.
# the default value is "info".

controller_name: gateway.api7.io/api7-ingress-controller # The controller name of the API7 Ingress Controller,
controller_name: gateway.apisix.io/api7-ingress-controller # The controller name of the API7 Ingress Controller,
# which is used to identify the controller in the GatewayClass.
# The default value is "gateway.api7.io/api7-ingress-controller".
leader_election_id: "api7-ingress-controller-leader" # The leader election ID for the API7 Ingress Controller.
Expand Down
2 changes: 1 addition & 1 deletion docs/configure.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The API7 Ingress Controller is a Kubernetes Ingress Controller that implements t
log_level: "info" # The log level of the API7 Ingress Controller.
# the default value is "info".

controller_name: gateway.api7.io/api7-ingress-controller # The controller name of the API7 Ingress Controller,
controller_name: gateway.apisix.io/api7-ingress-controller # The controller name of the API7 Ingress Controller,
# which is used to identify the controller in the GatewayClass.
# The default value is "gateway.api7.io/api7-ingress-controller".

Expand Down
139 changes: 137 additions & 2 deletions internal/controller/httproute_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

"github.com/go-logr/logr"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -18,7 +19,9 @@ import (
"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"
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
"sigs.k8s.io/gateway-api/apis/v1alpha2"

"github.com/api7/api7-ingress-controller/api/v1alpha1"
"github.com/api7/api7-ingress-controller/internal/controller/indexer"
Expand All @@ -33,10 +36,14 @@ type HTTPRouteReconciler struct { //nolint:revive
Log logr.Logger

Provider provider.Provider

genericEvent chan event.GenericEvent
}

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

return ctrl.NewControllerManagedBy(mgr).
For(&gatewayv1.HTTPRoute{}).
WithEventFilter(predicate.GenerationChangedPredicate{}).
Expand Down Expand Up @@ -65,6 +72,29 @@ func (r *HTTPRouteReconciler) SetupWithManager(mgr ctrl.Manager) error {
},
),
).
Watches(&v1alpha1.HTTPRoutePolicy{},
handler.EnqueueRequestsFromMapFunc(r.listHTTPRouteByHTTPRoutePolicy),
builder.WithPredicates(
predicate.Funcs{
CreateFunc: func(e event.CreateEvent) bool {
return true
},
DeleteFunc: func(e event.DeleteEvent) bool {
return true
},
UpdateFunc: r.httpRoutePolicyPredicateOnUpdate,
GenericFunc: func(e event.GenericEvent) bool {
return false
},
},
),
).
WatchesRawSource(
source.Channel(
r.genericEvent,
handler.EnqueueRequestsFromMapFunc(r.listHTTPRouteForGenericEvent),
),
).
Complete(r)
}

Expand Down Expand Up @@ -131,6 +161,11 @@ func (r *HTTPRouteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
acceptStatus.msg = err.Error()
}

if err := r.processHTTPRoutePolicies(tctx, hr); err != nil {
acceptStatus.status = false
acceptStatus.msg = err.Error()
}

if err := r.processHTTPRouteBackendRefs(tctx); err != nil {
resolveRefStatus = status{
status: false,
Expand Down Expand Up @@ -161,6 +196,7 @@ func (r *HTTPRouteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
if err := r.Status().Update(ctx, hr); err != nil {
return ctrl.Result{}, err
}
UpdateStatus(r.Client, r.Log, tctx)
return ctrl.Result{}, nil
}

Expand Down Expand Up @@ -244,6 +280,79 @@ func (r *HTTPRouteReconciler) listHTTPRoutesForGateway(ctx context.Context, obj
return requests
}

func (r *HTTPRouteReconciler) listHTTPRouteByHTTPRoutePolicy(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 != "HTTPRoute" {
continue
}
key := types.NamespacedName{
Namespace: obj.GetNamespace(),
Name: string(ref.Name),
}
if _, ok := keys[key]; ok {
continue
}

var httpRoute gatewayv1.HTTPRoute
if err := r.Get(ctx, client.ObjectKey{Namespace: key.Namespace, Name: key.Name}, &httpRoute); err != nil {
r.Log.Error(err, "failed to get HTTPRoute by HTTPRoutePolicy targetRef", "namespace", key.Namespace, "name", key.Name)
continue
}
if ref.SectionName != nil {
var matchRuleName bool
for _, rule := range httpRoute.Spec.Rules {
if rule.Name != nil && *rule.Name == *ref.SectionName {
matchRuleName = true
break
}
}
if !matchRuleName {
r.Log.Error(errors.Errorf("failed to get HTTPRoute rule by HTTPRoutePolicy targetRef"), "namespace", key.Namespace, "name", key.Name, "sectionName", *ref.SectionName)
continue
}
}
keys[key] = struct{}{}
requests = append(requests, reconcile.Request{
NamespacedName: types.NamespacedName{
Namespace: key.Namespace,
Name: key.Name,
},
})
}

return requests
}

func (r *HTTPRouteReconciler) listHTTPRouteForGenericEvent(ctx context.Context, obj client.Object) []reconcile.Request {
switch v := obj.(type) {
case *v1alpha1.HTTPRoutePolicy:
var (
namespacedNames = make(map[types.NamespacedName]struct{})
requests []reconcile.Request
)
for _, ref := range v.Spec.TargetRefs {
namespacedName := types.NamespacedName{Namespace: v.GetNamespace(), Name: string(ref.Name)}
if _, ok := namespacedNames[namespacedName]; !ok {
namespacedNames[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)
continue
}
requests = append(requests, reconcile.Request{NamespacedName: namespacedName})
}
}
return requests
}
return nil
}

func (r *HTTPRouteReconciler) processHTTPRouteBackendRefs(tctx *provider.TranslateContext) error {
var terr error
for _, backend := range tctx.BackendRefs {
Expand Down Expand Up @@ -306,7 +415,7 @@ func (r *HTTPRouteReconciler) processHTTPRouteBackendRefs(tctx *provider.Transla
return terr
}

func (t *HTTPRouteReconciler) processHTTPRoute(tctx *provider.TranslateContext, httpRoute *gatewayv1.HTTPRoute) error {
func (r *HTTPRouteReconciler) processHTTPRoute(tctx *provider.TranslateContext, httpRoute *gatewayv1.HTTPRoute) error {
var terror error
for _, rule := range httpRoute.Spec.Rules {
for _, filter := range rule.Filters {
Expand All @@ -315,7 +424,7 @@ func (t *HTTPRouteReconciler) processHTTPRoute(tctx *provider.TranslateContext,
}
if filter.ExtensionRef.Kind == "PluginConfig" {
pluginconfig := new(v1alpha1.PluginConfig)
if err := t.Get(context.Background(), client.ObjectKey{
if err := r.Get(context.Background(), client.ObjectKey{
Namespace: httpRoute.GetNamespace(),
Name: string(filter.ExtensionRef.Name),
}, pluginconfig); err != nil {
Expand Down Expand Up @@ -360,3 +469,29 @@ func (t *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)
}
r.genericEvent <- event.GenericEvent{Object: dump}
}
return true
}
Loading
Loading