Example #1
0
// 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{}, passStdin bool) 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",
	)
	if passStdin {
		if c.verbose {
			c.Ui.Info("Stdin passed to handler process")
		}
		cmd.Stdin = os.Stdin
	} else {
		cmd.Stdin = nil
	}
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	// Start the child process
	c.childLock.Lock()
	if err := cmd.Start(); err != nil {
		c.Ui.Error(fmt.Sprintf("Error starting handler: %s", err))
		c.childLock.Unlock()
		return err
	}

	// Setup the child info
	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
}
Example #2
0
func (c *WatchCommand) Run(args []string) int {
	var watchType, datacenter, token, key, prefix, service, tag, passingOnly, stale, 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(&stale, "stale", "", "")
	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 stale != "" {
		b, err := strconv.ParseBool(stale)
		if err != nil {
			c.Ui.Error(fmt.Sprintf("Failed to parse stale flag: %s", err))
			return 1
		}
		params["stale"] = b
	}
	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
}