istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/config/kube/gateway/controller_test.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package gateway
    16  
    17  import (
    18  	"testing"
    19  	"time"
    20  
    21  	. "github.com/onsi/gomega"
    22  	v1 "k8s.io/api/core/v1"
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  	"k8s.io/apimachinery/pkg/runtime/schema"
    25  	k8s "sigs.k8s.io/gateway-api/apis/v1"
    26  
    27  	networking "istio.io/api/networking/v1alpha3"
    28  	"istio.io/istio/pilot/pkg/config/memory"
    29  	"istio.io/istio/pilot/pkg/features"
    30  	"istio.io/istio/pilot/pkg/model"
    31  	"istio.io/istio/pilot/pkg/networking/core"
    32  	"istio.io/istio/pilot/pkg/serviceregistry/kube/controller"
    33  	"istio.io/istio/pilot/pkg/serviceregistry/util/xdsfake"
    34  	"istio.io/istio/pkg/config"
    35  	"istio.io/istio/pkg/config/constants"
    36  	"istio.io/istio/pkg/config/schema/collections"
    37  	"istio.io/istio/pkg/config/schema/gvk"
    38  	"istio.io/istio/pkg/kube"
    39  	"istio.io/istio/pkg/kube/kclient/clienttest"
    40  	"istio.io/istio/pkg/test"
    41  	"istio.io/istio/pkg/util/sets"
    42  )
    43  
    44  var (
    45  	gatewayClassSpec = &k8s.GatewayClassSpec{
    46  		ControllerName: k8s.GatewayController(features.ManagedGatewayController),
    47  	}
    48  	gatewaySpec = &k8s.GatewaySpec{
    49  		GatewayClassName: "gwclass",
    50  		Listeners: []k8s.Listener{
    51  			{
    52  				Name:          "default",
    53  				Port:          9009,
    54  				Protocol:      "HTTP",
    55  				AllowedRoutes: &k8s.AllowedRoutes{Namespaces: &k8s.RouteNamespaces{From: func() *k8s.FromNamespaces { x := k8s.NamespacesFromAll; return &x }()}},
    56  			},
    57  		},
    58  	}
    59  	httpRouteSpec = &k8s.HTTPRouteSpec{
    60  		CommonRouteSpec: k8s.CommonRouteSpec{ParentRefs: []k8s.ParentReference{{
    61  			Name: "gwspec",
    62  		}}},
    63  		Hostnames: []k8s.Hostname{"test.cluster.local"},
    64  	}
    65  
    66  	expectedgw = &networking.Gateway{
    67  		Servers: []*networking.Server{
    68  			{
    69  				Port: &networking.Port{
    70  					Number:   9009,
    71  					Name:     "default",
    72  					Protocol: "HTTP",
    73  				},
    74  				Hosts: []string{"*/*"},
    75  			},
    76  		},
    77  	}
    78  )
    79  
    80  var AlwaysReady = func(class schema.GroupVersionResource, stop <-chan struct{}) bool {
    81  	return true
    82  }
    83  
    84  func TestListInvalidGroupVersionKind(t *testing.T) {
    85  	g := NewWithT(t)
    86  	clientSet := kube.NewFakeClient()
    87  	clientSet.RunAndWait(test.NewStop(t))
    88  	store := memory.NewController(memory.Make(collections.All))
    89  	controller := NewController(clientSet, store, AlwaysReady, nil, controller.Options{})
    90  
    91  	typ := config.GroupVersionKind{Kind: "wrong-kind"}
    92  	c := controller.List(typ, "ns1")
    93  	g.Expect(c).To(HaveLen(0))
    94  }
    95  
    96  func TestListGatewayResourceType(t *testing.T) {
    97  	g := NewWithT(t)
    98  
    99  	clientSet := kube.NewFakeClient()
   100  	clientSet.RunAndWait(test.NewStop(t))
   101  	store := memory.NewController(memory.Make(collections.All))
   102  	controller := NewController(clientSet, store, AlwaysReady, nil, controller.Options{})
   103  
   104  	store.Create(config.Config{
   105  		Meta: config.Meta{
   106  			GroupVersionKind: gvk.GatewayClass,
   107  			Name:             "gwclass",
   108  			Namespace:        "ns1",
   109  		},
   110  		Spec: gatewayClassSpec,
   111  	})
   112  	if _, err := store.Create(config.Config{
   113  		Meta: config.Meta{
   114  			GroupVersionKind: gvk.KubernetesGateway,
   115  			Name:             "gwspec",
   116  			Namespace:        "ns1",
   117  		},
   118  		Spec: gatewaySpec,
   119  	}); err != nil {
   120  		t.Fatal(err)
   121  	}
   122  	store.Create(config.Config{
   123  		Meta: config.Meta{
   124  			GroupVersionKind: gvk.HTTPRoute,
   125  			Name:             "http-route",
   126  			Namespace:        "ns1",
   127  		},
   128  		Spec: httpRouteSpec,
   129  	})
   130  
   131  	cg := core.NewConfigGenTest(t, core.TestOptions{})
   132  	g.Expect(controller.Reconcile(cg.PushContext())).ToNot(HaveOccurred())
   133  	cfg := controller.List(gvk.Gateway, "ns1")
   134  	g.Expect(cfg).To(HaveLen(1))
   135  	for _, c := range cfg {
   136  		g.Expect(c.GroupVersionKind).To(Equal(gvk.Gateway))
   137  		g.Expect(c.Name).To(Equal("gwspec" + "-" + constants.KubernetesGatewayName + "-default"))
   138  		g.Expect(c.Namespace).To(Equal("ns1"))
   139  		g.Expect(c.Spec).To(Equal(expectedgw))
   140  	}
   141  }
   142  
   143  func TestNamespaceEvent(t *testing.T) {
   144  	clientSet := kube.NewFakeClient()
   145  	store := memory.NewController(memory.Make(collections.All))
   146  	c := NewController(clientSet, store, AlwaysReady, nil, controller.Options{})
   147  	s := xdsfake.NewFakeXDS()
   148  
   149  	c.RegisterEventHandler(gvk.Namespace, func(_, cfg config.Config, _ model.Event) {
   150  		s.ConfigUpdate(&model.PushRequest{
   151  			Full:   true,
   152  			Reason: model.NewReasonStats(model.NamespaceUpdate),
   153  		})
   154  	})
   155  
   156  	stop := test.NewStop(t)
   157  	c.Run(stop)
   158  	kube.WaitForCacheSync("test", stop, c.HasSynced)
   159  	c.state.ReferencedNamespaceKeys = sets.String{"allowed": struct{}{}}
   160  
   161  	ns1 := &v1.Namespace{ObjectMeta: metav1.ObjectMeta{
   162  		Name: "ns1",
   163  		Labels: map[string]string{
   164  			"foo": "bar",
   165  		},
   166  	}}
   167  	ns2 := &v1.Namespace{ObjectMeta: metav1.ObjectMeta{
   168  		Name: "ns2",
   169  		Labels: map[string]string{
   170  			"allowed": "true",
   171  		},
   172  	}}
   173  	ns := clienttest.Wrap(t, c.namespaces)
   174  
   175  	ns.Create(ns1)
   176  	s.AssertEmpty(t, time.Millisecond*10)
   177  
   178  	ns.Create(ns2)
   179  	s.AssertEmpty(t, time.Millisecond*10)
   180  
   181  	ns1.Annotations = map[string]string{"foo": "bar"}
   182  	ns.Update(ns1)
   183  	s.AssertEmpty(t, time.Millisecond*10)
   184  
   185  	ns2.Annotations = map[string]string{"foo": "bar"}
   186  	ns.Update(ns2)
   187  	s.AssertEmpty(t, time.Millisecond*10)
   188  
   189  	ns1.Labels["bar"] = "foo"
   190  	ns.Update(ns1)
   191  	s.AssertEmpty(t, time.Millisecond*10)
   192  
   193  	ns2.Labels["foo"] = "bar"
   194  	ns.Update(ns2)
   195  	s.WaitOrFail(t, "xds full")
   196  
   197  	ns1.Labels["allowed"] = "true"
   198  	ns.Update(ns1)
   199  	s.WaitOrFail(t, "xds full")
   200  
   201  	ns2.Labels["allowed"] = "false"
   202  	ns.Update(ns2)
   203  	s.WaitOrFail(t, "xds full")
   204  }