From f2fc0b990c8f74fc46f5fa7c11bcc545f37c4f38 Mon Sep 17 00:00:00 2001 From: pastequo <40832495+pastequo@users.noreply.github.com> Date: Thu, 12 Oct 2023 11:00:20 +0200 Subject: [PATCH] Gateway filtering based on exposition annotation * feat: Filter based on exposition annotation * test: Add unit tests for gateway filtering based on annotations * test: Add some unit test case if no gateway matched exposition value --- pkg/reconciler/ingress/config/istio.go | 49 +++- pkg/reconciler/ingress/config/istio_test.go | 159 ++++++++++++ pkg/reconciler/ingress/ingress.go | 72 +----- pkg/reconciler/ingress/ingress_test.go | 129 ---------- pkg/reconciler/ingress/lister.go | 3 +- pkg/reconciler/ingress/lister_test.go | 116 +++++++++ pkg/reconciler/ingress/resources/gateway.go | 154 ++++++----- .../ingress/resources/gateway_test.go | 241 ++++++++++++------ pkg/reconciler/ingress/resources/secret.go | 10 +- .../ingress/resources/secret_test.go | 2 +- 10 files changed, 590 insertions(+), 345 deletions(-) diff --git a/pkg/reconciler/ingress/config/istio.go b/pkg/reconciler/ingress/config/istio.go index 70702801d8..a1ab053f5a 100644 --- a/pkg/reconciler/ingress/config/istio.go +++ b/pkg/reconciler/ingress/config/istio.go @@ -22,6 +22,7 @@ import ( "strings" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation" "knative.dev/pkg/network" "knative.dev/pkg/system" @@ -38,6 +39,9 @@ const ( // localGatewayKeyPrefix is the prefix of all keys to configure Istio gateways for public & private Ingresses. localGatewayKeyPrefix = "local-gateway." + // expositionKeyPrefix is the prefix of all keys to filter on Istio gateways. + expositionKeyPrefix = "exposition." + // KnativeIngressGateway is the name of the ingress gateway KnativeIngressGateway = "knative-ingress-gateway" @@ -69,9 +73,10 @@ func defaultLocalGateways() []Gateway { // Gateway specifies the name of the Gateway and the K8s Service backing it. type Gateway struct { - Namespace string - Name string - ServiceURL string + Namespace string + Name string + ServiceURL string + Expositions sets.Set[string] } // QualifiedName returns gateway name in '{namespace}/{name}' format. @@ -103,6 +108,9 @@ func parseGateways(configMap *corev1.ConfigMap, prefix string) ([]Gateway, error gatewayNames = append(gatewayNames, gatewayName) urls[gatewayName] = serviceURL } + + expositions := parseExposition(configMap) + sort.Strings(gatewayNames) gateways := make([]Gateway, len(gatewayNames)) for i, gatewayName := range gatewayNames { @@ -120,10 +128,45 @@ func parseGateways(configMap *corev1.ConfigMap, prefix string) ([]Gateway, error Name: name, ServiceURL: urls[gatewayName], } + + if expositionKeys, ok := expositions[fmt.Sprintf("%s.%s", namespace, name)]; ok { + gateways[i].Expositions = expositionKeys + } } return gateways, nil } +func parseExposition(configMap *corev1.ConfigMap) map[string]sets.Set[string] { + ret := make(map[string]sets.Set[string]) + + for k, v := range configMap.Data { + if !strings.HasPrefix(k, expositionKeyPrefix) || k == expositionKeyPrefix { + continue + } + + gatewayName, expositionKeys := k[len(expositionKeyPrefix):], v + + if !strings.Contains(gatewayName, ".") { + gatewayName = fmt.Sprintf("%s.%s", system.Namespace(), gatewayName) + } + + expositions := strings.Split(expositionKeys, ",") + for _, expo := range expositions { + toAdd := strings.TrimSpace(expo) + if len(toAdd) == 0 { + continue + } + if _, ok := ret[gatewayName]; !ok { + ret[gatewayName] = sets.New[string]() + } + + ret[gatewayName] = ret[gatewayName].Insert(toAdd) + } + } + + return ret +} + // NewIstioFromConfigMap creates an Istio config from the supplied ConfigMap func NewIstioFromConfigMap(configMap *corev1.ConfigMap) (*Istio, error) { gateways, err := parseGateways(configMap, gatewayKeyPrefix) diff --git a/pkg/reconciler/ingress/config/istio_test.go b/pkg/reconciler/ingress/config/istio_test.go index a6a464613b..791c7d1a52 100644 --- a/pkg/reconciler/ingress/config/istio_test.go +++ b/pkg/reconciler/ingress/config/istio_test.go @@ -22,6 +22,7 @@ import ( "github.com/google/go-cmp/cmp" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/sets" "knative.dev/pkg/system" . "knative.dev/pkg/configmap/testing" @@ -222,6 +223,164 @@ func TestGatewayConfiguration(t *testing.T) { "local-gateway.custom-namespace.invalid": "_invalid", }, }, + }, { + name: "local gateway configuration in custom namespace with valid url with exposition", + wantErr: false, + wantIstio: &Istio{ + IngressGateways: defaultIngressGateways(), + LocalGateways: []Gateway{ + { + Namespace: "custom-namespace-0", + Name: "custom-local-gateway-0", + ServiceURL: "istio-ingressbackroad.istio-system.svc.cluster.local", + }, + { + Namespace: "custom-namespace-1", + Name: "custom-local-gateway-1", + ServiceURL: "istio-ingressbackroad.istio-system.svc.cluster.local", + Expositions: sets.New[string]("some-value-1"), + }, + { + Namespace: "custom-namespace-2", + Name: "custom-local-gateway-2", + ServiceURL: "istio-ingressbackroad.istio-system.svc.cluster.local", + Expositions: sets.New[string]("some-value-2a", "some-value-2b"), + }}, + }, + config: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: system.Namespace(), + Name: IstioConfigName, + }, + Data: map[string]string{ + "local-gateway.custom-namespace-0.custom-local-gateway-0": "istio-ingressbackroad.istio-system.svc.cluster.local", + "local-gateway.custom-namespace-1.custom-local-gateway-1": "istio-ingressbackroad.istio-system.svc.cluster.local", + "local-gateway.custom-namespace-2.custom-local-gateway-2": "istio-ingressbackroad.istio-system.svc.cluster.local", + "exposition.custom-namespace-1.custom-local-gateway-1": "some-value-1", + "exposition.custom-namespace-2.custom-local-gateway-2": "some-value-2a,some-value-2b", + }, + }, + }, { + name: "gateway configuration defined with/without namespace with exposition defined with/without namespace", + wantErr: false, + wantIstio: &Istio{ + IngressGateways: []Gateway{ + { + Namespace: "knative-testing", + Name: "custom-gateway-wo-wi", + ServiceURL: "istio-ingressfreeway.istio-system.svc.cluster.local", + Expositions: sets.New[string]("some-value-wo-wi"), + }, + { + Namespace: "knative-testing", + Name: "custom-gateway-wo-wo", + ServiceURL: "istio-ingressfreeway.istio-system.svc.cluster.local", + Expositions: sets.New[string]("some-value-wo-wo"), + }, + { + Namespace: "knative-testing", + Name: "custom-gateway-wi-wi", + ServiceURL: "istio-ingressfreeway.istio-system.svc.cluster.local", + Expositions: sets.New[string]("some-value-wi-wi"), + }, + { + Namespace: "knative-testing", + Name: "custom-gateway-wi-wo", + ServiceURL: "istio-ingressfreeway.istio-system.svc.cluster.local", + Expositions: sets.New[string]("some-value-wi-wo"), + }}, + LocalGateways: defaultLocalGateways(), + }, + config: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: system.Namespace(), + Name: IstioConfigName, + }, + Data: map[string]string{ + "gateway.custom-gateway-wo-wo": "istio-ingressfreeway.istio-system.svc.cluster.local", + "gateway.custom-gateway-wo-wi": "istio-ingressfreeway.istio-system.svc.cluster.local", + "gateway.knative-testing.custom-gateway-wi-wo": "istio-ingressfreeway.istio-system.svc.cluster.local", + "gateway.knative-testing.custom-gateway-wi-wi": "istio-ingressfreeway.istio-system.svc.cluster.local", + "exposition.custom-gateway-wo-wo": "some-value-wo-wo", + "exposition.knative-testing.custom-gateway-wo-wi": "some-value-wo-wi", + "exposition.custom-gateway-wi-wo": "some-value-wi-wo", + "exposition.knative-testing.custom-gateway-wi-wi": "some-value-wi-wi", + }, + }, + }, { + name: "Same exposition defined for local and non-local gateways", + wantErr: false, + wantIstio: &Istio{ + IngressGateways: []Gateway{ + { + Namespace: "knative-testing", + Name: "custom-gateway-no-exposition", + ServiceURL: "istio-ingress1.istio-system.svc.cluster.local", + }, + { + Namespace: "knative-testing", + Name: "custom-gateway-with-exposition", + ServiceURL: "istio-ingress2.istio-system.svc.cluster.local", + Expositions: sets.New[string]("some-value"), + }, + }, + LocalGateways: []Gateway{ + { + Namespace: "knative-testing", + Name: "custom-gateway-no-exposition", + ServiceURL: "istio-ingress1.istio-system.svc.cluster.local", + }, + { + Namespace: "knative-testing", + Name: "custom-gateway-with-exposition", + ServiceURL: "istio-ingress2.istio-system.svc.cluster.local", + Expositions: sets.New[string]("some-value"), + }, + }, + }, + config: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: system.Namespace(), + Name: IstioConfigName, + }, + Data: map[string]string{ + "gateway.custom-gateway-no-exposition": "istio-ingress1.istio-system.svc.cluster.local", + "gateway.custom-gateway-with-exposition": "istio-ingress2.istio-system.svc.cluster.local", + "local-gateway.custom-gateway-no-exposition": "istio-ingress1.istio-system.svc.cluster.local", + "local-gateway.custom-gateway-with-exposition": "istio-ingress2.istio-system.svc.cluster.local", + "exposition.custom-gateway-with-exposition": "some-value", + }, + }, + }, { + name: "Exposition defined but referencing no known gateways", + wantErr: false, + wantIstio: &Istio{ + IngressGateways: []Gateway{ + { + Namespace: "knative-testing", + Name: "custom-gateway", + ServiceURL: "istio-ingress.istio-system.svc.cluster.local", + }, + }, + LocalGateways: []Gateway{ + { + Namespace: "knative-testing", + Name: "custom-local-gateway", + ServiceURL: "istio-ingress.istio-system.svc.cluster.local", + }, + }, + }, + config: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: system.Namespace(), + Name: IstioConfigName, + }, + Data: map[string]string{ + "gateway.custom-gateway": "istio-ingress.istio-system.svc.cluster.local", + "local-gateway.custom-local-gateway": "istio-ingress.istio-system.svc.cluster.local", + "exposition.unknown-value": "some-value", + }, + }, }} for _, tt := range gatewayConfigTests { diff --git a/pkg/reconciler/ingress/ingress.go b/pkg/reconciler/ingress/ingress.go index 1140885a6f..826a6792a4 100644 --- a/pkg/reconciler/ingress/ingress.go +++ b/pkg/reconciler/ingress/ingress.go @@ -111,10 +111,7 @@ func (r *Reconciler) reconcileIngress(ctx context.Context, ing *v1alpha1.Ingress ing.Status.InitializeConditions() logger.Infof("Reconciling ingress: %#v", ing) - defaultGateways, err := computeDefaultGateways(ctx, ing) - if err != nil { - return fmt.Errorf("failed to compute default gateways: %w", err) - } + defaultGateways := resources.QualifiedGatewayNamesFromContext(ctx, ing) gatewayNames := map[v1alpha1.IngressVisibility]sets.Set[string]{} gatewayNames[v1alpha1.IngressVisibilityClusterLocal] = defaultGateways[v1alpha1.IngressVisibilityClusterLocal] @@ -134,7 +131,7 @@ func (r *Reconciler) reconcileIngress(ctx context.Context, ing *v1alpha1.Ingress if err != nil { return err } - targetWildcardSecrets, err := resources.MakeWildcardSecrets(ctx, wildcardSecrets) + targetWildcardSecrets, err := resources.MakeWildcardSecrets(ctx, wildcardSecrets, ing) if err != nil { return err } @@ -226,8 +223,8 @@ func (r *Reconciler) reconcileIngress(ctx context.Context, ing *v1alpha1.Ingress } if ready { - publicLbs := getLBStatus(publicGatewayServiceURLFromContext(ctx)) - privateLbs := getLBStatus(privateGatewayServiceURLFromContext(ctx)) + publicLbs := getLBStatus(resources.PublicGatewayServiceURLFromContext(ctx, ing)) + privateLbs := getLBStatus(resources.PrivateGatewayServiceURLFromContext(ctx, ing)) ing.Status.MarkLoadBalancerReady(publicLbs, privateLbs) } else { ing.Status.MarkLoadBalancerNotReady() @@ -373,7 +370,7 @@ func (r *Reconciler) reconcileDeletion(ctx context.Context, ing *v1alpha1.Ingres errs := []error{} for _, tls := range ing.Spec.TLS { - nameNamespaces, err := resources.GetIngressGatewaySvcNameNamespaces(ctx) + nameNamespaces, err := resources.GetIngressGatewaySvcNameNamespaces(ctx, ing) if err != nil { errs = append(errs, err) continue @@ -441,41 +438,6 @@ func (r *Reconciler) GetVirtualServiceLister() istiolisters.VirtualServiceLister return r.virtualServiceLister } -// qualifiedGatewayNamesFromContext get gateway names from context -func qualifiedGatewayNamesFromContext(ctx context.Context) map[v1alpha1.IngressVisibility]sets.Set[string] { - ci := config.FromContext(ctx).Istio - publicGateways := sets.New[string]() - for _, gw := range ci.IngressGateways { - publicGateways.Insert(gw.QualifiedName()) - } - - privateGateways := sets.New[string]() - for _, gw := range ci.LocalGateways { - privateGateways.Insert(gw.QualifiedName()) - } - - return map[v1alpha1.IngressVisibility]sets.Set[string]{ - v1alpha1.IngressVisibilityExternalIP: publicGateways, - v1alpha1.IngressVisibilityClusterLocal: privateGateways, - } -} - -func publicGatewayServiceURLFromContext(ctx context.Context) string { - cfg := config.FromContext(ctx).Istio - if len(cfg.IngressGateways) > 0 { - return cfg.IngressGateways[0].ServiceURL - } - return "" -} - -func privateGatewayServiceURLFromContext(ctx context.Context) string { - cfg := config.FromContext(ctx).Istio - if len(cfg.LocalGateways) > 0 { - return cfg.LocalGateways[0].ServiceURL - } - return "" -} - // getLBStatus gets the LB Status. func getLBStatus(gatewayServiceURL string) []v1alpha1.LoadBalancerIngressStatus { // The Ingress isn't load-balanced by any particular @@ -509,27 +471,3 @@ func isIngressPublic(ing *v1alpha1.Ingress) bool { } return false } - -func computeDefaultGateways(ctx context.Context, ing *v1alpha1.Ingress) (map[v1alpha1.IngressVisibility]sets.String, error) { - ret := qualifiedGatewayNamesFromContext(ctx) // gateways from config - - for _, visibility := range []v1alpha1.IngressVisibility{v1alpha1.IngressVisibilityClusterLocal, v1alpha1.IngressVisibilityExternalIP} { - gateways, err := resources.GetGatewaysFromAnnotations(ing, visibility) - if err != nil { - return nil, fmt.Errorf("failed to get %s gateways from annotation: %w", visibility, err) - } - - // Ensure all gateways are known in the configuration - unknownGateways := gateways.Difference(ret[visibility]) - if unknownGateways.Len() > 0 { - return nil, fmt.Errorf("following qualified name(s) aren't defined in the configuration (%s): %v", visibility, unknownGateways.List()) - } - - // If ingress specifies gateways, restrict to them - if gateways.Len() > 0 { - ret[visibility] = gateways - } - } - - return ret, nil -} diff --git a/pkg/reconciler/ingress/ingress_test.go b/pkg/reconciler/ingress/ingress_test.go index 4abe4abb63..680d756618 100644 --- a/pkg/reconciler/ingress/ingress_test.go +++ b/pkg/reconciler/ingress/ingress_test.go @@ -1534,132 +1534,3 @@ func proberCalledTimes(n int) func(*testing.T, *TableRow) { } } } - -func TestComputeDefaultGateways(t *testing.T) { - type Expectation struct { - Error bool - Values map[v1alpha1.IngressVisibility]sets.String - } - - cases := []struct { - name string - cfg *config.Istio - ingress *v1alpha1.Ingress - want Expectation - }{ - { - name: "All match", - cfg: &config.Istio{ - IngressGateways: []config.Gateway{ - {Namespace: "ns1", Name: "gtw1"}, - }, - LocalGateways: []config.Gateway{ - {Namespace: "ns1", Name: "gtw2"}, - {Namespace: "ns2", Name: "gtw3"}, - }, - }, - ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ - resources.PublicGatewayAnnotation: "ns1/gtw1", - resources.LocalGatewaysAnnotation: "ns1/gtw2,ns2/gtw3", - }}}, - want: Expectation{ - Values: map[v1alpha1.IngressVisibility]sets.String{ - v1alpha1.IngressVisibilityExternalIP: sets.NewString("ns1/gtw1"), - v1alpha1.IngressVisibilityClusterLocal: sets.NewString("ns1/gtw2", "ns2/gtw3"), - }, - }, - }, - { - name: "Partial match", - cfg: &config.Istio{ - IngressGateways: []config.Gateway{ - {Namespace: "ns1", Name: "gtw1"}, - {Namespace: "ns1", Name: "wontmatch"}, - {Namespace: "wontmatch", Name: "gtw1"}, - }, - LocalGateways: []config.Gateway{ - {Namespace: "ns1", Name: "gtw2"}, - }, - }, - ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ - resources.PublicGatewayAnnotation: "ns1/gtw1", - resources.LocalGatewaysAnnotation: "ns1/gtw2", - }}}, - want: Expectation{ - Values: map[v1alpha1.IngressVisibility]sets.String{ - v1alpha1.IngressVisibilityExternalIP: sets.NewString("ns1/gtw1"), - v1alpha1.IngressVisibilityClusterLocal: sets.NewString("ns1/gtw2"), - }, - }, - }, - { - name: "No annotation", - cfg: &config.Istio{ - IngressGateways: []config.Gateway{ - {Namespace: "ns1", Name: "gtw1"}, - }, - LocalGateways: []config.Gateway{ - {Namespace: "ns1", Name: "gtw2"}, - }, - }, - ingress: &v1alpha1.Ingress{}, - want: Expectation{ - Values: map[v1alpha1.IngressVisibility]sets.String{ - v1alpha1.IngressVisibilityExternalIP: sets.NewString("ns1/gtw1"), - v1alpha1.IngressVisibilityClusterLocal: sets.NewString("ns1/gtw2"), - }, - }, - }, - { - name: "Invalid values in annotation", - cfg: &config.Istio{ - IngressGateways: []config.Gateway{ - {Namespace: "ns1", Name: "gtw1"}, - }, - LocalGateways: []config.Gateway{ - {Namespace: "ns1", Name: "gtw2"}, - }, - }, - ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ - resources.PublicGatewayAnnotation: "ns1.gtw1", - }}}, - want: Expectation{ - Error: true, - }, - }, - { - name: "Unknown values in annotation", - cfg: &config.Istio{ - IngressGateways: []config.Gateway{ - {Namespace: "ns1", Name: "gtw1"}, - }, - LocalGateways: []config.Gateway{ - {Namespace: "ns1", Name: "gtw2"}, - }, - }, - ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ - resources.PublicGatewayAnnotation: "unknown/unknown", - }}}, - want: Expectation{ - Error: true, - }, - }, - } - - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - ctx := config.ToContext(context.Background(), &config.Config{Istio: c.cfg}) - got, err := computeDefaultGateways(ctx, c.ingress) - - if (err != nil) != c.want.Error { - t.Errorf("Expecting error: %v, got error: %v", c.want.Error, err) - } - - if !c.want.Error { - if diff := cmp.Diff(c.want.Values, got); diff != "" { - t.Error("Unexpected Gateways (-want, +got):", diff) - } - } - }) - } -} diff --git a/pkg/reconciler/ingress/lister.go b/pkg/reconciler/ingress/lister.go index b529d9d3f3..70d2cd103f 100644 --- a/pkg/reconciler/ingress/lister.go +++ b/pkg/reconciler/ingress/lister.go @@ -31,6 +31,7 @@ import ( corev1listers "k8s.io/client-go/listers/core/v1" "k8s.io/client-go/tools/cache" istiolisters "knative.dev/net-istio/pkg/client/istio/listers/networking/v1beta1" + "knative.dev/net-istio/pkg/reconciler/ingress/resources" "knative.dev/networking/pkg/apis/networking/v1alpha1" "knative.dev/networking/pkg/ingress" "knative.dev/networking/pkg/k8s" @@ -60,7 +61,7 @@ type gatewayPodTargetLister struct { func (l *gatewayPodTargetLister) ListProbeTargets(ctx context.Context, ing *v1alpha1.Ingress) ([]status.ProbeTarget, error) { results := []status.ProbeTarget{} - hostsByGateway := ingress.HostsPerVisibility(ing, convertVisibilityMap(qualifiedGatewayNamesFromContext(ctx))) + hostsByGateway := ingress.HostsPerVisibility(ing, convertVisibilityMap(resources.QualifiedGatewayNamesFromContext(ctx, ing))) gatewayNames := make([]string, 0, len(hostsByGateway)) for gatewayName := range hostsByGateway { gatewayNames = append(gatewayNames, gatewayName) diff --git a/pkg/reconciler/ingress/lister_test.go b/pkg/reconciler/ingress/lister_test.go index 955350be24..6a0fad7a2b 100644 --- a/pkg/reconciler/ingress/lister_test.go +++ b/pkg/reconciler/ingress/lister_test.go @@ -29,6 +29,7 @@ import ( istiov1beta1 "istio.io/api/networking/v1beta1" v1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" "knative.dev/net-istio/pkg/reconciler/ingress/config" + "knative.dev/net-istio/pkg/reconciler/ingress/resources" "knative.dev/networking/pkg/apis/networking/v1alpha1" "knative.dev/networking/pkg/status" @@ -1491,6 +1492,121 @@ func TestListProbeTargets(t *testing.T) { Port: "80", URLs: []*url.URL{{Scheme: "http", Host: "foo.bar.com:80"}}, }}, + }, { + name: "one gateway matched", + ingressGateways: []config.Gateway{ + { + Name: "gateway-not-matching", + Namespace: "default", + }, + { + Name: "gateway-matching", + Namespace: "default", + Expositions: sets.New[string]("my-exposition"), + }}, + gatewayLister: &fakeGatewayLister{ + gateways: []*v1beta1.Gateway{{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "gateway-not-matching", + }, + Spec: istiov1beta1.Gateway{ + Servers: []*istiov1beta1.Server{{ + Hosts: []string{"*"}, + Port: &istiov1beta1.Port{ + Name: "http", + Number: 8888, + Protocol: "HTTP", + }, + }}, + Selector: map[string]string{ + "gwt": "istio-not-matching", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "gateway-matching", + }, + Spec: istiov1beta1.Gateway{ + Servers: []*istiov1beta1.Server{{ + Hosts: []string{"*"}, + Port: &istiov1beta1.Port{ + Name: "http", + Number: 8080, + Protocol: "HTTP", + }, + }}, + Selector: map[string]string{ + "gwt": "istio", + }, + }, + }}, + }, + endpointsLister: &fakeEndpointsLister{ + endpointses: []*v1.Endpoints{{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "gateway-matching", + }, + Subsets: []v1.EndpointSubset{{ + Ports: []v1.EndpointPort{{ + Name: "bogus", + Port: 8081, + }, { + Name: "real", + Port: 8080, + }}, + Addresses: []v1.EndpointAddress{{ + IP: "1.1.1.1", + }}, + }}, + }}, + }, + serviceLister: &fakeServiceLister{ + services: []*v1.Service{{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "gateway-matching", + Labels: map[string]string{ + "gwt": "istio", + }, + }, + Spec: v1.ServiceSpec{ + Ports: []v1.ServicePort{{ + Name: "bogus", + Port: 8081, + }, { + Name: "real", + Port: 8080, + }}, + }, + }}, + }, + ingress: &v1alpha1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "whatever", + Annotations: map[string]string{ + resources.ExpositionAnnotation: "my-exposition", + }, + }, + Spec: v1alpha1.IngressSpec{ + Rules: []v1alpha1.IngressRule{{ + Hosts: []string{ + "foo.bar.com", + }, + Visibility: v1alpha1.IngressVisibilityExternalIP, + }}, + }, + }, + results: []status.ProbeTarget{{ + PodIPs: sets.NewString("1.1.1.1"), + PodPort: "8080", + Port: "8080", + URLs: []*url.URL{{Scheme: "http", Host: "foo.bar.com:8080"}}, + }}, }} for _, test := range tests { diff --git a/pkg/reconciler/ingress/resources/gateway.go b/pkg/reconciler/ingress/resources/gateway.go index f0b8be006b..d841094481 100644 --- a/pkg/reconciler/ingress/resources/gateway.go +++ b/pkg/reconciler/ingress/resources/gateway.go @@ -46,10 +46,9 @@ const ( dns1123LabelMaxLength = 63 // Public for testing only. dns1123LabelFmt = "[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?" - // Ingress annotation to select gateways + // Ingress annotation to select gateways thru exposition flag // public for testing purposes - PublicGatewayAnnotation = "serving.knative.dev/istio-gateways" - LocalGatewaysAnnotation = "serving.knative.dev/istio-local-gateways" + ExpositionAnnotation = "serving.knative.dev/istio-exposition" ) var httpServerPortName = "http-server" @@ -268,17 +267,7 @@ func makeIngressGateway(ing *v1alpha1.Ingress, selector map[string]string, serve } func getGatewayServices(ctx context.Context, ing *v1alpha1.Ingress, svcLister corev1listers.ServiceLister) ([]*corev1.Service, error) { - restrictedGateways, err := GetGatewaysFromAnnotations(ing, v1alpha1.IngressVisibilityExternalIP) - if err != nil { - return nil, err - } - - filter := FilterOption{} - if restrictedGateways.Len() > 0 { - filter.QualifiedNames = &restrictedGateways - } - - ingressSvcMetas, err := GetSelectedIngressGatewaySvcNameNamespaces(ctx, filter) + ingressSvcMetas, err := GetIngressGatewaySvcNameNamespaces(ctx, ing) if err != nil { return nil, err } @@ -396,43 +385,17 @@ func GetNonWildcardIngressTLS(ingressTLS []v1alpha1.IngressTLS, nonWildcardSecre return result } -// GetIngressGatewaySvcNameNamespaces gets the Istio ingress namespaces from ConfigMap. -func GetIngressGatewaySvcNameNamespaces(ctx context.Context) ([]metav1.ObjectMeta, error) { - return getSelectedIngressGatewaySvcNameNamespaces(ctx, FilterOption{}) -} +// GetIngressGatewaySvcNameNamespaces gets the Istio ingress namespaces from ConfigMap for gateways which should expose the service. +func GetIngressGatewaySvcNameNamespaces(ctx context.Context, ing *v1alpha1.Ingress) ([]metav1.ObjectMeta, error) { + nameNamespaces := make([]metav1.ObjectMeta, 0) -type FilterOption struct { - QualifiedNames *sets.String -} - -// GetSelectedIngressGatewaySvcNameNamespaces gets the Istio ingress namespaces from ConfigMap for gateways which qualified name is in the list. -func GetSelectedIngressGatewaySvcNameNamespaces(ctx context.Context, filter FilterOption) ([]metav1.ObjectMeta, error) { - return getSelectedIngressGatewaySvcNameNamespaces(ctx, filter) -} - -func getSelectedIngressGatewaySvcNameNamespaces(ctx context.Context, filter FilterOption) ([]metav1.ObjectMeta, error) { - cfg := config.FromContext(ctx).Istio - - // If there is a filter, ensure all names are known in the config - if filter.QualifiedNames != nil { - knownNames := sets.NewString() - for _, ingressgateway := range cfg.IngressGateways { - knownNames.Insert(ingressgateway.QualifiedName()) - } - - unknownGateways := filter.QualifiedNames.Difference(knownNames) - if unknownGateways.Len() > 0 { - return nil, fmt.Errorf("following qualified name(s) aren't defined in the configuration: %v", unknownGateways.List()) - } + serviceGateways := gatewaysFromContext(ctx, ing) + servicePublicGateways, ok := serviceGateways[v1alpha1.IngressVisibilityExternalIP] + if !ok { + return nameNamespaces, nil } - nameNamespaces := make([]metav1.ObjectMeta, 0, len(cfg.IngressGateways)) - - for _, ingressgateway := range cfg.IngressGateways { - if filter.QualifiedNames != nil && !filter.QualifiedNames.Has(ingressgateway.QualifiedName()) { - continue - } - + for _, ingressgateway := range servicePublicGateways { meta, err := parseIngressGatewayConfig(ingressgateway) if err != nil { return nil, err @@ -492,35 +455,92 @@ func isPlaceHolderServer(server *istiov1beta1.Server) bool { return cmp.Equal(server, &placeholderServer, protocmp.Transform()) } -// GetGatewaysFromAnnotations extracts Gateways from ingress annotations. -func GetGatewaysFromAnnotations(ing *v1alpha1.Ingress, visibility v1alpha1.IngressVisibility) (sets.String, error) { - annotation := "" +// QualifiedGatewayNamesFromContext get gateway names from context. +func QualifiedGatewayNamesFromContext(ctx context.Context, ing *v1alpha1.Ingress) map[v1alpha1.IngressVisibility]sets.Set[string] { + ret := make(map[v1alpha1.IngressVisibility]sets.Set[string]) + + gateways := gatewaysFromContext(ctx, ing) + + for _, visibility := range []v1alpha1.IngressVisibility{v1alpha1.IngressVisibilityClusterLocal, v1alpha1.IngressVisibilityExternalIP} { + ret[visibility] = sets.New[string]() - switch visibility { - case v1alpha1.IngressVisibilityClusterLocal: - annotation = LocalGatewaysAnnotation - case v1alpha1.IngressVisibilityExternalIP: - annotation = PublicGatewayAnnotation - default: - return nil, fmt.Errorf("unexpected visibility value: %s", visibility) + for _, gtw := range gateways[visibility] { + ret[visibility] = ret[visibility].Insert(gtw.QualifiedName()) + } } - ret := sets.NewString() + return ret +} + +// getExpositionFromAnnotation extracts exposition values from ingress annotations. +func getExpositionFromAnnotation(ing *v1alpha1.Ingress) sets.Set[string] { + ret := sets.New[string]() - filters, ok := ing.ObjectMeta.Annotations[annotation] + filters, ok := ing.ObjectMeta.Annotations[ExpositionAnnotation] if !ok { - return ret, nil + return ret } - for _, gtw := range strings.Split(filters, ",") { - qualifiedName := strings.TrimSpace(gtw) + for _, expo := range strings.Split(filters, ",") { + toAdd := strings.TrimSpace(expo) + if len(toAdd) == 0 { + continue + } + + ret = ret.Insert(toAdd) + } + + return ret +} + +// gatewaysFromContext get gateways relevant to this ingress from context. +func gatewaysFromContext(ctx context.Context, ing *v1alpha1.Ingress) map[v1alpha1.IngressVisibility][]config.Gateway { + ret := make(map[v1alpha1.IngressVisibility][]config.Gateway) + + expositions := getExpositionFromAnnotation(ing) + + istioConfig := config.FromContext(ctx).Istio + + ret[v1alpha1.IngressVisibilityExternalIP] = filterGatewayFromList(istioConfig.IngressGateways, expositions) + ret[v1alpha1.IngressVisibilityClusterLocal] = filterGatewayFromList(istioConfig.LocalGateways, expositions) + + return ret +} + +func filterGatewayFromList(gateways []config.Gateway, exposition sets.Set[string]) []config.Gateway { + ret := make([]config.Gateway, 0, len(gateways)) - if !strings.Contains(qualifiedName, "/") { - return nil, fmt.Errorf("values in %s should be qualified name ($namespace/$name), got: %s", annotation, qualifiedName) + for i := range gateways { + gtw := gateways[i] + + if exposition.Len() > 0 { + matchedExpositions := gtw.Expositions.Intersection(exposition) + if matchedExpositions.Len() == 0 { + continue + } } - ret.Insert(qualifiedName) + ret = append(ret, gtw) } - return ret, nil + return ret +} + +func PublicGatewayServiceURLFromContext(ctx context.Context, ing *v1alpha1.Ingress) string { + return getGatewayServiceURLFromContext(ctx, ing, v1alpha1.IngressVisibilityExternalIP) +} + +func PrivateGatewayServiceURLFromContext(ctx context.Context, ing *v1alpha1.Ingress) string { + return getGatewayServiceURLFromContext(ctx, ing, v1alpha1.IngressVisibilityClusterLocal) +} + +func getGatewayServiceURLFromContext(ctx context.Context, ing *v1alpha1.Ingress, visibility v1alpha1.IngressVisibility) string { + allGateways := gatewaysFromContext(ctx, ing) + + gateways, ok := allGateways[visibility] + if ok && len(gateways) > 0 { + return gateways[0].ServiceURL + } + + return "" } diff --git a/pkg/reconciler/ingress/resources/gateway_test.go b/pkg/reconciler/ingress/resources/gateway_test.go index 85951309b9..0702a25168 100644 --- a/pkg/reconciler/ingress/resources/gateway_test.go +++ b/pkg/reconciler/ingress/resources/gateway_test.go @@ -162,7 +162,7 @@ var ingressResourceWithPublicGatewayAnnotation = v1alpha1.Ingress{ Name: "ingress", Namespace: "test-ns", Annotations: map[string]string{ - PublicGatewayAnnotation: "knative-serving/gateway1", + ExpositionAnnotation: "my-exposition", }, }, Spec: ingressSpec, @@ -794,9 +794,10 @@ func TestMakeIngressGateways(t *testing.T) { Istio: &config.Istio{ IngressGateways: []config.Gateway{ { - Namespace: "knative-serving", - Name: "gateway1", - ServiceURL: "gateway1.aNamespace.svc.cluster.local", + Namespace: "knative-serving", + Name: "gateway1", + ServiceURL: "gateway1.aNamespace.svc.cluster.local", + Expositions: sets.New[string]("my-exposition"), }, { Namespace: "knative-serving", @@ -846,11 +847,11 @@ func TestMakeIngressGateways(t *testing.T) { "istio": "ingressgateway1", }, &modifiedDefaultTLSServer)}, }, { - name: "Unknown gateway", + name: "No gateway matched", ia: &ingressResourceWithPublicGatewayAnnotation, - conf: configDefaultGateway, // default config doesn't have the agteways defined in ingressResourceWithPublicGatewayAnnotation + conf: configDefaultGateway, // default config doesn't have the gateways defined in ingressResourceWithPublicGatewayAnnotation servers: []*istiov1beta1.Server{&httpServer}, - wantErr: true, + want: []*v1beta1.Gateway{}, }} for _, c := range cases { ctx, cancel, _ := rtesting.SetupFakeContextWithCancel(t) @@ -1099,96 +1100,78 @@ func TestGatewayNameLongIngressName(t *testing.T) { } } -func TestGetGatewaysFromAnnotations(t *testing.T) { - type Expectation struct { - Error bool - Values sets.String - } - +func TestGetExpositionFromAnnotation(t *testing.T) { cases := []struct { - name string - ingress *v1alpha1.Ingress - wantForPublic Expectation - wantForLocal Expectation + name string + ingress *v1alpha1.Ingress + want sets.Set[string] }{ { - name: "Happy path", + name: "Happy path - single value", ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ - PublicGatewayAnnotation: "ns1/gtw1", - LocalGatewaysAnnotation: "ns1/gtw2,ns2/gtw3", + ExpositionAnnotation: "expo", }}}, - wantForPublic: Expectation{Values: sets.NewString("ns1/gtw1")}, - wantForLocal: Expectation{Values: sets.NewString("ns1/gtw2", "ns2/gtw3")}, + want: sets.New[string]("expo"), }, { - name: "No annotation", - ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{}}}, - wantForPublic: Expectation{Values: sets.NewString()}, - wantForLocal: Expectation{Values: sets.NewString()}, + name: "Happy path - multiple values", + ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ + ExpositionAnnotation: "expo1,expo2", + }}}, + want: sets.New[string]("expo1", "expo2"), + }, + { + name: "No annotation", + ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{}}}, + want: sets.New[string](), }, { - name: "Invalid annotation", + name: "Annotation with spaces", ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ - PublicGatewayAnnotation: "ns1.gtw1", - LocalGatewaysAnnotation: "ns1/gtw2,ns2.gtw3", + ExpositionAnnotation: " expo ", }}}, - wantForPublic: Expectation{Error: true}, - wantForLocal: Expectation{Error: true}, + want: sets.New[string]("expo"), }, { - name: "Annotation with spaces", + name: "Multiple annotation with spaces", + ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ + ExpositionAnnotation: "expo1 , expo2 ", + }}}, + want: sets.New[string]("expo1", "expo2"), + }, + { + name: "Empty value", + ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ + ExpositionAnnotation: "", + }}}, + want: sets.New[string](), + }, + { + name: "Only comma", + ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ + ExpositionAnnotation: ",", + }}}, + want: sets.New[string](), + }, + { + name: "Empty values in list", ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ - PublicGatewayAnnotation: " ns1/gtw1 ", - LocalGatewaysAnnotation: "ns1/gtw2 , ns2/gtw3 ", + ExpositionAnnotation: ",,expo,", }}}, - wantForPublic: Expectation{Values: sets.NewString("ns1/gtw1")}, - wantForLocal: Expectation{Values: sets.NewString("ns1/gtw2", "ns2/gtw3")}, + want: sets.New[string]("expo"), }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { - gotPublic, err := GetGatewaysFromAnnotations(c.ingress, v1alpha1.IngressVisibilityExternalIP) - if (err != nil) != c.wantForPublic.Error { - t.Errorf("Expecting error for public: %v, got error: %v", c.wantForPublic.Error, err) - } - - if !c.wantForPublic.Error { - if diff := cmp.Diff(c.wantForPublic.Values, gotPublic); diff != "" { - t.Error("Unexpected public Gateways (-want, +got):", diff) - } - } - - gotLocal, err := GetGatewaysFromAnnotations(c.ingress, v1alpha1.IngressVisibilityClusterLocal) - if (err != nil) != c.wantForLocal.Error { - t.Errorf("Expecting error for local: %v, got error: %v", c.wantForLocal.Error, err) - } - - if !c.wantForLocal.Error { - if diff := cmp.Diff(c.wantForLocal.Values, gotLocal); diff != "" { - t.Error("Unexpected local Gateways (-want, +got):", diff) - } + got := getExpositionFromAnnotation(c.ingress) + if diff := cmp.Diff(c.want, got); diff != "" { + t.Error("Unexpected Expositions (-want, +got):", diff) } }) } } -func TestGetGatewaysFromAnnotationsInvalidVisibility(t *testing.T) { - ingress := &v1alpha1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{ - PublicGatewayAnnotation: "ns1/gtw1", - LocalGatewaysAnnotation: "ns1/gtw2,ns2/gtw3", - }, - }, - } - - _, err := GetGatewaysFromAnnotations(ingress, v1alpha1.IngressVisibility("doesn't exist")) - if err == nil { - t.Errorf("Expecting error for invalid ingress visibiliy") - } -} - func TestParseIngressGatewayConfig(t *testing.T) { type Expectation struct { Error bool @@ -1237,3 +1220,117 @@ func TestParseIngressGatewayConfig(t *testing.T) { }) } } + +func TestQualifiedGatewayNamesFromContext(t *testing.T) { + cases := []struct { + name string + cfg *config.Istio + ingress *v1alpha1.Ingress + want map[v1alpha1.IngressVisibility]sets.Set[string] + }{ + { + name: "All match", + cfg: &config.Istio{ + IngressGateways: []config.Gateway{ + {Namespace: "ns1", Name: "gtw1", Expositions: sets.New[string]("expo")}, + }, + LocalGateways: []config.Gateway{ + {Namespace: "ns1", Name: "gtw2", Expositions: sets.New[string]("expo")}, + {Namespace: "ns2", Name: "gtw3", Expositions: sets.New[string]("expo")}, + }, + }, + ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ + ExpositionAnnotation: "expo", + }}}, + want: map[v1alpha1.IngressVisibility]sets.Set[string]{ + v1alpha1.IngressVisibilityExternalIP: sets.New[string]("ns1/gtw1"), + v1alpha1.IngressVisibilityClusterLocal: sets.New[string]("ns1/gtw2", "ns2/gtw3"), + }, + }, + { + name: "Different expo", + cfg: &config.Istio{ + IngressGateways: []config.Gateway{ + {Namespace: "ns1", Name: "gtw1", Expositions: sets.New[string]("expo1")}, + }, + LocalGateways: []config.Gateway{ + {Namespace: "ns1", Name: "gtw2", Expositions: sets.New[string]("expo2")}, + {Namespace: "ns2", Name: "gtw3", Expositions: sets.New[string]("expo3")}, + }, + }, + ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ + ExpositionAnnotation: "expo1,expo3", + }}}, + want: map[v1alpha1.IngressVisibility]sets.Set[string]{ + v1alpha1.IngressVisibilityExternalIP: sets.New[string]("ns1/gtw1"), + v1alpha1.IngressVisibilityClusterLocal: sets.New[string]("ns2/gtw3"), + }, + }, + { + name: "Partial match", + cfg: &config.Istio{ + IngressGateways: []config.Gateway{ + {Namespace: "ns1", Name: "gtw1", Expositions: sets.New[string]("expo")}, + {Namespace: "wontmatch", Name: "wontmatch1", Expositions: sets.New[string]("another-expo")}, + {Namespace: "wontmatch", Name: "wontmatch2"}, + }, + LocalGateways: []config.Gateway{ + {Namespace: "ns1", Name: "gtw2", Expositions: sets.New[string]("expo")}, + }, + }, + ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ + ExpositionAnnotation: "expo", + }}}, + want: map[v1alpha1.IngressVisibility]sets.Set[string]{ + v1alpha1.IngressVisibilityExternalIP: sets.New[string]("ns1/gtw1"), + v1alpha1.IngressVisibilityClusterLocal: sets.New[string]("ns1/gtw2"), + }, + }, + { + name: "Unknown exposition", + cfg: &config.Istio{ + IngressGateways: []config.Gateway{ + {Namespace: "ns1", Name: "gtw1", Expositions: sets.New[string]("expo1")}, + }, + LocalGateways: []config.Gateway{ + {Namespace: "ns1", Name: "gtw2", Expositions: sets.New[string]("expo2")}, + }, + }, + ingress: &v1alpha1.Ingress{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ + ExpositionAnnotation: "unknown-value", + }}}, + want: map[v1alpha1.IngressVisibility]sets.Set[string]{ + v1alpha1.IngressVisibilityExternalIP: sets.New[string](), + v1alpha1.IngressVisibilityClusterLocal: sets.New[string](), + }, + }, + { + name: "No annotation", + cfg: &config.Istio{ + IngressGateways: []config.Gateway{ + {Namespace: "ns1", Name: "gtw1"}, + }, + LocalGateways: []config.Gateway{ + {Namespace: "ns1", Name: "gtw2"}, + }, + }, + ingress: &v1alpha1.Ingress{}, + want: map[v1alpha1.IngressVisibility]sets.Set[string]{ + v1alpha1.IngressVisibilityExternalIP: sets.New[string]("ns1/gtw1"), + v1alpha1.IngressVisibilityClusterLocal: sets.New[string]("ns1/gtw2"), + }, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + ctx := config.ToContext(context.Background(), &config.Config{Istio: c.cfg}) + + got := QualifiedGatewayNamesFromContext(ctx, c.ingress) + if diff := cmp.Diff(c.want, got); diff != "" { + t.Error("Unexpected Gateways (-want, +got):", diff) + } + + }) + } +} diff --git a/pkg/reconciler/ingress/resources/secret.go b/pkg/reconciler/ingress/resources/secret.go index e60be44cc5..fe5a8266be 100644 --- a/pkg/reconciler/ingress/resources/secret.go +++ b/pkg/reconciler/ingress/resources/secret.go @@ -52,8 +52,8 @@ func GetSecrets(ing *v1alpha1.Ingress, secretLister corev1listers.SecretLister) } // MakeSecrets makes copies of the origin Secrets under the namespace of Istio gateway service. -func MakeSecrets(ctx context.Context, originSecrets map[string]*corev1.Secret, accessor kmeta.OwnerRefableAccessor) ([]*corev1.Secret, error) { - nameNamespaces, err := GetIngressGatewaySvcNameNamespaces(ctx) +func MakeSecrets(ctx context.Context, originSecrets map[string]*corev1.Secret, ing *v1alpha1.Ingress) ([]*corev1.Secret, error) { + nameNamespaces, err := GetIngressGatewaySvcNameNamespaces(ctx, ing) if err != nil { return nil, err } @@ -65,7 +65,7 @@ func MakeSecrets(ctx context.Context, originSecrets map[string]*corev1.Secret, a // as the origin namespace continue } - secrets = append(secrets, makeSecret(originSecret, targetSecret(originSecret, accessor), meta.Namespace, + secrets = append(secrets, makeSecret(originSecret, targetSecret(originSecret, ing), meta.Namespace, MakeTargetSecretLabels(originSecret.Name, originSecret.Namespace), MakeTargetSecretAnnotations(originSecret.Name))) } } @@ -74,8 +74,8 @@ func MakeSecrets(ctx context.Context, originSecrets map[string]*corev1.Secret, a // MakeWildcardSecrets copies wildcard certificates from origin namespace to the namespace of gateway servicess so they could // consumed by Istio ingress. -func MakeWildcardSecrets(ctx context.Context, originWildcardCerts map[string]*corev1.Secret) ([]*corev1.Secret, error) { - nameNamespaces, err := GetIngressGatewaySvcNameNamespaces(ctx) +func MakeWildcardSecrets(ctx context.Context, originWildcardCerts map[string]*corev1.Secret, ing *v1alpha1.Ingress) ([]*corev1.Secret, error) { + nameNamespaces, err := GetIngressGatewaySvcNameNamespaces(ctx, ing) if err != nil { return nil, err } diff --git a/pkg/reconciler/ingress/resources/secret_test.go b/pkg/reconciler/ingress/resources/secret_test.go index 3a7815dd66..d948174ac1 100644 --- a/pkg/reconciler/ingress/resources/secret_test.go +++ b/pkg/reconciler/ingress/resources/secret_test.go @@ -280,7 +280,7 @@ func TestMakeWildcardSecrets(t *testing.T) { originSecrets := map[string]*corev1.Secret{ fmt.Sprintf("%s/%s", c.originSecret.Namespace, c.originSecret.Name): c.originSecret, } - secrets, err := MakeWildcardSecrets(ctx, originSecrets) + secrets, err := MakeWildcardSecrets(ctx, originSecrets, &ci) if (err != nil) != c.wantErr { t.Fatalf("Test: %q; MakeWildcardSecrets() error = %v, WantErr %v", c.name, err, c.wantErr) }