...

Source file src/k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim/strategy_test.go

Documentation: k8s.io/kubernetes/pkg/registry/core/persistentvolumeclaim

     1  /*
     2  Copyright 2015 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 persistentvolumeclaim
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"testing"
    23  
    24  	"github.com/google/go-cmp/cmp"
    25  	genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
    26  	utilfeature "k8s.io/apiserver/pkg/util/feature"
    27  	featuregatetesting "k8s.io/component-base/featuregate/testing"
    28  	apitesting "k8s.io/kubernetes/pkg/api/testing"
    29  	api "k8s.io/kubernetes/pkg/apis/core"
    30  	"k8s.io/kubernetes/pkg/features"
    31  
    32  	// ensure types are installed
    33  	_ "k8s.io/kubernetes/pkg/apis/core/install"
    34  )
    35  
    36  func TestSelectableFieldLabelConversions(t *testing.T) {
    37  	apitesting.TestSelectableFieldLabelConversionsOfKind(t,
    38  		"v1",
    39  		"PersistentVolumeClaim",
    40  		PersistentVolumeClaimToSelectableFields(&api.PersistentVolumeClaim{}),
    41  		map[string]string{"name": "metadata.name"},
    42  	)
    43  }
    44  
    45  func TestDropConditions(t *testing.T) {
    46  	ctx := genericapirequest.NewDefaultContext()
    47  	pvcWithConditions := func() *api.PersistentVolumeClaim {
    48  		return &api.PersistentVolumeClaim{
    49  			Status: api.PersistentVolumeClaimStatus{
    50  				Conditions: []api.PersistentVolumeClaimCondition{
    51  					{Type: api.PersistentVolumeClaimResizing, Status: api.ConditionTrue},
    52  				},
    53  			},
    54  		}
    55  	}
    56  	pvcWithoutConditions := func() *api.PersistentVolumeClaim {
    57  		return &api.PersistentVolumeClaim{
    58  			Status: api.PersistentVolumeClaimStatus{},
    59  		}
    60  	}
    61  
    62  	pvcInfo := []struct {
    63  		description   string
    64  		hasConditions bool
    65  		pvc           func() *api.PersistentVolumeClaim
    66  	}{
    67  		{
    68  			description:   "has Conditions",
    69  			hasConditions: true,
    70  			pvc:           pvcWithConditions,
    71  		},
    72  		{
    73  			description:   "does not have Conditions",
    74  			hasConditions: false,
    75  			pvc:           pvcWithoutConditions,
    76  		},
    77  	}
    78  
    79  	for _, oldPvcInfo := range pvcInfo {
    80  		for _, newPvcInfo := range pvcInfo {
    81  			oldPvcHasConditins, oldPvc := oldPvcInfo.hasConditions, oldPvcInfo.pvc()
    82  			newPvcHasConditions, newPvc := newPvcInfo.hasConditions, newPvcInfo.pvc()
    83  
    84  			t.Run(fmt.Sprintf("old pvc %s, new pvc %s", oldPvcInfo.description, newPvcInfo.description), func(t *testing.T) {
    85  				StatusStrategy.PrepareForUpdate(ctx, newPvc, oldPvc)
    86  
    87  				// old pvc should never be changed
    88  				if !reflect.DeepEqual(oldPvc, oldPvcInfo.pvc()) {
    89  					t.Errorf("old pvc changed: %v", cmp.Diff(oldPvc, oldPvcInfo.pvc()))
    90  				}
    91  
    92  				switch {
    93  				case oldPvcHasConditins || newPvcHasConditions:
    94  					// new pvc should not be changed if the feature is enabled, or if the old pvc had Conditions
    95  					if !reflect.DeepEqual(newPvc, newPvcInfo.pvc()) {
    96  						t.Errorf("new pvc changed: %v", cmp.Diff(newPvc, newPvcInfo.pvc()))
    97  					}
    98  				default:
    99  					// new pvc should not need to be changed
   100  					if !reflect.DeepEqual(newPvc, newPvcInfo.pvc()) {
   101  						t.Errorf("new pvc changed: %v", cmp.Diff(newPvc, newPvcInfo.pvc()))
   102  					}
   103  				}
   104  			})
   105  		}
   106  	}
   107  
   108  }
   109  
   110  var (
   111  	coreGroup    = ""
   112  	snapGroup    = "snapshot.storage.k8s.io"
   113  	genericGroup = "generic.storage.k8s.io"
   114  	pvcKind      = "PersistentVolumeClaim"
   115  	snapKind     = "VolumeSnapshot"
   116  	genericKind  = "Generic"
   117  	podKind      = "Pod"
   118  )
   119  
   120  func makeDataSource(apiGroup, kind, name string) *api.TypedLocalObjectReference {
   121  	return &api.TypedLocalObjectReference{
   122  		APIGroup: &apiGroup,
   123  		Kind:     kind,
   124  		Name:     name,
   125  	}
   126  
   127  }
   128  
   129  func makeDataSourceRef(apiGroup, kind, name string, namespace *string) *api.TypedObjectReference {
   130  	return &api.TypedObjectReference{
   131  		APIGroup:  &apiGroup,
   132  		Kind:      kind,
   133  		Name:      name,
   134  		Namespace: namespace,
   135  	}
   136  }
   137  
   138  func TestPrepareForCreate(t *testing.T) {
   139  	ctx := genericapirequest.NewDefaultContext()
   140  
   141  	ns := "ns1"
   142  	volumeDataSource := makeDataSource(coreGroup, pvcKind, "my-vol")
   143  	volumeDataSourceRef := makeDataSourceRef(coreGroup, pvcKind, "my-vol", nil)
   144  	xnsVolumeDataSourceRef := makeDataSourceRef(coreGroup, pvcKind, "my-vol", &ns)
   145  	snapshotDataSource := makeDataSource(snapGroup, snapKind, "my-snap")
   146  	snapshotDataSourceRef := makeDataSourceRef(snapGroup, snapKind, "my-snap", nil)
   147  	xnsSnapshotDataSourceRef := makeDataSourceRef(snapGroup, snapKind, "my-snap", &ns)
   148  	genericDataSource := makeDataSource(genericGroup, genericKind, "my-foo")
   149  	genericDataSourceRef := makeDataSourceRef(genericGroup, genericKind, "my-foo", nil)
   150  	xnsGenericDataSourceRef := makeDataSourceRef(genericGroup, genericKind, "my-foo", &ns)
   151  	coreDataSource := makeDataSource(coreGroup, podKind, "my-pod")
   152  	coreDataSourceRef := makeDataSourceRef(coreGroup, podKind, "my-pod", nil)
   153  	xnsCoreDataSourceRef := makeDataSourceRef(coreGroup, podKind, "my-pod", &ns)
   154  
   155  	var tests = map[string]struct {
   156  		anyEnabled    bool
   157  		xnsEnabled    bool
   158  		dataSource    *api.TypedLocalObjectReference
   159  		dataSourceRef *api.TypedObjectReference
   160  		want          *api.TypedLocalObjectReference
   161  		wantRef       *api.TypedObjectReference
   162  	}{
   163  		"any disabled with empty ds": {
   164  			want: nil,
   165  		},
   166  		"any disabled with volume ds": {
   167  			dataSource: volumeDataSource,
   168  			want:       volumeDataSource,
   169  		},
   170  		"any disabled with snapshot ds": {
   171  			dataSource: snapshotDataSource,
   172  			want:       snapshotDataSource,
   173  		},
   174  		"any disabled with generic ds": {
   175  			dataSource: genericDataSource,
   176  			want:       nil,
   177  		},
   178  		"any disabled with invalid ds": {
   179  			dataSource: coreDataSource,
   180  			want:       nil,
   181  		},
   182  		"any disabled with volume ds ref": {
   183  			dataSourceRef: volumeDataSourceRef,
   184  		},
   185  		"any disabled with snapshot ds ref": {
   186  			dataSourceRef: snapshotDataSourceRef,
   187  		},
   188  		"any disabled with generic ds ref": {
   189  			dataSourceRef: genericDataSourceRef,
   190  		},
   191  		"any disabled with invalid ds ref": {
   192  			dataSourceRef: coreDataSourceRef,
   193  		},
   194  		"any enabled with empty ds": {
   195  			anyEnabled: true,
   196  			want:       nil,
   197  		},
   198  		"any enabled with volume ds": {
   199  			dataSource: volumeDataSource,
   200  			anyEnabled: true,
   201  			want:       volumeDataSource,
   202  			wantRef:    volumeDataSourceRef,
   203  		},
   204  		"any enabled with snapshot ds": {
   205  			dataSource: snapshotDataSource,
   206  			anyEnabled: true,
   207  			want:       snapshotDataSource,
   208  			wantRef:    snapshotDataSourceRef,
   209  		},
   210  		"any enabled with generic ds": {
   211  			dataSource: genericDataSource,
   212  			anyEnabled: true,
   213  		},
   214  		"any enabled with invalid ds": {
   215  			dataSource: coreDataSource,
   216  			anyEnabled: true,
   217  		},
   218  		"any enabled with volume ds ref": {
   219  			dataSourceRef: volumeDataSourceRef,
   220  			anyEnabled:    true,
   221  			want:          volumeDataSource,
   222  			wantRef:       volumeDataSourceRef,
   223  		},
   224  		"any enabled with snapshot ds ref": {
   225  			dataSourceRef: snapshotDataSourceRef,
   226  			anyEnabled:    true,
   227  			want:          snapshotDataSource,
   228  			wantRef:       snapshotDataSourceRef,
   229  		},
   230  		"any enabled with generic ds ref": {
   231  			dataSourceRef: genericDataSourceRef,
   232  			anyEnabled:    true,
   233  			want:          genericDataSource,
   234  			wantRef:       genericDataSourceRef,
   235  		},
   236  		"any enabled with invalid ds ref": {
   237  			dataSourceRef: coreDataSourceRef,
   238  			anyEnabled:    true,
   239  			want:          coreDataSource,
   240  			wantRef:       coreDataSourceRef,
   241  		},
   242  		"any enabled with mismatched data sources": {
   243  			dataSource:    volumeDataSource,
   244  			dataSourceRef: snapshotDataSourceRef,
   245  			anyEnabled:    true,
   246  			want:          volumeDataSource,
   247  			wantRef:       snapshotDataSourceRef,
   248  		},
   249  		"both any and xns enabled with empty ds": {
   250  			anyEnabled: true,
   251  			xnsEnabled: true,
   252  			want:       nil,
   253  		},
   254  		"both any and xns enabled with volume ds": {
   255  			dataSource: volumeDataSource,
   256  			anyEnabled: true,
   257  			xnsEnabled: true,
   258  			want:       volumeDataSource,
   259  			wantRef:    volumeDataSourceRef,
   260  		},
   261  		"both any and xns enabled with snapshot ds": {
   262  			dataSource: snapshotDataSource,
   263  			anyEnabled: true,
   264  			xnsEnabled: true,
   265  			want:       snapshotDataSource,
   266  			wantRef:    snapshotDataSourceRef,
   267  		},
   268  		"both any and xns enabled with generic ds": {
   269  			dataSource: genericDataSource,
   270  			anyEnabled: true,
   271  			xnsEnabled: true,
   272  		},
   273  		"both any and xns enabled with invalid ds": {
   274  			dataSource: coreDataSource,
   275  			anyEnabled: true,
   276  			xnsEnabled: true,
   277  		},
   278  		"both any and xns enabled with volume ds ref": {
   279  			dataSourceRef: volumeDataSourceRef,
   280  			anyEnabled:    true,
   281  			xnsEnabled:    true,
   282  			want:          volumeDataSource,
   283  			wantRef:       volumeDataSourceRef,
   284  		},
   285  		"both any and xns enabled with snapshot ds ref": {
   286  			dataSourceRef: snapshotDataSourceRef,
   287  			anyEnabled:    true,
   288  			xnsEnabled:    true,
   289  			want:          snapshotDataSource,
   290  			wantRef:       snapshotDataSourceRef,
   291  		},
   292  		"both any and xns enabled with generic ds ref": {
   293  			dataSourceRef: genericDataSourceRef,
   294  			anyEnabled:    true,
   295  			xnsEnabled:    true,
   296  			want:          genericDataSource,
   297  			wantRef:       genericDataSourceRef,
   298  		},
   299  		"both any and xns enabled with invalid ds ref": {
   300  			dataSourceRef: coreDataSourceRef,
   301  			anyEnabled:    true,
   302  			xnsEnabled:    true,
   303  			want:          coreDataSource,
   304  			wantRef:       coreDataSourceRef,
   305  		},
   306  		"both any and xns enabled with mismatched data sources": {
   307  			dataSource:    volumeDataSource,
   308  			dataSourceRef: snapshotDataSourceRef,
   309  			anyEnabled:    true,
   310  			xnsEnabled:    true,
   311  			want:          volumeDataSource,
   312  			wantRef:       snapshotDataSourceRef,
   313  		},
   314  		"both any and xns enabled with volume xns ds ref": {
   315  			dataSourceRef: xnsVolumeDataSourceRef,
   316  			anyEnabled:    true,
   317  			xnsEnabled:    true,
   318  			wantRef:       xnsVolumeDataSourceRef,
   319  		},
   320  		"both any and xns enabled with snapshot xns ds ref": {
   321  			dataSourceRef: xnsSnapshotDataSourceRef,
   322  			anyEnabled:    true,
   323  			xnsEnabled:    true,
   324  			wantRef:       xnsSnapshotDataSourceRef,
   325  		},
   326  		"both any and xns enabled with generic xns ds ref": {
   327  			dataSourceRef: xnsGenericDataSourceRef,
   328  			anyEnabled:    true,
   329  			xnsEnabled:    true,
   330  			wantRef:       xnsGenericDataSourceRef,
   331  		},
   332  		"both any and xns enabled with invalid xns ds ref": {
   333  			dataSourceRef: xnsCoreDataSourceRef,
   334  			anyEnabled:    true,
   335  			xnsEnabled:    true,
   336  			wantRef:       xnsCoreDataSourceRef,
   337  		},
   338  		"only xns enabled with snapshot xns ds ref": {
   339  			dataSourceRef: xnsSnapshotDataSourceRef,
   340  			xnsEnabled:    true,
   341  		},
   342  	}
   343  
   344  	for testName, test := range tests {
   345  		t.Run(testName, func(t *testing.T) {
   346  			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AnyVolumeDataSource, test.anyEnabled)()
   347  			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CrossNamespaceVolumeDataSource, test.xnsEnabled)()
   348  			pvc := api.PersistentVolumeClaim{
   349  				Spec: api.PersistentVolumeClaimSpec{
   350  					DataSource:    test.dataSource,
   351  					DataSourceRef: test.dataSourceRef,
   352  				},
   353  			}
   354  
   355  			// Method under test
   356  			Strategy.PrepareForCreate(ctx, &pvc)
   357  
   358  			if !reflect.DeepEqual(pvc.Spec.DataSource, test.want) {
   359  				t.Errorf("data source does not match, test: %s, anyEnabled: %v, dataSource: %v, expected: %v",
   360  					testName, test.anyEnabled, test.dataSource, test.want)
   361  			}
   362  			if !reflect.DeepEqual(pvc.Spec.DataSourceRef, test.wantRef) {
   363  				t.Errorf("data source ref does not match, test: %s, anyEnabled: %v, dataSourceRef: %v, expected: %v",
   364  					testName, test.anyEnabled, test.dataSourceRef, test.wantRef)
   365  			}
   366  		})
   367  	}
   368  }
   369  

View as plain text