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 }