github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/client/application/mock_test.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package application_test 5 6 import ( 7 "io" 8 "strings" 9 "sync" 10 11 "github.com/juju/collections/set" 12 "github.com/juju/errors" 13 "github.com/juju/juju/caas" 14 "github.com/juju/juju/storage/provider" 15 "github.com/juju/schema" 16 jtesting "github.com/juju/testing" 17 "gopkg.in/juju/charm.v6" 18 csparams "gopkg.in/juju/charmrepo.v3/csclient/params" 19 "gopkg.in/juju/environschema.v1" 20 "gopkg.in/juju/names.v2" 21 "gopkg.in/macaroon.v2-unstable" 22 23 "github.com/juju/juju/apiserver/common/storagecommon" 24 "github.com/juju/juju/apiserver/facades/client/application" 25 coreapplication "github.com/juju/juju/core/application" 26 "github.com/juju/juju/core/constraints" 27 "github.com/juju/juju/core/crossmodel" 28 "github.com/juju/juju/core/instance" 29 "github.com/juju/juju/core/status" 30 "github.com/juju/juju/environs" 31 "github.com/juju/juju/network" 32 "github.com/juju/juju/state" 33 statestorage "github.com/juju/juju/state/storage" 34 "github.com/juju/juju/storage" 35 "github.com/juju/juju/storage/poolmanager" 36 coretesting "github.com/juju/juju/testing" 37 ) 38 39 type mockEnviron struct { 40 environs.NetworkingEnviron 41 42 stub jtesting.Stub 43 spaceInfo *environs.ProviderSpaceInfo 44 } 45 46 func (e *mockEnviron) ProviderSpaceInfo(space *network.SpaceInfo) (*environs.ProviderSpaceInfo, error) { 47 e.stub.MethodCall(e, "ProviderSpaceInfo", space) 48 return e.spaceInfo, e.stub.NextErr() 49 } 50 51 type mockNoNetworkEnviron struct { 52 environs.Environ 53 } 54 55 type mockCharm struct { 56 jtesting.Stub 57 58 charm.Charm 59 config *charm.Config 60 meta *charm.Meta 61 } 62 63 func (m *mockCharm) Meta() *charm.Meta { 64 m.MethodCall(m, "Meta") 65 return m.meta 66 } 67 68 func (c *mockCharm) Config() *charm.Config { 69 c.MethodCall(c, "Config") 70 c.PopNoErr() 71 return c.config 72 } 73 74 type mockApplication struct { 75 jtesting.Stub 76 application.Application 77 78 bindings map[string]string 79 charm *mockCharm 80 curl *charm.URL 81 endpoints []state.Endpoint 82 name string 83 scale int 84 subordinate bool 85 series string 86 units []*mockUnit 87 addedUnit mockUnit 88 config coreapplication.ConfigAttributes 89 lxdProfileUpgradeChanges chan struct{} 90 constraints constraints.Value 91 channel csparams.Channel 92 exposed bool 93 remote bool 94 } 95 96 func (m *mockApplication) Name() string { 97 m.MethodCall(m, "Name") 98 return m.name 99 } 100 101 func (m *mockApplication) Channel() csparams.Channel { 102 m.MethodCall(m, "Channel") 103 return m.channel 104 } 105 106 func (m *mockApplication) Charm() (application.Charm, bool, error) { 107 m.MethodCall(m, "Charm") 108 return m.charm, true, nil 109 } 110 111 func (m *mockApplication) CharmURL() (curl *charm.URL, force bool) { 112 m.MethodCall(m, "CharmURL") 113 return m.curl, true 114 } 115 116 func (m *mockApplication) CharmConfig() (charm.Settings, error) { 117 m.MethodCall(m, "CharmConfig") 118 return m.charm.config.DefaultSettings(), m.NextErr() 119 } 120 121 func (m *mockApplication) Constraints() (constraints.Value, error) { 122 m.MethodCall(m, "Constraints") 123 return m.constraints, nil 124 } 125 126 func (m *mockApplication) Endpoints() ([]state.Endpoint, error) { 127 m.MethodCall(m, "Endpoints") 128 return m.endpoints, nil 129 } 130 131 func (m *mockApplication) EndpointBindings() (map[string]string, error) { 132 m.MethodCall(m, "EndpointBindings") 133 return m.bindings, m.NextErr() 134 } 135 136 func (a *mockApplication) AllUnits() ([]application.Unit, error) { 137 a.MethodCall(a, "AllUnits") 138 if err := a.NextErr(); err != nil { 139 return nil, err 140 } 141 units := make([]application.Unit, len(a.units)) 142 for i := range a.units { 143 units[i] = a.units[i] 144 } 145 return units, nil 146 } 147 148 func (a *mockApplication) SetCharmProfile(charmURL string) error { 149 a.MethodCall(a, "SetCharmProfile", charmURL) 150 return a.NextErr() 151 } 152 153 func (a *mockApplication) SetCharm(cfg state.SetCharmConfig) error { 154 a.MethodCall(a, "SetCharm", cfg) 155 return a.NextErr() 156 } 157 158 func (a *mockApplication) DestroyOperation() *state.DestroyApplicationOperation { 159 a.MethodCall(a, "DestroyOperation") 160 return &state.DestroyApplicationOperation{} 161 } 162 163 func (a *mockApplication) AddUnit(args state.AddUnitParams) (application.Unit, error) { 164 a.MethodCall(a, "AddUnit", args) 165 if err := a.NextErr(); err != nil { 166 return nil, err 167 } 168 return &a.addedUnit, nil 169 } 170 171 func (a *mockApplication) GetScale() int { 172 a.MethodCall(a, "GetScale") 173 return a.scale 174 } 175 176 func (a *mockApplication) ChangeScale(scaleChange int) (int, error) { 177 a.MethodCall(a, "ChangeScale", scaleChange) 178 if err := a.NextErr(); err != nil { 179 return a.scale, err 180 } 181 return a.scale + scaleChange, nil 182 } 183 184 func (a *mockApplication) Scale(scale int) error { 185 a.MethodCall(a, "Scale", scale) 186 if err := a.NextErr(); err != nil { 187 return err 188 } 189 return nil 190 } 191 192 func (a *mockApplication) IsPrincipal() bool { 193 a.MethodCall(a, "IsPrincipal") 194 a.PopNoErr() 195 return !a.subordinate 196 } 197 198 func (a *mockApplication) UpdateApplicationSeries(series string, force bool) error { 199 a.MethodCall(a, "UpdateApplicationSeries", series, force) 200 return a.NextErr() 201 } 202 203 func (a *mockApplication) Series() string { 204 a.MethodCall(a, "Series") 205 a.PopNoErr() 206 return a.series 207 } 208 209 func (a *mockApplication) ApplicationConfig() (coreapplication.ConfigAttributes, error) { 210 a.MethodCall(a, "ApplicationConfig") 211 return a.config, a.NextErr() 212 } 213 214 func (a *mockApplication) UpdateApplicationConfig( 215 changes coreapplication.ConfigAttributes, 216 reset []string, 217 extra environschema.Fields, 218 defaults schema.Defaults, 219 ) error { 220 a.MethodCall(a, "UpdateApplicationConfig", changes, reset, extra, defaults) 221 return a.NextErr() 222 } 223 224 func (a *mockApplication) UpdateCharmConfig(settings charm.Settings) error { 225 a.MethodCall(a, "UpdateCharmConfig", settings) 226 return a.NextErr() 227 } 228 229 func (a *mockApplication) SetExposed() error { 230 a.MethodCall(a, "SetExposed") 231 return a.NextErr() 232 } 233 234 func (a *mockApplication) WatchLXDProfileUpgradeNotifications() (state.NotifyWatcher, error) { 235 a.MethodCall(a, "WatchLXDProfileUpgradeNotifications") 236 return &mockNotifyWatcher{ch: a.lxdProfileUpgradeChanges}, a.NextErr() 237 } 238 239 func (a *mockApplication) IsExposed() bool { 240 a.MethodCall(a, "IsExposed") 241 return a.exposed 242 } 243 244 func (a *mockApplication) IsRemote() bool { 245 a.MethodCall(a, "IsRemote") 246 return a.remote 247 } 248 249 type mockNotifyWatcher struct { 250 state.NotifyWatcher 251 jtesting.Stub 252 ch chan struct{} 253 } 254 255 func (m *mockNotifyWatcher) Changes() <-chan struct{} { 256 m.MethodCall(m, "Changes") 257 return m.ch 258 } 259 260 func (m *mockNotifyWatcher) Err() error { 261 return m.NextErr() 262 } 263 264 type mockRemoteApplication struct { 265 jtesting.Stub 266 name string 267 sourceModelTag names.ModelTag 268 endpoints []state.Endpoint 269 bindings map[string]string 270 spaces []state.RemoteSpace 271 offerUUID string 272 offerURL string 273 mac *macaroon.Macaroon 274 } 275 276 func (m *mockRemoteApplication) Name() string { 277 return m.name 278 } 279 280 func (m *mockRemoteApplication) SourceModel() names.ModelTag { 281 return m.sourceModelTag 282 } 283 284 func (m *mockRemoteApplication) Endpoints() ([]state.Endpoint, error) { 285 return m.endpoints, nil 286 } 287 288 func (m *mockRemoteApplication) Bindings() map[string]string { 289 return m.bindings 290 } 291 292 func (m *mockRemoteApplication) Spaces() []state.RemoteSpace { 293 return m.spaces 294 } 295 296 func (m *mockRemoteApplication) AddEndpoints(eps []charm.Relation) error { 297 for _, ep := range eps { 298 m.endpoints = append(m.endpoints, state.Endpoint{ 299 ApplicationName: m.name, 300 Relation: charm.Relation{ 301 Name: ep.Name, 302 Interface: ep.Interface, 303 Role: ep.Role, 304 }, 305 }) 306 } 307 return nil 308 } 309 310 func (m *mockRemoteApplication) Destroy() error { 311 m.MethodCall(m, "Destroy") 312 return nil 313 } 314 315 type mockBackend struct { 316 jtesting.Stub 317 application.Backend 318 319 charm *mockCharm 320 allmodels []application.Model 321 users set.Strings 322 applications map[string]*mockApplication 323 remoteApplications map[string]application.RemoteApplication 324 endpoints *[]state.Endpoint 325 relations map[int]*mockRelation 326 offerConnections map[string]application.OfferConnection 327 unitStorageAttachments map[string][]state.StorageAttachment 328 storageInstances map[string]*mockStorage 329 storageInstanceFilesystems map[string]*mockFilesystem 330 controllers map[string]crossmodel.ControllerInfo 331 machines map[string]*mockMachine 332 } 333 334 type mockFilesystemAccess struct { 335 storagecommon.FilesystemAccess 336 *mockBackend 337 } 338 339 func (m *mockBackend) VolumeAccess() storagecommon.VolumeAccess { 340 return nil 341 } 342 343 func (m *mockBackend) FilesystemAccess() storagecommon.FilesystemAccess { 344 return &mockFilesystemAccess{mockBackend: m} 345 } 346 347 func (m *mockBackend) ControllerTag() names.ControllerTag { 348 return coretesting.ControllerTag 349 } 350 351 func (m *mockBackend) GetBlockForType(t state.BlockType) (state.Block, bool, error) { 352 return nil, false, nil 353 } 354 355 func (m *mockBackend) Charm(curl *charm.URL) (application.Charm, error) { 356 m.MethodCall(m, "Charm", curl) 357 if err := m.NextErr(); err != nil { 358 return nil, err 359 } 360 if m.charm != nil { 361 return m.charm, nil 362 } 363 return nil, errors.NotFoundf("charm %q", curl) 364 } 365 366 func (m *mockBackend) Unit(name string) (application.Unit, error) { 367 m.MethodCall(m, "Unit", name) 368 if err := m.NextErr(); err != nil { 369 return nil, err 370 } 371 var unitApp *mockApplication 372 for appName, app := range m.applications { 373 if strings.HasPrefix(name, appName+"/") { 374 unitApp = app 375 break 376 } 377 } 378 if unitApp != nil { 379 for _, u := range unitApp.units { 380 if u.tag.Id() == name { 381 return u, nil 382 } 383 } 384 } 385 return nil, errors.NotFoundf("unit %q", name) 386 } 387 388 func (m *mockBackend) UnitsInError() ([]application.Unit, error) { 389 return []application.Unit{ 390 m.applications["postgresql"].units[0], 391 }, nil 392 } 393 394 func (m *mockBackend) Machine(id string) (application.Machine, error) { 395 m.MethodCall(m, "Machine", id) 396 for machineId, machine := range m.machines { 397 if id == machineId { 398 return machine, nil 399 } 400 } 401 return nil, errors.NotFoundf("machine %q", id) 402 } 403 404 type mockMachine struct { 405 jtesting.Stub 406 407 id string 408 upgradeCharmProfileComplete string 409 } 410 411 func (m *mockMachine) IsLockedForSeriesUpgrade() (bool, error) { 412 m.MethodCall(m, "IsLockedForSeriesUpgrade") 413 return false, m.NextErr() 414 } 415 416 func (m *mockMachine) IsParentLockedForSeriesUpgrade() (bool, error) { 417 m.MethodCall(m, "IsParentLockedForSeriesUpgrade") 418 return false, m.NextErr() 419 } 420 421 func (m *mockMachine) Id() string { 422 m.MethodCall(m, "Id") 423 return m.id 424 } 425 426 func (m *mockMachine) UpgradeCharmProfileComplete() (string, error) { 427 m.MethodCall(m, "UpgradeCharmProfileComplete") 428 return m.upgradeCharmProfileComplete, m.NextErr() 429 } 430 431 func (m *mockMachine) RemoveUpgradeCharmProfileData() error { 432 m.MethodCall(m, "RemoveUpgradeCharmProfileData") 433 return m.NextErr() 434 } 435 436 func (m *mockBackend) InferEndpoints(endpoints ...string) ([]state.Endpoint, error) { 437 m.MethodCall(m, "InferEndpoints", endpoints) 438 if err := m.NextErr(); err != nil { 439 return nil, err 440 } 441 if m.endpoints != nil { 442 return *m.endpoints, nil 443 } 444 return nil, errors.Errorf("no relations found") 445 } 446 447 func (m *mockBackend) EndpointsRelation(endpoints ...state.Endpoint) (application.Relation, error) { 448 m.MethodCall(m, "EndpointsRelation", endpoints) 449 if err := m.NextErr(); err != nil { 450 return nil, err 451 } 452 if rel, ok := m.relations[123]; ok { 453 return rel, nil 454 } 455 return nil, errors.NotFoundf("relation") 456 } 457 458 func (m *mockBackend) Relation(id int) (application.Relation, error) { 459 m.MethodCall(m, "Relation", id) 460 if err := m.NextErr(); err != nil { 461 return nil, err 462 } 463 if rel, ok := m.relations[id]; ok { 464 return rel, nil 465 } 466 return nil, errors.NotFoundf("relation") 467 } 468 469 type mockOfferConnection struct { 470 application.OfferConnection 471 } 472 473 func (m *mockBackend) OfferConnectionForRelation(key string) (application.OfferConnection, error) { 474 m.MethodCall(m, "OfferConnectionForRelation", key) 475 if err := m.NextErr(); err != nil { 476 return nil, err 477 } 478 if oc, ok := m.offerConnections[key]; ok { 479 return oc, nil 480 } 481 return nil, errors.NotFoundf("offer connection for relation") 482 } 483 484 func (m *mockBackend) UnitStorageAttachments(tag names.UnitTag) ([]state.StorageAttachment, error) { 485 m.MethodCall(m, "UnitStorageAttachments", tag) 486 if err := m.NextErr(); err != nil { 487 return nil, err 488 } 489 return m.unitStorageAttachments[tag.Id()], nil 490 } 491 492 func (m *mockBackend) StorageInstance(tag names.StorageTag) (state.StorageInstance, error) { 493 m.MethodCall(m, "StorageInstance", tag) 494 if err := m.NextErr(); err != nil { 495 return nil, err 496 } 497 s, ok := m.storageInstances[tag.Id()] 498 if !ok { 499 return nil, errors.NotFoundf("storage %s", tag.Id()) 500 } 501 return s, nil 502 } 503 504 func (m *mockFilesystemAccess) StorageInstanceFilesystem(tag names.StorageTag) (state.Filesystem, error) { 505 m.MethodCall(m, "StorageInstanceFilesystem", tag) 506 if err := m.NextErr(); err != nil { 507 return nil, err 508 } 509 f, ok := m.storageInstanceFilesystems[tag.Id()] 510 if !ok { 511 return nil, errors.NotFoundf("filesystem for storage %s", tag.Id()) 512 } 513 return f, nil 514 } 515 516 func (m *mockBackend) AddRemoteApplication(args state.AddRemoteApplicationParams) (application.RemoteApplication, error) { 517 m.MethodCall(m, "AddRemoteApplication", args) 518 if err := m.NextErr(); err != nil { 519 return nil, err 520 } 521 app := &mockRemoteApplication{ 522 name: args.Name, 523 sourceModelTag: args.SourceModel, 524 offerUUID: args.OfferUUID, 525 offerURL: args.URL, 526 bindings: args.Bindings, 527 mac: args.Macaroon, 528 } 529 for _, ep := range args.Endpoints { 530 app.endpoints = append(app.endpoints, state.Endpoint{ 531 ApplicationName: app.name, 532 Relation: charm.Relation{ 533 Name: ep.Name, 534 Interface: ep.Interface, 535 Role: ep.Role, 536 }, 537 }) 538 } 539 for _, sp := range args.Spaces { 540 remoteSpaceInfo := state.RemoteSpace{ 541 CloudType: sp.CloudType, 542 Name: sp.Name, 543 ProviderId: string(sp.ProviderId), 544 ProviderAttributes: sp.ProviderAttributes, 545 } 546 for _, sn := range sp.Subnets { 547 remoteSpaceInfo.Subnets = append(remoteSpaceInfo.Subnets, state.RemoteSubnet{ 548 CIDR: sn.CIDR, 549 VLANTag: sn.VLANTag, 550 ProviderId: string(sn.ProviderId), 551 ProviderNetworkId: string(sn.ProviderNetworkId), 552 AvailabilityZones: sn.AvailabilityZones, 553 }) 554 } 555 app.spaces = append(app.spaces, remoteSpaceInfo) 556 } 557 m.remoteApplications[app.name] = app 558 return app, nil 559 } 560 561 func (m *mockBackend) RemoteApplication(name string) (application.RemoteApplication, error) { 562 m.MethodCall(m, "RemoteApplication", name) 563 if err := m.NextErr(); err != nil { 564 return nil, err 565 } 566 app, ok := m.remoteApplications[name] 567 if !ok { 568 return nil, errors.NotFoundf("remote application %q", name) 569 } 570 return app, nil 571 } 572 573 func (m *mockBackend) Application(name string) (application.Application, error) { 574 m.MethodCall(m, "Application", name) 575 if err := m.NextErr(); err != nil { 576 return nil, err 577 } 578 app, ok := m.applications[name] 579 if !ok { 580 return nil, errors.NotFoundf("application %q", name) 581 } 582 return app, nil 583 } 584 585 func (m *mockBackend) ApplyOperation(op state.ModelOperation) error { 586 m.MethodCall(m, "ApplyOperation", op) 587 return m.NextErr() 588 } 589 590 type mockExternalController struct { 591 uuid string 592 info crossmodel.ControllerInfo 593 } 594 595 func (m *mockExternalController) Id() string { 596 return m.uuid 597 } 598 599 func (m *mockExternalController) ControllerInfo() crossmodel.ControllerInfo { 600 return m.info 601 } 602 603 func (m *mockBackend) SaveController(controllerInfo crossmodel.ControllerInfo, modelUUID string) (application.ExternalController, error) { 604 m.controllers[modelUUID] = controllerInfo 605 return &mockExternalController{controllerInfo.ControllerTag.Id(), controllerInfo}, nil 606 } 607 608 type mockBlockChecker struct { 609 jtesting.Stub 610 } 611 612 func (c *mockBlockChecker) ChangeAllowed() error { 613 c.MethodCall(c, "ChangeAllowed") 614 return c.NextErr() 615 } 616 617 func (c *mockBlockChecker) RemoveAllowed() error { 618 c.MethodCall(c, "RemoveAllowed") 619 return c.NextErr() 620 } 621 622 type mockRelation struct { 623 application.Relation 624 jtesting.Stub 625 626 tag names.Tag 627 status status.Status 628 message string 629 suspended bool 630 suspendedReason string 631 } 632 633 func (r *mockRelation) Tag() names.Tag { 634 return r.tag 635 } 636 637 func (r *mockRelation) SetStatus(status status.StatusInfo) error { 638 r.MethodCall(r, "SetStatus") 639 r.status = status.Status 640 r.message = status.Message 641 return r.NextErr() 642 } 643 644 func (r *mockRelation) SetSuspended(suspended bool, reason string) error { 645 r.MethodCall(r, "SetSuspended") 646 r.suspended = suspended 647 r.suspendedReason = reason 648 return r.NextErr() 649 } 650 651 func (r *mockRelation) Suspended() bool { 652 r.MethodCall(r, "Suspended") 653 return r.suspended 654 } 655 656 func (r *mockRelation) SuspendedReason() string { 657 r.MethodCall(r, "SuspendedReason") 658 return r.suspendedReason 659 } 660 661 func (r *mockRelation) Destroy() error { 662 r.MethodCall(r, "Destroy") 663 return r.NextErr() 664 } 665 666 type mockUnit struct { 667 application.Unit 668 jtesting.Stub 669 tag names.UnitTag 670 machineId string 671 name string 672 } 673 674 func (u *mockUnit) Tag() names.Tag { 675 return u.tag 676 } 677 678 func (u *mockUnit) UnitTag() names.UnitTag { 679 return u.tag 680 } 681 682 func (u *mockUnit) IsPrincipal() bool { 683 u.MethodCall(u, "IsPrincipal") 684 u.PopNoErr() 685 return true 686 } 687 688 func (u *mockUnit) DestroyOperation() *state.DestroyUnitOperation { 689 u.MethodCall(u, "DestroyOperation") 690 return &state.DestroyUnitOperation{} 691 } 692 693 func (u *mockUnit) AssignWithPolicy(policy state.AssignmentPolicy) error { 694 u.MethodCall(u, "AssignWithPolicy", policy) 695 return u.NextErr() 696 } 697 698 func (u *mockUnit) AssignWithPlacement(placement *instance.Placement) error { 699 u.MethodCall(u, "AssignWithPlacement", placement) 700 return u.NextErr() 701 } 702 703 func (u *mockUnit) Resolve(retryHooks bool) error { 704 u.MethodCall(u, "Resolve", retryHooks) 705 return u.NextErr() 706 } 707 708 func (u *mockUnit) AssignedMachineId() (string, error) { 709 u.MethodCall(u, "AssignedMachineId") 710 return u.machineId, u.NextErr() 711 } 712 713 func (u *mockUnit) Name() string { 714 u.MethodCall(u, "Name") 715 return u.name 716 } 717 718 type mockStorageAttachment struct { 719 state.StorageAttachment 720 jtesting.Stub 721 unit names.UnitTag 722 storage names.StorageTag 723 } 724 725 func (a *mockStorageAttachment) Unit() names.UnitTag { 726 return a.unit 727 } 728 729 func (a *mockStorageAttachment) StorageInstance() names.StorageTag { 730 return a.storage 731 } 732 733 type mockStorage struct { 734 state.StorageInstance 735 jtesting.Stub 736 tag names.StorageTag 737 owner names.Tag 738 } 739 740 func (a *mockStorage) Kind() state.StorageKind { 741 return state.StorageKindFilesystem 742 } 743 744 func (a *mockStorage) StorageTag() names.StorageTag { 745 return a.tag 746 } 747 748 func (a *mockStorage) Owner() (names.Tag, bool) { 749 return a.owner, a.owner != nil 750 } 751 752 type mockFilesystem struct { 753 state.Filesystem 754 detachable bool 755 } 756 757 func (f *mockFilesystem) Detachable() bool { 758 return f.detachable 759 } 760 761 type blobs struct { 762 sync.Mutex 763 m map[string]bool // maps path to added (true), or deleted (false) 764 } 765 766 // Add adds a path to the list of known paths. 767 func (b *blobs) Add(path string) { 768 b.Lock() 769 defer b.Unlock() 770 b.check() 771 b.m[path] = true 772 } 773 774 // Remove marks a path as deleted, even if it was not previously Added. 775 func (b *blobs) Remove(path string) { 776 b.Lock() 777 defer b.Unlock() 778 b.check() 779 b.m[path] = false 780 } 781 782 func (b *blobs) check() { 783 if b.m == nil { 784 b.m = make(map[string]bool) 785 } 786 } 787 788 type recordingStorage struct { 789 statestorage.Storage 790 putBarrier *sync.WaitGroup 791 blobs *blobs 792 } 793 794 func (s *recordingStorage) Put(path string, r io.Reader, size int64) error { 795 if s.putBarrier != nil { 796 // This goroutine has gotten to Put() so mark it Done() and 797 // wait for the other goroutines to get to this point. 798 s.putBarrier.Done() 799 s.putBarrier.Wait() 800 } 801 if err := s.Storage.Put(path, r, size); err != nil { 802 return errors.Trace(err) 803 } 804 s.blobs.Add(path) 805 return nil 806 } 807 808 func (s *recordingStorage) Remove(path string) error { 809 if err := s.Storage.Remove(path); err != nil { 810 return errors.Trace(err) 811 } 812 s.blobs.Remove(path) 813 return nil 814 } 815 816 type mockStoragePoolManager struct { 817 jtesting.Stub 818 poolmanager.PoolManager 819 storageType storage.ProviderType 820 } 821 822 func (m *mockStoragePoolManager) Get(name string) (*storage.Config, error) { 823 m.MethodCall(m, "Get", name) 824 if err := m.NextErr(); err != nil { 825 return nil, err 826 } 827 storageType := m.storageType 828 if name == "db" { 829 storageType = provider.RootfsProviderType 830 } 831 return storage.NewConfig(name, storageType, map[string]interface{}{"foo": "bar"}) 832 } 833 834 type mockCaasBroker struct { 835 jtesting.Stub 836 caas.Broker 837 storageClassName string 838 } 839 840 func (m *mockCaasBroker) GetStorageClassName(labels ...string) (string, error) { 841 m.MethodCall(m, "GetStorageClassName", labels) 842 if err := m.NextErr(); err != nil { 843 return "", err 844 } 845 return m.storageClassName, m.NextErr() 846 }