diff --git a/render/detailed_node.go b/render/detailed_node.go index 6b785e823..e03506f9d 100644 --- a/render/detailed_node.go +++ b/render/detailed_node.go @@ -6,7 +6,6 @@ import ( "strconv" "github.com/weaveworks/scope/probe/docker" - "github.com/weaveworks/scope/probe/endpoint" "github.com/weaveworks/scope/probe/host" "github.com/weaveworks/scope/probe/process" "github.com/weaveworks/scope/report" @@ -112,8 +111,10 @@ func MakeDetailedNode(r report.Report, n RenderableNode) DetailedNode { for _, id := range n.Origins { if table, ok := OriginTable(r, id); ok { tables = append(tables, table) - } else if nmd, ok := r.Endpoint.NodeMetadatas[id]; ok { - connections = append(connections, connectionDetailsRows(r.Endpoint, id, nmd)...) + } else if _, ok := r.Endpoint.NodeMetadatas[id]; ok { + connections = append(connections, connectionDetailsRows(r.Endpoint, id)...) + } else if _, ok := r.Address.NodeMetadatas[id]; ok { + connections = append(connections, connectionDetailsRows(r.Address, id)...) } } if len(connections) > 0 { @@ -135,9 +136,6 @@ func MakeDetailedNode(r report.Report, n RenderableNode) DetailedNode { // OriginTable produces a table (to be consumed directly by the UI) based on // an origin ID, which is (optimistically) a node ID in one of our topologies. func OriginTable(r report.Report, originID string) (Table, bool) { - if nmd, ok := r.Address.NodeMetadatas[originID]; ok { - return addressOriginTable(nmd) - } if nmd, ok := r.Process.NodeMetadatas[originID]; ok { return processOriginTable(nmd) } @@ -153,16 +151,28 @@ func OriginTable(r report.Report, originID string) (Table, bool) { return Table{}, false } -func connectionDetailsRows(endpointTopology report.Topology, originID string, nmd report.NodeMetadata) []Row { +func connectionDetailsRows(topology report.Topology, originID string) []Row { rows := []Row{} - local := fmt.Sprintf("%s:%s", nmd.Metadata[endpoint.Addr], nmd.Metadata[endpoint.Port]) - adjacencies := endpointTopology.Adjacency[report.MakeAdjacencyID(originID)] + labeler := func(nodeID string) (string, bool) { + if _, addr, port, ok := report.ParseEndpointNodeID(nodeID); ok { + return fmt.Sprintf("%s:%s", addr, port), true + } + if _, addr, ok := report.ParseAddressNodeID(nodeID); ok { + return addr, true + } + return "", false + } + local, ok := labeler(originID) + if !ok { + return rows + } + adjacencies := topology.Adjacency[report.MakeAdjacencyID(originID)] sort.Strings(adjacencies) - for _, adj := range adjacencies { - if _, address, port, ok := report.ParseEndpointNodeID(adj); ok { + for _, nodeID := range adjacencies { + if remote, ok := labeler(nodeID); ok { rows = append(rows, Row{ Key: local, - ValueMajor: fmt.Sprintf("%s:%s", address, port), + ValueMajor: remote, }) } } @@ -178,19 +188,6 @@ func connectionDetailsTable(connectionRows []Row) Table { } } -func addressOriginTable(nmd report.NodeMetadata) (Table, bool) { - rows := []Row{} - if val, ok := nmd.Metadata[endpoint.Addr]; ok { - rows = append(rows, Row{"Address", val, ""}) - } - return Table{ - Title: "Origin Address", - Numeric: false, - Rows: rows, - Rank: addressRank, - }, len(rows) > 0 -} - func processOriginTable(nmd report.NodeMetadata) (Table, bool) { rows := []Row{} for _, tuple := range []struct{ key, human string }{ diff --git a/render/detailed_node_test.go b/render/detailed_node_test.go index a359a4fa8..9219fee48 100644 --- a/render/detailed_node_test.go +++ b/render/detailed_node_test.go @@ -14,13 +14,6 @@ func TestOriginTable(t *testing.T) { t.Errorf("unknown origin ID gave unexpected success") } for originID, want := range map[string]render.Table{ - test.ClientAddressNodeID: { - Title: "Origin Address", - Numeric: false, - Rows: []render.Row{ - {"Address", test.ClientIP, ""}, - }, - }, test.ServerProcessNodeID: { Title: "Origin Process", Numeric: false, @@ -52,7 +45,74 @@ func TestOriginTable(t *testing.T) { } } -func TestMakeDetailedNode(t *testing.T) { +func TestMakeDetailedHostNode(t *testing.T) { + renderableNode := render.HostRenderer.Render(test.Report)[render.MakeHostID(test.ClientHostID)] + have := render.MakeDetailedNode(test.Report, renderableNode) + want := render.DetailedNode{ + ID: render.MakeHostID(test.ClientHostID), + LabelMajor: "client", + LabelMinor: "hostname.com", + Pseudo: false, + Tables: []render.Table{ + { + Title: "Connections", + Numeric: true, + Rank: 100, + Rows: []render.Row{ + { + Key: "TCP connections", + ValueMajor: "3", + ValueMinor: "", + }, + }, + }, + { + Title: "Origin Host", + Numeric: false, + Rank: 1, + Rows: []render.Row{ + { + Key: "Host name", + ValueMajor: "client.hostname.com", + ValueMinor: "", + }, + { + Key: "Load", + ValueMajor: "0.01 0.01 0.01", + ValueMinor: "", + }, + { + Key: "Operating system", + ValueMajor: "Linux", + ValueMinor: "", + }, + }, + }, + { + Title: "Connection Details", + Numeric: false, + Rank: 0, + Rows: []render.Row{ + { + Key: "Local", + ValueMajor: "Remote", + ValueMinor: "", + }, + { + Key: "10.10.10.20", + ValueMajor: "192.168.1.1", + ValueMinor: "", + }, + }, + }, + }, + } + if !reflect.DeepEqual(want, have) { + t.Errorf("%s", test.Diff(want, have)) + } +} + +func TestMakeDetailedContainerNode(t *testing.T) { renderableNode := render.ContainerRenderer.Render(test.Report)[test.ServerContainerID] have := render.MakeDetailedNode(test.Report, renderableNode) want := render.DetailedNode{ diff --git a/report/id.go b/report/id.go index cb9bdb89c..a2a88de95 100644 --- a/report/id.go +++ b/report/id.go @@ -114,6 +114,15 @@ func ParseEndpointNodeID(endpointNodeID string) (hostID, address, port string, o return fields[0], fields[1], fields[2], true } +// ParseAddressNodeID produces the host ID, address from an address node ID. +func ParseAddressNodeID(addressNodeID string) (hostID, address string, ok bool) { + fields := strings.SplitN(addressNodeID, ScopeDelim, 2) + if len(fields) != 2 { + return "", "", false + } + return fields[0], fields[1], true +} + // ExtractHostID extracts the host id from NodeMetadata func ExtractHostID(m NodeMetadata) string { hostid, _, _ := ParseNodeID(m.Metadata[HostNodeID])