diff --git a/internal/controller/apisixroute_controller.go b/internal/controller/apisixroute_controller.go index c4dde0d5a0..b9bdc7fbab 100644 --- a/internal/controller/apisixroute_controller.go +++ b/internal/controller/apisixroute_controller.go @@ -285,6 +285,43 @@ func (r *ApisixRouteReconciler) validateSecrets(ctx context.Context, tc *provide return nil } +func (r *ApisixRouteReconciler) processExternalNodes(ctx context.Context, tc *provider.TranslateContext, ups apiv2.ApisixUpstream) error { + for _, node := range ups.Spec.ExternalNodes { + if node.Type == apiv2.ExternalTypeService { + var ( + service corev1.Service + serviceNN = k8stypes.NamespacedName{Namespace: ups.GetNamespace(), Name: node.Name} + ) + if err := r.Get(ctx, serviceNN, &service); err != nil { + r.Log.Error(err, "failed to get service in ApisixUpstream", "ApisixUpstream", ups.Name, "Service", serviceNN) + if client.IgnoreNotFound(err) == nil { + continue + } + return err + } + tc.Services[utils.NamespacedName(&service)] = &service + } + } + return nil +} + +func (r *ApisixRouteReconciler) processTLSSecret(ctx context.Context, tc *provider.TranslateContext, ups apiv2.ApisixUpstream, secretNs string) error { + if ups.Spec.TLSSecret != nil && ups.Spec.TLSSecret.Name != "" { + var ( + secret corev1.Secret + secretNN = k8stypes.NamespacedName{Namespace: cmp.Or(ups.Spec.TLSSecret.Namespace, secretNs), Name: ups.Spec.TLSSecret.Name} + ) + if err := r.Get(ctx, secretNN, &secret); err != nil { + r.Log.Error(err, "failed to get secret in ApisixUpstream", "ApisixUpstream", ups.Name, "Secret", secretNN) + if client.IgnoreNotFound(err) != nil { + return err + } + } + tc.Secrets[secretNN] = &secret + } + return nil +} + func (r *ApisixRouteReconciler) validateBackends(ctx context.Context, tc *provider.TranslateContext, in *apiv2.ApisixRoute, http apiv2.ApisixRouteHTTP) error { var backends = make(map[k8stypes.NamespacedName]struct{}) for _, backend := range http.Backends { @@ -321,6 +358,9 @@ func (r *ApisixRouteReconciler) validateBackends(ctx context.Context, tc *provid } } else { tc.Upstreams[serviceNN] = &au + if err := r.processTLSSecret(ctx, tc, au, in.GetNamespace()); err != nil { + return err + } } if service.Spec.Type == corev1.ServiceTypeExternalName { @@ -384,35 +424,12 @@ func (r *ApisixRouteReconciler) validateUpstreams(ctx context.Context, tc *provi } tc.Upstreams[upsNN] = &ups - for _, node := range ups.Spec.ExternalNodes { - if node.Type == apiv2.ExternalTypeService { - var ( - service corev1.Service - serviceNN = k8stypes.NamespacedName{Namespace: ups.GetNamespace(), Name: node.Name} - ) - if err := r.Get(ctx, serviceNN, &service); err != nil { - r.Log.Error(err, "failed to get service in ApisixUpstream", "ApisixUpstream", upsNN, "Service", serviceNN) - if client.IgnoreNotFound(err) == nil { - continue - } - return err - } - tc.Services[utils.NamespacedName(&service)] = &service - } + if err := r.processExternalNodes(ctx, tc, ups); err != nil { + return err } - if ups.Spec.TLSSecret != nil && ups.Spec.TLSSecret.Name != "" { - var ( - secret corev1.Secret - secretNN = k8stypes.NamespacedName{Namespace: cmp.Or(ups.Spec.TLSSecret.Namespace, ar.GetNamespace()), Name: ups.Spec.TLSSecret.Name} - ) - if err := r.Get(ctx, secretNN, &secret); err != nil { - r.Log.Error(err, "failed to get secret in ApisixUpstream", "ApisixUpstream", upsNN, "Secret", secretNN) - if client.IgnoreNotFound(err) != nil { - return err - } - } - tc.Secrets[secretNN] = &secret + if err := r.processTLSSecret(ctx, tc, ups, ar.GetNamespace()); err != nil { + return err } } diff --git a/test/e2e/crds/v2/route.go b/test/e2e/crds/v2/route.go index 5b33d37df6..8681c193cd 100644 --- a/test/e2e/crds/v2/route.go +++ b/test/e2e/crds/v2/route.go @@ -25,6 +25,7 @@ import ( "net" "net/http" "net/url" + "strings" "time" "github.com/gorilla/websocket" @@ -1368,4 +1369,61 @@ spec: }) }) }) + Context("Test tls secret processed from ApisixUpstream", func() { + var Cert = strings.TrimSpace(framework.TestServerCert) + var Key = strings.TrimSpace(framework.TestServerKey) + createSecret := func(s *scaffold.Scaffold, secretName string) { + err := s.NewKubeTlsSecret(secretName, Cert, Key) + assert.Nil(GinkgoT(), err, "create secret error") + } + const apisixRouteSpec = ` +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: default + namespace: %s +spec: + ingressClassName: %s + http: + - name: rule0 + match: + hosts: + - httpbin + paths: + - /* + backends: + - serviceName: httpbin-service-e2e-test + servicePort: 80 + +` + const apisixUpstreamSpec = ` +apiVersion: apisix.apache.org/v2 +kind: ApisixUpstream +metadata: + name: httpbin-service-e2e-test + namespace: %s +spec: + ingressClassName: %s + tlsSecret: + name: %s + namespace: %s +` + + It("with matching backend", func() { + secretName := fmt.Sprintf("test-tls-secret-%s", s.Namespace()) + createSecret(s, secretName) + By("apply apisixupstream") + applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "httpbin-service-e2e-test"}, + new(apiv2.ApisixUpstream), fmt.Sprintf(apisixUpstreamSpec, s.Namespace(), s.Namespace(), secretName, s.Namespace())) + By("apply apisixroute") + applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "default"}, + new(apiv2.ApisixRoute), fmt.Sprintf(apisixRouteSpec, s.Namespace(), s.Namespace())) + time.Sleep(6 * time.Second) + services, err := s.DefaultDataplaneResource().Service().List(context.Background()) + Expect(err).ShouldNot(HaveOccurred(), "list services") + assert.Len(GinkgoT(), services, 1, "there should be one service") + service := services[0] + Expect(service.Upstream.TLS).ShouldNot(BeNil(), "check tls in service") + }) + }) })