github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/worker/uniter/runner/args.go (about)

     1  // Copyright 2012-2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package runner
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"os/exec"
    10  	"path/filepath"
    11  	"strings"
    12  
    13  	"github.com/juju/juju/version"
    14  )
    15  
    16  var windowsSuffixOrder = []string{
    17  	".ps1",
    18  	".cmd",
    19  	".bat",
    20  	".exe",
    21  }
    22  
    23  func lookPath(hook string) (string, error) {
    24  	hookFile, err := exec.LookPath(hook)
    25  	if err != nil {
    26  		if ee, ok := err.(*exec.Error); ok && os.IsNotExist(ee.Err) {
    27  			return "", &missingHookError{hook}
    28  		}
    29  		return "", err
    30  	}
    31  	return hookFile, nil
    32  }
    33  
    34  // searchHook will search, in order, hooks suffixed with extensions
    35  // in windowsSuffixOrder. As windows cares about extensions to determine
    36  // how to execute a file, we will allow several suffixes, with powershell
    37  // being default.
    38  func searchHook(charmDir, hook string) (string, error) {
    39  	hookFile := filepath.Join(charmDir, hook)
    40  	if version.Current.OS != version.Windows {
    41  		// we are not running on windows,
    42  		// there is no need to look for suffixed hooks
    43  		return lookPath(hookFile)
    44  	}
    45  	for _, suffix := range windowsSuffixOrder {
    46  		file := fmt.Sprintf("%s%s", hookFile, suffix)
    47  		foundHook, err := lookPath(file)
    48  		if err != nil {
    49  			if IsMissingHookError(err) {
    50  				// look for next suffix
    51  				continue
    52  			}
    53  			return "", err
    54  		}
    55  		return foundHook, nil
    56  	}
    57  	return "", &missingHookError{hook}
    58  }
    59  
    60  // hookCommand constructs an appropriate command to be passed to
    61  // exec.Command(). The exec package uses cmd.exe as default on windows.
    62  // cmd.exe does not know how to execute ps1 files by default, and
    63  // powershell needs a few flags to allow execution (-ExecutionPolicy)
    64  // and propagate error levels (-File). .cmd and .bat files can be run
    65  // directly.
    66  func hookCommand(hook string) []string {
    67  	if version.Current.OS != version.Windows {
    68  		// we are not running on windows,
    69  		// just return the hook name
    70  		return []string{hook}
    71  	}
    72  	if strings.HasSuffix(hook, ".ps1") {
    73  		return []string{
    74  			"powershell.exe",
    75  			"-NonInteractive",
    76  			"-ExecutionPolicy",
    77  			"RemoteSigned",
    78  			"-File",
    79  			hook,
    80  		}
    81  	}
    82  	return []string{hook}
    83  }