code: func plugin(name string, args ...string) (string, error) {
  	if name == "" {
  		return "", nil
  	}
  
  	stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
  
  	// Strip and trim each arg or else some plugins get confused with the newline
  	// characters
  	jsons := make([]string, 0, len(args))
  	for _, arg := range args {
  		if v := strings.TrimSpace(arg); v != "" {
  			jsons = append(jsons, v)
  		}
  	}
  
  	cmd := exec.Command(name, jsons...)
  	cmd.Stdout = stdout
  	cmd.Stderr = stderr
  	if err := cmd.Start(); err != nil {
  		return "", fmt.Errorf("exec %q: %s\n\nstdout:\n\n%s\n\nstderr:\n\n%s",
  			name, err, stdout.Bytes(), stderr.Bytes())
  	}
  
  	done := make(chan error, 1)
  	go func() {
  		done <- cmd.Wait()
  	}()
  
  	select {
  	case <-time.After(30 * time.Second):
  		if cmd.Process != nil {
  			if err := cmd.Process.Kill(); err != nil {
  				return "", fmt.Errorf("exec %q: failed to kill", name)
  			}
  		}
  		<-done // Allow the goroutine to exit
  		return "", fmt.Errorf("exec %q: did not finish in 30s", name)
  	case err := <-done:
  		if err != nil {
  			return "", fmt.Errorf("exec %q: %s\n\nstdout:\n\n%s\n\nstderr:\n\n%s",
  				name, err, stdout.Bytes(), stderr.Bytes())
  		}
  	}
  
  	return strings.TrimSpace(stdout.String()), nil
  }
docs: // plugin executes a subprocess as the given command string. It is assumed the
  // resulting command returns JSON which is then parsed and returned as the
  // value for use in the template.