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{}