func StartBalancerAgent(args []string, errorSink daemon.ErrorSink) *BalancerAgent { a := &BalancerAgent{errorSink: errorSink} if err := a.parseArgs(args); err != nil { errorSink.Post(err) return a } if err := a.start(); err != nil { errorSink.Post(err) } return a }
func (es *etcdStore) WatchServices(ctx context.Context, resCh chan<- data.ServiceChange, errorSink daemon.ErrorSink, opts store.QueryServiceOptions) { if ctx == nil { ctx = es.ctx } svcs := make(map[string]struct{}) handleResponse := func(r *etcd.Response) { switch r.Action { case "delete": switch key := parseKey(r.Node.Key).(type) { case parsedRootKey: for name := range svcs { resCh <- data.ServiceChange{name, true} } svcs = make(map[string]struct{}) case parsedServiceRootKey: delete(svcs, key.serviceName) resCh <- data.ServiceChange{key.serviceName, true} case interface { relevantTo(opts store.QueryServiceOptions) (bool, string) }: if relevant, service := key.relevantTo(opts); relevant { resCh <- data.ServiceChange{service, false} } } case "set": switch key := parseKey(r.Node.Key).(type) { case parsedServiceKey: svcs[key.serviceName] = struct{}{} resCh <- data.ServiceChange{key.serviceName, false} case interface { relevantTo(opts store.QueryServiceOptions) (bool, string) }: if relevant, service := key.relevantTo(opts); relevant { resCh <- data.ServiceChange{service, false} } } } } // Get the initial service list, so that we can report them as // deleted if the root node is deleted. This also gets the // initial index for the watch. (Though perhaps that should // really be based on the ModifieedIndex of the nodes // themselves?) node, startIndex, err := es.getDirNode(ROOT, true, false) if err != nil { errorSink.Post(err) return } for name := range indexDir(node) { svcs[name] = struct{}{} } go func() { watcher := es.Watcher(ROOT, &etcd.WatcherOptions{ AfterIndex: startIndex, Recursive: true, }) for { next, err := watcher.Next(ctx) if err != nil { errorSink.Post(err) break } handleResponse(next) } }() }