func (s *cmdControllerSuite) TestSystemKillCallsEnvironDestroyOnHostedEnviron(c *gc.C) { st := s.Factory.MakeEnvironment(c, &factory.EnvParams{ Name: "foo", }) defer st.Close() st.SwitchBlockOn(state.DestroyBlock, "TestBlockDestroyEnvironment") st.Close() opc := make(chan dummy.Operation, 200) dummy.Listen(opc) conn, err := juju.NewAPIState(s.AdminUserTag(c), s.Environ, api.DialOpts{}) c.Assert(err, jc.ErrorIsNil) s.AddCleanup(func(*gc.C) { conn.Close() }) client := undertakerapi.NewClient(conn) startTime := time.Date(2015, time.September, 1, 17, 2, 1, 0, time.UTC) mClock := testing.NewClock(startTime) undertaker.NewUndertaker(client, mClock) store, err := configstore.Default() _, err = store.ReadInfo("dummyenv") c.Assert(err, jc.ErrorIsNil) s.run(c, "kill-controller", "dummyenv", "-y") // Ensure that Destroy was called on the hosted environment ... opRecvTimeout(c, st, opc, dummy.OpDestroy{}) // ... and that the configstore was removed. _, err = store.ReadInfo("dummyenv") c.Assert(err, jc.Satisfies, errors.IsNotFound) }
func checkInvalid(c *gc.C, config undertaker.Config, message string) { check := func(err error) { c.Check(err, jc.Satisfies, errors.IsNotValid) c.Check(err, gc.ErrorMatches, message) } err := config.Validate() check(err) worker, err := undertaker.NewUndertaker(config) c.Check(worker, gc.IsNil) check(err) }
func (fix fixture) run(c *gc.C, test func(worker.Worker)) *testing.Stub { stub := &testing.Stub{} environ := &mockEnviron{ stub: stub, } facade := &mockFacade{ stub: stub, info: fix.info, } stub.SetErrors(fix.errors...) w, err := undertaker.NewUndertaker(undertaker.Config{ Facade: facade, Environ: environ, }) c.Assert(err, jc.ErrorIsNil) defer fix.cleanup(c, w) test(w) return stub }
func (fix fixture) run(c *gc.C, test func(worker.Worker, *coretesting.Clock)) *testing.Stub { stub := &testing.Stub{} environ := &mockEnviron{ stub: stub, } facade := &mockFacade{ stub: stub, info: fix.info, } clock := coretesting.NewClock(time.Now()) stub.SetErrors(fix.errors...) w, err := undertaker.NewUndertaker(undertaker.Config{ Facade: facade, Environ: environ, Clock: clock, RemoveDelay: RIPTime, }) c.Assert(err, jc.ErrorIsNil) defer fix.cleanup(c, w) test(w, clock) return stub }
func (s *undertakerSuite) TestAPICalls(c *gc.C) { cfg, uuid := dummyCfgAndUUID(c) client := &mockClient{ calls: make(chan string), mockEnviron: clientEnviron{ Life: state.Dying, UUID: uuid, HasMachinesAndServices: true, }, cfg: cfg, watcher: &mockEnvironResourceWatcher{ events: make(chan struct{}), }, } startTime := time.Date(2015, time.September, 1, 17, 2, 1, 0, time.UTC) mClock := &clock{ Clock: testing.NewClock(startTime), } wg := sync.WaitGroup{} wg.Add(1) go func() { defer wg.Done() for _, test := range []struct { call string callback func() }{{ call: "EnvironInfo", }, { call: "ProcessDyingEnviron", callback: func() { c.Check(client.mockEnviron.Life, gc.Equals, state.Dying) c.Check(client.mockEnviron.TimeOfDeath, gc.IsNil) client.mockEnviron.HasMachinesAndServices = false client.watcher.(*mockEnvironResourceWatcher).events <- struct{}{} mClock.advanceAfterNextNow(undertaker.RIPTime) }}, { call: "ProcessDyingEnviron", callback: func() { c.Check(client.mockEnviron.Life, gc.Equals, state.Dead) c.Check(client.mockEnviron.TimeOfDeath, gc.NotNil) }}, { call: "RemoveEnviron", callback: func() { oneDayLater := startTime.Add(undertaker.RIPTime) c.Check(mClock.Now().Equal(oneDayLater), jc.IsTrue) c.Check(client.mockEnviron.Removed, gc.Equals, true) }}, } { select { case call := <-client.calls: c.Check(call, gc.Equals, test.call) if test.callback != nil { test.callback() } case <-time.After(testing.LongWait): c.Fatalf("timed out waiting for API call: %q", test.call) } } }() worker := undertaker.NewUndertaker(client, mClock) defer worker.Kill() wg.Wait() assertNoMoreCalls(c, client) }
func (s *undertakerSuite) TestRemoveEnvironOnRebootCalled(c *gc.C) { startTime := time.Date(2015, time.September, 1, 17, 2, 1, 0, time.UTC) mClock := testing.NewClock(startTime) halfDayEarlier := mClock.Now().Add(-12 * time.Hour) cfg, uuid := dummyCfgAndUUID(c) client := &mockClient{ calls: make(chan string, 1), // Mimic the situation where the worker is started after the // environment has been set to dead 12hrs ago. mockEnviron: clientEnviron{ Life: state.Dead, UUID: uuid, TimeOfDeath: &halfDayEarlier, }, cfg: cfg, } wg := sync.WaitGroup{} wg.Add(1) // We expect RemoveEnviron not to be called, as we have to wait another // 12hrs. go func() { defer wg.Done() for _, test := range []struct { call string callback func() }{{ call: "EnvironInfo", callback: func() { // As environ was set to dead 12hrs earlier, assert that the // undertaker picks up where it left off and RemoveEnviron // is called 12hrs later. mClock.Advance(12 * time.Hour) }, }, { call: "RemoveEnviron", callback: func() { c.Assert(client.mockEnviron.Removed, gc.Equals, true) }}, } { select { case call := <-client.calls: c.Assert(call, gc.Equals, test.call) if test.callback != nil { test.callback() } case <-time.After(testing.LongWait): c.Fatalf("timed out waiting for API call: %q", test.call) } } }() worker := undertaker.NewUndertaker(client, mClock) defer worker.Kill() wg.Wait() assertNoMoreCalls(c, client) }
func (s *undertakerSuite) TestRemoveEnvironDocsNotCalledForStateServer(c *gc.C) { mockWatcher := &mockEnvironResourceWatcher{ events: make(chan struct{}, 1), } uuid, err := utils.NewUUID() c.Assert(err, jc.ErrorIsNil) client := &mockClient{ calls: make(chan string, 1), mockEnviron: clientEnviron{ Life: state.Dying, UUID: uuid.String(), IsSystem: true, }, watcher: mockWatcher, } startTime := time.Date(2015, time.September, 1, 17, 2, 1, 0, time.UTC) mClock := &clock{ Clock: testing.NewClock(startTime), } wg := sync.WaitGroup{} wg.Add(1) go func() { defer wg.Done() for _, test := range []struct { call string callback func() }{{ call: "EnvironInfo", callback: func() { mockWatcher.events <- struct{}{} }, }, { call: "ProcessDyingEnviron", callback: func() { c.Assert(client.mockEnviron.Life, gc.Equals, state.Dead) c.Assert(client.mockEnviron.TimeOfDeath, gc.NotNil) mClock.advanceAfterNextNow(undertaker.RIPTime) }, }, } { select { case call := <-client.calls: c.Assert(call, gc.Equals, test.call) if test.callback != nil { test.callback() } case <-time.After(testing.LongWait): c.Fatalf("timed out waiting for API call: %q", test.call) } } }() worker := undertaker.NewUndertaker(client, mClock) defer worker.Kill() wg.Wait() assertNoMoreCalls(c, client) }