github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/caas/kubernetes/provider/metadata_test.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package provider_test 5 6 import ( 7 "context" 8 "errors" 9 10 "github.com/juju/collections/set" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 core "k8s.io/api/core/v1" 14 storagev1 "k8s.io/api/storage/v1" 15 v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 16 "k8s.io/apimachinery/pkg/runtime" 17 "k8s.io/client-go/kubernetes/fake" 18 19 "github.com/juju/juju/caas/kubernetes" 20 "github.com/juju/juju/caas/kubernetes/provider" 21 "github.com/juju/juju/environs" 22 ) 23 24 type K8sMetadataSuite struct { 25 BaseSuite 26 } 27 28 var _ = gc.Suite(&K8sMetadataSuite{}) 29 30 var ( 31 annotatedOperatorStorage = &storagev1.StorageClass{ 32 ObjectMeta: v1.ObjectMeta{ 33 Name: "operator-storage", 34 Annotations: map[string]string{ 35 "juju.is/operator-storage": "true", 36 }, 37 }, 38 } 39 40 annotatedWorkloadStorage = &storagev1.StorageClass{ 41 ObjectMeta: v1.ObjectMeta{ 42 Name: "workload-storage", 43 Annotations: map[string]string{ 44 "juju.is/workload-storage": "true", 45 }, 46 }, 47 } 48 49 azureNode = newNode(map[string]string{ 50 "failure-domain.beta.kubernetes.io/region": "wallyworld-region", 51 "kubernetes.azure.com/cluster": "true", 52 }) 53 54 azureStorageClass = &storagev1.StorageClass{ 55 ObjectMeta: v1.ObjectMeta{ 56 Name: "mynode", 57 }, 58 Provisioner: "kubernetes.io/azure-disk", 59 } 60 61 defaultStorage = &storagev1.StorageClass{ 62 ObjectMeta: v1.ObjectMeta{ 63 Name: "default", 64 Annotations: map[string]string{ 65 "storageclass.kubernetes.io/is-default-class": "true", 66 }, 67 }, 68 } 69 70 ec2Node = newNode(map[string]string{ 71 "failure-domain.beta.kubernetes.io/region": "wallyworld-region", 72 "manufacturer": "amazon_ec2", 73 }) 74 75 ec2StorageClass = &storagev1.StorageClass{ 76 ObjectMeta: v1.ObjectMeta{ 77 Name: "mynode", 78 }, 79 Provisioner: "kubernetes.io/aws-ebs", 80 } 81 82 gceNode = newNode(map[string]string{ 83 "failure-domain.beta.kubernetes.io/region": "wallyworld-region", 84 "cloud.google.com/gke-nodepool": "true", 85 "cloud.google.com/gke-os-distribution": "true", 86 }) 87 88 gceStorageClass = &storagev1.StorageClass{ 89 ObjectMeta: v1.ObjectMeta{ 90 Name: "mynode", 91 }, 92 Provisioner: "kubernetes.io/gce-pd", 93 } 94 95 microk8sNode = newNode(map[string]string{ 96 "microk8s.io/cluster": "true", 97 "failure-domain.beta.kubernetes.io/region": "wallyworld-region", 98 }) 99 100 microk8sStorageClass = &storagev1.StorageClass{ 101 ObjectMeta: v1.ObjectMeta{ 102 Name: "mynode", 103 }, 104 Provisioner: "microk8s.io/hostpath", 105 } 106 107 nominatedStorage = &storagev1.StorageClass{ 108 ObjectMeta: v1.ObjectMeta{ 109 Name: "nominated", 110 }, 111 } 112 ) 113 114 func newNode(labels map[string]string) *core.Node { 115 n := core.Node{} 116 n.SetLabels(labels) 117 return &n 118 } 119 120 func (s *K8sMetadataSuite) TestMicrok8sFromNodeMeta(c *gc.C) { 121 node := core.Node{ 122 ObjectMeta: v1.ObjectMeta{ 123 Name: "mynode", 124 Labels: map[string]string{"microk8s.io/cluster": "true"}, 125 }, 126 } 127 cloud, region := provider.GetCloudProviderFromNodeMeta(node) 128 c.Assert(cloud, gc.Equals, "microk8s") 129 c.Assert(region, gc.Equals, "localhost") 130 } 131 132 func (s *K8sMetadataSuite) TestMicrok8sWithRegionFromNodeMeta(c *gc.C) { 133 node := core.Node{ 134 ObjectMeta: v1.ObjectMeta{ 135 Name: "mynode", 136 Labels: map[string]string{ 137 "microk8s.io/cluster": "true", 138 "failure-domain.beta.kubernetes.io/region": "somewhere", 139 }, 140 }, 141 } 142 cloud, region := provider.GetCloudProviderFromNodeMeta(node) 143 c.Assert(cloud, gc.Equals, "microk8s") 144 c.Assert(region, gc.Equals, "somewhere") 145 } 146 147 func (s *K8sMetadataSuite) TestK8sCloudCheckersValidationPass(c *gc.C) { 148 // CompileK8sCloudCheckers will panic if there is invalid requirement definition so check it by calling it. 149 cloudCheckers := provider.CompileK8sCloudCheckers() 150 c.Assert(cloudCheckers, gc.NotNil) 151 } 152 153 type hostRegionTestcase struct { 154 expectedCloud string 155 expectedRegions set.Strings 156 node *core.Node 157 } 158 159 var hostRegionsTestCases = []hostRegionTestcase{ 160 { 161 expectedRegions: set.NewStrings(), 162 node: newNode(map[string]string{}), 163 }, 164 { 165 expectedRegions: set.NewStrings(), 166 node: newNode(map[string]string{ 167 "cloud.google.com/gke-nodepool": "", 168 }), 169 }, 170 { 171 expectedRegions: set.NewStrings(), 172 node: newNode(map[string]string{ 173 "cloud.google.com/gke-os-distribution": "", 174 }), 175 }, 176 { 177 expectedCloud: "gce", 178 expectedRegions: set.NewStrings(""), 179 node: newNode(map[string]string{ 180 "cloud.google.com/gke-nodepool": "", 181 "cloud.google.com/gke-os-distribution": "", 182 }), 183 }, 184 { 185 expectedCloud: "gce", 186 expectedRegions: set.NewStrings(""), 187 node: newNode(map[string]string{ 188 "juju.is/cloud": "gce", 189 }), 190 }, 191 { 192 expectedCloud: "ec2", 193 expectedRegions: set.NewStrings(""), 194 node: newNode(map[string]string{ 195 "juju.is/cloud": "ec2", 196 }), 197 }, 198 { 199 expectedCloud: "azure", 200 expectedRegions: set.NewStrings(""), 201 node: newNode(map[string]string{ 202 "juju.is/cloud": "azure", 203 }), 204 }, 205 { 206 expectedCloud: "azure", 207 expectedRegions: set.NewStrings(""), 208 node: newNode(map[string]string{ 209 "kubernetes.azure.com/cluster": "", 210 }), 211 }, 212 { 213 expectedCloud: "ec2", 214 expectedRegions: set.NewStrings(""), 215 node: newNode(map[string]string{ 216 "manufacturer": "amazon_ec2", 217 }), 218 }, 219 { 220 expectedCloud: "ec2", 221 expectedRegions: set.NewStrings(""), 222 node: newNode(map[string]string{ 223 "eks.amazonaws.com/nodegroup": "any-node-group", 224 }), 225 }, 226 { 227 expectedRegions: set.NewStrings(), 228 node: newNode(map[string]string{ 229 "failure-domain.beta.kubernetes.io/region": "a-fancy-region", 230 }), 231 }, 232 { 233 expectedRegions: set.NewStrings(), 234 node: newNode(map[string]string{ 235 "failure-domain.beta.kubernetes.io/region": "a-fancy-region", 236 "cloud.google.com/gke-nodepool": "", 237 }), 238 }, 239 { 240 expectedRegions: set.NewStrings(), 241 node: newNode(map[string]string{ 242 "failure-domain.beta.kubernetes.io/region": "a-fancy-region", 243 "cloud.google.com/gke-os-distribution": "", 244 }), 245 }, 246 { 247 expectedCloud: "gce", 248 expectedRegions: set.NewStrings("a-fancy-region"), 249 node: newNode(map[string]string{ 250 "failure-domain.beta.kubernetes.io/region": "a-fancy-region", 251 "cloud.google.com/gke-nodepool": "", 252 "cloud.google.com/gke-os-distribution": "", 253 }), 254 }, 255 { 256 expectedCloud: "azure", 257 expectedRegions: set.NewStrings("a-fancy-region"), 258 node: newNode(map[string]string{ 259 "failure-domain.beta.kubernetes.io/region": "a-fancy-region", 260 "kubernetes.azure.com/cluster": "", 261 }), 262 }, 263 { 264 expectedCloud: "ec2", 265 expectedRegions: set.NewStrings("a-fancy-region"), 266 node: newNode(map[string]string{ 267 "failure-domain.beta.kubernetes.io/region": "a-fancy-region", 268 "manufacturer": "amazon_ec2", 269 }), 270 }, 271 } 272 273 func (s *K8sMetadataSuite) TestListHostCloudRegions(c *gc.C) { 274 for _, v := range hostRegionsTestCases { 275 clientSet := fake.NewSimpleClientset(v.node) 276 277 metadata, err := provider.GetClusterMetadata( 278 context.TODO(), 279 "", 280 clientSet.CoreV1().Nodes(), 281 clientSet.StorageV1().StorageClasses(), 282 ) 283 c.Check(err, jc.ErrorIsNil) 284 c.Check(metadata.Cloud, gc.Equals, v.expectedCloud) 285 c.Check(metadata.Regions, jc.DeepEquals, v.expectedRegions) 286 } 287 } 288 289 func (_ *K8sMetadataSuite) TestGetMetadataVariations(c *gc.C) { 290 tests := []struct { 291 Name string 292 InitialObjects []runtime.Object 293 NominatedStorage string 294 Result kubernetes.ClusterMetadata 295 }{ 296 // EC2 tests 297 { 298 Name: "Test ec2 cloud finds provisioner storage", 299 InitialObjects: []runtime.Object{ 300 ec2Node, 301 ec2StorageClass, 302 }, 303 Result: kubernetes.ClusterMetadata{ 304 Cloud: "ec2", 305 Regions: set.NewStrings("wallyworld-region"), 306 WorkloadStorageClass: ec2StorageClass, 307 OperatorStorageClass: ec2StorageClass, 308 }, 309 }, 310 { 311 Name: "Test ec2 cloud prefers annotation storage", 312 InitialObjects: []runtime.Object{ 313 ec2Node, 314 ec2StorageClass, 315 annotatedOperatorStorage, 316 annotatedWorkloadStorage, 317 }, 318 Result: kubernetes.ClusterMetadata{ 319 Cloud: "ec2", 320 Regions: set.NewStrings("wallyworld-region"), 321 WorkloadStorageClass: annotatedWorkloadStorage, 322 OperatorStorageClass: annotatedOperatorStorage, 323 }, 324 }, 325 { 326 Name: "Test ec2 cloud prefers annotation storage without workload", 327 InitialObjects: []runtime.Object{ 328 ec2Node, 329 annotatedOperatorStorage, 330 }, 331 Result: kubernetes.ClusterMetadata{ 332 Cloud: "ec2", 333 Regions: set.NewStrings("wallyworld-region"), 334 WorkloadStorageClass: nil, 335 OperatorStorageClass: annotatedOperatorStorage, 336 }, 337 }, 338 { 339 Name: "Test ec2 cloud prefers nominated storage as first priority", 340 InitialObjects: []runtime.Object{ 341 ec2Node, 342 ec2StorageClass, 343 annotatedOperatorStorage, 344 annotatedWorkloadStorage, 345 nominatedStorage, 346 }, 347 NominatedStorage: "nominated", 348 Result: kubernetes.ClusterMetadata{ 349 Cloud: "ec2", 350 Regions: set.NewStrings("wallyworld-region"), 351 WorkloadStorageClass: nominatedStorage, 352 OperatorStorageClass: nominatedStorage, 353 }, 354 }, 355 { 356 Name: "Test ec2 cloud with no found storage", 357 InitialObjects: []runtime.Object{ 358 ec2Node, 359 }, 360 Result: kubernetes.ClusterMetadata{ 361 Cloud: "ec2", 362 Regions: set.NewStrings("wallyworld-region"), 363 WorkloadStorageClass: nil, 364 OperatorStorageClass: nil, 365 }, 366 }, 367 { 368 Name: "Test ec2 cloud with default storage", 369 InitialObjects: []runtime.Object{ 370 ec2Node, 371 defaultStorage, 372 }, 373 Result: kubernetes.ClusterMetadata{ 374 Cloud: "ec2", 375 Regions: set.NewStrings("wallyworld-region"), 376 WorkloadStorageClass: defaultStorage, 377 OperatorStorageClass: defaultStorage, 378 }, 379 }, 380 381 // Microk8s 382 { 383 Name: "Test microk8s cloud finds provisioner storage", 384 InitialObjects: []runtime.Object{ 385 microk8sNode, 386 microk8sStorageClass, 387 }, 388 Result: kubernetes.ClusterMetadata{ 389 Cloud: "microk8s", 390 Regions: set.NewStrings("wallyworld-region"), 391 WorkloadStorageClass: microk8sStorageClass, 392 OperatorStorageClass: microk8sStorageClass, 393 }, 394 }, 395 { 396 Name: "Test microk8s cloud prefers annotation storage", 397 InitialObjects: []runtime.Object{ 398 microk8sNode, 399 microk8sStorageClass, 400 annotatedOperatorStorage, 401 annotatedWorkloadStorage, 402 }, 403 Result: kubernetes.ClusterMetadata{ 404 Cloud: "microk8s", 405 Regions: set.NewStrings("wallyworld-region"), 406 WorkloadStorageClass: annotatedWorkloadStorage, 407 OperatorStorageClass: annotatedOperatorStorage, 408 }, 409 }, 410 { 411 Name: "Test microk8s cloud prefers annotation storage without workload", 412 InitialObjects: []runtime.Object{ 413 microk8sNode, 414 annotatedOperatorStorage, 415 }, 416 Result: kubernetes.ClusterMetadata{ 417 Cloud: "microk8s", 418 Regions: set.NewStrings("wallyworld-region"), 419 WorkloadStorageClass: nil, 420 OperatorStorageClass: annotatedOperatorStorage, 421 }, 422 }, 423 { 424 Name: "Test microk8s cloud prefers nominated storage as first priority", 425 InitialObjects: []runtime.Object{ 426 microk8sNode, 427 microk8sStorageClass, 428 annotatedOperatorStorage, 429 annotatedWorkloadStorage, 430 nominatedStorage, 431 }, 432 NominatedStorage: "nominated", 433 Result: kubernetes.ClusterMetadata{ 434 Cloud: "microk8s", 435 Regions: set.NewStrings("wallyworld-region"), 436 WorkloadStorageClass: nominatedStorage, 437 OperatorStorageClass: nominatedStorage, 438 }, 439 }, 440 { 441 Name: "Test microk8s cloud with no found storage", 442 InitialObjects: []runtime.Object{ 443 microk8sNode, 444 }, 445 Result: kubernetes.ClusterMetadata{ 446 Cloud: "microk8s", 447 Regions: set.NewStrings("wallyworld-region"), 448 WorkloadStorageClass: nil, 449 OperatorStorageClass: nil, 450 }, 451 }, 452 { 453 Name: "Test microk8s cloud doesn't use default storage", 454 InitialObjects: []runtime.Object{ 455 microk8sNode, 456 defaultStorage, 457 }, 458 Result: kubernetes.ClusterMetadata{ 459 Cloud: "microk8s", 460 Regions: set.NewStrings("wallyworld-region"), 461 WorkloadStorageClass: nil, 462 OperatorStorageClass: nil, 463 }, 464 }, 465 466 // Azure 467 { 468 Name: "Test azure cloud finds provisioner storage", 469 InitialObjects: []runtime.Object{ 470 azureNode, 471 azureStorageClass, 472 }, 473 Result: kubernetes.ClusterMetadata{ 474 Cloud: "azure", 475 Regions: set.NewStrings("wallyworld-region"), 476 WorkloadStorageClass: azureStorageClass, 477 OperatorStorageClass: azureStorageClass, 478 }, 479 }, 480 { 481 Name: "Test azure cloud prefers annotation storage", 482 InitialObjects: []runtime.Object{ 483 azureNode, 484 azureStorageClass, 485 annotatedOperatorStorage, 486 annotatedWorkloadStorage, 487 }, 488 Result: kubernetes.ClusterMetadata{ 489 Cloud: "azure", 490 Regions: set.NewStrings("wallyworld-region"), 491 WorkloadStorageClass: annotatedWorkloadStorage, 492 OperatorStorageClass: annotatedOperatorStorage, 493 }, 494 }, 495 { 496 Name: "Test azure cloud prefers annotation storage without workload", 497 InitialObjects: []runtime.Object{ 498 azureNode, 499 annotatedOperatorStorage, 500 }, 501 Result: kubernetes.ClusterMetadata{ 502 Cloud: "azure", 503 Regions: set.NewStrings("wallyworld-region"), 504 WorkloadStorageClass: nil, 505 OperatorStorageClass: annotatedOperatorStorage, 506 }, 507 }, 508 { 509 Name: "Test azure cloud prefers nominated storage as first priority", 510 InitialObjects: []runtime.Object{ 511 azureNode, 512 azureStorageClass, 513 annotatedOperatorStorage, 514 annotatedWorkloadStorage, 515 nominatedStorage, 516 }, 517 NominatedStorage: "nominated", 518 Result: kubernetes.ClusterMetadata{ 519 Cloud: "azure", 520 Regions: set.NewStrings("wallyworld-region"), 521 WorkloadStorageClass: nominatedStorage, 522 OperatorStorageClass: nominatedStorage, 523 }, 524 }, 525 { 526 Name: "Test azure cloud with no found storage", 527 InitialObjects: []runtime.Object{ 528 azureNode, 529 }, 530 Result: kubernetes.ClusterMetadata{ 531 Cloud: "azure", 532 Regions: set.NewStrings("wallyworld-region"), 533 WorkloadStorageClass: nil, 534 OperatorStorageClass: nil, 535 }, 536 }, 537 { 538 Name: "Test azure cloud with default storage", 539 InitialObjects: []runtime.Object{ 540 azureNode, 541 defaultStorage, 542 }, 543 Result: kubernetes.ClusterMetadata{ 544 Cloud: "azure", 545 Regions: set.NewStrings("wallyworld-region"), 546 WorkloadStorageClass: defaultStorage, 547 OperatorStorageClass: defaultStorage, 548 }, 549 }, 550 551 // GCE 552 { 553 Name: "Test gce cloud finds provisioner storage", 554 InitialObjects: []runtime.Object{ 555 gceNode, 556 gceStorageClass, 557 }, 558 Result: kubernetes.ClusterMetadata{ 559 Cloud: "gce", 560 Regions: set.NewStrings("wallyworld-region"), 561 WorkloadStorageClass: gceStorageClass, 562 OperatorStorageClass: gceStorageClass, 563 }, 564 }, 565 { 566 Name: "Test gce cloud prefers annotation storage", 567 InitialObjects: []runtime.Object{ 568 gceNode, 569 gceStorageClass, 570 annotatedOperatorStorage, 571 annotatedWorkloadStorage, 572 }, 573 Result: kubernetes.ClusterMetadata{ 574 Cloud: "gce", 575 Regions: set.NewStrings("wallyworld-region"), 576 WorkloadStorageClass: annotatedWorkloadStorage, 577 OperatorStorageClass: annotatedOperatorStorage, 578 }, 579 }, 580 { 581 Name: "Test gce cloud prefers annotation storage without workload", 582 InitialObjects: []runtime.Object{ 583 gceNode, 584 annotatedOperatorStorage, 585 }, 586 Result: kubernetes.ClusterMetadata{ 587 Cloud: "gce", 588 Regions: set.NewStrings("wallyworld-region"), 589 WorkloadStorageClass: nil, 590 OperatorStorageClass: annotatedOperatorStorage, 591 }, 592 }, 593 { 594 Name: "Test gce cloud prefers nominated storage as first priority", 595 InitialObjects: []runtime.Object{ 596 gceNode, 597 gceStorageClass, 598 annotatedOperatorStorage, 599 annotatedWorkloadStorage, 600 nominatedStorage, 601 }, 602 NominatedStorage: "nominated", 603 Result: kubernetes.ClusterMetadata{ 604 Cloud: "gce", 605 Regions: set.NewStrings("wallyworld-region"), 606 WorkloadStorageClass: nominatedStorage, 607 OperatorStorageClass: nominatedStorage, 608 }, 609 }, 610 { 611 Name: "Test gce cloud with no found storage", 612 InitialObjects: []runtime.Object{ 613 gceNode, 614 }, 615 Result: kubernetes.ClusterMetadata{ 616 Cloud: "gce", 617 Regions: set.NewStrings("wallyworld-region"), 618 WorkloadStorageClass: nil, 619 OperatorStorageClass: nil, 620 }, 621 }, 622 { 623 Name: "Test gce cloud with default storage", 624 InitialObjects: []runtime.Object{ 625 gceNode, 626 defaultStorage, 627 }, 628 Result: kubernetes.ClusterMetadata{ 629 Cloud: "gce", 630 Regions: set.NewStrings("wallyworld-region"), 631 WorkloadStorageClass: defaultStorage, 632 OperatorStorageClass: defaultStorage, 633 }, 634 }, 635 636 // Other 637 { 638 Name: "Test other cloud prefers annotation storage", 639 InitialObjects: []runtime.Object{ 640 newNode(map[string]string{}), 641 gceStorageClass, 642 annotatedOperatorStorage, 643 annotatedWorkloadStorage, 644 }, 645 Result: kubernetes.ClusterMetadata{ 646 Cloud: "", 647 Regions: set.NewStrings(), 648 WorkloadStorageClass: annotatedWorkloadStorage, 649 OperatorStorageClass: annotatedOperatorStorage, 650 }, 651 }, 652 { 653 Name: "Test other cloud prefers annotation storage without workload", 654 InitialObjects: []runtime.Object{ 655 newNode(map[string]string{}), 656 annotatedOperatorStorage, 657 }, 658 Result: kubernetes.ClusterMetadata{ 659 Cloud: "", 660 Regions: set.NewStrings(), 661 WorkloadStorageClass: annotatedOperatorStorage, 662 OperatorStorageClass: annotatedOperatorStorage, 663 }, 664 }, 665 { 666 Name: "Test other cloud prefers nominated storage as first priority", 667 InitialObjects: []runtime.Object{ 668 newNode(map[string]string{}), 669 gceStorageClass, 670 annotatedOperatorStorage, 671 annotatedWorkloadStorage, 672 nominatedStorage, 673 }, 674 NominatedStorage: "nominated", 675 Result: kubernetes.ClusterMetadata{ 676 Cloud: "", 677 Regions: set.NewStrings(), 678 WorkloadStorageClass: nominatedStorage, 679 OperatorStorageClass: nominatedStorage, 680 }, 681 }, 682 { 683 Name: "Test other cloud with no found storage", 684 InitialObjects: []runtime.Object{ 685 newNode(map[string]string{}), 686 }, 687 Result: kubernetes.ClusterMetadata{ 688 Cloud: "", 689 Regions: set.NewStrings(), 690 WorkloadStorageClass: nil, 691 OperatorStorageClass: nil, 692 }, 693 }, 694 { 695 Name: "Test other cloud with default storage", 696 InitialObjects: []runtime.Object{ 697 newNode(map[string]string{}), 698 defaultStorage, 699 }, 700 Result: kubernetes.ClusterMetadata{ 701 Cloud: "", 702 Regions: set.NewStrings(), 703 WorkloadStorageClass: defaultStorage, 704 OperatorStorageClass: defaultStorage, 705 }, 706 }, 707 } 708 709 for _, test := range tests { 710 c.Logf("running test %s", test.Name) 711 clientSet := fake.NewSimpleClientset(test.InitialObjects...) 712 713 metadata, err := provider.GetClusterMetadata( 714 context.TODO(), 715 test.NominatedStorage, 716 clientSet.CoreV1().Nodes(), 717 clientSet.StorageV1().StorageClasses(), 718 ) 719 c.Assert(err, jc.ErrorIsNil) 720 c.Check(*metadata, jc.DeepEquals, test.Result) 721 } 722 } 723 724 func (s *K8sMetadataSuite) TestNominatedStorageNotFound(c *gc.C) { 725 clientSet := fake.NewSimpleClientset( 726 newNode(map[string]string{}), 727 gceStorageClass, 728 annotatedOperatorStorage, 729 annotatedWorkloadStorage, 730 ) 731 732 _, err := provider.GetClusterMetadata( 733 context.TODO(), 734 "my-nominated-storage", 735 clientSet.CoreV1().Nodes(), 736 clientSet.StorageV1().StorageClasses(), 737 ) 738 739 var notFoundError *environs.NominatedStorageNotFound 740 c.Assert(err, gc.NotNil) 741 c.Assert(errors.As(err, ¬FoundError), jc.IsTrue) 742 c.Assert(notFoundError.StorageName, gc.Equals, "my-nominated-storage") 743 } 744 745 // TestNominatedStorageNotFoundWithNilStorageClasses is a regression test to 746 // make sure that when no storage classes are defined and a nominated storage 747 // class has been specified a NominatedStorageNotFoundError is returned. 748 func (s *K8sMetadataSuite) TestNominatedStorageNotFoundWithNilStorageClasses(c *gc.C) { 749 clientSet := fake.NewSimpleClientset( 750 newNode(map[string]string{}), 751 ) 752 753 _, err := provider.GetClusterMetadata( 754 context.TODO(), 755 "my-nominated-storage", 756 clientSet.CoreV1().Nodes(), 757 clientSet.StorageV1().StorageClasses(), 758 ) 759 760 var notFoundError *environs.NominatedStorageNotFound 761 c.Assert(err, gc.NotNil) 762 c.Assert(errors.As(err, ¬FoundError), jc.IsTrue) 763 c.Assert(notFoundError.StorageName, gc.Equals, "my-nominated-storage") 764 }