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  }