...

Source file src/k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumebinding/assume_cache_test.go

Documentation: k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumebinding

     1  /*
     2  Copyright 2017 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 volumebinding
    18  
    19  import (
    20  	"fmt"
    21  	"testing"
    22  
    23  	v1 "k8s.io/api/core/v1"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/component-helpers/storage/volume"
    26  	"k8s.io/klog/v2/ktesting"
    27  )
    28  
    29  func verifyListPVs(t *testing.T, cache PVAssumeCache, expectedPVs map[string]*v1.PersistentVolume, storageClassName string) {
    30  	pvList := cache.ListPVs(storageClassName)
    31  	if len(pvList) != len(expectedPVs) {
    32  		t.Errorf("ListPVs() returned %v PVs, expected %v", len(pvList), len(expectedPVs))
    33  	}
    34  	for _, pv := range pvList {
    35  		expectedPV, ok := expectedPVs[pv.Name]
    36  		if !ok {
    37  			t.Errorf("ListPVs() returned unexpected PV %q", pv.Name)
    38  		}
    39  		if expectedPV != pv {
    40  			t.Errorf("ListPVs() returned PV %p, expected %p", pv, expectedPV)
    41  		}
    42  	}
    43  }
    44  
    45  func verifyPV(cache PVAssumeCache, name string, expectedPV *v1.PersistentVolume) error {
    46  	pv, err := cache.GetPV(name)
    47  	if err != nil {
    48  		return err
    49  	}
    50  	if pv != expectedPV {
    51  		return fmt.Errorf("GetPV() returned %p, expected %p", pv, expectedPV)
    52  	}
    53  	return nil
    54  }
    55  
    56  func TestAssumePV(t *testing.T) {
    57  	logger, _ := ktesting.NewTestContext(t)
    58  	scenarios := map[string]struct {
    59  		oldPV         *v1.PersistentVolume
    60  		newPV         *v1.PersistentVolume
    61  		shouldSucceed bool
    62  	}{
    63  		"success-same-version": {
    64  			oldPV:         makePV("pv1", "").withVersion("5").PersistentVolume,
    65  			newPV:         makePV("pv1", "").withVersion("5").PersistentVolume,
    66  			shouldSucceed: true,
    67  		},
    68  		"success-storageclass-same-version": {
    69  			oldPV:         makePV("pv1", "class1").withVersion("5").PersistentVolume,
    70  			newPV:         makePV("pv1", "class1").withVersion("5").PersistentVolume,
    71  			shouldSucceed: true,
    72  		},
    73  		"success-new-higher-version": {
    74  			oldPV:         makePV("pv1", "").withVersion("5").PersistentVolume,
    75  			newPV:         makePV("pv1", "").withVersion("6").PersistentVolume,
    76  			shouldSucceed: true,
    77  		},
    78  		"fail-old-not-found": {
    79  			oldPV:         makePV("pv2", "").withVersion("5").PersistentVolume,
    80  			newPV:         makePV("pv1", "").withVersion("5").PersistentVolume,
    81  			shouldSucceed: false,
    82  		},
    83  		"fail-new-lower-version": {
    84  			oldPV:         makePV("pv1", "").withVersion("5").PersistentVolume,
    85  			newPV:         makePV("pv1", "").withVersion("4").PersistentVolume,
    86  			shouldSucceed: false,
    87  		},
    88  		"fail-new-bad-version": {
    89  			oldPV:         makePV("pv1", "").withVersion("5").PersistentVolume,
    90  			newPV:         makePV("pv1", "").withVersion("a").PersistentVolume,
    91  			shouldSucceed: false,
    92  		},
    93  		"fail-old-bad-version": {
    94  			oldPV:         makePV("pv1", "").withVersion("a").PersistentVolume,
    95  			newPV:         makePV("pv1", "").withVersion("5").PersistentVolume,
    96  			shouldSucceed: false,
    97  		},
    98  	}
    99  
   100  	for name, scenario := range scenarios {
   101  		cache := NewPVAssumeCache(logger, nil)
   102  		internalCache, ok := cache.(*pvAssumeCache).AssumeCache.(*assumeCache)
   103  		if !ok {
   104  			t.Fatalf("Failed to get internal cache")
   105  		}
   106  
   107  		// Add oldPV to cache
   108  		internalCache.add(scenario.oldPV)
   109  		if err := verifyPV(cache, scenario.oldPV.Name, scenario.oldPV); err != nil {
   110  			t.Errorf("Failed to GetPV() after initial update: %v", err)
   111  			continue
   112  		}
   113  
   114  		// Assume newPV
   115  		err := cache.Assume(scenario.newPV)
   116  		if scenario.shouldSucceed && err != nil {
   117  			t.Errorf("Test %q failed: Assume() returned error %v", name, err)
   118  		}
   119  		if !scenario.shouldSucceed && err == nil {
   120  			t.Errorf("Test %q failed: Assume() returned success but expected error", name)
   121  		}
   122  
   123  		// Check that GetPV returns correct PV
   124  		expectedPV := scenario.newPV
   125  		if !scenario.shouldSucceed {
   126  			expectedPV = scenario.oldPV
   127  		}
   128  		if err := verifyPV(cache, scenario.oldPV.Name, expectedPV); err != nil {
   129  			t.Errorf("Failed to GetPV() after initial update: %v", err)
   130  		}
   131  	}
   132  }
   133  
   134  func TestRestorePV(t *testing.T) {
   135  	logger, _ := ktesting.NewTestContext(t)
   136  	cache := NewPVAssumeCache(logger, nil)
   137  	internalCache, ok := cache.(*pvAssumeCache).AssumeCache.(*assumeCache)
   138  	if !ok {
   139  		t.Fatalf("Failed to get internal cache")
   140  	}
   141  
   142  	oldPV := makePV("pv1", "").withVersion("5").PersistentVolume
   143  	newPV := makePV("pv1", "").withVersion("5").PersistentVolume
   144  
   145  	// Restore PV that doesn't exist
   146  	cache.Restore("nothing")
   147  
   148  	// Add oldPV to cache
   149  	internalCache.add(oldPV)
   150  	if err := verifyPV(cache, oldPV.Name, oldPV); err != nil {
   151  		t.Fatalf("Failed to GetPV() after initial update: %v", err)
   152  	}
   153  
   154  	// Restore PV
   155  	cache.Restore(oldPV.Name)
   156  	if err := verifyPV(cache, oldPV.Name, oldPV); err != nil {
   157  		t.Fatalf("Failed to GetPV() after initial restore: %v", err)
   158  	}
   159  
   160  	// Assume newPV
   161  	if err := cache.Assume(newPV); err != nil {
   162  		t.Fatalf("Assume() returned error %v", err)
   163  	}
   164  	if err := verifyPV(cache, oldPV.Name, newPV); err != nil {
   165  		t.Fatalf("Failed to GetPV() after Assume: %v", err)
   166  	}
   167  
   168  	// Restore PV
   169  	cache.Restore(oldPV.Name)
   170  	if err := verifyPV(cache, oldPV.Name, oldPV); err != nil {
   171  		t.Fatalf("Failed to GetPV() after restore: %v", err)
   172  	}
   173  }
   174  
   175  func TestBasicPVCache(t *testing.T) {
   176  	logger, _ := ktesting.NewTestContext(t)
   177  	cache := NewPVAssumeCache(logger, nil)
   178  	internalCache, ok := cache.(*pvAssumeCache).AssumeCache.(*assumeCache)
   179  	if !ok {
   180  		t.Fatalf("Failed to get internal cache")
   181  	}
   182  
   183  	// Get object that doesn't exist
   184  	pv, err := cache.GetPV("nothere")
   185  	if err == nil {
   186  		t.Errorf("GetPV() returned unexpected success")
   187  	}
   188  	if pv != nil {
   189  		t.Errorf("GetPV() returned unexpected PV %q", pv.Name)
   190  	}
   191  
   192  	// Add a bunch of PVs
   193  	pvs := map[string]*v1.PersistentVolume{}
   194  	for i := 0; i < 10; i++ {
   195  		pv := makePV(fmt.Sprintf("test-pv%v", i), "").withVersion("1").PersistentVolume
   196  		pvs[pv.Name] = pv
   197  		internalCache.add(pv)
   198  	}
   199  
   200  	// List them
   201  	verifyListPVs(t, cache, pvs, "")
   202  
   203  	// Update a PV
   204  	updatedPV := makePV("test-pv3", "").withVersion("2").PersistentVolume
   205  	pvs[updatedPV.Name] = updatedPV
   206  	internalCache.update(nil, updatedPV)
   207  
   208  	// List them
   209  	verifyListPVs(t, cache, pvs, "")
   210  
   211  	// Delete a PV
   212  	deletedPV := pvs["test-pv7"]
   213  	delete(pvs, deletedPV.Name)
   214  	internalCache.delete(deletedPV)
   215  
   216  	// List them
   217  	verifyListPVs(t, cache, pvs, "")
   218  }
   219  
   220  func TestPVCacheWithStorageClasses(t *testing.T) {
   221  	logger, _ := ktesting.NewTestContext(t)
   222  	cache := NewPVAssumeCache(logger, nil)
   223  	internalCache, ok := cache.(*pvAssumeCache).AssumeCache.(*assumeCache)
   224  	if !ok {
   225  		t.Fatalf("Failed to get internal cache")
   226  	}
   227  
   228  	// Add a bunch of PVs
   229  	pvs1 := map[string]*v1.PersistentVolume{}
   230  	for i := 0; i < 10; i++ {
   231  		pv := makePV(fmt.Sprintf("test-pv%v", i), "class1").withVersion("1").PersistentVolume
   232  		pvs1[pv.Name] = pv
   233  		internalCache.add(pv)
   234  	}
   235  
   236  	// Add a bunch of PVs
   237  	pvs2 := map[string]*v1.PersistentVolume{}
   238  	for i := 0; i < 10; i++ {
   239  		pv := makePV(fmt.Sprintf("test2-pv%v", i), "class2").withVersion("1").PersistentVolume
   240  		pvs2[pv.Name] = pv
   241  		internalCache.add(pv)
   242  	}
   243  
   244  	// List them
   245  	verifyListPVs(t, cache, pvs1, "class1")
   246  	verifyListPVs(t, cache, pvs2, "class2")
   247  
   248  	// Update a PV
   249  	updatedPV := makePV("test-pv3", "class1").withVersion("2").PersistentVolume
   250  	pvs1[updatedPV.Name] = updatedPV
   251  	internalCache.update(nil, updatedPV)
   252  
   253  	// List them
   254  	verifyListPVs(t, cache, pvs1, "class1")
   255  	verifyListPVs(t, cache, pvs2, "class2")
   256  
   257  	// Delete a PV
   258  	deletedPV := pvs1["test-pv7"]
   259  	delete(pvs1, deletedPV.Name)
   260  	internalCache.delete(deletedPV)
   261  
   262  	// List them
   263  	verifyListPVs(t, cache, pvs1, "class1")
   264  	verifyListPVs(t, cache, pvs2, "class2")
   265  }
   266  
   267  func TestAssumeUpdatePVCache(t *testing.T) {
   268  	logger, _ := ktesting.NewTestContext(t)
   269  	cache := NewPVAssumeCache(logger, nil)
   270  	internalCache, ok := cache.(*pvAssumeCache).AssumeCache.(*assumeCache)
   271  	if !ok {
   272  		t.Fatalf("Failed to get internal cache")
   273  	}
   274  
   275  	pvName := "test-pv0"
   276  
   277  	// Add a PV
   278  	pv := makePV(pvName, "").withVersion("1").PersistentVolume
   279  	internalCache.add(pv)
   280  	if err := verifyPV(cache, pvName, pv); err != nil {
   281  		t.Fatalf("failed to get PV: %v", err)
   282  	}
   283  
   284  	// Assume PV
   285  	newPV := pv.DeepCopy()
   286  	newPV.Spec.ClaimRef = &v1.ObjectReference{Name: "test-claim"}
   287  	if err := cache.Assume(newPV); err != nil {
   288  		t.Fatalf("failed to assume PV: %v", err)
   289  	}
   290  	if err := verifyPV(cache, pvName, newPV); err != nil {
   291  		t.Fatalf("failed to get PV after assume: %v", err)
   292  	}
   293  
   294  	// Add old PV
   295  	internalCache.add(pv)
   296  	if err := verifyPV(cache, pvName, newPV); err != nil {
   297  		t.Fatalf("failed to get PV after old PV added: %v", err)
   298  	}
   299  }
   300  
   301  func makeClaim(name, version, namespace string) *v1.PersistentVolumeClaim {
   302  	return &v1.PersistentVolumeClaim{
   303  		ObjectMeta: metav1.ObjectMeta{
   304  			Name:            name,
   305  			Namespace:       namespace,
   306  			ResourceVersion: version,
   307  			Annotations:     map[string]string{},
   308  		},
   309  	}
   310  }
   311  
   312  func verifyPVC(cache PVCAssumeCache, pvcKey string, expectedPVC *v1.PersistentVolumeClaim) error {
   313  	pvc, err := cache.GetPVC(pvcKey)
   314  	if err != nil {
   315  		return err
   316  	}
   317  	if pvc != expectedPVC {
   318  		return fmt.Errorf("GetPVC() returned %p, expected %p", pvc, expectedPVC)
   319  	}
   320  	return nil
   321  }
   322  
   323  func TestAssumePVC(t *testing.T) {
   324  	logger, _ := ktesting.NewTestContext(t)
   325  	scenarios := map[string]struct {
   326  		oldPVC        *v1.PersistentVolumeClaim
   327  		newPVC        *v1.PersistentVolumeClaim
   328  		shouldSucceed bool
   329  	}{
   330  		"success-same-version": {
   331  			oldPVC:        makeClaim("pvc1", "5", "ns1"),
   332  			newPVC:        makeClaim("pvc1", "5", "ns1"),
   333  			shouldSucceed: true,
   334  		},
   335  		"success-new-higher-version": {
   336  			oldPVC:        makeClaim("pvc1", "5", "ns1"),
   337  			newPVC:        makeClaim("pvc1", "6", "ns1"),
   338  			shouldSucceed: true,
   339  		},
   340  		"fail-old-not-found": {
   341  			oldPVC:        makeClaim("pvc2", "5", "ns1"),
   342  			newPVC:        makeClaim("pvc1", "5", "ns1"),
   343  			shouldSucceed: false,
   344  		},
   345  		"fail-new-lower-version": {
   346  			oldPVC:        makeClaim("pvc1", "5", "ns1"),
   347  			newPVC:        makeClaim("pvc1", "4", "ns1"),
   348  			shouldSucceed: false,
   349  		},
   350  		"fail-new-bad-version": {
   351  			oldPVC:        makeClaim("pvc1", "5", "ns1"),
   352  			newPVC:        makeClaim("pvc1", "a", "ns1"),
   353  			shouldSucceed: false,
   354  		},
   355  		"fail-old-bad-version": {
   356  			oldPVC:        makeClaim("pvc1", "a", "ns1"),
   357  			newPVC:        makeClaim("pvc1", "5", "ns1"),
   358  			shouldSucceed: false,
   359  		},
   360  	}
   361  
   362  	for name, scenario := range scenarios {
   363  		cache := NewPVCAssumeCache(logger, nil)
   364  		internalCache, ok := cache.(*pvcAssumeCache).AssumeCache.(*assumeCache)
   365  		if !ok {
   366  			t.Fatalf("Failed to get internal cache")
   367  		}
   368  
   369  		// Add oldPVC to cache
   370  		internalCache.add(scenario.oldPVC)
   371  		if err := verifyPVC(cache, getPVCName(scenario.oldPVC), scenario.oldPVC); err != nil {
   372  			t.Errorf("Failed to GetPVC() after initial update: %v", err)
   373  			continue
   374  		}
   375  
   376  		// Assume newPVC
   377  		err := cache.Assume(scenario.newPVC)
   378  		if scenario.shouldSucceed && err != nil {
   379  			t.Errorf("Test %q failed: Assume() returned error %v", name, err)
   380  		}
   381  		if !scenario.shouldSucceed && err == nil {
   382  			t.Errorf("Test %q failed: Assume() returned success but expected error", name)
   383  		}
   384  
   385  		// Check that GetPVC returns correct PVC
   386  		expectedPV := scenario.newPVC
   387  		if !scenario.shouldSucceed {
   388  			expectedPV = scenario.oldPVC
   389  		}
   390  		if err := verifyPVC(cache, getPVCName(scenario.oldPVC), expectedPV); err != nil {
   391  			t.Errorf("Failed to GetPVC() after initial update: %v", err)
   392  		}
   393  	}
   394  }
   395  
   396  func TestRestorePVC(t *testing.T) {
   397  	logger, _ := ktesting.NewTestContext(t)
   398  	cache := NewPVCAssumeCache(logger, nil)
   399  	internalCache, ok := cache.(*pvcAssumeCache).AssumeCache.(*assumeCache)
   400  	if !ok {
   401  		t.Fatalf("Failed to get internal cache")
   402  	}
   403  
   404  	oldPVC := makeClaim("pvc1", "5", "ns1")
   405  	newPVC := makeClaim("pvc1", "5", "ns1")
   406  
   407  	// Restore PVC that doesn't exist
   408  	cache.Restore("nothing")
   409  
   410  	// Add oldPVC to cache
   411  	internalCache.add(oldPVC)
   412  	if err := verifyPVC(cache, getPVCName(oldPVC), oldPVC); err != nil {
   413  		t.Fatalf("Failed to GetPVC() after initial update: %v", err)
   414  	}
   415  
   416  	// Restore PVC
   417  	cache.Restore(getPVCName(oldPVC))
   418  	if err := verifyPVC(cache, getPVCName(oldPVC), oldPVC); err != nil {
   419  		t.Fatalf("Failed to GetPVC() after initial restore: %v", err)
   420  	}
   421  
   422  	// Assume newPVC
   423  	if err := cache.Assume(newPVC); err != nil {
   424  		t.Fatalf("Assume() returned error %v", err)
   425  	}
   426  	if err := verifyPVC(cache, getPVCName(oldPVC), newPVC); err != nil {
   427  		t.Fatalf("Failed to GetPVC() after Assume: %v", err)
   428  	}
   429  
   430  	// Restore PVC
   431  	cache.Restore(getPVCName(oldPVC))
   432  	if err := verifyPVC(cache, getPVCName(oldPVC), oldPVC); err != nil {
   433  		t.Fatalf("Failed to GetPVC() after restore: %v", err)
   434  	}
   435  }
   436  
   437  func TestAssumeUpdatePVCCache(t *testing.T) {
   438  	logger, _ := ktesting.NewTestContext(t)
   439  	cache := NewPVCAssumeCache(logger, nil)
   440  	internalCache, ok := cache.(*pvcAssumeCache).AssumeCache.(*assumeCache)
   441  	if !ok {
   442  		t.Fatalf("Failed to get internal cache")
   443  	}
   444  
   445  	pvcName := "test-pvc0"
   446  	pvcNamespace := "test-ns"
   447  
   448  	// Add a PVC
   449  	pvc := makeClaim(pvcName, "1", pvcNamespace)
   450  	internalCache.add(pvc)
   451  	if err := verifyPVC(cache, getPVCName(pvc), pvc); err != nil {
   452  		t.Fatalf("failed to get PVC: %v", err)
   453  	}
   454  
   455  	// Assume PVC
   456  	newPVC := pvc.DeepCopy()
   457  	newPVC.Annotations[volume.AnnSelectedNode] = "test-node"
   458  	if err := cache.Assume(newPVC); err != nil {
   459  		t.Fatalf("failed to assume PVC: %v", err)
   460  	}
   461  	if err := verifyPVC(cache, getPVCName(pvc), newPVC); err != nil {
   462  		t.Fatalf("failed to get PVC after assume: %v", err)
   463  	}
   464  
   465  	// Add old PVC
   466  	internalCache.add(pvc)
   467  	if err := verifyPVC(cache, getPVCName(pvc), newPVC); err != nil {
   468  		t.Fatalf("failed to get PVC after old PVC added: %v", err)
   469  	}
   470  }
   471  

View as plain text