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  }