github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/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{t, msg} 182 } 183 184 func (s *baseStorageSuite) blockAllChanges(c *gc.C, msg string) { 185 s.addBlock(c, state.ChangeBlock, msg) 186 } 187 188 func (s *baseStorageSuite) blockDestroyEnvironment(c *gc.C, msg string) { 189 s.addBlock(c, state.DestroyBlock, msg) 190 } 191 192 func (s *baseStorageSuite) blockRemoveObject(c *gc.C, msg string) { 193 s.addBlock(c, state.RemoveBlock, msg) 194 } 195 196 func (s *baseStorageSuite) assertBlocked(c *gc.C, err error, msg string) { 197 c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue) 198 c.Assert(err, gc.ErrorMatches, msg) 199 } 200 201 func (s *baseStorageSuite) constructPoolManager(c *gc.C) *mockPoolManager { 202 return &mockPoolManager{ 203 getPool: func(name string) (*jujustorage.Config, error) { 204 if one, ok := s.pools[name]; ok { 205 return one, nil 206 } 207 return nil, errors.NotFoundf("mock pool manager: get pool %v", name) 208 }, 209 createPool: func(name string, providerType jujustorage.ProviderType, attrs map[string]interface{}) (*jujustorage.Config, error) { 210 pool, err := jujustorage.NewConfig(name, providerType, attrs) 211 s.pools[name] = pool 212 return pool, err 213 }, 214 deletePool: func(name string) error { 215 delete(s.pools, name) 216 return nil 217 }, 218 listPools: func() ([]*jujustorage.Config, error) { 219 result := make([]*jujustorage.Config, len(s.pools)) 220 i := 0 221 for _, v := range s.pools { 222 result[i] = v 223 i++ 224 } 225 return result, nil 226 }, 227 } 228 } 229 230 type mockPoolManager struct { 231 getPool func(name string) (*jujustorage.Config, error) 232 createPool func(name string, providerType jujustorage.ProviderType, attrs map[string]interface{}) (*jujustorage.Config, error) 233 deletePool func(name string) error 234 listPools func() ([]*jujustorage.Config, error) 235 } 236 237 func (m *mockPoolManager) Get(name string) (*jujustorage.Config, error) { 238 return m.getPool(name) 239 } 240 241 func (m *mockPoolManager) Create(name string, providerType jujustorage.ProviderType, attrs map[string]interface{}) (*jujustorage.Config, error) { 242 return m.createPool(name, providerType, attrs) 243 } 244 245 func (m *mockPoolManager) Delete(name string) error { 246 return m.deletePool(name) 247 } 248 249 func (m *mockPoolManager) List() ([]*jujustorage.Config, error) { 250 return m.listPools() 251 } 252 253 type mockState struct { 254 storageInstance func(names.StorageTag) (state.StorageInstance, error) 255 allStorageInstances func() ([]state.StorageInstance, error) 256 storageInstanceAttachments func(names.StorageTag) ([]state.StorageAttachment, error) 257 unitAssignedMachine func(u names.UnitTag) (names.MachineTag, error) 258 storageInstanceVolume func(names.StorageTag) (state.Volume, error) 259 storageInstanceVolumeAttachment func(names.MachineTag, names.VolumeTag) (state.VolumeAttachment, error) 260 storageInstanceFilesystem func(names.StorageTag) (state.Filesystem, error) 261 storageInstanceFilesystemAttachment func(m names.MachineTag, f names.FilesystemTag) (state.FilesystemAttachment, error) 262 watchStorageAttachment func(names.StorageTag, names.UnitTag) state.NotifyWatcher 263 watchFilesystemAttachment func(names.MachineTag, names.FilesystemTag) state.NotifyWatcher 264 watchVolumeAttachment func(names.MachineTag, names.VolumeTag) state.NotifyWatcher 265 envName string 266 volume func(tag names.VolumeTag) (state.Volume, error) 267 machineVolumeAttachments func(machine names.MachineTag) ([]state.VolumeAttachment, error) 268 volumeAttachments func(volume names.VolumeTag) ([]state.VolumeAttachment, error) 269 allVolumes func() ([]state.Volume, error) 270 addStorageForUnit func(u names.UnitTag, name string, cons state.StorageConstraints) error 271 getBlockForType func(t state.BlockType) (state.Block, bool, error) 272 } 273 274 func (st *mockState) StorageInstance(s names.StorageTag) (state.StorageInstance, error) { 275 return st.storageInstance(s) 276 } 277 278 func (st *mockState) AllStorageInstances() ([]state.StorageInstance, error) { 279 return st.allStorageInstances() 280 } 281 282 func (st *mockState) StorageAttachments(tag names.StorageTag) ([]state.StorageAttachment, error) { 283 return st.storageInstanceAttachments(tag) 284 } 285 286 func (st *mockState) UnitAssignedMachine(unit names.UnitTag) (names.MachineTag, error) { 287 return st.unitAssignedMachine(unit) 288 } 289 290 func (st *mockState) FilesystemAttachment(m names.MachineTag, f names.FilesystemTag) (state.FilesystemAttachment, error) { 291 return st.storageInstanceFilesystemAttachment(m, f) 292 } 293 294 func (st *mockState) StorageInstanceFilesystem(s names.StorageTag) (state.Filesystem, error) { 295 return st.storageInstanceFilesystem(s) 296 } 297 298 func (st *mockState) StorageInstanceVolume(s names.StorageTag) (state.Volume, error) { 299 return st.storageInstanceVolume(s) 300 } 301 302 func (st *mockState) VolumeAttachment(m names.MachineTag, v names.VolumeTag) (state.VolumeAttachment, error) { 303 return st.storageInstanceVolumeAttachment(m, v) 304 } 305 306 func (st *mockState) WatchStorageAttachment(s names.StorageTag, u names.UnitTag) state.NotifyWatcher { 307 return st.watchStorageAttachment(s, u) 308 } 309 310 func (st *mockState) WatchFilesystemAttachment(mtag names.MachineTag, f names.FilesystemTag) state.NotifyWatcher { 311 return st.watchFilesystemAttachment(mtag, f) 312 } 313 314 func (st *mockState) WatchVolumeAttachment(mtag names.MachineTag, v names.VolumeTag) state.NotifyWatcher { 315 return st.watchVolumeAttachment(mtag, v) 316 } 317 318 func (st *mockState) EnvName() (string, error) { 319 return st.envName, nil 320 } 321 322 func (st *mockState) AllVolumes() ([]state.Volume, error) { 323 return st.allVolumes() 324 } 325 326 func (st *mockState) VolumeAttachments(volume names.VolumeTag) ([]state.VolumeAttachment, error) { 327 return st.volumeAttachments(volume) 328 } 329 330 func (st *mockState) MachineVolumeAttachments(machine names.MachineTag) ([]state.VolumeAttachment, error) { 331 return st.machineVolumeAttachments(machine) 332 } 333 334 func (st *mockState) Volume(tag names.VolumeTag) (state.Volume, error) { 335 return st.volume(tag) 336 } 337 338 func (st *mockState) AddStorageForUnit(u names.UnitTag, name string, cons state.StorageConstraints) error { 339 return st.addStorageForUnit(u, name, cons) 340 } 341 342 func (st *mockState) GetBlockForType(t state.BlockType) (state.Block, bool, error) { 343 return st.getBlockForType(t) 344 } 345 346 type mockNotifyWatcher struct { 347 state.NotifyWatcher 348 changes chan struct{} 349 } 350 351 func (m *mockNotifyWatcher) Changes() <-chan struct{} { 352 return m.changes 353 } 354 355 type mockVolume struct { 356 state.Volume 357 tag names.VolumeTag 358 storage names.StorageTag 359 hasNoStorage bool 360 } 361 362 func (m *mockVolume) StorageInstance() (names.StorageTag, error) { 363 if m.hasNoStorage { 364 return names.StorageTag{}, errors.NewNotAssigned(nil, "error from mock") 365 } 366 return m.storage, nil 367 } 368 369 func (m *mockVolume) VolumeTag() names.VolumeTag { 370 return m.tag 371 } 372 373 func (m *mockVolume) Params() (state.VolumeParams, bool) { 374 return state.VolumeParams{ 375 Pool: "loop", 376 Size: 1024, 377 }, true 378 } 379 380 func (m *mockVolume) Info() (state.VolumeInfo, error) { 381 return state.VolumeInfo{}, errors.NotProvisionedf("%v", m.tag) 382 } 383 384 type mockFilesystem struct { 385 state.Filesystem 386 tag names.FilesystemTag 387 } 388 389 func (m *mockFilesystem) FilesystemTag() names.FilesystemTag { 390 return m.tag 391 } 392 393 type mockFilesystemAttachment struct { 394 state.FilesystemAttachment 395 tag names.FilesystemTag 396 } 397 398 func (m *mockFilesystemAttachment) Filesystem() names.FilesystemTag { 399 return m.tag 400 } 401 402 func (m *mockFilesystemAttachment) Info() (state.FilesystemAttachmentInfo, error) { 403 return state.FilesystemAttachmentInfo{}, nil 404 } 405 406 type mockStorageInstance struct { 407 state.StorageInstance 408 kind state.StorageKind 409 owner names.Tag 410 storageTag names.Tag 411 } 412 413 func (m *mockStorageInstance) Kind() state.StorageKind { 414 return m.kind 415 } 416 417 func (m *mockStorageInstance) Owner() names.Tag { 418 return m.owner 419 } 420 421 func (m *mockStorageInstance) Tag() names.Tag { 422 return m.storageTag 423 } 424 425 func (m *mockStorageInstance) StorageTag() names.StorageTag { 426 return m.storageTag.(names.StorageTag) 427 } 428 429 func (m *mockStorageInstance) CharmURL() *charm.URL { 430 panic("not implemented for test") 431 } 432 433 type mockStorageAttachment struct { 434 state.StorageAttachment 435 storage *mockStorageInstance 436 } 437 438 func (m *mockStorageAttachment) StorageInstance() names.StorageTag { 439 return m.storage.Tag().(names.StorageTag) 440 } 441 442 func (m *mockStorageAttachment) Unit() names.UnitTag { 443 return m.storage.Owner().(names.UnitTag) 444 } 445 446 type mockVolumeAttachment struct { 447 VolumeTag names.VolumeTag 448 MachineTag names.MachineTag 449 } 450 451 func (va *mockVolumeAttachment) Volume() names.VolumeTag { 452 return va.VolumeTag 453 } 454 455 func (va *mockVolumeAttachment) Machine() names.MachineTag { 456 return va.MachineTag 457 } 458 459 func (va *mockVolumeAttachment) Life() state.Life { 460 panic("not implemented for test") 461 } 462 463 func (va *mockVolumeAttachment) Info() (state.VolumeAttachmentInfo, error) { 464 return state.VolumeAttachmentInfo{}, errors.New("not interested yet") 465 } 466 467 func (va *mockVolumeAttachment) Params() (state.VolumeAttachmentParams, bool) { 468 panic("not implemented for test") 469 } 470 471 type mockBlock struct { 472 t state.BlockType 473 msg string 474 } 475 476 func (b mockBlock) Id() string { 477 panic("not implemented for test") 478 } 479 480 func (b mockBlock) Tag() (names.Tag, error) { 481 panic("not implemented for test") 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 }