// startChild is a long running routine used to start and // wait for the child process to exit. func (c *LockCommand) startChild(script string, doneCh chan struct{}) error { defer close(doneCh) if c.verbose { c.Ui.Info(fmt.Sprintf("Starting handler '%s'", script)) } // Create the command cmd, err := agent.ExecScript(script) if err != nil { c.Ui.Error(fmt.Sprintf("Error executing handler: %s", err)) return err } // Setup the command streams cmd.Env = append(os.Environ(), "CONSUL_LOCK_HELD=true", ) cmd.Stdin = nil cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr // Start the child process if err := cmd.Start(); err != nil { c.Ui.Error(fmt.Sprintf("Error starting handler: %s", err)) return err } // Setup the child info c.childLock.Lock() c.child = cmd.Process c.childLock.Unlock() // Wait for the child process if err := cmd.Wait(); err != nil { c.Ui.Error(fmt.Sprintf("Error running handler: %s", err)) return err } return nil }
func (c *WatchCommand) Run(args []string) int { var watchType, datacenter, token, key, prefix, service, tag, passingOnly, state, name string cmdFlags := flag.NewFlagSet("watch", flag.ContinueOnError) cmdFlags.Usage = func() { c.Ui.Output(c.Help()) } cmdFlags.StringVar(&watchType, "type", "", "") cmdFlags.StringVar(&datacenter, "datacenter", "", "") cmdFlags.StringVar(&token, "token", "", "") cmdFlags.StringVar(&key, "key", "", "") cmdFlags.StringVar(&prefix, "prefix", "", "") cmdFlags.StringVar(&service, "service", "", "") cmdFlags.StringVar(&tag, "tag", "", "") cmdFlags.StringVar(&passingOnly, "passingonly", "", "") cmdFlags.StringVar(&state, "state", "", "") cmdFlags.StringVar(&name, "name", "", "") httpAddr := HTTPAddrFlag(cmdFlags) if err := cmdFlags.Parse(args); err != nil { return 1 } // Check for a type if watchType == "" { c.Ui.Error("Watch type must be specified") c.Ui.Error("") c.Ui.Error(c.Help()) return 1 } // Grab the script to execute if any script := strings.Join(cmdFlags.Args(), " ") // Compile the watch parameters params := make(map[string]interface{}) if watchType != "" { params["type"] = watchType } if datacenter != "" { params["datacenter"] = datacenter } if token != "" { params["token"] = token } if key != "" { params["key"] = key } if prefix != "" { params["prefix"] = prefix } if service != "" { params["service"] = service } if tag != "" { params["tag"] = tag } if state != "" { params["state"] = state } if name != "" { params["name"] = name } if passingOnly != "" { b, err := strconv.ParseBool(passingOnly) if err != nil { c.Ui.Error(fmt.Sprintf("Failed to parse passingonly flag: %s", err)) return 1 } params["passingonly"] = b } // Create the watch wp, err := watch.Parse(params) if err != nil { c.Ui.Error(fmt.Sprintf("%s", err)) return 1 } // Create and test the HTTP client client, err := HTTPClient(*httpAddr) if err != nil { c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err)) return 1 } _, err = client.Agent().NodeName() if err != nil { c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err)) return 1 } // Setup handler // errExit: // 0: false // 1: true errExit := 0 if script == "" { wp.Handler = func(idx uint64, data interface{}) { defer wp.Stop() buf, err := json.MarshalIndent(data, "", " ") if err != nil { c.Ui.Error(fmt.Sprintf("Error encoding output: %s", err)) errExit = 1 } c.Ui.Output(string(buf)) } } else { wp.Handler = func(idx uint64, data interface{}) { // Create the command var buf bytes.Buffer var err error cmd, err := agent.ExecScript(script) if err != nil { c.Ui.Error(fmt.Sprintf("Error executing handler: %s", err)) goto ERR } cmd.Env = append(os.Environ(), "CONSUL_INDEX="+strconv.FormatUint(idx, 10), ) // Encode the input if err = json.NewEncoder(&buf).Encode(data); err != nil { c.Ui.Error(fmt.Sprintf("Error encoding output: %s", err)) goto ERR } cmd.Stdin = &buf cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr // Run the handler if err := cmd.Run(); err != nil { c.Ui.Error(fmt.Sprintf("Error executing handler: %s", err)) goto ERR } return ERR: wp.Stop() errExit = 1 } } // Watch for a shutdown go func() { <-c.ShutdownCh wp.Stop() os.Exit(0) }() // Run the watch if err := wp.Run(*httpAddr); err != nil { c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err)) return 1 } return errExit }