github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/apiserver/storage/package_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package storage_test 5 6 import ( 7 stdtesting "testing" 8 9 "github.com/juju/errors" 10 "github.com/juju/names" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 "gopkg.in/juju/charm.v5" 14 15 "github.com/juju/juju/apiserver/common" 16 "github.com/juju/juju/apiserver/params" 17 "github.com/juju/juju/apiserver/storage" 18 "github.com/juju/juju/apiserver/testing" 19 "github.com/juju/juju/state" 20 jujustorage "github.com/juju/juju/storage" 21 coretesting "github.com/juju/juju/testing" 22 ) 23 24 func TestAll(t *stdtesting.T) { 25 gc.TestingT(t) 26 } 27 28 type baseStorageSuite struct { 29 coretesting.BaseSuite 30 31 resources *common.Resources 32 authorizer testing.FakeAuthorizer 33 34 api *storage.API 35 state *mockState 36 37 storageTag names.StorageTag 38 storageInstance *mockStorageInstance 39 unitTag names.UnitTag 40 machineTag names.MachineTag 41 42 volumeTag names.VolumeTag 43 volume state.Volume 44 volumeAttachment state.VolumeAttachment 45 calls []string 46 47 poolManager *mockPoolManager 48 pools map[string]*jujustorage.Config 49 50 blocks map[state.BlockType]state.Block 51 } 52 53 func (s *baseStorageSuite) SetUpTest(c *gc.C) { 54 s.BaseSuite.SetUpTest(c) 55 s.resources = common.NewResources() 56 s.authorizer = testing.FakeAuthorizer{names.NewUserTag("testuser"), true} 57 s.calls = []string{} 58 s.state = s.constructState(c) 59 60 s.pools = make(map[string]*jujustorage.Config) 61 s.poolManager = s.constructPoolManager(c) 62 63 var err error 64 s.api, err = storage.CreateAPI(s.state, s.poolManager, s.resources, s.authorizer) 65 c.Assert(err, jc.ErrorIsNil) 66 } 67 68 func (s *baseStorageSuite) assertCalls(c *gc.C, expectedCalls []string) { 69 c.Assert(s.calls, jc.SameContents, expectedCalls) 70 } 71 72 const ( 73 allStorageInstancesCall = "allStorageInstances" 74 storageInstanceAttachmentsCall = "storageInstanceAttachments" 75 unitAssignedMachineCall = "UnitAssignedMachine" 76 storageInstanceCall = "StorageInstance" 77 storageInstanceFilesystemCall = "StorageInstanceFilesystem" 78 storageInstanceFilesystemAttachmentCall = "storageInstanceFilesystemAttachment" 79 storageInstanceVolumeCall = "storageInstanceVolume" 80 volumeCall = "volumeCall" 81 machineVolumeAttachmentsCall = "machineVolumeAttachments" 82 volumeAttachmentsCall = "volumeAttachments" 83 allVolumesCall = "allVolumes" 84 addStorageForUnitCall = "addStorageForUnit" 85 getBlockForTypeCall = "getBlockForType" 86 ) 87 88 func (s *baseStorageSuite) constructState(c *gc.C) *mockState { 89 s.unitTag = names.NewUnitTag("mysql/0") 90 s.storageTag = names.NewStorageTag("data/0") 91 92 s.storageInstance = &mockStorageInstance{ 93 kind: state.StorageKindFilesystem, 94 owner: s.unitTag, 95 storageTag: s.storageTag, 96 } 97 98 storageInstanceAttachment := &mockStorageAttachment{storage: s.storageInstance} 99 100 s.machineTag = names.NewMachineTag("66") 101 filesystemTag := names.NewFilesystemTag("104") 102 s.volumeTag = names.NewVolumeTag("22") 103 filesystem := &mockFilesystem{tag: filesystemTag} 104 filesystemAttachment := &mockFilesystemAttachment{} 105 s.volume = &mockVolume{tag: s.volumeTag, storage: s.storageTag} 106 s.volumeAttachment = &mockVolumeAttachment{ 107 VolumeTag: s.volumeTag, 108 MachineTag: s.machineTag, 109 } 110 111 s.blocks = make(map[state.BlockType]state.Block) 112 return &mockState{ 113 allStorageInstances: func() ([]state.StorageInstance, error) { 114 s.calls = append(s.calls, allStorageInstancesCall) 115 return []state.StorageInstance{s.storageInstance}, nil 116 }, 117 storageInstance: func(sTag names.StorageTag) (state.StorageInstance, error) { 118 s.calls = append(s.calls, storageInstanceCall) 119 c.Assert(sTag, gc.DeepEquals, s.storageTag) 120 return s.storageInstance, nil 121 }, 122 storageInstanceAttachments: func(tag names.StorageTag) ([]state.StorageAttachment, error) { 123 s.calls = append(s.calls, storageInstanceAttachmentsCall) 124 c.Assert(tag, gc.DeepEquals, s.storageTag) 125 return []state.StorageAttachment{storageInstanceAttachment}, nil 126 }, 127 storageInstanceFilesystem: func(sTag names.StorageTag) (state.Filesystem, error) { 128 s.calls = append(s.calls, storageInstanceFilesystemCall) 129 c.Assert(sTag, gc.DeepEquals, s.storageTag) 130 return filesystem, nil 131 }, 132 storageInstanceFilesystemAttachment: func(m names.MachineTag, f names.FilesystemTag) (state.FilesystemAttachment, error) { 133 s.calls = append(s.calls, storageInstanceFilesystemAttachmentCall) 134 c.Assert(m, gc.DeepEquals, s.machineTag) 135 c.Assert(f, gc.DeepEquals, filesystemTag) 136 return filesystemAttachment, nil 137 }, 138 storageInstanceVolume: func(t names.StorageTag) (state.Volume, error) { 139 s.calls = append(s.calls, storageInstanceVolumeCall) 140 c.Assert(t, gc.DeepEquals, s.storageTag) 141 return s.volume, nil 142 }, 143 unitAssignedMachine: func(u names.UnitTag) (names.MachineTag, error) { 144 s.calls = append(s.calls, unitAssignedMachineCall) 145 c.Assert(u, gc.DeepEquals, s.unitTag) 146 return s.machineTag, nil 147 }, 148 volume: func(tag names.VolumeTag) (state.Volume, error) { 149 s.calls = append(s.calls, volumeCall) 150 c.Assert(tag, gc.DeepEquals, s.volumeTag) 151 return s.volume, nil 152 }, 153 machineVolumeAttachments: func(machine names.MachineTag) ([]state.VolumeAttachment, error) { 154 s.calls = append(s.calls, machineVolumeAttachmentsCall) 155 c.Assert(machine, gc.DeepEquals, s.machineTag) 156 return []state.VolumeAttachment{s.volumeAttachment}, nil 157 }, 158 volumeAttachments: func(volume names.VolumeTag) ([]state.VolumeAttachment, error) { 159 s.calls = append(s.calls, volumeAttachmentsCall) 160 c.Assert(volume, gc.DeepEquals, s.volumeTag) 161 return []state.VolumeAttachment{s.volumeAttachment}, nil 162 }, 163 allVolumes: func() ([]state.Volume, error) { 164 s.calls = append(s.calls, allVolumesCall) 165 return []state.Volume{s.volume}, nil 166 }, 167 envName: "storagetest", 168 addStorageForUnit: func(u names.UnitTag, name string, cons state.StorageConstraints) error { 169 s.calls = append(s.calls, addStorageForUnitCall) 170 return nil 171 }, 172 getBlockForType: func(t state.BlockType) (state.Block, bool, error) { 173 s.calls = append(s.calls, getBlockForTypeCall) 174 val, found := s.blocks[t] 175 return val, found, nil 176 }, 177 } 178 } 179 180 func (s *baseStorageSuite) addBlock(c *gc.C, t state.BlockType, msg string) { 181 s.blocks[t] = mockBlock{ 182 t: t, 183 msg: msg, 184 } 185 } 186 187 func (s *baseStorageSuite) blockAllChanges(c *gc.C, msg string) { 188 s.addBlock(c, state.ChangeBlock, msg) 189 } 190 191 func (s *baseStorageSuite) blockDestroyEnvironment(c *gc.C, msg string) { 192 s.addBlock(c, state.DestroyBlock, msg) 193 } 194 195 func (s *baseStorageSuite) blockRemoveObject(c *gc.C, msg string) { 196 s.addBlock(c, state.RemoveBlock, msg) 197 } 198 199 func (s *baseStorageSuite) assertBlocked(c *gc.C, err error, msg string) { 200 c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue) 201 c.Assert(err, gc.ErrorMatches, msg) 202 } 203 204 func (s *baseStorageSuite) constructPoolManager(c *gc.C) *mockPoolManager { 205 return &mockPoolManager{ 206 getPool: func(name string) (*jujustorage.Config, error) { 207 if one, ok := s.pools[name]; ok { 208 return one, nil 209 } 210 return nil, errors.NotFoundf("mock pool manager: get pool %v", name) 211 }, 212 createPool: func(name string, providerType jujustorage.ProviderType, attrs map[string]interface{}) (*jujustorage.Config, error) { 213 pool, err := jujustorage.NewConfig(name, providerType, attrs) 214 s.pools[name] = pool 215 return pool, err 216 }, 217 deletePool: func(name string) error { 218 delete(s.pools, name) 219 return nil 220 }, 221 listPools: func() ([]*jujustorage.Config, error) { 222 result := make([]*jujustorage.Config, len(s.pools)) 223 i := 0 224 for _, v := range s.pools { 225 result[i] = v 226 i++ 227 } 228 return result, nil 229 }, 230 } 231 } 232 233 type mockPoolManager struct { 234 getPool func(name string) (*jujustorage.Config, error) 235 createPool func(name string, providerType jujustorage.ProviderType, attrs map[string]interface{}) (*jujustorage.Config, error) 236 deletePool func(name string) error 237 listPools func() ([]*jujustorage.Config, error) 238 } 239 240 func (m *mockPoolManager) Get(name string) (*jujustorage.Config, error) { 241 return m.getPool(name) 242 } 243 244 func (m *mockPoolManager) Create(name string, providerType jujustorage.ProviderType, attrs map[string]interface{}) (*jujustorage.Config, error) { 245 return m.createPool(name, providerType, attrs) 246 } 247 248 func (m *mockPoolManager) Delete(name string) error { 249 return m.deletePool(name) 250 } 251 252 func (m *mockPoolManager) List() ([]*jujustorage.Config, error) { 253 return m.listPools() 254 } 255 256 type mockState struct { 257 storageInstance func(names.StorageTag) (state.StorageInstance, error) 258 allStorageInstances func() ([]state.StorageInstance, error) 259 storageInstanceAttachments func(names.StorageTag) ([]state.StorageAttachment, error) 260 unitAssignedMachine func(u names.UnitTag) (names.MachineTag, error) 261 storageInstanceVolume func(names.StorageTag) (state.Volume, error) 262 storageInstanceVolumeAttachment func(names.MachineTag, names.VolumeTag) (state.VolumeAttachment, error) 263 storageInstanceFilesystem func(names.StorageTag) (state.Filesystem, error) 264 storageInstanceFilesystemAttachment func(m names.MachineTag, f names.FilesystemTag) (state.FilesystemAttachment, error) 265 watchStorageAttachment func(names.StorageTag, names.UnitTag) state.NotifyWatcher 266 watchFilesystemAttachment func(names.MachineTag, names.FilesystemTag) state.NotifyWatcher 267 watchVolumeAttachment func(names.MachineTag, names.VolumeTag) state.NotifyWatcher 268 envName string 269 volume func(tag names.VolumeTag) (state.Volume, error) 270 machineVolumeAttachments func(machine names.MachineTag) ([]state.VolumeAttachment, error) 271 volumeAttachments func(volume names.VolumeTag) ([]state.VolumeAttachment, error) 272 allVolumes func() ([]state.Volume, error) 273 addStorageForUnit func(u names.UnitTag, name string, cons state.StorageConstraints) error 274 getBlockForType func(t state.BlockType) (state.Block, bool, error) 275 } 276 277 func (st *mockState) StorageInstance(s names.StorageTag) (state.StorageInstance, error) { 278 return st.storageInstance(s) 279 } 280 281 func (st *mockState) AllStorageInstances() ([]state.StorageInstance, error) { 282 return st.allStorageInstances() 283 } 284 285 func (st *mockState) StorageAttachments(tag names.StorageTag) ([]state.StorageAttachment, error) { 286 return st.storageInstanceAttachments(tag) 287 } 288 289 func (st *mockState) UnitAssignedMachine(unit names.UnitTag) (names.MachineTag, error) { 290 return st.unitAssignedMachine(unit) 291 } 292 293 func (st *mockState) FilesystemAttachment(m names.MachineTag, f names.FilesystemTag) (state.FilesystemAttachment, error) { 294 return st.storageInstanceFilesystemAttachment(m, f) 295 } 296 297 func (st *mockState) StorageInstanceFilesystem(s names.StorageTag) (state.Filesystem, error) { 298 return st.storageInstanceFilesystem(s) 299 } 300 301 func (st *mockState) StorageInstanceVolume(s names.StorageTag) (state.Volume, error) { 302 return st.storageInstanceVolume(s) 303 } 304 305 func (st *mockState) VolumeAttachment(m names.MachineTag, v names.VolumeTag) (state.VolumeAttachment, error) { 306 return st.storageInstanceVolumeAttachment(m, v) 307 } 308 309 func (st *mockState) WatchStorageAttachment(s names.StorageTag, u names.UnitTag) state.NotifyWatcher { 310 return st.watchStorageAttachment(s, u) 311 } 312 313 func (st *mockState) WatchFilesystemAttachment(mtag names.MachineTag, f names.FilesystemTag) state.NotifyWatcher { 314 return st.watchFilesystemAttachment(mtag, f) 315 } 316 317 func (st *mockState) WatchVolumeAttachment(mtag names.MachineTag, v names.VolumeTag) state.NotifyWatcher { 318 return st.watchVolumeAttachment(mtag, v) 319 } 320 321 func (st *mockState) EnvName() (string, error) { 322 return st.envName, nil 323 } 324 325 func (st *mockState) AllVolumes() ([]state.Volume, error) { 326 return st.allVolumes() 327 } 328 329 func (st *mockState) VolumeAttachments(volume names.VolumeTag) ([]state.VolumeAttachment, error) { 330 return st.volumeAttachments(volume) 331 } 332 333 func (st *mockState) MachineVolumeAttachments(machine names.MachineTag) ([]state.VolumeAttachment, error) { 334 return st.machineVolumeAttachments(machine) 335 } 336 337 func (st *mockState) Volume(tag names.VolumeTag) (state.Volume, error) { 338 return st.volume(tag) 339 } 340 341 func (st *mockState) AddStorageForUnit(u names.UnitTag, name string, cons state.StorageConstraints) error { 342 return st.addStorageForUnit(u, name, cons) 343 } 344 345 func (st *mockState) GetBlockForType(t state.BlockType) (state.Block, bool, error) { 346 return st.getBlockForType(t) 347 } 348 349 type mockNotifyWatcher struct { 350 state.NotifyWatcher 351 changes chan struct{} 352 } 353 354 func (m *mockNotifyWatcher) Changes() <-chan struct{} { 355 return m.changes 356 } 357 358 type mockVolume struct { 359 state.Volume 360 tag names.VolumeTag 361 storage names.StorageTag 362 hasNoStorage bool 363 } 364 365 func (m *mockVolume) StorageInstance() (names.StorageTag, error) { 366 if m.hasNoStorage { 367 return names.StorageTag{}, errors.NewNotAssigned(nil, "error from mock") 368 } 369 return m.storage, nil 370 } 371 372 func (m *mockVolume) VolumeTag() names.VolumeTag { 373 return m.tag 374 } 375 376 func (m *mockVolume) Params() (state.VolumeParams, bool) { 377 return state.VolumeParams{ 378 Pool: "loop", 379 Size: 1024, 380 }, true 381 } 382 383 func (m *mockVolume) Info() (state.VolumeInfo, error) { 384 return state.VolumeInfo{}, errors.NotProvisionedf("%v", m.tag) 385 } 386 387 func (m *mockVolume) Status() (state.StatusInfo, error) { 388 return state.StatusInfo{Status: state.StatusAttached}, nil 389 } 390 391 type mockFilesystem struct { 392 state.Filesystem 393 tag names.FilesystemTag 394 } 395 396 func (m *mockFilesystem) FilesystemTag() names.FilesystemTag { 397 return m.tag 398 } 399 400 type mockFilesystemAttachment struct { 401 state.FilesystemAttachment 402 tag names.FilesystemTag 403 } 404 405 func (m *mockFilesystemAttachment) Filesystem() names.FilesystemTag { 406 return m.tag 407 } 408 409 func (m *mockFilesystemAttachment) Info() (state.FilesystemAttachmentInfo, error) { 410 return state.FilesystemAttachmentInfo{}, nil 411 } 412 413 type mockStorageInstance struct { 414 state.StorageInstance 415 kind state.StorageKind 416 owner names.Tag 417 storageTag names.Tag 418 } 419 420 func (m *mockStorageInstance) Kind() state.StorageKind { 421 return m.kind 422 } 423 424 func (m *mockStorageInstance) Owner() names.Tag { 425 return m.owner 426 } 427 428 func (m *mockStorageInstance) Tag() names.Tag { 429 return m.storageTag 430 } 431 432 func (m *mockStorageInstance) StorageTag() names.StorageTag { 433 return m.storageTag.(names.StorageTag) 434 } 435 436 func (m *mockStorageInstance) CharmURL() *charm.URL { 437 panic("not implemented for test") 438 } 439 440 type mockStorageAttachment struct { 441 state.StorageAttachment 442 storage *mockStorageInstance 443 } 444 445 func (m *mockStorageAttachment) StorageInstance() names.StorageTag { 446 return m.storage.Tag().(names.StorageTag) 447 } 448 449 func (m *mockStorageAttachment) Unit() names.UnitTag { 450 return m.storage.Owner().(names.UnitTag) 451 } 452 453 type mockVolumeAttachment struct { 454 VolumeTag names.VolumeTag 455 MachineTag names.MachineTag 456 } 457 458 func (va *mockVolumeAttachment) Volume() names.VolumeTag { 459 return va.VolumeTag 460 } 461 462 func (va *mockVolumeAttachment) Machine() names.MachineTag { 463 return va.MachineTag 464 } 465 466 func (va *mockVolumeAttachment) Life() state.Life { 467 panic("not implemented for test") 468 } 469 470 func (va *mockVolumeAttachment) Info() (state.VolumeAttachmentInfo, error) { 471 return state.VolumeAttachmentInfo{}, errors.New("not interested yet") 472 } 473 474 func (va *mockVolumeAttachment) Params() (state.VolumeAttachmentParams, bool) { 475 panic("not implemented for test") 476 } 477 478 type mockBlock struct { 479 state.Block 480 t state.BlockType 481 msg string 482 } 483 484 func (b mockBlock) Type() state.BlockType { 485 return b.t 486 } 487 488 func (b mockBlock) Message() string { 489 return b.msg 490 }