mirror of
https://github.com/weaveworks/scope.git
synced 2026-08-18 03:46:45 +00:00
Merge pull request #2719 from weaveworks/update-weave-client-to-2.0
Gather Weave Net plugin and proxy info from report
This commit is contained in:
@@ -34,6 +34,8 @@ type Status struct {
|
||||
Router Router
|
||||
DNS *DNS
|
||||
IPAM *IPAM
|
||||
Proxy *Proxy
|
||||
Plugin *Plugin
|
||||
}
|
||||
|
||||
// Router describes the status of the Weave Router
|
||||
@@ -95,6 +97,16 @@ type IPAM struct {
|
||||
PendingAllocates []string
|
||||
}
|
||||
|
||||
// Proxy describes the status of Weave Proxy
|
||||
type Proxy struct {
|
||||
Addresses []string
|
||||
}
|
||||
|
||||
// Plugin describes the status of the Weave Plugin
|
||||
type Plugin struct {
|
||||
DriverName string
|
||||
}
|
||||
|
||||
var weavePsMatch = regexp.MustCompile(`^([0-9a-f]{12}) ((?:[0-9a-f][0-9a-f]\:){5}(?:[0-9a-f][0-9a-f]))(.*)$`)
|
||||
var ipMatch = regexp.MustCompile(`([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})(/[0-9]+)`)
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ const (
|
||||
mockContainerIP = "10.0.0.123"
|
||||
mockContainerIPWithScope = ";10.0.0.123"
|
||||
mockHostname = "hostname.weave.local"
|
||||
mockProxyAddress = "unix:///foo/bar/weave.sock"
|
||||
mockDriverName = "weave_mock"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -41,8 +43,16 @@ var (
|
||||
"Hostname": "%s.",
|
||||
"Tombstone": 0
|
||||
}]
|
||||
}
|
||||
}`, mockWeavePeerName, mockWeavePeerNickName, mockContainerID, mockHostname)
|
||||
},
|
||||
"Proxy": {
|
||||
"Addresses": [
|
||||
"%s"
|
||||
]
|
||||
},
|
||||
"Plugin": {
|
||||
"DriverName": "%s"
|
||||
}
|
||||
}`, mockWeavePeerName, mockWeavePeerNickName, mockContainerID, mockHostname, mockProxyAddress, mockDriverName)
|
||||
mockIP = net.ParseIP("1.2.3.4")
|
||||
)
|
||||
|
||||
@@ -84,6 +94,12 @@ func TestStatus(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Proxy: &weave.Proxy{
|
||||
Addresses: []string{mockProxyAddress},
|
||||
},
|
||||
Plugin: &weave.Plugin{
|
||||
DriverName: mockDriverName,
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(status, want) {
|
||||
t.Fatal(test.Diff(status, want))
|
||||
|
||||
+17
-124
@@ -1,7 +1,6 @@
|
||||
package overlay
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -13,8 +12,6 @@ import (
|
||||
"github.com/weaveworks/scope/probe/docker"
|
||||
"github.com/weaveworks/scope/probe/host"
|
||||
"github.com/weaveworks/scope/report"
|
||||
|
||||
docker_client "github.com/fsouza/go-dockerclient"
|
||||
)
|
||||
|
||||
// Keys for use in Node
|
||||
@@ -54,9 +51,6 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
// NewDockerClientStub is used for testing
|
||||
NewDockerClientStub = newDockerClient
|
||||
|
||||
containerNotRunningRE = regexp.MustCompile(`Container .* is not running\n`)
|
||||
|
||||
containerMetadata = report.MetadataTemplates{
|
||||
@@ -145,52 +139,30 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// DockerClient is used for testing
|
||||
type DockerClient interface {
|
||||
CreateExec(docker_client.CreateExecOptions) (*docker_client.Exec, error)
|
||||
StartExec(string, docker_client.StartExecOptions) error
|
||||
InspectContainer(id string) (*docker_client.Container, error)
|
||||
}
|
||||
|
||||
func newDockerClient() (DockerClient, error) {
|
||||
return docker_client.NewClientFromEnv()
|
||||
}
|
||||
|
||||
// Weave represents a single Weave router, presumably on the same host
|
||||
// as the probe. It is both a Reporter and a Tagger: it produces an Overlay
|
||||
// topology, and (in theory) can tag existing topologies with foreign keys to
|
||||
// overlay -- though I'm not sure what that would look like in practice right
|
||||
// now.
|
||||
type Weave struct {
|
||||
client weave.Client
|
||||
dockerClient DockerClient
|
||||
hostID string
|
||||
client weave.Client
|
||||
hostID string
|
||||
|
||||
mtx sync.RWMutex
|
||||
statusCache weave.Status
|
||||
psCache map[string]weave.PSEntry
|
||||
proxyRunningCache bool
|
||||
proxyAddressCache string
|
||||
pluginRunningCache bool
|
||||
mtx sync.RWMutex
|
||||
statusCache weave.Status
|
||||
psCache map[string]weave.PSEntry
|
||||
|
||||
backoff backoff.Interface
|
||||
psBackoff backoff.Interface
|
||||
proxyBackoff backoff.Interface
|
||||
pluginBackoff backoff.Interface
|
||||
backoff backoff.Interface
|
||||
psBackoff backoff.Interface
|
||||
}
|
||||
|
||||
// NewWeave returns a new Weave tagger based on the Weave router at
|
||||
// address. The address should be an IP or FQDN, no port.
|
||||
func NewWeave(hostID string, client weave.Client) (*Weave, error) {
|
||||
dockerClient, err := NewDockerClientStub()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w := &Weave{
|
||||
client: client,
|
||||
dockerClient: dockerClient,
|
||||
hostID: hostID,
|
||||
psCache: map[string]weave.PSEntry{},
|
||||
client: client,
|
||||
hostID: hostID,
|
||||
psCache: map[string]weave.PSEntry{},
|
||||
}
|
||||
|
||||
w.backoff = backoff.New(w.status, "collecting weave status")
|
||||
@@ -201,14 +173,6 @@ func NewWeave(hostID string, client weave.Client) (*Weave, error) {
|
||||
w.psBackoff.SetInitialBackoff(10 * time.Second)
|
||||
go w.psBackoff.Start()
|
||||
|
||||
w.proxyBackoff = backoff.New(w.proxyStatus, "collecting weave proxy status")
|
||||
w.proxyBackoff.SetInitialBackoff(10 * time.Second)
|
||||
go w.proxyBackoff.Start()
|
||||
|
||||
w.pluginBackoff = backoff.New(w.pluginStatus, "collecting weave plugin status")
|
||||
w.pluginBackoff.SetInitialBackoff(10 * time.Second)
|
||||
go w.pluginBackoff.Start()
|
||||
|
||||
return w, nil
|
||||
}
|
||||
|
||||
@@ -219,8 +183,6 @@ func (*Weave) Name() string { return "Weave" }
|
||||
func (w *Weave) Stop() {
|
||||
w.backoff.Stop()
|
||||
w.psBackoff.Stop()
|
||||
w.proxyBackoff.Stop()
|
||||
w.pluginBackoff.Stop()
|
||||
}
|
||||
|
||||
func (w *Weave) ps() (bool, error) {
|
||||
@@ -251,78 +213,6 @@ func (w *Weave) status() (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
func filterContainerNotFound(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch err.(type) {
|
||||
case *docker_client.Error:
|
||||
// This is really ugly, but this error comes from the client in some cases
|
||||
// and there is no other way to distinguish it :(
|
||||
dockerError := err.(*docker_client.Error)
|
||||
if containerNotRunningRE.MatchString(dockerError.Message) {
|
||||
return nil
|
||||
}
|
||||
case *docker_client.ContainerNotRunning:
|
||||
return nil
|
||||
case *docker_client.NoSuchContainer:
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (w *Weave) proxyStatus() (bool, error) {
|
||||
update := func(running bool, address string) {
|
||||
w.mtx.Lock()
|
||||
defer w.mtx.Unlock()
|
||||
w.proxyRunningCache = running
|
||||
w.proxyAddressCache = address
|
||||
}
|
||||
|
||||
exec, err := w.dockerClient.CreateExec(docker_client.CreateExecOptions{
|
||||
AttachStdout: true,
|
||||
Cmd: []string{"curl", "-s", "--unix-socket", "status.sock", "http:/status"},
|
||||
Container: "weaveproxy",
|
||||
})
|
||||
if err != nil {
|
||||
update(false, "")
|
||||
return false, filterContainerNotFound(err)
|
||||
}
|
||||
out := bytes.NewBuffer(nil)
|
||||
err = w.dockerClient.StartExec(exec.ID, docker_client.StartExecOptions{
|
||||
OutputStream: out,
|
||||
})
|
||||
if err != nil {
|
||||
update(true, "")
|
||||
return false, filterContainerNotFound(err)
|
||||
}
|
||||
|
||||
update(true, out.String())
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (w *Weave) pluginStatus() (bool, error) {
|
||||
update := func(running bool) {
|
||||
w.mtx.Lock()
|
||||
defer w.mtx.Unlock()
|
||||
|
||||
w.pluginRunningCache = running
|
||||
}
|
||||
|
||||
c, err := w.dockerClient.InspectContainer("weaveplugin")
|
||||
if err != nil {
|
||||
update(false)
|
||||
return false, filterContainerNotFound(err)
|
||||
}
|
||||
|
||||
update(c.State.Running)
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Tag implements Tagger.
|
||||
func (w *Weave) Tag(r report.Report) (report.Report, error) {
|
||||
w.mtx.RLock()
|
||||
@@ -462,14 +352,17 @@ func (w *Weave) addCurrentPeerInfo(latests map[string]string, node report.Node)
|
||||
latests[WeaveDNSEntryCount] = fmt.Sprintf("%d", dnsEntryCount)
|
||||
}
|
||||
latests[WeaveProxyStatus] = "not running"
|
||||
if w.proxyRunningCache {
|
||||
if w.statusCache.Proxy != nil {
|
||||
latests[WeaveProxyStatus] = "running"
|
||||
latests[WeaveProxyAddress] = w.proxyAddressCache
|
||||
latests[WeaveProxyAddress] = ""
|
||||
if len(w.statusCache.Proxy.Addresses) > 0 {
|
||||
latests[WeaveProxyAddress] = w.statusCache.Proxy.Addresses[0]
|
||||
}
|
||||
}
|
||||
latests[WeavePluginStatus] = "not running"
|
||||
if w.pluginRunningCache {
|
||||
if w.statusCache.Plugin != nil {
|
||||
latests[WeavePluginStatus] = "running"
|
||||
latests[WeavePluginDriver] = "weave"
|
||||
latests[WeavePluginDriver] = w.statusCache.Plugin.DriverName
|
||||
}
|
||||
node = node.AddPrefixMulticolumnTable(WeaveConnectionsMulticolumnTablePrefix, getConnectionsTable(w.statusCache.Router))
|
||||
node = node.WithParents(report.MakeSets().Add(report.Host, report.MakeStringSet(w.hostID)))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package overlay_test
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -12,8 +11,6 @@ import (
|
||||
"github.com/weaveworks/scope/test"
|
||||
"github.com/weaveworks/scope/test/reflect"
|
||||
"github.com/weaveworks/scope/test/weave"
|
||||
|
||||
docker_client "github.com/fsouza/go-dockerclient"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -21,54 +18,7 @@ const (
|
||||
mockContainerIPWithScope = ";" + weave.MockContainerIP
|
||||
)
|
||||
|
||||
type mockDockerClient struct {
|
||||
sync.RWMutex
|
||||
containers map[string]*docker_client.Container
|
||||
}
|
||||
|
||||
func (m *mockDockerClient) InspectContainer(id string) (*docker_client.Container, error) {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
c, ok := m.containers[id]
|
||||
if !ok {
|
||||
return nil, &docker_client.NoSuchContainer{}
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (m *mockDockerClient) CreateExec(docker_client.CreateExecOptions) (*docker_client.Exec, error) {
|
||||
return &docker_client.Exec{ID: "id"}, nil
|
||||
}
|
||||
|
||||
func (m *mockDockerClient) StartExec(_ string, options docker_client.StartExecOptions) error {
|
||||
options.OutputStream.Write([]byte("exec_output"))
|
||||
return nil
|
||||
}
|
||||
|
||||
var mockWeaveContainers = map[string]*docker_client.Container{
|
||||
"weaveproxy": {
|
||||
ID: "foo",
|
||||
State: docker_client.State{
|
||||
Running: true,
|
||||
},
|
||||
},
|
||||
|
||||
"weaveplugin": {
|
||||
ID: "bar",
|
||||
State: docker_client.State{
|
||||
Running: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func runTest(t *testing.T, f func(*overlay.Weave)) {
|
||||
// Place and restore docker client
|
||||
origNewDockerClientStub := overlay.NewDockerClientStub
|
||||
overlay.NewDockerClientStub = func() (overlay.DockerClient, error) {
|
||||
return &mockDockerClient{containers: mockWeaveContainers}, nil
|
||||
}
|
||||
defer func() { overlay.NewDockerClientStub = origNewDockerClientStub }()
|
||||
|
||||
w, err := overlay.NewWeave(mockHostID, weave.MockClient{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -152,14 +102,16 @@ func TestOverlayTopology(t *testing.T) {
|
||||
if have, ok := node.Latest.Lookup(overlay.WeaveProxyStatus); !ok || have != "running" {
|
||||
t.Errorf("Expected weave proxy status %q, got %q", "running", have)
|
||||
}
|
||||
// The weave proxy address should equal what Exec writes to stdout
|
||||
if have, ok := node.Latest.Lookup(overlay.WeaveProxyAddress); !ok || have != "exec_output" {
|
||||
t.Errorf("Expected weave proxy address %q, got %q", "exec_output", have)
|
||||
if have, ok := node.Latest.Lookup(overlay.WeaveProxyAddress); !ok || have != weave.MockProxyAddress {
|
||||
t.Errorf("Expected weave proxy address %q, got %q", weave.MockProxyAddress, have)
|
||||
}
|
||||
// The weave plugin container is running
|
||||
if have, ok := node.Latest.Lookup(overlay.WeavePluginStatus); !ok || have != "running" {
|
||||
t.Errorf("Expected weave plugin status %q, got %q", "running", have)
|
||||
}
|
||||
if have, ok := node.Latest.Lookup(overlay.WeavePluginDriver); !ok || have != weave.MockDriverName {
|
||||
t.Errorf("Expected weave proxy address %q, got %q", weave.MockDriverName, have)
|
||||
}
|
||||
// The mock data indicates ranges are owned by unreachable peers
|
||||
if have, ok := node.Latest.Lookup(overlay.WeaveIPAMStatus); !ok || have != "all ranges owned by unreachable peers" {
|
||||
t.Errorf("Expected weave IPAM status %q, got %q", "all ranges owned by unreachable peers", have)
|
||||
|
||||
@@ -15,6 +15,8 @@ const (
|
||||
MockContainerMAC = "d6:f2:5a:12:36:a8"
|
||||
MockContainerIP = "10.0.0.123"
|
||||
MockHostname = "hostname.weave.local"
|
||||
MockProxyAddress = "unix:///foo/bar/weave.sock"
|
||||
MockDriverName = "weave_mock"
|
||||
)
|
||||
|
||||
// MockClient is a mock version of weave.Client
|
||||
@@ -54,6 +56,12 @@ func (MockClient) Status() (weave.Status, error) {
|
||||
{Size: 0, IsKnownPeer: false},
|
||||
},
|
||||
},
|
||||
Proxy: &weave.Proxy{
|
||||
Addresses: []string{MockProxyAddress},
|
||||
},
|
||||
Plugin: &weave.Plugin{
|
||||
DriverName: MockDriverName,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user