mirror of
https://github.com/weaveworks/scope.git
synced 2026-07-28 01:31:17 +00:00
Include host scope for contianer joins based on IP.
This commit is contained in:
@@ -22,12 +22,13 @@ import (
|
||||
|
||||
// These constants are keys used in node metadata
|
||||
const (
|
||||
ContainerName = "docker_container_name"
|
||||
ContainerCommand = "docker_container_command"
|
||||
ContainerPorts = "docker_container_ports"
|
||||
ContainerCreated = "docker_container_created"
|
||||
ContainerIPs = "docker_container_ips"
|
||||
ContainerHostname = "docker_container_hostname"
|
||||
ContainerName = "docker_container_name"
|
||||
ContainerCommand = "docker_container_command"
|
||||
ContainerPorts = "docker_container_ports"
|
||||
ContainerCreated = "docker_container_created"
|
||||
ContainerIPs = "docker_container_ips"
|
||||
ContainerHostname = "docker_container_hostname"
|
||||
ContainerIPsWithScopes = "docker_container_ips_with_scopes"
|
||||
|
||||
NetworkRxDropped = "network_rx_dropped"
|
||||
NetworkRxBytes = "network_rx_bytes"
|
||||
@@ -72,7 +73,7 @@ type Container interface {
|
||||
Image() string
|
||||
PID() int
|
||||
Hostname() string
|
||||
GetNode([]net.IP) report.Node
|
||||
GetNode(string, []net.IP) report.Node
|
||||
|
||||
StartGatheringStats() error
|
||||
StopGatheringStats()
|
||||
@@ -219,20 +220,28 @@ func (c *container) ports(localAddrs []net.IP) string {
|
||||
return strings.Join(ports, ", ")
|
||||
}
|
||||
|
||||
func (c *container) GetNode(localAddrs []net.IP) report.Node {
|
||||
func (c *container) GetNode(hostID string, localAddrs []net.IP) report.Node {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
|
||||
ips := append(c.container.NetworkSettings.SecondaryIPAddresses,
|
||||
c.container.NetworkSettings.IPAddress)
|
||||
// Treat all Docker IPs as local scoped.
|
||||
ipsWithScopes := []string{}
|
||||
for _, ip := range ips {
|
||||
ipsWithScopes = append(ipsWithScopes, fmt.Sprintf("%s:%s", hostID, ip))
|
||||
}
|
||||
|
||||
result := report.MakeNodeWith(map[string]string{
|
||||
ContainerID: c.ID(),
|
||||
ContainerName: strings.TrimPrefix(c.container.Name, "/"),
|
||||
ContainerPorts: c.ports(localAddrs),
|
||||
ContainerCreated: c.container.Created.Format(time.RFC822),
|
||||
ContainerCommand: c.container.Path + " " + strings.Join(c.container.Args, " "),
|
||||
ImageID: c.container.Image,
|
||||
ContainerIPs: strings.Join(append(c.container.NetworkSettings.SecondaryIPAddresses,
|
||||
c.container.NetworkSettings.IPAddress), " "),
|
||||
ContainerHostname: c.Hostname(),
|
||||
ContainerID: c.ID(),
|
||||
ContainerName: strings.TrimPrefix(c.container.Name, "/"),
|
||||
ContainerPorts: c.ports(localAddrs),
|
||||
ContainerCreated: c.container.Created.Format(time.RFC822),
|
||||
ContainerCommand: c.container.Path + " " + strings.Join(c.container.Args, " "),
|
||||
ImageID: c.container.Image,
|
||||
ContainerIPs: strings.Join(ips, " "),
|
||||
ContainerIPsWithScopes: strings.Join(ipsWithScopes, " "),
|
||||
ContainerHostname: c.Hostname(),
|
||||
})
|
||||
AddLabels(result, c.container.Config.Labels)
|
||||
|
||||
@@ -268,3 +277,9 @@ func (c *container) GetNode(localAddrs []net.IP) report.Node {
|
||||
func ExtractContainerIPs(nmd report.Node) []string {
|
||||
return strings.Fields(nmd.Metadata[ContainerIPs])
|
||||
}
|
||||
|
||||
// ExtractContainerIPsWithScopes returns the list of container IPs, prepended
|
||||
// with scopes, given a Node from the Container topology.
|
||||
func ExtractContainerIPsWithScopes(nmd report.Node) []string {
|
||||
return strings.Fields(nmd.Metadata[ContainerIPsWithScopes])
|
||||
}
|
||||
|
||||
@@ -66,19 +66,20 @@ func TestContainer(t *testing.T) {
|
||||
|
||||
// Now see if we go them
|
||||
want := report.MakeNode().WithMetadata(map[string]string{
|
||||
"docker_container_command": " ",
|
||||
"docker_container_created": "01 Jan 01 00:00 UTC",
|
||||
"docker_container_id": "ping",
|
||||
"docker_container_ips": "1.2.3.4",
|
||||
"docker_container_name": "pong",
|
||||
"docker_container_ports": "1.2.3.4:80->80/tcp, 81/tcp",
|
||||
"docker_image_id": "baz",
|
||||
"docker_label_foo1": "bar1",
|
||||
"docker_label_foo2": "bar2",
|
||||
"memory_usage": "12345",
|
||||
"docker_container_command": " ",
|
||||
"docker_container_created": "01 Jan 01 00:00 UTC",
|
||||
"docker_container_id": "ping",
|
||||
"docker_container_ips": "1.2.3.4",
|
||||
"docker_container_ips_with_scopes": "scope:1.2.3.4",
|
||||
"docker_container_name": "pong",
|
||||
"docker_container_ports": "1.2.3.4:80->80/tcp, 81/tcp",
|
||||
"docker_image_id": "baz",
|
||||
"docker_label_foo1": "bar1",
|
||||
"docker_label_foo2": "bar2",
|
||||
"memory_usage": "12345",
|
||||
})
|
||||
test.Poll(t, 100*time.Millisecond, want, func() interface{} {
|
||||
node := c.GetNode([]net.IP{})
|
||||
node := c.GetNode("scope", []net.IP{})
|
||||
for k, v := range node.Metadata {
|
||||
if v == "0" || v == "" {
|
||||
delete(node.Metadata, k)
|
||||
@@ -93,7 +94,7 @@ func TestContainer(t *testing.T) {
|
||||
if c.PID() != 1 {
|
||||
t.Errorf("%s != 1", c.PID())
|
||||
}
|
||||
if !reflect.DeepEqual(docker.ExtractContainerIPs(c.GetNode([]net.IP{})), []string{"1.2.3.4"}) {
|
||||
t.Errorf("%v != %v", docker.ExtractContainerIPs(c.GetNode([]net.IP{})), []string{"1.2.3.4"})
|
||||
if have := docker.ExtractContainerIPs(c.GetNode("", []net.IP{})); !reflect.DeepEqual(have, []string{"1.2.3.4"}) {
|
||||
t.Errorf("%v != %v", have, []string{"1.2.3.4"})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ func (c *mockContainer) StartGatheringStats() error {
|
||||
|
||||
func (c *mockContainer) StopGatheringStats() {}
|
||||
|
||||
func (c *mockContainer) GetNode(_ []net.IP) report.Node {
|
||||
func (c *mockContainer) GetNode(_ string, _ []net.IP) report.Node {
|
||||
return report.MakeNodeWith(map[string]string{
|
||||
docker.ContainerID: c.c.ID,
|
||||
docker.ContainerName: c.c.Name,
|
||||
|
||||
@@ -46,7 +46,7 @@ func (r *Reporter) containerTopology(localAddrs []net.IP) report.Topology {
|
||||
|
||||
r.registry.WalkContainers(func(c Container) {
|
||||
nodeID := report.MakeContainerNodeID(r.hostID, c.ID())
|
||||
result.AddNode(nodeID, c.GetNode(localAddrs))
|
||||
result.AddNode(nodeID, c.GetNode(r.hostID, localAddrs))
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
@@ -178,6 +178,13 @@ func (w *Weave) Tag(r report.Report) (report.Report, error) {
|
||||
existingIPs := report.MakeIDList(docker.ExtractContainerIPs(node)...)
|
||||
existingIPs = existingIPs.Add(e.ips...)
|
||||
node.Metadata[docker.ContainerIPs] = strings.Join(existingIPs, " ")
|
||||
|
||||
existingIPsWithScopes := report.MakeIDList(docker.ExtractContainerIPsWithScopes(node)...)
|
||||
for _, ip := range e.ips {
|
||||
existingIPsWithScopes = existingIPsWithScopes.Add(fmt.Sprintf(":%s", ip))
|
||||
}
|
||||
node.Metadata[docker.ContainerIPsWithScopes] = strings.Join(existingIPsWithScopes, " ")
|
||||
|
||||
node.Metadata[WeaveMACAddress] = e.macAddress
|
||||
}
|
||||
return r, nil
|
||||
|
||||
@@ -51,10 +51,11 @@ func TestWeaveTaggerOverlayTopology(t *testing.T) {
|
||||
Container: report.Topology{
|
||||
Nodes: report.Nodes{
|
||||
nodeID: report.MakeNodeWith(map[string]string{
|
||||
docker.ContainerID: mockContainerID,
|
||||
overlay.WeaveDNSHostname: mockHostname,
|
||||
overlay.WeaveMACAddress: mockContainerMAC,
|
||||
docker.ContainerIPs: mockContainerIP,
|
||||
docker.ContainerID: mockContainerID,
|
||||
overlay.WeaveDNSHostname: mockHostname,
|
||||
overlay.WeaveMACAddress: mockContainerMAC,
|
||||
docker.ContainerIPs: mockContainerIP,
|
||||
docker.ContainerIPsWithScopes: mockContainerIPWithScope,
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -78,13 +79,14 @@ func TestWeaveTaggerOverlayTopology(t *testing.T) {
|
||||
}
|
||||
|
||||
const (
|
||||
mockHostID = "host1"
|
||||
mockWeavePeerName = "winnebago"
|
||||
mockWeavePeerNickName = "winny"
|
||||
mockContainerID = "83183a667c01"
|
||||
mockContainerMAC = "d6:f2:5a:12:36:a8"
|
||||
mockContainerIP = "10.0.0.123"
|
||||
mockHostname = "hostname.weave.local"
|
||||
mockHostID = "host1"
|
||||
mockWeavePeerName = "winnebago"
|
||||
mockWeavePeerNickName = "winny"
|
||||
mockContainerID = "83183a667c01"
|
||||
mockContainerMAC = "d6:f2:5a:12:36:a8"
|
||||
mockContainerIP = "10.0.0.123"
|
||||
mockContainerIPWithScope = ":10.0.0.123"
|
||||
mockHostname = "hostname.weave.local"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -283,23 +283,22 @@ func MapEndpoint2IP(m RenderableNode, local report.Networks) RenderableNodes {
|
||||
if ok {
|
||||
return RenderableNodes{}
|
||||
}
|
||||
addr, ok := m.Metadata[endpoint.Addr]
|
||||
scope, addr, port, ok := report.ParseEndpointNodeID(m.ID)
|
||||
if !ok {
|
||||
return RenderableNodes{}
|
||||
}
|
||||
if !local.Contains(net.ParseIP(addr)) {
|
||||
if ip := net.ParseIP(addr); ip != nil && !local.Contains(ip) {
|
||||
return RenderableNodes{TheInternetID: newDerivedPseudoNode(TheInternetID, TheInternetMajor, m)}
|
||||
}
|
||||
|
||||
result := RenderableNodes{addr: NewRenderableNodeWith(addr, "", "", "", m)}
|
||||
// Emit addr:port nodes as well, so connections from the internet to containers
|
||||
// via port mapping also works.
|
||||
port, ok := m.Metadata[endpoint.Port]
|
||||
if ok {
|
||||
id := fmt.Sprintf("%s:%s", addr, port)
|
||||
result[id] = NewRenderableNodeWith(id, "", "", "", m)
|
||||
// Emit 2 nodes: scope:addr and scope:addr:port, so connections from the
|
||||
// internet to containers via port mapping also works.
|
||||
id := fmt.Sprintf("%s:%s", scope, addr)
|
||||
idWithPort := fmt.Sprintf("%s:%s:%s", scope, addr, port)
|
||||
return RenderableNodes{
|
||||
id: NewRenderableNodeWith(id, "", "", "", m),
|
||||
idWithPort: NewRenderableNodeWith(idWithPort, "", "", "", m),
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var portMappingMatch = regexp.MustCompile(`([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}):([0-9]+)->([0-9]+)/tcp`)
|
||||
@@ -309,20 +308,20 @@ var portMappingMatch = regexp.MustCompile(`([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.
|
||||
// the endpoint topology.
|
||||
func MapContainer2IP(m RenderableNode, _ report.Networks) RenderableNodes {
|
||||
result := RenderableNodes{}
|
||||
addrs, ok := m.Metadata[docker.ContainerIPs]
|
||||
if !ok {
|
||||
return result
|
||||
}
|
||||
for _, addr := range strings.Fields(addrs) {
|
||||
node := NewRenderableNodeWith(addr, "", "", "", m)
|
||||
node.Counters[containersKey] = 1
|
||||
result[addr] = node
|
||||
if addrs, ok := m.Metadata[docker.ContainerIPsWithScopes]; ok {
|
||||
for _, addr := range strings.Fields(addrs) {
|
||||
node := NewRenderableNodeWith(addr, "", "", "", m)
|
||||
node.Counters[containersKey] = 1
|
||||
result[addr] = node
|
||||
}
|
||||
}
|
||||
|
||||
// also output all the host:port port mappings
|
||||
// Also output all the host:port port mappings.
|
||||
// In this case, we assume this doesn't need a scope,
|
||||
// as they are for host IPs.
|
||||
for _, mapping := range portMappingMatch.FindAllStringSubmatch(m.Metadata[docker.ContainerPorts], -1) {
|
||||
ip, port := mapping[1], mapping[2]
|
||||
id := fmt.Sprintf("%s:%s", ip, port)
|
||||
id := fmt.Sprintf(":%s:%s", ip, port)
|
||||
node := NewRenderableNodeWith(id, "", "", "", m)
|
||||
node.Counters[containersKey] = 1
|
||||
result[id] = node
|
||||
|
||||
Reference in New Issue
Block a user