Skip to content

Commit bc6ef45

Browse files
authored
chore: Add support for Secret resources in Gateway reconciliation (#119)
1 parent 100bbc8 commit bc6ef45

File tree

4 files changed

+122
-28
lines changed

4 files changed

+122
-28
lines changed

internal/controller/gateway_controller.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package controller
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"reflect"
78

@@ -42,7 +43,15 @@ func (r *GatewayReconciler) SetupWithManager(mgr ctrl.Manager) error {
4243
predicate.NewPredicateFuncs(r.checkGatewayClass),
4344
),
4445
).
45-
WithEventFilter(predicate.GenerationChangedPredicate{}).
46+
WithEventFilter(
47+
predicate.Or(
48+
predicate.GenerationChangedPredicate{},
49+
predicate.NewPredicateFuncs(func(obj client.Object) bool {
50+
_, ok := obj.(*corev1.Secret)
51+
return ok
52+
}),
53+
),
54+
).
4655
Watches(
4756
&gatewayv1.GatewayClass{},
4857
handler.EnqueueRequestsFromMapFunc(r.listGatewayForGatewayClass),
@@ -58,6 +67,10 @@ func (r *GatewayReconciler) SetupWithManager(mgr ctrl.Manager) error {
5867
&v1alpha1.GatewayProxy{},
5968
handler.EnqueueRequestsFromMapFunc(r.listGatewaysForGatewayProxy),
6069
).
70+
Watches(
71+
&corev1.Secret{},
72+
handler.EnqueueRequestsFromMapFunc(r.listGatewaysForSecret),
73+
).
6174
Complete(r)
6275
}
6376

@@ -295,6 +308,34 @@ func (r *GatewayReconciler) listGatewaysForHTTPRoute(ctx context.Context, obj cl
295308
return recs
296309
}
297310

