Beispiel #1
0
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
}
Beispiel #2
0
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
}
Beispiel #3
0
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
}
Beispiel #4
0
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}}
		}
	}
}
Beispiel #5
0
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))
}
Beispiel #6
0
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
}
Beispiel #7
0
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
}
Beispiel #8
0
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
}
Beispiel #9
0
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
}
Beispiel #10
0
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
}
Beispiel #11
0
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
}
Beispiel #12
0
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
}
Beispiel #13
0
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)
}