github.com/mirantis/virtlet@v1.5.2-0.20191204181327-1659b8a48e9b/pkg/utils/command.go (about) 1 /* 2 Copyright 2018 Mirantis 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package utils 18 19 import ( 20 "bytes" 21 "fmt" 22 "os/exec" 23 "strings" 24 ) 25 26 // Command represents an external command being prepared or run. 27 type Command interface { 28 // Output runs the command and returns its standard output. 29 // If stdin is non-nil, it's passed to the command's standed 30 // input. Any returned error will usually be of type 31 // *ExitError with ExitError.Stderr containing the stderr 32 // output of the command. 33 Run(stdin []byte) ([]byte, error) 34 } 35 36 // Commander is used to run external commands. 37 type Commander interface { 38 // Command returns an isntance of Command to execute the named 39 // program with the given arguments. 40 Command(name string, arg ...string) Command 41 } 42 43 type realCommand struct { 44 *exec.Cmd 45 } 46 47 func (c realCommand) Run(stdin []byte) ([]byte, error) { 48 if stdin != nil { 49 c.Stdin = bytes.NewBuffer(stdin) 50 } 51 out, err := c.Cmd.Output() 52 if err == nil { 53 return out, nil 54 } 55 fullCmd := strings.Join(append([]string{c.Path}, c.Args...), " ") 56 if exitErr, ok := err.(*exec.ExitError); ok { 57 return out, fmt.Errorf("command %s: %v: %s", fullCmd, exitErr, exitErr.Stderr) 58 } 59 return out, fmt.Errorf("command %s: %v", fullCmd, err) 60 } 61 62 type defaultCommander struct{} 63 64 func (c *defaultCommander) Command(name string, arg ...string) Command { 65 return realCommand{exec.Command(name, arg...)} 66 } 67 68 // DefaultCommander is an implementation of Commander that runs the 69 // commands using exec.Command. 70 var DefaultCommander Commander = &defaultCommander{}