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 }