mirror of
https://github.com/weaveworks/scope.git
synced 2026-05-06 01:08:03 +00:00
This dependency makes it harder to see the structure of the program, and sometimes complicates compilation. Mostly just changing the source of strings that are already exported from the report package. A few new strings have to be moved there, plus the function `IsPauseImageName()`.
313 lines
11 KiB
Go
313 lines
11 KiB
Go
package report
|
|
|
|
import (
|
|
"net"
|
|
"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 {
|
|
return makeAddressID(hostID, namespaceID, address) + ScopeDelim + port
|
|
}
|
|
|
|
// MakeAddressNodeID produces an address node ID from its composite parts.
|
|
func MakeAddressNodeID(hostID, address string) string {
|
|
return makeAddressID(hostID, "", address)
|
|
}
|
|
|
|
func makeAddressID(hostID, namespaceID, address string) 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.
|
|
addressIP := net.ParseIP(address)
|
|
if addressIP != nil && LocalNetworks.Contains(addressIP) {
|
|
scope = hostID
|
|
} else if IsLoopback(address) {
|
|
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")
|
|
}
|