github.com/kiali/kiali@v1.84.0/graph/telemetry/istio/appender/mesh_check.go (about) 1 package appender 2 3 import ( 4 "github.com/kiali/kiali/config" 5 "github.com/kiali/kiali/graph" 6 ) 7 8 const MeshCheckAppenderName = "meshCheck" 9 const SidecarsCheckAppenderName = "sidecarsCheck" 10 11 // MeshCheckAppender flags nodes whose backing workloads are missing at least one Envoy sidecar. Note that 12 // a node with no backing workloads is not flagged. 13 // Name: meshCheck 14 type MeshCheckAppender struct { 15 AccessibleNamespaces graph.AccessibleNamespaces 16 } 17 18 // Name implements Appender 19 func (a MeshCheckAppender) Name() string { 20 return MeshCheckAppenderName 21 } 22 23 // IsFinalizer implements Appender 24 func (a MeshCheckAppender) IsFinalizer() bool { 25 return false 26 } 27 28 // AppendGraph implements Appender 29 func (a MeshCheckAppender) AppendGraph(trafficMap graph.TrafficMap, globalInfo *graph.AppenderGlobalInfo, namespaceInfo *graph.AppenderNamespaceInfo) { 30 if len(trafficMap) == 0 { 31 return 32 } 33 34 a.applyMeshChecks(trafficMap, globalInfo, namespaceInfo) 35 } 36 37 func (a *MeshCheckAppender) applyMeshChecks(trafficMap graph.TrafficMap, globalInfo *graph.AppenderGlobalInfo, namespaceInfo *graph.AppenderNamespaceInfo) { 38 for _, n := range trafficMap { 39 // skip if we've already determined the node is out-of-mesh. we may process the same 40 // node multiple times to ensure we check every node (e.g. missing sidecars indicate missing 41 // telemetry and so we need to check nodes when we can, regardless of namespace) 42 if n.Metadata[graph.IsOutOfMesh] == true { 43 continue 44 } 45 46 // skip if the node is not in an accessible namespace, we can't do the checking 47 if !a.nodeOK(n) { 48 continue 49 } 50 51 // We whitelist istio components because they may not report telemetry using injected sidecars. 52 if config.IsIstioNamespace(n.Namespace) { 53 continue 54 } 55 56 // dead nodes tell no tales (er, have no pods) 57 if isDead, ok := n.Metadata[graph.IsDead]; ok && isDead.(bool) { 58 continue 59 } 60 61 // get the workloads for the node and check to see if they have sidecars. Note that 62 // if there are no workloads/pods we don't flag it as missing sidecars. No pods means 63 // no missing sidecars. (In most cases this means it was flagged as dead, and handled above) 64 hasIstioSidecar := true 65 hasIstioAmbient := true 66 switch n.NodeType { 67 case graph.NodeTypeWorkload: 68 if workload, found := getWorkload(n.Cluster, n.Namespace, n.Workload, globalInfo); found { 69 hasIstioSidecar = workload.IstioSidecar 70 hasIstioAmbient = workload.IstioAmbient 71 } 72 case graph.NodeTypeApp: 73 workloads := getAppWorkloads(n.Cluster, n.Namespace, n.App, n.Version, globalInfo) 74 if len(workloads) > 0 { 75 for _, workload := range workloads { 76 if !workload.IstioSidecar { 77 hasIstioSidecar = false 78 } 79 if !workload.IstioAmbient { 80 hasIstioAmbient = false 81 } 82 if !hasIstioSidecar && !hasIstioAmbient { 83 break 84 } 85 } 86 } 87 default: 88 continue 89 } 90 91 if !hasIstioSidecar && !hasIstioAmbient && n.Metadata[graph.IsWaypoint] != true { 92 n.Metadata[graph.IsOutOfMesh] = true 93 } 94 95 } 96 } 97 98 // nodeOK returns true if we have access to its workload info 99 func (a *MeshCheckAppender) nodeOK(node *graph.Node) bool { 100 key := graph.GetClusterSensitiveKey(node.Cluster, node.Namespace) 101 _, ok := a.AccessibleNamespaces[key] 102 return ok 103 }