go.etcd.io/etcd@v3.3.27+incompatible/etcdctl/ctlv2/command/watch_command.go (about) 1 // Copyright 2015 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package command 16 17 import ( 18 "context" 19 "errors" 20 "fmt" 21 "os" 22 "os/signal" 23 24 "github.com/coreos/etcd/client" 25 26 "github.com/urfave/cli" 27 ) 28 29 // NewWatchCommand returns the CLI command for "watch". 30 func NewWatchCommand() cli.Command { 31 return cli.Command{ 32 Name: "watch", 33 Usage: "watch a key for changes", 34 ArgsUsage: "<key>", 35 Flags: []cli.Flag{ 36 cli.BoolFlag{Name: "forever, f", Usage: "forever watch a key until CTRL+C"}, 37 cli.IntFlag{Name: "after-index", Value: 0, Usage: "watch after the given index"}, 38 cli.BoolFlag{Name: "recursive, r", Usage: "returns all values for key and child keys"}, 39 }, 40 Action: func(c *cli.Context) error { 41 watchCommandFunc(c, mustNewKeyAPI(c)) 42 return nil 43 }, 44 } 45 } 46 47 // watchCommandFunc executes the "watch" command. 48 func watchCommandFunc(c *cli.Context, ki client.KeysAPI) { 49 if len(c.Args()) == 0 { 50 handleError(c, ExitBadArgs, errors.New("key required")) 51 } 52 key := c.Args()[0] 53 recursive := c.Bool("recursive") 54 forever := c.Bool("forever") 55 index := c.Int("after-index") 56 57 stop := false 58 w := ki.Watcher(key, &client.WatcherOptions{AfterIndex: uint64(index), Recursive: recursive}) 59 60 sigch := make(chan os.Signal, 1) 61 signal.Notify(sigch, os.Interrupt) 62 63 go func() { 64 <-sigch 65 os.Exit(0) 66 }() 67 68 for !stop { 69 resp, err := w.Next(context.TODO()) 70 if err != nil { 71 handleError(c, ExitServerError, err) 72 } 73 if resp.Node.Dir { 74 continue 75 } 76 if recursive { 77 fmt.Printf("[%s] %s\n", resp.Action, resp.Node.Key) 78 } 79 80 printResponseKey(resp, c.GlobalString("output")) 81 82 if !forever { 83 stop = true 84 } 85 } 86 }