github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/exec/exec.go (about)

     1  /*
     2  Copyright 2014 The Kubernetes Authors All rights reserved.
     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 exec
    18  
    19  import (
    20  	osexec "os/exec"
    21  	"syscall"
    22  )
    23  
    24  // ErrExecutableNotFound is returned if the executable is not found.
    25  var ErrExecutableNotFound = osexec.ErrNotFound
    26  
    27  // Interface is an interface that presents a subset of the os/exec API.  Use this
    28  // when you want to inject fakeable/mockable exec behavior.
    29  type Interface interface {
    30  	// Command returns a Cmd instance which can be used to run a single command.
    31  	// This follows the pattern of package os/exec.
    32  	Command(cmd string, args ...string) Cmd
    33  
    34  	// LookPath wraps os/exec.LookPath
    35  	LookPath(file string) (string, error)
    36  }
    37  
    38  // Cmd is an interface that presents an API that is very similar to Cmd from os/exec.
    39  // As more functionality is needed, this can grow.  Since Cmd is a struct, we will have
    40  // to replace fields with get/set method pairs.
    41  type Cmd interface {
    42  	// CombinedOutput runs the command and returns its combined standard output
    43  	// and standard error.  This follows the pattern of package os/exec.
    44  	CombinedOutput() ([]byte, error)
    45  	SetDir(dir string)
    46  }
    47  
    48  // ExitError is an interface that presents an API similar to os.ProcessState, which is
    49  // what ExitError from os/exec is.  This is designed to make testing a bit easier and
    50  // probably loses some of the cross-platform properties of the underlying library.
    51  type ExitError interface {
    52  	String() string
    53  	Error() string
    54  	Exited() bool
    55  	ExitStatus() int
    56  }
    57  
    58  // Implements Interface in terms of really exec()ing.
    59  type executor struct{}
    60  
    61  // New returns a new Interface which will os/exec to run commands.
    62  func New() Interface {
    63  	return &executor{}
    64  }
    65  
    66  // Command is part of the Interface interface.
    67  func (executor *executor) Command(cmd string, args ...string) Cmd {
    68  	return (*cmdWrapper)(osexec.Command(cmd, args...))
    69  }
    70  
    71  // LookPath is part of the Interface interface
    72  func (executor *executor) LookPath(file string) (string, error) {
    73  	return osexec.LookPath(file)
    74  }
    75  
    76  // Wraps exec.Cmd so we can capture errors.
    77  type cmdWrapper osexec.Cmd
    78  
    79  func (cmd *cmdWrapper) SetDir(dir string) {
    80  	cmd.Dir = dir
    81  }
    82  
    83  // CombinedOutput is part of the Cmd interface.
    84  func (cmd *cmdWrapper) CombinedOutput() ([]byte, error) {
    85  	out, err := (*osexec.Cmd)(cmd).CombinedOutput()
    86  	if err != nil {
    87  		if ee, ok := err.(*osexec.ExitError); ok {
    88  			// Force a compile fail if exitErrorWrapper can't convert to ExitError.
    89  			var x ExitError = &exitErrorWrapper{ee}
    90  			return out, x
    91  		}
    92  		if ee, ok := err.(*osexec.Error); ok {
    93  			if ee.Err == osexec.ErrNotFound {
    94  				return out, ErrExecutableNotFound
    95  			}
    96  		}
    97  		return out, err
    98  	}
    99  	return out, nil
   100  }
   101  
   102  // exitErrorWrapper is an implementation of ExitError in terms of os/exec ExitError.
   103  // Note: standard exec.ExitError is type *os.ProcessState, which already implements Exited().
   104  type exitErrorWrapper struct {
   105  	*osexec.ExitError
   106  }
   107  
   108  // ExitStatus is part of the ExitError interface.
   109  func (eew exitErrorWrapper) ExitStatus() int {
   110  	ws, ok := eew.Sys().(syscall.WaitStatus)
   111  	if !ok {
   112  		panic("can't call ExitStatus() on a non-WaitStatus exitErrorWrapper")
   113  	}
   114  	return ws.ExitStatus()
   115  }