id.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package render
  2. import (
  3. "strings"
  4. "github.com/weaveworks/scope/report"
  5. )
  6. // Constants are used in the tests.
  7. const (
  8. IncomingInternetID = "in-theinternet"
  9. OutgoingInternetID = "out-theinternet"
  10. )
  11. // IsInternetNode determines whether the node represents the Internet.
  12. func IsInternetNode(n report.Node) bool {
  13. return n.ID == IncomingInternetID || n.ID == OutgoingInternetID
  14. }
  15. // MakePseudoNodeID joins the parts of an id into the id of a pseudonode
  16. func MakePseudoNodeID(parts ...string) string {
  17. return strings.Join(append([]string{"pseudo"}, parts...), ":")
  18. }
  19. // ParsePseudoNodeID returns the joined id parts of a pseudonode
  20. // ID. If the ID is not recognisable as a pseudonode ID, it is
  21. // returned as is, with the returned bool set to false. That is
  22. // convenient because not all pseudonode IDs actually follow the
  23. // format produced by MakePseudoNodeID.
  24. func ParsePseudoNodeID(nodeID string) (string, bool) {
  25. // Not using strings.SplitN() to avoid a heap allocation
  26. pos := strings.Index(nodeID, ":")
  27. if pos == -1 || nodeID[:pos] != "pseudo" {
  28. return nodeID, false
  29. }
  30. return nodeID[pos+1:], true
  31. }
  32. // MakeGroupNodeTopology joins the parts of a group topology into the topology of a group node
  33. func MakeGroupNodeTopology(originalTopology, key string) string {
  34. return strings.Join([]string{"group", originalTopology, key}, ":")
  35. }
  36. // ParseGroupNodeTopology returns the parts of a group topology.
  37. func ParseGroupNodeTopology(topology string) (string, string, bool) {
  38. parts := strings.Split(topology, ":")
  39. if len(parts) != 3 || parts[0] != "group" {
  40. return "", "", false
  41. }
  42. return parts[1], parts[2], true
  43. }
  44. // NewDerivedNode makes a node based on node, but with a new ID
  45. func NewDerivedNode(id string, node report.Node) report.Node {
  46. return report.MakeNode(id).WithChildren(node.Children.Add(node))
  47. }
  48. // NewDerivedPseudoNode makes a new pseudo node with the node as a child
  49. func NewDerivedPseudoNode(id string, node report.Node) report.Node {
  50. output := NewDerivedNode(id, node).WithTopology(Pseudo)
  51. return output
  52. }
  53. func pseudoNodeID(rpt report.Report, n report.Node, local report.Networks) (string, bool) {
  54. _, addr, _, ok := report.ParseEndpointNodeID(n.ID)
  55. if !ok {
  56. return "", false
  57. }
  58. if id, ok := externalNodeID(rpt, n, addr, local); ok {
  59. return id, ok
  60. }
  61. // due to https://github.com/weaveworks/scope/issues/1323 we are dropping
  62. // all non-external pseudo nodes for now.
  63. return "", false
  64. }
  65. // figure out if a node should be considered external and returns an ID which can be used to create a pseudo node
  66. func externalNodeID(rpt report.Report, n report.Node, addr string, local report.Networks) (string, bool) {
  67. // First, check if it's a known service and emit a a specific node if it
  68. // is. This needs to be done before checking IPs since known services can
  69. // live in the same network, see https://github.com/weaveworks/scope/issues/2163
  70. if hostname, found := rpt.DNS.FirstMatch(n.ID, isKnownService); found {
  71. return ServiceNodeIDPrefix + hostname, true
  72. }
  73. // If the dstNodeAddr is not in a network local to this report, we emit an
  74. // internet pseudoNode
  75. // Create a buffer on the stack of this function, so we don't need to allocate in ParseIP
  76. var into [5]byte // one extra byte to save a memory allocation in critbitgo
  77. if ip := report.ParseIP([]byte(addr), into[:4]); ip != nil && !local.Contains(ip) {
  78. // emit one internet node for incoming, one for outgoing
  79. if len(n.Adjacency) > 0 {
  80. return IncomingInternetID, true
  81. }
  82. return OutgoingInternetID, true
  83. }
  84. // The node is not external
  85. return "", false
  86. }