github.com/kiali/kiali@v1.84.0/graph/telemetry/istio/appender/workload_entry_test.go (about)

     1  package appender_test
     2  
     3  import (
     4  	"sort"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  	networking_v1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1"
     9  	core_v1 "k8s.io/api/core/v1"
    10  	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    11  	"k8s.io/apimachinery/pkg/runtime"
    12  
    13  	"github.com/kiali/kiali/business"
    14  	"github.com/kiali/kiali/config"
    15  	"github.com/kiali/kiali/graph"
    16  	"github.com/kiali/kiali/graph/telemetry/istio/appender"
    17  	"github.com/kiali/kiali/kubernetes"
    18  	"github.com/kiali/kiali/kubernetes/kubetest"
    19  )
    20  
    21  const (
    22  	testCluster  = "defaultCluster"
    23  	appName      = "ratings"
    24  	appNamespace = "testNamespace"
    25  )
    26  
    27  func setupBusinessLayer(t *testing.T, istioObjects ...runtime.Object) *business.Layer {
    28  	k8s := kubetest.NewFakeK8sClient(istioObjects...)
    29  	conf := config.NewConfig()
    30  	conf.KubernetesConfig.ClusterName = testCluster
    31  	conf.ExternalServices.Istio.IstioAPIEnabled = false
    32  	config.Set(conf)
    33  
    34  	business.SetupBusinessLayer(t, k8s, *conf)
    35  	k8sclients := make(map[string]kubernetes.ClientInterface)
    36  	k8sclients[conf.KubernetesConfig.ClusterName] = k8s
    37  	businessLayer := business.NewWithBackends(k8sclients, k8sclients, nil, nil)
    38  	return businessLayer
    39  }
    40  
    41  func setupWorkloadEntries(t *testing.T) *business.Layer {
    42  	workloadV1 := &networking_v1beta1.WorkloadEntry{}
    43  	workloadV1.Name = "workloadA"
    44  	workloadV1.Namespace = appNamespace
    45  	workloadV1.Spec.Labels = map[string]string{
    46  		"app":     appName,
    47  		"version": "v1",
    48  	}
    49  	workloadV2 := &networking_v1beta1.WorkloadEntry{}
    50  	workloadV2.Name = "workloadB"
    51  	workloadV2.Namespace = appNamespace
    52  	workloadV2.Spec.Labels = map[string]string{
    53  		"app":     appName,
    54  		"version": "v2",
    55  	}
    56  	ns := &core_v1.Namespace{ObjectMeta: meta_v1.ObjectMeta{Name: appNamespace}}
    57  	return setupBusinessLayer(t, workloadV1, workloadV2, ns)
    58  }
    59  
    60  func workloadEntriesTrafficMap() map[string]*graph.Node {
    61  	// VersionedApp graph
    62  	trafficMap := make(map[string]*graph.Node)
    63  
    64  	// 1 service, 3 workloads. v1 and v2 are workload entries. v3 is not a workload entry e.g. a kube deployment.
    65  
    66  	// Service node
    67  	n0, _ := graph.NewNode(testCluster, appNamespace, appName, appNamespace, "", "", "", graph.GraphTypeVersionedApp)
    68  
    69  	// v1 Workload
    70  	n1, _ := graph.NewNode(testCluster, appNamespace, appName, appNamespace, "ratings-v1", appName, "v1", graph.GraphTypeVersionedApp)
    71  
    72  	// v2 Workload
    73  	n2, _ := graph.NewNode(testCluster, appNamespace, appName, appNamespace, "ratings-v2", appName, "v2", graph.GraphTypeVersionedApp)
    74  
    75  	// v3 Workload
    76  	n3, _ := graph.NewNode(testCluster, appNamespace, appName, appNamespace, "ratings-v3", appName, "v3", graph.GraphTypeVersionedApp)
    77  
    78  	// v4 Workload (just to test ignoring of outsider nodes)
    79  	n4, _ := graph.NewNode(testCluster, "outsider", "outsider", "outsider", "outsider-v1", "outsider", "v1", graph.GraphTypeVersionedApp)
    80  
    81  	trafficMap[n0.ID] = n0
    82  	trafficMap[n1.ID] = n1
    83  	trafficMap[n2.ID] = n2
    84  	trafficMap[n3.ID] = n3
    85  	trafficMap[n4.ID] = n4
    86  
    87  	n0.AddEdge(n1).Metadata[graph.ProtocolKey] = graph.HTTP.Name
    88  	n0.AddEdge(n2).Metadata[graph.ProtocolKey] = graph.HTTP.Name
    89  	n0.AddEdge(n3).Metadata[graph.ProtocolKey] = graph.HTTP.Name
    90  	n0.AddEdge(n4).Metadata[graph.ProtocolKey] = graph.HTTP.Name
    91  	// Need to put some metadata in here to ensure it gets counted as a workload
    92  
    93  	return trafficMap
    94  }
    95  
    96  func TestWorkloadEntry(t *testing.T) {
    97  	assert := require.New(t)
    98  
    99  	businessLayer := setupWorkloadEntries(t)
   100  	trafficMap := workloadEntriesTrafficMap()
   101  
   102  	assert.Equal(5, len(trafficMap))
   103  
   104  	seSVCID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "", "", "", graph.GraphTypeVersionedApp)
   105  	seSVCNode, found := trafficMap[seSVCID]
   106  	assert.True(found)
   107  	assert.Equal(4, len(seSVCNode.Edges))
   108  
   109  	v1WorkloadID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v1", appName, "v1", graph.GraphTypeVersionedApp)
   110  	v1Node, found := trafficMap[v1WorkloadID]
   111  	assert.True(found)
   112  	assert.NotContains(v1Node.Metadata, graph.HasWorkloadEntry)
   113  
   114  	v2WorkloadID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v2", appName, "v2", graph.GraphTypeVersionedApp)
   115  	v2Node, found := trafficMap[v2WorkloadID]
   116  	assert.True(found)
   117  	assert.NotContains(v2Node.Metadata, graph.HasWorkloadEntry)
   118  
   119  	v3WorkloadID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v3", appName, "v3", graph.GraphTypeVersionedApp)
   120  	v3Node, found := trafficMap[v3WorkloadID]
   121  	assert.True(found)
   122  	assert.NotContains(v3Node.Metadata, graph.HasWorkloadEntry)
   123  
   124  	v4WorkloadID, _, _ := graph.Id(testCluster, "outsider", "outsider", "outsider", "outsider-v1", "outsider", "v1", graph.GraphTypeVersionedApp)
   125  	v4Node, found := trafficMap[v4WorkloadID]
   126  	assert.True(found)
   127  	assert.NotContains(v4Node.Metadata, graph.HasWorkloadEntry)
   128  
   129  	globalInfo := graph.NewAppenderGlobalInfo()
   130  	globalInfo.Business = businessLayer
   131  	namespaceInfo := graph.NewAppenderNamespaceInfo(appNamespace)
   132  
   133  	// Run the appender...
   134  	a := appender.WorkloadEntryAppender{}
   135  	a.AppendGraph(trafficMap, globalInfo, namespaceInfo)
   136  
   137  	assert.Equal(5, len(trafficMap))
   138  
   139  	workloadV1ID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v1", appName, "v1", graph.GraphTypeVersionedApp)
   140  	workloadV1Node, found := trafficMap[workloadV1ID]
   141  	assert.True(found)
   142  	assert.Equal(workloadV1Node.Metadata[graph.HasWorkloadEntry], []graph.WEInfo{{Name: "workloadA"}})
   143  
   144  	workloadV2ID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v2", appName, "v2", graph.GraphTypeVersionedApp)
   145  	workloadV2Node, found := trafficMap[workloadV2ID]
   146  	assert.True(found)
   147  	assert.Equal(workloadV2Node.Metadata[graph.HasWorkloadEntry], []graph.WEInfo{{Name: "workloadB"}})
   148  
   149  	workloadV3ID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v3", appName, "v3", graph.GraphTypeVersionedApp)
   150  	workloadV3Node, found := trafficMap[workloadV3ID]
   151  	assert.True(found)
   152  	assert.NotContains(workloadV3Node.Metadata, graph.HasWorkloadEntry)
   153  }
   154  
   155  func TestWorkloadEntryAppLabelNotMatching(t *testing.T) {
   156  	assert := require.New(t)
   157  
   158  	workloadV1 := &networking_v1beta1.WorkloadEntry{}
   159  	workloadV1.Name = "workloadA"
   160  	workloadV1.Namespace = appNamespace
   161  	workloadV1.Spec.Labels = map[string]string{
   162  		"app":     "pastamaker",
   163  		"version": "v1",
   164  	}
   165  
   166  	workloadV2 := &networking_v1beta1.WorkloadEntry{}
   167  	workloadV2.Name = "workloadB"
   168  	workloadV2.Namespace = appNamespace
   169  	workloadV2.Spec.Labels = map[string]string{
   170  		"app":     "pastamaker",
   171  		"version": "v2",
   172  	}
   173  
   174  	ns := &core_v1.Namespace{ObjectMeta: meta_v1.ObjectMeta{Name: appNamespace}}
   175  	businessLayer := setupBusinessLayer(t, workloadV1, workloadV2, ns)
   176  	trafficMap := workloadEntriesTrafficMap()
   177  
   178  	assert.Equal(5, len(trafficMap))
   179  
   180  	seSVCID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "", "", "", graph.GraphTypeVersionedApp)
   181  	seSVCNode, found := trafficMap[seSVCID]
   182  	assert.True(found)
   183  	assert.Equal(4, len(seSVCNode.Edges))
   184  
   185  	v1WorkloadID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v1", appName, "v1", graph.GraphTypeVersionedApp)
   186  	v1Node, found := trafficMap[v1WorkloadID]
   187  	assert.True(found)
   188  	assert.NotContains(v1Node.Metadata, graph.HasWorkloadEntry)
   189  
   190  	v2WorkloadID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v2", appName, "v2", graph.GraphTypeVersionedApp)
   191  	v2Node, found := trafficMap[v2WorkloadID]
   192  	assert.True(found)
   193  	assert.NotContains(v2Node.Metadata, graph.HasWorkloadEntry)
   194  
   195  	v3WorkloadID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v3", appName, "v3", graph.GraphTypeVersionedApp)
   196  	v3Node, found := trafficMap[v3WorkloadID]
   197  	assert.True(found)
   198  	assert.NotContains(v3Node.Metadata, graph.HasWorkloadEntry)
   199  
   200  	globalInfo := graph.NewAppenderGlobalInfo()
   201  	globalInfo.Business = businessLayer
   202  	namespaceInfo := graph.NewAppenderNamespaceInfo(appNamespace)
   203  
   204  	// Run the appender...
   205  	a := appender.WorkloadEntryAppender{}
   206  	a.AppendGraph(trafficMap, globalInfo, namespaceInfo)
   207  
   208  	assert.Equal(5, len(trafficMap))
   209  
   210  	workloadV1ID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v1", appName, "v1", graph.GraphTypeVersionedApp)
   211  	workloadV1Node, found := trafficMap[workloadV1ID]
   212  	assert.True(found)
   213  	assert.NotContains(workloadV1Node.Metadata, graph.HasWorkloadEntry)
   214  
   215  	workloadV2ID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v2", appName, "v2", graph.GraphTypeVersionedApp)
   216  	workloadV2Node, found := trafficMap[workloadV2ID]
   217  	assert.True(found)
   218  	assert.NotContains(workloadV2Node.Metadata, graph.HasWorkloadEntry)
   219  
   220  	workloadV3ID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v3", appName, "v3", graph.GraphTypeVersionedApp)
   221  	workloadV3Node, found := trafficMap[workloadV3ID]
   222  	assert.True(found)
   223  	assert.NotContains(workloadV3Node.Metadata, graph.HasWorkloadEntry)
   224  }
   225  
   226  func TestMultipleWorkloadEntryForSameWorkload(t *testing.T) {
   227  	assert := require.New(t)
   228  
   229  	workloadV1A := &networking_v1beta1.WorkloadEntry{}
   230  	workloadV1A.Name = "workloadV1A"
   231  	workloadV1A.Namespace = appNamespace
   232  	workloadV1A.Spec.Labels = map[string]string{
   233  		"app":     appName,
   234  		"version": "v1",
   235  	}
   236  
   237  	workloadV1B := &networking_v1beta1.WorkloadEntry{}
   238  	workloadV1B.Name = "workloadV1B"
   239  	workloadV1B.Namespace = appNamespace
   240  	workloadV1B.Spec.Labels = map[string]string{
   241  		"app":     appName,
   242  		"version": "v1",
   243  	}
   244  
   245  	workloadV2 := &networking_v1beta1.WorkloadEntry{}
   246  	workloadV2.Name = "workloadV2"
   247  	workloadV2.Namespace = appNamespace
   248  	workloadV2.Spec.Labels = map[string]string{
   249  		"app":     appName,
   250  		"version": "v2",
   251  	}
   252  
   253  	ns := &core_v1.Namespace{ObjectMeta: meta_v1.ObjectMeta{Name: appNamespace}}
   254  	businessLayer := setupBusinessLayer(t, workloadV1A, workloadV1B, workloadV2, ns)
   255  	trafficMap := workloadEntriesTrafficMap()
   256  
   257  	assert.Equal(5, len(trafficMap))
   258  
   259  	seSVCID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "", "", "", graph.GraphTypeVersionedApp)
   260  	seSVCNode, found := trafficMap[seSVCID]
   261  	assert.True(found)
   262  	assert.Equal(4, len(seSVCNode.Edges))
   263  
   264  	v1WorkloadID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v1", appName, "v1", graph.GraphTypeVersionedApp)
   265  	v1Node, found := trafficMap[v1WorkloadID]
   266  	assert.True(found)
   267  	assert.NotContains(v1Node.Metadata, graph.HasWorkloadEntry)
   268  
   269  	v2WorkloadID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v2", appName, "v2", graph.GraphTypeVersionedApp)
   270  	v2Node, found := trafficMap[v2WorkloadID]
   271  	assert.True(found)
   272  	assert.NotContains(v2Node.Metadata, graph.HasWorkloadEntry)
   273  
   274  	v3WorkloadID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v3", appName, "v3", graph.GraphTypeVersionedApp)
   275  	v3Node, found := trafficMap[v3WorkloadID]
   276  	assert.True(found)
   277  	assert.NotContains(v3Node.Metadata, graph.HasWorkloadEntry)
   278  
   279  	globalInfo := graph.NewAppenderGlobalInfo()
   280  	globalInfo.Business = businessLayer
   281  	namespaceInfo := graph.NewAppenderNamespaceInfo(appNamespace)
   282  
   283  	// Run the appender...
   284  	a := appender.WorkloadEntryAppender{}
   285  	a.AppendGraph(trafficMap, globalInfo, namespaceInfo)
   286  
   287  	assert.Equal(5, len(trafficMap))
   288  
   289  	workloadV1ID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v1", appName, "v1", graph.GraphTypeVersionedApp)
   290  	workloadV1Node, found := trafficMap[workloadV1ID]
   291  	assert.True(found)
   292  	res := workloadV1Node.Metadata[graph.HasWorkloadEntry].([]graph.WEInfo)
   293  	sort.Slice(res, func(i, j int) bool {
   294  		return res[i].Name < res[j].Name
   295  	})
   296  	assert.Equal(
   297  		[]graph.WEInfo{{Name: "workloadV1A"}, {Name: "workloadV1B"}},
   298  		res,
   299  	)
   300  
   301  	workloadV2ID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v2", appName, "v2", graph.GraphTypeVersionedApp)
   302  	workloadV2Node, found := trafficMap[workloadV2ID]
   303  	assert.True(found)
   304  	assert.Equal(workloadV2Node.Metadata[graph.HasWorkloadEntry], []graph.WEInfo{{Name: "workloadV2"}})
   305  
   306  	workloadV3ID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v3", appName, "v3", graph.GraphTypeVersionedApp)
   307  	workloadV3Node, found := trafficMap[workloadV3ID]
   308  	assert.True(found)
   309  	assert.NotContains(workloadV3Node.Metadata, graph.HasWorkloadEntry)
   310  }
   311  
   312  func TestWorkloadWithoutWorkloadEntries(t *testing.T) {
   313  	assert := require.New(t)
   314  
   315  	businessLayer := setupBusinessLayer(t, &core_v1.Namespace{ObjectMeta: meta_v1.ObjectMeta{Name: appNamespace}})
   316  	trafficMap := workloadEntriesTrafficMap()
   317  
   318  	assert.Equal(5, len(trafficMap))
   319  
   320  	seSVCID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "", "", "", graph.GraphTypeVersionedApp)
   321  	seSVCNode, found := trafficMap[seSVCID]
   322  	assert.True(found)
   323  	assert.Equal(4, len(seSVCNode.Edges))
   324  
   325  	v1WorkloadID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v1", appName, "v1", graph.GraphTypeVersionedApp)
   326  	v1Node, found := trafficMap[v1WorkloadID]
   327  	assert.True(found)
   328  	assert.NotContains(v1Node.Metadata, graph.HasWorkloadEntry)
   329  
   330  	v2WorkloadID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v2", appName, "v2", graph.GraphTypeVersionedApp)
   331  	v2Node, found := trafficMap[v2WorkloadID]
   332  	assert.True(found)
   333  	assert.NotContains(v2Node.Metadata, graph.HasWorkloadEntry)
   334  
   335  	v3WorkloadID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v3", appName, "v3", graph.GraphTypeVersionedApp)
   336  	v3Node, found := trafficMap[v3WorkloadID]
   337  	assert.True(found)
   338  	assert.NotContains(v3Node.Metadata, graph.HasWorkloadEntry)
   339  
   340  	globalInfo := graph.NewAppenderGlobalInfo()
   341  	globalInfo.Business = businessLayer
   342  	namespaceInfo := graph.NewAppenderNamespaceInfo(appNamespace)
   343  
   344  	// Run the appender...
   345  	a := appender.WorkloadEntryAppender{}
   346  	a.AppendGraph(trafficMap, globalInfo, namespaceInfo)
   347  
   348  	assert.Equal(5, len(trafficMap))
   349  
   350  	workloadV1ID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v1", appName, "v1", graph.GraphTypeVersionedApp)
   351  	workloadV1Node, found := trafficMap[workloadV1ID]
   352  	assert.True(found)
   353  	assert.NotContains(workloadV1Node.Metadata, graph.HasWorkloadEntry)
   354  
   355  	workloadV2ID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v2", appName, "v2", graph.GraphTypeVersionedApp)
   356  	workloadV2Node, found := trafficMap[workloadV2ID]
   357  	assert.True(found)
   358  	assert.NotContains(workloadV2Node.Metadata, graph.HasWorkloadEntry)
   359  
   360  	workloadV3ID, _, _ := graph.Id(testCluster, appNamespace, appName, appNamespace, "ratings-v3", appName, "v3", graph.GraphTypeVersionedApp)
   361  	workloadV3Node, found := trafficMap[workloadV3ID]
   362  	assert.True(found)
   363  	assert.NotContains(workloadV3Node.Metadata, graph.HasWorkloadEntry)
   364  }