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

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package caasoperator_test
     5  
     6  import (
     7  	"sync"
     8  	"time"
     9  
    10  	"github.com/juju/clock/testclock"
    11  	"github.com/juju/errors"
    12  	"github.com/juju/testing"
    13  	jc "github.com/juju/testing/checkers"
    14  	gc "gopkg.in/check.v1"
    15  	"gopkg.in/juju/names.v2"
    16  	"gopkg.in/juju/worker.v1"
    17  	"gopkg.in/juju/worker.v1/dependency"
    18  	dt "gopkg.in/juju/worker.v1/dependency/testing"
    19  	"gopkg.in/juju/worker.v1/workertest"
    20  
    21  	"github.com/juju/juju/api/base"
    22  	"github.com/juju/juju/apiserver/params"
    23  	"github.com/juju/juju/core/machinelock"
    24  	coretesting "github.com/juju/juju/testing"
    25  	"github.com/juju/juju/worker/caasoperator"
    26  	"github.com/juju/juju/worker/uniter"
    27  )
    28  
    29  type ManifoldSuite struct {
    30  	testing.IsolationSuite
    31  
    32  	manifold        dependency.Manifold
    33  	context         dependency.Context
    34  	agent           fakeAgent
    35  	apiCaller       fakeAPICaller
    36  	charmDownloader fakeDownloader
    37  	client          fakeClient
    38  	clock           *testclock.Clock
    39  	dataDir         string
    40  	stub            testing.Stub
    41  }
    42  
    43  var _ = gc.Suite(&ManifoldSuite{})
    44  
    45  func (s *ManifoldSuite) SetUpTest(c *gc.C) {
    46  	s.IsolationSuite.SetUpTest(c)
    47  
    48  	s.dataDir = c.MkDir()
    49  	s.agent = fakeAgent{
    50  		config: fakeAgentConfig{
    51  			tag:     names.NewApplicationTag("gitlab"),
    52  			dataDir: s.dataDir,
    53  		},
    54  	}
    55  	s.clock = testclock.NewClock(time.Time{})
    56  	s.stub.ResetCalls()
    57  
    58  	s.context = s.newContext(nil)
    59  	s.manifold = caasoperator.Manifold(caasoperator.ManifoldConfig{
    60  		AgentName:             "agent",
    61  		APICallerName:         "api-caller",
    62  		ClockName:             "clock",
    63  		CharmDirName:          "charm-dir",
    64  		HookRetryStrategyName: "hook-retry-strategy",
    65  		MachineLock:           &fakemachinelock{},
    66  		NewWorker:             s.newWorker,
    67  		NewClient:             s.newClient,
    68  		NewCharmDownloader:    s.newCharmDownloader,
    69  		LeadershipGuarantee:   30 * time.Second,
    70  	})
    71  }
    72  
    73  func (s *ManifoldSuite) newContext(overlay map[string]interface{}) dependency.Context {
    74  	resources := map[string]interface{}{
    75  		"agent":               &s.agent,
    76  		"api-caller":          &s.apiCaller,
    77  		"clock":               s.clock,
    78  		"charm-dir":           &mockCharmDirGuard{},
    79  		"hook-retry-strategy": params.RetryStrategy{},
    80  	}
    81  	for k, v := range overlay {
    82  		resources[k] = v
    83  	}
    84  	return dt.StubContext(nil, resources)
    85  }
    86  
    87  func (s *ManifoldSuite) newWorker(config caasoperator.Config) (worker.Worker, error) {
    88  	s.stub.MethodCall(s, "NewWorker", config)
    89  	if err := s.stub.NextErr(); err != nil {
    90  		return nil, err
    91  	}
    92  	w := worker.NewRunner(worker.RunnerParams{})
    93  	s.AddCleanup(func(c *gc.C) { workertest.DirtyKill(c, w) })
    94  	return w, nil
    95  }
    96  
    97  func (s *ManifoldSuite) newClient(caller base.APICaller) caasoperator.Client {
    98  	s.stub.MethodCall(s, "NewClient", caller)
    99  	return &s.client
   100  }
   101  
   102  func (s *ManifoldSuite) newCharmDownloader(caller base.APICaller) caasoperator.Downloader {
   103  	s.stub.MethodCall(s, "NewCharmDownloader", caller)
   104  	return &s.charmDownloader
   105  }
   106  
   107  var expectedInputs = []string{"agent", "api-caller", "clock", "charm-dir", "hook-retry-strategy"}
   108  
   109  func (s *ManifoldSuite) TestInputs(c *gc.C) {
   110  	c.Assert(s.manifold.Inputs, jc.SameContents, expectedInputs)
   111  }
   112  
   113  func (s *ManifoldSuite) TestMissingInputs(c *gc.C) {
   114  	for _, input := range expectedInputs {
   115  		context := s.newContext(map[string]interface{}{
   116  			input: dependency.ErrMissing,
   117  		})
   118  		_, err := s.manifold.Start(context)
   119  		c.Assert(errors.Cause(err), gc.Equals, dependency.ErrMissing)
   120  	}
   121  }
   122  
   123  func (s *ManifoldSuite) TestStart(c *gc.C) {
   124  	w := s.startWorkerClean(c)
   125  	workertest.CleanKill(c, w)
   126  
   127  	s.stub.CheckCallNames(c, "NewClient", "NewCharmDownloader", "NewWorker")
   128  	s.stub.CheckCall(c, 0, "NewClient", &s.apiCaller)
   129  	s.stub.CheckCall(c, 1, "NewCharmDownloader", &s.apiCaller)
   130  
   131  	args := s.stub.Calls()[2].Args
   132  	c.Assert(args, gc.HasLen, 1)
   133  	c.Assert(args[0], gc.FitsTypeOf, caasoperator.Config{})
   134  	config := args[0].(caasoperator.Config)
   135  
   136  	// Don't care about some helper funcs.
   137  	c.Assert(config.UniterParams, gc.NotNil)
   138  	c.Assert(config.LeadershipTrackerFunc, gc.NotNil)
   139  	c.Assert(config.UniterFacadeFunc, gc.NotNil)
   140  	c.Assert(config.StartUniterFunc, gc.NotNil)
   141  	c.Assert(config.UniterParams.UpdateStatusSignal, gc.NotNil)
   142  	c.Assert(config.UniterParams.NewOperationExecutor, gc.NotNil)
   143  	config.LeadershipTrackerFunc = nil
   144  	config.StartUniterFunc = nil
   145  	config.UniterFacadeFunc = nil
   146  	config.UniterParams.UpdateStatusSignal = nil
   147  	config.UniterParams.NewOperationExecutor = nil
   148  
   149  	c.Assert(config, jc.DeepEquals, caasoperator.Config{
   150  		ModelUUID:          coretesting.ModelTag.Id(),
   151  		ModelName:          "gitlab-model",
   152  		Application:        "gitlab",
   153  		DataDir:            s.dataDir,
   154  		CharmGetter:        &s.client,
   155  		Clock:              s.clock,
   156  		PodSpecSetter:      &s.client,
   157  		Downloader:         &s.charmDownloader,
   158  		StatusSetter:       &s.client,
   159  		UnitGetter:         &s.client,
   160  		UnitRemover:        &s.client,
   161  		ApplicationWatcher: &s.client,
   162  		VersionSetter:      &s.client,
   163  		UniterParams: &uniter.UniterParams{
   164  			DataDir:       s.dataDir,
   165  			MachineLock:   &fakemachinelock{},
   166  			CharmDirGuard: &mockCharmDirGuard{},
   167  			Clock:         s.clock,
   168  		},
   169  	})
   170  }
   171  
   172  func (s *ManifoldSuite) startWorkerClean(c *gc.C) worker.Worker {
   173  	w, err := s.manifold.Start(s.context)
   174  	c.Assert(err, jc.ErrorIsNil)
   175  	workertest.CheckAlive(c, w)
   176  	return w
   177  }
   178  
   179  type fakemachinelock struct {
   180  	mu sync.Mutex
   181  }
   182  
   183  func (f *fakemachinelock) Acquire(spec machinelock.Spec) (func(), error) {
   184  	f.mu.Lock()
   185  	return func() {
   186  		f.mu.Unlock()
   187  	}, nil
   188  }
   189  func (f *fakemachinelock) Report(opts ...machinelock.ReportOption) (string, error) {
   190  	return "", nil
   191  }