github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/watcher_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package apiserver_test 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/names/v5" 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 12 "github.com/juju/juju/apiserver" 13 "github.com/juju/juju/apiserver/common" 14 apiservererrors "github.com/juju/juju/apiserver/errors" 15 "github.com/juju/juju/apiserver/facade" 16 "github.com/juju/juju/apiserver/facade/facadetest" 17 apiservertesting "github.com/juju/juju/apiserver/testing" 18 "github.com/juju/juju/controller" 19 "github.com/juju/juju/core/migration" 20 "github.com/juju/juju/core/network" 21 "github.com/juju/juju/rpc/params" 22 "github.com/juju/juju/state" 23 "github.com/juju/juju/testing" 24 ) 25 26 type watcherSuite struct { 27 testing.BaseSuite 28 resources *common.Resources 29 authorizer apiservertesting.FakeAuthorizer 30 } 31 32 var _ = gc.Suite(&watcherSuite{}) 33 34 func (s *watcherSuite) SetUpTest(c *gc.C) { 35 s.BaseSuite.SetUpTest(c) 36 s.resources = common.NewResources() 37 s.AddCleanup(func(*gc.C) { 38 s.resources.StopAll() 39 }) 40 s.authorizer = apiservertesting.FakeAuthorizer{} 41 } 42 43 func (s *watcherSuite) getFacade( 44 c *gc.C, 45 name string, 46 version int, 47 id string, 48 dispose func(), 49 ) interface{} { 50 factory := getFacadeFactory(c, name, version) 51 facade, err := factory(s.facadeContext(id, dispose)) 52 c.Assert(err, jc.ErrorIsNil) 53 return facade 54 } 55 56 func (s *watcherSuite) facadeContext(id string, dispose func()) facadetest.Context { 57 return facadetest.Context{ 58 Resources_: s.resources, 59 Auth_: s.authorizer, 60 ID_: id, 61 Dispose_: dispose, 62 } 63 } 64 65 func getFacadeFactory(c *gc.C, name string, version int) facade.Factory { 66 factory, err := apiserver.AllFacades().GetFactory(name, version) 67 c.Assert(err, jc.ErrorIsNil) 68 return factory 69 } 70 71 func (s *watcherSuite) TestVolumeAttachmentsWatcher(c *gc.C) { 72 ch := make(chan []string, 1) 73 id := s.resources.Register(&fakeStringsWatcher{ch: ch}) 74 s.authorizer.Tag = names.NewMachineTag("123") 75 76 ch <- []string{"0:1", "1:2"} 77 facade := s.getFacade(c, "VolumeAttachmentsWatcher", 2, id, nopDispose).(machineStorageIdsWatcher) 78 result, err := facade.Next() 79 c.Assert(err, jc.ErrorIsNil) 80 81 c.Assert(result, jc.DeepEquals, params.MachineStorageIdsWatchResult{ 82 Changes: []params.MachineStorageId{ 83 {MachineTag: "machine-0", AttachmentTag: "volume-1"}, 84 {MachineTag: "machine-1", AttachmentTag: "volume-2"}, 85 }, 86 }) 87 } 88 89 func (s *watcherSuite) TestFilesystemAttachmentsWatcher(c *gc.C) { 90 ch := make(chan []string, 1) 91 id := s.resources.Register(&fakeStringsWatcher{ch: ch}) 92 s.authorizer.Tag = names.NewMachineTag("123") 93 94 ch <- []string{"0:1", "1:2"} 95 facade := s.getFacade(c, "FilesystemAttachmentsWatcher", 2, id, nopDispose).(machineStorageIdsWatcher) 96 result, err := facade.Next() 97 c.Assert(err, jc.ErrorIsNil) 98 99 c.Assert(result, jc.DeepEquals, params.MachineStorageIdsWatchResult{ 100 Changes: []params.MachineStorageId{ 101 {MachineTag: "machine-0", AttachmentTag: "filesystem-1"}, 102 {MachineTag: "machine-1", AttachmentTag: "filesystem-2"}, 103 }, 104 }) 105 } 106 107 func (s *watcherSuite) TestMigrationStatusWatcher(c *gc.C) { 108 w := apiservertesting.NewFakeNotifyWatcher() 109 id := s.resources.Register(w) 110 s.authorizer.Tag = names.NewMachineTag("12") 111 apiserver.PatchGetMigrationBackend(s, new(fakeMigrationBackend), new(fakeMigrationBackend)) 112 apiserver.PatchGetControllerCACert(s, "no worries") 113 114 facade := s.getFacade(c, "MigrationStatusWatcher", 1, id, nopDispose).(migrationStatusWatcher) 115 defer c.Check(facade.Stop(), jc.ErrorIsNil) 116 result, err := facade.Next() 117 c.Assert(err, jc.ErrorIsNil) 118 c.Assert(result, jc.DeepEquals, params.MigrationStatus{ 119 MigrationId: "id", 120 Attempt: 2, 121 Phase: "IMPORT", 122 SourceAPIAddrs: []string{"1.2.3.4:5", "2.3.4.5:6", "3.4.5.6:7"}, 123 SourceCACert: "no worries", 124 TargetAPIAddrs: []string{"1.2.3.4:5555"}, 125 TargetCACert: "trust me", 126 }) 127 } 128 129 func (s *watcherSuite) TestMigrationStatusWatcherNoMigration(c *gc.C) { 130 w := apiservertesting.NewFakeNotifyWatcher() 131 id := s.resources.Register(w) 132 s.authorizer.Tag = names.NewMachineTag("12") 133 backend := &fakeMigrationBackend{noMigration: true} 134 apiserver.PatchGetMigrationBackend(s, backend, backend) 135 136 facade := s.getFacade(c, "MigrationStatusWatcher", 1, id, nopDispose).(migrationStatusWatcher) 137 defer c.Check(facade.Stop(), jc.ErrorIsNil) 138 result, err := facade.Next() 139 c.Assert(err, jc.ErrorIsNil) 140 c.Assert(result, jc.DeepEquals, params.MigrationStatus{ 141 Phase: "NONE", 142 }) 143 } 144 145 func (s *watcherSuite) TestMigrationStatusWatcherNotAgent(c *gc.C) { 146 id := s.resources.Register(apiservertesting.NewFakeNotifyWatcher()) 147 s.authorizer.Tag = names.NewUserTag("frogdog") 148 149 factory, err := apiserver.AllFacades().GetFactory("MigrationStatusWatcher", 1) 150 c.Assert(err, jc.ErrorIsNil) 151 _, err = factory(facadetest.Context{ 152 Resources_: s.resources, 153 Auth_: s.authorizer, 154 ID_: id, 155 }) 156 c.Assert(err, gc.Equals, apiservererrors.ErrPerm) 157 } 158 159 type machineStorageIdsWatcher interface { 160 Next() (params.MachineStorageIdsWatchResult, error) 161 } 162 163 type fakeStringsWatcher struct { 164 state.StringsWatcher 165 ch chan []string 166 } 167 168 func (w *fakeStringsWatcher) Changes() <-chan []string { 169 return w.ch 170 } 171 172 func (w *fakeStringsWatcher) Stop() error { 173 return nil 174 } 175 176 type fakeMigrationBackend struct { 177 noMigration bool 178 } 179 180 func (b *fakeMigrationBackend) LatestMigration() (state.ModelMigration, error) { 181 if b.noMigration { 182 return nil, errors.NotFoundf("migration") 183 } 184 return new(fakeModelMigration), nil 185 } 186 187 func (b *fakeMigrationBackend) APIHostPortsForClients() ([]network.SpaceHostPorts, error) { 188 return []network.SpaceHostPorts{ 189 { 190 network.SpaceHostPort{SpaceAddress: network.NewSpaceAddress("1.2.3.4"), NetPort: 5}, 191 network.SpaceHostPort{SpaceAddress: network.NewSpaceAddress("2.3.4.5"), NetPort: 6}, 192 }, { 193 network.SpaceHostPort{SpaceAddress: network.NewSpaceAddress("3.4.5.6"), NetPort: 7}, 194 }, 195 }, nil 196 } 197 198 func (b *fakeMigrationBackend) ControllerModel() (*state.Model, error) { 199 return nil, nil 200 } 201 202 func (b *fakeMigrationBackend) ControllerConfig() (controller.Config, error) { 203 return nil, nil 204 } 205 206 type fakeModelMigration struct { 207 state.ModelMigration 208 } 209 210 func (m *fakeModelMigration) Id() string { 211 return "id" 212 } 213 214 func (m *fakeModelMigration) Attempt() int { 215 return 2 216 } 217 218 func (m *fakeModelMigration) Phase() (migration.Phase, error) { 219 return migration.IMPORT, nil 220 } 221 222 func (m *fakeModelMigration) TargetInfo() (*migration.TargetInfo, error) { 223 return &migration.TargetInfo{ 224 ControllerTag: names.NewControllerTag("uuid"), 225 Addrs: []string{"1.2.3.4:5555"}, 226 CACert: "trust me", 227 AuthTag: names.NewUserTag("admin"), 228 Password: "sekret", 229 }, nil 230 } 231 232 type migrationStatusWatcher interface { 233 Next() (params.MigrationStatus, error) 234 Stop() error 235 } 236 237 func nopDispose() {}