github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/worker/uniter/context_windows.go (about)

     1  package uniter
     2  
     3  import (
     4      "fmt"
     5      "os"
     6      "os/exec"
     7      "path/filepath"
     8      "strings"
     9      "strconv"
    10      // "syscall"
    11  
    12      "launchpad.net/juju-core/juju/osenv"
    13  )
    14  
    15  var suffixOrder = []string{
    16      "ps1",
    17      "cmd",
    18      "bat",
    19  }
    20  
    21  func (ctx *HookContext) getScript (hookFile string) (string, string) {
    22      for i := range suffixOrder {
    23          file := hookFile + fmt.Sprintf(".%s", suffixOrder[i])
    24          if _, err := os.Stat(file); err == nil {
    25              return file, suffixOrder[i]
    26          }
    27      }
    28      return hookFile, ""
    29  }
    30  
    31  func (ctx *HookContext) getCommand (hookFile, suffix string) []string {
    32      var command []string
    33      if suffix == "ps1"{
    34          command = append(command, "powershell")
    35          command = append(command, "-NonInteractive")
    36          command = append(command, "-ExecutionPolicy")
    37          command = append(command, "RemoteSigned")
    38          command = append(command, "-File")
    39          command = append(command, hookFile)
    40          return command
    41      }
    42      command = append(command, hookFile)
    43      return command
    44  }
    45  
    46  func (ctx *HookContext) runCharmHook(hookName, charmDir string, env []string) error {
    47      hookFile := filepath.Join(charmDir, "hooks", hookName)
    48      hookFileSlash := filepath.ToSlash(hookFile)
    49      // we get the correct file name and the suffix
    50      suffixedHook, suffix := ctx.getScript(hookFileSlash)
    51      com := ctx.getCommand(suffixedHook, suffix)
    52      logger.Infof("Running hook file: %q", hookFileSlash)
    53  
    54      ps := exec.Command(com[0], com[1:]...)
    55      ps.Env = env
    56      ps.Dir = charmDir
    57      outReader, outWriter, err := os.Pipe()
    58      if err != nil {
    59          return fmt.Errorf("cannot make logging pipe: %v", err)
    60      }
    61      ps.Stdout = outWriter
    62      ps.Stderr = outWriter
    63      hookLogger := &hookLogger{
    64          r:      outReader,
    65          done:   make(chan struct{}),
    66          logger: ctx.GetLogger(hookName),
    67      }
    68      go hookLogger.run()
    69      err = ps.Start()
    70      outWriter.Close()
    71      if err == nil {
    72          err = ps.Wait()
    73      }
    74      hookLogger.stop()
    75      if ee, ok := err.(*exec.Error); ok && err != nil {
    76          if os.IsNotExist(ee.Err) {
    77              // Missing hook is perfectly valid, but worth mentioning.
    78              logger.Infof("skipped %q hook (not implemented) -->%q ", hookName, ee.Err)
    79              return &missingHookError{hookName}
    80          }
    81      }
    82      return err
    83  }
    84  
    85  func (ctx *HookContext) hookVars(charmDir, toolsDir, socketPath string) []string {
    86      environ := os.Environ()
    87      for i:=0; i<len(environ); i++ {
    88          if strings.ToUpper(environ[i][:5]) == "PATH=" {
    89              environ[i] = fmt.Sprintf("Path=%s", filepath.FromSlash(toolsDir) + ";" + os.Getenv("PATH"))
    90          }
    91          if strings.ToUpper(environ[i][:13]) == "PSMODULEPATH=" {
    92              charmModules := filepath.Join(charmDir, "Modules")
    93              hookModules := filepath.Join(charmDir, "hooks", "Modules")
    94              psModulePath := os.Getenv("PSMODULEPATH") + ";" + charmModules + ";" + hookModules
    95              environ[i] = fmt.Sprintf("PSModulePath=%s", psModulePath)
    96          }
    97      }
    98  
    99      environ = append(environ, "CHARM_DIR=" + filepath.FromSlash(charmDir))
   100      environ = append(environ, "JUJU_CONTEXT_ID=" + ctx.id)
   101      environ = append(environ, "JUJU_AGENT_SOCKET=" + socketPath)
   102      environ = append(environ, "JUJU_UNIT_NAME=" + ctx.unit.Name())
   103      environ = append(environ, "JUJU_ENV_UUID=" + ctx.uuid)
   104      environ = append(environ, "JUJU_ENV_NAME=" + ctx.envName)
   105      environ = append(environ, "JUJU_API_ADDRESSES=" + strings.Join(ctx.apiAddrs, " "))
   106      environ = append(environ, "JUJU_MUST_REBOOT=" + strconv.Itoa(osenv.MustReboot))
   107  
   108      if r, found := ctx.HookRelation(); found {
   109          environ = append(environ, "JUJU_RELATION="+r.Name())
   110          environ = append(environ, "JUJU_RELATION_ID="+r.FakeId())
   111          name, _ := ctx.RemoteUnitName()
   112          environ = append(environ, "JUJU_REMOTE_UNIT="+name)
   113      }
   114      return environ
   115  }