k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/test/integration/volume/persistent_volumes_test.go (about)

     1  /*
     2  Copyright 2014 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package volume
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"math/rand"
    23  	"os"
    24  	"strconv"
    25  	"testing"
    26  	"time"
    27  
    28  	v1 "k8s.io/api/core/v1"
    29  	storage "k8s.io/api/storage/v1"
    30  	"k8s.io/apimachinery/pkg/api/resource"
    31  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    32  	"k8s.io/apimachinery/pkg/watch"
    33  	"k8s.io/client-go/informers"
    34  	clientset "k8s.io/client-go/kubernetes"
    35  	restclient "k8s.io/client-go/rest"
    36  	ref "k8s.io/client-go/tools/reference"
    37  	kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
    38  	"k8s.io/kubernetes/pkg/api/legacyscheme"
    39  	persistentvolumecontroller "k8s.io/kubernetes/pkg/controller/volume/persistentvolume"
    40  	"k8s.io/kubernetes/pkg/volume"
    41  	volumetest "k8s.io/kubernetes/pkg/volume/testing"
    42  	"k8s.io/kubernetes/pkg/volume/util"
    43  	"k8s.io/kubernetes/test/integration/framework"
    44  	"k8s.io/kubernetes/test/utils/ktesting"
    45  
    46  	"k8s.io/klog/v2"
    47  )
    48  
    49  // Several tests in this file are configurable by environment variables:
    50  // KUBE_INTEGRATION_PV_OBJECTS - nr. of PVs/PVCs to be created
    51  //
    52  //	(100 by default)
    53  //
    54  // KUBE_INTEGRATION_PV_SYNC_PERIOD - volume controller sync period
    55  //
    56  //	(1s by default)
    57  //
    58  // KUBE_INTEGRATION_PV_END_SLEEP - for how long should
    59  //
    60  //	TestPersistentVolumeMultiPVsPVCs sleep when it's finished (0s by
    61  //	default). This is useful to test how long does it take for periodic sync
    62  //	to process bound PVs/PVCs.
    63  const defaultObjectCount = 100
    64  const defaultSyncPeriod = 1 * time.Second
    65  
    66  const provisionerPluginName = "kubernetes.io/mock-provisioner"
    67  
    68  func getObjectCount() int {
    69  	objectCount := defaultObjectCount
    70  	if s := os.Getenv("KUBE_INTEGRATION_PV_OBJECTS"); s != "" {
    71  		var err error
    72  		objectCount, err = strconv.Atoi(s)
    73  		if err != nil {
    74  			klog.Fatalf("cannot parse value of KUBE_INTEGRATION_PV_OBJECTS: %v", err)
    75  		}
    76  	}
    77  	klog.V(2).Infof("using KUBE_INTEGRATION_PV_OBJECTS=%d", objectCount)
    78  	return objectCount
    79  }
    80  
    81  func getSyncPeriod(syncPeriod time.Duration) time.Duration {
    82  	period := syncPeriod
    83  	if s := os.Getenv("KUBE_INTEGRATION_PV_SYNC_PERIOD"); s != "" {
    84  		var err error
    85  		period, err = time.ParseDuration(s)
    86  		if err != nil {
    87  			klog.Fatalf("cannot parse value of KUBE_INTEGRATION_PV_SYNC_PERIOD: %v", err)
    88  		}
    89  	}
    90  	klog.V(2).Infof("using KUBE_INTEGRATION_PV_SYNC_PERIOD=%v", period)
    91  	return period
    92  }
    93  
    94  func testSleep() {
    95  	var period time.Duration
    96  	if s := os.Getenv("KUBE_INTEGRATION_PV_END_SLEEP"); s != "" {
    97  		var err error
    98  		period, err = time.ParseDuration(s)
    99  		if err != nil {
   100  			klog.Fatalf("cannot parse value of KUBE_INTEGRATION_PV_END_SLEEP: %v", err)
   101  		}
   102  	}
   103  	klog.V(2).Infof("using KUBE_INTEGRATION_PV_END_SLEEP=%v", period)
   104  	if period != 0 {
   105  		time.Sleep(period)
   106  		klog.V(2).Infof("sleep finished")
   107  	}
   108  }
   109  
   110  func TestPersistentVolumeRecycler(t *testing.T) {
   111  	klog.V(2).Infof("TestPersistentVolumeRecycler started")
   112  	s := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount,StorageObjectInUseProtection"}, framework.SharedEtcd())
   113  	defer s.TearDownFn()
   114  	namespaceName := "pv-recycler"
   115  
   116  	tCtx := ktesting.Init(t)
   117  	defer tCtx.Cancel("test has completed")
   118  
   119  	testClient, ctrl, informers, watchPV, watchPVC := createClients(tCtx, namespaceName, t, s, defaultSyncPeriod)
   120  	defer watchPV.Stop()
   121  	defer watchPVC.Stop()
   122  
   123  	ns := framework.CreateNamespaceOrDie(testClient, namespaceName, t)
   124  	defer framework.DeleteNamespaceOrDie(testClient, ns, t)
   125  
   126  	// NOTE: This test cannot run in parallel, because it is creating and deleting
   127  	// non-namespaced objects (PersistenceVolumes).
   128  	defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
   129  
   130  	informers.Start(tCtx.Done())
   131  	go ctrl.Run(tCtx)
   132  
   133  	// This PV will be claimed, released, and recycled.
   134  	pv := createPV("fake-pv-recycler", "/tmp/foo", "10G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, v1.PersistentVolumeReclaimRecycle)
   135  	pvc := createPVC("fake-pvc-recycler", ns.Name, "5G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, "")
   136  
   137  	_, err := testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pv, metav1.CreateOptions{})
   138  	if err != nil {
   139  		t.Errorf("Failed to create PersistentVolume: %v", err)
   140  	}
   141  	klog.V(2).Infof("TestPersistentVolumeRecycler pvc created")
   142  
   143  	_, err = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc, metav1.CreateOptions{})
   144  	if err != nil {
   145  		t.Errorf("Failed to create PersistentVolumeClaim: %v", err)
   146  	}
   147  	klog.V(2).Infof("TestPersistentVolumeRecycler pvc created")
   148  
   149  	// wait until the controller pairs the volume and claim
   150  	waitForPersistentVolumePhase(testClient, pv.Name, watchPV, v1.VolumeBound)
   151  	klog.V(2).Infof("TestPersistentVolumeRecycler pv bound")
   152  	waitForPersistentVolumeClaimPhase(testClient, pvc.Name, ns.Name, watchPVC, v1.ClaimBound)
   153  	klog.V(2).Infof("TestPersistentVolumeRecycler pvc bound")
   154  
   155  	// deleting a claim releases the volume, after which it can be recycled
   156  	if err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Delete(context.TODO(), pvc.Name, metav1.DeleteOptions{}); err != nil {
   157  		t.Errorf("error deleting claim %s", pvc.Name)
   158  	}
   159  	klog.V(2).Infof("TestPersistentVolumeRecycler pvc deleted")
   160  
   161  	waitForPersistentVolumePhase(testClient, pv.Name, watchPV, v1.VolumeReleased)
   162  	klog.V(2).Infof("TestPersistentVolumeRecycler pv released")
   163  	waitForPersistentVolumePhase(testClient, pv.Name, watchPV, v1.VolumeAvailable)
   164  	klog.V(2).Infof("TestPersistentVolumeRecycler pv available")
   165  }
   166  
   167  func TestPersistentVolumeDeleter(t *testing.T) {
   168  	klog.V(2).Infof("TestPersistentVolumeDeleter started")
   169  	s := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount,StorageObjectInUseProtection"}, framework.SharedEtcd())
   170  	defer s.TearDownFn()
   171  	namespaceName := "pv-deleter"
   172  
   173  	tCtx := ktesting.Init(t)
   174  	defer tCtx.Cancel("test has completed")
   175  	testClient, ctrl, informers, watchPV, watchPVC := createClients(tCtx, namespaceName, t, s, defaultSyncPeriod)
   176  	defer watchPV.Stop()
   177  	defer watchPVC.Stop()
   178  
   179  	ns := framework.CreateNamespaceOrDie(testClient, namespaceName, t)
   180  	defer framework.DeleteNamespaceOrDie(testClient, ns, t)
   181  
   182  	// NOTE: This test cannot run in parallel, because it is creating and deleting
   183  	// non-namespaced objects (PersistenceVolumes).
   184  	defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
   185  
   186  	informers.Start(tCtx.Done())
   187  	go ctrl.Run(tCtx)
   188  
   189  	// This PV will be claimed, released, and deleted.
   190  	pv := createPV("fake-pv-deleter", "/tmp/foo", "10G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, v1.PersistentVolumeReclaimDelete)
   191  	pvc := createPVC("fake-pvc-deleter", ns.Name, "5G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, "")
   192  
   193  	_, err := testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pv, metav1.CreateOptions{})
   194  	if err != nil {
   195  		t.Errorf("Failed to create PersistentVolume: %v", err)
   196  	}
   197  	klog.V(2).Infof("TestPersistentVolumeDeleter pv created")
   198  	_, err = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc, metav1.CreateOptions{})
   199  	if err != nil {
   200  		t.Errorf("Failed to create PersistentVolumeClaim: %v", err)
   201  	}
   202  	klog.V(2).Infof("TestPersistentVolumeDeleter pvc created")
   203  	waitForPersistentVolumePhase(testClient, pv.Name, watchPV, v1.VolumeBound)
   204  	klog.V(2).Infof("TestPersistentVolumeDeleter pv bound")
   205  	waitForPersistentVolumeClaimPhase(testClient, pvc.Name, ns.Name, watchPVC, v1.ClaimBound)
   206  	klog.V(2).Infof("TestPersistentVolumeDeleter pvc bound")
   207  
   208  	// deleting a claim releases the volume, after which it can be recycled
   209  	if err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Delete(context.TODO(), pvc.Name, metav1.DeleteOptions{}); err != nil {
   210  		t.Errorf("error deleting claim %s", pvc.Name)
   211  	}
   212  	klog.V(2).Infof("TestPersistentVolumeDeleter pvc deleted")
   213  
   214  	waitForPersistentVolumePhase(testClient, pv.Name, watchPV, v1.VolumeReleased)
   215  	klog.V(2).Infof("TestPersistentVolumeDeleter pv released")
   216  
   217  	for {
   218  		event := <-watchPV.ResultChan()
   219  		if event.Type == watch.Deleted {
   220  			break
   221  		}
   222  	}
   223  	klog.V(2).Infof("TestPersistentVolumeDeleter pv deleted")
   224  }
   225  
   226  func TestPersistentVolumeBindRace(t *testing.T) {
   227  	// Test a race binding many claims to a PV that is pre-bound to a specific
   228  	// PVC. Only this specific PVC should get bound.
   229  	klog.V(2).Infof("TestPersistentVolumeBindRace started")
   230  	s := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount,StorageObjectInUseProtection"}, framework.SharedEtcd())
   231  	defer s.TearDownFn()
   232  	namespaceName := "pv-bind-race"
   233  
   234  	tCtx := ktesting.Init(t)
   235  	defer tCtx.Cancel("test has completed")
   236  	testClient, ctrl, informers, watchPV, watchPVC := createClients(tCtx, namespaceName, t, s, defaultSyncPeriod)
   237  	defer watchPV.Stop()
   238  	defer watchPVC.Stop()
   239  
   240  	ns := framework.CreateNamespaceOrDie(testClient, namespaceName, t)
   241  	defer framework.DeleteNamespaceOrDie(testClient, ns, t)
   242  
   243  	// NOTE: This test cannot run in parallel, because it is creating and deleting
   244  	// non-namespaced objects (PersistenceVolumes).
   245  	defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
   246  
   247  	informers.Start(tCtx.Done())
   248  	go ctrl.Run(tCtx)
   249  
   250  	pv := createPV("fake-pv-race", "/tmp/foo", "10G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, v1.PersistentVolumeReclaimRetain)
   251  	pvc := createPVC("fake-pvc-race", ns.Name, "5G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, "")
   252  	counter := 0
   253  	maxClaims := 100
   254  	claims := []*v1.PersistentVolumeClaim{}
   255  	for counter <= maxClaims {
   256  		counter++
   257  		newPvc := pvc.DeepCopy()
   258  		newPvc.ObjectMeta = metav1.ObjectMeta{Name: fmt.Sprintf("fake-pvc-race-%d", counter)}
   259  		claim, err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), newPvc, metav1.CreateOptions{})
   260  		if err != nil {
   261  			t.Fatalf("Error creating newPvc: %v", err)
   262  		}
   263  		claims = append(claims, claim)
   264  	}
   265  	klog.V(2).Infof("TestPersistentVolumeBindRace claims created")
   266  
   267  	// putting a bind manually on a pv should only match the claim it is bound to
   268  	claim := claims[rand.Intn(maxClaims-1)]
   269  	claimRef, err := ref.GetReference(legacyscheme.Scheme, claim)
   270  	if err != nil {
   271  		t.Fatalf("Unexpected error getting claimRef: %v", err)
   272  	}
   273  	pv.Spec.ClaimRef = claimRef
   274  	pv.Spec.ClaimRef.UID = ""
   275  
   276  	pv, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pv, metav1.CreateOptions{})
   277  	if err != nil {
   278  		t.Fatalf("Unexpected error creating pv: %v", err)
   279  	}
   280  	klog.V(2).Infof("TestPersistentVolumeBindRace pv created, pre-bound to %s", claim.Name)
   281  
   282  	waitForPersistentVolumePhase(testClient, pv.Name, watchPV, v1.VolumeBound)
   283  	klog.V(2).Infof("TestPersistentVolumeBindRace pv bound")
   284  	waitForAnyPersistentVolumeClaimPhase(watchPVC, v1.ClaimBound)
   285  	klog.V(2).Infof("TestPersistentVolumeBindRace pvc bound")
   286  
   287  	pv, err = testClient.CoreV1().PersistentVolumes().Get(context.TODO(), pv.Name, metav1.GetOptions{})
   288  	if err != nil {
   289  		t.Fatalf("Unexpected error getting pv: %v", err)
   290  	}
   291  	if pv.Spec.ClaimRef == nil {
   292  		t.Fatalf("Unexpected nil claimRef")
   293  	}
   294  	if pv.Spec.ClaimRef.Namespace != claimRef.Namespace || pv.Spec.ClaimRef.Name != claimRef.Name {
   295  		t.Fatalf("Bind mismatch! Expected %s/%s but got %s/%s", claimRef.Namespace, claimRef.Name, pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name)
   296  	}
   297  }
   298  
   299  // TestPersistentVolumeClaimLabelSelector test binding using label selectors
   300  func TestPersistentVolumeClaimLabelSelector(t *testing.T) {
   301  	s := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount,StorageObjectInUseProtection"}, framework.SharedEtcd())
   302  	defer s.TearDownFn()
   303  	namespaceName := "pvc-label-selector"
   304  
   305  	tCtx := ktesting.Init(t)
   306  	defer tCtx.Cancel("test has completed")
   307  	testClient, controller, informers, watchPV, watchPVC := createClients(tCtx, namespaceName, t, s, defaultSyncPeriod)
   308  	defer watchPV.Stop()
   309  	defer watchPVC.Stop()
   310  
   311  	ns := framework.CreateNamespaceOrDie(testClient, namespaceName, t)
   312  	defer framework.DeleteNamespaceOrDie(testClient, ns, t)
   313  
   314  	// NOTE: This test cannot run in parallel, because it is creating and deleting
   315  	// non-namespaced objects (PersistenceVolumes).
   316  	defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
   317  
   318  	informers.Start(tCtx.Done())
   319  	go controller.Run(tCtx)
   320  
   321  	var (
   322  		err     error
   323  		modes   = []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}
   324  		reclaim = v1.PersistentVolumeReclaimRetain
   325  
   326  		pvTrue  = createPV("pv-true", "/tmp/foo-label", "1G", modes, reclaim)
   327  		pvFalse = createPV("pv-false", "/tmp/foo-label", "1G", modes, reclaim)
   328  		pvc     = createPVC("pvc-ls-1", ns.Name, "1G", modes, "")
   329  	)
   330  
   331  	pvTrue.ObjectMeta.SetLabels(map[string]string{"foo": "true"})
   332  	pvFalse.ObjectMeta.SetLabels(map[string]string{"foo": "false"})
   333  
   334  	_, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvTrue, metav1.CreateOptions{})
   335  	if err != nil {
   336  		t.Fatalf("Failed to create PersistentVolume: %v", err)
   337  	}
   338  	_, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvFalse, metav1.CreateOptions{})
   339  	if err != nil {
   340  		t.Fatalf("Failed to create PersistentVolume: %v", err)
   341  	}
   342  	t.Log("volumes created")
   343  
   344  	pvc.Spec.Selector = &metav1.LabelSelector{
   345  		MatchLabels: map[string]string{
   346  			"foo": "true",
   347  		},
   348  	}
   349  
   350  	_, err = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc, metav1.CreateOptions{})
   351  	if err != nil {
   352  		t.Fatalf("Failed to create PersistentVolumeClaim: %v", err)
   353  	}
   354  	t.Log("claim created")
   355  
   356  	waitForAnyPersistentVolumePhase(watchPV, v1.VolumeBound)
   357  	t.Log("volume bound")
   358  	waitForPersistentVolumeClaimPhase(testClient, pvc.Name, ns.Name, watchPVC, v1.ClaimBound)
   359  	t.Log("claim bound")
   360  
   361  	pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-false", metav1.GetOptions{})
   362  	if err != nil {
   363  		t.Fatalf("Unexpected error getting pv: %v", err)
   364  	}
   365  	if pv.Spec.ClaimRef != nil {
   366  		t.Fatalf("False PV shouldn't be bound")
   367  	}
   368  	pv, err = testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-true", metav1.GetOptions{})
   369  	if err != nil {
   370  		t.Fatalf("Unexpected error getting pv: %v", err)
   371  	}
   372  	if pv.Spec.ClaimRef == nil {
   373  		t.Fatalf("True PV should be bound")
   374  	}
   375  	if pv.Spec.ClaimRef.Namespace != pvc.Namespace || pv.Spec.ClaimRef.Name != pvc.Name {
   376  		t.Fatalf("Bind mismatch! Expected %s/%s but got %s/%s", pvc.Namespace, pvc.Name, pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name)
   377  	}
   378  }
   379  
   380  // TestPersistentVolumeClaimLabelSelectorMatchExpressions test binding using
   381  // MatchExpressions label selectors
   382  func TestPersistentVolumeClaimLabelSelectorMatchExpressions(t *testing.T) {
   383  	s := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount,StorageObjectInUseProtection"}, framework.SharedEtcd())
   384  	defer s.TearDownFn()
   385  	namespaceName := "pvc-match-expressions"
   386  
   387  	tCtx := ktesting.Init(t)
   388  	defer tCtx.Cancel("test has completed")
   389  	testClient, controller, informers, watchPV, watchPVC := createClients(tCtx, namespaceName, t, s, defaultSyncPeriod)
   390  	defer watchPV.Stop()
   391  	defer watchPVC.Stop()
   392  
   393  	ns := framework.CreateNamespaceOrDie(testClient, namespaceName, t)
   394  	defer framework.DeleteNamespaceOrDie(testClient, ns, t)
   395  
   396  	// NOTE: This test cannot run in parallel, because it is creating and deleting
   397  	// non-namespaced objects (PersistenceVolumes).
   398  	defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
   399  
   400  	informers.Start(tCtx.Done())
   401  	go controller.Run(tCtx)
   402  
   403  	var (
   404  		err     error
   405  		modes   = []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}
   406  		reclaim = v1.PersistentVolumeReclaimRetain
   407  
   408  		pvTrue  = createPV("pv-true", "/tmp/foo-label", "1G", modes, reclaim)
   409  		pvFalse = createPV("pv-false", "/tmp/foo-label", "1G", modes, reclaim)
   410  		pvc     = createPVC("pvc-ls-1", ns.Name, "1G", modes, "")
   411  	)
   412  
   413  	pvTrue.ObjectMeta.SetLabels(map[string]string{"foo": "valA", "bar": ""})
   414  	pvFalse.ObjectMeta.SetLabels(map[string]string{"foo": "valB", "baz": ""})
   415  
   416  	_, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvTrue, metav1.CreateOptions{})
   417  	if err != nil {
   418  		t.Fatalf("Failed to create PersistentVolume: %v", err)
   419  	}
   420  	_, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvFalse, metav1.CreateOptions{})
   421  	if err != nil {
   422  		t.Fatalf("Failed to create PersistentVolume: %v", err)
   423  	}
   424  	t.Log("volumes created")
   425  
   426  	pvc.Spec.Selector = &metav1.LabelSelector{
   427  		MatchExpressions: []metav1.LabelSelectorRequirement{
   428  			{
   429  				Key:      "foo",
   430  				Operator: metav1.LabelSelectorOpIn,
   431  				Values:   []string{"valA"},
   432  			},
   433  			{
   434  				Key:      "foo",
   435  				Operator: metav1.LabelSelectorOpNotIn,
   436  				Values:   []string{"valB"},
   437  			},
   438  			{
   439  				Key:      "bar",
   440  				Operator: metav1.LabelSelectorOpExists,
   441  				Values:   []string{},
   442  			},
   443  			{
   444  				Key:      "baz",
   445  				Operator: metav1.LabelSelectorOpDoesNotExist,
   446  				Values:   []string{},
   447  			},
   448  		},
   449  	}
   450  
   451  	_, err = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc, metav1.CreateOptions{})
   452  	if err != nil {
   453  		t.Fatalf("Failed to create PersistentVolumeClaim: %v", err)
   454  	}
   455  	t.Log("claim created")
   456  
   457  	waitForAnyPersistentVolumePhase(watchPV, v1.VolumeBound)
   458  	t.Log("volume bound")
   459  	waitForPersistentVolumeClaimPhase(testClient, pvc.Name, ns.Name, watchPVC, v1.ClaimBound)
   460  	t.Log("claim bound")
   461  
   462  	pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-false", metav1.GetOptions{})
   463  	if err != nil {
   464  		t.Fatalf("Unexpected error getting pv: %v", err)
   465  	}
   466  	if pv.Spec.ClaimRef != nil {
   467  		t.Fatalf("False PV shouldn't be bound")
   468  	}
   469  	pv, err = testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-true", metav1.GetOptions{})
   470  	if err != nil {
   471  		t.Fatalf("Unexpected error getting pv: %v", err)
   472  	}
   473  	if pv.Spec.ClaimRef == nil {
   474  		t.Fatalf("True PV should be bound")
   475  	}
   476  	if pv.Spec.ClaimRef.Namespace != pvc.Namespace || pv.Spec.ClaimRef.Name != pvc.Name {
   477  		t.Fatalf("Bind mismatch! Expected %s/%s but got %s/%s", pvc.Namespace, pvc.Name, pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name)
   478  	}
   479  }
   480  
   481  // TestPersistentVolumeMultiPVs tests binding of one PVC to 100 PVs with
   482  // different size.
   483  func TestPersistentVolumeMultiPVs(t *testing.T) {
   484  	s := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount,StorageObjectInUseProtection"}, framework.SharedEtcd())
   485  	defer s.TearDownFn()
   486  	namespaceName := "multi-pvs"
   487  
   488  	tCtx := ktesting.Init(t)
   489  	defer tCtx.Cancel("test has completed")
   490  	testClient, controller, informers, watchPV, watchPVC := createClients(tCtx, namespaceName, t, s, defaultSyncPeriod)
   491  	defer watchPV.Stop()
   492  	defer watchPVC.Stop()
   493  
   494  	ns := framework.CreateNamespaceOrDie(testClient, namespaceName, t)
   495  	defer framework.DeleteNamespaceOrDie(testClient, ns, t)
   496  
   497  	// NOTE: This test cannot run in parallel, because it is creating and deleting
   498  	// non-namespaced objects (PersistenceVolumes).
   499  	defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
   500  
   501  	informers.Start(tCtx.Done())
   502  	go controller.Run(tCtx)
   503  
   504  	maxPVs := getObjectCount()
   505  	pvs := make([]*v1.PersistentVolume, maxPVs)
   506  	for i := 0; i < maxPVs; i++ {
   507  		// This PV will be claimed, released, and deleted
   508  		pvs[i] = createPV("pv-"+strconv.Itoa(i), "/tmp/foo"+strconv.Itoa(i), strconv.Itoa(i+1)+"G",
   509  			[]v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, v1.PersistentVolumeReclaimRetain)
   510  	}
   511  
   512  	pvc := createPVC("pvc-2", ns.Name, strconv.Itoa(maxPVs/2)+"G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, "")
   513  
   514  	for i := 0; i < maxPVs; i++ {
   515  		_, err := testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvs[i], metav1.CreateOptions{})
   516  		if err != nil {
   517  			t.Errorf("Failed to create PersistentVolume %d: %v", i, err)
   518  		}
   519  		waitForPersistentVolumePhase(testClient, pvs[i].Name, watchPV, v1.VolumeAvailable)
   520  	}
   521  	t.Log("volumes created")
   522  
   523  	_, err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc, metav1.CreateOptions{})
   524  	if err != nil {
   525  		t.Errorf("Failed to create PersistentVolumeClaim: %v", err)
   526  	}
   527  	t.Log("claim created")
   528  
   529  	// wait until the binder pairs the claim with a volume
   530  	waitForAnyPersistentVolumePhase(watchPV, v1.VolumeBound)
   531  	t.Log("volume bound")
   532  	waitForPersistentVolumeClaimPhase(testClient, pvc.Name, ns.Name, watchPVC, v1.ClaimBound)
   533  	t.Log("claim bound")
   534  
   535  	// only one PV is bound
   536  	bound := 0
   537  	for i := 0; i < maxPVs; i++ {
   538  		pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), pvs[i].Name, metav1.GetOptions{})
   539  		if err != nil {
   540  			t.Fatalf("Unexpected error getting pv: %v", err)
   541  		}
   542  		if pv.Spec.ClaimRef == nil {
   543  			continue
   544  		}
   545  		// found a bounded PV
   546  		p := pv.Spec.Capacity[v1.ResourceStorage]
   547  		pvCap := p.Value()
   548  		expectedCap := resource.MustParse(strconv.Itoa(maxPVs/2) + "G")
   549  		expectedCapVal := expectedCap.Value()
   550  		if pv.Spec.ClaimRef.Name != pvc.Name || pvCap != expectedCapVal {
   551  			t.Fatalf("Bind mismatch! Expected %s capacity %d but got %s capacity %d", pvc.Name, expectedCapVal, pv.Spec.ClaimRef.Name, pvCap)
   552  		}
   553  		t.Logf("claim bounded to %s capacity %v", pv.Name, pv.Spec.Capacity[v1.ResourceStorage])
   554  		bound++
   555  	}
   556  	t.Log("volumes checked")
   557  
   558  	if bound != 1 {
   559  		t.Fatalf("Only 1 PV should be bound but got %d", bound)
   560  	}
   561  
   562  	// deleting a claim releases the volume
   563  	if err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Delete(context.TODO(), pvc.Name, metav1.DeleteOptions{}); err != nil {
   564  		t.Errorf("error deleting claim %s", pvc.Name)
   565  	}
   566  	t.Log("claim deleted")
   567  
   568  	waitForAnyPersistentVolumePhase(watchPV, v1.VolumeReleased)
   569  	t.Log("volumes released")
   570  }
   571  
   572  // TestPersistentVolumeMultiPVsPVCs tests binding of 100 PVC to 100 PVs.
   573  // This test is configurable by KUBE_INTEGRATION_PV_* variables.
   574  func TestPersistentVolumeMultiPVsPVCs(t *testing.T) {
   575  	s := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount,StorageObjectInUseProtection"}, framework.SharedEtcd())
   576  	defer s.TearDownFn()
   577  	namespaceName := "multi-pvs-pvcs"
   578  
   579  	tCtx := ktesting.Init(t)
   580  	defer tCtx.Cancel("test has completed")
   581  	testClient, binder, informers, watchPV, watchPVC := createClients(tCtx, namespaceName, t, s, defaultSyncPeriod)
   582  	defer watchPV.Stop()
   583  	defer watchPVC.Stop()
   584  
   585  	ns := framework.CreateNamespaceOrDie(testClient, namespaceName, t)
   586  	defer framework.DeleteNamespaceOrDie(testClient, ns, t)
   587  
   588  	// NOTE: This test cannot run in parallel, because it is creating and deleting
   589  	// non-namespaced objects (PersistenceVolumes).
   590  	defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
   591  
   592  	informers.Start(tCtx.Done())
   593  	go binder.Run(tCtx)
   594  
   595  	objCount := getObjectCount()
   596  	pvs := make([]*v1.PersistentVolume, objCount)
   597  	pvcs := make([]*v1.PersistentVolumeClaim, objCount)
   598  	for i := 0; i < objCount; i++ {
   599  		// This PV will be claimed, released, and deleted
   600  		pvs[i] = createPV("pv-"+strconv.Itoa(i), "/tmp/foo"+strconv.Itoa(i), "1G",
   601  			[]v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, v1.PersistentVolumeReclaimRetain)
   602  		pvcs[i] = createPVC("pvc-"+strconv.Itoa(i), ns.Name, "1G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, "")
   603  	}
   604  
   605  	// Create PVs first
   606  	klog.V(2).Infof("TestPersistentVolumeMultiPVsPVCs: start")
   607  
   608  	// Create the volumes in a separate goroutine to pop events from
   609  	// watchPV early - it seems it has limited capacity and it gets stuck
   610  	// with >3000 volumes.
   611  	go func() {
   612  		for i := 0; i < objCount; i++ {
   613  			_, _ = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvs[i], metav1.CreateOptions{})
   614  		}
   615  	}()
   616  	// Wait for them to get Available
   617  	for i := 0; i < objCount; i++ {
   618  		waitForAnyPersistentVolumePhase(watchPV, v1.VolumeAvailable)
   619  		klog.V(1).Infof("%d volumes available", i+1)
   620  	}
   621  	klog.V(2).Infof("TestPersistentVolumeMultiPVsPVCs: volumes are Available")
   622  
   623  	// Start a separate goroutine that randomly modifies PVs and PVCs while the
   624  	// binder is working. We test that the binder can bind volumes despite
   625  	// users modifying objects underneath.
   626  	stopCh := make(chan struct{}, 0)
   627  	go func() {
   628  		for {
   629  			// Roll a dice and decide a PV or PVC to modify
   630  			if rand.Intn(2) == 0 {
   631  				// Modify PV
   632  				i := rand.Intn(objCount)
   633  				name := "pv-" + strconv.Itoa(i)
   634  				pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), name, metav1.GetOptions{})
   635  				if err != nil {
   636  					// Silently ignore error, the PV may have be already deleted
   637  					// or not exists yet.
   638  					klog.V(4).Infof("Failed to read PV %s: %v", name, err)
   639  					continue
   640  				}
   641  				if pv.Annotations == nil {
   642  					pv.Annotations = map[string]string{"TestAnnotation": fmt.Sprint(rand.Int())}
   643  				} else {
   644  					pv.Annotations["TestAnnotation"] = fmt.Sprint(rand.Int())
   645  				}
   646  				_, err = testClient.CoreV1().PersistentVolumes().Update(context.TODO(), pv, metav1.UpdateOptions{})
   647  				if err != nil {
   648  					// Silently ignore error, the PV may have been updated by
   649  					// the controller.
   650  					klog.V(4).Infof("Failed to update PV %s: %v", pv.Name, err)
   651  					continue
   652  				}
   653  				klog.V(4).Infof("Updated PV %s", pv.Name)
   654  			} else {
   655  				// Modify PVC
   656  				i := rand.Intn(objCount)
   657  				name := "pvc-" + strconv.Itoa(i)
   658  				pvc, err := testClient.CoreV1().PersistentVolumeClaims(metav1.NamespaceDefault).Get(context.TODO(), name, metav1.GetOptions{})
   659  				if err != nil {
   660  					// Silently ignore error, the PVC may have be already
   661  					// deleted or not exists yet.
   662  					klog.V(4).Infof("Failed to read PVC %s: %v", name, err)
   663  					continue
   664  				}
   665  				if pvc.Annotations == nil {
   666  					pvc.Annotations = map[string]string{"TestAnnotation": fmt.Sprint(rand.Int())}
   667  				} else {
   668  					pvc.Annotations["TestAnnotation"] = fmt.Sprint(rand.Int())
   669  				}
   670  				_, err = testClient.CoreV1().PersistentVolumeClaims(metav1.NamespaceDefault).Update(context.TODO(), pvc, metav1.UpdateOptions{})
   671  				if err != nil {
   672  					// Silently ignore error, the PVC may have been updated by
   673  					// the controller.
   674  					klog.V(4).Infof("Failed to update PVC %s: %v", pvc.Name, err)
   675  					continue
   676  				}
   677  				klog.V(4).Infof("Updated PVC %s", pvc.Name)
   678  			}
   679  
   680  			select {
   681  			case <-stopCh:
   682  				return
   683  			default:
   684  				continue
   685  			}
   686  		}
   687  	}()
   688  
   689  	// Create the claims, again in a separate goroutine.
   690  	go func() {
   691  		for i := 0; i < objCount; i++ {
   692  			_, _ = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvcs[i], metav1.CreateOptions{})
   693  		}
   694  	}()
   695  
   696  	// wait until the binder pairs all claims
   697  	for i := 0; i < objCount; i++ {
   698  		waitForAnyPersistentVolumeClaimPhase(watchPVC, v1.ClaimBound)
   699  		klog.V(1).Infof("%d claims bound", i+1)
   700  	}
   701  	// wait until the binder pairs all volumes
   702  	for i := 0; i < objCount; i++ {
   703  		waitForPersistentVolumePhase(testClient, pvs[i].Name, watchPV, v1.VolumeBound)
   704  		klog.V(1).Infof("%d claims bound", i+1)
   705  	}
   706  
   707  	klog.V(2).Infof("TestPersistentVolumeMultiPVsPVCs: claims are bound")
   708  	close(stopCh)
   709  
   710  	// check that everything is bound to something
   711  	for i := 0; i < objCount; i++ {
   712  		pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), pvs[i].Name, metav1.GetOptions{})
   713  		if err != nil {
   714  			t.Fatalf("Unexpected error getting pv: %v", err)
   715  		}
   716  		if pv.Spec.ClaimRef == nil {
   717  			t.Fatalf("PV %q is not bound", pv.Name)
   718  		}
   719  		klog.V(2).Infof("PV %q is bound to PVC %q", pv.Name, pv.Spec.ClaimRef.Name)
   720  
   721  		pvc, err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Get(context.TODO(), pvcs[i].Name, metav1.GetOptions{})
   722  		if err != nil {
   723  			t.Fatalf("Unexpected error getting pvc: %v", err)
   724  		}
   725  		if pvc.Spec.VolumeName == "" {
   726  			t.Fatalf("PVC %q is not bound", pvc.Name)
   727  		}
   728  		klog.V(2).Infof("PVC %q is bound to PV %q", pvc.Name, pvc.Spec.VolumeName)
   729  	}
   730  	testSleep()
   731  }
   732  
   733  // TestPersistentVolumeControllerStartup tests startup of the controller.
   734  // The controller should not unbind any volumes when it starts.
   735  func TestPersistentVolumeControllerStartup(t *testing.T) {
   736  	s := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount,StorageObjectInUseProtection"}, framework.SharedEtcd())
   737  	defer s.TearDownFn()
   738  	namespaceName := "controller-startup"
   739  
   740  	objCount := getObjectCount()
   741  
   742  	const shortSyncPeriod = 2 * time.Second
   743  	syncPeriod := getSyncPeriod(shortSyncPeriod)
   744  
   745  	tCtx := ktesting.Init(t)
   746  	defer tCtx.Cancel("test has completed")
   747  	testClient, binder, informers, watchPV, watchPVC := createClients(tCtx, namespaceName, t, s, shortSyncPeriod)
   748  	defer watchPV.Stop()
   749  	defer watchPVC.Stop()
   750  
   751  	ns := framework.CreateNamespaceOrDie(testClient, namespaceName, t)
   752  	defer framework.DeleteNamespaceOrDie(testClient, ns, t)
   753  
   754  	// Create *bound* volumes and PVCs
   755  	pvs := make([]*v1.PersistentVolume, objCount)
   756  	pvcs := make([]*v1.PersistentVolumeClaim, objCount)
   757  	for i := 0; i < objCount; i++ {
   758  		pvName := "pv-startup-" + strconv.Itoa(i)
   759  		pvcName := "pvc-startup-" + strconv.Itoa(i)
   760  
   761  		pvc := createPVC(pvcName, ns.Name, "1G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, "")
   762  		pvc.Annotations = map[string]string{"annBindCompleted": ""}
   763  		pvc.Spec.VolumeName = pvName
   764  		newPVC, err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc, metav1.CreateOptions{})
   765  		if err != nil {
   766  			t.Fatalf("Cannot create claim %q: %v", pvc.Name, err)
   767  		}
   768  		// Save Bound status as a separate transaction
   769  		newPVC.Status.Phase = v1.ClaimBound
   770  		newPVC, err = testClient.CoreV1().PersistentVolumeClaims(ns.Name).UpdateStatus(context.TODO(), newPVC, metav1.UpdateOptions{})
   771  		if err != nil {
   772  			t.Fatalf("Cannot update claim status %q: %v", pvc.Name, err)
   773  		}
   774  		pvcs[i] = newPVC
   775  		// Drain watchPVC with all events generated by the PVC until it's bound
   776  		// We don't want to catch "PVC created with Status.Phase == Pending"
   777  		// later in this test.
   778  		waitForAnyPersistentVolumeClaimPhase(watchPVC, v1.ClaimBound)
   779  
   780  		pv := createPV(pvName, "/tmp/foo"+strconv.Itoa(i), "1G",
   781  			[]v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, v1.PersistentVolumeReclaimRetain)
   782  		claimRef, err := ref.GetReference(legacyscheme.Scheme, newPVC)
   783  		if err != nil {
   784  			klog.V(3).Infof("unexpected error getting claim reference: %v", err)
   785  			return
   786  		}
   787  		pv.Spec.ClaimRef = claimRef
   788  		newPV, err := testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pv, metav1.CreateOptions{})
   789  		if err != nil {
   790  			t.Fatalf("Cannot create volume %q: %v", pv.Name, err)
   791  		}
   792  		// Save Bound status as a separate transaction
   793  		newPV.Status.Phase = v1.VolumeBound
   794  		newPV, err = testClient.CoreV1().PersistentVolumes().UpdateStatus(context.TODO(), newPV, metav1.UpdateOptions{})
   795  		if err != nil {
   796  			t.Fatalf("Cannot update volume status %q: %v", pv.Name, err)
   797  		}
   798  		pvs[i] = newPV
   799  		// Drain watchPV with all events generated by the PV until it's bound
   800  		// We don't want to catch "PV created with Status.Phase == Pending"
   801  		// later in this test.
   802  		waitForAnyPersistentVolumePhase(watchPV, v1.VolumeBound)
   803  	}
   804  
   805  	// Start the controller when all PVs and PVCs are already saved in etcd
   806  	informers.Start(tCtx.Done())
   807  	go binder.Run(tCtx)
   808  
   809  	// wait for at least two sync periods for changes. No volume should be
   810  	// Released and no claim should be Lost during this time.
   811  	timer := time.NewTimer(2 * syncPeriod)
   812  	defer timer.Stop()
   813  	finished := false
   814  	for !finished {
   815  		select {
   816  		case volumeEvent := <-watchPV.ResultChan():
   817  			volume, ok := volumeEvent.Object.(*v1.PersistentVolume)
   818  			if !ok {
   819  				continue
   820  			}
   821  			if volume.Status.Phase != v1.VolumeBound {
   822  				t.Errorf("volume %s unexpectedly changed state to %s", volume.Name, volume.Status.Phase)
   823  			}
   824  
   825  		case claimEvent := <-watchPVC.ResultChan():
   826  			claim, ok := claimEvent.Object.(*v1.PersistentVolumeClaim)
   827  			if !ok {
   828  				continue
   829  			}
   830  			if claim.Status.Phase != v1.ClaimBound {
   831  				t.Errorf("claim %s unexpectedly changed state to %s", claim.Name, claim.Status.Phase)
   832  			}
   833  
   834  		case <-timer.C:
   835  			// Wait finished
   836  			klog.V(2).Infof("Wait finished")
   837  			finished = true
   838  		}
   839  	}
   840  
   841  	// check that everything is bound to something
   842  	for i := 0; i < objCount; i++ {
   843  		pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), pvs[i].Name, metav1.GetOptions{})
   844  		if err != nil {
   845  			t.Fatalf("Unexpected error getting pv: %v", err)
   846  		}
   847  		if pv.Spec.ClaimRef == nil {
   848  			t.Fatalf("PV %q is not bound", pv.Name)
   849  		}
   850  		klog.V(2).Infof("PV %q is bound to PVC %q", pv.Name, pv.Spec.ClaimRef.Name)
   851  
   852  		pvc, err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Get(context.TODO(), pvcs[i].Name, metav1.GetOptions{})
   853  		if err != nil {
   854  			t.Fatalf("Unexpected error getting pvc: %v", err)
   855  		}
   856  		if pvc.Spec.VolumeName == "" {
   857  			t.Fatalf("PVC %q is not bound", pvc.Name)
   858  		}
   859  		klog.V(2).Infof("PVC %q is bound to PV %q", pvc.Name, pvc.Spec.VolumeName)
   860  	}
   861  }
   862  
   863  // TestPersistentVolumeProvisionMultiPVCs tests provisioning of many PVCs.
   864  // This test is configurable by KUBE_INTEGRATION_PV_* variables.
   865  func TestPersistentVolumeProvisionMultiPVCs(t *testing.T) {
   866  	s := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount,StorageObjectInUseProtection"}, framework.SharedEtcd())
   867  	defer s.TearDownFn()
   868  	namespaceName := "provision-multi-pvs"
   869  
   870  	tCtx := ktesting.Init(t)
   871  	defer tCtx.Cancel("test has completed")
   872  	testClient, binder, informers, watchPV, watchPVC := createClients(tCtx, namespaceName, t, s, defaultSyncPeriod)
   873  	defer watchPV.Stop()
   874  	defer watchPVC.Stop()
   875  
   876  	ns := framework.CreateNamespaceOrDie(testClient, namespaceName, t)
   877  	defer framework.DeleteNamespaceOrDie(testClient, ns, t)
   878  
   879  	// NOTE: This test cannot run in parallel, because it is creating and deleting
   880  	// non-namespaced objects (PersistenceVolumes and StorageClasses).
   881  	defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
   882  	defer testClient.StorageV1().StorageClasses().DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
   883  
   884  	storageClass := storage.StorageClass{
   885  		TypeMeta: metav1.TypeMeta{
   886  			Kind: "StorageClass",
   887  		},
   888  		ObjectMeta: metav1.ObjectMeta{
   889  			Name: "gold",
   890  		},
   891  		Provisioner: provisionerPluginName,
   892  	}
   893  	testClient.StorageV1().StorageClasses().Create(context.TODO(), &storageClass, metav1.CreateOptions{})
   894  
   895  	informers.Start(tCtx.Done())
   896  	go binder.Run(tCtx)
   897  
   898  	objCount := getObjectCount()
   899  	pvcs := make([]*v1.PersistentVolumeClaim, objCount)
   900  	for i := 0; i < objCount; i++ {
   901  		pvc := createPVC("pvc-provision-"+strconv.Itoa(i), ns.Name, "1G", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, "gold")
   902  		pvcs[i] = pvc
   903  	}
   904  
   905  	klog.V(2).Infof("TestPersistentVolumeProvisionMultiPVCs: start")
   906  	// Create the claims in a separate goroutine to pop events from watchPVC
   907  	// early. It gets stuck with >3000 claims.
   908  	go func() {
   909  		for i := 0; i < objCount; i++ {
   910  			_, _ = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvcs[i], metav1.CreateOptions{})
   911  		}
   912  	}()
   913  
   914  	// Wait until the controller provisions and binds all of them
   915  	for i := 0; i < objCount; i++ {
   916  		waitForAnyPersistentVolumeClaimPhase(watchPVC, v1.ClaimBound)
   917  		klog.V(1).Infof("%d claims bound", i+1)
   918  	}
   919  	klog.V(2).Infof("TestPersistentVolumeProvisionMultiPVCs: claims are bound")
   920  
   921  	// check that we have enough bound PVs
   922  	pvList, err := testClient.CoreV1().PersistentVolumes().List(context.TODO(), metav1.ListOptions{})
   923  	if err != nil {
   924  		t.Fatalf("Failed to list volumes: %s", err)
   925  	}
   926  	if len(pvList.Items) != objCount {
   927  		t.Fatalf("Expected to get %d volumes, got %d", objCount, len(pvList.Items))
   928  	}
   929  	for i := 0; i < objCount; i++ {
   930  		pv := &pvList.Items[i]
   931  		if pv.Status.Phase != v1.VolumeBound {
   932  			t.Fatalf("Expected volume %s to be bound, is %s instead", pv.Name, pv.Status.Phase)
   933  		}
   934  		klog.V(2).Infof("PV %q is bound to PVC %q", pv.Name, pv.Spec.ClaimRef.Name)
   935  	}
   936  
   937  	// Delete the claims
   938  	for i := 0; i < objCount; i++ {
   939  		_ = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Delete(context.TODO(), pvcs[i].Name, metav1.DeleteOptions{})
   940  	}
   941  
   942  	// Wait for the PVs to get deleted by listing remaining volumes
   943  	// (delete events were unreliable)
   944  	for {
   945  		volumes, err := testClient.CoreV1().PersistentVolumes().List(context.TODO(), metav1.ListOptions{})
   946  		if err != nil {
   947  			t.Fatalf("Failed to list volumes: %v", err)
   948  		}
   949  
   950  		klog.V(1).Infof("%d volumes remaining", len(volumes.Items))
   951  		if len(volumes.Items) == 0 {
   952  			break
   953  		}
   954  		time.Sleep(time.Second)
   955  	}
   956  	klog.V(2).Infof("TestPersistentVolumeProvisionMultiPVCs: volumes are deleted")
   957  }
   958  
   959  // TestPersistentVolumeMultiPVsDiffAccessModes tests binding of one PVC to two
   960  // PVs with different access modes.
   961  func TestPersistentVolumeMultiPVsDiffAccessModes(t *testing.T) {
   962  	s := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount,StorageObjectInUseProtection"}, framework.SharedEtcd())
   963  	defer s.TearDownFn()
   964  	namespaceName := "multi-pvs-diff-access"
   965  
   966  	tCtx := ktesting.Init(t)
   967  	defer tCtx.Cancel("test has completed")
   968  	testClient, controller, informers, watchPV, watchPVC := createClients(tCtx, namespaceName, t, s, defaultSyncPeriod)
   969  	defer watchPV.Stop()
   970  	defer watchPVC.Stop()
   971  
   972  	ns := framework.CreateNamespaceOrDie(testClient, namespaceName, t)
   973  	defer framework.DeleteNamespaceOrDie(testClient, ns, t)
   974  
   975  	// NOTE: This test cannot run in parallel, because it is creating and deleting
   976  	// non-namespaced objects (PersistenceVolumes).
   977  	defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
   978  
   979  	informers.Start(tCtx.Done())
   980  	go controller.Run(tCtx)
   981  
   982  	// This PV will be claimed, released, and deleted
   983  	pvRwo := createPV("pv-rwo", "/tmp/foo", "10G",
   984  		[]v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, v1.PersistentVolumeReclaimRetain)
   985  	pvRwm := createPV("pv-rwm", "/tmp/bar", "10G",
   986  		[]v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, v1.PersistentVolumeReclaimRetain)
   987  
   988  	pvc := createPVC("pvc-rwm", ns.Name, "5G", []v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, "")
   989  
   990  	_, err := testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvRwm, metav1.CreateOptions{})
   991  	if err != nil {
   992  		t.Errorf("Failed to create PersistentVolume: %v", err)
   993  	}
   994  	_, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvRwo, metav1.CreateOptions{})
   995  	if err != nil {
   996  		t.Errorf("Failed to create PersistentVolume: %v", err)
   997  	}
   998  	t.Log("volumes created")
   999  
  1000  	_, err = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc, metav1.CreateOptions{})
  1001  	if err != nil {
  1002  		t.Errorf("Failed to create PersistentVolumeClaim: %v", err)
  1003  	}
  1004  	t.Log("claim created")
  1005  
  1006  	// wait until the controller pairs the volume and claim
  1007  	waitForAnyPersistentVolumePhase(watchPV, v1.VolumeBound)
  1008  	t.Log("volume bound")
  1009  	waitForPersistentVolumeClaimPhase(testClient, pvc.Name, ns.Name, watchPVC, v1.ClaimBound)
  1010  	t.Log("claim bound")
  1011  
  1012  	// only RWM PV is bound
  1013  	pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-rwo", metav1.GetOptions{})
  1014  	if err != nil {
  1015  		t.Fatalf("Unexpected error getting pv: %v", err)
  1016  	}
  1017  	if pv.Spec.ClaimRef != nil {
  1018  		t.Fatalf("ReadWriteOnce PV shouldn't be bound")
  1019  	}
  1020  	pv, err = testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-rwm", metav1.GetOptions{})
  1021  	if err != nil {
  1022  		t.Fatalf("Unexpected error getting pv: %v", err)
  1023  	}
  1024  	if pv.Spec.ClaimRef == nil {
  1025  		t.Fatalf("ReadWriteMany PV should be bound")
  1026  	}
  1027  	if pv.Spec.ClaimRef.Name != pvc.Name {
  1028  		t.Fatalf("Bind mismatch! Expected %s but got %s", pvc.Name, pv.Spec.ClaimRef.Name)
  1029  	}
  1030  
  1031  	// deleting a claim releases the volume
  1032  	if err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Delete(context.TODO(), pvc.Name, metav1.DeleteOptions{}); err != nil {
  1033  		t.Errorf("error deleting claim %s", pvc.Name)
  1034  	}
  1035  	t.Log("claim deleted")
  1036  
  1037  	waitForAnyPersistentVolumePhase(watchPV, v1.VolumeReleased)
  1038  	t.Log("volume released")
  1039  }
  1040  
  1041  // TestRetroactiveStorageClassAssignment tests PVC retroactive storage class
  1042  // assignment and binding of PVCs with storage class name set to nil or "" with
  1043  // and without presence of a default SC.
  1044  func TestRetroactiveStorageClassAssignment(t *testing.T) {
  1045  	s := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=DefaultStorageClass"}, framework.SharedEtcd())
  1046  	defer s.TearDownFn()
  1047  	namespaceName := "retro-pvc-sc"
  1048  	defaultStorageClassName := "gold"
  1049  	storageClassName := "silver"
  1050  
  1051  	tCtx := ktesting.Init(t)
  1052  	defer tCtx.Cancel("test has completed")
  1053  	testClient, binder, informers, watchPV, watchPVC := createClients(tCtx, namespaceName, t, s, defaultSyncPeriod)
  1054  	defer watchPV.Stop()
  1055  	defer watchPVC.Stop()
  1056  
  1057  	ns := framework.CreateNamespaceOrDie(testClient, namespaceName, t)
  1058  	defer framework.DeleteNamespaceOrDie(testClient, ns, t)
  1059  
  1060  	// NOTE: This test cannot run in parallel, because it is creating and deleting
  1061  	// non-namespaced objects (PersistenceVolumes and StorageClasses).
  1062  	defer testClient.CoreV1().PersistentVolumes().DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
  1063  	defer testClient.CoreV1().PersistentVolumeClaims(namespaceName).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
  1064  	defer testClient.StorageV1().StorageClasses().DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
  1065  
  1066  	// Create non default SC (extra SC - should not be used by any PVC in this test).
  1067  	nonDefaultSC := storage.StorageClass{
  1068  		TypeMeta: metav1.TypeMeta{
  1069  			Kind: "StorageClass",
  1070  		},
  1071  		ObjectMeta: metav1.ObjectMeta{
  1072  			Name: storageClassName,
  1073  			Annotations: map[string]string{
  1074  				util.IsDefaultStorageClassAnnotation: "false",
  1075  			},
  1076  		},
  1077  		Provisioner: provisionerPluginName,
  1078  	}
  1079  	if _, err := testClient.StorageV1().StorageClasses().Create(context.TODO(), &nonDefaultSC, metav1.CreateOptions{}); err != nil {
  1080  		t.Errorf("Failed to create a storage class: %v", err)
  1081  	}
  1082  
  1083  	informers.Start(tCtx.Done())
  1084  	go binder.Run(tCtx)
  1085  
  1086  	klog.V(2).Infof("TestRetroactiveStorageClassAssignment: start")
  1087  
  1088  	// 1. Test that PV with SC set to "" binds to PVC with SC set to nil while default SC does not exist (verifies that feature enablement does not break old behavior).
  1089  	pv1 := createPVWithStorageClass("pv-1", "/tmp/foo", "5G", "",
  1090  		[]v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, v1.PersistentVolumeReclaimRetain)
  1091  	_, err := testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pv1, metav1.CreateOptions{})
  1092  	if err != nil {
  1093  		t.Errorf("Failed to create PersistentVolume: %v", err)
  1094  	}
  1095  
  1096  	pvc1 := createPVCWithNilStorageClass("pvc-1", ns.Name, "5G", []v1.PersistentVolumeAccessMode{v1.ReadWriteMany})
  1097  	_, err = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc1, metav1.CreateOptions{})
  1098  	if err != nil {
  1099  		t.Errorf("Failed to create PersistentVolumeClaim: %v", err)
  1100  	}
  1101  
  1102  	// Wait until the controller pairs the volume.
  1103  	waitForPersistentVolumePhase(testClient, pv1.Name, watchPV, v1.VolumeBound)
  1104  	t.Log("volume bound")
  1105  	waitForPersistentVolumeClaimPhase(testClient, pvc1.Name, ns.Name, watchPVC, v1.ClaimBound)
  1106  	t.Log("claim bound")
  1107  
  1108  	pv, err := testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-1", metav1.GetOptions{})
  1109  	if err != nil {
  1110  		t.Fatalf("Unexpected error getting pv: %v", err)
  1111  	}
  1112  	if pv.Spec.ClaimRef == nil {
  1113  		t.Fatalf("PV %s with \"\" storage class should have been bound to PVC %s that has nil storage class", pv1.Name, pvc1.Name)
  1114  	}
  1115  	if pv.Spec.ClaimRef.Name != pvc1.Name {
  1116  		t.Fatalf("Bind mismatch! Expected %s but got %s", pvc1.Name, pv.Spec.ClaimRef.Name)
  1117  	}
  1118  
  1119  	// 2. Test that retroactive SC assignment works - default SC is created after creation of PVC with nil SC.
  1120  	pvcRetro := createPVCWithNilStorageClass("pvc-provision-noclass", ns.Name, "5G", []v1.PersistentVolumeAccessMode{v1.ReadWriteMany})
  1121  	if _, err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvcRetro, metav1.CreateOptions{}); err != nil {
  1122  		t.Errorf("Failed to create PVC: %v", err)
  1123  	}
  1124  	t.Log("claim created")
  1125  
  1126  	// Create default SC.
  1127  	defaultSC := storage.StorageClass{
  1128  		TypeMeta: metav1.TypeMeta{
  1129  			Kind: "StorageClass",
  1130  		},
  1131  		ObjectMeta: metav1.ObjectMeta{
  1132  			Name: defaultStorageClassName,
  1133  			Annotations: map[string]string{
  1134  				util.IsDefaultStorageClassAnnotation: "true",
  1135  			},
  1136  		},
  1137  		Provisioner: provisionerPluginName,
  1138  	}
  1139  	if _, err := testClient.StorageV1().StorageClasses().Create(context.TODO(), &defaultSC, metav1.CreateOptions{}); err != nil {
  1140  		t.Errorf("Failed to create a storage class: %v", err)
  1141  	}
  1142  
  1143  	// Verify SC was assigned retroactively to PVC.
  1144  	if _, ok := waitForPersistentVolumeClaimStorageClass(t, pvcRetro.Name, defaultStorageClassName, watchPVC, 20*time.Second); !ok {
  1145  		t.Errorf("Expected claim %s to get a storage class %s assigned retroactively", pvcRetro.Name, defaultStorageClassName)
  1146  	}
  1147  
  1148  	waitForPersistentVolumeClaimPhase(testClient, pvcRetro.Name, ns.Name, watchPVC, v1.ClaimBound)
  1149  
  1150  	// 3. Test that a new claim with nil class will still bind to PVs with SC set to "" (if available) and SC will not be assigned retroactively.
  1151  	pv3 := createPVWithStorageClass("pv-3", "/tmp/bar", "5G", "",
  1152  		[]v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, v1.PersistentVolumeReclaimRetain)
  1153  	_, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pv3, metav1.CreateOptions{})
  1154  	if err != nil {
  1155  		t.Errorf("Failed to create PersistentVolume: %v", err)
  1156  	}
  1157  	waitForPersistentVolumePhase(testClient, pv3.Name, watchPV, v1.VolumeAvailable)
  1158  
  1159  	pvc3 := createPVCWithNilStorageClass("pvc-3", ns.Name, "5G", []v1.PersistentVolumeAccessMode{v1.ReadWriteMany})
  1160  	if _, err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc3, metav1.CreateOptions{}); err != nil {
  1161  		t.Errorf("Failed to create PVC: %v", err)
  1162  	}
  1163  	t.Log("claim created")
  1164  
  1165  	waitForPersistentVolumeClaimPhase(testClient, pvc3.Name, ns.Name, watchPVC, v1.ClaimBound)
  1166  
  1167  	pvc, err := testClient.CoreV1().PersistentVolumeClaims(ns.Name).Get(context.TODO(), "pvc-3", metav1.GetOptions{})
  1168  	if err != nil {
  1169  		t.Fatalf("Unexpected error getting pv: %v", err)
  1170  	}
  1171  	if pvc.Spec.StorageClassName != nil {
  1172  		t.Errorf("claim %s should still have nil storage class because it bound to existing PV", pvc.Name)
  1173  	}
  1174  
  1175  	// Create another PV which should remain unbound.
  1176  	pvUnbound := createPVWithStorageClass("pv-unbound", "/tmp/bar", "5G", "",
  1177  		[]v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, v1.PersistentVolumeReclaimRetain)
  1178  	_, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pvUnbound, metav1.CreateOptions{})
  1179  	if err != nil {
  1180  		t.Errorf("Failed to create PersistentVolume: %v", err)
  1181  	}
  1182  
  1183  	waitForPersistentVolumePhase(testClient, pvUnbound.Name, watchPV, v1.VolumeAvailable)
  1184  
  1185  	pv, err = testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-unbound", metav1.GetOptions{})
  1186  	if err != nil {
  1187  		t.Fatalf("Unexpected error getting pv: %v", err)
  1188  	}
  1189  	if pv.Spec.ClaimRef != nil {
  1190  		t.Fatalf("PV %s shouldn't be bound", pvUnbound.Name)
  1191  	}
  1192  
  1193  	// Remove the PV to not interfere with next test.
  1194  	testClient.CoreV1().PersistentVolumes().Delete(context.TODO(), pvUnbound.Name, metav1.DeleteOptions{})
  1195  
  1196  	// 4. Test that PV with SC set to "" binds to PVC with SC set to "" while default SC exists.
  1197  	// This tests that the feature enablement and default SC presence does not break this binding.
  1198  	// If this breaks there would be no way to ever bind PVs with SC set to "".
  1199  	pvc4 := createPVC("pvc-4", ns.Name, "5G", []v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, "")
  1200  	_, err = testClient.CoreV1().PersistentVolumeClaims(ns.Name).Create(context.TODO(), pvc4, metav1.CreateOptions{})
  1201  	if err != nil {
  1202  		t.Errorf("Failed to create PersistentVolumeClaim: %v", err)
  1203  	}
  1204  
  1205  	pv4 := createPVWithStorageClass("pv-4", "/tmp/bar", "5G", "",
  1206  		[]v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, v1.PersistentVolumeReclaimRetain)
  1207  	_, err = testClient.CoreV1().PersistentVolumes().Create(context.TODO(), pv4, metav1.CreateOptions{})
  1208  	if err != nil {
  1209  		t.Errorf("Failed to create PersistentVolume: %v", err)
  1210  	}
  1211  
  1212  	// Wait until the controller pairs the volume.
  1213  	waitForPersistentVolumePhase(testClient, pv4.Name, watchPV, v1.VolumeBound)
  1214  	t.Log("volume bound")
  1215  	waitForPersistentVolumeClaimPhase(testClient, pvc4.Name, ns.Name, watchPVC, v1.ClaimBound)
  1216  	t.Log("claim bound")
  1217  
  1218  	pv, err = testClient.CoreV1().PersistentVolumes().Get(context.TODO(), "pv-4", metav1.GetOptions{})
  1219  	if err != nil {
  1220  		t.Fatalf("Unexpected error getting pv: %v", err)
  1221  	}
  1222  	if pv.Spec.ClaimRef == nil {
  1223  		t.Fatalf("PV %s with \"\" storage class should have been bound to PVC %s that also has \"\" storage class", pv4.Name, pvc4.Name)
  1224  	}
  1225  	if pv.Spec.ClaimRef.Name != pvc4.Name {
  1226  		t.Fatalf("Bind mismatch! Expected PV %s to bind to PVC %s but instead it bound to PVC %s", pv.Name, pvc4.Name, pv.Spec.ClaimRef.Name)
  1227  	}
  1228  }
  1229  
  1230  func waitForPersistentVolumePhase(client *clientset.Clientset, pvName string, w watch.Interface, phase v1.PersistentVolumePhase) {
  1231  	// Check if the volume is already in requested phase
  1232  	volume, err := client.CoreV1().PersistentVolumes().Get(context.TODO(), pvName, metav1.GetOptions{})
  1233  	if err == nil && volume.Status.Phase == phase {
  1234  		return
  1235  	}
  1236  
  1237  	// Wait for the phase
  1238  	for {
  1239  		event := <-w.ResultChan()
  1240  		volume, ok := event.Object.(*v1.PersistentVolume)
  1241  		if !ok {
  1242  			continue
  1243  		}
  1244  		if volume.Status.Phase == phase && volume.Name == pvName {
  1245  			klog.V(2).Infof("volume %q is %s", volume.Name, phase)
  1246  			break
  1247  		}
  1248  	}
  1249  }
  1250  
  1251  func waitForPersistentVolumeClaimPhase(client *clientset.Clientset, claimName, namespace string, w watch.Interface, phase v1.PersistentVolumeClaimPhase) {
  1252  	// Check if the claim is already in requested phase
  1253  	claim, err := client.CoreV1().PersistentVolumeClaims(namespace).Get(context.TODO(), claimName, metav1.GetOptions{})
  1254  	if err == nil && claim.Status.Phase == phase {
  1255  		return
  1256  	}
  1257  
  1258  	// Wait for the phase
  1259  	for {
  1260  		event := <-w.ResultChan()
  1261  		claim, ok := event.Object.(*v1.PersistentVolumeClaim)
  1262  		if !ok {
  1263  			continue
  1264  		}
  1265  		if claim.Status.Phase == phase && claim.Name == claimName {
  1266  			klog.V(2).Infof("claim %q is %s", claim.Name, phase)
  1267  			break
  1268  		}
  1269  	}
  1270  }
  1271  
  1272  func waitForAnyPersistentVolumePhase(w watch.Interface, phase v1.PersistentVolumePhase) {
  1273  	for {
  1274  		event := <-w.ResultChan()
  1275  		volume, ok := event.Object.(*v1.PersistentVolume)
  1276  		if !ok {
  1277  			continue
  1278  		}
  1279  		if volume.Status.Phase == phase {
  1280  			klog.V(2).Infof("volume %q is %s", volume.Name, phase)
  1281  			break
  1282  		}
  1283  	}
  1284  }
  1285  
  1286  func waitForAnyPersistentVolumeClaimPhase(w watch.Interface, phase v1.PersistentVolumeClaimPhase) {
  1287  	for {
  1288  		event := <-w.ResultChan()
  1289  		claim, ok := event.Object.(*v1.PersistentVolumeClaim)
  1290  		if !ok {
  1291  			continue
  1292  		}
  1293  		if claim.Status.Phase == phase {
  1294  			klog.V(2).Infof("claim %q is %s", claim.Name, phase)
  1295  			break
  1296  		}
  1297  	}
  1298  }
  1299  
  1300  func waitForPersistentVolumeClaimStorageClass(t *testing.T, claimName, scName string, w watch.Interface, duration time.Duration) (*v1.PersistentVolumeClaim, bool) {
  1301  	stopTimer := time.NewTimer(duration)
  1302  	defer stopTimer.Stop()
  1303  
  1304  	// Wait for the storage class
  1305  	for {
  1306  		select {
  1307  		case event := <-w.ResultChan():
  1308  			claim, ok := event.Object.(*v1.PersistentVolumeClaim)
  1309  			if ok {
  1310  				t.Logf("Watching claim %s", claim.Name)
  1311  			} else {
  1312  				t.Errorf("Watch closed unexpectedly")
  1313  			}
  1314  			if claim.Spec.StorageClassName == nil {
  1315  				t.Logf("Claim %v does not yet have expected storage class %v", claim.Name, scName)
  1316  				continue
  1317  			}
  1318  			if *claim.Spec.StorageClassName == scName && claim.Name == claimName {
  1319  				t.Logf("Claim %s now has expected storage class %s", claim.Name, *claim.Spec.StorageClassName)
  1320  				return claim, true
  1321  			}
  1322  		case <-stopTimer.C:
  1323  			return nil, false
  1324  		}
  1325  
  1326  	}
  1327  }
  1328  
  1329  func createClients(ctx context.Context, namespaceName string, t *testing.T, s *kubeapiservertesting.TestServer, syncPeriod time.Duration) (*clientset.Clientset, *persistentvolumecontroller.PersistentVolumeController, informers.SharedInformerFactory, watch.Interface, watch.Interface) {
  1330  	// Use higher QPS and Burst, there is a test for race conditions which
  1331  	// creates many objects and default values were too low.
  1332  	binderConfig := restclient.CopyConfig(s.ClientConfig)
  1333  	binderConfig.QPS = 1000000
  1334  	binderConfig.Burst = 1000000
  1335  	binderClient := clientset.NewForConfigOrDie(binderConfig)
  1336  	testConfig := restclient.CopyConfig(s.ClientConfig)
  1337  	testConfig.QPS = 1000000
  1338  	testConfig.Burst = 1000000
  1339  	testClient := clientset.NewForConfigOrDie(testConfig)
  1340  
  1341  	host := volumetest.NewFakeVolumeHost(t, "/tmp/fake", nil, nil)
  1342  	plugin := &volumetest.FakeVolumePlugin{
  1343  		PluginName:             provisionerPluginName,
  1344  		Host:                   host,
  1345  		Config:                 volume.VolumeConfig{},
  1346  		LastProvisionerOptions: volume.VolumeOptions{},
  1347  		NewAttacherCallCount:   0,
  1348  		NewDetacherCallCount:   0,
  1349  		Mounters:               nil,
  1350  		Unmounters:             nil,
  1351  		Attachers:              nil,
  1352  		Detachers:              nil,
  1353  	}
  1354  	plugins := []volume.VolumePlugin{plugin}
  1355  	informers := informers.NewSharedInformerFactory(testClient, getSyncPeriod(syncPeriod))
  1356  	ctrl, err := persistentvolumecontroller.NewController(
  1357  		ctx,
  1358  		persistentvolumecontroller.ControllerParameters{
  1359  			KubeClient:                binderClient,
  1360  			SyncPeriod:                getSyncPeriod(syncPeriod),
  1361  			VolumePlugins:             plugins,
  1362  			VolumeInformer:            informers.Core().V1().PersistentVolumes(),
  1363  			ClaimInformer:             informers.Core().V1().PersistentVolumeClaims(),
  1364  			ClassInformer:             informers.Storage().V1().StorageClasses(),
  1365  			PodInformer:               informers.Core().V1().Pods(),
  1366  			NodeInformer:              informers.Core().V1().Nodes(),
  1367  			EnableDynamicProvisioning: true,
  1368  		})
  1369  	if err != nil {
  1370  		t.Fatalf("Failed to construct PersistentVolumes: %v", err)
  1371  	}
  1372  
  1373  	watchPV, err := testClient.CoreV1().PersistentVolumes().Watch(context.TODO(), metav1.ListOptions{})
  1374  	if err != nil {
  1375  		t.Fatalf("Failed to watch PersistentVolumes: %v", err)
  1376  	}
  1377  	watchPVC, err := testClient.CoreV1().PersistentVolumeClaims(namespaceName).Watch(context.TODO(), metav1.ListOptions{})
  1378  	if err != nil {
  1379  		t.Fatalf("Failed to watch PersistentVolumeClaims: %v", err)
  1380  	}
  1381  
  1382  	return testClient, ctrl, informers, watchPV, watchPVC
  1383  }
  1384  
  1385  func createPV(name, path, cap string, mode []v1.PersistentVolumeAccessMode, reclaim v1.PersistentVolumeReclaimPolicy) *v1.PersistentVolume {
  1386  	return &v1.PersistentVolume{
  1387  		ObjectMeta: metav1.ObjectMeta{Name: name},
  1388  		Spec: v1.PersistentVolumeSpec{
  1389  			PersistentVolumeSource:        v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{Path: path}},
  1390  			Capacity:                      v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse(cap)},
  1391  			AccessModes:                   mode,
  1392  			PersistentVolumeReclaimPolicy: reclaim,
  1393  		},
  1394  	}
  1395  }
  1396  
  1397  func createPVWithStorageClass(name, path, cap, scName string, mode []v1.PersistentVolumeAccessMode, reclaim v1.PersistentVolumeReclaimPolicy) *v1.PersistentVolume {
  1398  	return &v1.PersistentVolume{
  1399  		ObjectMeta: metav1.ObjectMeta{Name: name},
  1400  		Spec: v1.PersistentVolumeSpec{
  1401  			PersistentVolumeSource:        v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{Path: path}},
  1402  			Capacity:                      v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse(cap)},
  1403  			AccessModes:                   mode,
  1404  			PersistentVolumeReclaimPolicy: reclaim,
  1405  			StorageClassName:              scName,
  1406  		},
  1407  	}
  1408  }
  1409  
  1410  func createPVC(name, namespace, cap string, mode []v1.PersistentVolumeAccessMode, class string) *v1.PersistentVolumeClaim {
  1411  	return &v1.PersistentVolumeClaim{
  1412  		ObjectMeta: metav1.ObjectMeta{
  1413  			Name:      name,
  1414  			Namespace: namespace,
  1415  		},
  1416  		Spec: v1.PersistentVolumeClaimSpec{
  1417  			Resources:        v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse(cap)}},
  1418  			AccessModes:      mode,
  1419  			StorageClassName: &class,
  1420  		},
  1421  	}
  1422  }
  1423  
  1424  func createPVCWithNilStorageClass(name, namespace, cap string, mode []v1.PersistentVolumeAccessMode) *v1.PersistentVolumeClaim {
  1425  	return &v1.PersistentVolumeClaim{
  1426  		ObjectMeta: metav1.ObjectMeta{
  1427  			Name:      name,
  1428  			Namespace: namespace,
  1429  		},
  1430  		Spec: v1.PersistentVolumeClaimSpec{
  1431  			Resources:   v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse(cap)}},
  1432  			AccessModes: mode,
  1433  		},
  1434  	}
  1435  }