Skip to content

Commit 80268eb

Browse files
committed
Merge remote-tracking branch 'origin/release-v2-dev' into feat/apisixupstream
# Conflicts: # internal/controller/apisixroute_controller.go # internal/controller/indexer/indexer.go # internal/provider/adc/translator/apisixroute.go
2 parents 8291748 + d4f7530 commit 80268eb

File tree

8 files changed

+1214
-210
lines changed

8 files changed

+1214
-210
lines changed
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
// Licensed under the Apache License, Version 2.0 (the "License");
2+
// you may not use this file except in compliance with the License.
3+
// You may obtain a copy of the License at
4+
//
5+
// http://www.apache.org/licenses/LICENSE-2.0
6+
//
7+
// Unless required by applicable law or agreed to in writing, software
8+
// distributed under the License is distributed on an "AS IS" BASIS,
9+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
// See the License for the specific language governing permissions and
11+
// limitations under the License.
12+
13+
package controller
14+
15+
import (
16+
"context"
17+
"fmt"
18+
19+
"github.com/go-logr/logr"
20+
networkingv1 "k8s.io/api/networking/v1"
21+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
22+
"k8s.io/apimachinery/pkg/runtime"
23+
ctrl "sigs.k8s.io/controller-runtime"
24+
"sigs.k8s.io/controller-runtime/pkg/builder"
25+
"sigs.k8s.io/controller-runtime/pkg/client"
26+
"sigs.k8s.io/controller-runtime/pkg/handler"
27+
"sigs.k8s.io/controller-runtime/pkg/predicate"
28+
"sigs.k8s.io/controller-runtime/pkg/reconcile"
29+
30+
"github.com/apache/apisix-ingress-controller/api/v1alpha1"
31+
apiv2 "github.com/apache/apisix-ingress-controller/api/v2"
32+
"github.com/apache/apisix-ingress-controller/internal/controller/status"
33+
"github.com/apache/apisix-ingress-controller/internal/provider"
34+
"github.com/apache/apisix-ingress-controller/internal/utils"
35+
)
36+
37+
// ApisixPluginConfigReconciler reconciles a ApisixPluginConfig object
38+
type ApisixPluginConfigReconciler struct {
39+
client.Client
40+
Scheme *runtime.Scheme
41+
Log logr.Logger
42+
Updater status.Updater
43+
}
44+
45+
// SetupWithManager sets up the controller with the Manager.
46+
func (r *ApisixPluginConfigReconciler) SetupWithManager(mgr ctrl.Manager) error {
47+
return ctrl.NewControllerManagedBy(mgr).
48+
For(&apiv2.ApisixPluginConfig{}).
49+
WithEventFilter(
50+
predicate.Or(
51+
predicate.GenerationChangedPredicate{},
52+
),
53+
).
54+
Watches(&networkingv1.IngressClass{},
55+
handler.EnqueueRequestsFromMapFunc(r.listApisixPluginConfigForIngressClass),
56+
builder.WithPredicates(
57+
predicate.NewPredicateFuncs(r.matchesIngressController),
58+
),
59+
).
60+
Watches(&v1alpha1.GatewayProxy{},
61+
handler.EnqueueRequestsFromMapFunc(r.listApisixPluginConfigForGatewayProxy),
62+
).
63+
Named("apisixpluginconfig").
64+
Complete(r)
65+
}
66+
67+
func (r *ApisixPluginConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
68+
var pc apiv2.ApisixPluginConfig
69+
if err := r.Get(ctx, req.NamespacedName, &pc); err != nil {
70+
if client.IgnoreNotFound(err) == nil {
71+
pc.Namespace = req.Namespace
72+
pc.Name = req.Name
73+
pc.TypeMeta = metav1.TypeMeta{
74+
Kind: KindApisixPluginConfig,
75+
APIVersion: apiv2.GroupVersion.String(),
76+
}
77+
78+
return ctrl.Result{}, nil
79+
}
80+
return ctrl.Result{}, err
81+
}
82+
83+
var (
84+
tctx = provider.NewDefaultTranslateContext(ctx)
85+
ic *networkingv1.IngressClass
86+
err error
87+
)
88+
defer func() {
89+
r.updateStatus(&pc, err)
90+
}()
91+
92+
if ic, err = r.getIngressClass(&pc); err != nil {
93+
return ctrl.Result{}, err
94+
}
95+
if err = r.processIngressClassParameters(ctx, tctx, &pc, ic); err != nil {
96+
return ctrl.Result{}, err
97+
}
98+
return ctrl.Result{}, nil
99+
}
100+
101+
func (r *ApisixPluginConfigReconciler) listApisixPluginConfigForIngressClass(ctx context.Context, object client.Object) (requests []reconcile.Request) {
102+
ic, ok := object.(*networkingv1.IngressClass)
103+
if !ok {
104+
return nil
105+
}
106+
107+
isDefaultIngressClass := IsDefaultIngressClass(ic)
108+
var pcList apiv2.ApisixPluginConfigList
109+
if err := r.List(ctx, &pcList); err != nil {
110+
return nil
111+
}
112+
for _, pc := range pcList.Items {
113+
if pc.Spec.IngressClassName == ic.Name || (isDefaultIngressClass && pc.Spec.IngressClassName == "") {
114+
requests = append(requests, reconcile.Request{NamespacedName: utils.NamespacedName(&pc)})
115+
}
116+
}
117+
return requests
118+
}
119+
120+
func (r *ApisixPluginConfigReconciler) listApisixPluginConfigForGatewayProxy(ctx context.Context, object client.Object) (requests []reconcile.Request) {
121+
gp, ok := object.(*v1alpha1.GatewayProxy)
122+
if !ok {
123+
return nil
124+
}
125+
126+
var icList networkingv1.IngressClassList
127+
if err := r.List(ctx, &icList); err != nil {
128+
r.Log.Error(err, "failed to list ingress classes for gateway proxy", "gatewayproxy", gp.GetName())
129+
return nil
130+
}
131+
132+
for _, ic := range icList.Items {
133+
requests = append(requests, r.listApisixPluginConfigForIngressClass(ctx, &ic)...)
134+
}
135+
136+
return requests
137+
}
138+
139+
func (r *ApisixPluginConfigReconciler) matchesIngressController(obj client.Object) bool {
140+
ingressClass, ok := obj.(*networkingv1.IngressClass)
141+
if !ok {
142+
return false
143+
}
144+
return matchesController(ingressClass.Spec.Controller)
145+
}
146+
147+
func (r *ApisixPluginConfigReconciler) getIngressClass(pc *apiv2.ApisixPluginConfig) (*networkingv1.IngressClass, error) {
148+
if pc.Spec.IngressClassName == "" {
149+
return r.getDefaultIngressClass()
150+
}
151+
152+
var ic networkingv1.IngressClass
153+
if err := r.Get(context.Background(), client.ObjectKey{Name: pc.Spec.IngressClassName}, &ic); err != nil {
154+
return nil, err
155+
}
156+
return &ic, nil
157+
}
158+
159+
func (r *ApisixPluginConfigReconciler) getDefaultIngressClass() (*networkingv1.IngressClass, error) {
160+
var icList networkingv1.IngressClassList
161+
if err := r.List(context.Background(), &icList); err != nil {
162+
r.Log.Error(err, "failed to list ingress classes")
163+
return nil, err
164+
}
165+
for _, ic := range icList.Items {
166+
if IsDefaultIngressClass(&ic) && matchesController(ic.Spec.Controller) {
167+
return &ic, nil
168+
}
169+
}
170+
return nil, ReasonError{
171+
Reason: string(metav1.StatusReasonNotFound),
172+
Message: "default ingress class not found or does not match the controller",
173+
}
174+
}
175+
176+
// processIngressClassParameters processes the IngressClass parameters that reference GatewayProxy
177+
func (r *ApisixPluginConfigReconciler) processIngressClassParameters(ctx context.Context, tc *provider.TranslateContext, pc *apiv2.ApisixPluginConfig, ingressClass *networkingv1.IngressClass) error {
178+
if ingressClass == nil || ingressClass.Spec.Parameters == nil {
179+
return nil
180+
}
181+
182+
var (
183+
ingressClassKind = utils.NamespacedNameKind(ingressClass)
184+
pcKind = utils.NamespacedNameKind(pc)
185+
parameters = ingressClass.Spec.Parameters
186+
)
187+
if parameters.APIGroup == nil || *parameters.APIGroup != v1alpha1.GroupVersion.Group || parameters.Kind != KindGatewayProxy {
188+
return nil
189+
}
190+
191+
// check if the parameters reference GatewayProxy
192+
var (
193+
gatewayProxy v1alpha1.GatewayProxy
194+
ns = parameters.Namespace
195+
)
196+
if ns == nil {
197+
ns = &pc.Namespace
198+
}
199+
200+
if err := r.Get(ctx, client.ObjectKey{Namespace: *ns, Name: parameters.Name}, &gatewayProxy); err != nil {
201+
r.Log.Error(err, "failed to get GatewayProxy", "namespace", *ns, "name", parameters.Name)
202+
return err
203+
}
204+
205+
tc.GatewayProxies[ingressClassKind] = gatewayProxy
206+
tc.ResourceParentRefs[pcKind] = append(tc.ResourceParentRefs[pcKind], ingressClassKind)
207+
208+
return nil
209+
}
210+
211+
func (r *ApisixPluginConfigReconciler) updateStatus(pc *apiv2.ApisixPluginConfig, err error) {
212+
SetApisixCRDConditionAccepted(&pc.Status, pc.GetGeneration(), err)
213+
r.Updater.Update(status.Update{
214+
NamespacedName: utils.NamespacedName(pc),
215+
Resource: &apiv2.ApisixPluginConfig{},
216+
Mutator: status.MutatorFunc(func(obj client.Object) client.Object {
217+
cp, ok := obj.(*apiv2.ApisixPluginConfig)
218+
if !ok {
219+
err := fmt.Errorf("unsupported object type %T", obj)
220+
panic(err)
221+
}
222+
cpCopy := cp.DeepCopy()
223+
cpCopy.Status = pc.Status
224+
return cpCopy
225+
}),
226+
})
227+
}

0 commit comments

Comments
 (0)