github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/client/storage/client_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 "fmt" 8 9 "github.com/juju/collections/set" 10 "github.com/juju/errors" 11 "github.com/juju/names/v5" 12 jc "github.com/juju/testing/checkers" 13 "go.uber.org/mock/gomock" 14 gc "gopkg.in/check.v1" 15 16 basemocks "github.com/juju/juju/api/base/mocks" 17 "github.com/juju/juju/api/client/storage" 18 apiservererrors "github.com/juju/juju/apiserver/errors" 19 "github.com/juju/juju/rpc/params" 20 jujustorage "github.com/juju/juju/storage" 21 ) 22 23 type storageMockSuite struct { 24 } 25 26 var _ = gc.Suite(&storageMockSuite{}) 27 28 func (s *storageMockSuite) TestStorageDetails(c *gc.C) { 29 ctrl := gomock.NewController(c) 30 defer ctrl.Finish() 31 32 one := "shared-fs/0" 33 oneTag := names.NewStorageTag(one) 34 two := "db-dir/1000" 35 twoTag := names.NewStorageTag(two) 36 expected := set.NewStrings(oneTag.String(), twoTag.String()) 37 msg := "call failure" 38 args := params.Entities{ 39 Entities: []params.Entity{ 40 {Tag: oneTag.String()}, 41 {Tag: twoTag.String()}, 42 }, 43 } 44 instances := []params.StorageDetailsResult{ 45 { 46 Result: ¶ms.StorageDetails{StorageTag: oneTag.String()}, 47 }, 48 { 49 Result: ¶ms.StorageDetails{ 50 StorageTag: twoTag.String(), 51 Status: params.EntityStatus{ 52 Status: "attached", 53 }, 54 Persistent: true, 55 }, 56 }, 57 { 58 Error: apiservererrors.ServerError(errors.New(msg)), 59 }, 60 } 61 results := params.StorageDetailsResults{ 62 Results: instances, 63 } 64 result := new(params.StorageDetailsResults) 65 66 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 67 mockFacadeCaller.EXPECT().FacadeCall("StorageDetails", args, result).SetArg(2, results).Return(nil) 68 69 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 70 71 tags := []names.StorageTag{oneTag, twoTag} 72 found, err := storageClient.StorageDetails(tags) 73 c.Assert(err, jc.ErrorIsNil) 74 c.Assert(found, gc.HasLen, 3) 75 c.Assert(expected.Contains(found[0].Result.StorageTag), jc.IsTrue) 76 c.Assert(expected.Contains(found[1].Result.StorageTag), jc.IsTrue) 77 c.Assert(found[2].Error, gc.ErrorMatches, msg) 78 } 79 80 func (s *storageMockSuite) TestStorageDetailsFacadeCallError(c *gc.C) { 81 ctrl := gomock.NewController(c) 82 defer ctrl.Finish() 83 84 msg := "facade failure" 85 one := "shared-fs/0" 86 oneTag := names.NewStorageTag(one) 87 88 result := new(params.StorageDetailsResults) 89 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 90 mockFacadeCaller.EXPECT().FacadeCall("StorageDetails", gomock.AssignableToTypeOf(params.Entities{}), result).SetArg(2, params.StorageDetailsResults{}).Return(errors.New(msg)) 91 92 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 93 found, err := storageClient.StorageDetails([]names.StorageTag{oneTag}) 94 c.Assert(errors.Cause(err), gc.ErrorMatches, msg) 95 c.Assert(found, gc.HasLen, 0) 96 } 97 98 func (s *storageMockSuite) TestListStorageDetails(c *gc.C) { 99 ctrl := gomock.NewController(c) 100 defer ctrl.Finish() 101 102 storageTag := names.NewStorageTag("db-dir/1000") 103 result := new(params.StorageDetailsListResults) 104 results := params.StorageDetailsListResults{ 105 Results: []params.StorageDetailsListResult{{ 106 Result: []params.StorageDetails{{ 107 StorageTag: storageTag.String(), 108 Status: params.EntityStatus{ 109 Status: "attached", 110 }, 111 Persistent: true, 112 }}, 113 }}, 114 } 115 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 116 mockFacadeCaller.EXPECT().FacadeCall("ListStorageDetails", gomock.AssignableToTypeOf(params.StorageFilters{}), result).SetArg(2, results).Return(nil) 117 118 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 119 found, err := storageClient.ListStorageDetails() 120 c.Check(err, jc.ErrorIsNil) 121 c.Assert(found, gc.HasLen, 1) 122 expected := []params.StorageDetails{{ 123 StorageTag: "storage-db-dir-1000", 124 Status: params.EntityStatus{ 125 Status: "attached", 126 }, 127 Persistent: true, 128 }} 129 130 c.Assert(found, jc.DeepEquals, expected) 131 } 132 133 func (s *storageMockSuite) TestListStorageDetailsFacadeCallError(c *gc.C) { 134 ctrl := gomock.NewController(c) 135 defer ctrl.Finish() 136 137 msg := "facade failure" 138 139 result := new(params.StorageDetailsListResults) 140 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 141 mockFacadeCaller.EXPECT().FacadeCall("ListStorageDetails", gomock.AssignableToTypeOf(params.StorageFilters{}), result).SetArg(2, params.StorageDetailsListResults{}).Return(errors.New(msg)) 142 143 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 144 found, err := storageClient.ListStorageDetails() 145 c.Assert(errors.Cause(err), gc.ErrorMatches, msg) 146 c.Assert(found, gc.HasLen, 0) 147 } 148 149 func (s *storageMockSuite) TestListPools(c *gc.C) { 150 ctrl := gomock.NewController(c) 151 defer ctrl.Finish() 152 153 someNames := []string{"a", "b"} 154 types := []string{"1"} 155 expected := []params.StoragePool{ 156 {Name: "name0", Provider: "type0"}, 157 {Name: "name1", Provider: "type1"}, 158 {Name: "name2", Provider: "type2"}, 159 } 160 want := len(expected) 161 162 args := params.StoragePoolFilters{ 163 Filters: []params.StoragePoolFilter{{ 164 Names: someNames, 165 Providers: types, 166 }}, 167 } 168 result := new(params.StoragePoolsResults) 169 pools := make([]params.StoragePool, want) 170 for i := 0; i < want; i++ { 171 pools[i] = params.StoragePool{ 172 Name: fmt.Sprintf("name%v", i), 173 Provider: fmt.Sprintf("type%v", i), 174 } 175 } 176 results := params.StoragePoolsResults{ 177 Results: []params.StoragePoolsResult{{ 178 Result: pools, 179 }}, 180 } 181 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 182 mockFacadeCaller.EXPECT().FacadeCall("ListPools", args, result).SetArg(2, results).Return(nil) 183 184 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 185 186 found, err := storageClient.ListPools(types, someNames) 187 c.Assert(err, jc.ErrorIsNil) 188 c.Assert(found, gc.HasLen, want) 189 c.Assert(found, gc.DeepEquals, expected) 190 } 191 192 func (s *storageMockSuite) TestListPoolsFacadeCallError(c *gc.C) { 193 ctrl := gomock.NewController(c) 194 defer ctrl.Finish() 195 196 msg := "facade failure" 197 198 result := new(params.StoragePoolsResults) 199 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 200 mockFacadeCaller.EXPECT().FacadeCall("ListPools", gomock.AssignableToTypeOf(params.StoragePoolFilters{}), result).SetArg(2, params.StoragePoolsResults{}).Return(errors.New(msg)) 201 202 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 203 found, err := storageClient.ListPools(nil, nil) 204 c.Assert(errors.Cause(err), gc.ErrorMatches, msg) 205 c.Assert(found, gc.HasLen, 0) 206 } 207 208 func (s *storageMockSuite) TestCreatePool(c *gc.C) { 209 ctrl := gomock.NewController(c) 210 defer ctrl.Finish() 211 212 poolName := "poolName" 213 poolType := "poolType" 214 poolConfig := map[string]interface{}{ 215 "test": "one", 216 "pass": true, 217 } 218 args := params.StoragePoolArgs{ 219 Pools: []params.StoragePool{{ 220 Name: poolName, 221 Provider: poolType, 222 Attrs: poolConfig, 223 }, 224 }} 225 result := new(params.ErrorResults) 226 results := params.ErrorResults{ 227 Results: make([]params.ErrorResult, len(args.Pools)), 228 } 229 230 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 231 mockFacadeCaller.EXPECT().FacadeCall("CreatePool", args, result).SetArg(2, results).Return(nil) 232 233 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 234 err := storageClient.CreatePool(poolName, poolType, poolConfig) 235 c.Assert(err, jc.ErrorIsNil) 236 } 237 238 func (s *storageMockSuite) TestCreatePoolFacadeCallError(c *gc.C) { 239 ctrl := gomock.NewController(c) 240 defer ctrl.Finish() 241 242 msg := "facade failure" 243 244 result := new(params.ErrorResults) 245 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 246 mockFacadeCaller.EXPECT().FacadeCall("CreatePool", gomock.AssignableToTypeOf(params.StoragePoolArgs{}), result).Return(errors.New(msg)) 247 248 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 249 err := storageClient.CreatePool("", "", nil) 250 c.Assert(errors.Cause(err), gc.ErrorMatches, msg) 251 } 252 253 func (s *storageMockSuite) TestListVolumes(c *gc.C) { 254 ctrl := gomock.NewController(c) 255 defer ctrl.Finish() 256 257 args := params.VolumeFilters{ 258 Filters: []params.VolumeFilter{ 259 {Machines: []string{"machine-0"}}, 260 {Machines: []string{"machine-1"}}, 261 }} 262 result := new(params.VolumeDetailsListResults) 263 details := params.VolumeDetails{ 264 VolumeTag: "volume-0", 265 MachineAttachments: map[string]params.VolumeAttachmentDetails{ 266 "machine-0": {}, 267 "machine-1": {}, 268 }, 269 } 270 results := params.VolumeDetailsListResults{ 271 Results: []params.VolumeDetailsListResult{{ 272 Result: []params.VolumeDetails{details}, 273 }, { 274 Result: []params.VolumeDetails{details}, 275 }}, 276 } 277 278 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 279 mockFacadeCaller.EXPECT().FacadeCall("ListVolumes", args, result).SetArg(2, results).Return(nil) 280 281 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 282 found, err := storageClient.ListVolumes([]string{"0", "1"}) 283 c.Assert(err, jc.ErrorIsNil) 284 c.Assert(found, gc.HasLen, 2) 285 for i := 0; i < 2; i++ { 286 c.Assert(found[i].Result, jc.DeepEquals, []params.VolumeDetails{{ 287 VolumeTag: "volume-0", 288 MachineAttachments: map[string]params.VolumeAttachmentDetails{ 289 "machine-0": {}, 290 "machine-1": {}, 291 }, 292 }}) 293 } 294 } 295 296 func (s *storageMockSuite) TestListVolumesEmptyFilter(c *gc.C) { 297 ctrl := gomock.NewController(c) 298 defer ctrl.Finish() 299 300 tag := "ok" 301 args := params.VolumeFilters{ 302 Filters: []params.VolumeFilter{{}}, 303 } 304 result := new(params.VolumeDetailsListResults) 305 results := params.VolumeDetailsListResults{ 306 Results: []params.VolumeDetailsListResult{ 307 {Result: []params.VolumeDetails{{VolumeTag: tag}}}, 308 }, 309 } 310 311 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 312 mockFacadeCaller.EXPECT().FacadeCall("ListVolumes", args, result).SetArg(2, results).Return(nil) 313 314 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 315 found, err := storageClient.ListVolumes(nil) 316 c.Assert(err, jc.ErrorIsNil) 317 c.Assert(found, gc.HasLen, 1) 318 c.Assert(found[0].Result, gc.HasLen, 1) 319 c.Assert(found[0].Result[0].VolumeTag, gc.Equals, tag) 320 } 321 322 func (s *storageMockSuite) TestListVolumesFacadeCallError(c *gc.C) { 323 msg := "facade failure" 324 325 ctrl := gomock.NewController(c) 326 defer ctrl.Finish() 327 328 args := params.VolumeFilters{ 329 Filters: []params.VolumeFilter{{}}, 330 } 331 result := new(params.VolumeDetailsListResults) 332 333 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 334 mockFacadeCaller.EXPECT().FacadeCall("ListVolumes", args, result).Return(errors.New(msg)) 335 336 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 337 _, err := storageClient.ListVolumes(nil) 338 c.Assert(errors.Cause(err), gc.ErrorMatches, msg) 339 } 340 341 func (s *storageMockSuite) TestListFilesystems(c *gc.C) { 342 ctrl := gomock.NewController(c) 343 defer ctrl.Finish() 344 345 args := params.FilesystemFilters{ 346 Filters: []params.FilesystemFilter{{ 347 Machines: []string{"machine-1"}, 348 }, { 349 Machines: []string{"machine-2"}, 350 }}, 351 } 352 result := new(params.FilesystemDetailsListResults) 353 expected := params.FilesystemDetails{ 354 FilesystemTag: "filesystem-1", 355 Info: params.FilesystemInfo{ 356 FilesystemId: "fs-id", 357 Size: 4096, 358 }, 359 Status: params.EntityStatus{ 360 Status: "attached", 361 }, 362 MachineAttachments: map[string]params.FilesystemAttachmentDetails{ 363 "0": { 364 FilesystemAttachmentInfo: params.FilesystemAttachmentInfo{ 365 MountPoint: "/mnt/kinabalu", 366 ReadOnly: false, 367 }, 368 }, 369 }, 370 } 371 results := params.FilesystemDetailsListResults{ 372 Results: []params.FilesystemDetailsListResult{ 373 {Result: []params.FilesystemDetails{expected}}, 374 {}, 375 }, 376 } 377 378 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 379 mockFacadeCaller.EXPECT().FacadeCall("ListFilesystems", args, result).SetArg(2, results).Return(nil) 380 381 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 382 found, err := storageClient.ListFilesystems([]string{"1", "2"}) 383 c.Assert(err, jc.ErrorIsNil) 384 c.Assert(found, gc.HasLen, 2) 385 c.Assert(found[0].Result, jc.DeepEquals, []params.FilesystemDetails{expected}) 386 c.Assert(found[1].Result, jc.DeepEquals, []params.FilesystemDetails{}) 387 } 388 389 func (s *storageMockSuite) TestListFilesystemsEmptyFilter(c *gc.C) { 390 ctrl := gomock.NewController(c) 391 defer ctrl.Finish() 392 393 args := params.FilesystemFilters{ 394 Filters: []params.FilesystemFilter{{}}, 395 } 396 result := new(params.FilesystemDetailsListResults) 397 results := params.FilesystemDetailsListResults{ 398 Results: []params.FilesystemDetailsListResult{{}}, 399 } 400 401 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 402 mockFacadeCaller.EXPECT().FacadeCall("ListFilesystems", args, result).SetArg(2, results).Return(nil) 403 404 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 405 _, err := storageClient.ListFilesystems(nil) 406 c.Assert(err, jc.ErrorIsNil) 407 } 408 409 func (s *storageMockSuite) TestListFilesystemsFacadeCallError(c *gc.C) { 410 msg := "facade failure" 411 412 ctrl := gomock.NewController(c) 413 defer ctrl.Finish() 414 415 args := params.FilesystemFilters{ 416 Filters: []params.FilesystemFilter{{}}, 417 } 418 result := new(params.FilesystemDetailsListResults) 419 420 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 421 mockFacadeCaller.EXPECT().FacadeCall("ListFilesystems", args, result).Return(errors.New(msg)) 422 423 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 424 _, err := storageClient.ListFilesystems(nil) 425 c.Assert(errors.Cause(err), gc.ErrorMatches, msg) 426 } 427 428 func (s *storageMockSuite) TestAddToUnit(c *gc.C) { 429 ctrl := gomock.NewController(c) 430 defer ctrl.Finish() 431 size := uint64(42) 432 cons := params.StorageConstraints{ 433 Pool: "value", 434 Size: &size, 435 } 436 437 errOut := "error" 438 unitStorages := []params.StorageAddParams{ 439 {UnitTag: "u-a", StorageName: "one", Constraints: cons}, 440 {UnitTag: "u-b", StorageName: errOut, Constraints: cons}, 441 {UnitTag: "u-b", StorageName: "nil-constraints"}, 442 } 443 444 storageN := 3 445 expectedError := apiservererrors.ServerError(errors.NotValidf("storage directive")) 446 expectedDetails := ¶ms.AddStorageDetails{[]string{"a/0", "b/1"}} 447 one := func(u, s string, attrs params.StorageConstraints) params.AddStorageResult { 448 result := params.AddStorageResult{} 449 if s == errOut { 450 result.Error = expectedError 451 } else { 452 result.Result = expectedDetails 453 } 454 return result 455 } 456 args := params.StoragesAddParams{ 457 Storages: unitStorages, 458 } 459 result := new(params.AddStorageResults) 460 results := params.AddStorageResults{ 461 Results: []params.AddStorageResult{ 462 one(unitStorages[0].UnitTag, unitStorages[0].StorageName, unitStorages[0].Constraints), 463 one(unitStorages[1].UnitTag, unitStorages[1].StorageName, unitStorages[1].Constraints), 464 one(unitStorages[2].UnitTag, unitStorages[2].StorageName, unitStorages[2].Constraints), 465 }, 466 } 467 468 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 469 mockFacadeCaller.EXPECT().FacadeCall("AddToUnit", args, result).SetArg(2, results).Return(nil) 470 471 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 472 r, err := storageClient.AddToUnit(unitStorages) 473 c.Assert(err, jc.ErrorIsNil) 474 c.Assert(r, gc.HasLen, storageN) 475 expected := []params.AddStorageResult{ 476 {Result: expectedDetails}, 477 {Error: expectedError}, 478 {Result: expectedDetails}, 479 } 480 c.Assert(r, jc.SameContents, expected) 481 } 482 483 func (s *storageMockSuite) TestAddToUnitFacadeCallError(c *gc.C) { 484 ctrl := gomock.NewController(c) 485 defer ctrl.Finish() 486 487 unitStorages := []params.StorageAddParams{ 488 {UnitTag: "u-a", StorageName: "one"}, 489 } 490 msg := "facade failure" 491 args := params.StoragesAddParams{ 492 Storages: unitStorages, 493 } 494 result := new(params.AddStorageResults) 495 496 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 497 mockFacadeCaller.EXPECT().FacadeCall("AddToUnit", args, result).Return(errors.New(msg)) 498 499 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 500 found, err := storageClient.AddToUnit(unitStorages) 501 c.Assert(errors.Cause(err), gc.ErrorMatches, msg) 502 c.Assert(found, gc.HasLen, 0) 503 } 504 505 func (s *storageMockSuite) TestRemove(c *gc.C) { 506 ctrl := gomock.NewController(c) 507 defer ctrl.Finish() 508 509 false_ := false 510 args := params.RemoveStorage{[]params.RemoveStorageInstance{ 511 {Tag: "storage-foo-0", DestroyAttachments: false, DestroyStorage: false, Force: &false_}, 512 {Tag: "storage-bar-1", DestroyAttachments: false, DestroyStorage: false, Force: &false_}, 513 }} 514 result := new(params.ErrorResults) 515 results := params.ErrorResults{ 516 Results: []params.ErrorResult{ 517 {}, 518 {Error: ¶ms.Error{Message: "baz"}}, 519 }, 520 } 521 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 522 mockFacadeCaller.EXPECT().FacadeCall("Remove", args, result).SetArg(2, results).Return(nil) 523 524 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 525 obtained, err := storageClient.Remove([]string{"foo/0", "bar/1"}, false, false, &false_, nil) 526 c.Check(err, jc.ErrorIsNil) 527 c.Assert(obtained, gc.HasLen, 2) 528 c.Assert(obtained[0].Error, gc.IsNil) 529 c.Assert(obtained[1].Error, jc.DeepEquals, ¶ms.Error{Message: "baz"}) 530 } 531 532 func (s *storageMockSuite) TestRemoveDestroyAttachments(c *gc.C) { 533 ctrl := gomock.NewController(c) 534 defer ctrl.Finish() 535 536 true_ := true 537 args := params.RemoveStorage{[]params.RemoveStorageInstance{ 538 {Tag: "storage-foo-0", DestroyAttachments: true, DestroyStorage: true, Force: &true_}, 539 }} 540 result := new(params.ErrorResults) 541 results := params.ErrorResults{ 542 Results: []params.ErrorResult{{}}, 543 } 544 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 545 mockFacadeCaller.EXPECT().FacadeCall("Remove", args, result).SetArg(2, results).Return(nil) 546 547 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 548 obtained, err := storageClient.Remove([]string{"foo/0"}, true, true, &true_, nil) 549 c.Check(err, jc.ErrorIsNil) 550 c.Assert(obtained, gc.HasLen, 1) 551 c.Assert(obtained[0].Error, gc.IsNil) 552 } 553 554 func (s *storageMockSuite) TestRemoveInvalidStorageId(c *gc.C) { 555 ctrl := gomock.NewController(c) 556 defer ctrl.Finish() 557 558 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 559 560 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 561 _, err := storageClient.Remove([]string{"foo/bar"}, false, false, nil, nil) 562 c.Check(err, gc.ErrorMatches, `storage ID "foo/bar" not valid`) 563 } 564 565 func (s *storageMockSuite) TestDetach(c *gc.C) { 566 ctrl := gomock.NewController(c) 567 defer ctrl.Finish() 568 expectedArgs := params.StorageDetachmentParams{ 569 StorageIds: params.StorageAttachmentIds{[]params.StorageAttachmentId{ 570 {StorageTag: "storage-foo-0"}, 571 {StorageTag: "storage-bar-1"}, 572 }}, 573 } 574 result := new(params.ErrorResults) 575 results := params.ErrorResults{ 576 Results: []params.ErrorResult{ 577 {}, 578 {Error: ¶ms.Error{Message: "baz"}}, 579 }, 580 } 581 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 582 mockFacadeCaller.EXPECT().FacadeCall("DetachStorage", expectedArgs, result).SetArg(2, results).Return(nil) 583 584 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 585 obtained, err := storageClient.Detach([]string{"foo/0", "bar/1"}, nil, nil) 586 c.Check(err, jc.ErrorIsNil) 587 c.Assert(obtained, gc.HasLen, 2) 588 c.Assert(obtained[0].Error, gc.IsNil) 589 c.Assert(obtained[1].Error, jc.DeepEquals, ¶ms.Error{Message: "baz"}) 590 } 591 592 func (s *storageMockSuite) TestDetachArityMismatch(c *gc.C) { 593 ctrl := gomock.NewController(c) 594 defer ctrl.Finish() 595 result := new(params.ErrorResults) 596 results := params.ErrorResults{ 597 Results: []params.ErrorResult{{}, {}, {}}, 598 } 599 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 600 mockFacadeCaller.EXPECT().FacadeCall("DetachStorage", gomock.AssignableToTypeOf(params.StorageDetachmentParams{}), result).SetArg(2, results).Return(nil) 601 602 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 603 _, err := storageClient.Detach([]string{"foo/0", "bar/1"}, nil, nil) 604 c.Check(err, gc.ErrorMatches, `expected 2 result\(s\), got 3`) 605 } 606 607 func (s *storageMockSuite) TestAttach(c *gc.C) { 608 ctrl := gomock.NewController(c) 609 defer ctrl.Finish() 610 expectedArgs := params.StorageAttachmentIds{[]params.StorageAttachmentId{ 611 { 612 StorageTag: "storage-bar-1", 613 UnitTag: "unit-foo-0", 614 }, 615 { 616 StorageTag: "storage-baz-2", 617 UnitTag: "unit-foo-0", 618 }, 619 }} 620 result := new(params.ErrorResults) 621 results := params.ErrorResults{ 622 Results: []params.ErrorResult{ 623 {}, 624 {Error: ¶ms.Error{Message: "qux"}}, 625 }, 626 } 627 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 628 mockFacadeCaller.EXPECT().FacadeCall("Attach", expectedArgs, result).SetArg(2, results).Return(nil) 629 630 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 631 obtained, err := storageClient.Attach("foo/0", []string{"bar/1", "baz/2"}) 632 c.Check(err, jc.ErrorIsNil) 633 c.Assert(obtained, gc.HasLen, 2) 634 c.Assert(obtained[0].Error, gc.IsNil) 635 c.Assert(obtained[1].Error, jc.DeepEquals, ¶ms.Error{Message: "qux"}) 636 } 637 638 func (s *storageMockSuite) TestAttachArityMismatch(c *gc.C) { 639 ctrl := gomock.NewController(c) 640 defer ctrl.Finish() 641 result := new(params.ErrorResults) 642 results := params.ErrorResults{ 643 Results: []params.ErrorResult{{}, {}, {}}, 644 } 645 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 646 mockFacadeCaller.EXPECT().FacadeCall("Attach", gomock.AssignableToTypeOf(params.StorageAttachmentIds{}), result).SetArg(2, results).Return(nil) 647 648 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 649 _, err := storageClient.Attach("foo/0", []string{"bar/1", "baz/2"}) 650 c.Check(err, gc.ErrorMatches, `expected 2 result\(s\), got 3`) 651 } 652 653 func (s *storageMockSuite) TestImport(c *gc.C) { 654 ctrl := gomock.NewController(c) 655 defer ctrl.Finish() 656 expectedArgs := params.BulkImportStorageParams{[]params.ImportStorageParams{{ 657 Kind: params.StorageKindBlock, 658 Pool: "foo", 659 ProviderId: "bar", 660 StorageName: "baz", 661 }}} 662 result := new(params.ImportStorageResults) 663 results := params.ImportStorageResults{ 664 Results: []params.ImportStorageResult{{ 665 Result: ¶ms.ImportStorageDetails{ 666 StorageTag: "storage-qux-0", 667 }, 668 }, 669 }} 670 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 671 mockFacadeCaller.EXPECT().FacadeCall("Import", expectedArgs, result).SetArg(2, results).Return(nil) 672 673 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 674 storageTag, err := storageClient.Import(jujustorage.StorageKindBlock, "foo", "bar", "baz") 675 c.Assert(err, jc.ErrorIsNil) 676 c.Assert(storageTag, gc.Equals, names.NewStorageTag("qux/0")) 677 } 678 679 func (s *storageMockSuite) TestImportError(c *gc.C) { 680 ctrl := gomock.NewController(c) 681 defer ctrl.Finish() 682 result := new(params.ImportStorageResults) 683 results := params.ImportStorageResults{ 684 Results: []params.ImportStorageResult{{ 685 Error: ¶ms.Error{Message: "qux"}, 686 }, 687 }} 688 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 689 mockFacadeCaller.EXPECT().FacadeCall("Import", gomock.AssignableToTypeOf(params.BulkImportStorageParams{}), result).SetArg(2, results).Return(nil) 690 691 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 692 _, err := storageClient.Import(jujustorage.StorageKindBlock, "foo", "bar", "baz") 693 c.Check(err, gc.ErrorMatches, "qux") 694 } 695 696 func (s *storageMockSuite) TestImportArityMismatch(c *gc.C) { 697 ctrl := gomock.NewController(c) 698 defer ctrl.Finish() 699 700 result := new(params.ImportStorageResults) 701 results := params.ImportStorageResults{ 702 Results: []params.ImportStorageResult{{}, {}}, 703 } 704 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 705 mockFacadeCaller.EXPECT().FacadeCall("Import", gomock.AssignableToTypeOf(params.BulkImportStorageParams{}), result).SetArg(2, results).Return(nil) 706 707 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 708 _, err := storageClient.Import(jujustorage.StorageKindBlock, "foo", "bar", "baz") 709 c.Check(err, gc.ErrorMatches, `expected 1 result, got 2`) 710 } 711 712 func (s *storageMockSuite) TestRemovePool(c *gc.C) { 713 ctrl := gomock.NewController(c) 714 defer ctrl.Finish() 715 716 poolName := "poolName" 717 expectedArgs := params.StoragePoolDeleteArgs{ 718 Pools: []params.StoragePoolDeleteArg{{ 719 Name: poolName, 720 }}, 721 } 722 result := new(params.ErrorResults) 723 results := params.ErrorResults{ 724 Results: make([]params.ErrorResult, len(expectedArgs.Pools)), 725 } 726 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 727 mockFacadeCaller.EXPECT().FacadeCall("RemovePool", expectedArgs, result).SetArg(2, results).Return(nil) 728 729 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 730 err := storageClient.RemovePool(poolName) 731 c.Assert(err, jc.ErrorIsNil) 732 } 733 734 func (s *storageMockSuite) TestRemovePoolFacadeCallError(c *gc.C) { 735 ctrl := gomock.NewController(c) 736 defer ctrl.Finish() 737 738 msg := "facade failure" 739 result := new(params.ErrorResults) 740 results := params.ErrorResults{ 741 Results: make([]params.ErrorResult, 1), 742 } 743 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 744 mockFacadeCaller.EXPECT().FacadeCall("RemovePool", gomock.AssignableToTypeOf(params.StoragePoolDeleteArgs{}), result).SetArg(2, results).Return(errors.New(msg)) 745 746 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 747 err := storageClient.RemovePool("") 748 c.Assert(errors.Cause(err), gc.ErrorMatches, msg) 749 } 750 751 func (s *storageMockSuite) TestUpdatePool(c *gc.C) { 752 ctrl := gomock.NewController(c) 753 defer ctrl.Finish() 754 755 poolName := "poolName" 756 providerType := "loop" 757 poolConfig := map[string]interface{}{ 758 "test": "one", 759 "pass": true, 760 } 761 expectedArgs := params.StoragePoolArgs{ 762 Pools: []params.StoragePool{{ 763 Name: poolName, 764 Provider: providerType, 765 Attrs: poolConfig, 766 }}, 767 } 768 result := new(params.ErrorResults) 769 results := params.ErrorResults{ 770 Results: make([]params.ErrorResult, len(expectedArgs.Pools)), 771 } 772 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 773 mockFacadeCaller.EXPECT().FacadeCall("UpdatePool", expectedArgs, result).SetArg(2, results).Return(nil) 774 775 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 776 err := storageClient.UpdatePool(poolName, providerType, poolConfig) 777 c.Assert(err, jc.ErrorIsNil) 778 } 779 780 func (s *storageMockSuite) TestUpdatePoolFacadeCallError(c *gc.C) { 781 ctrl := gomock.NewController(c) 782 defer ctrl.Finish() 783 784 msg := "facade failure" 785 result := new(params.ErrorResults) 786 results := params.ErrorResults{ 787 Results: make([]params.ErrorResult, 1), 788 } 789 mockFacadeCaller := basemocks.NewMockFacadeCaller(ctrl) 790 mockFacadeCaller.EXPECT().FacadeCall("UpdatePool", gomock.AssignableToTypeOf(params.StoragePoolArgs{}), result).SetArg(2, results).Return(errors.New(msg)) 791 792 storageClient := storage.NewClientFromCaller(mockFacadeCaller) 793 err := storageClient.UpdatePool("", "", nil) 794 c.Assert(errors.Cause(err), gc.ErrorMatches, msg) 795 }