Skip to content

Commit 1ad0626

Browse files
committed
conflicts
1 parent 4aafb68 commit 1ad0626

File tree

4 files changed

+196
-59
lines changed

4 files changed

+196
-59
lines changed

internal/controller/httproute_controller.go

Lines changed: 32 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ import (
55
"fmt"
66
"strings"
77

8-
"github.com/api7/api7-ingress-controller/internal/controller/config"
8+
"github.com/api7/api7-ingress-controller/api/v1alpha1"
9+
"github.com/api7/api7-ingress-controller/internal/controller/indexer"
10+
"github.com/api7/api7-ingress-controller/internal/provider"
911
"github.com/go-logr/logr"
1012
corev1 "k8s.io/api/core/v1"
1113
discoveryv1 "k8s.io/api/discovery/v1"
12-
"k8s.io/apimachinery/pkg/api/meta"
1314
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1415
"k8s.io/apimachinery/pkg/runtime"
1516
"k8s.io/apimachinery/pkg/types"
@@ -22,10 +23,6 @@ import (
2223
"sigs.k8s.io/controller-runtime/pkg/reconcile"
2324
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
2425
"sigs.k8s.io/gateway-api/apis/v1alpha2"
25-
26-
"github.com/api7/api7-ingress-controller/api/v1alpha1"
27-
"github.com/api7/api7-ingress-controller/internal/controller/indexer"
28-
"github.com/api7/api7-ingress-controller/internal/provider"
2926
)
3027

3128
// HTTPRouteReconciler reconciles a GatewayClass object.
@@ -125,6 +122,11 @@ func (r *HTTPRouteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
125122
acceptStatus.msg = err.Error()
126123
}
127124

125+
if err := r.processHTTPRoutePolicies(tctx, hr); err != nil {
126+
acceptStatus.status = false
127+
acceptStatus.msg = err.Error()
128+
}
129+
128130
if err := r.processHTTPRouteBackendRefs(tctx); err != nil {
129131
resolveRefStatus = status{
130132
status: false,
@@ -245,26 +247,42 @@ func (r *HTTPRouteReconciler) listHTTPRouteByHTTPRoutePolicy(ctx context.Context
245247
return nil
246248
}
247249

248-
var keys = make(map[client.ObjectKey]struct{})
250+
var keys = make(map[ancestorRefKey]struct{})
249251
for _, ref := range httpRoutePolicy.Spec.TargetRefs {
250252
if ref.Kind == "HTTPRoute" {
251-
keys[client.ObjectKey{
252-
Namespace: obj.GetNamespace(),
253-
Name: string(ref.Name),
254-
}] = struct{}{}
253+
key := ancestorRefKey{
254+
Group: gatewayv1.GroupName,
255+
Kind: "HTTPRoute",
256+
Namespace: gatewayv1.Namespace(obj.GetNamespace()),
257+
Name: ref.Name,
258+
}
259+
if ref.SectionName != nil {
260+
key.SectionName = *ref.SectionName
261+
}
262+
keys[key] = struct{}{}
255263
}
256264
}
257265
for key := range keys {
258266
var httpRoute gatewayv1.HTTPRoute
259-
if err := r.Get(ctx, key, &httpRoute); err != nil {
260-
r.Log.Error(err, "failed to get httproute by HTTPRoutePolicy targetRef", "HTTPRoutePolicy", obj.GetName())
267+
if err := r.Get(ctx, client.ObjectKey{Namespace: string(key.Namespace), Name: string(key.Name)}, &httpRoute); err != nil {
268+
r.Log.Error(err, "failed to get httproute by HTTPRoutePolicy targetRef", "namespace", obj.GetNamespace(), "name", obj.GetName())
269+
if err := r.updateHTTPRoutePolicyStatus(key, *httpRoutePolicy, false, string(v1alpha2.PolicyReasonTargetNotFound), "not found HTTPRoute"); err != nil {
270+
r.Log.Error(err, "failed to update HTTPRoutePolicy Status")
271+
}
261272
continue
262273
}
263274
requests = append(requests, reconcile.Request{
264-
NamespacedName: key,
275+
NamespacedName: types.NamespacedName{
276+
Namespace: string(key.Namespace),
277+
Name: string(key.Name),
278+
},
265279
})
266280
}
267281

282+
if err := r.Status().Update(ctx, httpRoutePolicy); err != nil {
283+
r.Log.Error(err, "failed to update HTTPRoutePolicy status", "namespace", obj.GetNamespace(), "name", obj.GetName())
284+
}
285+
268286
return requests
269287
}
270288

@@ -376,38 +394,6 @@ func (r *HTTPRouteReconciler) processHTTPRoute(tctx *provider.TranslateContext,
376394
},
377395
})
378396
}
379-
380-
var httpRoutePolicyList v1alpha1.HTTPRoutePolicyList
381-
var ruleName string
382-
if rule.Name != nil {
383-
ruleName = string(*rule.Name)
384-
}
385-
key := indexer.GenHTTPRoutePolicyIndexKey(v1alpha1.GroupVersion.Group, "HTTPRoute", httpRoute.GetNamespace(), httpRoute.GetName(), ruleName)
386-
if err := r.List(context.Background(), &httpRoutePolicyList, client.MatchingFields{indexer.HTTPRoutePolicy: key}); err != nil {
387-
terror = err
388-
continue
389-
}
390-
for _, item := range httpRoutePolicyList.Items {
391-
tctx.HTTPRoutePolicies[ruleName] = append(tctx.HTTPRoutePolicies[key], item.Spec)
392-
item.Status.Ancestors = []v1alpha2.PolicyAncestorStatus{
393-
{
394-
AncestorRef: v1alpha2.ParentReference{
395-
Group: nil,
396-
Kind: nil,
397-
Namespace: nil,
398-
Name: gatewayv1.ObjectName(httpRoute.GetName()),
399-
SectionName: nil,
400-
Port: nil,
401-
},
402-
ControllerName: v1alpha2.GatewayController(config.GetControllerName()),
403-
Conditions: []metav1.Condition{},
404-
},
405-
}
406-
meta.SetStatusCondition(&item.Status.Ancestors[0].Conditions, NewCondition(item.Generation, true, "Successfully"))
407-
if err := r.Status().Update(context.Background(), &item); err != nil {
408-
r.Log.Error(err, "failed to Update policy status")
409-
}
410-
}
411397
}
412398

