mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-05 19:21:46 +00:00
110 lines
2.8 KiB
Go
110 lines
2.8 KiB
Go
package docker
|
|
|
|
import (
|
|
"errors"
|
|
"github.com/fsouza/go-dockerclient"
|
|
|
|
. "github.com/weaveworks/weave/common"
|
|
)
|
|
|
|
// An observer for container events
|
|
type ContainerObserver interface {
|
|
ContainerStarted(ident string)
|
|
ContainerDied(ident string)
|
|
}
|
|
|
|
type Client struct {
|
|
*docker.Client
|
|
}
|
|
|
|
// NewClient creates a new Docker client and checks we can talk to Docker
|
|
func NewClient(apiPath string) (*Client, error) {
|
|
dc, err := docker.NewClient(apiPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
client := &Client{dc}
|
|
|
|
return client, client.checkWorking(apiPath)
|
|
}
|
|
|
|
func NewVersionedClient(apiPath string, apiVersionString string) (*Client, error) {
|
|
dc, err := docker.NewVersionedClient(apiPath, apiVersionString)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
client := &Client{dc}
|
|
|
|
return client, client.checkWorking(apiPath)
|
|
}
|
|
|
|
func (c *Client) checkWorking(apiPath string) error {
|
|
env, err := c.Version()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
Log.Infof("[docker] Using Docker API on %s: %v", apiPath, env)
|
|
return nil
|
|
}
|
|
|
|
// AddObserver adds an observer for docker events
|
|
func (c *Client) AddObserver(ob ContainerObserver) error {
|
|
events := make(chan *docker.APIEvents)
|
|
if err := c.AddEventListener(events); err != nil {
|
|
Log.Errorf("[docker] Unable to add listener to Docker API: %s", err)
|
|
return err
|
|
}
|
|
|
|
go func() {
|
|
for event := range events {
|
|
switch event.Status {
|
|
case "start":
|
|
id := event.ID
|
|
ob.ContainerStarted(id)
|
|
case "die":
|
|
id := event.ID
|
|
ob.ContainerDied(id)
|
|
}
|
|
}
|
|
}()
|
|
return nil
|
|
}
|
|
|
|
// IsContainerNotRunning returns true if we have checked with Docker that the ID is not running
|
|
func (c *Client) IsContainerNotRunning(idStr string) bool {
|
|
container, err := c.InspectContainer(idStr)
|
|
if err == nil {
|
|
return !container.State.Running
|
|
}
|
|
if _, notThere := err.(*docker.NoSuchContainer); notThere {
|
|
return true
|
|
}
|
|
Log.Errorf("[docker] Could not check container status: %s", err)
|
|
return false
|
|
}
|
|
|
|
// This is intended to find an IP address that we can reach the container on;
|
|
// if it is on the Docker bridge network then that address; if on the host network
|
|
// then localhost
|
|
func (c *Client) GetContainerIP(nameOrID string) (string, error) {
|
|
Log.Debugf("Getting IP for container %s", nameOrID)
|
|
info, err := c.InspectContainer(nameOrID)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if info.NetworkSettings.Networks != nil {
|
|
Log.Debugln("Networks: ", info.NetworkSettings.Networks)
|
|
if bridgeNetwork, ok := info.NetworkSettings.Networks["bridge"]; ok {
|
|
return bridgeNetwork.IPAddress, nil
|
|
} else if _, ok := info.NetworkSettings.Networks["host"]; ok {
|
|
return "127.0.0.1", nil
|
|
}
|
|
} else if info.HostConfig.NetworkMode == "host" {
|
|
return "127.0.0.1", nil
|
|
}
|
|
if info.NetworkSettings.IPAddress == "" {
|
|
return "", errors.New("No IP address found for container " + nameOrID)
|
|
}
|
|
return info.NetworkSettings.IPAddress, nil
|
|
}
|