github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/storageprovisioner/caasworker_test.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package storageprovisioner_test 5 6 import ( 7 stdcontext "context" 8 "time" 9 10 "github.com/juju/clock" 11 "github.com/juju/errors" 12 "github.com/juju/loggo" 13 "github.com/juju/names/v5" 14 "github.com/juju/retry" 15 "github.com/juju/testing" 16 jc "github.com/juju/testing/checkers" 17 "github.com/juju/worker/v3/workertest" 18 gc "gopkg.in/check.v1" 19 20 "github.com/juju/juju/environs/context" 21 "github.com/juju/juju/rpc/params" 22 "github.com/juju/juju/storage" 23 coretesting "github.com/juju/juju/testing" 24 "github.com/juju/juju/worker/storageprovisioner" 25 ) 26 27 type WorkerSuite struct { 28 testing.IsolationSuite 29 30 config storageprovisioner.Config 31 applicationsWatcher *mockApplicationsWatcher 32 lifeGetter *mockLifecycleManager 33 34 applicationChanges chan []string 35 } 36 37 var _ = gc.Suite(&WorkerSuite{}) 38 39 func (s *WorkerSuite) SetUpTest(c *gc.C) { 40 s.IsolationSuite.SetUpTest(c) 41 42 s.applicationChanges = make(chan []string) 43 s.applicationsWatcher = newMockApplicationsWatcher(s.applicationChanges) 44 s.lifeGetter = &mockLifecycleManager{} 45 46 s.config = storageprovisioner.Config{ 47 Model: coretesting.ModelTag, 48 Scope: coretesting.ModelTag, 49 Applications: s.applicationsWatcher, 50 Volumes: newMockVolumeAccessor(), 51 Filesystems: newMockFilesystemAccessor(), 52 Life: s.lifeGetter, 53 Status: &mockStatusSetter{}, 54 Clock: &mockClock{}, 55 Logger: loggo.GetLogger("test"), 56 Registry: storage.StaticProviderRegistry{}, 57 CloudCallContextFunc: func(_ stdcontext.Context) context.ProviderCallContext { return context.NewEmptyCloudCallContext() }, 58 } 59 } 60 61 func (s *WorkerSuite) TestValidateConfig(c *gc.C) { 62 s.testValidateConfig(c, func(config *storageprovisioner.Config) { 63 config.Scope = names.NewApplicationTag("mariadb") 64 config.Applications = nil 65 }, `nil Applications not valid`) 66 } 67 68 func (s *WorkerSuite) testValidateConfig(c *gc.C, f func(*storageprovisioner.Config), expect string) { 69 config := s.config 70 f(&config) 71 w, err := storageprovisioner.NewCaasWorker(config) 72 if err == nil { 73 workertest.DirtyKill(c, w) 74 } 75 c.Check(err, gc.ErrorMatches, expect) 76 } 77 78 func (s *WorkerSuite) TestStartStop(c *gc.C) { 79 w, err := storageprovisioner.NewCaasWorker(s.config) 80 c.Assert(err, jc.ErrorIsNil) 81 workertest.CheckAlive(c, w) 82 workertest.CleanKill(c, w) 83 } 84 85 func (s *WorkerSuite) TestWatchApplicationDead(c *gc.C) { 86 w, err := storageprovisioner.NewCaasWorker(s.config) 87 c.Assert(err, jc.ErrorIsNil) 88 defer workertest.CleanKill(c, w) 89 90 select { 91 case s.applicationChanges <- []string{"postgresql"}: 92 case <-time.After(coretesting.LongWait): 93 c.Fatal("timed out sending applications change") 94 } 95 96 // Given the worker time to startup. 97 retryCallArgs := retry.CallArgs{ 98 Clock: clock.WallClock, 99 MaxDuration: coretesting.LongWait, 100 Delay: 10 * time.Millisecond, 101 Func: func() error { 102 if len(s.config.Filesystems.(*mockFilesystemAccessor).Calls()) > 0 { 103 return nil 104 } 105 return errors.NotYetAvailablef("Worker not up") 106 }, 107 } 108 err = retry.Call(retryCallArgs) 109 c.Assert(err, jc.ErrorIsNil) 110 111 workertest.CleanKill(c, w) 112 // Only call is to watch model. 113 s.config.Filesystems.(*mockFilesystemAccessor).CheckCallNames(c, "WatchFilesystems") 114 s.config.Filesystems.(*mockFilesystemAccessor).CheckCall(c, 0, "WatchFilesystems", coretesting.ModelTag) 115 } 116 117 func (s *WorkerSuite) TestStopsWatchingApplicationBecauseApplicationRemoved(c *gc.C) { 118 s.assertStopsWatchingApplication(c, func() { 119 s.lifeGetter.err = ¶ms.Error{Code: params.CodeNotFound} 120 }) 121 } 122 123 func (s *WorkerSuite) assertStopsWatchingApplication(c *gc.C, lifeGetterInjecter func()) { 124 w, err := storageprovisioner.NewCaasWorker(s.config) 125 c.Assert(err, jc.ErrorIsNil) 126 defer workertest.CleanKill(c, w) 127 128 select { 129 case s.applicationChanges <- []string{"mariadb"}: 130 case <-time.After(coretesting.LongWait): 131 c.Fatal("timed out sending applications change") 132 } 133 134 // Check that the worker is running or not; 135 // given it time to startup. 136 startingRetryCallArgs := retry.CallArgs{ 137 Clock: clock.WallClock, 138 MaxDuration: coretesting.LongWait, 139 Delay: 10 * time.Millisecond, 140 Func: func() error { 141 _, running := storageprovisioner.StorageWorker(w, "mariadb") 142 if running { 143 return nil 144 } 145 return errors.NotYetAvailablef("Worker not up") 146 }, 147 } 148 err = retry.Call(startingRetryCallArgs) 149 c.Assert(err, jc.ErrorIsNil) 150 151 // Add an additional app worker so we can check that the correct one is accessed. 152 storageprovisioner.NewStorageWorker(c, w, "postgresql") 153 154 if lifeGetterInjecter != nil { 155 lifeGetterInjecter() 156 } 157 select { 158 case s.applicationChanges <- []string{"postgresql"}: 159 case <-time.After(coretesting.LongWait): 160 c.Fatal("timed out sending applications change") 161 } 162 163 // The mariadb worker should still be running. 164 _, ok := storageprovisioner.StorageWorker(w, "mariadb") 165 c.Assert(ok, jc.IsTrue) 166 167 // Check that the postgresql worker is running or not; 168 // given it time to shutdown. 169 stoppingRetryCallArgs := retry.CallArgs{ 170 Clock: clock.WallClock, 171 MaxDuration: coretesting.LongWait, 172 Delay: 10 * time.Millisecond, 173 Func: func() error { 174 _, running := storageprovisioner.StorageWorker(w, "postgresql") 175 if !running { 176 return nil 177 } 178 return errors.NotYetAvailablef("Worker not down") 179 }, 180 } 181 err = retry.Call(stoppingRetryCallArgs) 182 c.Assert(err, jc.ErrorIsNil) 183 184 workertest.CleanKill(c, w) 185 workertest.CheckKilled(c, s.applicationsWatcher.watcher) 186 } 187 188 func (s *WorkerSuite) TestStopsWatchingApplicationBecauseApplicationDead(c *gc.C) { 189 s.assertStopsWatchingApplication(c, nil) 190 } 191 192 func (s *WorkerSuite) TestWatcherErrorStopsWorker(c *gc.C) { 193 w, err := storageprovisioner.NewCaasWorker(s.config) 194 c.Assert(err, jc.ErrorIsNil) 195 defer workertest.DirtyKill(c, w) 196 197 select { 198 case s.applicationChanges <- []string{"mariadb"}: 199 case <-time.After(coretesting.LongWait): 200 c.Fatal("timed out sending applications change") 201 } 202 203 s.applicationsWatcher.watcher.KillErr(errors.New("splat")) 204 workertest.CheckKilled(c, s.applicationsWatcher.watcher) 205 err = workertest.CheckKilled(c, w) 206 c.Assert(err, gc.ErrorMatches, "splat") 207 }