@@ -22,8 +22,11 @@ import (
2222
2323	volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1" 
2424	volumesnapshotv1beta1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1beta1" 
25+ 	storagelisters "github.com/kubernetes-csi/external-snapshotter/client/v6/listers/volumesnapshot/v1" 
26+ 	"github.com/kubernetes-csi/external-snapshotter/v6/pkg/utils" 
2527	v1 "k8s.io/api/admission/v1" 
2628	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 
29+ 	"k8s.io/apimachinery/pkg/labels" 
2730	"k8s.io/klog/v2" 
2831)
2932
@@ -36,10 +39,26 @@ var (
3639	SnapshotContentV1Beta1GVR  =  metav1.GroupVersionResource {Group : volumesnapshotv1beta1 .GroupName , Version : "v1beta1" , Resource : "volumesnapshotcontents" }
3740	// SnapshotContentV1GVR is GroupVersionResource for v1 VolumeSnapshotContents 
3841	SnapshotContentV1GVR  =  metav1.GroupVersionResource {Group : volumesnapshotv1 .GroupName , Version : "v1" , Resource : "volumesnapshotcontents" }
42+ 	// SnapshotContentV1GVR is GroupVersionResource for v1 VolumeSnapshotContents 
43+ 	SnapshotClassV1GVR  =  metav1.GroupVersionResource {Group : volumesnapshotv1 .GroupName , Version : "v1" , Resource : "volumesnapshotclasses" }
3944)
4045
46+ type  SnapshotAdmitter  interface  {
47+ 	Admit (v1.AdmissionReview ) * v1.AdmissionResponse 
48+ }
49+ 
50+ type  admitter  struct  {
51+ 	lister  storagelisters.VolumeSnapshotClassLister 
52+ }
53+ 
54+ func  NewSnapshotAdmitter (lister  storagelisters.VolumeSnapshotClassLister ) SnapshotAdmitter  {
55+ 	return  & admitter {
56+ 		lister : lister ,
57+ 	}
58+ }
59+ 
4160// Add a label {"added-label": "yes"} to the object 
42- func  admitSnapshot (ar  v1.AdmissionReview ) * v1.AdmissionResponse  {
61+ func  ( a   admitter )  Admit (ar  v1.AdmissionReview ) * v1.AdmissionResponse  {
4362	klog .V (2 ).Info ("admitting volumesnapshots or volumesnapshotcontents" )
4463
4564	reviewResponse  :=  & v1.AdmissionResponse {
@@ -106,6 +125,18 @@ func admitSnapshot(ar v1.AdmissionReview) *v1.AdmissionResponse {
106125			return  toV1AdmissionResponse (err )
107126		}
108127		return  decideSnapshotContentV1 (snapcontent , oldSnapcontent , isUpdate )
128+ 	case  SnapshotClassV1GVR :
129+ 		snapClass  :=  & volumesnapshotv1.VolumeSnapshotClass {}
130+ 		if  _ , _ , err  :=  deserializer .Decode (raw , nil , snapClass ); err  !=  nil  {
131+ 			klog .Error (err )
132+ 			return  toV1AdmissionResponse (err )
133+ 		}
134+ 		oldSnapClass  :=  & volumesnapshotv1.VolumeSnapshotClass {}
135+ 		if  _ , _ , err  :=  deserializer .Decode (oldRaw , nil , oldSnapClass ); err  !=  nil  {
136+ 			klog .Error (err )
137+ 			return  toV1AdmissionResponse (err )
138+ 		}
139+ 		return  decideSnapshotClassV1 (snapClass , oldSnapClass , a .lister )
109140	default :
110141		err  :=  fmt .Errorf ("expect resource to be %s or %s" , SnapshotV1Beta1GVR , SnapshotContentV1Beta1GVR )
111142		klog .Error (err )
@@ -223,6 +254,43 @@ func decideSnapshotContentV1(snapcontent, oldSnapcontent *volumesnapshotv1.Volum
223254	return  reviewResponse 
224255}
225256
257+ func  decideSnapshotClassV1 (snapClass , oldSnapClass  * volumesnapshotv1.VolumeSnapshotClass , lister  storagelisters.VolumeSnapshotClassLister ) * v1.AdmissionResponse  {
258+ 	reviewResponse  :=  & v1.AdmissionResponse {
259+ 		Allowed : true ,
260+ 		Result :  & metav1.Status {},
261+ 	}
262+ 
263+ 	// Only Validate when a new snapClass is being set as a default. 
264+ 	if  snapClass .Annotations [utils .IsDefaultSnapshotClassAnnotation ] !=  "true"  {
265+ 		return  reviewResponse 
266+ 	}
267+ 
268+ 	// If Old snapshot class has this, then we can assume that it was validated if driver is the same. 
269+ 	if  oldSnapClass .Annotations [utils .IsDefaultSnapshotClassAnnotation ] ==  "true"  &&  oldSnapClass .Driver  ==  snapClass .Driver  {
270+ 		return  reviewResponse 
271+ 	}
272+ 
273+ 	ret , err  :=  lister .List (labels .Everything ())
274+ 	if  err  !=  nil  {
275+ 		reviewResponse .Allowed  =  false 
276+ 		reviewResponse .Result .Message  =  err .Error ()
277+ 		return  reviewResponse 
278+ 	}
279+ 
280+ 	for  _ , snapshotClass  :=  range  ret  {
281+ 		if  snapshotClass .Annotations [utils .IsDefaultSnapshotClassAnnotation ] !=  "true"  {
282+ 			continue 
283+ 		}
284+ 		if  snapshotClass .Driver  ==  snapClass .Driver  {
285+ 			reviewResponse .Allowed  =  false 
286+ 			reviewResponse .Result .Message  =  fmt .Sprintf ("default snapshot class: %v already exits for driver: %v" , snapshotClass .Name , snapClass .Driver )
287+ 			return  reviewResponse 
288+ 		}
289+ 	}
290+ 
291+ 	return  reviewResponse 
292+ }
293+ 
226294func  strPtrDereference (s  * string ) string  {
227295	if  s  ==  nil  {
228296		return  "<nil string pointer>" 
0 commit comments