@@ -22,7 +22,6 @@ import (
2222 "fmt"
2323 "path/filepath"
2424 "regexp"
25- "strconv"
2625 "strings"
2726
2827 corev1 "k8s.io/api/core/v1"
@@ -31,10 +30,9 @@ import (
3130 "github.com/go-logr/logr"
3231 kmmv1beta1 "github.com/kubernetes-sigs/kernel-module-management/api/v1beta1"
3332 "github.com/kubernetes-sigs/kernel-module-management/internal/constants"
33+ "github.com/kubernetes-sigs/kernel-module-management/internal/version"
3434 "k8s.io/apimachinery/pkg/runtime"
3535 "k8s.io/apimachinery/pkg/util/sets"
36- "k8s.io/client-go/discovery"
37- "k8s.io/client-go/rest"
3836 ctrl "sigs.k8s.io/controller-runtime"
3937 "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
4038)
@@ -43,56 +41,15 @@ import (
4341// 63 (max label key length after slash) - len("version-schedule-plugin.") = 38
4442const maxCombinedLength = 38
4543
46- var kubeVersionRe = regexp .MustCompile (`^v?(\d+)\.(\d+)` )
47-
48- // KubeVersion holds the parsed major and minor version of a Kubernetes cluster.
49- type KubeVersion struct {
50- Major int
51- Minor int
52- }
53-
5444type ModuleValidator struct {
5545 logger logr.Logger
56- kubeVersion * KubeVersion
46+ kubeVersion * version. KubeVersion
5747}
5848
59- func NewModuleValidator (logger logr.Logger , kubeVersion * KubeVersion ) * ModuleValidator {
49+ func NewModuleValidator (logger logr.Logger , kubeVersion * version. KubeVersion ) * ModuleValidator {
6050 return & ModuleValidator {logger : logger , kubeVersion : kubeVersion }
6151}
6252
63- // DiscoverKubeVersion queries the Kubernetes API server and returns its version.
64- func DiscoverKubeVersion (cfg * rest.Config ) (KubeVersion , error ) {
65- discClient , err := discovery .NewDiscoveryClientForConfig (cfg )
66- if err != nil {
67- return KubeVersion {}, fmt .Errorf ("failed to create discovery client: %v" , err )
68- }
69-
70- serverVersion , err := discClient .ServerVersion ()
71- if err != nil {
72- return KubeVersion {}, fmt .Errorf ("failed to query Kubernetes server version: %v" , err )
73- }
74-
75- return parseKubeVersion (serverVersion .GitVersion )
76- }
77-
78- // parseKubeVersion extracts the major and minor version from a Kubernetes
79- // GitVersion string such as "v1.34.0" or "v1.34.0+k3s1".
80- func parseKubeVersion (gitVersion string ) (KubeVersion , error ) {
81- m := kubeVersionRe .FindStringSubmatch (gitVersion )
82- if m == nil {
83- return KubeVersion {}, fmt .Errorf ("cannot parse Kubernetes version from %q" , gitVersion )
84- }
85- major , err := strconv .Atoi (m [1 ])
86- if err != nil {
87- return KubeVersion {}, fmt .Errorf ("cannot parse Kubernetes major version from %q: %v" , gitVersion , err )
88- }
89- minor , err := strconv .Atoi (m [2 ])
90- if err != nil {
91- return KubeVersion {}, fmt .Errorf ("cannot parse Kubernetes minor version from %q: %v" , gitVersion , err )
92- }
93- return KubeVersion {Major : major , Minor : minor }, nil
94- }
95-
9653func (m * ModuleValidator ) SetupWebhookWithManager (mgr ctrl.Manager ) error {
9754 // controller-runtime will set the path to `validate-<group>-<version>-<resource> so we
9855 // need to make sure it is set correctly in the +kubebuilder annotation below.
@@ -145,7 +102,7 @@ func (m *ModuleValidator) ValidateDelete(ctx context.Context, obj runtime.Object
145102 return nil , NotImplemented
146103}
147104
148- func validateModule (mod * kmmv1beta1.Module , kubeVersion * KubeVersion ) (admission.Warnings , error ) {
105+ func validateModule (mod * kmmv1beta1.Module , kubeVersion * version. KubeVersion ) (admission.Warnings , error ) {
149106 nameLength := len (mod .Name + mod .Namespace )
150107
151108 if nameLength > maxCombinedLength {
@@ -192,20 +149,18 @@ func validateModule(mod *kmmv1beta1.Module, kubeVersion *KubeVersion) (admission
192149 return nil , validateFilesToSign (mod .Spec .ModuleLoader .Container )
193150}
194151
195- func validateDRA (mod * kmmv1beta1.Module , kubeVersion * KubeVersion ) error {
152+ func validateDRA (mod * kmmv1beta1.Module , kubeVersion * version. KubeVersion ) error {
196153 if mod .Spec .DRA == nil {
197154 return nil
198155 }
199156
200157 // Skip version gating when kubeVersion is nil (e.g. hub webhook validating
201158 // a ManagedClusterModule — the spoke's own webhook will enforce its version).
202- if kubeVersion != nil {
203- if kubeVersion .Major < constants .MinKubeMajorForDRA || (kubeVersion .Major == constants .MinKubeMajorForDRA && kubeVersion .Minor < constants .MinKubeMinorForDRA ) {
204- return fmt .Errorf (
205- "spec.dra requires Kubernetes %d.%d or later; current cluster version is %d.%d" ,
206- constants .MinKubeMajorForDRA , constants .MinKubeMinorForDRA , kubeVersion .Major , kubeVersion .Minor ,
207- )
208- }
159+ if kubeVersion != nil && ! kubeVersion .AtLeast (constants .MinKubeMajorForDRA , constants .MinKubeMinorForDRA ) {
160+ return fmt .Errorf (
161+ "spec.dra requires Kubernetes %d.%d or later; current cluster version is %d.%d" ,
162+ constants .MinKubeMajorForDRA , constants .MinKubeMinorForDRA , kubeVersion .Major , kubeVersion .Minor ,
163+ )
209164 }
210165
211166 driverName := mod .Spec .DRA .DriverName
@@ -252,7 +207,7 @@ func validateHostPathVolumes(fieldPath string, volumes []corev1.Volume) error {
252207 for i , vol := range volumes {
253208 if vol .HostPath != nil && ! isAllowedHostPath (vol .HostPath .Path ) {
254209 return fmt .Errorf (
255- "%s.volumes[%d]: hostPath %q is not allowed; only /dev, /sys, /var and /opt paths are permitted" ,
210+ "%s.volumes[%d]: hostPath %q is not allowed; only /dev, /sys, /var, /opt and /run paths are permitted" ,
256211 fieldPath , i , vol .HostPath .Path ,
257212 )
258213 }
0 commit comments