forked from kiali/kiali
-
Notifications
You must be signed in to change notification settings - Fork 0
/
host.go
144 lines (124 loc) · 3.43 KB
/
host.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
package kubernetes
import (
"fmt"
"strings"
core_v1 "k8s.io/api/core/v1"
"github.com/kiali/kiali/config"
)
// Host represents the FQDN format for Istio hostnames
type Host struct {
Service string
Namespace string
Cluster string
// CompleteInput is true when Service, Namespace and Cluster fields are present.
// It is true for simple service names and FQDN services.
// It is false for service.namespace format and service entries.
CompleteInput bool
}
// ParseHost takes as an input a hostname (simple or full FQDN), namespace and clusterName and returns a parsed Host struct
func ParseHost(hostName, namespace, cluster string) Host {
if cluster == "" {
cluster = config.Get().ExternalServices.Istio.IstioIdentityDomain
}
domainParts := strings.Split(hostName, ".")
host := Host{
Service: domainParts[0],
}
if len(domainParts) > 1 {
if len(domainParts) > 2 {
parsedClusterName := strings.Join(domainParts[2:], ".")
if parsedClusterName == cluster {
// FQDN input
host.Cluster = cluster
host.CompleteInput = true
}
}
if host.CompleteInput {
host.Namespace = domainParts[1]
} else {
// ServiceEntry or broken hostname
host.Service = hostName
}
} else {
// Simple format
host.Namespace = namespace
host.Cluster = cluster
host.CompleteInput = true
}
return host
}
// GetHost parses hostName and returns a Host struct. It considers Namespaces in the cluster to be more accurate
// when deciding if the hostName is a ServiceEntry or a service.namespace host definition.
func GetHost(hostName, namespace, cluster string, clusterNamespaces []string) Host {
hParts := strings.Split(hostName, ".")
// It might be a service entry or a 2-format host specification
if len(hParts) == 2 {
// It is subject of validation when object is within the namespace
// Otherwise is considered as a service entry
if hParts[1] == namespace || includes(clusterNamespaces, hParts[1]) {
return Host{
Service: hParts[0],
Namespace: hParts[1],
Cluster: cluster,
CompleteInput: true,
}
}
}
return ParseHost(hostName, namespace, cluster)
}
func includes(nss []string, namespace string) bool {
for _, ns := range nss {
if ns == namespace {
return true
}
}
return false
}
// String outputs a full FQDN version of the Host
func (h Host) String() string {
return fmt.Sprintf("%s.%s.%s", h.Service, h.Namespace, h.Cluster)
}
func ParseTwoPartHost(host Host) (string, string) {
localSvc, localNs := host.Service, host.Namespace
if !host.CompleteInput {
svcParts := strings.Split(host.Service, ".")
if len(svcParts) > 1 {
localSvc = svcParts[0]
localNs = svcParts[1]
}
}
return localSvc, localNs
}
func HasMatchingWorkloads(service string, workloadList []map[string]string) bool {
appLabel := config.Get().IstioLabels.AppLabelName
// Check Workloads
for _, wl := range workloadList {
if service == wl[appLabel] {
return true
}
}
return false
}
func HasMatchingServices(service string, services []core_v1.Service) bool {
for _, s := range services {
if service == s.Name {
return true
}
}
return false
}
func HasMatchingServiceEntries(service string, serviceEntries map[string][]string) bool {
for k := range serviceEntries {
hostKey := k
if i := strings.Index(k, "*"); i > -1 {
hostKey = k[i+1:]
}
if strings.HasSuffix(service, hostKey) {
return true
}
}
if _, found := serviceEntries[service]; found {
return true
}
return false
}