func ParseExempt(params map[string]interface{}, exempt []string) (*WatchPlan, error) {
	plan := &WatchPlan{
		stopCh: make(chan struct{}),
	}
	if err := assignValue(params, "datacenter", &plan.Datacenter); err != nil {
		return nil, err
	}
	if err := assignValue(params, "token", &plan.Token); err != nil {
		return nil, err
	}
	if err := assignValue(params, "type", &plan.Type); err != nil {
		return nil, err
	}
	if plan.Type == "" {
		return nil, fmt.Errorf("Watch type must be specified")
	}
	factory := watchFuncFactory[plan.Type]
	if factory == nil {
		return nil, fmt.Errorf("Unsupported watch type: %s", plan.Type)
	}
	fn, err := factory(params)
	if err != nil {
		return nil, err
	}
	plan.Func = fn
	if len(exempt) > 0 {
		plan.Exempt = make(map[string]interface{})
		for _, ex := range exempt {
			val, ok := params[ex]
			if ok {
				plan.Exempt[ex] = val
				delete(params, ex)
			}
		}
	}
	if len(params) != 0 {
		var bad []string
		for key := range params {
			bad = append(bad, key)
		}
		return nil, fmt.Errorf("Invalid parameters: %v", bad)
	}
	return plan, nil
}
ParseExempt takes a watch query and compiles it into a WatchPlan or an error
Any exempt parameters are stored in the Exempt map
package watch
import (
	"fmt"
	"io"
	"sync"
	consulapi "github.com/hashicorp/consul/api"
)
type WatchPlan struct {
	Datacenter string
	Token      string
	Type       string
	Exempt     map[string]interface{}
	Func      WatchFunc
	Handler   HandlerFunc
	LogOutput io.Writer
	address    string
	client     *consulapi.Client
	lastIndex  uint64
	lastResult interface{}
	stop     bool
	stopCh   chan struct{}
	stopLock sync.Mutex
}
type WatchFunc func(*WatchPlan) (uint64, interface{}, error)
type HandlerFunc func(uint64, interface{})
func Parse(params map[string]interface{}) (*WatchPlan, error) {
	return ParseExempt(params, nil)
}