github.com/kiali/kiali@v1.84.0/kubernetes/cache/cache_test.go (about)

     1  package cache_test
     2  
     3  import (
     4  	"sync"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  	apps_v1 "k8s.io/api/apps/v1"
     9  	core_v1 "k8s.io/api/core/v1"
    10  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    11  
    12  	"github.com/kiali/kiali/config"
    13  	"github.com/kiali/kiali/kubernetes"
    14  	"github.com/kiali/kiali/kubernetes/cache"
    15  	"github.com/kiali/kiali/kubernetes/kubetest"
    16  	"github.com/kiali/kiali/models"
    17  )
    18  
    19  func TestNoHomeClusterReturnsError(t *testing.T) {
    20  	require := require.New(t)
    21  	conf := config.NewConfig()
    22  	config.Set(conf)
    23  
    24  	client := kubetest.NewFakeK8sClient()
    25  	clientFactory := kubetest.NewK8SClientFactoryMock(client)
    26  	clientFactory.SetClients(map[string]kubernetes.ClientInterface{"nothomecluster": client})
    27  
    28  	cache, err := cache.NewKialiCache(clientFactory, *conf)
    29  	defer func() {
    30  		if cache != nil {
    31  			cache.Stop()
    32  		}
    33  	}()
    34  	require.Error(err, "no home cluster should return an error")
    35  }
    36  
    37  func TestKubeCacheCreatedPerClient(t *testing.T) {
    38  	require := require.New(t)
    39  	conf := config.NewConfig()
    40  	config.Set(conf)
    41  
    42  	ns := &core_v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test"}}
    43  	deploymentCluster1 := &apps_v1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "deployment1", Namespace: "test"}}
    44  	deploymentCluster2 := &apps_v1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "deployment2", Namespace: "test"}}
    45  	client := kubetest.NewFakeK8sClient(ns, deploymentCluster1)
    46  	client2 := kubetest.NewFakeK8sClient(ns, deploymentCluster2)
    47  	clientFactory := kubetest.NewK8SClientFactoryMock(nil)
    48  	clientFactory.SetClients(map[string]kubernetes.ClientInterface{
    49  		conf.KubernetesConfig.ClusterName: client,
    50  		"cluster2":                        client2,
    51  	})
    52  
    53  	kialiCache := cache.NewTestingCacheWithFactory(t, clientFactory, *conf)
    54  
    55  	caches := kialiCache.GetKubeCaches()
    56  	require.Equal(2, len(caches))
    57  
    58  	_, err := caches[conf.KubernetesConfig.ClusterName].GetDeployment("test", "deployment1")
    59  	require.NoError(err)
    60  
    61  	_, err = caches["cluster2"].GetDeployment("test", "deployment2")
    62  	require.NoError(err)
    63  
    64  	_, err = kialiCache.GetKubeCache(conf.KubernetesConfig.ClusterName)
    65  	require.NoError(err)
    66  
    67  	_, err = kialiCache.GetKubeCache("cluster2")
    68  	require.NoError(err)
    69  
    70  	_, err = kialiCache.GetKubeCache("cluster3")
    71  	require.Error(err)
    72  }
    73  
    74  func ztunnelDaemonSet() *apps_v1.DaemonSet {
    75  	return &apps_v1.DaemonSet{
    76  		ObjectMeta: metav1.ObjectMeta{
    77  			Name:      "ztunnel",
    78  			Namespace: "istio-system",
    79  		},
    80  		Spec: apps_v1.DaemonSetSpec{
    81  			Selector: &metav1.LabelSelector{
    82  				MatchLabels: map[string]string{"app": "ztunnel"},
    83  			},
    84  		},
    85  	}
    86  }
    87  
    88  func TestIsAmbientEnabled(t *testing.T) {
    89  	require := require.New(t)
    90  	conf := config.NewConfig()
    91  	client := kubetest.NewFakeK8sClient(
    92  		&core_v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "istio-system"}},
    93  		ztunnelDaemonSet(),
    94  	)
    95  	cache := cache.NewTestingCache(t, client, *conf)
    96  
    97  	require.True(cache.IsAmbientEnabled(conf.KubernetesConfig.ClusterName))
    98  	// Call multiple times to ensure results are consistent.
    99  	require.True(cache.IsAmbientEnabled(conf.KubernetesConfig.ClusterName))
   100  }
   101  
   102  func TestIsAmbientEnabledOutsideIstioSystem(t *testing.T) {
   103  	require := require.New(t)
   104  	conf := config.NewConfig()
   105  	ztunnel := ztunnelDaemonSet()
   106  	ztunnel.Namespace = "alternate-istio-namespace"
   107  	client := kubetest.NewFakeK8sClient(
   108  		&core_v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "alternate-istio-namespace"}},
   109  		ztunnel,
   110  	)
   111  	cache := cache.NewTestingCache(t, client, *conf)
   112  
   113  	require.True(cache.IsAmbientEnabled(conf.KubernetesConfig.ClusterName))
   114  	// Call multiple times to ensure results are consistent.
   115  	require.True(cache.IsAmbientEnabled(conf.KubernetesConfig.ClusterName))
   116  }
   117  
   118  func TestIsAmbientDisabled(t *testing.T) {
   119  	require := require.New(t)
   120  	conf := config.NewConfig()
   121  	client := kubetest.NewFakeK8sClient(
   122  		&core_v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "istio-system"}},
   123  	)
   124  	cache := cache.NewTestingCache(t, client, *conf)
   125  
   126  	require.False(cache.IsAmbientEnabled(conf.KubernetesConfig.ClusterName))
   127  	// Call multiple times to ensure results are consistent.
   128  	require.False(cache.IsAmbientEnabled(conf.KubernetesConfig.ClusterName))
   129  }
   130  
   131  func TestIsAmbientMultiCluster(t *testing.T) {
   132  	require := require.New(t)
   133  	conf := config.NewConfig()
   134  	conf.KubernetesConfig.ClusterName = "east"
   135  	east := kubetest.NewFakeK8sClient(
   136  		&core_v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "istio-system"}},
   137  		ztunnelDaemonSet(),
   138  	)
   139  	west := kubetest.NewFakeK8sClient(
   140  		&core_v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "istio-system"}},
   141  	)
   142  	clientFactory := kubetest.NewK8SClientFactoryMock(nil)
   143  	clientFactory.SetClients(map[string]kubernetes.ClientInterface{
   144  		"east": east,
   145  		"west": west,
   146  	})
   147  	cache := cache.NewTestingCacheWithFactory(t, clientFactory, *conf)
   148  
   149  	require.True(cache.IsAmbientEnabled("east"))
   150  	require.False(cache.IsAmbientEnabled("west"))
   151  }
   152  
   153  // This test only tests anything when the '-race' flag is passed to 'go test'.
   154  func TestIsAmbientIsThreadSafe(t *testing.T) {
   155  	conf := config.NewConfig()
   156  	client := kubetest.NewFakeK8sClient(
   157  		&core_v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "istio-system"}},
   158  		ztunnelDaemonSet(),
   159  	)
   160  	cache := cache.NewTestingCache(t, client, *conf)
   161  
   162  	wg := sync.WaitGroup{}
   163  	for i := 0; i < 10; i++ {
   164  		wg.Add(1)
   165  		go func() {
   166  			defer wg.Done()
   167  			cache.IsAmbientEnabled(conf.KubernetesConfig.ClusterName)
   168  		}()
   169  	}
   170  	wg.Wait()
   171  }
   172  
   173  func TestSetNamespace(t *testing.T) {
   174  	require := require.New(t)
   175  
   176  	conf := config.NewConfig()
   177  	conf.KubernetesConfig.CacheTokenNamespaceDuration = 10000
   178  	conf.KubernetesConfig.ClusterName = "east"
   179  	kubernetes.SetConfig(t, *conf)
   180  
   181  	client := kubetest.NewFakeK8sClient()
   182  	cache := cache.NewTestingCache(t, client, *conf)
   183  	cache.SetNamespaces("token", []models.Namespace{{Name: "test", Cluster: "east"}})
   184  	cache.SetNamespace("token", models.Namespace{Name: "test", Cluster: "east", Labels: map[string]string{"app": "test"}})
   185  
   186  	ns, found := cache.GetNamespace("east", "token", "test")
   187  	require.True(found)
   188  	require.Equal(map[string]string{"app": "test"}, ns.Labels)
   189  }
   190  
   191  func TestSetNamespaceIsThreadSafe(t *testing.T) {
   192  	conf := config.NewConfig()
   193  	conf.KubernetesConfig.CacheTokenNamespaceDuration = 10000
   194  	conf.KubernetesConfig.ClusterName = "east"
   195  	kubernetes.SetConfig(t, *conf)
   196  
   197  	client := kubetest.NewFakeK8sClient()
   198  	cache := cache.NewTestingCache(t, client, *conf)
   199  
   200  	wg := sync.WaitGroup{}
   201  	for i := 0; i < 10; i++ {
   202  		wg.Add(1)
   203  		go func() {
   204  			defer wg.Done()
   205  			cache.SetNamespace("token", models.Namespace{Name: "test", Cluster: "east", Labels: map[string]string{"app": "test"}})
   206  		}()
   207  	}
   208  	wg.Wait()
   209  }
   210  
   211  func TestGetNamespaces(t *testing.T) {
   212  	require := require.New(t)
   213  	conf := config.NewConfig()
   214  	conf.KubernetesConfig.CacheTokenNamespaceDuration = 10000
   215  	conf.KubernetesConfig.ClusterName = "east"
   216  	kubernetes.SetConfig(t, *conf)
   217  
   218  	client := kubetest.NewFakeK8sClient()
   219  	cache := cache.NewTestingCache(t, client, *conf)
   220  	cache.SetNamespaces("token", []models.Namespace{{Name: "test", Cluster: "east"}})
   221  
   222  	namespaces, found := cache.GetNamespaces("east", "token")
   223  	require.True(found)
   224  	require.Equal(1, len(namespaces))
   225  	require.Equal("test", namespaces[0].Name)
   226  
   227  	_, found = cache.GetNamespaces("west", "token")
   228  	require.False(found)
   229  
   230  	_, found = cache.GetNamespaces("east", "token2")
   231  	require.False(found)
   232  }
   233  
   234  func TestRefreshTokenNamespaces(t *testing.T) {
   235  	require := require.New(t)
   236  	conf := config.NewConfig()
   237  	conf.KubernetesConfig.CacheTokenNamespaceDuration = 10000
   238  	conf.KubernetesConfig.ClusterName = "east"
   239  	kubernetes.SetConfig(t, *conf)
   240  
   241  	client := kubetest.NewFakeK8sClient()
   242  	cache := cache.NewTestingCache(t, client, *conf)
   243  	cache.SetNamespaces("token", []models.Namespace{{Name: "test", Cluster: "east"}})
   244  	cache.RefreshTokenNamespaces("east")
   245  
   246  	_, found := cache.GetNamespaces("east", "token")
   247  	require.False(found)
   248  
   249  	// Test refresh doesn't affect other clusters.
   250  	cache.SetNamespaces("token", []models.Namespace{{Name: "test", Cluster: "east"}})
   251  	cache.SetNamespaces("token", []models.Namespace{{Name: "test", Cluster: "west"}})
   252  	cache.RefreshTokenNamespaces("east")
   253  
   254  	namespaces, found := cache.GetNamespaces("west", "token")
   255  	require.True(found)
   256  	require.Equal(1, len(namespaces))
   257  	require.Equal("test", namespaces[0].Name)
   258  }