123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- package weave
- import (
- "bytes"
- "fmt"
- "net"
- "net/http"
- "net/url"
- "os"
- realexec "os/exec"
- "regexp"
- "strconv"
- "github.com/ugorji/go/codec"
- "github.com/weaveworks/common/exec"
- )
- const dockerAPIVersion = "1.22" // Support Docker Engine >= 1.10
- // Client for Weave Net API
- type Client interface {
- Status() (Status, error)
- AddDNSEntry(fqdn, containerid string, ip net.IP) error
- Expose() error // on the interface for mocking
- }
- // Status describes whats happen in the Weave Net router.
- type Status struct {
- Version string
- Router Router
- DNS *DNS
- IPAM *IPAM
- Proxy *Proxy
- Plugin *Plugin
- }
- // Router describes the status of the Weave Router
- type Router struct {
- Name string
- Encryption bool
- ProtocolMinVersion int
- ProtocolMaxVersion int
- PeerDiscovery bool
- Peers []Peer
- Connections []struct {
- Address string
- Outbound bool
- State string
- Info string
- }
- Targets []string
- TrustedSubnets []string
- }
- // Peer describes a peer in the weave network
- type Peer struct {
- Name string
- NickName string
- Connections []struct {
- Name string
- NickName string
- Address string
- Outbound bool
- Established bool
- }
- }
- // DNS describes the status of Weave DNS
- type DNS struct {
- Domain string
- Upstream []string
- TTL uint32
- Entries []struct {
- Hostname string
- ContainerID string
- Tombstone int64
- }
- }
- // IPAM describes the status of Weave IPAM
- type IPAM struct {
- Paxos *struct {
- Elector bool
- KnownNodes int
- Quorum uint
- }
- Range string
- DefaultSubnet string
- Entries []struct {
- Size uint32
- IsKnownPeer bool
- }
- 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 ipMatch = regexp.MustCompile(`([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})(/[0-9]+)`)
- type client struct {
- url string
- }
- // NewClient makes a new Client
- func NewClient(url string) Client {
- return &client{
- url: url,
- }
- }
- func (c *client) Status() (Status, error) {
- req, err := http.NewRequest("GET", c.url+"/report", nil)
- if err != nil {
- return Status{}, err
- }
- req.Header.Add("Accept", "application/json")
- resp, err := http.DefaultClient.Do(req)
- if err != nil {
- return Status{}, errorf("%v", err)
- }
- defer resp.Body.Close()
- if resp.StatusCode != http.StatusOK {
- return Status{}, fmt.Errorf("Got %d", resp.StatusCode)
- }
- var status Status
- decoder := codec.NewDecoder(resp.Body, &codec.JsonHandle{})
- if err := decoder.Decode(&status); err != nil {
- return Status{}, err
- }
- return status, nil
- }
- func (c *client) AddDNSEntry(fqdn, containerID string, ip net.IP) error {
- data := url.Values{
- "fqdn": []string{fqdn},
- }
- url := fmt.Sprintf("%s/name/%s/%s", c.url, containerID, ip.String())
- req, err := http.NewRequest("PUT", url, bytes.NewBufferString(data.Encode()))
- if err != nil {
- return err
- }
- req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
- req.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
- resp, err := http.DefaultClient.Do(req)
- if err != nil {
- return errorf("%v", err)
- }
- if err := resp.Body.Close(); err != nil {
- return err
- }
- if resp.StatusCode != http.StatusNoContent {
- return fmt.Errorf("Got %d", resp.StatusCode)
- }
- return nil
- }
- func (c *client) Expose() error {
- cmd := weaveCommand("--local", "ps", "weave:expose")
- output, err := cmd.Output()
- if err != nil {
- stdErr := []byte{}
- if exitErr, ok := err.(*realexec.ExitError); ok {
- stdErr = exitErr.Stderr
- }
- return errorf("Error running weave ps: %s: %q", err, stdErr)
- }
- ips := ipMatch.FindAllSubmatch(output, -1)
- if ips != nil {
- // Alread exposed!
- return nil
- }
- cmd = weaveCommand("--local", "expose")
- if _, err := cmd.Output(); err != nil {
- stdErr := []byte{}
- if exitErr, ok := err.(*realexec.ExitError); ok {
- stdErr = exitErr.Stderr
- }
- return errorf("Error running weave expose: %s: %q", err, stdErr)
- }
- return nil
- }
- func weaveCommand(arg ...string) exec.Cmd {
- cmd := exec.Command("weave", arg...)
- cmd.SetEnv(append(os.Environ(), "DOCKER_API_VERSION="+dockerAPIVersion))
- return cmd
- }
- func errorf(format string, a ...interface{}) error {
- return fmt.Errorf(format+". If you are not running Weave Net, you may wish to suppress this warning by launching scope with the `--weave=false` option.", a...)
- }
|