Exemple #1
0
func (w *collect) do() error {
	logger.Tracef("recording metrics")

	config := w.agent.CurrentConfig()
	tag := config.Tag()
	unitTag, ok := tag.(names.UnitTag)
	if !ok {
		return errors.Errorf("expected a unit tag, got %v", tag)
	}
	paths := uniter.NewWorkerPaths(config.DataDir(), unitTag, "metrics-collect")

	recorder, err := newRecorder(unitTag, paths, w.unitCharmLookup, w.metricFactory)
	if errors.Cause(err) == errMetricsNotDefined {
		logger.Tracef("%v", err)
		return nil
	} else if err != nil {
		return errors.Annotate(err, "failed to instantiate metric recorder")
	}

	ctx := newHookContext(unitTag.String(), recorder)
	err = ctx.addJujuUnitsMetric()
	if err != nil {
		return errors.Annotatef(err, "error adding 'juju-units' metric")
	}

	r := runner.NewRunner(ctx, paths)
	err = r.RunHook(string(hooks.CollectMetrics))
	if err != nil {
		return errors.Annotatef(err, "error running 'collect-metrics' hook")
	}
	return nil
}
Exemple #2
0
func (s *RunHookSuite) TestRunHook(c *gc.C) {
	uuid, err := utils.NewUUID()
	c.Assert(err, jc.ErrorIsNil)
	for i, t := range runHookTests {
		c.Logf("\ntest %d: %s; perm %v", i, t.summary, t.spec.perm)
		ctx := s.getHookContext(c, uuid.String(), t.relid, t.remote, noProxies)
		paths := NewRealPaths(c)
		rnr := runner.NewRunner(ctx, paths)
		var hookExists bool
		if t.spec.perm != 0 {
			spec := t.spec
			spec.dir = "hooks"
			spec.name = hookName
			c.Logf("makeCharm %#v", spec)
			makeCharm(c, spec, paths.charm)
			hookExists = true
		}
		t0 := time.Now()
		err := rnr.RunHook("something-happened")
		if t.err == "" && hookExists {
			c.Assert(err, jc.ErrorIsNil)
		} else if !hookExists {
			c.Assert(runner.IsMissingHookError(err), jc.IsTrue)
		} else {
			c.Assert(err, gc.ErrorMatches, t.err)
		}
		if t.spec.background != "" && time.Now().Sub(t0) > 5*time.Second {
			c.Errorf("background process holding up hook execution")
		}
	}
}
Exemple #3
0
func (s *RunCommandSuite) TestRunCommandsEnvStdOutAndErrAndRC(c *gc.C) {
	// TODO(bogdanteleaga): powershell throws another exit status code when
	// outputting to stderr using Write-Error. Either find another way to
	// output to stderr or change the checks
	if runtime.GOOS == "windows" {
		c.Skip("bug 1403084: Have to figure out a good way to output to stderr from powershell")
	}
	ctx, err := s.contextFactory.HookContext(hook.Info{Kind: hooks.ConfigChanged})
	c.Assert(err, jc.ErrorIsNil)
	paths := runnertesting.NewRealPaths(c)
	runner := runner.NewRunner(ctx, paths)

	commands := `
echo $JUJU_CHARM_DIR
echo this is standard err >&2
exit 42
`
	result, err := runner.RunCommands(commands)
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(result.Code, gc.Equals, 42)
	c.Assert(strings.TrimRight(string(result.Stdout), "\r\n"), gc.Equals, paths.GetCharmDir())
	c.Assert(strings.TrimRight(string(result.Stderr), "\r\n"), gc.Equals, "this is standard err")
	c.Assert(ctx.GetProcess(), gc.NotNil)
}
Exemple #4
0
func (s *RunHookSuite) TestRunHook(c *gc.C) {
	for i, t := range runHookTests {
		c.Logf("\ntest %d: %s; perm %v", i, t.summary, t.spec.perm)
		ctx, err := s.contextFactory.HookContext(hook.Info{Kind: hooks.ConfigChanged})
		c.Assert(err, jc.ErrorIsNil)

		paths := runnertesting.NewRealPaths(c)
		rnr := runner.NewRunner(ctx, paths)
		var hookExists bool
		if t.spec.perm != 0 {
			spec := t.spec
			spec.dir = "hooks"
			spec.name = hookName
			c.Logf("makeCharm %#v", spec)
			makeCharm(c, spec, paths.GetCharmDir())
			hookExists = true
		}
		t0 := time.Now()
		err = rnr.RunHook("something-happened")
		if t.err == "" && hookExists {
			c.Assert(err, jc.ErrorIsNil)
		} else if !hookExists {
			c.Assert(context.IsMissingHookError(err), jc.IsTrue)
		} else {
			c.Assert(err, gc.ErrorMatches, t.err)
		}
		if t.spec.background != "" && time.Now().Sub(t0) > 5*time.Second {
			c.Errorf("background process holding up hook execution")
		}
	}
}
Exemple #5
0
func (s *RunMockContextSuite) TestRunActionParamsFailure(c *gc.C) {
	expectErr := errors.New("stork")
	ctx := &MockContext{
		actionData:      &context.ActionData{},
		actionParamsErr: expectErr,
	}
	actualErr := runner.NewRunner(ctx, s.paths).RunAction("juju-run")
	c.Assert(errors.Cause(actualErr), gc.Equals, expectErr)
}
Exemple #6
0
func (s *RunMockContextSuite) TestRunCommandsFlushFailure(c *gc.C) {
	expectErr := errors.New("pew pew pew")
	ctx := &MockContext{
		flushResult: expectErr,
	}
	_, actualErr := runner.NewRunner(ctx, s.paths).RunCommands(echoPidScript + "; exit 123")
	c.Assert(actualErr, gc.Equals, expectErr)
	c.Assert(ctx.flushBadge, gc.Equals, "run commands")
	c.Assert(ctx.flushFailure, gc.IsNil) // exit code in _ result, as tested elsewhere
	s.assertRecordedPid(c, ctx.expectPid)
}
Exemple #7
0
func (s *RunMockContextSuite) TestRunCommandsFlushSuccess(c *gc.C) {
	expectErr := errors.New("pew pew pew")
	ctx := &MockContext{
		flushResult: expectErr,
	}
	_, actualErr := runner.NewRunner(ctx, s.paths).RunCommands(echoPidScript)
	c.Assert(actualErr, gc.Equals, expectErr)
	c.Assert(ctx.flushBadge, gc.Equals, "run commands")
	c.Assert(ctx.flushFailure, gc.IsNil)
	s.assertRecordedPid(c, ctx.expectPid)
}
Exemple #8
0
func (s *RunMockContextSuite) TestRunHookFlushSuccess(c *gc.C) {
	expectErr := errors.New("pew pew pew")
	ctx := &MockContext{
		flushResult: expectErr,
	}
	makeCharm(c, hookSpec{
		dir:  "hooks",
		name: hookName,
		perm: 0700,
	}, s.paths.GetCharmDir())
	actualErr := runner.NewRunner(ctx, s.paths).RunHook("something-happened")
	c.Assert(actualErr, gc.Equals, expectErr)
	c.Assert(ctx.flushBadge, gc.Equals, "something-happened")
	c.Assert(ctx.flushFailure, gc.IsNil)
	s.assertRecordedPid(c, ctx.expectPid)
}
Exemple #9
0
func (s *RunMockContextSuite) TestRunHookFlushFailure(c *gc.C) {
	expectErr := errors.New("pew pew pew")
	ctx := &MockContext{
		flushResult: expectErr,
	}
	makeCharm(c, hookSpec{
		dir:  "hooks",
		name: hookName,
		perm: 0700,
		code: 123,
	}, s.paths.charm)
	actualErr := runner.NewRunner(ctx, s.paths).RunHook("something-happened")
	c.Assert(actualErr, gc.Equals, expectErr)
	c.Assert(ctx.flushBadge, gc.Equals, "something-happened")
	c.Assert(ctx.flushFailure, gc.ErrorMatches, "exit status 123")
	s.assertRecordedPid(c, ctx.expectPid)
}
Exemple #10
0
func (s *RunMockContextSuite) TestRunActionSuccessful(c *gc.C) {
	ctx := &MockContext{
		actionData: &context.ActionData{},
		actionParams: map[string]interface{}{
			"command": "echo 1",
			"timeout": 0,
		},
		actionResults: map[string]interface{}{},
	}
	err := runner.NewRunner(ctx, s.paths).RunAction("juju-run")
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(ctx.flushBadge, gc.Equals, "juju-run")
	c.Assert(ctx.flushFailure, gc.IsNil)
	c.Assert(ctx.actionResults["Code"], gc.Equals, "0")
	c.Assert(strings.TrimRight(ctx.actionResults["Stdout"].(string), "\r\n"), gc.Equals, "1")
	c.Assert(ctx.actionResults["Stderr"], gc.Equals, "")
}
Exemple #11
0
func (w *hookRunner) RunHook(code, info string, interrupt <-chan struct{}) (runErr error) {
	unitTag := w.tag
	paths := uniter.NewPaths(w.config.DataDir(), unitTag)
	ctx := NewLimitedContext(unitTag.String())
	ctx.SetEnvVars(map[string]string{
		"JUJU_METER_STATUS": code,
		"JUJU_METER_INFO":   info,
	})
	r := runner.NewRunner(ctx, paths)
	releaser, err := w.acquireExecutionLock(interrupt)
	if err != nil {
		return errors.Annotate(err, "failed to acquire machine lock")
	}
	// Defer the logging first so it is executed after the Release. LIFO.
	defer logger.Debugf("release lock %q for meter status hook execution", w.machineLockName)
	defer releaser.Release()
	return r.RunHook(string(hooks.MeterStatusChanged))
}
Exemple #12
0
func (h *hookRunner) do(recorder spool.MetricRecorder) error {
	h.m.Lock()
	defer h.m.Unlock()
	logger.Tracef("recording metrics")

	ctx := newHookContext(h.unitTag, recorder)
	err := ctx.addJujuUnitsMetric()
	if err != nil {
		return errors.Annotatef(err, "error adding 'juju-units' metric")
	}

	r := runner.NewRunner(ctx, h.paths)
	err = r.RunHook(string(hooks.CollectMetrics))
	if err != nil {
		return errors.Annotatef(err, "error running 'collect-metrics' hook")
	}
	return nil
}
Exemple #13
0
func (s *RunMockContextSuite) TestRunActionCancelled(c *gc.C) {
	timeout := 1 * time.Nanosecond
	ctx := &MockContext{
		actionData: &context.ActionData{},
		actionParams: map[string]interface{}{
			"command": "sleep 10",
			"timeout": float64(timeout.Nanoseconds()),
		},
		actionResults: map[string]interface{}{},
	}
	err := runner.NewRunner(ctx, s.paths).RunAction("juju-run")
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(ctx.flushBadge, gc.Equals, "juju-run")
	c.Assert(ctx.flushFailure, gc.Equals, exec.ErrCancelled)
	c.Assert(ctx.actionResults["Code"], gc.Equals, nil)
	c.Assert(ctx.actionResults["Stdout"], gc.Equals, nil)
	c.Assert(ctx.actionResults["Stderr"], gc.Equals, nil)
}
Exemple #14
0
func (w *hookRunner) RunHook(code, info string, interrupt <-chan struct{}) (runErr error) {
	unitTag := w.tag
	paths := uniter.NewPaths(w.config.DataDir(), unitTag)
	ctx := NewLimitedContext(unitTag.String())
	ctx.SetEnvVars(map[string]string{
		"JUJU_METER_STATUS": code,
		"JUJU_METER_INFO":   info,
	})
	r := runner.NewRunner(ctx, paths)
	unlock, err := w.acquireExecutionLock(interrupt)
	if err != nil {
		return errors.Annotate(err, "failed to acquire machine lock")
	}
	defer func() {
		unlockErr := unlock()
		if unlockErr != nil {
			logger.Criticalf("hook run resulted in error %v; unlock failure error: %v", runErr, unlockErr)
		}
	}()
	return r.RunHook(string(hooks.MeterStatusChanged))
}