github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/worker/migrationminion/worker_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package migrationminion_test
     5  
     6  import (
     7  	"sync"
     8  	"time"
     9  
    10  	"github.com/juju/errors"
    11  	jujutesting "github.com/juju/testing"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/agent"
    16  	"github.com/juju/juju/core/migration"
    17  	"github.com/juju/juju/network"
    18  	coretesting "github.com/juju/juju/testing"
    19  	"github.com/juju/juju/watcher"
    20  	"github.com/juju/juju/worker"
    21  	"github.com/juju/juju/worker/fortress"
    22  	"github.com/juju/juju/worker/migrationminion"
    23  	"github.com/juju/juju/worker/workertest"
    24  )
    25  
    26  type Suite struct {
    27  	coretesting.BaseSuite
    28  	stub   *jujutesting.Stub
    29  	client *stubMinionClient
    30  	guard  *stubGuard
    31  	agent  *stubAgent
    32  }
    33  
    34  var _ = gc.Suite(&Suite{})
    35  
    36  func (s *Suite) SetUpTest(c *gc.C) {
    37  	s.BaseSuite.SetUpTest(c)
    38  	s.stub = new(jujutesting.Stub)
    39  	s.client = newStubMinionClient(s.stub)
    40  	s.guard = newStubGuard(s.stub)
    41  	s.agent = newStubAgent()
    42  }
    43  
    44  func (s *Suite) TestStartAndStop(c *gc.C) {
    45  	w, err := migrationminion.New(migrationminion.Config{
    46  		Facade: s.client,
    47  		Guard:  s.guard,
    48  		Agent:  s.agent,
    49  	})
    50  	c.Assert(err, jc.ErrorIsNil)
    51  	workertest.CleanKill(c, w)
    52  	s.stub.CheckCallNames(c, "Watch")
    53  }
    54  
    55  func (s *Suite) TestWatchFailure(c *gc.C) {
    56  	s.client.watchErr = errors.New("boom")
    57  	w, err := migrationminion.New(migrationminion.Config{
    58  		Facade: s.client,
    59  		Guard:  s.guard,
    60  		Agent:  s.agent,
    61  	})
    62  	c.Assert(err, jc.ErrorIsNil)
    63  	err = workertest.CheckKilled(c, w)
    64  	c.Check(err, gc.ErrorMatches, "setting up watcher: boom")
    65  }
    66  
    67  func (s *Suite) TestClosedWatcherChannel(c *gc.C) {
    68  	close(s.client.watcher.changes)
    69  	w, err := migrationminion.New(migrationminion.Config{
    70  		Facade: s.client,
    71  		Guard:  s.guard,
    72  		Agent:  s.agent,
    73  	})
    74  	c.Assert(err, jc.ErrorIsNil)
    75  	err = workertest.CheckKilled(c, w)
    76  	c.Check(err, gc.ErrorMatches, "watcher channel closed")
    77  }
    78  
    79  func (s *Suite) TestUnlockError(c *gc.C) {
    80  	s.client.watcher.changes <- watcher.MigrationStatus{
    81  		Phase: migration.NONE,
    82  	}
    83  	s.guard.unlockErr = errors.New("squish")
    84  	w, err := migrationminion.New(migrationminion.Config{
    85  		Facade: s.client,
    86  		Guard:  s.guard,
    87  		Agent:  s.agent,
    88  	})
    89  	c.Assert(err, jc.ErrorIsNil)
    90  
    91  	err = workertest.CheckKilled(c, w)
    92  	c.Check(err, gc.ErrorMatches, "squish")
    93  	s.stub.CheckCallNames(c, "Watch", "Unlock")
    94  }
    95  
    96  func (s *Suite) TestLockdownError(c *gc.C) {
    97  	s.client.watcher.changes <- watcher.MigrationStatus{
    98  		Phase: migration.QUIESCE,
    99  	}
   100  	s.guard.lockdownErr = errors.New("squash")
   101  	w, err := migrationminion.New(migrationminion.Config{
   102  		Facade: s.client,
   103  		Guard:  s.guard,
   104  		Agent:  s.agent,
   105  	})
   106  	c.Assert(err, jc.ErrorIsNil)
   107  
   108  	err = workertest.CheckKilled(c, w)
   109  	c.Check(err, gc.ErrorMatches, "squash")
   110  	s.stub.CheckCallNames(c, "Watch", "Lockdown")
   111  }
   112  
   113  func (s *Suite) TestNONE(c *gc.C) {
   114  	s.client.watcher.changes <- watcher.MigrationStatus{
   115  		Phase: migration.NONE,
   116  	}
   117  	w, err := migrationminion.New(migrationminion.Config{
   118  		Facade: s.client,
   119  		Guard:  s.guard,
   120  		Agent:  s.agent,
   121  	})
   122  	c.Assert(err, jc.ErrorIsNil)
   123  
   124  	workertest.CheckAlive(c, w)
   125  	workertest.CleanKill(c, w)
   126  	s.stub.CheckCallNames(c, "Watch", "Unlock")
   127  }
   128  
   129  func (s *Suite) TestSUCCESS(c *gc.C) {
   130  	addrs := []string{"1.1.1.1:1", "9.9.9.9:9"}
   131  	s.client.watcher.changes <- watcher.MigrationStatus{
   132  		Phase:          migration.SUCCESS,
   133  		TargetAPIAddrs: addrs,
   134  		TargetCACert:   "top secret",
   135  	}
   136  	w, err := migrationminion.New(migrationminion.Config{
   137  		Facade: s.client,
   138  		Guard:  s.guard,
   139  		Agent:  s.agent,
   140  	})
   141  	c.Assert(err, jc.ErrorIsNil)
   142  
   143  	select {
   144  	case <-s.agent.configChanged:
   145  	case <-time.After(coretesting.LongWait):
   146  		c.Fatal("timed out waiting for config to be changed")
   147  	}
   148  	workertest.CleanKill(c, w)
   149  	c.Assert(s.agent.conf.addrs, gc.DeepEquals, addrs)
   150  	c.Assert(s.agent.conf.caCert, gc.DeepEquals, "top secret")
   151  	s.stub.CheckCallNames(c, "Watch", "Lockdown")
   152  }
   153  
   154  func newStubGuard(stub *jujutesting.Stub) *stubGuard {
   155  	return &stubGuard{stub: stub}
   156  }
   157  
   158  type stubGuard struct {
   159  	stub        *jujutesting.Stub
   160  	unlockErr   error
   161  	lockdownErr error
   162  }
   163  
   164  func (g *stubGuard) Lockdown(fortress.Abort) error {
   165  	g.stub.AddCall("Lockdown")
   166  	return g.lockdownErr
   167  }
   168  
   169  func (g *stubGuard) Unlock() error {
   170  	g.stub.AddCall("Unlock")
   171  	return g.unlockErr
   172  }
   173  
   174  func newStubMinionClient(stub *jujutesting.Stub) *stubMinionClient {
   175  	return &stubMinionClient{
   176  		stub:    stub,
   177  		watcher: newStubWatcher(),
   178  	}
   179  }
   180  
   181  type stubMinionClient struct {
   182  	stub     *jujutesting.Stub
   183  	watcher  *stubWatcher
   184  	watchErr error
   185  }
   186  
   187  func (c *stubMinionClient) Watch() (watcher.MigrationStatusWatcher, error) {
   188  	c.stub.MethodCall(c, "Watch")
   189  	if c.watchErr != nil {
   190  		return nil, c.watchErr
   191  	}
   192  	return c.watcher, nil
   193  }
   194  
   195  func newStubWatcher() *stubWatcher {
   196  	return &stubWatcher{
   197  		Worker:  workertest.NewErrorWorker(nil),
   198  		changes: make(chan watcher.MigrationStatus, 1),
   199  	}
   200  }
   201  
   202  type stubWatcher struct {
   203  	worker.Worker
   204  	changes chan watcher.MigrationStatus
   205  }
   206  
   207  func (w *stubWatcher) Changes() <-chan watcher.MigrationStatus {
   208  	return w.changes
   209  }
   210  
   211  func newStubAgent() *stubAgent {
   212  	return &stubAgent{
   213  		configChanged: make(chan bool),
   214  	}
   215  }
   216  
   217  type stubAgent struct {
   218  	agent.Agent
   219  	configChanged chan bool
   220  	conf          stubConfig
   221  }
   222  
   223  func (ma *stubAgent) CurrentConfig() agent.Config {
   224  	return &ma.conf
   225  }
   226  
   227  func (ma *stubAgent) ChangeConfig(f agent.ConfigMutator) error {
   228  	defer close(ma.configChanged)
   229  	return f(&ma.conf)
   230  }
   231  
   232  type stubConfig struct {
   233  	agent.ConfigSetter
   234  
   235  	mu     sync.Mutex
   236  	addrs  []string
   237  	caCert string
   238  }
   239  
   240  func (mc *stubConfig) setAddresses(addrs ...string) {
   241  	mc.mu.Lock()
   242  	defer mc.mu.Unlock()
   243  	mc.addrs = append([]string(nil), addrs...)
   244  }
   245  
   246  func (mc *stubConfig) SetAPIHostPorts(servers [][]network.HostPort) {
   247  	mc.mu.Lock()
   248  	defer mc.mu.Unlock()
   249  	mc.addrs = nil
   250  	for _, hps := range servers {
   251  		for _, hp := range hps {
   252  			mc.addrs = append(mc.addrs, hp.NetAddr())
   253  		}
   254  	}
   255  }
   256  
   257  func (mc *stubConfig) SetCACert(cert string) {
   258  	mc.mu.Lock()
   259  	defer mc.mu.Unlock()
   260  	mc.caCert = cert
   261  }