mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-02 17:50:39 +00:00
Treat addresses on the docker bridge as local.
This commit is contained in:
@@ -34,6 +34,7 @@ func main() {
|
||||
spyProcs = flag.Bool("processes", true, "report processes (needs root)")
|
||||
dockerEnabled = flag.Bool("docker", true, "collect Docker-related attributes for processes")
|
||||
dockerInterval = flag.Duration("docker.interval", 10*time.Second, "how often to update Docker attributes")
|
||||
dockerBridge = flag.String("docker.bridge", "docker0", "the docker bridge name")
|
||||
weaveRouterAddr = flag.String("weave.router.addr", "", "IP address or FQDN of the Weave router")
|
||||
procRoot = flag.String("proc.root", "/proc", "location of the proc filesystem")
|
||||
)
|
||||
@@ -81,6 +82,10 @@ func main() {
|
||||
reporters := []tag.Reporter{}
|
||||
|
||||
if *dockerEnabled && runtime.GOOS == linux {
|
||||
if err = report.AddLocalBridge(*dockerBridge); err != nil {
|
||||
log.Fatalf("failed to get docker bridge address: %v", err)
|
||||
}
|
||||
|
||||
dockerRegistry, err := docker.NewRegistry(*dockerInterval)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to start docker registry: %v", err)
|
||||
|
||||
@@ -34,7 +34,7 @@ type LeafMapFunc func(report.NodeMetadata) (RenderableNode, bool)
|
||||
// The srcNode renderable node is essentially from MapFunc, representing one of
|
||||
// the rendered nodes this pseudo node refers to. srcNodeID and dstNodeID are
|
||||
// node IDs prior to mapping.
|
||||
type PseudoFunc func(srcNodeID string, srcNode RenderableNode, dstNodeID string, local Networks) (RenderableNode, bool)
|
||||
type PseudoFunc func(srcNodeID string, srcNode RenderableNode, dstNodeID string, local report.Networks) (RenderableNode, bool)
|
||||
|
||||
// MapFunc is anything which can take an arbitrary RenderableNode and
|
||||
// return another RenderableNode.
|
||||
@@ -257,7 +257,7 @@ func MapAddress2Host(n RenderableNode) (RenderableNode, bool) {
|
||||
// the report's local networks. Otherwise, the returned function will
|
||||
// produce a single pseudo node per (dst address, src address, src port).
|
||||
func GenericPseudoNode(addresser func(id string) net.IP) PseudoFunc {
|
||||
return func(src string, srcMapped RenderableNode, dst string, local Networks) (RenderableNode, bool) {
|
||||
return func(src string, srcMapped RenderableNode, dst string, local report.Networks) (RenderableNode, bool) {
|
||||
// Use the addresser to extract the destination IP
|
||||
dstNodeAddr := addresser(dst)
|
||||
|
||||
@@ -278,7 +278,7 @@ func GenericPseudoNode(addresser func(id string) net.IP) PseudoFunc {
|
||||
}
|
||||
|
||||
// PanicPseudoNode just panics; it is for Topologies without edges
|
||||
func PanicPseudoNode(src string, srcMapped RenderableNode, dst string, local Networks) (RenderableNode, bool) {
|
||||
func PanicPseudoNode(src string, srcMapped RenderableNode, dst string, local report.Networks) (RenderableNode, bool) {
|
||||
panic(dst)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,16 +7,13 @@ import (
|
||||
"github.com/weaveworks/scope/report"
|
||||
)
|
||||
|
||||
// Networks represent a set of subnets local to a report.
|
||||
type Networks []*net.IPNet
|
||||
|
||||
// LocalNetworks returns a superset of the networks (think: CIDRs) that are
|
||||
// "local" from the perspective of each host represented in the report. It's
|
||||
// used to determine which nodes in the report are "remote", i.e. outside of
|
||||
// our infrastructure.
|
||||
func LocalNetworks(r report.Report) Networks {
|
||||
func LocalNetworks(r report.Report) report.Networks {
|
||||
var (
|
||||
result = Networks{}
|
||||
result = report.Networks{}
|
||||
networks = map[string]struct{}{}
|
||||
)
|
||||
|
||||
@@ -39,13 +36,3 @@ func LocalNetworks(r report.Report) Networks {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Contains returns true if IP is in Networks.
|
||||
func (n Networks) Contains(ip net.IP) bool {
|
||||
for _, net := range n {
|
||||
if net.Contains(ip) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ func TestReportLocalNetworks(t *testing.T) {
|
||||
"nonets": {},
|
||||
"foo": {"local_networks": "10.0.0.1/8 192.168.1.1/24 10.0.0.1/8 badnet/33"},
|
||||
}}})
|
||||
want := render.Networks([]*net.IPNet{
|
||||
want := report.Networks([]*net.IPNet{
|
||||
mustParseCIDR("10.0.0.1/8"),
|
||||
mustParseCIDR("192.168.1.1/24"),
|
||||
})
|
||||
@@ -26,21 +26,6 @@ func TestReportLocalNetworks(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestContains(t *testing.T) {
|
||||
networks := render.Networks([]*net.IPNet{
|
||||
mustParseCIDR("10.0.0.1/8"),
|
||||
mustParseCIDR("192.168.1.1/24"),
|
||||
})
|
||||
|
||||
if networks.Contains(net.ParseIP("52.52.52.52")) {
|
||||
t.Errorf("52.52.52.52 not in %v", networks)
|
||||
}
|
||||
|
||||
if !networks.Contains(net.ParseIP("10.0.0.1")) {
|
||||
t.Errorf("10.0.0.1 in %v", networks)
|
||||
}
|
||||
}
|
||||
|
||||
func mustParseCIDR(s string) *net.IPNet {
|
||||
_, ipNet, err := net.ParseCIDR(s)
|
||||
if err != nil {
|
||||
|
||||
15
report/id.go
15
report/id.go
@@ -55,11 +55,18 @@ func MakeEndpointNodeID(hostID, address, port string) string {
|
||||
|
||||
// MakeAddressNodeID produces an address node ID from its composite parts.
|
||||
func MakeAddressNodeID(hostID, address string) string {
|
||||
if !isLoopback(address) {
|
||||
// Only loopback addresses get scoped by hostID.
|
||||
hostID = ""
|
||||
var scope string
|
||||
|
||||
// Loopback addresses and addresses explicity marked as
|
||||
// local get scoped by hostID
|
||||
addressIP := net.ParseIP(address)
|
||||
if addressIP != nil && LocalNetworks.Contains(addressIP) {
|
||||
scope = hostID
|
||||
} else if isLoopback(address) {
|
||||
scope = hostID
|
||||
}
|
||||
return hostID + ScopeDelim + address
|
||||
|
||||
return scope + ScopeDelim + address
|
||||
}
|
||||
|
||||
// MakeProcessNodeID produces a process node ID from its composite parts.
|
||||
|
||||
60
report/networks.go
Normal file
60
report/networks.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package report
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
// Networks represent a set of subnets
|
||||
type Networks []*net.IPNet
|
||||
|
||||
// Interface is exported for testing.
|
||||
type Interface interface {
|
||||
Addrs() ([]net.Addr, error)
|
||||
}
|
||||
|
||||
// Variables exposed for testing
|
||||
var (
|
||||
LocalNetworks = Networks{}
|
||||
InterfaceByNameStub = func(name string) (Interface, error) {
|
||||
return net.InterfaceByName(name)
|
||||
}
|
||||
)
|
||||
|
||||
// Contains returns true if IP is in Networks.
|
||||
func (n Networks) Contains(ip net.IP) bool {
|
||||
for _, net := range n {
|
||||
if net.Contains(ip) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// AddLocalBridge records the subnet address associated with the bridge name
|
||||
// supplied, such that MakeAddressNodeID will scope addresses in this subnet
|
||||
// as local.
|
||||
func AddLocalBridge(name string) error {
|
||||
inf, err := InterfaceByNameStub(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addrs, err := inf.Addrs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
_, network, err := net.ParseCIDR(addr.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if network == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
LocalNetworks = append(LocalNetworks, network)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
72
report/networks_test.go
Normal file
72
report/networks_test.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package report_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/weaveworks/scope/report"
|
||||
"github.com/weaveworks/scope/test"
|
||||
)
|
||||
|
||||
func TestContains(t *testing.T) {
|
||||
networks := report.Networks([]*net.IPNet{
|
||||
mustParseCIDR("10.0.0.1/8"),
|
||||
mustParseCIDR("192.168.1.1/24"),
|
||||
})
|
||||
|
||||
if networks.Contains(net.ParseIP("52.52.52.52")) {
|
||||
t.Errorf("52.52.52.52 not in %v", networks)
|
||||
}
|
||||
|
||||
if !networks.Contains(net.ParseIP("10.0.0.1")) {
|
||||
t.Errorf("10.0.0.1 in %v", networks)
|
||||
}
|
||||
}
|
||||
|
||||
func mustParseCIDR(s string) *net.IPNet {
|
||||
_, ipNet, err := net.ParseCIDR(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ipNet
|
||||
}
|
||||
|
||||
type mockInterface struct {
|
||||
addrs []net.Addr
|
||||
}
|
||||
|
||||
type mockAddr string
|
||||
|
||||
func (m mockInterface) Addrs() ([]net.Addr, error) {
|
||||
return m.addrs, nil
|
||||
}
|
||||
|
||||
func (m mockAddr) Network() string {
|
||||
return "ip+net"
|
||||
}
|
||||
|
||||
func (m mockAddr) String() string {
|
||||
return string(m)
|
||||
}
|
||||
|
||||
func TestAddLocal(t *testing.T) {
|
||||
oldInterfaceByNameStub := report.InterfaceByNameStub
|
||||
defer func() { report.InterfaceByNameStub = oldInterfaceByNameStub }()
|
||||
|
||||
report.InterfaceByNameStub = func(name string) (report.Interface, error) {
|
||||
return mockInterface{[]net.Addr{mockAddr("52.53.54.55/16")}}, nil
|
||||
}
|
||||
|
||||
err := report.AddLocalBridge("foo")
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
want := report.Networks([]*net.IPNet{mustParseCIDR("52.53.54.55/16")})
|
||||
have := report.LocalNetworks
|
||||
|
||||
if !reflect.DeepEqual(want, have) {
|
||||
t.Errorf("%s", test.Diff(want, have))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user