mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-04 07:49:35 +00:00 
			
		
		
		
	Merge pull request #26894 from jsafrane/fix-integration-pv-flake
Automatic merge from submit-queue Fix integration pv flakes There are two fixes in this PR: - run tests in separarate functions and use objects with different names, otherwise events from the beginning of the function are caught later when we watch for events of a different PV/PVC - don't set PV.Spec.ClaimRef.UID of pre-bound PVs. PVs with UID set are considered as bound and they are deleted/recycled when appropriate PVC does not exists yet. Fixes #26730 and probably also ~~#26894~~ #26256
This commit is contained in:
		@@ -103,6 +103,7 @@ func testSleep() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestPersistentVolumeRecycler(t *testing.T) {
 | 
					func TestPersistentVolumeRecycler(t *testing.T) {
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeRecycler started")
 | 
				
			||||||
	_, s := framework.RunAMaster(t)
 | 
						_, s := framework.RunAMaster(t)
 | 
				
			||||||
	defer s.Close()
 | 
						defer s.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -115,58 +116,80 @@ func TestPersistentVolumeRecycler(t *testing.T) {
 | 
				
			|||||||
	defer ctrl.Stop()
 | 
						defer ctrl.Stop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// This PV will be claimed, released, and recycled.
 | 
						// This PV will be claimed, released, and recycled.
 | 
				
			||||||
	pv := createPV("fake-pv", "/tmp/foo", "10G", []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, api.PersistentVolumeReclaimRecycle)
 | 
						pv := createPV("fake-pv-recycler", "/tmp/foo", "10G", []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, api.PersistentVolumeReclaimRecycle)
 | 
				
			||||||
 | 
						pvc := createPVC("fake-pvc-recycler", "5G", []api.PersistentVolumeAccessMode{api.ReadWriteOnce})
 | 
				
			||||||
	pvc := createPVC("fake-pvc", "5G", []api.PersistentVolumeAccessMode{api.ReadWriteOnce})
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err := testClient.PersistentVolumes().Create(pv)
 | 
						_, err := testClient.PersistentVolumes().Create(pv)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Errorf("Failed to create PersistentVolume: %v", err)
 | 
							t.Errorf("Failed to create PersistentVolume: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeRecycler pvc created")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = testClient.PersistentVolumeClaims(api.NamespaceDefault).Create(pvc)
 | 
						_, err = testClient.PersistentVolumeClaims(api.NamespaceDefault).Create(pvc)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Errorf("Failed to create PersistentVolumeClaim: %v", err)
 | 
							t.Errorf("Failed to create PersistentVolumeClaim: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeRecycler pvc created")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// wait until the controller pairs the volume and claim
 | 
						// wait until the controller pairs the volume and claim
 | 
				
			||||||
	waitForPersistentVolumePhase(testClient, pv.Name, watchPV, api.VolumeBound)
 | 
						waitForPersistentVolumePhase(testClient, pv.Name, watchPV, api.VolumeBound)
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeRecycler pv bound")
 | 
				
			||||||
	waitForPersistentVolumeClaimPhase(testClient, pvc.Name, watchPVC, api.ClaimBound)
 | 
						waitForPersistentVolumeClaimPhase(testClient, pvc.Name, watchPVC, api.ClaimBound)
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeRecycler pvc bound")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// deleting a claim releases the volume, after which it can be recycled
 | 
						// deleting a claim releases the volume, after which it can be recycled
 | 
				
			||||||
	if err := testClient.PersistentVolumeClaims(api.NamespaceDefault).Delete(pvc.Name, nil); err != nil {
 | 
						if err := testClient.PersistentVolumeClaims(api.NamespaceDefault).Delete(pvc.Name, nil); err != nil {
 | 
				
			||||||
		t.Errorf("error deleting claim %s", pvc.Name)
 | 
							t.Errorf("error deleting claim %s", pvc.Name)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeRecycler pvc deleted")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	waitForPersistentVolumePhase(testClient, pv.Name, watchPV, api.VolumeReleased)
 | 
						waitForPersistentVolumePhase(testClient, pv.Name, watchPV, api.VolumeReleased)
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeRecycler pv released")
 | 
				
			||||||
	waitForPersistentVolumePhase(testClient, pv.Name, watchPV, api.VolumeAvailable)
 | 
						waitForPersistentVolumePhase(testClient, pv.Name, watchPV, api.VolumeAvailable)
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeRecycler pv available")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// end of Recycler test.
 | 
					}
 | 
				
			||||||
	// Deleter test begins now.
 | 
					
 | 
				
			||||||
	// tests are serial because running masters concurrently that delete keys may cause similar tests to time out
 | 
					func TestPersistentVolumeDeleter(t *testing.T) {
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeDeleter started")
 | 
				
			||||||
 | 
						_, s := framework.RunAMaster(t)
 | 
				
			||||||
 | 
						defer s.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	deleteAllEtcdKeys()
 | 
						deleteAllEtcdKeys()
 | 
				
			||||||
 | 
						testClient, ctrl, watchPV, watchPVC := createClients(t, s)
 | 
				
			||||||
 | 
						defer watchPV.Stop()
 | 
				
			||||||
 | 
						defer watchPVC.Stop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// change the reclamation policy of the PV for the next test
 | 
						ctrl.Run()
 | 
				
			||||||
	pv.Spec.PersistentVolumeReclaimPolicy = api.PersistentVolumeReclaimDelete
 | 
						defer ctrl.Stop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = testClient.PersistentVolumes().Create(pv)
 | 
						// This PV will be claimed, released, and deleted.
 | 
				
			||||||
 | 
						pv := createPV("fake-pv-deleter", "/tmp/foo", "10G", []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, api.PersistentVolumeReclaimDelete)
 | 
				
			||||||
 | 
						pvc := createPVC("fake-pvc-deleter", "5G", []api.PersistentVolumeAccessMode{api.ReadWriteOnce})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := testClient.PersistentVolumes().Create(pv)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Errorf("Failed to create PersistentVolume: %v", err)
 | 
							t.Errorf("Failed to create PersistentVolume: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeDeleter pv created")
 | 
				
			||||||
	_, err = testClient.PersistentVolumeClaims(api.NamespaceDefault).Create(pvc)
 | 
						_, err = testClient.PersistentVolumeClaims(api.NamespaceDefault).Create(pvc)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Errorf("Failed to create PersistentVolumeClaim: %v", err)
 | 
							t.Errorf("Failed to create PersistentVolumeClaim: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeDeleter pvc created")
 | 
				
			||||||
	waitForPersistentVolumePhase(testClient, pv.Name, watchPV, api.VolumeBound)
 | 
						waitForPersistentVolumePhase(testClient, pv.Name, watchPV, api.VolumeBound)
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeDeleter pv bound")
 | 
				
			||||||
	waitForPersistentVolumeClaimPhase(testClient, pvc.Name, watchPVC, api.ClaimBound)
 | 
						waitForPersistentVolumeClaimPhase(testClient, pvc.Name, watchPVC, api.ClaimBound)
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeDeleter pvc bound")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// deleting a claim releases the volume, after which it can be recycled
 | 
						// deleting a claim releases the volume, after which it can be recycled
 | 
				
			||||||
	if err := testClient.PersistentVolumeClaims(api.NamespaceDefault).Delete(pvc.Name, nil); err != nil {
 | 
						if err := testClient.PersistentVolumeClaims(api.NamespaceDefault).Delete(pvc.Name, nil); err != nil {
 | 
				
			||||||
		t.Errorf("error deleting claim %s", pvc.Name)
 | 
							t.Errorf("error deleting claim %s", pvc.Name)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeDeleter pvc deleted")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	waitForPersistentVolumePhase(testClient, pv.Name, watchPV, api.VolumeReleased)
 | 
						waitForPersistentVolumePhase(testClient, pv.Name, watchPV, api.VolumeReleased)
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeDeleter pv released")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		event := <-watchPV.ResultChan()
 | 
							event := <-watchPV.ResultChan()
 | 
				
			||||||
@@ -174,9 +197,27 @@ func TestPersistentVolumeRecycler(t *testing.T) {
 | 
				
			|||||||
			break
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeDeleter pv deleted")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestPersistentVolumeBindRace(t *testing.T) {
 | 
				
			||||||
 | 
						// Test a race binding many claims to a PV that is pre-bound to a specific
 | 
				
			||||||
 | 
						// PVC. Only this specific PVC should get bound.
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeBindRace started")
 | 
				
			||||||
 | 
						_, s := framework.RunAMaster(t)
 | 
				
			||||||
 | 
						defer s.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// test the race between claims and volumes.  ensure only a volume only binds to a single claim.
 | 
					 | 
				
			||||||
	deleteAllEtcdKeys()
 | 
						deleteAllEtcdKeys()
 | 
				
			||||||
 | 
						testClient, ctrl, watchPV, watchPVC := createClients(t, s)
 | 
				
			||||||
 | 
						defer watchPV.Stop()
 | 
				
			||||||
 | 
						defer watchPVC.Stop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctrl.Run()
 | 
				
			||||||
 | 
						defer ctrl.Stop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pv := createPV("fake-pv-race", "/tmp/foo", "10G", []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, api.PersistentVolumeReclaimRetain)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pvc := createPVC("fake-pvc-race", "5G", []api.PersistentVolumeAccessMode{api.ReadWriteOnce})
 | 
				
			||||||
	counter := 0
 | 
						counter := 0
 | 
				
			||||||
	maxClaims := 100
 | 
						maxClaims := 100
 | 
				
			||||||
	claims := []*api.PersistentVolumeClaim{}
 | 
						claims := []*api.PersistentVolumeClaim{}
 | 
				
			||||||
@@ -184,13 +225,14 @@ func TestPersistentVolumeRecycler(t *testing.T) {
 | 
				
			|||||||
		counter += 1
 | 
							counter += 1
 | 
				
			||||||
		clone, _ := conversion.NewCloner().DeepCopy(pvc)
 | 
							clone, _ := conversion.NewCloner().DeepCopy(pvc)
 | 
				
			||||||
		newPvc, _ := clone.(*api.PersistentVolumeClaim)
 | 
							newPvc, _ := clone.(*api.PersistentVolumeClaim)
 | 
				
			||||||
		newPvc.ObjectMeta = api.ObjectMeta{Name: fmt.Sprintf("fake-pvc-%d", counter)}
 | 
							newPvc.ObjectMeta = api.ObjectMeta{Name: fmt.Sprintf("fake-pvc-race-%d", counter)}
 | 
				
			||||||
		claim, err := testClient.PersistentVolumeClaims(api.NamespaceDefault).Create(newPvc)
 | 
							claim, err := testClient.PersistentVolumeClaims(api.NamespaceDefault).Create(newPvc)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			t.Fatal("Error creating newPvc: %v", err)
 | 
								t.Fatal("Error creating newPvc: %v", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		claims = append(claims, claim)
 | 
							claims = append(claims, claim)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeBindRace claims created")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// putting a bind manually on a pv should only match the claim it is bound to
 | 
						// putting a bind manually on a pv should only match the claim it is bound to
 | 
				
			||||||
	rand.Seed(time.Now().Unix())
 | 
						rand.Seed(time.Now().Unix())
 | 
				
			||||||
@@ -200,14 +242,18 @@ func TestPersistentVolumeRecycler(t *testing.T) {
 | 
				
			|||||||
		t.Fatalf("Unexpected error getting claimRef: %v", err)
 | 
							t.Fatalf("Unexpected error getting claimRef: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	pv.Spec.ClaimRef = claimRef
 | 
						pv.Spec.ClaimRef = claimRef
 | 
				
			||||||
 | 
						pv.Spec.ClaimRef.UID = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pv, err = testClient.PersistentVolumes().Create(pv)
 | 
						pv, err = testClient.PersistentVolumes().Create(pv)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("Unexpected error creating pv: %v", err)
 | 
							t.Fatalf("Unexpected error creating pv: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeBindRace pv created, pre-bound to %s", claim.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	waitForPersistentVolumePhase(testClient, pv.Name, watchPV, api.VolumeBound)
 | 
						waitForPersistentVolumePhase(testClient, pv.Name, watchPV, api.VolumeBound)
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeBindRace pv bound")
 | 
				
			||||||
	waitForAnyPersistentVolumeClaimPhase(watchPVC, api.ClaimBound)
 | 
						waitForAnyPersistentVolumeClaimPhase(watchPVC, api.ClaimBound)
 | 
				
			||||||
 | 
						glog.V(2).Infof("TestPersistentVolumeBindRace pvc bound")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pv, err = testClient.PersistentVolumes().Get(pv.Name)
 | 
						pv, err = testClient.PersistentVolumes().Get(pv.Name)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user