// removeDirCommandFunc executes the "rmdir" command. func removeDirCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error) { if len(c.Args()) == 0 { return nil, errors.New("Key required") } key := c.Args()[0] return client.DeleteDir(key) }
// lsCommandFunc executes the "ls" command. func lsCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error) { key := "/" if len(c.Args()) != 0 { key = c.Args()[0] } recursive := c.Bool("recursive") // Retrieve the value from the server. return client.Get(key, false, recursive) }
// Just like handlePrint but also passed the context of the command func handleContextualPrint(c *cli.Context, fn handlerFunc, pFn contextualPrintFunc) { resp, err := rawhandle(c, fn) if err != nil { handleError(ErrorFromEtcd, err) } if resp != nil && pFn != nil { pFn(c, resp, c.GlobalString("output")) } }
// handlePrint wraps the command function handlers to parse global flags // into a client and to properly format the response objects. func handlePrint(c *cli.Context, fn handlerFunc, pFn printFunc) { resp, err := rawhandle(c, fn) // Print error and exit, if necessary. if err != nil { handleError(ErrorFromEtcd, err) } if resp != nil && pFn != nil { pFn(resp, c.GlobalString("output")) } }
// rPrint recursively prints out the nodes in the node structure. func rPrint(c *cli.Context, n *etcd.Node) { if n.Dir && c.Bool("p") { fmt.Println(fmt.Sprintf("%v/", n.Key)) } else { fmt.Println(n.Key) } for _, node := range n.Nodes { rPrint(c, &node) } }
// rawhandle wraps the command function handlers and sets up the // environment but performs no output formatting. func rawhandle(c *cli.Context, fn handlerFunc) (*etcd.Response, error) { sync := !c.GlobalBool("no-sync") peerstr := c.GlobalString("peers") // Use an environment variable if nothing was supplied on the // command line if peerstr == "" { peerstr = os.Getenv("ETCDCTL_PEERS") } // If we still don't have peers, use a default if peerstr == "" { peerstr = "127.0.0.1:4001" } peers := strings.Split(peerstr, ",") // If no sync, create http path for each peer address if !sync { revisedPeers := make([]string, 0) for _, peer := range peers { if revisedPeer, err := createHttpPath(peer); err != nil { fmt.Fprintf(os.Stderr, "Unsupported url %v: %v\n", peer, err) } else { revisedPeers = append(revisedPeers, revisedPeer) } } peers = revisedPeers } client := etcd.NewClient(peers) if c.GlobalBool("debug") { go dumpCURL(client) } // Sync cluster. if sync { if ok := client.SyncCluster(); !ok { handleError(FailedToConnectToHost, errors.New("Cannot sync with the cluster using peers "+strings.Join(peers, ", "))) } } if c.GlobalBool("debug") { fmt.Fprintf(os.Stderr, "Cluster-Peers: %s\n", strings.Join(client.GetCluster(), " ")) } // Execute handler function. return fn(c, client) }
// updateCommandFunc executes the "update" command. func updateCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error) { if len(c.Args()) == 0 { return nil, errors.New("Key required") } key := c.Args()[0] value, err := argOrStdin(c.Args(), os.Stdin, 1) if err != nil { return nil, errors.New("Value required") } ttl := c.Int("ttl") return client.Update(key, value, uint64(ttl)) }
// setDirCommandFunc executes the "setDir" command. func setDirCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error) { if len(c.Args()) == 0 { return nil, errors.New("Key required") } key := c.Args()[0] ttl := c.Int("ttl") return client.SetDir(key, uint64(ttl)) }
// getCommandFunc executes the "get" command. func getCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error) { if len(c.Args()) == 0 { return nil, errors.New("Key required") } key := c.Args()[0] consistent := c.Bool("consistent") sorted := c.Bool("sort") // Setup consistency on the client. if consistent { client.SetConsistency(etcd.STRONG_CONSISTENCY) } else { client.SetConsistency(etcd.WEAK_CONSISTENCY) } // Retrieve the value from the server. return client.Get(key, sorted, false) }
// setCommandFunc executes the "set" command. func setCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error) { if len(c.Args()) == 0 { return nil, errors.New("Key required") } key := c.Args()[0] value, err := argOrStdin(c.Args(), os.Stdin, 1) if err != nil { return nil, errors.New("Value required") } ttl := c.Int("ttl") prevValue := c.String("swap-with-value") prevIndex := c.Int("swap-with-index") if prevValue == "" && prevIndex == 0 { return client.Set(key, value, uint64(ttl)) } else { return client.CompareAndSwap(key, value, uint64(ttl), prevValue, uint64(prevIndex)) } }
// execWatchCommandFunc executes the "exec-watch" command. func execWatchCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error) { _ = io.Copy _ = exec.Command args := c.Args() argsLen := len(args) if argsLen < 2 { return nil, errors.New("Key and command to exec required") } key := args[argsLen-1] cmdArgs := args[:argsLen-1] index := 0 if c.Int("after-index") != 0 { index = c.Int("after-index") + 1 key = args[0] cmdArgs = args[2:] } recursive := c.Bool("recursive") if recursive != false { key = args[0] cmdArgs = args[2:] } sigch := make(chan os.Signal, 1) signal.Notify(sigch, os.Interrupt) stop := make(chan bool) go func() { <-sigch stop <- true os.Exit(0) }() receiver := make(chan *etcd.Response) client.SetConsistency(etcd.WEAK_CONSISTENCY) go client.Watch(key, uint64(index), recursive, receiver, stop) for { resp := <-receiver cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) cmd.Env = environResponse(resp, os.Environ()) stdout, err := cmd.StdoutPipe() if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } stderr, err := cmd.StderrPipe() if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } err = cmd.Start() if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } go io.Copy(os.Stdout, stdout) go io.Copy(os.Stderr, stderr) cmd.Wait() } return nil, nil }