Esempio n. 1
0
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)
}
Esempio n. 2
0
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)
}
Esempio n. 3
0
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
}
Esempio n. 4
0
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
}
Esempio n. 5
0
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)
}
Esempio n. 6
0
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)
}
Esempio n. 7
0
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)
}