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)
		}
	}
}