311+
func (r *GatewayReconciler) listGatewaysForSecret(ctx context.Context, obj client.Object) (requests []reconcile.Request) {
312+
secret, ok := obj.(*corev1.Secret)
313+
if !ok {
314+
r.Log.Error(
315+
errors.New("unexpected object type"),
316+
"Secret watch predicate received unexpected object type",
317+
"expected", FullTypeName(new(corev1.Secret)), "found", FullTypeName(obj),
318+
)
319+
return nil
320+
}
321+
var gatewayList gatewayv1.GatewayList
322+
if err := r.List(ctx, &gatewayList, client.MatchingFields{
323+
indexer.SecretIndexRef: indexer.GenIndexKey(secret.GetNamespace(), secret.GetName()),
324+
}); err != nil {
325+
r.Log.Error(err, "failed to list gateways")
326+
return nil
327+
}
328+
for _, gateway := range gatewayList.Items {
329+
requests = append(requests, reconcile.Request{
330+
NamespacedName: types.NamespacedName{
331+
Namespace: gateway.GetNamespace(),
332+
Name: gateway.GetName(),
333+
},
334+
})
335+
}
336+
return requests
337+
}
338+
298339
func (r *GatewayReconciler) processInfrastructure(tctx *provider.TranslateContext, gateway *gatewayv1.Gateway) error {
299340
rk := provider.ResourceKind{
300341
Kind: gateway.Kind,
@@ -316,12 +357,12 @@ func (r *GatewayReconciler) processListenerConfig(tctx *provider.TranslateContex
316357
if ref.Namespace != nil {
317358
ns = string(*ref.Namespace)
318359
}
319-
if ref.Kind != nil && *ref.Kind == gatewayv1.Kind("Secret") {
360+
if ref.Kind != nil && *ref.Kind == KindSecret {
320361
if err := r.Get(context.Background(), client.ObjectKey{
321362
Namespace: ns,
322363
Name: string(ref.Name),
323364
}, &secret); err != nil {
324-
log.Error(err, "failed to get secret", "namespace", ns, "name", string(ref.Name))
365+
log.Error(err, "failed to get secret", "namespace", ns, "name", ref.Name)
325366
SetGatewayListenerConditionProgrammed(gateway, string(listener.Name), false, err.Error())
326367
SetGatewayListenerConditionResolvedRefs(gateway, string(listener.Name), false, err.Error())
327368
break

internal/controller/indexer/indexer.go

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,19 @@ const (
2727
)
2828

2929
func SetupIndexer(mgr ctrl.Manager) error {
30-
if err := setupGatewayIndexer(mgr); err != nil {
31-
return err
32-
}
33-
if err := setupHTTPRouteIndexer(mgr); err != nil {
34-
return err
35-
}
36-
if err := setupIngressIndexer(mgr); err != nil {
37-
return err
38-
}
39-
if err := setupConsumerIndexer(mgr); err != nil {
40-
return err
41-
}
42-
if err := setupBackendTrafficPolicyIndexer(mgr); err != nil {
43-
return err
44-
}
45-
if err := setupIngressClassIndexer(mgr); err != nil {
46-
return err
47-
}
48-
if err := setupGatewayProxyIndexer(mgr); err != nil {
49-
return err
30+
for _, setup := range []func(ctrl.Manager) error{
31+
setupGatewayIndexer,
32+
setupHTTPRouteIndexer,
33+
setupIngressIndexer,
34+
setupConsumerIndexer,
35+
setupBackendTrafficPolicyIndexer,
36+
setupIngressClassIndexer,
37+
setupGatewayProxyIndexer,
38+
setupGatewaySecretIndex,
39+
} {
40+
if err := setup(mgr); err != nil {
41+
return err
42+
}
5043
}
5144
return nil
5245
}
@@ -191,6 +184,15 @@ func setupGatewayProxyIndexer(mgr ctrl.Manager) error {
191184
return nil
192185
}
193186

187+
func setupGatewaySecretIndex(mgr ctrl.Manager) error {
188+
return mgr.GetFieldIndexer().IndexField(
189+
context.Background(),
190+
&gatewayv1.Gateway{},
191+
SecretIndexRef,
192+
GatewaySecretIndexFunc,
193+
)
194+
}
195+
194196
func GatewayProxySecretIndexFunc(rawObj client.Object) []string {
195197
gatewayProxy := rawObj.(*v1alpha1.GatewayProxy)
196198
secretKeys := make([]string, 0)
@@ -310,6 +312,31 @@ func IngressSecretIndexFunc(rawObj client.Object) []string {
310312
return secrets
311313
}
312314

315+
func GatewaySecretIndexFunc(rawObj client.Object) (keys []string) {
316+
gateway := rawObj.(*gatewayv1.Gateway)
317+
var m = make(map[string]struct{})
318+
for _, listener := range gateway.Spec.Listeners {
319+
if listener.TLS == nil || len(listener.TLS.CertificateRefs) == 0 {
320+
continue
321+
}
322+
for _, ref := range listener.TLS.CertificateRefs {
323+
if ref.Kind == nil || *ref.Kind != "Secret" {
324+
continue
325+
}
326+
namespace := gateway.GetNamespace()
327+
if ref.Namespace != nil {
328+
namespace = string(*ref.Namespace)
329+
}
330+
key := GenIndexKey(namespace, string(ref.Name))
331+
if _, ok := m[key]; !ok {
332+
m[key] = struct{}{}
333+
keys = append(keys, key)
334+
}
335+
}
336+
}
337+
return keys
338+
}
339+
313340
func GenIndexKeyWithGK(group, kind, namespace, name string) string {
314341
gvk := schema.GroupKind{
315342
Group: group,

internal/controller/utils.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package controller
33
import (
44
"context"
55
"fmt"
6+
"path"
7+
"reflect"
68
"strings"
79

810
"github.com/api7/gopkg/pkg/log"
@@ -29,6 +31,7 @@ const (
2931
KindIngress = "Ingress"
3032
KindIngressClass = "IngressClass"
3133
KindGatewayProxy = "GatewayProxy"
34+
KindSecret = "Secret"
3235
)
3336

3437
const defaultIngressClassAnnotation = "ingressclass.kubernetes.io/is-default-class"
@@ -839,3 +842,14 @@ func ProcessGatewayProxy(r client.Client, tctx *provider.TranslateContext, gatew
839842

840843
return nil
841844
}
845+
846+
// FullTypeName returns the fully qualified name of the type of the given value.
847+
func FullTypeName(a any) string {
848+
typeOf := reflect.TypeOf(a)
849+
pkgPath := typeOf.PkgPath()
850+
name := typeOf.String()
851+
if typeOf.Kind() == reflect.Ptr {
852+
pkgPath = typeOf.Elem().PkgPath()
853+
}
854+
return path.Join(path.Dir(pkgPath), name)
855+
}

test/e2e/gatewayapi/gateway.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ spec:
4848
`
4949

5050
Context("Gateway", func() {
51-
var defautlGatewayClass = `
51+
var defaultGatewayClass = `
5252
apiVersion: gateway.networking.k8s.io/v1
5353
kind: GatewayClass
5454
metadata:
@@ -57,7 +57,7 @@ spec:
5757
controllerName: "apisix.apache.org/api7-ingress-controller"
5858
`
5959

60-
var defautlGateway = `
60+
var defaultGateway = `
6161
apiVersion: gateway.networking.k8s.io/v1
6262
kind: Gateway
6363
metadata:
@@ -101,7 +101,7 @@ spec:
101101
time.Sleep(5 * time.Second)
102102

103103
By("create GatewayClass")
104-
err = s.CreateResourceFromStringWithNamespace(defautlGatewayClass, "")
104+
err = s.CreateResourceFromStringWithNamespace(defaultGatewayClass, "")
105105
Expect(err).NotTo(HaveOccurred(), "creating GatewayClass")
106106
time.Sleep(5 * time.Second)
107107

@@ -112,7 +112,7 @@ spec:
112112
Expect(gcyaml).To(ContainSubstring("message: the gatewayclass has been accepted by the api7-ingress-controller"), "checking GatewayClass condition message")
113113

114114
By("create Gateway")
115-
err = s.CreateResourceFromStringWithNamespace(defautlGateway, s.CurrentNamespace())
115+
err = s.CreateResourceFromStringWithNamespace(defaultGateway, s.CurrentNamespace())
116116
Expect(err).NotTo(HaveOccurred(), "creating Gateway")
117117
time.Sleep(5 * time.Second)
118118

@@ -196,7 +196,7 @@ spec:
196196
})
197197

198198
Context("Gateway SSL with and without hostname", func() {
199-
It("Check if SSL resource was created", func() {
199+
It("Check if SSL resource was created and updated", func() {
200200
By("create GatewayProxy")
201201
gatewayProxy := fmt.Sprintf(gatewayProxyYaml, framework.DashboardTLSEndpoint, s.AdminKey())
202202
err := s.CreateResourceFromString(gatewayProxy)
@@ -266,6 +266,18 @@ spec:
266266
assert.Len(GinkgoT(), tls, 1, "tls number not expect")
267267
assert.Equal(GinkgoT(), Cert, tls[0].Cert, "tls cert not expect")
268268
assert.Equal(GinkgoT(), tls[0].Labels["k8s/controller-name"], "apisix.apache.org/api7-ingress-controller")
269+
270+
By("update secret")
271+
err = s.NewKubeTlsSecret(secretName, framework.TestCert, framework.TestKey)
272+
Expect(err).NotTo(HaveOccurred(), "update secret")
273+
Eventually(func() string {
274+
tls, err := s.DefaultDataplaneResource().SSL().List(context.Background())
275+
Expect(err).NotTo(HaveOccurred(), "list ssl from dashboard")
276+
if len(tls) < 1 {
277+
return ""
278+
}
279+
return tls[0].Cert
280+
}).WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(Equal(framework.TestCert))
269281
})
270282
})
271283
})

0 commit comments

Comments
 (0)