forked from kiali/kiali
/
istio_details_service.go
162 lines (145 loc) · 5.57 KB
/
istio_details_service.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package kubernetes
import (
"fmt"
"sync"
)
// GetIstioDetails returns Istio details for a given service,
// on this version it describes the RouterRules and destinationPolicies defined for a service.
// A service is defined by the namespace and the service name.
// It returns an error on any problem.
func (in *IstioClient) GetIstioDetails(namespace string, serviceName string) (*IstioDetails, error) {
var routeRules, destinationPolicies, virtualServices, destinationRules []IstioObject
var routeRulesErr, destinationPoliciesErr, virtualServicesErr, destinationRulesErr error
var wg sync.WaitGroup
wg.Add(4)
go func() {
defer wg.Done()
routeRules, routeRulesErr = in.GetRouteRules(namespace, serviceName)
}()
go func() {
defer wg.Done()
destinationPolicies, destinationPoliciesErr = in.GetDestinationPolicies(namespace, serviceName)
}()
go func() {
defer wg.Done()
virtualServices, virtualServicesErr = in.GetVirtualServices(namespace, serviceName)
}()
go func() {
defer wg.Done()
destinationRules, destinationRulesErr = in.GetDestinationRules(namespace, serviceName)
}()
wg.Wait()
var istioDetails = IstioDetails{}
istioDetails.RouteRules = routeRules
if routeRulesErr != nil {
return nil, routeRulesErr
}
istioDetails.DestinationPolicies = destinationPolicies
if destinationPoliciesErr != nil {
return nil, destinationPoliciesErr
}
istioDetails.VirtualServices = virtualServices
if virtualServicesErr != nil {
return nil, virtualServicesErr
}
istioDetails.DestinationRules = destinationRules
if destinationRulesErr != nil {
return nil, destinationRulesErr
}
return &istioDetails, nil
}
func (in *IstioClient) GetRouteRules(namespace string, serviceName string) ([]IstioObject, error) {
result, err := in.istioConfigApi.Get().Namespace(namespace).Resource(routeRules).Do().Get()
if err != nil {
return nil, err
}
rulesList, ok := result.(*RouteRuleList)
if !ok {
return nil, fmt.Errorf("%s/%s doesn't return a RouteRule list", namespace, serviceName)
}
// RouterRules have its own names non related to the service which are defined.
// So, to fetch the rules per a specific service we need to filter by destination.
// Probably in future iterations we might change this if it's not enough.
routerRules := make([]IstioObject, 0)
for _, rule := range rulesList.GetItems() {
if destination, ok := rule.GetSpec()["destination"]; ok {
dest := destination.(map[string]interface{})
if dest["name"] == serviceName {
routerRules = append(routerRules, rule.DeepCopyIstioObject())
}
}
}
return routerRules, nil
}
func (in *IstioClient) GetDestinationPolicies(namespace string, serviceName string) ([]IstioObject, error) {
result, err := in.istioConfigApi.Get().Namespace(namespace).Resource(destinationPolicies).Do().Get()
if err != nil {
return nil, err
}
destinationPolicyList, ok := result.(*DestinationPolicyList)
if !ok {
return nil, fmt.Errorf("%s/%s doesn't return a DestinationPolicy list", namespace, serviceName)
}
// destinationPolicies have its own names non related to the service which are defined.
// So, to fetch the rules per a specific service we need to filter by destination.
// Probably in future iterations we might change this if it's not enough.
destinationPolicies := make([]IstioObject, 0)
for _, policy := range destinationPolicyList.Items {
if destination, ok := policy.Spec["destination"]; ok {
dest := destination.(map[string]interface{})
if dest["name"] == serviceName {
destinationPolicies = append(destinationPolicies, policy.DeepCopyIstioObject())
}
}
}
return destinationPolicies, nil
}
func (in *IstioClient) GetVirtualServices(namespace string, serviceName string) ([]IstioObject, error) {
result, err := in.istioNetworkingApi.Get().Namespace(namespace).Resource(virtualServices).Do().Get()
if err != nil {
return nil, err
}
virtualServiceList, ok := result.(*VirtualServiceList)
if !ok {
return nil, fmt.Errorf("%s/%s doesn't return a VirtualService list", namespace, serviceName)
}
// VirtualServices have its own names non related to the service which are defined.
// So, to fetch the rules per a specific service we need to filter by hosts.
// Probably in future iterations we might change this if it's not enough.
virtualServices := make([]IstioObject, 0)
for _, virtualService := range virtualServiceList.GetItems() {
if hosts, ok := virtualService.GetSpec()["hosts"]; ok {
if hostsArray, ok := hosts.([]interface{}); ok {
for _, host := range hostsArray {
if host == serviceName {
virtualServices = append(virtualServices, virtualService.DeepCopyIstioObject())
break
}
}
}
}
}
return virtualServices, nil
}
func (in *IstioClient) GetDestinationRules(namespace string, serviceName string) ([]IstioObject, error) {
result, err := in.istioNetworkingApi.Get().Namespace(namespace).Resource(destinationRules).Do().Get()
if err != nil {
return nil, err
}
destinationRuleList, ok := result.(*DestinationRuleList)
if !ok {
return nil, fmt.Errorf("%s/%s doesn't return a DestinationRule list", namespace, serviceName)
}
// DestinationRules have its own names non related to the service which are defined.
// So, to fetch the rules per a specific service we need to filter by name.
// Probably in future iterations we might change this if it's not enough.
destinationRules := make([]IstioObject, 0)
for _, destinationRule := range destinationRuleList.Items {
if name, ok := destinationRule.Spec["name"]; ok {
if name == serviceName {
destinationRules = append(destinationRules, destinationRule.DeepCopyIstioObject())
}
}
}
return destinationRules, nil
}