413399
return terror
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package controller
2+
3+
import (
4+
"context"
5+
"time"
6+
7+
"github.com/api7/api7-ingress-controller/api/v1alpha1"
8+
"github.com/api7/api7-ingress-controller/internal/controller/config"
9+
"github.com/api7/api7-ingress-controller/internal/controller/indexer"
10+
"github.com/api7/api7-ingress-controller/internal/provider"
11+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12+
"sigs.k8s.io/controller-runtime/pkg/client"
13+
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
14+
"sigs.k8s.io/gateway-api/apis/v1alpha2"
15+
)
16+
17+
func (r *HTTPRouteReconciler) processHTTPRoutePolicies(tctx *provider.TranslateContext, httpRoute *gatewayv1.HTTPRoute) error {
18+
// list HTTPRoutePolices which sectionName is not specified
19+
var (
20+
checker = conflictChecker{
21+
httpRoute: httpRoute,
22+
policies: make(map[ancestorRefKey][]v1alpha1.HTTPRoutePolicy),
23+
}
24+
listForAllRules v1alpha1.HTTPRoutePolicyList
25+
key = indexer.GenHTTPRoutePolicyIndexKey(v1alpha1.GroupVersion.Group, "HTTPRoute", httpRoute.GetNamespace(), httpRoute.GetName(), "")
26+
)
27+
if err := r.List(context.Background(), &listForAllRules, client.MatchingFields{indexer.HTTPRoutePolicy: key}); err != nil {
28+
return err
29+
}
30+
31+
for _, item := range listForAllRules.Items {
32+
checker.append("", item)
33+
tctx.HTTPRoutePolicies["*"] = append(tctx.HTTPRoutePolicies["*"], item)
34+
}
35+
36+
for _, rule := range httpRoute.Spec.Rules {
37+
if rule.Name == nil {
38+
continue
39+
}
40+
41+
var (
42+
ruleName = string(*rule.Name)
43+
listForSectionRules v1alpha1.HTTPRoutePolicyList
44+
key = indexer.GenHTTPRoutePolicyIndexKey(v1alpha1.GroupVersion.Group, "HTTPRoute", httpRoute.GetNamespace(), httpRoute.GetName(), ruleName)
45+
)
46+
if err := r.List(context.Background(), &listForSectionRules, client.MatchingFields{indexer.HTTPRoutePolicy: key}); err != nil {
47+
continue
48+
}
49+
for _, item := range listForSectionRules.Items {
50+
checker.append(ruleName, item)
51+
tctx.HTTPRoutePolicies[ruleName] = append(tctx.HTTPRoutePolicies[ruleName], item)
52+
}
53+
}
54+
55+
var (
56+
status = true
57+
reason = string(v1alpha2.PolicyReasonAccepted)
58+
message string
59+
)
60+
if checker.conflict {
61+
status = false
62+
reason = string(v1alpha2.PolicyReasonConflicted)
63+
message = "HTTPRoutePolicy conflict with others target to the HTTPRoute"
64+
65+
// clear HTTPRoutePolices from TranslateContext
66+
tctx.HTTPRoutePolicies = make(map[string][]v1alpha1.HTTPRoutePolicy)
67+
}
68+
69+
for key, policies := range checker.policies {
70+
for _, policy := range policies {
71+
if err := r.updateHTTPRoutePolicyStatus(key, policy, status, reason, message); err != nil {
72+
r.Log.Error(err, "failed to update HTTPRoutePolicyStatus")
73+
}
74+
}
75+
}
76+
77+
return nil
78+
}
79+
80+
func (r *HTTPRouteReconciler) updateHTTPRoutePolicyStatus(key ancestorRefKey, policy v1alpha1.HTTPRoutePolicy, status bool, reason, message string) error {
81+
condition := metav1.Condition{
82+
Type: string(v1alpha2.PolicyConditionAccepted),
83+
Status: metav1.ConditionTrue,
84+
ObservedGeneration: policy.GetGeneration(),
85+
LastTransitionTime: metav1.Time{Time: time.Now()},
86+
Reason: reason,
87+
Message: message,
88+
}
89+
if !status {
90+
condition.Status = metav1.ConditionFalse
91+
}
92+
var hasAncestor bool
93+
for _, ancestor := range policy.Status.Ancestors {
94+
if ancestor.AncestorRef.Kind != nil && *ancestor.AncestorRef.Kind == key.Kind && ancestor.AncestorRef.Name == key.Name {
95+
ancestor.ControllerName = v1alpha2.GatewayController(config.GetControllerName())
96+
ancestor.Conditions = []metav1.Condition{condition}
97+
hasAncestor = true
98+
}
99+
}
100+
if !hasAncestor {
101+
ref := v1alpha2.ParentReference{
102+
Group: &key.Group,
103+
Kind: &key.Kind,
104+
Namespace: &key.Namespace,
105+
Name: key.Name,
106+
}
107+
if key.SectionName != "" {
108+
ref.SectionName = &key.SectionName
109+
}
110+
policy.Status.Ancestors = append(policy.Status.Ancestors, v1alpha2.PolicyAncestorStatus{
111+
AncestorRef: ref,
112+
ControllerName: v1alpha2.GatewayController(config.GetControllerName()),
113+
Conditions: []metav1.Condition{condition},
114+
})
115+
}
116+
return r.Status().Update(context.Background(), &policy)
117+
}
118+
119+
type conflictChecker struct {
120+
httpRoute *gatewayv1.HTTPRoute
121+
policies map[ancestorRefKey][]v1alpha1.HTTPRoutePolicy
122+
conflict bool
123+
}
124+
125+
type ancestorRefKey struct {
126+
Group gatewayv1.Group
127+
Kind gatewayv1.Kind
128+
Namespace gatewayv1.Namespace
129+
Name gatewayv1.ObjectName
130+
SectionName gatewayv1.SectionName
131+
}
132+
133+
func (c *conflictChecker) append(sectionName string, policy v1alpha1.HTTPRoutePolicy) {
134+
key := ancestorRefKey{
135+
Group: gatewayv1.GroupName,
136+
Kind: "HTTPRoute",
137+
Namespace: gatewayv1.Namespace(c.httpRoute.GetNamespace()),
138+
Name: gatewayv1.ObjectName(c.httpRoute.GetName()),
139+
SectionName: gatewayv1.SectionName(sectionName),
140+
}
141+
c.policies[key] = append(c.policies[key], policy)
142+
143+
if !c.conflict {
144+
Loop:
145+
for _, items := range c.policies {
146+
for _, item := range items {
147+
if item.Spec.Priority != policy.Spec.Priority || *item.Spec.Priority != *policy.Spec.Priority {
148+
c.conflict = true
149+
break Loop
150+
}
151+
}
152+
}
153+
}
154+
}

