forked from weaveworks/scope
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathid.go
328 lines (256 loc) · 12 KB
/
id.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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
package report
import (
"net"
"strconv"
"strings"
)
// Delimiters are used to separate parts of node IDs, to guarantee uniqueness
// in particular contexts.
const (
// ScopeDelim is a general-purpose delimiter used within node IDs to
// separate different contextual scopes. Different topologies have
// different key structures.
ScopeDelim = ";"
// EdgeDelim separates two node IDs when they need to exist in the same key.
// Concretely, it separates node IDs in keys that represent edges.
EdgeDelim = "|"
// Key added to nodes to prevent them being joined with conntracked connections
DoesNotMakeConnections = "does_not_make_connections"
// WeaveOverlayPeerPrefix is the prefix for weave peers in the overlay network
WeaveOverlayPeerPrefix = ""
// DockerOverlayPeerPrefix is the prefix for docker peers in the overlay network
DockerOverlayPeerPrefix = "docker_peer_"
)
// MakeEndpointNodeID produces an endpoint node ID from its composite parts.
func MakeEndpointNodeID(hostID, namespaceID, address, port string) string {
addressIP := net.ParseIP(address)
return makeAddressID(hostID, namespaceID, address, addressIP) + ScopeDelim + port
}
// MakeEndpointNodeIDB produces an endpoint node ID from its composite parts in binary, not strings.
func MakeEndpointNodeIDB(hostID string, namespaceID uint32, addressIP net.IP, port uint16) string {
namespace := ""
if namespaceID > 0 {
namespace = strconv.FormatUint(uint64(namespaceID), 10)
}
return makeAddressID(hostID, namespace, addressIP.String(), addressIP) + ScopeDelim + strconv.Itoa(int(port))
}
// MakeAddressNodeID produces an address node ID from its composite parts.
func MakeAddressNodeID(hostID, address string) string {
addressIP := net.ParseIP(address)
return makeAddressID(hostID, "", address, addressIP)
}
// MakeAddressNodeIDB produces an address node ID from its composite parts, in binary not string.
func MakeAddressNodeIDB(hostID string, addressIP net.IP) string {
return makeAddressID(hostID, "", addressIP.String(), addressIP)
}
func makeAddressID(hostID, namespaceID, address string, addressIP net.IP) string {
var scope string
// Loopback addresses and addresses explicitly marked as local get
// scoped by hostID
// Loopback addresses are also scoped by the networking
// namespace if available, since they can clash.
if addressIP != nil && LocalNetworks.Contains(addressIP) {
scope = hostID
} else if addressIP != nil && addressIP.IsLoopback() {
scope = hostID
if namespaceID != "" {
scope += "-" + namespaceID
}
}
return scope + ScopeDelim + address
}
// MakeScopedEndpointNodeID is like MakeEndpointNodeID, but it always
// prefixes the ID with a scope.
func MakeScopedEndpointNodeID(scope, address, port string) string {
return scope + ScopeDelim + address + ScopeDelim + port
}
// MakeScopedAddressNodeID is like MakeAddressNodeID, but it always
// prefixes the ID witha scope.
func MakeScopedAddressNodeID(scope, address string) string {
return scope + ScopeDelim + address
}
// MakeProcessNodeID produces a process node ID from its composite parts.
func MakeProcessNodeID(hostID, pid string) string {
return hostID + ScopeDelim + pid
}
// MakeECSServiceNodeID produces an ECS Service node ID from its composite parts.
func MakeECSServiceNodeID(cluster, serviceName string) string {
return cluster + ScopeDelim + serviceName
}
var (
// MakeHostNodeID produces a host node ID from its composite parts.
MakeHostNodeID = makeSingleComponentID("host")
// ParseHostNodeID parses a host node ID
ParseHostNodeID = parseSingleComponentID("host")
// MakeContainerNodeID produces a container node ID from its composite parts.
MakeContainerNodeID = makeSingleComponentID("container")
// ParseContainerNodeID parses a container node ID
ParseContainerNodeID = parseSingleComponentID("container")
// MakeContainerImageNodeID produces a container image node ID from its composite parts.
MakeContainerImageNodeID = makeSingleComponentID("container_image")
// ParseContainerImageNodeID parses a container image node ID
ParseContainerImageNodeID = parseSingleComponentID("container_image")
// MakePodNodeID produces a pod node ID from its composite parts.
MakePodNodeID = makeSingleComponentID("pod")
// ParsePodNodeID parses a pod node ID
ParsePodNodeID = parseSingleComponentID("pod")
// MakeServiceNodeID produces a service node ID from its composite parts.
MakeServiceNodeID = makeSingleComponentID("service")
// ParseServiceNodeID parses a service node ID
ParseServiceNodeID = parseSingleComponentID("service")
// MakeDeploymentNodeID produces a deployment node ID from its composite parts.
MakeDeploymentNodeID = makeSingleComponentID("deployment")
// ParseDeploymentNodeID parses a deployment node ID
ParseDeploymentNodeID = parseSingleComponentID("deployment")
// MakeReplicaSetNodeID produces a replica set node ID from its composite parts.
MakeReplicaSetNodeID = makeSingleComponentID("replica_set")
// ParseReplicaSetNodeID parses a replica set node ID
ParseReplicaSetNodeID = parseSingleComponentID("replica_set")
// MakeDaemonSetNodeID produces a replica set node ID from its composite parts.
MakeDaemonSetNodeID = makeSingleComponentID("daemonset")
// ParseDaemonSetNodeID parses a daemon set node ID
ParseDaemonSetNodeID = parseSingleComponentID("daemonset")
// MakeStatefulSetNodeID produces a statefulset node ID from its composite parts.
MakeStatefulSetNodeID = makeSingleComponentID("statefulset")
// ParseStatefulSetNodeID parses a statefulset node ID
ParseStatefulSetNodeID = parseSingleComponentID("statefulset")
// MakeCronJobNodeID produces a cronjob node ID from its composite parts.
MakeCronJobNodeID = makeSingleComponentID("cronjob")
// ParseCronJobNodeID parses a cronjob node ID
ParseCronJobNodeID = parseSingleComponentID("cronjob")
// MakeJobNodeID produces a job node ID from its composite parts.
MakeJobNodeID = makeSingleComponentID("job")
// ParseJobNodeID parses a job node ID
ParseJobNodeID = parseSingleComponentID("job")
// MakeNamespaceNodeID produces a namespace node ID from its composite parts.
MakeNamespaceNodeID = makeSingleComponentID("namespace")
// ParseNamespaceNodeID parses a namespace set node ID
ParseNamespaceNodeID = parseSingleComponentID("namespace")
// MakeECSTaskNodeID produces a ECSTask node ID from its composite parts.
MakeECSTaskNodeID = makeSingleComponentID("ecs_task")
// ParseECSTaskNodeID parses a ECSTask node ID
ParseECSTaskNodeID = parseSingleComponentID("ecs_task")
// MakeSwarmServiceNodeID produces a Swarm service node ID from its composite parts.
MakeSwarmServiceNodeID = makeSingleComponentID("swarm_service")
// ParseSwarmServiceNodeID parses a Swarm service node ID
ParseSwarmServiceNodeID = parseSingleComponentID("swarm_service")
// MakePersistentVolumeNodeID produces a Persistent Volume node ID from its composite parts.
MakePersistentVolumeNodeID = makeSingleComponentID("persistent_volume")
// ParsePersistentVolumeNodeID parses a Persistent Volume node ID
ParsePersistentVolumeNodeID = parseSingleComponentID("persistent_volume")
// MakePersistentVolumeClaimNodeID produces a Persistent Volume Claim node ID from its composite parts.
MakePersistentVolumeClaimNodeID = makeSingleComponentID("persistent_volume_claim")
// ParsePersistentVolumeClaimNodeID parses a Persistent Volume Claim node ID
ParsePersistentVolumeClaimNodeID = parseSingleComponentID("persistent_volume_claim")
// MakeStorageClassNodeID produces a storage class node ID from its composite parts.
MakeStorageClassNodeID = makeSingleComponentID("storage_class")
// ParseStorageClassNodeID parses a storage class node ID
ParseStorageClassNodeID = parseSingleComponentID("storage_class")
// MakeVolumeSnapshotNodeID produces a volume snapshot node ID from its composite parts.
MakeVolumeSnapshotNodeID = makeSingleComponentID("volume_snapshot")
// ParseVolumeSnapshotNodeID parses a volume snapshot node ID
ParseVolumeSnapshotNodeID = parseSingleComponentID("volume_snapshot")
// MakeVolumeSnapshotDataNodeID produces a volume snapshot data node ID from its composite parts.
MakeVolumeSnapshotDataNodeID = makeSingleComponentID("volume_snapshot_data")
// ParseVolumeSnapshotDataNodeID parses a volume snapshot data node ID
ParseVolumeSnapshotDataNodeID = parseSingleComponentID("volume_snapshot_data")
)
// makeSingleComponentID makes a single-component node id encoder
func makeSingleComponentID(tag string) func(string) string {
return func(id string) string {
return id + ScopeDelim + "<" + tag + ">"
}
}
// parseSingleComponentID makes a single-component node id decoder
func parseSingleComponentID(tag string) func(string) (string, bool) {
return func(id string) (string, bool) {
field0, field1, ok := split2(id, ScopeDelim)
if !ok || field1 != "<"+tag+">" {
return "", false
}
return field0, true
}
}
// MakeOverlayNodeID produces an overlay topology node ID from a router peer's
// prefix and name, which is assumed to be globally unique.
func MakeOverlayNodeID(peerPrefix, peerName string) string {
return "#" + peerPrefix + peerName
}
// ParseOverlayNodeID produces the overlay type and peer name.
func ParseOverlayNodeID(id string) (overlayPrefix string, peerName string) {
if !strings.HasPrefix(id, "#") {
// Best we can do
return "", ""
}
id = id[1:]
if strings.HasPrefix(id, DockerOverlayPeerPrefix) {
return DockerOverlayPeerPrefix, id[len(DockerOverlayPeerPrefix):]
}
return WeaveOverlayPeerPrefix, id
}
// Split a string s into two parts separated by sep.
func split2(s, sep string) (s1, s2 string, ok bool) {
// Not using strings.SplitN() to avoid a heap allocation
pos := strings.Index(s, sep)
if pos == -1 {
return "", "", false
}
return s[:pos], s[pos+1:], true
}
// ParseNodeID produces the id and tag of a single-component node ID.
func ParseNodeID(nodeID string) (id string, tag string, ok bool) {
return split2(nodeID, ScopeDelim)
}
// ParseEndpointNodeID produces the scope, address, and port and remainder.
// Note that scope may be blank.
func ParseEndpointNodeID(endpointNodeID string) (scope, address, port string, ok bool) {
// Not using strings.SplitN() to avoid a heap allocation
first := strings.Index(endpointNodeID, ScopeDelim)
if first == -1 {
return "", "", "", false
}
second := strings.Index(endpointNodeID[first+1:], ScopeDelim)
if second == -1 {
return "", "", "", false
}
return endpointNodeID[:first], endpointNodeID[first+1 : first+1+second], endpointNodeID[first+1+second+1:], true
}
// ParseAddressNodeID produces the host ID, address from an address node ID.
func ParseAddressNodeID(addressNodeID string) (hostID, address string, ok bool) {
return split2(addressNodeID, ScopeDelim)
}
// ParseProcessNodeID produces the host ID and PID from a process node ID.
func ParseProcessNodeID(processNodeID string) (hostID, pid string, ok bool) {
return split2(processNodeID, ScopeDelim)
}
// ParseECSServiceNodeID produces the cluster, service name from an ECS Service node ID
func ParseECSServiceNodeID(ecsServiceNodeID string) (cluster, serviceName string, ok bool) {
cluster, serviceName, ok = split2(ecsServiceNodeID, ScopeDelim)
if !ok {
return "", "", false
}
// In previous versions, ECS Service node IDs were of form serviceName + "<ecs_service>".
// For backwards compatibility, we should still return a sensical serviceName for these cases.
if serviceName == "<ecs_service>" {
return "unknown", cluster, true
}
return cluster, serviceName, true
}
// ExtractHostID extracts the host id from Node
func ExtractHostID(m Node) string {
hostNodeID, _ := m.Latest.Lookup(HostNodeID)
hostID, _ := ParseHostNodeID(hostNodeID)
return hostID
}
// IsLoopback ascertains if an address comes from a loopback interface.
func IsLoopback(address string) bool {
ip := net.ParseIP(address)
return ip != nil && ip.IsLoopback()
}
// IsPauseImageName indicates whether an image name corresponds to a
// kubernetes pause container image.
func IsPauseImageName(imageName string) bool {
return strings.Contains(imageName, "google_containers/pause") ||
strings.Contains(imageName, "k8s.gcr.io/pause") ||
strings.Contains(imageName, "eks/pause")
}