Example #1
0
func (s *suite) TestNothingHappensWhenEnvIsSeenAgain(c *gc.C) {
	// This could happen if there's a change to an environment doc but
	// it's otherwise still alive (unlikely but possible).
	st := newStateWithFakeWatcher(s.State)
	uuid := st.ModelUUID()
	otherSt := s.MakeModel(c)
	otherUUID := otherSt.ModelUUID()

	m := modelworkermanager.NewModelWorkerManager(st, s.startEnvWorker, s.dyingEnvWorker, time.Millisecond)
	defer m.Kill()

	// First time: runners started
	st.sendEnvChange(uuid)
	st.sendEnvChange(otherUUID)
	s.seeRunnersStart(c, 2)

	// Second time: no runners started
	st.sendEnvChange(uuid)
	s.checkNoRunnersStart(c)

	destroyEnvironment(c, otherSt)
	st.sendEnvChange(otherUUID)
	s.seeRunnersStart(c, 1)

	st.sendEnvChange(otherUUID)
	s.checkNoRunnersStart(c)
}
Example #2
0
func (s *suite) TestLoopExitKillsRunner(c *gc.C) {
	// If something causes EnvWorkerManager.loop to exit that isn't Kill() then it should stop the runner.
	// Currently the best way to cause this is to make
	// m.st.GetModel(tag) fail with any error other than NotFound
	otherSt := s.MakeModel(c)
	st := newStateWithFailingGetEnvironment(s.State)
	uuid := st.ModelUUID()
	m := modelworkermanager.NewModelWorkerManager(st, s.startEnvWorker, s.dyingEnvWorker, time.Millisecond)
	defer m.Kill()

	// First time: runners started
	st.sendEnvChange(uuid)
	runners := s.seeRunnersStart(c, 1)
	c.Assert(runners[0].killed, jc.IsFalse)

	destroyEnvironment(c, otherSt)
	st.sendEnvChange(otherSt.ModelUUID())
	dyingRunner := s.seeRunnersStart(c, 1)[0]
	c.Assert(dyingRunner.killed, jc.IsFalse)

	// Now we start failing
	st.shouldFail = true
	st.sendEnvChange(uuid)

	// This should kill the manager
	err := waitOrFatal(c, m.Wait)
	c.Assert(err, gc.ErrorMatches, "error loading model .*: unable to GetModel")

	// And that should kill all the runners
	c.Assert(runners[0].killed, jc.IsTrue)
	c.Assert(dyingRunner.killed, jc.IsTrue)
}
Example #3
0
func (s *suite) TestStateIsClosedIfStartEnvWorkersFails(c *gc.C) {
	// If State is not closed when startEnvWorker errors, MgoSuite's
	// dirty socket detection will pick up the leaked socket and
	// panic.
	s.startErr = worker.ErrTerminateAgent // This will make envWorkerManager exit.
	m := modelworkermanager.NewModelWorkerManager(s.State, s.startEnvWorker, s.dyingEnvWorker, time.Millisecond)
	waitOrFatal(c, m.Wait)
}
Example #4
0
func (s *suite) TestStartsWorkersForNewEnv(c *gc.C) {
	m := modelworkermanager.NewModelWorkerManager(s.State, s.startEnvWorker, s.dyingEnvWorker, time.Millisecond)
	defer m.Kill()
	s.seeRunnersStart(c, 1) // Runner for state server env

	// Create another environment and watch a runner be created for it.
	st2 := s.MakeModel(c)
	runner := s.seeRunnersStart(c, 1)[0]
	c.Assert(runner.modelUUID, gc.Equals, st2.ModelUUID())
}
Example #5
0
func (s *suite) TestNonFatalErrorCausesRunnerRestart(c *gc.C) {
	m := modelworkermanager.NewModelWorkerManager(s.State, s.startEnvWorker, s.dyingEnvWorker, time.Millisecond)
	defer m.Kill()
	runner0 := s.seeRunnersStart(c, 1)[0]

	runner0.tomb.Kill(errors.New("trivial"))
	runner0.tomb.Done()

	s.seeRunnersStart(c, 1)
}
Example #6
0
func (s *suite) TestFatalErrorKillsEnvWorkerManager(c *gc.C) {
	m := modelworkermanager.NewModelWorkerManager(s.State, s.startEnvWorker, s.dyingEnvWorker, time.Millisecond)
	runner := s.seeRunnersStart(c, 1)[0]

	runner.tomb.Kill(worker.ErrTerminateAgent)
	runner.tomb.Done()

	err := waitOrFatal(c, m.Wait)
	c.Assert(errors.Cause(err), gc.Equals, worker.ErrTerminateAgent)
}
Example #7
0
func (s *suite) TestNothingHappensWhenUnknownEnvReported(c *gc.C) {
	// This could perhaps happen when an environment is dying just as
	// the EnvWorkerManager is coming up (unlikely but possible).
	st := newStateWithFakeWatcher(s.State)

	m := modelworkermanager.NewModelWorkerManager(st, s.startEnvWorker, s.dyingEnvWorker, time.Millisecond)
	defer m.Kill()

	st.sendEnvChange("unknown-model-uuid")
	s.checkNoRunnersStart(c)

	// Existing environment still works.
	st.sendEnvChange(st.ModelUUID())
	s.seeRunnersStart(c, 1)
}
Example #8
0
func (s *suite) TestWorkerErrorIsPropagatedWhenKilled(c *gc.C) {
	st := newStateWithFakeWatcher(s.State)
	started := make(chan struct{}, 1)
	m := modelworkermanager.NewModelWorkerManager(st, func(modelworkermanager.InitialState, *state.State) (worker.Worker, error) {
		c.Logf("starting worker")
		started <- struct{}{}
		return &errorWhenKilledWorker{
			err: &cmdutil.FatalError{"an error"},
		}, nil
	}, s.dyingEnvWorker, time.Millisecond)
	st.sendEnvChange(st.ModelUUID())
	s.State.StartSync()
	<-started
	m.Kill()
	err := m.Wait()
	c.Assert(err, gc.ErrorMatches, "an error")
}
Example #9
0
func (s *suite) TestStartsWorkersForPreExistingEnvs(c *gc.C) {
	moreState := s.MakeModel(c)

	var seenEnvs []string
	m := modelworkermanager.NewModelWorkerManager(s.State, s.startEnvWorker, s.dyingEnvWorker, time.Millisecond)
	defer m.Kill()
	for _, r := range s.seeRunnersStart(c, 2) {
		seenEnvs = append(seenEnvs, r.modelUUID)
	}

	c.Assert(seenEnvs, jc.SameContents,
		[]string{s.State.ModelUUID(), moreState.ModelUUID()},
	)

	destroyEnvironment(c, moreState)
	dyingRunner := s.seeRunnersStart(c, 1)[0]
	c.Assert(dyingRunner.modelUUID, gc.Equals, moreState.ModelUUID())
}
Example #10
0
func (s *suite) TestKillPropagates(c *gc.C) {
	otherSt := s.MakeModel(c)

	m := modelworkermanager.NewModelWorkerManager(s.State, s.startEnvWorker, s.dyingEnvWorker, time.Millisecond)
	runners := s.seeRunnersStart(c, 2)
	c.Assert(runners[0].killed, jc.IsFalse)
	c.Assert(runners[1].killed, jc.IsFalse)

	destroyEnvironment(c, otherSt)
	dyingRunner := s.seeRunnersStart(c, 1)[0]
	c.Assert(dyingRunner.killed, jc.IsFalse)

	m.Kill()
	err := waitOrFatal(c, m.Wait)
	c.Assert(err, jc.ErrorIsNil)

	c.Assert(runners[0].killed, jc.IsTrue)
	c.Assert(runners[1].killed, jc.IsTrue)
	c.Assert(dyingRunner.killed, jc.IsTrue)
}
Example #11
0
func (s *suite) TestStopsWorkersWhenEnvGoesAway(c *gc.C) {
	m := modelworkermanager.NewModelWorkerManager(s.State, s.startEnvWorker, s.dyingEnvWorker, time.Millisecond)
	defer m.Kill()
	runner0 := s.seeRunnersStart(c, 1)[0]

	// Create an environment and grab the runner for it.
	otherState := s.MakeModel(c)
	runner1 := s.seeRunnersStart(c, 1)[0]

	// Set environment to dying.
	destroyEnvironment(c, otherState)
	s.seeRunnersStart(c, 1) // dying env runner

	// Set environment to dead.
	err := otherState.ProcessDyingModel()
	c.Assert(err, jc.ErrorIsNil)

	// See that the first runner is still running but the runner for
	// the new environment is stopped.
	s.State.StartSync()
	select {
	case <-runner0.tomb.Dead():
		c.Fatal("first runner should not die here")
	case <-runner1.tomb.Dead():
		break
	case <-time.After(testing.LongWait):
		c.Fatal("timed out waiting for runner to die")
	}

	// Make sure the first runner doesn't get stopped.
	s.State.StartSync()
	select {
	case <-runner0.tomb.Dead():
		c.Fatal("first runner should not die here")
	case <-time.After(testing.ShortWait):
		break
	}
}