func (w *Watcher) registerServiceWatcher(service string) error { wp, err := watch.Parse(map[string]interface{}{ "type": "service", "datacenter": datacenter, "service": service, }) if err != nil { return err } wp.Handler = func(idx uint64, data interface{}) { switch d := data.(type) { case []*consulapi.ServiceEntry: for _, i := range d { fmt.Printf("[ %v ]\t%v\n", time.Now(), i) broadcastData("service", &i) consulRegistry.Lock() consulRegistry.services[i.Service.Service] = i consulRegistry.Unlock() } } } go wp.Run(w.addr) w.watchers[service] = wp return nil }
func NewConsulWatcher(cr *ConsulRegistry) *ConsulWatcher { cw := &ConsulWatcher{ Registry: cr, watchers: make(map[string]*watch.WatchPlan), } wp, err := watch.Parse(map[string]interface{}{"type": "services"}) if err == nil { wp.Handler = cw.Handle go wp.Run(cr.Address) cw.wp = wp } return cw }
func newConsulWatcher(cr *consulRegistry) (Watcher, error) { cw := &consulWatcher{ Registry: cr, watchers: make(map[string]*watch.WatchPlan), } wp, err := watch.Parse(map[string]interface{}{"type": "services"}) if err != nil { return nil, err } wp.Handler = cw.Handle go wp.Run(cr.Address) cw.wp = wp return cw, nil }
func (cw *consulWatcher) handle(idx uint64, data interface{}) { services, ok := data.(map[string][]string) if !ok { return } // add new watchers for service, _ := range services { if _, ok := cw.watchers[service]; ok { continue } wp, err := watch.Parse(map[string]interface{}{ "type": "service", "service": service, }) if err == nil { wp.Handler = cw.serviceHandler go wp.Run(cw.r.Address) cw.watchers[service] = wp cw.next <- &Result{Action: "create", Service: &Service{Name: service}} } } cw.RLock() rservices := cw.services cw.RUnlock() // remove unknown services from registry for service, _ := range rservices { if _, ok := services[service]; !ok { cw.Lock() delete(cw.services, service) cw.Unlock() } } // remove unknown services from watchers for service, w := range cw.watchers { if _, ok := services[service]; !ok { w.Stop() delete(cw.watchers, service) cw.next <- &Result{Action: "delete", Service: &Service{Name: service}} } } }
func main() { logger.Println("Started.") conf := consul.DefaultConfig() watchParams := make(map[string]interface{}) watchParams["type"] = "keyprefix" watchParams["prefix"] = "/" watch, err := consulWatch.Parse(watchParams) MaybeFatal(err) watch.Datacenter = conf.Datacenter watch.Token = conf.Token watch.LogOutput = logOutput watch.Handler = makeKvPairsHandler(conf) MaybeFatal(watch.Run(conf.Address)) }
func newConsulWatcher(cr *consulRegistry) (Watcher, error) { cw := &consulWatcher{ r: cr, exit: make(chan bool), next: make(chan *Result, 10), watchers: make(map[string]*watch.WatchPlan), services: make(map[string][]*Service), } wp, err := watch.Parse(map[string]interface{}{"type": "services"}) if err != nil { return nil, err } wp.Handler = cw.handle go wp.Run(cr.Address) cw.wp = wp return cw, nil }
func newWatcher(key, addr, name string) (config.SourceWatcher, error) { w := &watcher{ name: name, ch: make(chan *config.ChangeSet), exit: make(chan bool), } wp, err := watch.Parse(map[string]interface{}{"type": "key", "key": key}) if err != nil { return nil, err } wp.Handler = w.handle if err := wp.Run(addr); err != nil { return nil, err } w.wp = wp return w, nil }
func NewWatcher(addr string, watchType string, drain chan<- *consulapi.HealthCheck) (*Watcher, error) { wp, err := watch.Parse(map[string]interface{}{ "type": watchType, }) if err != nil { return nil, err } wp.Handler = func(idx uint64, data interface{}) { switch d := data.(type) { case []*consulapi.HealthCheck: for _, i := range d { drain <- i } } } return &Watcher{ addr: addr, wp: wp, }, nil }
func (cs *Store) Watch() error { params := map[string]interface{}{ "type": "keyprefix", "prefix": cs.cfg.Namespace, } wp, err := watch.Parse(params) defer wp.Stop() if err != nil { printer.LogErrf("%v", err) } wp.Handler = func(idx uint64, data interface{}) { cs.Updated(data) } if err := wp.Run(cs.cfg.Consul.Address); err != nil { printer.LogErrf("Error querying Consul agent: %s", err) } return nil }
func newWatcher(addr string, watchType string, opts map[string]string) (*Watcher, error) { var options = map[string]interface{}{ "type": watchType, "datacenter": datacenter, } for k, v := range opts { options[k] = v } wp, err := watch.Parse(options) if err != nil { return nil, err } w := &Watcher{ addr, wp, make(map[string]*watch.WatchPlan), } wp.Handler = func(idx uint64, data interface{}) { switch d := data.(type) { // key case *consulapi.KVPair: fmt.Printf("[ %v ]\t%v\n", time.Now(), d) broadcastData(watchType, &ConsulKV{ d.Key, d.Value, }) // nodes case []*consulapi.Node: nodes := make([]*ConsulNode, 0, len(d)) for _, i := range d { fmt.Printf("[ %v ]\t%v\n", time.Now(), i) nodes = append(nodes, &ConsulNode{ Name: i.Node, Address: i.Address, }) } broadcastData(watchType, &nodes) // checks case []*consulapi.HealthCheck: for _, i := range d { fmt.Printf("[ %v ]\t%v\n", time.Now(), i) broadcastData(watchType, &ConsulHealthCheck{ i.Node, i.CheckID, i.Name, i.Status, i.Notes, i.Output, i.ServiceID, i.ServiceName, }) } // services case map[string][]string: for i, _ := range d { fmt.Printf("[ %v ]\t%v\n", time.Now(), i) if _, ok := w.watchers[i]; ok { continue } w.registerServiceWatcher(i) } consulRegistry.RLock() rs := consulRegistry.services consulRegistry.RUnlock() // remove unknown services from registry for s, _ := range rs { if _, ok := d[s]; !ok { consulRegistry.Lock() delete(consulRegistry.services, s) consulRegistry.Unlock() } } // remove unknown services from watchers for i, svc := range w.watchers { if _, ok := d[i]; !ok { svc.Stop() delete(w.watchers, i) } } default: fmt.Printf("Could not interpret data type: %v", &d) } } return w, nil }
func (r *Roll) Dispatch(host string) error { // Setup event cascadeEvent := CascadeEvent{"cascade cli", "run", ""} payload, _ := json.Marshal(cascadeEvent) nodeFilter := fmt.Sprintf("^%s", host) params := &api.UserEvent{Name: "cascade.cm", Payload: payload, NodeFilter: nodeFilter} var errExit error // Setup watch watchParams := make(map[string]interface{}) watchParams["type"] = "event" watchParams["name"] = "cascade.cm" watch, err := watch.Parse(watchParams) if err != nil { return err } r.watch = watch // Set handler r.watch.Handler = func(idx uint64, data interface{}) { events := data.([]*api.UserEvent) for _, event := range events { var e CascadeEvent err := json.Unmarshal(event.Payload, &e) if err != nil { fmt.Println("err: ", err) } if e.Ref == r.curID { r.Msg <- e.Msg if e.Msg == "success" || e.Msg == "fail" { r.watch.Stop() if e.Msg == "fail" { errExit = errors.New("err: failure roll stopped") } } } } } // Fire event id, _, err := r.event.Fire(params, nil) r.curID = id if err != nil { return err } // Send the host we are watching for r.Msg <- host // Execute Watch if err := r.watch.Run(ConsulHost); err != nil { return errors.New(fmt.Sprintf("err: querying Consul agent: %s", err)) } return errExit }
func (c *WatchCommand) Run(args []string) int { var watchType, datacenter, token, key, prefix, service, tag, passingOnly, stale, state, name string cmdFlags := flag.NewFlagSet("watch", flag.ContinueOnError) cmdFlags.Usage = func() { c.Ui.Output(c.Help()) } cmdFlags.StringVar(&watchType, "type", "", "") cmdFlags.StringVar(&datacenter, "datacenter", "", "") cmdFlags.StringVar(&token, "token", "", "") cmdFlags.StringVar(&key, "key", "", "") cmdFlags.StringVar(&prefix, "prefix", "", "") cmdFlags.StringVar(&service, "service", "", "") cmdFlags.StringVar(&tag, "tag", "", "") cmdFlags.StringVar(&passingOnly, "passingonly", "", "") cmdFlags.StringVar(&stale, "stale", "", "") cmdFlags.StringVar(&state, "state", "", "") cmdFlags.StringVar(&name, "name", "", "") httpAddr := HTTPAddrFlag(cmdFlags) if err := cmdFlags.Parse(args); err != nil { return 1 } // Check for a type if watchType == "" { c.Ui.Error("Watch type must be specified") c.Ui.Error("") c.Ui.Error(c.Help()) return 1 } // Grab the script to execute if any script := strings.Join(cmdFlags.Args(), " ") // Compile the watch parameters params := make(map[string]interface{}) if watchType != "" { params["type"] = watchType } if datacenter != "" { params["datacenter"] = datacenter } if token != "" { params["token"] = token } if key != "" { params["key"] = key } if prefix != "" { params["prefix"] = prefix } if service != "" { params["service"] = service } if tag != "" { params["tag"] = tag } if stale != "" { b, err := strconv.ParseBool(stale) if err != nil { c.Ui.Error(fmt.Sprintf("Failed to parse stale flag: %s", err)) return 1 } params["stale"] = b } if state != "" { params["state"] = state } if name != "" { params["name"] = name } if passingOnly != "" { b, err := strconv.ParseBool(passingOnly) if err != nil { c.Ui.Error(fmt.Sprintf("Failed to parse passingonly flag: %s", err)) return 1 } params["passingonly"] = b } // Create the watch wp, err := watch.Parse(params) if err != nil { c.Ui.Error(fmt.Sprintf("%s", err)) return 1 } // Create and test the HTTP client client, err := HTTPClient(*httpAddr) if err != nil { c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err)) return 1 } _, err = client.Agent().NodeName() if err != nil { c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err)) return 1 } // Setup handler // errExit: // 0: false // 1: true errExit := 0 if script == "" { wp.Handler = func(idx uint64, data interface{}) { defer wp.Stop() buf, err := json.MarshalIndent(data, "", " ") if err != nil { c.Ui.Error(fmt.Sprintf("Error encoding output: %s", err)) errExit = 1 } c.Ui.Output(string(buf)) } } else { wp.Handler = func(idx uint64, data interface{}) { // Create the command var buf bytes.Buffer var err error cmd, err := agent.ExecScript(script) if err != nil { c.Ui.Error(fmt.Sprintf("Error executing handler: %s", err)) goto ERR } cmd.Env = append(os.Environ(), "CONSUL_INDEX="+strconv.FormatUint(idx, 10), ) // Encode the input if err = json.NewEncoder(&buf).Encode(data); err != nil { c.Ui.Error(fmt.Sprintf("Error encoding output: %s", err)) goto ERR } cmd.Stdin = &buf cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr // Run the handler if err := cmd.Run(); err != nil { c.Ui.Error(fmt.Sprintf("Error executing handler: %s", err)) goto ERR } return ERR: wp.Stop() errExit = 1 } } // Watch for a shutdown go func() { <-c.ShutdownCh wp.Stop() os.Exit(0) }() // Run the watch if err := wp.Run(*httpAddr); err != nil { c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err)) return 1 } return errExit }
func (c *Client) watchInternal(wi helpers.WatchInfo) { var wp *watch.WatchPlan var err error if wi.Recursive { wp, err = watch.Parse(map[string]interface{}{ "type": "keyprefix", "prefix": c.qualified(wi.Path), }) } else { wp, err = watch.Parse(map[string]interface{}{ "type": "key", "key": c.qualified(wi.Path), }) } if err != nil { wi.ErrorChan <- err return } wp.Handler = func(u uint64, i interface{}) { if i == nil { return } switch i.(type) { case api.KVPairs: for _, pair := range i.(api.KVPairs) { if pair == nil { continue } this, err := helpers.ReadAndSet(c, wi.Object, pair.Key, pair.Value) if err != nil { wi.ErrorChan <- err continue } wi.ReturnChan <- this } case *api.KVPair: this, err := helpers.ReadAndSet(c, wi.Object, i.(*api.KVPair).Key, i.(*api.KVPair).Value) if err != nil { wi.ErrorChan <- err return } wi.ReturnChan <- this default: logrus.Errorf("received invalid pair %+v during watch", i) } } go func(wp *watch.WatchPlan) { if err := wp.Run(c.config.Address); err != nil { wi.ErrorChan <- err } }(wp) go func(wp *watch.WatchPlan, wi helpers.WatchInfo) { <-wi.StopChan (*wp).Stop() }(wp, wi) }