github.com/kiali/kiali@v1.84.0/graph/telemetry/istio/appender/dead_node_test.go (about) 1 package appender 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 apps_v1 "k8s.io/api/apps/v1" 9 core_v1 "k8s.io/api/core/v1" 10 meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 12 "github.com/kiali/kiali/business" 13 "github.com/kiali/kiali/config" 14 "github.com/kiali/kiali/graph" 15 "github.com/kiali/kiali/kubernetes" 16 "github.com/kiali/kiali/kubernetes/kubetest" 17 ) 18 19 func setupWorkloads(t *testing.T) *business.Layer { 20 conf := config.NewConfig() 21 conf.KubernetesConfig.ClusterName = config.DefaultClusterID 22 config.Set(conf) 23 24 k8s := kubetest.NewFakeK8sClient( 25 &core_v1.Namespace{ObjectMeta: meta_v1.ObjectMeta{Name: "testNamespace"}}, 26 &apps_v1.Deployment{ 27 ObjectMeta: meta_v1.ObjectMeta{ 28 Name: "testPodsWithTraffic-v1", 29 Namespace: "testNamespace", 30 }, 31 Spec: apps_v1.DeploymentSpec{ 32 Template: core_v1.PodTemplateSpec{ 33 ObjectMeta: meta_v1.ObjectMeta{ 34 Labels: map[string]string{"app": "testPodsWithTraffic", "version": "v1"}, 35 }, 36 }, 37 }, 38 }, 39 &apps_v1.Deployment{ 40 ObjectMeta: meta_v1.ObjectMeta{ 41 Name: "testPodsNoTraffic-v1", 42 Namespace: "testNamespace", 43 }, 44 Spec: apps_v1.DeploymentSpec{ 45 Template: core_v1.PodTemplateSpec{ 46 ObjectMeta: meta_v1.ObjectMeta{ 47 Labels: map[string]string{"app": "testPodsNoTraffic", "version": "v1"}, 48 }, 49 }, 50 }, 51 }, 52 &apps_v1.Deployment{ 53 ObjectMeta: meta_v1.ObjectMeta{ 54 Name: "testNoPodsWithTraffic-v1", 55 Namespace: "testNamespace", 56 }, 57 Spec: apps_v1.DeploymentSpec{ 58 Template: core_v1.PodTemplateSpec{ 59 ObjectMeta: meta_v1.ObjectMeta{ 60 Labels: map[string]string{"app": "testNoPodsWithTraffic", "version": "v1"}, 61 }, 62 }, 63 }, 64 }, 65 &apps_v1.Deployment{ 66 ObjectMeta: meta_v1.ObjectMeta{ 67 Name: "testNoPodsNoTraffic-v1", 68 Namespace: "testNamespace", 69 }, 70 Spec: apps_v1.DeploymentSpec{ 71 Template: core_v1.PodTemplateSpec{ 72 ObjectMeta: meta_v1.ObjectMeta{ 73 Labels: map[string]string{"app": "testNoPodsNoTraffic", "version": "v1"}, 74 }, 75 }, 76 }, 77 }, 78 &core_v1.Pod{ 79 ObjectMeta: meta_v1.ObjectMeta{ 80 Name: "testPodsWithTraffic-v1-1234", 81 Namespace: "testNamespace", 82 Labels: map[string]string{"app": "testPodsWithTraffic", "version": "v1"}, 83 }, 84 Status: core_v1.PodStatus{ 85 Message: "foo", 86 }, 87 }, 88 &core_v1.Pod{ 89 ObjectMeta: meta_v1.ObjectMeta{ 90 Name: "testPodsNoTraffic-v1-1234", 91 Namespace: "testNamespace", 92 Labels: map[string]string{"app": "testPodsNoTraffic", "version": "v1"}, 93 }, 94 Status: core_v1.PodStatus{ 95 Message: "foo", 96 }, 97 }, 98 ) 99 100 business.SetupBusinessLayer(t, k8s, *conf) 101 102 k8sclients := make(map[string]kubernetes.ClientInterface) 103 k8sclients[config.DefaultClusterID] = k8s 104 businessLayer := business.NewWithBackends(k8sclients, k8sclients, nil, nil) 105 return businessLayer 106 } 107 108 func TestDeadNode(t *testing.T) { 109 assert := assert.New(t) 110 111 businessLayer := setupWorkloads(t) 112 trafficMap := testTrafficMap() 113 114 assert.Equal(12, len(trafficMap)) 115 unknownID, _, _ := graph.Id(config.DefaultClusterID, graph.Unknown, "", graph.Unknown, graph.Unknown, graph.Unknown, graph.Unknown, graph.GraphTypeVersionedApp) 116 unknownNode, found := trafficMap[unknownID] 117 assert.Equal(true, found) 118 assert.Equal(graph.Unknown, unknownNode.Workload) 119 assert.Equal(10, len(unknownNode.Edges)) 120 121 ingressID, _, _ := graph.Id(config.DefaultClusterID, graph.Unknown, "", "istio-system", "istio-ingressgateway", "istio-ingressgateway", graph.Unknown, graph.GraphTypeVersionedApp) 122 ingressNode, found := trafficMap[ingressID] 123 assert.Equal(true, found) 124 assert.Equal("istio-ingressgateway", ingressNode.Workload) 125 assert.Equal(10, len(ingressNode.Edges)) 126 127 globalInfo := graph.NewAppenderGlobalInfo() 128 globalInfo.Business = businessLayer 129 namespaceInfo := graph.NewAppenderNamespaceInfo("testNamespace") 130 131 a := DeadNodeAppender{ 132 AccessibleNamespaces: map[string]*graph.AccessibleNamespace{ 133 fmt.Sprintf("%s:testNamespace", config.DefaultClusterID): { 134 Cluster: config.DefaultClusterID, 135 Name: "testNamespace", 136 }, 137 fmt.Sprintf("%s:istio-system", config.DefaultClusterID): { 138 Cluster: config.DefaultClusterID, 139 Name: "istio-system", 140 }, 141 }, 142 } 143 a.AppendGraph(trafficMap, globalInfo, namespaceInfo) 144 145 assert.Equal(10, len(trafficMap)) 146 147 _, found = trafficMap[unknownID] 148 assert.Equal(false, found) 149 150 ingressNode, found = trafficMap[ingressID] 151 assert.Equal(true, found) 152 assert.Equal(9, len(ingressNode.Edges)) 153 154 assert.Equal("testPodsWithTraffic-v1", ingressNode.Edges[0].Dest.Workload) 155 assert.Equal("testPodsNoTraffic-v1", ingressNode.Edges[1].Dest.Workload) 156 assert.Equal("testNoPodsWithTraffic-v1", ingressNode.Edges[2].Dest.Workload) 157 assert.Equal("testNoPodsNoTraffic-v1", ingressNode.Edges[3].Dest.Workload) 158 assert.Equal("testNoDeploymentWithTraffic-v1", ingressNode.Edges[4].Dest.Workload) 159 assert.Equal("testNodeWithTcpSentTraffic-v1", ingressNode.Edges[5].Dest.Workload) 160 assert.Equal("testNodeWithTcpSentOutTraffic-v1", ingressNode.Edges[6].Dest.Workload) 161 162 id, _, _ := graph.Id(config.DefaultClusterID, "testNamespace", "testNoPodsNoTraffic", "testNamespace", "testNoPodsNoTraffic-v1", "testNoPodsNoTraffic", "v1", graph.GraphTypeVersionedApp) 163 noPodsNoTraffic, ok := trafficMap[id] 164 assert.Equal(true, ok) 165 isDead, ok := noPodsNoTraffic.Metadata[graph.IsDead] 166 assert.Equal(true, ok) 167 assert.Equal(true, isDead) 168 169 // Check that external services are not removed 170 id, _, _ = graph.Id(config.DefaultClusterID, "testNamespace", "egress.io", "testNamespace", "", "", "", graph.GraphTypeVersionedApp) 171 _, okExternal := trafficMap[id] 172 assert.Equal(true, okExternal) 173 } 174 175 func testTrafficMap() map[string]*graph.Node { 176 trafficMap := make(map[string]*graph.Node) 177 178 n0, _ := graph.NewNode(config.DefaultClusterID, graph.Unknown, "", graph.Unknown, graph.Unknown, graph.Unknown, graph.Unknown, graph.GraphTypeVersionedApp) 179 180 n00, _ := graph.NewNode(config.DefaultClusterID, graph.Unknown, "", "istio-system", "istio-ingressgateway", "istio-ingressgateway", graph.Unknown, graph.GraphTypeVersionedApp) 181 n00.Metadata["httpOut"] = 4.8 182 183 n1, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "testPodsWithTraffic", "testNamespace", "testPodsWithTraffic-v1", "testPodsWithTraffic", "v1", graph.GraphTypeVersionedApp) 184 n1.Metadata["httpIn"] = 0.8 185 186 n2, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "testPodsNoTraffic", "testNamespace", "testPodsNoTraffic-v1", "testPodsNoTraffic", "v1", graph.GraphTypeVersionedApp) 187 188 n3, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "testNoPodsWithTraffic", "testNamespace", "testNoPodsWithTraffic-v1", "testNoPodsWithTraffic", "v1", graph.GraphTypeVersionedApp) 189 n3.Metadata["httpIn"] = 0.8 190 191 n4, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "testNoPodsNoTraffic", "testNamespace", "testNoPodsNoTraffic-v1", "testNoPodsNoTraffic", "v1", graph.GraphTypeVersionedApp) 192 193 n5, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "testNoDeploymentWithTraffic", "testNamespace", "testNoDeploymentWithTraffic-v1", "testNoDeploymentWithTraffic", "v1", graph.GraphTypeVersionedApp) 194 n5.Metadata["httpIn"] = 0.8 195 196 n6, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "testNoDeploymentNoTraffic", "testNamespace", "testNoDeploymentNoTraffic-v1", "testNoDeploymentNoTraffic", "v1", graph.GraphTypeVersionedApp) 197 198 n7, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "testNodeWithTcpSentTraffic", "testNamespace", "testNodeWithTcpSentTraffic-v1", "testNodeWithTcpSentTraffic", "v1", graph.GraphTypeVersionedApp) 199 n7.Metadata["tcpIn"] = 74.1 200 201 n8, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "testNodeWithTcpSentOutTraffic", "testNamespace", "testNodeWithTcpSentOutTraffic-v1", "testNodeWithTcpSentOutTraffic", "v1", graph.GraphTypeVersionedApp) 202 n8.Metadata["tcpOut"] = 74.1 203 204 n9, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "egress.io", "testNamespace", "", "", "", graph.GraphTypeVersionedApp) 205 n9.Metadata["httpIn"] = 0.8 206 n9.Metadata[graph.IsServiceEntry] = &graph.SEInfo{ 207 Location: "MESH_EXTERNAL", 208 } 209 210 n10, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "egress.not.defined", "testNamespace", "", "", "", graph.GraphTypeVersionedApp) 211 n10.Metadata["httpIn"] = 0.8 212 213 trafficMap[n0.ID] = n0 214 trafficMap[n00.ID] = n00 215 trafficMap[n1.ID] = n1 216 trafficMap[n2.ID] = n2 217 trafficMap[n3.ID] = n3 218 trafficMap[n4.ID] = n4 219 trafficMap[n5.ID] = n5 220 trafficMap[n6.ID] = n6 221 trafficMap[n7.ID] = n7 222 trafficMap[n8.ID] = n8 223 trafficMap[n9.ID] = n9 224 trafficMap[n10.ID] = n10 225 226 n0.AddEdge(n1) 227 e := n00.AddEdge(n1) 228 e.Metadata["http"] = 0.8 229 230 n0.AddEdge(n2) 231 e = n00.AddEdge(n2) 232 e.Metadata["http"] = 0.8 233 234 n0.AddEdge(n3) 235 e = n00.AddEdge(n3) 236 e.Metadata["http"] = 0.8 237 238 n0.AddEdge(n4) 239 e = n00.AddEdge(n4) 240 e.Metadata["http"] = 0.0 241 242 n0.AddEdge(n5) 243 e = n00.AddEdge(n5) 244 e.Metadata["http"] = 0.8 245 246 n0.AddEdge(n6) 247 e = n00.AddEdge(n6) 248 e.Metadata["http"] = 0.0 249 250 n0.AddEdge(n7) 251 e = n00.AddEdge(n7) 252 e.Metadata["tcp"] = 74.1 253 254 n0.AddEdge(n8) 255 e = n00.AddEdge(n8) 256 e.Metadata["tcp"] = 74.1 257 258 n0.AddEdge(n9) 259 e = n00.AddEdge(n9) 260 e.Metadata["http"] = 0.8 261 262 n0.AddEdge(n10) 263 e = n00.AddEdge(n10) 264 e.Metadata["http"] = 0.8 265 266 return trafficMap 267 } 268 269 func TestDeadNodeIssue2783(t *testing.T) { 270 assert := assert.New(t) 271 272 businessLayer := setupWorkloads(t) 273 trafficMap := testTrafficMapIssue2783() 274 275 assert.Equal(3, len(trafficMap)) 276 aID, _, _ := graph.Id(config.DefaultClusterID, "testNamespace", "a", "testNamespace", "a-v1", "a", "v1", graph.GraphTypeVersionedApp) 277 aNode, found := trafficMap[aID] 278 assert.Equal(true, found) 279 assert.Equal(1, len(aNode.Edges)) 280 281 bSvcID, _, _ := graph.Id(config.DefaultClusterID, "testNamespace", "b", graph.Unknown, graph.Unknown, graph.Unknown, graph.Unknown, graph.GraphTypeVersionedApp) 282 bSvcNode, found := trafficMap[bSvcID] 283 assert.Equal(true, found) 284 assert.Equal(1, len(bSvcNode.Edges)) 285 286 bID, _, _ := graph.Id(config.DefaultClusterID, "testNamespace", "b", "testNamespace", "b-v1", "b", "v1", graph.GraphTypeVersionedApp) 287 bNode, found := trafficMap[bID] 288 assert.Equal(true, found) 289 assert.Equal(0, len(bNode.Edges)) 290 291 globalInfo := graph.NewAppenderGlobalInfo() 292 globalInfo.Business = businessLayer 293 namespaceInfo := graph.NewAppenderNamespaceInfo("testNamespace") 294 295 a := DeadNodeAppender{ 296 AccessibleNamespaces: map[string]*graph.AccessibleNamespace{ 297 fmt.Sprintf("%s:testNamespace", config.DefaultClusterID): { 298 Cluster: config.DefaultClusterID, 299 Name: "testNamespace", 300 }, 301 }, 302 } 303 a.AppendGraph(trafficMap, globalInfo, namespaceInfo) 304 305 assert.Equal(0, len(trafficMap)) 306 } 307 308 // testTrafficMapIssue2783() ensures that zero request traffic does not leave behind an injected service node. 309 func testTrafficMapIssue2783() map[string]*graph.Node { 310 trafficMap := make(map[string]*graph.Node) 311 312 n0, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "a", "testNamespace", "a-v1", "a", "v1", graph.GraphTypeVersionedApp) 313 314 n1, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "b", graph.Unknown, graph.Unknown, graph.Unknown, graph.Unknown, graph.GraphTypeVersionedApp) 315 316 n2, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "b", "testNamespace", "b-v1", "b", "v1", graph.GraphTypeVersionedApp) 317 318 trafficMap[n0.ID] = n0 319 trafficMap[n1.ID] = n1 320 trafficMap[n2.ID] = n2 321 322 n0.AddEdge(n1) 323 n1.AddEdge(n2) 324 325 return trafficMap 326 } 327 328 func TestDeadNodeIssue2982(t *testing.T) { 329 assert := assert.New(t) 330 331 businessLayer := setupWorkloads(t) 332 trafficMap := testTrafficMapIssue2982() 333 334 assert.Equal(3, len(trafficMap)) 335 aID, _, _ := graph.Id(config.DefaultClusterID, "testNamespace", "testPodsWithTraffic", "testNamespace", "testPodsWithTraffic-v1", "a", "v1", graph.GraphTypeVersionedApp) 336 aNode, found := trafficMap[aID] 337 assert.Equal(true, found) 338 assert.Equal(1, len(aNode.Edges)) 339 340 bSvcID, _, _ := graph.Id(config.DefaultClusterID, "testNamespace", "b", graph.Unknown, graph.Unknown, graph.Unknown, graph.Unknown, graph.GraphTypeVersionedApp) 341 bSvcNode, found := trafficMap[bSvcID] 342 assert.Equal(true, found) 343 assert.Equal(1, len(bSvcNode.Edges)) 344 345 bID, _, _ := graph.Id(config.DefaultClusterID, "testNamespace", "b", "testNamespace", "b-v1", "b", "v1", graph.GraphTypeVersionedApp) 346 bNode, found := trafficMap[bID] 347 assert.Equal(true, found) 348 assert.Equal(0, len(bNode.Edges)) 349 350 globalInfo := graph.NewAppenderGlobalInfo() 351 globalInfo.Business = businessLayer 352 namespaceInfo := graph.NewAppenderNamespaceInfo("testNamespace") 353 354 a := DeadNodeAppender{ 355 AccessibleNamespaces: map[string]*graph.AccessibleNamespace{ 356 fmt.Sprintf("%s:testNamespace", config.DefaultClusterID): { 357 Cluster: config.DefaultClusterID, 358 Name: "testNamespace", 359 }, 360 }, 361 } 362 a.AppendGraph(trafficMap, globalInfo, namespaceInfo) 363 364 assert.Equal(1, len(trafficMap)) 365 _, found = trafficMap[aID] 366 assert.Equal(true, found) 367 } 368 369 // testTrafficMapIssue2783() ensures that zero request traffic does not leave behind an injected service node. 370 func testTrafficMapIssue2982() map[string]*graph.Node { 371 trafficMap := make(map[string]*graph.Node) 372 373 n0, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "testPodsWithTraffic", "testNamespace", "testPodsWithTraffic-v1", "testPodsWithTraffic", "v1", graph.GraphTypeVersionedApp) 374 n0.Metadata["httpIn"] = 0.8 375 376 n1, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "b", graph.Unknown, graph.Unknown, graph.Unknown, graph.Unknown, graph.GraphTypeVersionedApp) 377 378 n2, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "b", "testNamespace", "b-v1", "b", "v1", graph.GraphTypeVersionedApp) 379 380 trafficMap[n0.ID] = n0 381 trafficMap[n1.ID] = n1 382 trafficMap[n2.ID] = n2 383 384 n0.AddEdge(n1) 385 n1.AddEdge(n2) 386 387 return trafficMap 388 } 389 390 func TestDeadNodeIssue7179(t *testing.T) { 391 assert := assert.New(t) 392 393 businessLayer := setupWorkloads(t) 394 trafficMap := testTrafficMapIssue7179() 395 396 assert.Equal(2, len(trafficMap)) 397 aID, _, _ := graph.Id(config.DefaultClusterID, "testNamespace", "testPodsWithTraffic", "testNamespace", "testPodsWithTraffic-v1", "a", "v1", graph.GraphTypeVersionedApp) 398 aNode, found := trafficMap[aID] 399 assert.Equal(true, found) 400 assert.Equal(1, len(aNode.Edges)) 401 402 bID, _, _ := graph.Id("InaccessibleCluster", "testNamespace", "noTraffic", "testNamespace", "noTraffic-v1", "b", "v1", graph.GraphTypeVersionedApp) 403 bNode, found := trafficMap[bID] 404 assert.Equal(true, found) 405 assert.Equal(0, len(bNode.Edges)) 406 407 globalInfo := graph.NewAppenderGlobalInfo() 408 globalInfo.Business = businessLayer 409 namespaceInfo := graph.NewAppenderNamespaceInfo("testNamespace") 410 411 a := DeadNodeAppender{ 412 AccessibleNamespaces: map[string]*graph.AccessibleNamespace{ 413 fmt.Sprintf("%s:testNamespace", config.DefaultClusterID): { 414 Cluster: config.DefaultClusterID, 415 Name: "testNamespace", 416 }, 417 }, 418 } 419 a.AppendGraph(trafficMap, globalInfo, namespaceInfo) 420 421 assert.Equal(2, len(trafficMap)) 422 _, found = trafficMap[aID] 423 assert.Equal(true, found) 424 _, found = trafficMap[bID] 425 assert.Equal(true, found) 426 } 427 428 // testTrafficMapIssue7179() ensures we assume that innaccessible workloads are not dead. 429 func testTrafficMapIssue7179() map[string]*graph.Node { 430 trafficMap := make(map[string]*graph.Node) 431 432 n0, _ := graph.NewNode(config.DefaultClusterID, "testNamespace", "testPodsWithTraffic", "testNamespace", "testPodsWithTraffic-v1", "testPodsWithTraffic", "v1", graph.GraphTypeVersionedApp) 433 n0.Metadata["httpIn"] = 0.8 434 435 n1, _ := graph.NewNode("InaccessibleCluster", "testNamespace", "noTraffic", "testNamespace", "noTraffic-v1", "noTraffic", "v1", graph.GraphTypeVersionedApp) 436 437 trafficMap[n0.ID] = n0 438 trafficMap[n1.ID] = n1 439 440 n0.AddEdge(n1) 441 442 return trafficMap 443 }