internal/provider/adc/translator/httproute.go

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -231,21 +231,18 @@ func (t *Translator) fillPluginFromHTTPRequestRedirectFilter(plugins adctypes.Pl
231231
}
232232

233233
func (t *Translator) fillHTTPRoutePolicies(tctx *provider.TranslateContext, rule gatewayv1.HTTPRouteRule, routes []*adctypes.Route) {
234-
var ruleName string
234+
policies := tctx.HTTPRoutePolicies["*"] // policies which not specify a sectionName
235235
if rule.Name != nil {
236-
ruleName = string(*rule.Name)
236+
policies = append(policies, tctx.HTTPRoutePolicies[string(*rule.Name)]...) // append policies which specify the sectionName as the same as rule.name
237237
}
238-
specs, ok := tctx.HTTPRoutePolicies[ruleName]
239-
if !ok || len(specs) == 0 {
240-
return
241-
}
242-
for _, route := range routes {
243-
for _, spec := range specs {
244-
route.Priority = spec.Priority
245-
for _, data := range spec.Vars {
238+
239+
for _, policy := range policies {
240+
for _, route := range routes {
241+
route.Priority = policy.Spec.Priority
242+
for _, data := range policy.Spec.Vars {
246243
var v []adctypes.StringOrSlice
247244
if err := json.Unmarshal(data.Raw, &v); err != nil {
248-
log.Errorf("failed to unmarshal spec.Vars item to []StringOrSlice, data: %s", string(data.Raw))
245+
log.Errorf("failed to unmarshal spec.Vars item to []StringOrSlice, data: %s", string(data.Raw)) // todo: update status
249246
continue
250247
}
251248
route.Vars = append(route.Vars, v)

internal/provider/provider.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ type TranslateContext struct {
2727
Secrets map[types.NamespacedName]*corev1.Secret
2828
PluginConfigs map[types.NamespacedName]*v1alpha1.PluginConfig
2929
Services map[types.NamespacedName]*corev1.Service
30-
HTTPRoutePolicies map[string][]v1alpha1.HTTPRoutePolicySpec
30+
HTTPRoutePolicies map[string][]v1alpha1.HTTPRoutePolicy
3131
}
3232

3333
func NewDefaultTranslateContext() *TranslateContext {
@@ -36,6 +36,6 @@ func NewDefaultTranslateContext() *TranslateContext {
3636
Secrets: make(map[types.NamespacedName]*corev1.Secret),
3737
PluginConfigs: make(map[types.NamespacedName]*v1alpha1.PluginConfig),
3838
Services: make(map[types.NamespacedName]*corev1.Service),
39-
HTTPRoutePolicies: make(map[string][]v1alpha1.HTTPRoutePolicySpec),
39+
HTTPRoutePolicies: make(map[string][]v1alpha1.HTTPRoutePolicy),
4040
}
4141
}

0 commit comments

Comments
 (0)