template/funcs.go
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
}
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
}
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 ( " \n \n \n \n \n \n \n \n " , 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 ( " " , name ) } } <- done // Allow the goroutine to exit return " " , fmt . Errorf ( " " , name ) case err := <- done : if err != nil { return " " , fmt . Errorf ( " \n \n \n \n \n \n \n \n " , name , err , stdout . Bytes ( ) , stderr . Bytes ( ) ) } } return strings . TrimSpace ( stdout . String ( ) ) , nil }
// 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.
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 .