2022-12-19 03:04:34 +00:00
// Copyright © 2022 Roberto Hidalgo <chinampa@un.rob.mx>
2022-12-31 05:53:24 +00:00
// SPDX-License-Identifier: Apache-2.0
2022-12-19 03:04:34 +00:00
package exec
import (
"bytes"
"context"
"fmt"
os_exec "os/exec"
"strings"
"time"
2022-12-31 05:53:24 +00:00
"git.rob.mx/nidito/chinampa/pkg/errors"
2022-12-19 03:04:34 +00:00
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// ExecFunc is replaced in tests.
var ExecFunc = WithSubshell
func WithSubshell ( ctx context . Context , env [ ] string , executable string , args ... string ) ( bytes . Buffer , bytes . Buffer , error ) {
cmd := os_exec . CommandContext ( ctx , executable , args ... ) // #nosec G204
var stdout bytes . Buffer
cmd . Stdout = & stdout
var stderr bytes . Buffer
cmd . Stderr = & stderr
cmd . Env = env
return stdout , stderr , cmd . Run ( )
}
// Exec runs a subprocess and returns a list of lines from stdout.
2023-03-20 06:15:53 +00:00
func Exec ( name string , args [ ] string , env [ ] string , timeout time . Duration , log * logrus . Entry ) ( [ ] string , cobra . ShellCompDirective , error ) {
2022-12-19 03:04:34 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , timeout )
defer cancel ( ) // The cancel should be deferred so resources are cleaned up
2023-03-20 06:15:53 +00:00
log . Tracef ( "executing a subshell for %s" , args )
2022-12-19 03:04:34 +00:00
executable := args [ 0 ]
args = args [ 1 : ]
stdout , _ , err := ExecFunc ( ctx , env , executable , args ... )
if ctx . Err ( ) == context . DeadlineExceeded {
2023-03-20 06:15:53 +00:00
log . Warn ( "Sub-command timed out" )
log . Debugf ( "timeout running %s %s: %s" , executable , args , stdout . String ( ) )
2022-12-19 03:04:34 +00:00
return [ ] string { } , cobra . ShellCompDirectiveError , fmt . Errorf ( "timed out resolving %s %s" , executable , args )
}
if err != nil {
2023-03-20 06:15:53 +00:00
log . Debugf ( "error running %s %s: %s" , executable , args , err )
2022-12-19 03:04:34 +00:00
return [ ] string { } , cobra . ShellCompDirectiveError , errors . BadArguments { Msg : fmt . Sprintf ( "could not validate argument for command %s, ran <%s %s> failed: %s" , name , executable , strings . Join ( args , " " ) , err ) }
}
2023-03-20 06:15:53 +00:00
log . Tracef ( "finished running %s %s: %s" , executable , args , stdout . String ( ) )
2022-12-19 03:04:34 +00:00
return strings . Split ( strings . TrimSuffix ( stdout . String ( ) , "\n" ) , "\n" ) , cobra . ShellCompDirectiveDefault , nil
}