forked from kiali/kiali
/
istio_details.go
137 lines (123 loc) · 4.43 KB
/
istio_details.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package appender
import (
"github.com/kiali/kiali/business"
"github.com/kiali/kiali/config"
"github.com/kiali/kiali/graph"
"github.com/kiali/kiali/log"
"github.com/kiali/kiali/models"
)
const IstioAppenderName = "istio"
// IstioAppender is responsible for badging nodes with special Istio significance:
// - CircuitBreaker: n.Metadata["hasCB"] = true
// - VirtualService: n.Metadata["hasVS"] = true
// Name: istio
type IstioAppender struct{}
// Name implements Appender
func (a IstioAppender) Name() string {
return IstioAppenderName
}
// AppendGraph implements Appender
func (a IstioAppender) AppendGraph(trafficMap graph.TrafficMap, globalInfo *GlobalInfo, namespaceInfo *NamespaceInfo) {
if len(trafficMap) == 0 {
return
}
if globalInfo.Business == nil {
var err error
globalInfo.Business, err = business.Get()
checkError(err)
}
addBadging(trafficMap, globalInfo, namespaceInfo)
addLabels(trafficMap, globalInfo, namespaceInfo)
}
func addBadging(trafficMap graph.TrafficMap, globalInfo *GlobalInfo, namespaceInfo *NamespaceInfo) {
// Currently no other appenders use DestinationRules or VirtualServices, so they are not cached in NamespaceInfo
istioCfg, err := globalInfo.Business.IstioConfig.GetIstioConfigList(business.IstioConfigCriteria{
IncludeDestinationRules: true,
IncludeVirtualServices: true,
Namespace: namespaceInfo.Namespace,
})
checkError(err)
applyCircuitBreakers(trafficMap, namespaceInfo.Namespace, istioCfg)
applyVirtualServices(trafficMap, namespaceInfo.Namespace, istioCfg)
}
func applyCircuitBreakers(trafficMap graph.TrafficMap, namespace string, istioCfg models.IstioConfigList) {
NODES:
for _, n := range trafficMap {
// Skip the check if this node is outside the requested namespace, we limit badging to the requested namespaces
if n.Namespace != namespace {
continue
}
// Note, Because DestinationRules are applied to services we limit CB badges to service nodes and app nodes.
// Whether we should add to workload nodes is debatable, we could add it later if needed.
versionOk := n.Version != "" && n.Version != graph.UnknownVersion
switch {
case n.NodeType == graph.NodeTypeService:
for _, destinationRule := range istioCfg.DestinationRules.Items {
if destinationRule.HasCircuitBreaker(namespace, n.Service, "") {
n.Metadata["hasCB"] = true
continue NODES
}
}
case !versionOk && (n.NodeType == graph.NodeTypeApp):
if destServices, ok := n.Metadata["destServices"]; ok {
for serviceName, _ := range destServices.(map[string]bool) {
for _, destinationRule := range istioCfg.DestinationRules.Items {
if destinationRule.HasCircuitBreaker(namespace, serviceName, "") {
n.Metadata["hasCB"] = true
continue NODES
}
}
}
}
case versionOk:
if destServices, ok := n.Metadata["destServices"]; ok {
for serviceName, _ := range destServices.(map[string]bool) {
for _, destinationRule := range istioCfg.DestinationRules.Items {
if destinationRule.HasCircuitBreaker(namespace, serviceName, n.Version) {
n.Metadata["hasCB"] = true
continue NODES
}
}
}
}
default:
continue
}
}
}
func applyVirtualServices(trafficMap graph.TrafficMap, namespace string, istioCfg models.IstioConfigList) {
NODES:
for _, n := range trafficMap {
if n.NodeType != graph.NodeTypeService {
continue
}
if n.Namespace != namespace {
continue
}
for _, virtualService := range istioCfg.VirtualServices.Items {
if virtualService.IsValidHost(namespace, n.Service) {
n.Metadata["hasVS"] = true
continue NODES
}
}
}
}
// addLabels is a chance to add any missing label info to nodes when the telemetry does not provide enough information.
func addLabels(trafficMap graph.TrafficMap, globalInfo *GlobalInfo, namespaceInfo *NamespaceInfo) {
appLabelName := config.Get().IstioLabels.AppLabelName
for _, n := range trafficMap {
// make sure service nodes have the defined app label so it can be used for app grouping in the UI.
if n.NodeType == graph.NodeTypeService && n.App == "" {
service, err := globalInfo.Business.Svc.GetServiceDefinition(namespaceInfo.Namespace, n.Service)
if err != nil {
log.Debugf("Error fetching service definition, may not apply app label correctly for namespace=%s svc=%s: %s", namespaceInfo.Namespace, n.Service, err.Error())
if service == nil {
continue
}
}
if app, ok := service.Service.Labels[appLabelName]; ok {
n.App = app
}
}
}
}