func TestPersistentVolumeDeleter(t *testing.T) { _, s := runAMaster(t) defer s.Close() deleteAllEtcdKeys() client := client.NewOrDie(&client.Config{Host: s.URL, Version: testapi.Default.Version()}) binder := volumeclaimbinder.NewPersistentVolumeClaimBinder(client, 1*time.Second) binder.Run() defer binder.Stop() recycler, _ := volumeclaimbinder.NewPersistentVolumeRecycler(client, 1*time.Second, []volume.VolumePlugin{&volume.FakeVolumePlugin{"plugin-name", volume.NewFakeVolumeHost("/tmp/fake", nil, nil)}}) recycler.Run() defer recycler.Stop() // This PV will be claimed, released, and recycled. pv := &api.PersistentVolume{ ObjectMeta: api.ObjectMeta{Name: "fake-pv"}, Spec: api.PersistentVolumeSpec{ PersistentVolumeSource: api.PersistentVolumeSource{HostPath: &api.HostPathVolumeSource{Path: "/tmp/foo"}}, Capacity: api.ResourceList{api.ResourceName(api.ResourceStorage): resource.MustParse("10G")}, AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimDelete, }, } pvc := &api.PersistentVolumeClaim{ ObjectMeta: api.ObjectMeta{Name: "fake-pvc"}, Spec: api.PersistentVolumeClaimSpec{ Resources: api.ResourceRequirements{Requests: api.ResourceList{api.ResourceName(api.ResourceStorage): resource.MustParse("5G")}}, AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, }, } w, _ := client.PersistentVolumes().Watch(labels.Everything(), fields.Everything(), "0") defer w.Stop() _, _ = client.PersistentVolumes().Create(pv) _, _ = client.PersistentVolumeClaims(api.NamespaceDefault).Create(pvc) // wait until the binder pairs the volume and claim waitForPersistentVolumePhase(w, api.VolumeBound) // deleting a claim releases the volume, after which it can be recycled if err := client.PersistentVolumeClaims(api.NamespaceDefault).Delete(pvc.Name); err != nil { t.Errorf("error deleting claim %s", pvc.Name) } waitForPersistentVolumePhase(w, api.VolumeReleased) for { event := <-w.ResultChan() if event.Type == watch.Deleted { break } } }
func TestPersistentVolumeClaimBinder(t *testing.T) { _, s := runAMaster(t) defer s.Close() deleteAllEtcdKeys() client := client.NewOrDie(&client.Config{Host: s.URL, Version: testapi.Version()}) binder := volumeclaimbinder.NewPersistentVolumeClaimBinder(client, 1*time.Second) binder.Run() defer binder.Stop() for _, volume := range createTestVolumes() { _, err := client.PersistentVolumes().Create(volume) if err != nil { t.Fatalf("Unexpected error: %v", err) } } volumes, err := client.PersistentVolumes().List(labels.Everything(), fields.Everything()) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(volumes.Items) != 2 { t.Errorf("expected 2 PVs, got %#v", len(volumes.Items)) } for _, claim := range createTestClaims() { _, err := client.PersistentVolumeClaims(api.NamespaceDefault).Create(claim) if err != nil { t.Fatalf("Unexpected error: %v", err) } } claims, err := client.PersistentVolumeClaims(api.NamespaceDefault).List(labels.Everything(), fields.Everything()) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(claims.Items) != 3 { t.Errorf("expected 3 PVCs, got %#v", len(claims.Items)) } // the binder will eventually catch up and set status on Claims watch, err := client.PersistentVolumeClaims(api.NamespaceDefault).Watch(labels.Everything(), fields.Everything(), "0") if err != nil { t.Fatalf("Couldn't subscribe to PersistentVolumeClaims: %v", err) } defer watch.Stop() boundCount := 0 expectedBoundCount := 2 for { event := <-watch.ResultChan() claim := event.Object.(*api.PersistentVolumeClaim) if claim.Spec.VolumeName != "" { boundCount++ } if boundCount == expectedBoundCount { break } } for _, claim := range createTestClaims() { claim, err := client.PersistentVolumeClaims(api.NamespaceDefault).Get(claim.Name) if err != nil { t.Fatalf("Unexpected error: %v", err) } if (claim.Name == "claim01" || claim.Name == "claim02") && claim.Spec.VolumeName == "" { t.Errorf("Expected claim to be bound: %+v", claim) } if claim.Name == "claim03" && claim.Spec.VolumeName != "" { t.Errorf("Expected claim03 to be unbound: %v", claim) } } }