github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/externalcontrollerupdater/externalcontrollerupdater_test.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package externalcontrollerupdater_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/clock/testclock"
    10  	"github.com/juju/errors"
    11  	"github.com/juju/testing"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  	"gopkg.in/juju/names.v2"
    15  	"gopkg.in/juju/worker.v1/workertest"
    16  
    17  	"github.com/juju/juju/api"
    18  	"github.com/juju/juju/api/crosscontroller"
    19  	"github.com/juju/juju/core/crossmodel"
    20  	coretesting "github.com/juju/juju/testing"
    21  	"github.com/juju/juju/worker/externalcontrollerupdater"
    22  )
    23  
    24  var _ = gc.Suite(&ExternalControllerUpdaterSuite{})
    25  
    26  type ExternalControllerUpdaterSuite struct {
    27  	coretesting.BaseSuite
    28  
    29  	updater mockExternalControllerUpdaterClient
    30  	watcher mockExternalControllerWatcherClient
    31  
    32  	clock *testclock.Clock
    33  
    34  	stub       testing.Stub
    35  	newWatcher externalcontrollerupdater.NewExternalControllerWatcherClientFunc
    36  }
    37  
    38  func (s *ExternalControllerUpdaterSuite) SetUpTest(c *gc.C) {
    39  	s.BaseSuite.SetUpTest(c)
    40  
    41  	s.updater = mockExternalControllerUpdaterClient{
    42  		watcher: newMockStringsWatcher(),
    43  		info: crossmodel.ControllerInfo{
    44  			ControllerTag: coretesting.ControllerTag,
    45  			Alias:         "foo",
    46  			Addrs:         []string{"bar"},
    47  			CACert:        "baz",
    48  		},
    49  	}
    50  	s.AddCleanup(func(*gc.C) { s.updater.watcher.Stop() })
    51  
    52  	s.watcher = mockExternalControllerWatcherClient{
    53  		watcher: newMockNotifyWatcher(),
    54  		info: crosscontroller.ControllerInfo{
    55  			Addrs:  []string{"foo"},
    56  			CACert: "bar",
    57  		},
    58  	}
    59  	s.AddCleanup(func(*gc.C) { s.watcher.watcher.Stop() })
    60  
    61  	s.clock = testclock.NewClock(time.Time{})
    62  
    63  	s.stub.ResetCalls()
    64  	s.newWatcher = func(apiInfo *api.Info) (externalcontrollerupdater.ExternalControllerWatcherClientCloser, error) {
    65  		s.stub.AddCall("NextExternalControllerWatcherClient", apiInfo)
    66  		if err := s.stub.NextErr(); err != nil {
    67  			return nil, err
    68  		}
    69  		return &s.watcher, nil
    70  	}
    71  }
    72  
    73  func (s *ExternalControllerUpdaterSuite) TestStartStop(c *gc.C) {
    74  	w, err := externalcontrollerupdater.New(&s.updater, s.newWatcher, s.clock)
    75  	c.Assert(err, jc.ErrorIsNil)
    76  	workertest.CleanKill(c, w)
    77  }
    78  
    79  func (s *ExternalControllerUpdaterSuite) TestWatchExternalControllersCalled(c *gc.C) {
    80  	s.updater.watcher.changes = make(chan []string)
    81  
    82  	w, err := externalcontrollerupdater.New(&s.updater, s.newWatcher, s.clock)
    83  	c.Assert(err, jc.ErrorIsNil)
    84  	defer workertest.CleanKill(c, w)
    85  
    86  	select {
    87  	case s.updater.watcher.changes <- []string{}:
    88  	case <-time.After(coretesting.LongWait):
    89  		c.Fatal("timed out waiting to send changes")
    90  	}
    91  
    92  	workertest.CleanKill(c, w)
    93  	s.updater.Stub.CheckCallNames(c, "WatchExternalControllers")
    94  }
    95  
    96  func (s *ExternalControllerUpdaterSuite) TestWatchExternalControllers(c *gc.C) {
    97  	s.updater.watcher.changes <- []string{coretesting.ControllerTag.Id()}
    98  
    99  	w, err := externalcontrollerupdater.New(&s.updater, s.newWatcher, s.clock)
   100  	c.Assert(err, jc.ErrorIsNil)
   101  	defer workertest.CleanKill(c, w)
   102  
   103  	// Cause three notifications. Only the first notification is
   104  	// accompanied by API address changes, so there should be only
   105  	// one API reconnection, and one local controller update.
   106  	for i := 0; i < 3; i++ {
   107  		select {
   108  		case s.watcher.watcher.changes <- struct{}{}:
   109  		case <-time.After(coretesting.LongWait):
   110  			c.Fatal("timed out waiting to send changes")
   111  		}
   112  	}
   113  
   114  	workertest.CleanKill(c, w)
   115  	s.stub.CheckCalls(c, []testing.StubCall{{
   116  		"NextExternalControllerWatcherClient",
   117  		[]interface{}{&api.Info{
   118  			Addrs:  s.updater.info.Addrs,
   119  			CACert: s.updater.info.CACert,
   120  			Tag:    names.NewUserTag("jujuanonymous"),
   121  		}},
   122  	}, {
   123  		"NextExternalControllerWatcherClient",
   124  		[]interface{}{&api.Info{
   125  			Addrs:  s.watcher.info.Addrs,
   126  			CACert: s.updater.info.CACert, // only addresses are updated
   127  			Tag:    names.NewUserTag("jujuanonymous"),
   128  		}},
   129  	}})
   130  	s.updater.Stub.CheckCalls(c, []testing.StubCall{{
   131  		"WatchExternalControllers",
   132  		[]interface{}{},
   133  	}, {
   134  		"ExternalControllerInfo",
   135  		[]interface{}{coretesting.ControllerTag.Id()},
   136  	}, {
   137  		"SetExternalControllerInfo",
   138  		[]interface{}{crossmodel.ControllerInfo{
   139  			ControllerTag: s.updater.info.ControllerTag,
   140  			Alias:         s.updater.info.Alias,
   141  			Addrs:         s.watcher.info.Addrs, // new addrs
   142  			CACert:        s.updater.info.CACert,
   143  		}},
   144  	}})
   145  	s.watcher.Stub.CheckCallNames(c,
   146  		"WatchControllerInfo",
   147  		"ControllerInfo",
   148  		"Close",
   149  		"WatchControllerInfo",
   150  		"ControllerInfo", // no change
   151  		"ControllerInfo", // no change
   152  		"Close",
   153  	)
   154  }
   155  
   156  func (s *ExternalControllerUpdaterSuite) TestWatchExternalControllersErrorsContained(c *gc.C) {
   157  	// The first time we attempt to connect to the external controller,
   158  	// the dial should fail. The runner will reschedule the worker to
   159  	// try again.
   160  	s.stub.SetErrors(errors.New("no API connection for you"))
   161  
   162  	s.updater.watcher.changes <- []string{coretesting.ControllerTag.Id()}
   163  	s.watcher.watcher.changes = make(chan struct{})
   164  	s.watcher.info.Addrs = s.updater.info.Addrs // no change
   165  
   166  	w, err := externalcontrollerupdater.New(&s.updater, s.newWatcher, s.clock)
   167  	c.Assert(err, jc.ErrorIsNil)
   168  	defer workertest.CleanKill(c, w)
   169  
   170  	// The first run of the controller worker should fail to
   171  	// connect to the API, and should abort. The runner should
   172  	// then be waiting for a minute to restart the controller
   173  	// worker.
   174  	s.clock.WaitAdvance(time.Second, coretesting.LongWait, 1)
   175  	s.clock.WaitAdvance(59*time.Second, coretesting.LongWait, 1)
   176  
   177  	// The controller worker should have been restarted now.
   178  	select {
   179  	case s.watcher.watcher.changes <- struct{}{}:
   180  	case <-time.After(coretesting.LongWait):
   181  		c.Fatal("timed out waiting to send changes")
   182  	}
   183  
   184  	workertest.CleanKill(c, w)
   185  	s.stub.CheckCalls(c, []testing.StubCall{{
   186  		"NextExternalControllerWatcherClient",
   187  		[]interface{}{&api.Info{
   188  			Addrs:  s.updater.info.Addrs,
   189  			CACert: s.updater.info.CACert,
   190  			Tag:    names.NewUserTag("jujuanonymous"),
   191  		}},
   192  	}, {
   193  		"NextExternalControllerWatcherClient",
   194  		[]interface{}{&api.Info{
   195  			Addrs:  s.updater.info.Addrs,
   196  			CACert: s.updater.info.CACert,
   197  			Tag:    names.NewUserTag("jujuanonymous"),
   198  		}},
   199  	}})
   200  	s.updater.Stub.CheckCallNames(c,
   201  		"WatchExternalControllers",
   202  		"ExternalControllerInfo",
   203  		"ExternalControllerInfo",
   204  	)
   205  	s.watcher.Stub.CheckCallNames(c,
   206  		"WatchControllerInfo",
   207  		"ControllerInfo",
   208  		"Close",
   209  	)
   210  }