func WaitPrefixEvents(c *clientv3.Client, prefix string, rev int64, evs []mvccpb.Event_EventType) (*clientv3.Event, error) { wc := c.Watch(context.Background(), prefix, clientv3.WithPrefix(), clientv3.WithRev(rev)) if wc == nil { return nil, ErrNoWatcher } return waitEvents(wc, evs), nil }
// WaitEvents waits on a key until it observes the given events and returns the final one. func WaitEvents(c *clientv3.Client, key string, rev int64, evs []storagepb.Event_EventType) (*storagepb.Event, error) { wc := c.Watch(context.Background(), key, clientv3.WithRev(rev)) if wc == nil { return nil, ErrNoWatcher } return waitEvents(wc, evs), nil }
func waitUpdate(ctx context.Context, client *v3.Client, key string, opts ...v3.OpOption) error { cctx, cancel := context.WithCancel(ctx) defer cancel() wresp, ok := <-client.Watch(cctx, key, opts...) if !ok { return ctx.Err() } return wresp.Err() }
// snapshotToStdout streams a snapshot over stdout func snapshotToStdout(c *clientv3.Client) { // must explicitly fetch first revision since no retry on stdout wr := <-c.Watch(context.TODO(), "", clientv3.WithPrefix(), clientv3.WithRev(1)) if wr.Err() == nil { wr.CompactRevision = 1 } if rev := snapshot(os.Stdout, c, wr.CompactRevision+1); rev != 0 { err := fmt.Errorf("snapshot interrupted by compaction %v", rev) ExitWithError(ExitInterrupted, err) } os.Stdout.Sync() }
func waitDelete(ctx context.Context, client *v3.Client, key string, rev int64) error { cctx, cancel := context.WithCancel(ctx) defer cancel() wch := client.Watch(cctx, key, v3.WithRev(rev)) for wr := range wch { for _, ev := range wr.Events { if ev.Type == storagepb.DELETE { return nil } } } if err := ctx.Err(); err != nil { return err } return fmt.Errorf("lost watcher waiting for delete") }
func getWatchChan(c *clientv3.Client, args []string) (clientv3.WatchChan, error) { if len(args) < 1 || len(args) > 2 { return nil, fmt.Errorf("bad number of arguments") } key := args[0] opts := []clientv3.OpOption{clientv3.WithRev(watchRev)} if len(args) == 2 { if watchPrefix { return nil, fmt.Errorf("`range_end` and `--prefix` are mutually exclusive") } opts = append(opts, clientv3.WithRange(args[1])) } if watchPrefix { opts = append(opts, clientv3.WithPrefix()) } if watchPrevKey { opts = append(opts, clientv3.WithPrevKV()) } return c.Watch(context.TODO(), key, opts...), nil }
func etcdMon_v3(prefix string, c3 *clientv3.Client, bus chan fileChangeEvent, startRevision int64) { key, option := prefixToKeyOption(prefix) ch := c3.Watch(context.Background(), key, option, clientv3.WithRev(startRevision)) for chEvent := range ch { for _, event := range chEvent.Events { fileEvent := fileChangeEvent{ Path: string(event.Kv.Key), Content: event.Kv.Value, } switch event.Type { case mvccpb.PUT: bus <- fileEvent case mvccpb.DELETE: fileEvent.IsRemoved = true bus <- fileEvent default: log.Println("etcdMon_v3 undefined event type: ", event.Type) } } } close(bus) }
func main() { flag.Parse() if config.Version { fmt.Printf("skydns server version: %s\n", server.Version) os.Exit(0) } machines := strings.Split(machine, ",") var clientptr *etcdv3.Client var err error var clientv3 etcdv3.Client var clientv2 etcd.KeysAPI if config.Etcd3 { clientptr, err = newEtcdV3Client(machines, tlspem, tlskey, cacert) clientv3 = *clientptr } else { clientv2, err = newEtcdV2Client(machines, tlspem, tlskey, cacert, username, password) } if err != nil { panic(err) } if nameserver != "" { for _, hostPort := range strings.Split(nameserver, ",") { if err := validateHostPort(hostPort); err != nil { log.Fatalf("skydns: nameserver is invalid: %s", err) } config.Nameservers = append(config.Nameservers, hostPort) } } if err := validateHostPort(config.DnsAddr); err != nil { log.Fatalf("skydns: addr is invalid: %s", err) } if config.Etcd3 { if err := loadEtcdV3Config(clientv3, config); err != nil { log.Fatalf("skydns: %s", err) } } else { if err := loadEtcdV2Config(clientv2, config); err != nil { log.Fatalf("skydns: %s", err) } } if err := server.SetDefaults(config); err != nil { log.Fatalf("skydns: defaults could not be set from /etc/resolv.conf: %v", err) } if config.Local != "" { config.Local = dns.Fqdn(config.Local) } var backend server.Backend if config.Etcd3 { backend = backendetcdv3.NewBackendv3(clientv3, ctx, &backendetcdv3.Config{ Ttl: config.Ttl, Priority: config.Priority, }) } else { backend = backendetcd.NewBackend(clientv2, ctx, &backendetcd.Config{ Ttl: config.Ttl, Priority: config.Priority, }) } s := server.New(backend, config) if stub { s.UpdateStubZones() go func() { duration := 1 * time.Second if config.Etcd3 { var watcher etcdv3.WatchChan watcher = clientv3.Watch(ctx, msg.Path(config.Domain)+"/dns/stub/", etcdv3.WithPrefix()) for wresp := range watcher { if wresp.Err() != nil { log.Printf("skydns: stubzone update failed, sleeping %s + ~3s", duration) time.Sleep(duration + (time.Duration(rand.Float32() * 3e9))) duration *= 2 if duration > 32*time.Second { duration = 32 * time.Second } } else { s.UpdateStubZones() log.Printf("skydns: stubzone update") duration = 1 * time.Second //reset } } } else { var watcher etcd.Watcher watcher = clientv2.Watcher(msg.Path(config.Domain)+"/dns/stub/", &etcd.WatcherOptions{AfterIndex: 0, Recursive: true}) for { _, err := watcher.Next(ctx) if err != nil { // log.Printf("skydns: stubzone update failed, sleeping %s + ~3s", duration) time.Sleep(duration + (time.Duration(rand.Float32() * 3e9))) // Add some random. duration *= 2 if duration > 32*time.Second { duration = 32 * time.Second } } else { s.UpdateStubZones() log.Printf("skydns: stubzone update") duration = 1 * time.Second // reset } } } }() } if err := metrics.Metrics(); err != nil { log.Fatalf("skydns: %s", err) } else { log.Printf("skydns: metrics enabled on :%s%s", metrics.Port, metrics.Path) } if err := s.Run(); err != nil { log.Fatalf("skydns: %s", err) } }