2022-03-29 11:49:46 +08:00
/ *
2022-05-25 11:41:51 +08:00
Copyright 2018 The Kubernetes Authors .
2022-03-29 11:49:46 +08:00
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
package persistentvolume
import (
"reflect"
"testing"
"github.com/google/go-cmp/cmp"
2022-03-07 18:17:28 +08:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"
2022-03-29 11:49:46 +08:00
utilfeature "k8s.io/apiserver/pkg/util/feature"
featuregatetesting "k8s.io/component-base/featuregate/testing"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/features"
2023-10-31 10:12:02 +08:00
"k8s.io/utils/ptr"
2022-03-29 11:49:46 +08:00
)
func TestDropDisabledFields ( t * testing . T ) {
secretRef := & api . SecretReference {
Name : "expansion-secret" ,
Namespace : "default" ,
}
2023-10-31 10:12:02 +08:00
vacName := ptr . To ( "vac" )
2022-03-29 11:49:46 +08:00
tests := map [ string ] struct {
oldSpec * api . PersistentVolumeSpec
newSpec * api . PersistentVolumeSpec
expectOldSpec * api . PersistentVolumeSpec
expectNewSpec * api . PersistentVolumeSpec
csiExpansionEnabled bool
2023-10-31 10:12:02 +08:00
vacEnabled bool
2022-03-29 11:49:46 +08:00
} {
"disabled csi expansion clears secrets" : {
csiExpansionEnabled : false ,
newSpec : specWithCSISecrets ( secretRef ) ,
expectNewSpec : specWithCSISecrets ( nil ) ,
oldSpec : nil ,
expectOldSpec : nil ,
} ,
"enabled csi expansion preserve secrets" : {
csiExpansionEnabled : true ,
newSpec : specWithCSISecrets ( secretRef ) ,
expectNewSpec : specWithCSISecrets ( secretRef ) ,
oldSpec : nil ,
expectOldSpec : nil ,
} ,
"enabled csi expansion preserve secrets when both old and new have it" : {
csiExpansionEnabled : true ,
newSpec : specWithCSISecrets ( secretRef ) ,
expectNewSpec : specWithCSISecrets ( secretRef ) ,
oldSpec : specWithCSISecrets ( secretRef ) ,
expectOldSpec : specWithCSISecrets ( secretRef ) ,
} ,
"disabled csi expansion old pv had secrets" : {
csiExpansionEnabled : false ,
newSpec : specWithCSISecrets ( secretRef ) ,
expectNewSpec : specWithCSISecrets ( secretRef ) ,
oldSpec : specWithCSISecrets ( secretRef ) ,
expectOldSpec : specWithCSISecrets ( secretRef ) ,
} ,
"enabled csi expansion preserves secrets when old pv did not had secrets" : {
csiExpansionEnabled : true ,
newSpec : specWithCSISecrets ( secretRef ) ,
expectNewSpec : specWithCSISecrets ( secretRef ) ,
oldSpec : specWithCSISecrets ( nil ) ,
expectOldSpec : specWithCSISecrets ( nil ) ,
} ,
2022-11-22 00:18:24 +08:00
"disabled csi expansion neither new pv nor old pv had secrets" : {
csiExpansionEnabled : false ,
newSpec : specWithCSISecrets ( nil ) ,
expectNewSpec : specWithCSISecrets ( nil ) ,
oldSpec : specWithCSISecrets ( nil ) ,
expectOldSpec : specWithCSISecrets ( nil ) ,
} ,
2023-10-31 10:12:02 +08:00
"disabled vac clears volume attributes class name" : {
vacEnabled : false ,
newSpec : specWithVACName ( vacName ) ,
expectNewSpec : specWithVACName ( nil ) ,
oldSpec : nil ,
expectOldSpec : nil ,
} ,
"enabled vac preserve volume attributes class name" : {
vacEnabled : true ,
newSpec : specWithVACName ( vacName ) ,
expectNewSpec : specWithVACName ( vacName ) ,
oldSpec : nil ,
expectOldSpec : nil ,
} ,
"enabled vac preserve volume attributes class name when both old and new have it" : {
vacEnabled : true ,
newSpec : specWithVACName ( vacName ) ,
expectNewSpec : specWithVACName ( vacName ) ,
oldSpec : specWithVACName ( vacName ) ,
expectOldSpec : specWithVACName ( vacName ) ,
} ,
"disabled vac old pv had volume attributes class name" : {
vacEnabled : false ,
newSpec : specWithVACName ( vacName ) ,
expectNewSpec : specWithVACName ( vacName ) ,
oldSpec : specWithVACName ( vacName ) ,
expectOldSpec : specWithVACName ( vacName ) ,
} ,
"enabled vac preserves volume attributes class name when old pv did not had it" : {
vacEnabled : true ,
newSpec : specWithVACName ( vacName ) ,
expectNewSpec : specWithVACName ( vacName ) ,
oldSpec : specWithVACName ( nil ) ,
expectOldSpec : specWithVACName ( nil ) ,
} ,
"disabled vac neither new pv nor old pv had volume attributes class name" : {
vacEnabled : false ,
newSpec : specWithVACName ( nil ) ,
expectNewSpec : specWithVACName ( nil ) ,
oldSpec : specWithVACName ( nil ) ,
expectOldSpec : specWithVACName ( nil ) ,
} ,
2022-03-29 11:49:46 +08:00
}
for name , tc := range tests {
t . Run ( name , func ( t * testing . T ) {
defer featuregatetesting . SetFeatureGateDuringTest ( t , utilfeature . DefaultFeatureGate , features . CSINodeExpandSecret , tc . csiExpansionEnabled ) ( )
2023-10-31 10:12:02 +08:00
defer featuregatetesting . SetFeatureGateDuringTest ( t , utilfeature . DefaultFeatureGate , features . VolumeAttributesClass , tc . vacEnabled ) ( )
2022-03-29 11:49:46 +08:00
2023-03-10 21:03:41 +08:00
DropDisabledSpecFields ( tc . newSpec , tc . oldSpec )
2022-03-29 11:49:46 +08:00
if ! reflect . DeepEqual ( tc . newSpec , tc . expectNewSpec ) {
t . Error ( cmp . Diff ( tc . newSpec , tc . expectNewSpec ) )
}
if ! reflect . DeepEqual ( tc . oldSpec , tc . expectOldSpec ) {
t . Error ( cmp . Diff ( tc . oldSpec , tc . expectOldSpec ) )
}
} )
}
}
func specWithCSISecrets ( secret * api . SecretReference ) * api . PersistentVolumeSpec {
pvSpec := & api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
CSI : & api . CSIPersistentVolumeSource {
Driver : "com.google.gcepd" ,
VolumeHandle : "foobar" ,
} ,
} ,
}
if secret != nil {
pvSpec . CSI . NodeExpandSecretRef = secret
}
return pvSpec
}
2022-03-07 18:17:28 +08:00
2023-10-31 10:12:02 +08:00
func specWithVACName ( vacName * string ) * api . PersistentVolumeSpec {
pvSpec := & api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
CSI : & api . CSIPersistentVolumeSource {
Driver : "com.google.gcepd" ,
VolumeHandle : "foobar" ,
} ,
} ,
}
if vacName != nil {
pvSpec . VolumeAttributesClassName = vacName
}
return pvSpec
}
2022-03-07 18:17:28 +08:00
func TestWarnings ( t * testing . T ) {
testcases := [ ] struct {
name string
template * api . PersistentVolume
expected [ ] string
} {
{
name : "null" ,
template : nil ,
expected : nil ,
} ,
{
name : "no warning" ,
template : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta {
Name : "foo" ,
} ,
Status : api . PersistentVolumeStatus {
Phase : api . VolumeBound ,
} ,
} ,
expected : nil ,
} ,
{
name : "warning" ,
template : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta {
Name : "foo" ,
2023-03-31 17:33:41 +08:00
Annotations : map [ string ] string {
api . BetaStorageClassAnnotation : "" ,
} ,
2022-03-07 18:17:28 +08:00
} ,
Spec : api . PersistentVolumeSpec {
NodeAffinity : & api . VolumeNodeAffinity {
Required : & api . NodeSelector {
NodeSelectorTerms : [ ] api . NodeSelectorTerm {
{
MatchExpressions : [ ] api . NodeSelectorRequirement {
{
Key : "beta.kubernetes.io/os" ,
Operator : "Equal" ,
Values : [ ] string { "windows" } ,
} ,
} ,
} ,
} ,
} ,
} ,
} ,
Status : api . PersistentVolumeStatus {
Phase : api . VolumeBound ,
} ,
} ,
expected : [ ] string {
2023-03-31 17:33:41 +08:00
` metadata.annotations[volume.beta.kubernetes.io/storage-class]: deprecated since v1.8; use "storageClassName" attribute instead ` ,
2022-03-07 18:17:28 +08:00
` spec.nodeAffinity.required.nodeSelectorTerms[0].matchExpressions[0].key: beta.kubernetes.io/os is deprecated since v1.14; use "kubernetes.io/os" instead ` ,
} ,
} ,
2023-05-04 17:41:14 +08:00
{
name : "PV CephFS deprecation warning" ,
template : & api . PersistentVolume {
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
CephFS : & api . CephFSPersistentVolumeSource {
Monitors : nil ,
Path : "" ,
User : "" ,
SecretFile : "" ,
SecretRef : nil ,
ReadOnly : false ,
} ,
} ,
} ,
} ,
expected : [ ] string {
2023-06-16 22:17:03 +08:00
` spec.cephfs: deprecated in v1.28, non-functional in v1.31+ ` ,
2023-05-04 17:41:14 +08:00
} ,
} ,
2023-06-08 16:06:53 +08:00
{
name : "PV PhotonPersistentDisk deprecation warning" ,
template : & api . PersistentVolume {
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
PhotonPersistentDisk : & api . PhotonPersistentDiskVolumeSource {
PdID : "" ,
FSType : "" ,
} ,
} ,
} ,
} ,
expected : [ ] string {
2023-06-16 22:17:03 +08:00
` spec.photonPersistentDisk: deprecated in v1.11, non-functional in v1.16+ ` ,
2023-06-08 16:06:53 +08:00
} ,
} ,
2023-06-16 22:15:36 +08:00
{
name : "PV RBD deprecation warning" ,
template : & api . PersistentVolume {
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
RBD : & api . RBDPersistentVolumeSource {
CephMonitors : nil ,
RBDImage : "" ,
FSType : "" ,
RBDPool : "" ,
RadosUser : "" ,
Keyring : "" ,
SecretRef : nil ,
ReadOnly : false ,
} ,
} ,
} ,
} ,
expected : [ ] string {
` spec.rbd: deprecated in v1.28, non-functional in v1.31+ ` } ,
} ,
2023-06-08 16:06:53 +08:00
{
name : "PV ScaleIO deprecation warning" ,
template : & api . PersistentVolume {
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
ScaleIO : & api . ScaleIOPersistentVolumeSource {
Gateway : "" ,
System : "" ,
SecretRef : nil ,
SSLEnabled : false ,
ProtectionDomain : "" ,
StoragePool : "" ,
StorageMode : "" ,
VolumeName : "" ,
FSType : "" ,
ReadOnly : false ,
} ,
} ,
} ,
} ,
expected : [ ] string {
2023-06-16 22:17:03 +08:00
` spec.scaleIO: deprecated in v1.16, non-functional in v1.22+ ` ,
2023-06-08 16:06:53 +08:00
} ,
} ,
{
name : "PV StorageOS deprecation warning" ,
template : & api . PersistentVolume {
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
StorageOS : & api . StorageOSPersistentVolumeSource {
VolumeName : "" ,
VolumeNamespace : "" ,
FSType : "" ,
ReadOnly : false ,
SecretRef : nil ,
} ,
} ,
} ,
} ,
expected : [ ] string {
2023-06-16 22:17:03 +08:00
` spec.storageOS: deprecated in v1.22, non-functional in v1.25+ ` ,
2023-06-08 16:06:53 +08:00
} ,
} ,
{
name : "PV GlusterFS deprecation warning" ,
template : & api . PersistentVolume {
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
Glusterfs : & api . GlusterfsPersistentVolumeSource {
EndpointsName : "" ,
Path : "" ,
ReadOnly : false ,
EndpointsNamespace : nil ,
} ,
} ,
} ,
} ,
expected : [ ] string {
2023-06-16 22:17:03 +08:00
` spec.glusterfs: deprecated in v1.25, non-functional in v1.26+ ` ,
2023-06-08 16:06:53 +08:00
} ,
} ,
2022-03-07 18:17:28 +08:00
}
for _ , tc := range testcases {
t . Run ( "podspec_" + tc . name , func ( t * testing . T ) {
2022-05-25 11:41:51 +08:00
actual := sets . NewString ( GetWarningsForPersistentVolume ( tc . template ) ... )
2022-03-07 18:17:28 +08:00
expected := sets . NewString ( tc . expected ... )
for _ , missing := range expected . Difference ( actual ) . List ( ) {
t . Errorf ( "missing: %s" , missing )
}
for _ , extra := range actual . Difference ( expected ) . List ( ) {
t . Errorf ( "extra: %s" , extra )
}
} )
}
}