Skip to content

Commit 61d0982

Browse files
authored
Merge branch 'release-v2-dev' into docs/update-crd
2 parents f7060fe + afae2b6 commit 61d0982

30 files changed

+689
-101
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ KIND_NAME ?= apisix-ingress-cluster
2929

3030
GATEAY_API_VERSION ?= v1.2.0
3131
DASHBOARD_VERSION ?= dev
32-
ADC_VERSION ?= 0.19.0
32+
ADC_VERSION ?= 0.20.0
3333

3434
TEST_TIMEOUT ?= 80m
3535
TEST_DIR ?= ./test/e2e/

api/v1alpha1/gatewayproxy_types.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ import (
2222
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2323
)
2424

25-
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
26-
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
27-
2825
// GatewayProxySpec defines the desired state of GatewayProxy.
2926
type GatewayProxySpec struct {
3027
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
@@ -116,9 +113,10 @@ type ControlPlaneAuth struct {
116113
}
117114

118115
// ControlPlaneProvider defines configuration for control plane provider.
116+
// +kubebuilder:validation:XValidation:rule="has(self.endpoints) != has(self.service)"
119117
type ControlPlaneProvider struct {
120118
// Endpoints specifies the list of control plane endpoints.
121-
// +kubebuilder:validation:Required
119+
// +kubebuilder:validation:Optional
122120
// +kubebuilder:validation:MinItems=1
123121
Endpoints []string `json:"endpoints"`
124122

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,9 @@ spec:
140140
type: boolean
141141
required:
142142
- auth
143-
- endpoints
144143
type: object
144+
x-kubernetes-validations:
145+
- rule: has(self.endpoints) != has(self.service)
145146
type:
146147
description: Type specifies the type of provider. Can only be
147148
`ControlPlane`.

internal/controller/gatewayclass_congroller.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ const (
4343
FinalizerGatewayClassProtection = "apisix.apache.org/gc-protection"
4444
)
4545

46-
// +kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gatewayclasses,verbs=get;list;watch;update
47-
// +kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gatewayclasses/status,verbs=get;update
48-
4946
// GatewayClassReconciler reconciles a GatewayClass object.
5047
type GatewayClassReconciler struct { //nolint:revive
5148
client.Client
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package controller
19+
20+
import (
21+
"context"
22+
"errors"
23+
24+
"github.com/go-logr/logr"
25+
corev1 "k8s.io/api/core/v1"
26+
discoveryv1 "k8s.io/api/discovery/v1"
27+
networkingv1 "k8s.io/api/networking/v1"
28+
"k8s.io/apimachinery/pkg/runtime"
29+
"k8s.io/apimachinery/pkg/types"
30+
ctrl "sigs.k8s.io/controller-runtime"
31+
"sigs.k8s.io/controller-runtime/pkg/client"
32+
"sigs.k8s.io/controller-runtime/pkg/handler"
33+
"sigs.k8s.io/controller-runtime/pkg/reconcile"
34+
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
35+
36+
"github.com/apache/apisix-ingress-controller/api/v1alpha1"
37+
"github.com/apache/apisix-ingress-controller/internal/controller/indexer"
38+
"github.com/apache/apisix-ingress-controller/internal/provider"
39+
"github.com/apache/apisix-ingress-controller/internal/utils"
40+
)
41+
42+
// GatewayProxyController reconciles a GatewayProxy object.
43+
type GatewayProxyController struct {
44+
client.Client
45+
46+
Scheme *runtime.Scheme
47+
Log logr.Logger
48+
Provider provider.Provider
49+
}
50+
51+
func (r *GatewayProxyController) SetupWithManager(mrg ctrl.Manager) error {
52+
return ctrl.NewControllerManagedBy(mrg).
53+
For(&v1alpha1.GatewayProxy{}).
54+
Watches(&corev1.Service{},
55+
handler.EnqueueRequestsFromMapFunc(r.listGatewayProxiesForProviderService),
56+
).
57+
Watches(&discoveryv1.EndpointSlice{},
58+
handler.EnqueueRequestsFromMapFunc(r.listGatewayProxiesForProviderEndpointSlice),
59+
).
60+
Watches(&corev1.Secret{},
61+
handler.EnqueueRequestsFromMapFunc(r.listGatewayProxiesForSecret),
62+
).
63+
Complete(r)
64+
}
65+
66+
func (r *GatewayProxyController) Reconcile(ctx context.Context, req ctrl.Request) (reconcile.Result, error) {
67+
var tctx = provider.NewDefaultTranslateContext(ctx)
68+
69+
var gp v1alpha1.GatewayProxy
70+
if err := r.Get(ctx, req.NamespacedName, &gp); err != nil {
71+
if client.IgnoreNotFound(err) == nil {
72+
gp.Namespace = req.Namespace
73+
gp.Name = req.Name
74+
err = r.Provider.Update(ctx, tctx, &gp)
75+
}
76+
return ctrl.Result{}, err
77+
}
78+
79+
// if there is no provider, update with empty translate context
80+
if gp.Spec.Provider == nil || gp.Spec.Provider.ControlPlane == nil {
81+
return reconcile.Result{}, r.Provider.Update(ctx, tctx, &gp)
82+
}
83+
84+
// process endpoints for provider service
85+
providerService := gp.Spec.Provider.ControlPlane.Service
86+
if providerService == nil {
87+
tctx.EndpointSlices[req.NamespacedName] = nil
88+
} else {
89+
if err := addProviderEndpointsToTranslateContext(tctx, r.Client, types.NamespacedName{
90+
Namespace: gp.Namespace,
91+
Name: providerService.Name,
92+
}); err != nil {
93+
return reconcile.Result{}, err
94+
}
95+
}
96+
97+
// process secret for provider auth
98+
auth := gp.Spec.Provider.ControlPlane.Auth
99+
if auth.AdminKey != nil && auth.AdminKey.ValueFrom != nil && auth.AdminKey.ValueFrom.SecretKeyRef != nil {
100+
var (
101+
secret corev1.Secret
102+
secretNN = types.NamespacedName{
103+
Namespace: gp.GetNamespace(),
104+
Name: auth.AdminKey.ValueFrom.SecretKeyRef.Name,
105+
}
106+
)
107+
if err := r.Get(ctx, secretNN, &secret); err != nil {
108+
r.Log.Error(err, "failed to get secret", "secret", secretNN)
109+
return reconcile.Result{}, err
110+
}
111+
tctx.Secrets[secretNN] = &secret
112+
}
113+
114+
// list Gateways that reference the GatewayProxy
115+
var (
116+
gatewayList gatewayv1.GatewayList
117+
ingressClassList networkingv1.IngressClassList
118+
indexKey = indexer.GenIndexKey(gp.GetNamespace(), gp.GetName())
119+
)
120+
if err := r.List(ctx, &gatewayList, client.MatchingFields{indexer.ParametersRef: indexKey}); err != nil {
121+
r.Log.Error(err, "failed to list GatewayList")
122+
return ctrl.Result{}, nil
123+
}
124+
125+
// list IngressClasses that reference the GatewayProxy
126+
if err := r.List(ctx, &ingressClassList, client.MatchingFields{indexer.IngressClassParametersRef: indexKey}); err != nil {
127+
r.Log.Error(err, "failed to list IngressClassList")
128+
return reconcile.Result{}, err
129+
}
130+
131+
// append referrers to translate context
132+
for _, item := range gatewayList.Items {
133+
tctx.GatewayProxyReferrers[req.NamespacedName] = append(tctx.GatewayProxyReferrers[req.NamespacedName], utils.NamespacedNameKind(&item))
134+
}
135+
for _, item := range ingressClassList.Items {
136+
tctx.GatewayProxyReferrers[req.NamespacedName] = append(tctx.GatewayProxyReferrers[req.NamespacedName], utils.NamespacedNameKind(&item))
137+
}
138+
139+
if err := r.Provider.Update(ctx, tctx, &gp); err != nil {
140+
return reconcile.Result{}, err
141+
}
142+
143+
return reconcile.Result{}, nil
144+
}
145+
146+
func (r *GatewayProxyController) listGatewayProxiesForProviderService(ctx context.Context, obj client.Object) (requests []reconcile.Request) {
147+
service, ok := obj.(*corev1.Service)
148+
if !ok {
149+
r.Log.Error(errors.New("unexpected object type"), "failed to convert object to Service")
150+
return nil
151+
}
152+
153+
return ListRequests(ctx, r.Client, r.Log, &v1alpha1.GatewayProxyList{}, client.MatchingFields{
154+
indexer.ServiceIndexRef: indexer.GenIndexKey(service.GetNamespace(), service.GetName()),
155+
})
156+
}
157+
158+
func (r *GatewayProxyController) listGatewayProxiesForProviderEndpointSlice(ctx context.Context, obj client.Object) (requests []reconcile.Request) {
159+
endpointSlice, ok := obj.(*discoveryv1.EndpointSlice)
160+
if !ok {
161+
r.Log.Error(errors.New("unexpected object type"), "failed to convert object to EndpointSlice")
162+
return nil
163+
}
164+
165+
return ListRequests(ctx, r.Client, r.Log, &v1alpha1.GatewayProxyList{}, client.MatchingFields{
166+
indexer.ServiceIndexRef: indexer.GenIndexKey(endpointSlice.GetNamespace(), endpointSlice.Labels[discoveryv1.LabelServiceName]),
167+
})
168+
}
169+
170+
func (r *GatewayProxyController) listGatewayProxiesForSecret(ctx context.Context, object client.Object) []reconcile.Request {
171+
secret, ok := object.(*corev1.Secret)
172+
if !ok {
173+
r.Log.Error(errors.New("unexpected object type"), "failed to convert object to Secret")
174+
return nil
175+
}
176+
return ListRequests(ctx, r.Client, r.Log, &v1alpha1.GatewayProxyList{}, client.MatchingFields{
177+
indexer.SecretIndexRef: indexer.GenIndexKey(secret.GetNamespace(), secret.GetName()),
178+
})
179+
}

internal/controller/indexer/indexer.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,15 @@ func setupIngressClassIndexer(mgr ctrl.Manager) error {
241241
}
242242

243243
func setupGatewayProxyIndexer(mgr ctrl.Manager) error {
244+
if err := mgr.GetFieldIndexer().IndexField(
245+
context.Background(),
246+
&v1alpha1.GatewayProxy{},
247+
ServiceIndexRef,
248+
GatewayProxyServiceIndexFunc,
249+
); err != nil {
250+
return err
251+
}
252+
244253
if err := mgr.GetFieldIndexer().IndexField(
245254
context.Background(),
246255
&v1alpha1.GatewayProxy{},
@@ -272,6 +281,17 @@ func setupGatewayClassIndexer(mgr ctrl.Manager) error {
272281
)
273282
}
274283

284+
func GatewayProxyServiceIndexFunc(rawObj client.Object) []string {
285+
gatewayProxy := rawObj.(*v1alpha1.GatewayProxy)
286+
if gatewayProxy.Spec.Provider != nil &&
287+
gatewayProxy.Spec.Provider.ControlPlane != nil &&
288+
gatewayProxy.Spec.Provider.ControlPlane.Service != nil {
289+
service := gatewayProxy.Spec.Provider.ControlPlane.Service
290+
return []string{GenIndexKey(gatewayProxy.GetNamespace(), service.Name)}
291+
}
292+
return nil
293+
}
294+
275295
func GatewayProxySecretIndexFunc(rawObj client.Object) []string {
276296
gatewayProxy := rawObj.(*v1alpha1.GatewayProxy)
277297
secretKeys := make([]string, 0)

internal/controller/ingressclass_controller.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
networkingv1 "k8s.io/api/networking/v1"
2828
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2929
"k8s.io/apimachinery/pkg/runtime"
30+
"k8s.io/apimachinery/pkg/types"
3031
ctrl "sigs.k8s.io/controller-runtime"
3132
"sigs.k8s.io/controller-runtime/pkg/builder"
3233
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -229,6 +230,15 @@ func (r *IngressClassReconciler) processInfrastructure(tctx *provider.TranslateC
229230
}
230231
}
231232

233+
if service := gatewayProxy.Spec.Provider.ControlPlane.Service; service != nil {
234+
if err := addProviderEndpointsToTranslateContext(tctx, r.Client, types.NamespacedName{
235+
Namespace: gatewayProxy.GetNamespace(),
236+
Name: service.Name,
237+
}); err != nil {
238+
return err
239+
}
240+
}
241+
232242
_, ok := tctx.GatewayProxies[rk]
233243
if !ok {
234244
return fmt.Errorf("no gateway proxy found for ingress class")

0 commit comments

Comments
 (0)