Skip to content

Commit ac1b391

Browse files
committed
Merge branch 'release-v2-dev' into feat/support-apisix-consumer
2 parents 94d7da7 + 2755d41 commit ac1b391

File tree

8 files changed

+282
-44
lines changed

8 files changed

+282
-44
lines changed

api/v2/apisixupstream_types.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,19 @@ type ApisixUpstreamSpec struct {
3636
PortLevelSettings []PortLevelSettings `json:"portLevelSettings,omitempty" yaml:"portLevelSettings,omitempty"`
3737
}
3838

39+
// ApisixUpstreamStatus defines the observed state of ApisixUpstream.
40+
type ApisixUpstreamStatus = ApisixStatus
41+
3942
// +kubebuilder:object:root=true
43+
// +kubebuilder:subresource:status
4044

4145
// ApisixUpstream is the Schema for the apisixupstreams API.
4246
type ApisixUpstream struct {
4347
metav1.TypeMeta `json:",inline"`
4448
metav1.ObjectMeta `json:"metadata,omitempty"`
4549

46-
Spec ApisixUpstreamSpec `json:"spec,omitempty"`
50+
Spec ApisixUpstreamSpec `json:"spec,omitempty"`
51+
Status ApisixUpstreamStatus `json:"status,omitempty"`
4752
}
4853

4954
// +kubebuilder:object:root=true

api/v2/zz_generated.deepcopy.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/apisix.apache.org_apisixupstreams.yaml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,68 @@ spec:
490490
the pass_host is set to rewrite
491491
type: string
492492
type: object
493+
status:
494+
description: ApisixStatus is the status report for Apisix ingress Resources
495+
properties:
496+
conditions:
497+
items:
498+
description: Condition contains details for one aspect of the current
499+
state of this API Resource.
500+
properties:
501+
lastTransitionTime:
502+
description: |-
503+
lastTransitionTime is the last time the condition transitioned from one status to another.
504+
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
505+
format: date-time
506+
type: string
507+
message:
508+
description: |-
509+
message is a human readable message indicating details about the transition.
510+
This may be an empty string.
511+
maxLength: 32768
512+
type: string
513+
observedGeneration:
514+
description: |-
515+
observedGeneration represents the .metadata.generation that the condition was set based upon.
516+
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
517+
with respect to the current state of the instance.
518+
format: int64
519+
minimum: 0
520+
type: integer
521+
reason:
522+
description: |-
523+
reason contains a programmatic identifier indicating the reason for the condition's last transition.
524+
Producers of specific condition types may define expected values and meanings for this field,
525+
and whether the values are considered a guaranteed API.
526+
The value should be a CamelCase string.
527+
This field may not be empty.
528+
maxLength: 1024
529+
minLength: 1
530+
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
531+
type: string
532+
status:
533+
description: status of the condition, one of True, False, Unknown.
534+
enum:
535+
- "True"
536+
- "False"
537+
- Unknown
538+
type: string
539+
type:
540+
description: type of condition in CamelCase or in foo.example.com/CamelCase.
541+
maxLength: 316
542+
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
543+
type: string
544+
required:
545+
- lastTransitionTime
546+
- message
547+
- reason
548+
- status
549+
- type
550+
type: object
551+
type: array
552+
type: object
493553
type: object
494554
served: true
495555
storage: true
556+
subresources:
557+
status: {}

docs/crd/api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,6 +1289,8 @@ _Appears in:_
12891289

12901290

12911291

1292+
1293+
12921294
#### ApisixTlsSpec
12931295

12941296

internal/controller/apisixpluginconfig_controller.go

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import (
3030
"github.com/apache/apisix-ingress-controller/api/v1alpha1"
3131
apiv2 "github.com/apache/apisix-ingress-controller/api/v2"
3232
"github.com/apache/apisix-ingress-controller/internal/controller/status"
33-
"github.com/apache/apisix-ingress-controller/internal/provider"
3433
"github.com/apache/apisix-ingress-controller/internal/utils"
3534
)
3635

