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