mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 02:33:34 +00:00
rebase: update K8s packages to v0.32.1
Update K8s packages in go.mod to v0.32.1 Signed-off-by: Praveen M <m.praveen@ibm.com>
This commit is contained in:
35
vendor/k8s.io/kubernetes/pkg/volume/plugins.go
generated
vendored
35
vendor/k8s.io/kubernetes/pkg/volume/plugins.go
generated
vendored
@ -17,12 +17,12 @@ limitations under the License.
|
||||
package volume
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/mount-utils"
|
||||
"k8s.io/utils/exec"
|
||||
@ -62,6 +62,8 @@ const (
|
||||
ProbeRemove
|
||||
)
|
||||
|
||||
var ErrNoPluiginMatched = errors.New("no volume plugin matched")
|
||||
|
||||
// VolumeOptions contains option information about a volume.
|
||||
type VolumeOptions struct {
|
||||
// The attributes below are required by volume.Provisioner
|
||||
@ -306,15 +308,18 @@ type KubeletVolumeHost interface {
|
||||
GetTrustAnchorsBySigner(signerName string, labelSelector *metav1.LabelSelector, allowMissing bool) ([]byte, error)
|
||||
}
|
||||
|
||||
// CSIDriverVolumeHost is a volume host that has access to CSIDriverLister
|
||||
type CSIDriverVolumeHost interface {
|
||||
// CSIDriverLister returns the informer lister for the CSIDriver API Object
|
||||
CSIDriverLister() storagelistersv1.CSIDriverLister
|
||||
}
|
||||
|
||||
// AttachDetachVolumeHost is a AttachDetach Controller specific interface that plugins can use
|
||||
// to access methods on the Attach Detach Controller.
|
||||
type AttachDetachVolumeHost interface {
|
||||
CSIDriverVolumeHost
|
||||
// CSINodeLister returns the informer lister for the CSINode API Object
|
||||
CSINodeLister() storagelistersv1.CSINodeLister
|
||||
|
||||
// CSIDriverLister returns the informer lister for the CSIDriver API Object
|
||||
CSIDriverLister() storagelistersv1.CSIDriverLister
|
||||
|
||||
// VolumeAttachmentLister returns the informer lister for the VolumeAttachment API Object
|
||||
VolumeAttachmentLister() storagelistersv1.VolumeAttachmentLister
|
||||
// IsAttachDetachController is an interface marker to strictly tie AttachDetachVolumeHost
|
||||
@ -414,12 +419,11 @@ type VolumeHost interface {
|
||||
|
||||
// VolumePluginMgr tracks registered plugins.
|
||||
type VolumePluginMgr struct {
|
||||
mutex sync.RWMutex
|
||||
plugins map[string]VolumePlugin
|
||||
prober DynamicPluginProber
|
||||
probedPlugins map[string]VolumePlugin
|
||||
loggedDeprecationWarnings sets.Set[string]
|
||||
Host VolumeHost
|
||||
mutex sync.RWMutex
|
||||
plugins map[string]VolumePlugin
|
||||
prober DynamicPluginProber
|
||||
probedPlugins map[string]VolumePlugin
|
||||
Host VolumeHost
|
||||
}
|
||||
|
||||
// Spec is an internal representation of a volume. All API volume types translate to Spec.
|
||||
@ -560,7 +564,6 @@ func (pm *VolumePluginMgr) InitPlugins(plugins []VolumePlugin, prober DynamicPlu
|
||||
defer pm.mutex.Unlock()
|
||||
|
||||
pm.Host = host
|
||||
pm.loggedDeprecationWarnings = sets.New[string]()
|
||||
|
||||
if prober == nil {
|
||||
// Use a dummy prober to prevent nil deference.
|
||||
@ -602,6 +605,7 @@ func (pm *VolumePluginMgr) InitPlugins(plugins []VolumePlugin, prober DynamicPlu
|
||||
pm.plugins[name] = plugin
|
||||
klog.V(1).InfoS("Loaded volume plugin", "pluginName", name)
|
||||
}
|
||||
pm.refreshProbedPlugins()
|
||||
return utilerrors.NewAggregate(allErrs)
|
||||
}
|
||||
|
||||
@ -649,7 +653,7 @@ func (pm *VolumePluginMgr) FindPluginBySpec(spec *Spec) (VolumePlugin, error) {
|
||||
}
|
||||
|
||||
if len(matchedPluginNames) == 0 {
|
||||
return nil, fmt.Errorf("no volume plugin matched")
|
||||
return nil, ErrNoPluiginMatched
|
||||
}
|
||||
if len(matchedPluginNames) > 1 {
|
||||
return nil, fmt.Errorf("multiple volume plugins matched: %s", strings.Join(matchedPluginNames, ","))
|
||||
@ -863,6 +867,9 @@ func (pm *VolumePluginMgr) FindExpandablePluginBySpec(spec *Spec) (ExpandableVol
|
||||
klog.V(4).InfoS("FindExpandablePluginBySpec -> returning noopExpandableVolumePluginInstance", "specName", spec.Name())
|
||||
return &noopExpandableVolumePluginInstance{spec}, nil
|
||||
}
|
||||
if errors.Is(err, ErrNoPluiginMatched) {
|
||||
return nil, nil
|
||||
}
|
||||
klog.V(4).InfoS("FindExpandablePluginBySpec -> err", "specName", spec.Name(), "err", err)
|
||||
return nil, err
|
||||
}
|
||||
@ -984,7 +991,7 @@ func NewPersistentVolumeRecyclerPodTemplate() *v1.Pod {
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "pv-recycler",
|
||||
Image: "registry.k8s.io/build-image/debian-base:bookworm-v1.0.3",
|
||||
Image: "registry.k8s.io/build-image/debian-base:bookworm-v1.0.4",
|
||||
Command: []string{"/bin/sh"},
|
||||
Args: []string{"-c", "test -e /scrub && find /scrub -mindepth 1 -delete && test -z \"$(ls -A /scrub)\" || exit 1"},
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
|
7
vendor/k8s.io/kubernetes/pkg/volume/util/device_util_linux.go
generated
vendored
7
vendor/k8s.io/kubernetes/pkg/volume/util/device_util_linux.go
generated
vendored
@ -31,8 +31,13 @@ import (
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// FindMultipathDeviceForDevice given a device name like /dev/sdx, find the devicemapper parent
|
||||
// FindMultipathDeviceForDevice given a device name like /dev/sdx, find the devicemapper parent. If called with a device
|
||||
// already resolved to devicemapper, do nothing.
|
||||
func (handler *deviceHandler) FindMultipathDeviceForDevice(device string) string {
|
||||
if strings.HasPrefix(device, "/dev/dm-") {
|
||||
return device
|
||||
}
|
||||
|
||||
io := handler.getIo
|
||||
disk, err := findDeviceForPath(device, io)
|
||||
if err != nil {
|
||||
|
3
vendor/k8s.io/kubernetes/pkg/volume/util/finalizer.go
generated
vendored
3
vendor/k8s.io/kubernetes/pkg/volume/util/finalizer.go
generated
vendored
@ -22,4 +22,7 @@ const (
|
||||
|
||||
// PVProtectionFinalizer is the name of finalizer on PVs that are bound by PVCs
|
||||
PVProtectionFinalizer = "kubernetes.io/pv-protection"
|
||||
|
||||
// VACProtectionFinalizer is the name of finalizer on VACs that are used by PVs or PVCs
|
||||
VACProtectionFinalizer = "kubernetes.io/vac-protection"
|
||||
)
|
||||
|
9
vendor/k8s.io/kubernetes/pkg/volume/util/recyclerclient/recycler_client.go
generated
vendored
9
vendor/k8s.io/kubernetes/pkg/volume/util/recyclerclient/recycler_client.go
generated
vendored
@ -18,11 +18,12 @@ package recyclerclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
@ -72,7 +73,7 @@ func internalRecycleVolumeByWatchingPodUntilCompletion(pvName string, pod *v1.Po
|
||||
// Start the pod
|
||||
_, err = recyclerClient.CreatePod(pod)
|
||||
if err != nil {
|
||||
if errors.IsAlreadyExists(err) {
|
||||
if apierrors.IsAlreadyExists(err) {
|
||||
deleteErr := recyclerClient.DeletePod(pod.Name, pod.Namespace)
|
||||
if deleteErr != nil {
|
||||
return fmt.Errorf("failed to delete old recycler pod %s/%s: %s", pod.Namespace, pod.Name, deleteErr)
|
||||
@ -89,7 +90,7 @@ func internalRecycleVolumeByWatchingPodUntilCompletion(pvName string, pod *v1.Po
|
||||
klog.V(2).Infof("deleting recycler pod %s/%s", pod.Namespace, pod.Name)
|
||||
deleteErr := recyclerClient.DeletePod(pod.Name, pod.Namespace)
|
||||
if deleteErr != nil {
|
||||
klog.Errorf("failed to delete recycler pod %s/%s: %v", pod.Namespace, pod.Name, err)
|
||||
klog.Errorf("failed to delete recycler pod %s/%s: %v", pod.Namespace, pod.Name, deleteErr)
|
||||
}
|
||||
|
||||
// Returning recycler error is preferred, the pod will be deleted again on
|
||||
@ -128,7 +129,7 @@ func waitForPod(pod *v1.Pod, recyclerClient recyclerClient, podCh <-chan watch.E
|
||||
}
|
||||
if pod.Status.Phase == v1.PodFailed {
|
||||
if pod.Status.Message != "" {
|
||||
return fmt.Errorf(pod.Status.Message)
|
||||
return errors.New(pod.Status.Message)
|
||||
}
|
||||
return fmt.Errorf("pod failed, pod.Status.Message unknown")
|
||||
}
|
||||
|
127
vendor/k8s.io/kubernetes/pkg/volume/util/selinux.go
generated
vendored
127
vendor/k8s.io/kubernetes/pkg/volume/util/selinux.go
generated
vendored
@ -17,11 +17,14 @@ limitations under the License.
|
||||
package util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/opencontainers/selinux/go-selinux"
|
||||
"github.com/opencontainers/selinux/go-selinux/label"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
@ -71,7 +74,7 @@ func (l *translator) SELinuxOptionsToFileLabel(opts *v1.SELinuxOptions) (string,
|
||||
if err != nil {
|
||||
// In theory, this should be unreachable. InitLabels can fail only when args contain an unknown option,
|
||||
// and all options returned by contextOptions are known.
|
||||
return "", err
|
||||
return "", &SELinuxLabelTranslationError{msg: err.Error()}
|
||||
}
|
||||
// InitLabels() may allocate a new unique SELinux label in kubelet memory. The label is *not* allocated
|
||||
// in the container runtime. Clear it to avoid memory problems.
|
||||
@ -156,6 +159,19 @@ func (l *fakeTranslator) SELinuxEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type SELinuxLabelTranslationError struct {
|
||||
msg string
|
||||
}
|
||||
|
||||
func (e *SELinuxLabelTranslationError) Error() string {
|
||||
return e.msg
|
||||
}
|
||||
|
||||
func IsSELinuxLabelTranslationError(err error) bool {
|
||||
var seLinuxError *SELinuxLabelTranslationError
|
||||
return errors.As(err, &seLinuxError)
|
||||
}
|
||||
|
||||
// SupportsSELinuxContextMount checks if the given volumeSpec supports with mount -o context
|
||||
func SupportsSELinuxContextMount(volumeSpec *volume.Spec, volumePluginMgr *volume.VolumePluginMgr) (bool, error) {
|
||||
plugin, _ := volumePluginMgr.FindPluginBySpec(volumeSpec)
|
||||
@ -174,19 +190,41 @@ func VolumeSupportsSELinuxMount(volumeSpec *volume.Spec) bool {
|
||||
if volumeSpec.PersistentVolume == nil {
|
||||
return false
|
||||
}
|
||||
if len(volumeSpec.PersistentVolume.Spec.AccessModes) != 1 {
|
||||
return false
|
||||
}
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMount) {
|
||||
return true
|
||||
}
|
||||
// Only SELinuxMountReadWriteOncePod feature enabled
|
||||
if !v1helper.ContainsAccessMode(volumeSpec.PersistentVolume.Spec.AccessModes, v1.ReadWriteOncePod) {
|
||||
|
||||
// Only SELinuxMountReadWriteOncePod feature is enabled
|
||||
if len(volumeSpec.PersistentVolume.Spec.AccessModes) != 1 {
|
||||
// RWOP volumes must be the only access mode of the volume
|
||||
return false
|
||||
}
|
||||
if !v1helper.ContainsAccessMode(volumeSpec.PersistentVolume.Spec.AccessModes, v1.ReadWriteOncePod) {
|
||||
// Not a RWOP volume
|
||||
return false
|
||||
}
|
||||
// RWOP volume
|
||||
return true
|
||||
}
|
||||
|
||||
// MultipleSELinuxLabelsError tells that one volume in a pod is mounted in multiple containers and each has a different SELinux label.
|
||||
type MultipleSELinuxLabelsError struct {
|
||||
labels []string
|
||||
}
|
||||
|
||||
func (e *MultipleSELinuxLabelsError) Error() string {
|
||||
return fmt.Sprintf("multiple SELinux labels found: %s", strings.Join(e.labels, ","))
|
||||
}
|
||||
|
||||
func (e *MultipleSELinuxLabelsError) Labels() []string {
|
||||
return e.labels
|
||||
}
|
||||
|
||||
func IsMultipleSELinuxLabelsError(err error) bool {
|
||||
var multiError *MultipleSELinuxLabelsError
|
||||
return errors.As(err, &multiError)
|
||||
}
|
||||
|
||||
// AddSELinuxMountOption adds -o context="XYZ" mount option to a given list
|
||||
func AddSELinuxMountOption(options []string, seLinuxContext string) []string {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
|
||||
@ -196,3 +234,80 @@ func AddSELinuxMountOption(options []string, seLinuxContext string) []string {
|
||||
// For example: dirsync,context="system_u:object_r:container_file_t:s0:c15,c25",noatime
|
||||
return append(options, fmt.Sprintf("context=%q", seLinuxContext))
|
||||
}
|
||||
|
||||
// SELinuxLabelInfo contains information about SELinux labels that should be used to mount a volume for a Pod.
|
||||
type SELinuxLabelInfo struct {
|
||||
// SELinuxMountLabel is the SELinux label that should be used to mount the volume.
|
||||
// The volume plugin supports SELinuxMount and the Pod did not opt out via SELinuxChangePolicy.
|
||||
// Empty string otherwise.
|
||||
SELinuxMountLabel string
|
||||
// SELinuxProcessLabel is the SELinux label that will the container runtime use for the Pod.
|
||||
// Regardless if the volume plugin supports SELinuxMount or the Pod opted out via SELinuxChangePolicy.
|
||||
SELinuxProcessLabel string
|
||||
// PluginSupportsSELinuxContextMount is true if the volume plugin supports SELinux mount.
|
||||
PluginSupportsSELinuxContextMount bool
|
||||
}
|
||||
|
||||
// GetMountSELinuxLabel returns SELinux labels that should be used to mount the given volume volumeSpec and podSecurityContext.
|
||||
// It expects effectiveSELinuxContainerLabels as returned by volumeutil.GetPodVolumeNames, i.e. with all SELinuxOptions
|
||||
// from all containers that use the volume in the pod, potentially expanded with PodSecurityContext.SELinuxOptions,
|
||||
// if container's SELinuxOptions are nil.
|
||||
// It does not evaluate the volume access mode! It's up to the caller to check SELinuxMount feature gate,
|
||||
// it may need to bump different metrics based on feature gates / access modes / label anyway.
|
||||
func GetMountSELinuxLabel(volumeSpec *volume.Spec, effectiveSELinuxContainerLabels []*v1.SELinuxOptions, podSecurityContext *v1.PodSecurityContext, volumePluginMgr *volume.VolumePluginMgr, seLinuxTranslator SELinuxLabelTranslator) (SELinuxLabelInfo, error) {
|
||||
info := SELinuxLabelInfo{}
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
|
||||
return info, nil
|
||||
}
|
||||
|
||||
if !seLinuxTranslator.SELinuxEnabled() {
|
||||
return info, nil
|
||||
}
|
||||
|
||||
pluginSupportsSELinuxContextMount, err := SupportsSELinuxContextMount(volumeSpec, volumePluginMgr)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
info.PluginSupportsSELinuxContextMount = pluginSupportsSELinuxContextMount
|
||||
|
||||
// Collect all SELinux options from all containers that use this volume.
|
||||
// A set will squash any duplicities.
|
||||
labels := sets.New[string]()
|
||||
for _, containerLabel := range effectiveSELinuxContainerLabels {
|
||||
lbl, err := seLinuxTranslator.SELinuxOptionsToFileLabel(containerLabel)
|
||||
if err != nil {
|
||||
fullErr := fmt.Errorf("failed to construct SELinux label from context %q: %w", containerLabel, err)
|
||||
return info, fullErr
|
||||
}
|
||||
labels.Insert(lbl)
|
||||
}
|
||||
|
||||
// Ensure that all containers use the same SELinux label.
|
||||
if labels.Len() > 1 {
|
||||
// This volume is used with more than one SELinux label in the pod.
|
||||
return info, &MultipleSELinuxLabelsError{labels: labels.UnsortedList()}
|
||||
}
|
||||
if labels.Len() == 0 {
|
||||
return info, nil
|
||||
}
|
||||
|
||||
lbl, _ := labels.PopAny()
|
||||
info.SELinuxProcessLabel = lbl
|
||||
info.SELinuxMountLabel = lbl
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxChangePolicy) &&
|
||||
podSecurityContext != nil &&
|
||||
podSecurityContext.SELinuxChangePolicy != nil &&
|
||||
*podSecurityContext.SELinuxChangePolicy == v1.SELinuxChangePolicyRecursive {
|
||||
// The pod has opted into recursive SELinux label changes. Do not mount with -o context.
|
||||
info.SELinuxMountLabel = ""
|
||||
}
|
||||
|
||||
if !pluginSupportsSELinuxContextMount {
|
||||
// The volume plugin does not support SELinux mount. Do not mount with -o context.
|
||||
info.SELinuxMountLabel = ""
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
13
vendor/k8s.io/kubernetes/pkg/volume/util/util.go
generated
vendored
13
vendor/k8s.io/kubernetes/pkg/volume/util/util.go
generated
vendored
@ -32,12 +32,10 @@ import (
|
||||
utypes "k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/securitycontext"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util/types"
|
||||
@ -512,19 +510,18 @@ func IsLocalEphemeralVolume(volume v1.Volume) bool {
|
||||
}
|
||||
|
||||
// GetPodVolumeNames returns names of volumes that are used in a pod,
|
||||
// either as filesystem mount or raw block device, together with list
|
||||
// of all SELinux contexts of all containers that use the volumes.
|
||||
func GetPodVolumeNames(pod *v1.Pod) (mounts sets.Set[string], devices sets.Set[string], seLinuxContainerContexts map[string][]*v1.SELinuxOptions) {
|
||||
// either as filesystem mount or raw block device.
|
||||
// To save another sweep through containers, SELinux options are optionally collected too.
|
||||
func GetPodVolumeNames(pod *v1.Pod, collectSELinuxOptions bool) (mounts sets.Set[string], devices sets.Set[string], seLinuxContainerContexts map[string][]*v1.SELinuxOptions) {
|
||||
mounts = sets.New[string]()
|
||||
devices = sets.New[string]()
|
||||
seLinuxContainerContexts = make(map[string][]*v1.SELinuxOptions)
|
||||
|
||||
podutil.VisitContainers(&pod.Spec, podutil.AllFeatureEnabledContainers(), func(container *v1.Container, containerType podutil.ContainerType) bool {
|
||||
var seLinuxOptions *v1.SELinuxOptions
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
|
||||
if collectSELinuxOptions {
|
||||
effectiveContainerSecurity := securitycontext.DetermineEffectiveSecurityContext(pod, container)
|
||||
if effectiveContainerSecurity != nil {
|
||||
// No DeepCopy, SELinuxOptions is already a copy of Pod's or container's SELinuxOptions
|
||||
seLinuxOptions = effectiveContainerSecurity.SELinuxOptions
|
||||
}
|
||||
}
|
||||
@ -532,7 +529,7 @@ func GetPodVolumeNames(pod *v1.Pod) (mounts sets.Set[string], devices sets.Set[s
|
||||
if container.VolumeMounts != nil {
|
||||
for _, mount := range container.VolumeMounts {
|
||||
mounts.Insert(mount.Name)
|
||||
if seLinuxOptions != nil {
|
||||
if seLinuxOptions != nil && collectSELinuxOptions {
|
||||
seLinuxContainerContexts[mount.Name] = append(seLinuxContainerContexts[mount.Name], seLinuxOptions.DeepCopy())
|
||||
}
|
||||
}
|
||||
|
72
vendor/k8s.io/kubernetes/pkg/volume/util/volumeattributesclass.go
generated
vendored
72
vendor/k8s.io/kubernetes/pkg/volume/util/volumeattributesclass.go
generated
vendored
@ -1,72 +0,0 @@
|
||||
/*
|
||||
Copyright 2023 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 (
|
||||
"sort"
|
||||
|
||||
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
storagev1beta1listers "k8s.io/client-go/listers/storage/v1beta1"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
// AlphaIsDefaultVolumeAttributesClassAnnotation is the alpha version of IsDefaultVolumeAttributesClassAnnotation.
|
||||
AlphaIsDefaultVolumeAttributesClassAnnotation = "volumeattributesclass.alpha.kubernetes.io/is-default-class"
|
||||
)
|
||||
|
||||
// GetDefaultVolumeAttributesClass returns the default VolumeAttributesClass from the store, or nil.
|
||||
func GetDefaultVolumeAttributesClass(lister storagev1beta1listers.VolumeAttributesClassLister, driverName string) (*storagev1beta1.VolumeAttributesClass, error) {
|
||||
list, err := lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defaultClasses := []*storagev1beta1.VolumeAttributesClass{}
|
||||
for _, class := range list {
|
||||
if IsDefaultVolumeAttributesClassAnnotation(class.ObjectMeta) && class.DriverName == driverName {
|
||||
defaultClasses = append(defaultClasses, class)
|
||||
klog.V(4).Infof("GetDefaultVolumeAttributesClass added: %s", class.Name)
|
||||
}
|
||||
}
|
||||
|
||||
if len(defaultClasses) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Primary sort by creation timestamp, newest first
|
||||
// Secondary sort by class name, ascending order
|
||||
sort.Slice(defaultClasses, func(i, j int) bool {
|
||||
if defaultClasses[i].CreationTimestamp.UnixNano() == defaultClasses[j].CreationTimestamp.UnixNano() {
|
||||
return defaultClasses[i].Name < defaultClasses[j].Name
|
||||
}
|
||||
return defaultClasses[i].CreationTimestamp.UnixNano() > defaultClasses[j].CreationTimestamp.UnixNano()
|
||||
})
|
||||
if len(defaultClasses) > 1 {
|
||||
klog.V(4).Infof("%d default VolumeAttributesClass were found, choosing: %s", len(defaultClasses), defaultClasses[0].Name)
|
||||
}
|
||||
|
||||
return defaultClasses[0], nil
|
||||
}
|
||||
|
||||
// IsDefaultVolumeAttributesClassAnnotation returns a boolean if the default
|
||||
// volume attributes class annotation is set
|
||||
func IsDefaultVolumeAttributesClassAnnotation(obj metav1.ObjectMeta) bool {
|
||||
return obj.Annotations[AlphaIsDefaultVolumeAttributesClassAnnotation] == "true"
|
||||
}
|
Reference in New Issue
Block a user