@@ -46,11 +45,7 @@ type ApisixPluginConfigReconciler struct {
4645
func (r *ApisixPluginConfigReconciler) SetupWithManager(mgr ctrl.Manager) error {
4746
return ctrl.NewControllerManagedBy(mgr).
4847
For(&apiv2.ApisixPluginConfig{}).
49-
WithEventFilter(
50-
predicate.Or(
51-
predicate.GenerationChangedPredicate{},
52-
),
53-
).
48+
WithEventFilter(predicate.GenerationChangedPredicate{}).
5449
Watches(&networkingv1.IngressClass{},
5550
handler.EnqueueRequestsFromMapFunc(r.listApisixPluginConfigForIngressClass),
5651
builder.WithPredicates(
@@ -67,23 +62,12 @@ func (r *ApisixPluginConfigReconciler) SetupWithManager(mgr ctrl.Manager) error
6762
func (r *ApisixPluginConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
6863
var pc apiv2.ApisixPluginConfig
6964
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
65+
return ctrl.Result{}, client.IgnoreNotFound(err)
8166
}
8267

8368
var (
84-
tctx = provider.NewDefaultTranslateContext(ctx)
85-
ic *networkingv1.IngressClass
86-
err error
69+
ic *networkingv1.IngressClass
70+
err error
8771
)
8872
defer func() {
8973
r.updateStatus(&pc, err)
@@ -92,7 +76,7 @@ func (r *ApisixPluginConfigReconciler) Reconcile(ctx context.Context, req ctrl.R
9276
if ic, err = r.getIngressClass(&pc); err != nil {
9377
return ctrl.Result{}, err
9478
}
95-
if err = r.processIngressClassParameters(ctx, tctx, &pc, ic); err != nil {
79+
if err = r.processIngressClassParameters(ctx, &pc, ic); err != nil {
9680
return ctrl.Result{}, err
9781
}
9882
return ctrl.Result{}, nil
@@ -174,15 +158,13 @@ func (r *ApisixPluginConfigReconciler) getDefaultIngressClass() (*networkingv1.I
174158
}
175159

176160
// 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 {
161+
func (r *ApisixPluginConfigReconciler) processIngressClassParameters(ctx context.Context, pc *apiv2.ApisixPluginConfig, ingressClass *networkingv1.IngressClass) error {
178162
if ingressClass == nil || ingressClass.Spec.Parameters == nil {
179163
return nil
180164
}
181165

182166
var (
183-
ingressClassKind = utils.NamespacedNameKind(ingressClass)
184-
pcKind = utils.NamespacedNameKind(pc)
185-
parameters = ingressClass.Spec.Parameters
167+
parameters = ingressClass.Spec.Parameters
186168
)
187169
if parameters.APIGroup == nil || *parameters.APIGroup != v1alpha1.GroupVersion.Group || parameters.Kind != KindGatewayProxy {
188170
return nil
@@ -197,15 +179,7 @@ func (r *ApisixPluginConfigReconciler) processIngressClassParameters(ctx context
197179
ns = &pc.Namespace
198180
}
199181

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
182+
return r.Get(ctx, client.ObjectKey{Namespace: *ns, Name: parameters.Name}, &gatewayProxy)
209183
}
210184

211185
func (r *ApisixPluginConfigReconciler) updateStatus(pc *apiv2.ApisixPluginConfig, err error) {
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
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+
"cmp"
17+
"context"
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/utils"
34+
)
35+
36+
// ApisixUpstreamReconciler reconciles a ApisixUpstream object
37+
type ApisixUpstreamReconciler struct {
38+
client.Client
39+
Scheme *runtime.Scheme
40+
Log logr.Logger
41+
Updater status.Updater
42+
}
43+
44+
// SetupWithManager sets up the controller with the Manager.
45+
func (r *ApisixUpstreamReconciler) SetupWithManager(mgr ctrl.Manager) error {
46+
return ctrl.NewControllerManagedBy(mgr).
47+
For(&apiv2.ApisixUpstream{}).
48+
WithEventFilter(predicate.GenerationChangedPredicate{}).
49+
Watches(&networkingv1.IngressClass{},
50+
handler.EnqueueRequestsFromMapFunc(r.listApisixUpstreamForIngressClass),
51+
builder.WithPredicates(
52+
predicate.NewPredicateFuncs(r.matchesIngressController),
53+
),
54+
).
55+
Watches(&v1alpha1.GatewayProxy{},
56+
handler.EnqueueRequestsFromMapFunc(r.listApisixUpstreamForGatewayProxy),
57+
).
58+
Named("apisixupstream").
59+
Complete(r)
60+
}
61+
62+
func (r *ApisixUpstreamReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
63+
var au apiv2.ApisixUpstream
64+
if err := r.Get(ctx, req.NamespacedName, &au); err != nil {
65+
return ctrl.Result{}, client.IgnoreNotFound(err)
66+
}
67+
68+
var (
69+
ic *networkingv1.IngressClass
70+
err error
71+
)
72+
defer func() {
73+
r.updateStatus(&au, err)
74+
}()
75+
76+
if ic, err = r.getIngressClass(&au); err != nil {
77+
return ctrl.Result{}, err
78+
}
79+
if err = r.processIngressClassParameters(ctx, &au, ic); err != nil {
80+
return ctrl.Result{}, err
81+
}
82+
return ctrl.Result{}, nil
83+
}
84+
85+
func (r *ApisixUpstreamReconciler) listApisixUpstreamForIngressClass(ctx context.Context, object client.Object) (requests []reconcile.Request) {
86+
ic, ok := object.(*networkingv1.IngressClass)
87+
if !ok {
88+
return nil
89+
}
90+
91+
isDefaultIngressClass := IsDefaultIngressClass(ic)
92+
var auList apiv2.ApisixUpstreamList
93+
if err := r.List(ctx, &auList); err != nil {
94+
return nil
95+
}
96+
for _, pc := range auList.Items {
97+
if pc.Spec.IngressClassName == ic.Name || (isDefaultIngressClass && pc.Spec.IngressClassName == "") {
98+
requests = append(requests, reconcile.Request{NamespacedName: utils.NamespacedName(&pc)})
99+
}
100+
}
101+
return requests
102+
}
103+
104+
func (r *ApisixUpstreamReconciler) listApisixUpstreamForGatewayProxy(ctx context.Context, object client.Object) (requests []reconcile.Request) {
105+
gp, ok := object.(*v1alpha1.GatewayProxy)
106+
if !ok {
107+
return nil
108+
}
109+
110+
var icList networkingv1.IngressClassList
111+
if err := r.List(ctx, &icList); err != nil {
112+
r.Log.Error(err, "failed to list ingress classes for gateway proxy", "gatewayproxy", gp.GetName())
113+
return nil
114+
}
115+
116+
for _, ic := range icList.Items {
117+
requests = append(requests, r.listApisixUpstreamForIngressClass(ctx, &ic)...)
118+
}
119+
120+
return requests
121+
}
122+
123+
func (r *ApisixUpstreamReconciler) matchesIngressController(obj client.Object) bool {
124+
ingressClass, ok := obj.(*networkingv1.IngressClass)
125+
if !ok {
126+
return false
127+
}
128+
return matchesController(ingressClass.Spec.Controller)
129+
}
130+
131+
func (r *ApisixUpstreamReconciler) getIngressClass(au *apiv2.ApisixUpstream) (*networkingv1.IngressClass, error) {
132+
if au.Spec.IngressClassName == "" {
133+
return r.getDefaultIngressClass()
134+
}
135+
136+
var ic networkingv1.IngressClass
137+
if err := r.Get(context.Background(), client.ObjectKey{Name: au.Spec.IngressClassName}, &ic); err != nil {
138+
return nil, err
139+
}
140+
return &ic, nil
141+
}
142+
143+
func (r *ApisixUpstreamReconciler) processIngressClassParameters(ctx context.Context, au *apiv2.ApisixUpstream, ic *networkingv1.IngressClass) error {
144+
if ic == nil || ic.Spec.Parameters == nil {
145+
return nil
146+
}
147+
148+
var (
149+
parameters = ic.Spec.Parameters
150+
)
151+
if parameters.APIGroup == nil || *parameters.APIGroup != v1alpha1.GroupVersion.Group || parameters.Kind != KindGatewayProxy {
152+
return nil
153+
}
154+
155+
// check if the parameters reference GatewayProxy
156+
var (
157+
gp v1alpha1.GatewayProxy
158+
ns = cmp.Or(parameters.Namespace, &au.Namespace)
159+
)
160+
161+
return r.Get(ctx, client.ObjectKey{Namespace: *ns, Name: parameters.Name}, &gp)
162+
}
163+
164+
func (r *ApisixUpstreamReconciler) getDefaultIngressClass() (*networkingv1.IngressClass, error) {
165+
var icList networkingv1.IngressClassList
166+
if err := r.List(context.Background(), &icList); err != nil {
167+
r.Log.Error(err, "failed to list ingress classes")
168+
return nil, err
169+
}
170+
for _, ic := range icList.Items {
171+
if IsDefaultIngressClass(&ic) && matchesController(ic.Spec.Controller) {
172+
return &ic, nil
173+
}
174+
}
175+
return nil, ReasonError{
176+
Reason: string(metav1.StatusReasonNotFound),
177+
Message: "default ingress class not found or does not match the controller",
178+
}
179+
}
180+
181+
func (r *ApisixUpstreamReconciler) updateStatus(au *apiv2.ApisixUpstream, err error) {
182+
SetApisixCRDConditionAccepted(&au.Status, au.GetGeneration(), err)
183+
r.Updater.Update(status.Update{
184+
NamespacedName: utils.NamespacedName(au),
185+
Resource: &apiv2.ApisixUpstream{},
186+
Mutator: status.MutatorFunc(func(obj client.Object) client.Object {
187+
cp := obj.(*apiv2.ApisixUpstream).DeepCopy()
188+
cp.Status = au.Status
189+
return cp
190+
}),
191+
})
192+
}

0 commit comments

Comments
 (0)