Example #1
0
// Entries are Docker Engines
func (c *Cluster) monitorDiscovery(ch <-chan discovery.Entries, errCh <-chan error) {
	// Watch changes on the discovery channel.
	currentEntries := discovery.Entries{}
	for {
		select {
		case entries := <-ch:
			added, removed := currentEntries.Diff(entries)
			currentEntries = entries

			// Remove engines first. `addEngine` will refuse to add an engine
			// if there's already an engine with the same ID.  If an engine
			// changes address, we have to first remove it then add it back.
			for _, entry := range removed {
				c.removeEngine(entry.String())
			}

			// Since `addEngine` can be very slow (it has to connect to the
			// engine), we are going to do the adds in parallel.
			for _, entry := range added {
				go c.addEngine(entry.String())
			}
		case err := <-errCh:
			log.Errorf("Discovery error: %v", err)
		}
	}
}
Example #2
0
func TestWatch(t *testing.T) {
	d := &Discovery{}
	d.Initialize("1.1.1.1:1111,2.2.2.2:2222", 0, 0)
	expected := discovery.Entries{
		&discovery.Entry{Host: "1.1.1.1", Port: "1111"},
		&discovery.Entry{Host: "2.2.2.2", Port: "2222"},
	}
	ch, _ := d.Watch(nil)
	assert.True(t, expected.Equals(<-ch))
}
Example #3
0
// Create a new endpoint
func newDiscoveryEndpoint(url, localAddr string, discPort string, weaveCli *WeaveClient, heartbeat time.Duration, ttl time.Duration) (*discoveryEndpoint, error) {
	d, err := discovery.New(url, heartbeat, ttl)
	if err != nil {
		return nil, err
	}
	stopChan := make(chan struct{})
	ep := discoveryEndpoint{
		Discovery: d,
		url:       url,
		stopChan:  stopChan,
	}

	register := func() {}
	var localAddrHost, localAddrPort string
	if len(localAddr) > 0 {
		localAddrHost, localAddrPort, err = net.SplitHostPort(localAddr)
		if err != nil {
			Log.Warningf("[manager] Invalid local address '%s': %s", localAddr, err)
			return nil, err
		}

		register = func() {
			Log.Debugf("[manager] Registering on '%s' we are at '%s' (%s period)...", url, localAddr, heartbeat)
			if err := d.Register(localAddr); err != nil {
				Log.Warningf("[manager] Registration failed: %s", err)
			} else {
				ep.lastRegister = time.Now()
			}
		}
	}

	hostAndPort := func(e *discovery.Entry) (string, string, bool) {
		host := e.Host
		port := e.Port
		if len(discPort) > 0 {
			port = discPort
		}
		return host, port, (host == localAddrHost && port == localAddrPort)
	}

	entriesChan, errorsChan := d.Watch(stopChan)
	ticker := time.NewTicker(heartbeat)
	go func() {
		register()
		currentEntries := discovery.Entries{}
		for {
			select {
			case reportedEntries := <-entriesChan:
				added, removed := currentEntries.Diff(reportedEntries)

				ep.added += uint64(len(added))
				ep.removed += uint64(len(removed))

				currentEntries = reportedEntries
				Log.Printf("[manager] Updates from '%s': %d added, %d removed...", url, len(added), len(removed))
				for _, e := range added {
					if host, port, isLocal := hostAndPort(e); !isLocal {
						weaveCli.Join(host, port)
					}
				}
				for _, e := range removed {
					if host, port, isLocal := hostAndPort(e); !isLocal {
						weaveCli.Forget(host, port)
					}
				}
			case reportedError := <-errorsChan:
				Log.Warningf("[manager] Error from endpoint %s: %s...", url, reportedError)
			case <-ticker.C:
				register()
			case <-stopChan:
				ticker.Stop()
				return
			}
		}
	}()

	return &ep, nil
}