github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/worker/uniter/context_linux.go (about) 1 package uniter 2 3 import ( 4 "fmt" 5 "os" 6 "os/exec" 7 "path/filepath" 8 "strings" 9 "strconv" 10 11 "launchpad.net/juju-core/juju/osenv" 12 ) 13 14 15 func (ctx *HookContext) runCharmHook(hookName, charmDir string, env []string) error { 16 hookFile := filepath.Join(charmDir, "hooks", hookName) 17 logger.Infof("Running hook file: %q", hookFile) 18 ps := exec.Command(hookFile) 19 ps.Env = env 20 ps.Dir = charmDir 21 outReader, outWriter, err := os.Pipe() 22 if err != nil { 23 return fmt.Errorf("cannot make logging pipe: %v", err) 24 } 25 ps.Stdout = outWriter 26 ps.Stderr = outWriter 27 hookLogger := &hookLogger{ 28 r: outReader, 29 done: make(chan struct{}), 30 logger: ctx.GetLogger(hookName), 31 } 32 go hookLogger.run() 33 err = ps.Start() 34 outWriter.Close() 35 if err == nil { 36 err = ps.Wait() 37 } 38 hookLogger.stop() 39 if ee, ok := err.(*exec.Error); ok && err != nil { 40 if os.IsNotExist(ee.Err) { 41 // Missing hook is perfectly valid, but worth mentioning. 42 logger.Infof("skipped %q hook (not implemented) -->%q ", hookName, ee.Err) 43 return &missingHookError{hookName} 44 } 45 } 46 return err 47 } 48 49 // hookVars returns an os.Environ-style list of strings necessary to run a hook 50 // such that it can know what environment it's operating in, and can call back 51 // into ctx. 52 func (ctx *HookContext) hookVars(charmDir, toolsDir, socketPath string) []string { 53 vars := []string{ 54 "APT_LISTCHANGES_FRONTEND=none", 55 "DEBIAN_FRONTEND=noninteractive", 56 "PATH=" + toolsDir + ":" + os.Getenv("PATH"), 57 "CHARM_DIR=" + charmDir, 58 "JUJU_CONTEXT_ID=" + ctx.id, 59 "JUJU_AGENT_SOCKET=" + socketPath, 60 "JUJU_UNIT_NAME=" + ctx.unit.Name(), 61 "JUJU_ENV_UUID=" + ctx.uuid, 62 "JUJU_ENV_NAME=" + ctx.envName, 63 "JUJU_API_ADDRESSES=" + strings.Join(ctx.apiAddrs, " "), 64 "JUJU_MUST_REBOOT=" + strconv.Itoa(osenv.MustReboot), 65 } 66 if r, found := ctx.HookRelation(); found { 67 vars = append(vars, "JUJU_RELATION="+r.Name()) 68 vars = append(vars, "JUJU_RELATION_ID="+r.FakeId()) 69 name, _ := ctx.RemoteUnitName() 70 vars = append(vars, "JUJU_REMOTE_UNIT="+name) 71 } 72 vars = append(vars, ctx.proxySettings.AsEnvironmentValues()...) 73 return vars 74 }