diff --git a/pkg/volume/util/storageclass.go b/pkg/volume/util/storageclass.go new file mode 100644 index 00000000000..5350bc8e963 --- /dev/null +++ b/pkg/volume/util/storageclass.go @@ -0,0 +1,76 @@ +/* +Copyright 2022 The Kubernetes Authors. + +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 util + +import ( + "fmt" + storagev1 "k8s.io/api/storage/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + storagev1listers "k8s.io/client-go/listers/storage/v1" + "k8s.io/klog/v2" +) + +const ( + // isDefaultStorageClassAnnotation represents a StorageClass annotation that + // marks a class as the default StorageClass + IsDefaultStorageClassAnnotation = "storageclass.kubernetes.io/is-default-class" + + // betaIsDefaultStorageClassAnnotation is the beta version of IsDefaultStorageClassAnnotation. + // TODO: remove Beta when no longer used + BetaIsDefaultStorageClassAnnotation = "storageclass.beta.kubernetes.io/is-default-class" +) + +// GetDefaultClass returns the default StorageClass from the store, or nil. +func GetDefaultClass(lister storagev1listers.StorageClassLister) (*storagev1.StorageClass, error) { + list, err := lister.List(labels.Everything()) + if err != nil { + return nil, err + } + + defaultClasses := []*storagev1.StorageClass{} + for _, class := range list { + if IsDefaultAnnotation(class.ObjectMeta) { + defaultClasses = append(defaultClasses, class) + klog.V(4).Infof("GetDefaultClass added: %s", class.Name) + } + } + + if len(defaultClasses) == 0 { + return nil, nil + } + if len(defaultClasses) > 1 { + klog.V(4).Infof("GetDefaultClass %d defaults found", len(defaultClasses)) + return nil, errors.NewInternalError(fmt.Errorf("%d default StorageClasses were found", len(defaultClasses))) + } + return defaultClasses[0], nil +} + +// IsDefaultAnnotation returns a boolean if the default storage class +// annotation is set +// TODO: remove Beta when no longer needed +func IsDefaultAnnotation(obj metav1.ObjectMeta) bool { + if obj.Annotations[IsDefaultStorageClassAnnotation] == "true" { + return true + } + if obj.Annotations[BetaIsDefaultStorageClassAnnotation] == "true" { + return true + } + + return false +} diff --git a/plugin/pkg/admission/storage/storageclass/setdefault/admission.go b/plugin/pkg/admission/storage/storageclass/setdefault/admission.go index 33f85d4d256..aa4c1c14ba7 100644 --- a/plugin/pkg/admission/storage/storageclass/setdefault/admission.go +++ b/plugin/pkg/admission/storage/storageclass/setdefault/admission.go @@ -20,19 +20,16 @@ import ( "context" "fmt" "io" + "k8s.io/kubernetes/pkg/volume/util" "k8s.io/klog/v2" - storagev1 "k8s.io/api/storage/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" "k8s.io/apiserver/pkg/admission" genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer" "k8s.io/client-go/informers" storagev1listers "k8s.io/client-go/listers/storage/v1" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core/helper" - storageutil "k8s.io/kubernetes/pkg/apis/storage/util" ) const ( @@ -108,7 +105,7 @@ func (a *claimDefaulterPlugin) Admit(ctx context.Context, attr admission.Attribu klog.V(4).Infof("no storage class for claim %s (generate: %s)", pvc.Name, pvc.GenerateName) - def, err := getDefaultClass(a.lister) + def, err := util.GetDefaultClass(a.lister) if err != nil { return admission.NewForbidden(attr, err) } @@ -121,28 +118,3 @@ func (a *claimDefaulterPlugin) Admit(ctx context.Context, attr admission.Attribu pvc.Spec.StorageClassName = &def.Name return nil } - -// getDefaultClass returns the default StorageClass from the store, or nil. -func getDefaultClass(lister storagev1listers.StorageClassLister) (*storagev1.StorageClass, error) { - list, err := lister.List(labels.Everything()) - if err != nil { - return nil, err - } - - defaultClasses := []*storagev1.StorageClass{} - for _, class := range list { - if storageutil.IsDefaultAnnotation(class.ObjectMeta) { - defaultClasses = append(defaultClasses, class) - klog.V(4).Infof("getDefaultClass added: %s", class.Name) - } - } - - if len(defaultClasses) == 0 { - return nil, nil - } - if len(defaultClasses) > 1 { - klog.V(4).Infof("getDefaultClass %d defaults found", len(defaultClasses)) - return nil, errors.NewInternalError(fmt.Errorf("%d default StorageClasses were found", len(defaultClasses))) - } - return defaultClasses[0], nil -} diff --git a/test/e2e/framework/pv/pv.go b/test/e2e/framework/pv/pv.go index f16cd7f0c8b..fa02940773d 100644 --- a/test/e2e/framework/pv/pv.go +++ b/test/e2e/framework/pv/pv.go @@ -34,6 +34,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/test/e2e/framework" e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" ) @@ -45,14 +46,6 @@ const ( // VolumeSelectorKey is the key for volume selector. VolumeSelectorKey = "e2e-pv-pool" - // isDefaultStorageClassAnnotation represents a StorageClass annotation that - // marks a class as the default StorageClass - isDefaultStorageClassAnnotation = "storageclass.kubernetes.io/is-default-class" - - // betaIsDefaultStorageClassAnnotation is the beta version of IsDefaultStorageClassAnnotation. - // TODO: remove Beta when no longer used - betaIsDefaultStorageClassAnnotation = "storageclass.beta.kubernetes.io/is-default-class" - // volumeGidAnnotationKey is the of the annotation on the PersistentVolume // object that specifies a supplemental GID. // it is copied from k8s.io/kubernetes/pkg/volume/util VolumeGidAnnotationKey @@ -826,7 +819,7 @@ func GetDefaultStorageClassName(c clientset.Interface) (string, error) { } var scName string for _, sc := range list.Items { - if isDefaultAnnotation(sc.ObjectMeta) { + if util.IsDefaultAnnotation(sc.ObjectMeta) { if len(scName) != 0 { return "", fmt.Errorf("Multiple default storage classes found: %q and %q", scName, sc.Name) } @@ -840,20 +833,6 @@ func GetDefaultStorageClassName(c clientset.Interface) (string, error) { return scName, nil } -// isDefaultAnnotation returns a boolean if the default storage class -// annotation is set -// TODO: remove Beta when no longer needed -func isDefaultAnnotation(obj metav1.ObjectMeta) bool { - if obj.Annotations[isDefaultStorageClassAnnotation] == "true" { - return true - } - if obj.Annotations[betaIsDefaultStorageClassAnnotation] == "true" { - return true - } - - return false -} - // SkipIfNoDefaultStorageClass skips tests if no default SC can be found. func SkipIfNoDefaultStorageClass(c clientset.Interface) { _, err := GetDefaultStorageClassName(c)