mirror of
https://github.com/intel/intel-device-plugins-for-kubernetes.git
synced 2025-06-03 03:59:37 +00:00
operator: rework webhooks
controller-runtime has deprecated webhook.Defaulter/Validator and they will be removed in the next controller-runtime release. Move deviceplugin webhooks to use admission.CustomDefaulter/Validator. Common defaulter/validator types can serve all the plugins with only plugin specific data initialized. As part of the rework, move away from (the unmaintained) pkg/errors to errors in Go standard library. Signed-off-by: Mikko Ylinen <mikko.ylinen@intel.com>
This commit is contained in:
parent
76b5118a86
commit
c30e80bf86
@ -15,73 +15,35 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
|
||||
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers"
|
||||
)
|
||||
|
||||
var (
|
||||
// dlbdevicepluginlog is for logging in this package.
|
||||
dlbdevicepluginlog = logf.Log.WithName("dlbdeviceplugin-resource")
|
||||
|
||||
dlbMinVersion = controllers.ImageMinVersion
|
||||
)
|
||||
|
||||
// SetupWebhookWithManager sets up a webhook for DlbDevicePlugin custom resources.
|
||||
func (r *DlbDevicePlugin) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewWebhookManagedBy(mgr).
|
||||
For(r).
|
||||
WithDefaulter(&commonDevicePluginDefaulter{
|
||||
defaultImage: "intel/intel-dlb-plugin:" + controllers.ImageMinVersion.String(),
|
||||
}).
|
||||
WithValidator(&commonDevicePluginValidator{
|
||||
expectedImage: "intel-dlb-plugin",
|
||||
expectedInitImage: "intel-dlb-initimage",
|
||||
expectedVersion: *controllers.ImageMinVersion,
|
||||
}).
|
||||
Complete()
|
||||
}
|
||||
|
||||
// +kubebuilder:webhook:path=/mutate-deviceplugin-intel-com-v1-dlbdeviceplugin,mutating=true,failurePolicy=fail,groups=deviceplugin.intel.com,resources=dlbdeviceplugins,verbs=create;update,versions=v1,name=mdlbdeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Defaulter = &DlbDevicePlugin{}
|
||||
|
||||
// Default implements webhook.Defaulter so a webhook will be registered for the type.
|
||||
func (r *DlbDevicePlugin) Default() {
|
||||
dlbdevicepluginlog.Info("default", "name", r.Name)
|
||||
|
||||
if len(r.Spec.Image) == 0 {
|
||||
r.Spec.Image = "intel/intel-dlb-plugin:" + dlbMinVersion.String()
|
||||
}
|
||||
}
|
||||
|
||||
// +kubebuilder:webhook:verbs=create;update,path=/validate-deviceplugin-intel-com-v1-dlbdeviceplugin,mutating=false,failurePolicy=fail,groups=deviceplugin.intel.com,resources=dlbdeviceplugins,versions=v1,name=vdlbdeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Validator = &DlbDevicePlugin{}
|
||||
|
||||
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *DlbDevicePlugin) ValidateCreate() (admission.Warnings, error) {
|
||||
dlbdevicepluginlog.Info("validate create", "name", r.Name)
|
||||
|
||||
return nil, r.validatePlugin()
|
||||
}
|
||||
|
||||
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *DlbDevicePlugin) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
|
||||
dlbdevicepluginlog.Info("validate update", "name", r.Name)
|
||||
|
||||
return nil, r.validatePlugin()
|
||||
}
|
||||
|
||||
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *DlbDevicePlugin) ValidateDelete() (admission.Warnings, error) {
|
||||
dlbdevicepluginlog.Info("validate delete", "name", r.Name)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *DlbDevicePlugin) validatePlugin() error {
|
||||
func (r *DlbDevicePlugin) validatePlugin(ref *commonDevicePluginValidator) error {
|
||||
if r.Spec.InitImage != "" {
|
||||
if err := validatePluginImage(r.Spec.InitImage, "intel-dlb-initcontainer", dlbMinVersion); err != nil {
|
||||
if err := validatePluginImage(r.Spec.InitImage, ref.expectedInitImage, &ref.expectedVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return validatePluginImage(r.Spec.Image, "intel-dlb-plugin", dlbMinVersion)
|
||||
return validatePluginImage(r.Spec.Image, ref.expectedImage, &ref.expectedVersion)
|
||||
}
|
||||
|
@ -15,79 +15,42 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"fmt"
|
||||
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
|
||||
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers"
|
||||
)
|
||||
|
||||
var (
|
||||
// dsadevicepluginlog is for logging in this package.
|
||||
dsadevicepluginlog = logf.Log.WithName("dsadeviceplugin-resource")
|
||||
|
||||
dsaMinVersion = controllers.ImageMinVersion
|
||||
)
|
||||
|
||||
// SetupWebhookWithManager sets up a webhook for DsaDevicePlugin custom resources.
|
||||
func (r *DsaDevicePlugin) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewWebhookManagedBy(mgr).
|
||||
For(r).
|
||||
WithDefaulter(&commonDevicePluginDefaulter{
|
||||
defaultImage: "intel/intel-dsa-plugin:" + controllers.ImageMinVersion.String(),
|
||||
}).
|
||||
WithValidator(&commonDevicePluginValidator{
|
||||
expectedImage: "intel-dsa-plugin",
|
||||
expectedInitImage: "intel-idxd-config-initcontainer",
|
||||
expectedVersion: *controllers.ImageMinVersion,
|
||||
}).
|
||||
Complete()
|
||||
}
|
||||
|
||||
// +kubebuilder:webhook:path=/mutate-deviceplugin-intel-com-v1-dsadeviceplugin,mutating=true,failurePolicy=fail,groups=deviceplugin.intel.com,resources=dsadeviceplugins,verbs=create;update,versions=v1,name=mdsadeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Defaulter = &DsaDevicePlugin{}
|
||||
|
||||
// Default implements webhook.Defaulter so a webhook will be registered for the type.
|
||||
func (r *DsaDevicePlugin) Default() {
|
||||
dsadevicepluginlog.Info("default", "name", r.Name)
|
||||
|
||||
if len(r.Spec.Image) == 0 {
|
||||
r.Spec.Image = "intel/intel-dsa-plugin:" + dsaMinVersion.String()
|
||||
}
|
||||
}
|
||||
|
||||
// +kubebuilder:webhook:verbs=create;update,path=/validate-deviceplugin-intel-com-v1-dsadeviceplugin,mutating=false,failurePolicy=fail,groups=deviceplugin.intel.com,resources=dsadeviceplugins,versions=v1,name=vdsadeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Validator = &DsaDevicePlugin{}
|
||||
|
||||
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *DsaDevicePlugin) ValidateCreate() (admission.Warnings, error) {
|
||||
dsadevicepluginlog.Info("validate create", "name", r.Name)
|
||||
|
||||
return nil, r.validatePlugin()
|
||||
}
|
||||
|
||||
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *DsaDevicePlugin) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
|
||||
dsadevicepluginlog.Info("validate update", "name", r.Name)
|
||||
|
||||
return nil, r.validatePlugin()
|
||||
}
|
||||
|
||||
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *DsaDevicePlugin) ValidateDelete() (admission.Warnings, error) {
|
||||
dsadevicepluginlog.Info("validate delete", "name", r.Name)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *DsaDevicePlugin) validatePlugin() error {
|
||||
if err := validatePluginImage(r.Spec.Image, "intel-dsa-plugin", dsaMinVersion); err != nil {
|
||||
func (r *DsaDevicePlugin) validatePlugin(ref *commonDevicePluginValidator) error {
|
||||
if err := validatePluginImage(r.Spec.Image, ref.expectedImage, &ref.expectedVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(r.Spec.ProvisioningConfig) > 0 && len(r.Spec.InitImage) == 0 {
|
||||
return errors.Errorf("ProvisioningConfig is set with no InitImage")
|
||||
return fmt.Errorf("%w: ProvisioningConfig is set with no InitImage", errValidation)
|
||||
}
|
||||
|
||||
if len(r.Spec.InitImage) > 0 {
|
||||
return validatePluginImage(r.Spec.InitImage, "intel-idxd-config-initcontainer", dsaMinVersion)
|
||||
return validatePluginImage(r.Spec.InitImage, ref.expectedInitImage, &ref.expectedVersion)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -15,75 +15,33 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
|
||||
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers"
|
||||
)
|
||||
|
||||
var (
|
||||
// fpgadevicepluginlog is for logging in this package.
|
||||
fpgadevicepluginlog = logf.Log.WithName("fpgadeviceplugin-resource")
|
||||
|
||||
fpgaMinVersion = controllers.ImageMinVersion
|
||||
)
|
||||
|
||||
// SetupWebhookWithManager sets up a webhook for FpgaDevicePlugin custom resources.
|
||||
func (r *FpgaDevicePlugin) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewWebhookManagedBy(mgr).
|
||||
For(r).
|
||||
WithDefaulter(&commonDevicePluginDefaulter{
|
||||
defaultImage: "intel/intel-fpga-plugin:" + controllers.ImageMinVersion.String(),
|
||||
}).
|
||||
WithValidator(&commonDevicePluginValidator{
|
||||
expectedImage: "intel-fpga-plugin",
|
||||
expectedInitImage: "intel-fpga-initimage",
|
||||
expectedVersion: *controllers.ImageMinVersion,
|
||||
}).
|
||||
Complete()
|
||||
}
|
||||
|
||||
// +kubebuilder:webhook:path=/mutate-deviceplugin-intel-com-v1-fpgadeviceplugin,mutating=true,failurePolicy=fail,groups=deviceplugin.intel.com,resources=fpgadeviceplugins,verbs=create;update,versions=v1,name=mfpgadeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Defaulter = &FpgaDevicePlugin{}
|
||||
|
||||
// Default implements webhook.Defaulter so a webhook will be registered for the type.
|
||||
func (r *FpgaDevicePlugin) Default() {
|
||||
fpgadevicepluginlog.Info("default", "name", r.Name)
|
||||
|
||||
if len(r.Spec.Image) == 0 {
|
||||
r.Spec.Image = "intel/intel-fpga-plugin:" + fpgaMinVersion.String()
|
||||
}
|
||||
|
||||
if len(r.Spec.InitImage) == 0 {
|
||||
r.Spec.InitImage = "intel/intel-fpga-initcontainer:" + fpgaMinVersion.String()
|
||||
}
|
||||
}
|
||||
|
||||
// +kubebuilder:webhook:verbs=create;update,path=/validate-deviceplugin-intel-com-v1-fpgadeviceplugin,mutating=false,failurePolicy=fail,groups=deviceplugin.intel.com,resources=fpgadeviceplugins,versions=v1,name=vfpgadeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Validator = &FpgaDevicePlugin{}
|
||||
|
||||
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *FpgaDevicePlugin) ValidateCreate() (admission.Warnings, error) {
|
||||
fpgadevicepluginlog.Info("validate create", "name", r.Name)
|
||||
|
||||
return nil, r.validatePlugin()
|
||||
}
|
||||
|
||||
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *FpgaDevicePlugin) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
|
||||
fpgadevicepluginlog.Info("validate update", "name", r.Name)
|
||||
|
||||
return nil, r.validatePlugin()
|
||||
}
|
||||
|
||||
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *FpgaDevicePlugin) ValidateDelete() (admission.Warnings, error) {
|
||||
fpgadevicepluginlog.Info("validate delete", "name", r.Name)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *FpgaDevicePlugin) validatePlugin() error {
|
||||
if err := validatePluginImage(r.Spec.Image, "intel-fpga-plugin", fpgaMinVersion); err != nil {
|
||||
func (r *FpgaDevicePlugin) validatePlugin(ref *commonDevicePluginValidator) error {
|
||||
if err := validatePluginImage(r.Spec.Image, ref.expectedImage, &ref.expectedVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return validatePluginImage(r.Spec.InitImage, "intel-fpga-initcontainer", fpgaMinVersion)
|
||||
return validatePluginImage(r.Spec.InitImage, ref.expectedInitImage, &ref.expectedVersion)
|
||||
}
|
||||
|
@ -16,25 +16,15 @@ package v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
|
||||
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers"
|
||||
)
|
||||
|
||||
var (
|
||||
// gpudevicepluginlog is for logging in this package.
|
||||
gpudevicepluginlog = logf.Log.WithName("gpudeviceplugin-resource")
|
||||
|
||||
gpuMinVersion = controllers.ImageMinVersion
|
||||
)
|
||||
|
||||
var cli client.Client
|
||||
|
||||
// SetupWebhookWithManager sets up a webhook for GpuDevicePlugin custom resources.
|
||||
@ -43,53 +33,25 @@ func (r *GpuDevicePlugin) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
||||
|
||||
return ctrl.NewWebhookManagedBy(mgr).
|
||||
For(r).
|
||||
WithDefaulter(&commonDevicePluginDefaulter{
|
||||
defaultImage: "intel/intel-gpu-plugin:" + controllers.ImageMinVersion.String(),
|
||||
}).
|
||||
WithValidator(&commonDevicePluginValidator{
|
||||
expectedImage: "intel-gpu-plugin",
|
||||
expectedVersion: *controllers.ImageMinVersion,
|
||||
}).
|
||||
Complete()
|
||||
}
|
||||
|
||||
// +kubebuilder:webhook:path=/mutate-deviceplugin-intel-com-v1-gpudeviceplugin,mutating=true,failurePolicy=fail,groups=deviceplugin.intel.com,resources=gpudeviceplugins,verbs=create;update,versions=v1,name=mgpudeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Defaulter = &GpuDevicePlugin{}
|
||||
|
||||
// Default implements webhook.Defaulter so a webhook will be registered for the type.
|
||||
func (r *GpuDevicePlugin) Default() {
|
||||
gpudevicepluginlog.Info("default", "name", r.Name)
|
||||
|
||||
if len(r.Spec.Image) == 0 {
|
||||
r.Spec.Image = "intel/intel-gpu-plugin:" + gpuMinVersion.String()
|
||||
}
|
||||
}
|
||||
|
||||
// +kubebuilder:webhook:verbs=create;update,path=/validate-deviceplugin-intel-com-v1-gpudeviceplugin,mutating=false,failurePolicy=fail,groups=deviceplugin.intel.com,resources=gpudeviceplugins,versions=v1,name=vgpudeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Validator = &GpuDevicePlugin{}
|
||||
|
||||
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *GpuDevicePlugin) ValidateCreate() (admission.Warnings, error) {
|
||||
gpudevicepluginlog.Info("validate create", "name", r.Name)
|
||||
|
||||
return nil, r.validatePlugin()
|
||||
}
|
||||
|
||||
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *GpuDevicePlugin) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
|
||||
gpudevicepluginlog.Info("validate update", "name", r.Name)
|
||||
|
||||
return nil, r.validatePlugin()
|
||||
}
|
||||
|
||||
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *GpuDevicePlugin) ValidateDelete() (admission.Warnings, error) {
|
||||
gpudevicepluginlog.Info("validate delete", "name", r.Name)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *GpuDevicePlugin) crossCheckResourceManagement() bool {
|
||||
ctx := context.Background()
|
||||
func (r *GpuDevicePlugin) crossCheckResourceManagement(ctx context.Context) bool {
|
||||
log := logf.FromContext(ctx)
|
||||
gpuCrs := GpuDevicePluginList{}
|
||||
|
||||
if err := cli.List(ctx, &gpuCrs); err != nil {
|
||||
gpudevicepluginlog.Info("unable to list GPU CRs")
|
||||
log.Info("unable to list GPU CRs")
|
||||
|
||||
return false
|
||||
}
|
||||
@ -108,18 +70,18 @@ func (r *GpuDevicePlugin) crossCheckResourceManagement() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *GpuDevicePlugin) validatePlugin() error {
|
||||
func (r *GpuDevicePlugin) validatePlugin(ctx context.Context, ref *commonDevicePluginValidator) error {
|
||||
if r.Spec.SharedDevNum == 1 && r.Spec.PreferredAllocationPolicy != "none" {
|
||||
return errors.Errorf("PreferredAllocationPolicy is valid only when setting sharedDevNum > 1")
|
||||
return fmt.Errorf("%w: PreferredAllocationPolicy is valid only when setting sharedDevNum > 1", errValidation)
|
||||
}
|
||||
|
||||
if r.Spec.SharedDevNum == 1 && r.Spec.ResourceManager {
|
||||
return errors.Errorf("resourceManager is valid only when setting sharedDevNum > 1")
|
||||
return fmt.Errorf("%w: resourceManager is valid only when setting sharedDevNum > 1", errValidation)
|
||||
}
|
||||
|
||||
if !r.crossCheckResourceManagement() {
|
||||
return errors.Errorf("All GPU CRs must be with or without resource management")
|
||||
if !r.crossCheckResourceManagement(ctx) {
|
||||
return fmt.Errorf("%w: All GPU CRs must be with or without resource management", errValidation)
|
||||
}
|
||||
|
||||
return validatePluginImage(r.Spec.Image, "intel-gpu-plugin", gpuMinVersion)
|
||||
return validatePluginImage(r.Spec.Image, ref.expectedImage, &ref.expectedVersion)
|
||||
}
|
||||
|
@ -15,79 +15,42 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"fmt"
|
||||
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
|
||||
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers"
|
||||
)
|
||||
|
||||
var (
|
||||
// iaadevicepluginlog is for logging in this package.
|
||||
iaadevicepluginlog = logf.Log.WithName("iaadeviceplugin-resource")
|
||||
|
||||
iaaMinVersion = controllers.ImageMinVersion
|
||||
)
|
||||
|
||||
// SetupWebhookWithManager sets up a webhook for IaaDevicePlugin custom resources.
|
||||
func (r *IaaDevicePlugin) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewWebhookManagedBy(mgr).
|
||||
For(r).
|
||||
WithDefaulter(&commonDevicePluginDefaulter{
|
||||
defaultImage: "intel/intel-iaa-plugin:" + controllers.ImageMinVersion.String(),
|
||||
}).
|
||||
WithValidator(&commonDevicePluginValidator{
|
||||
expectedImage: "intel-iaa-plugin",
|
||||
expectedInitImage: "intel-idxd-config-initcontainer",
|
||||
expectedVersion: *controllers.ImageMinVersion,
|
||||
}).
|
||||
Complete()
|
||||
}
|
||||
|
||||
// +kubebuilder:webhook:path=/mutate-deviceplugin-intel-com-v1-iaadeviceplugin,mutating=true,failurePolicy=fail,groups=deviceplugin.intel.com,resources=iaadeviceplugins,verbs=create;update,versions=v1,name=miaadeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Defaulter = &IaaDevicePlugin{}
|
||||
|
||||
// Default implements webhook.Defaulter so a webhook will be registered for the type.
|
||||
func (r *IaaDevicePlugin) Default() {
|
||||
iaadevicepluginlog.Info("default", "name", r.Name)
|
||||
|
||||
if len(r.Spec.Image) == 0 {
|
||||
r.Spec.Image = "intel/intel-iaa-plugin:" + iaaMinVersion.String()
|
||||
}
|
||||
}
|
||||
|
||||
// +kubebuilder:webhook:verbs=create;update,path=/validate-deviceplugin-intel-com-v1-iaadeviceplugin,mutating=false,failurePolicy=fail,groups=deviceplugin.intel.com,resources=iaadeviceplugins,versions=v1,name=viaadeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Validator = &IaaDevicePlugin{}
|
||||
|
||||
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *IaaDevicePlugin) ValidateCreate() (admission.Warnings, error) {
|
||||
iaadevicepluginlog.Info("validate create", "name", r.Name)
|
||||
|
||||
return nil, r.validatePlugin()
|
||||
}
|
||||
|
||||
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *IaaDevicePlugin) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
|
||||
iaadevicepluginlog.Info("validate update", "name", r.Name)
|
||||
|
||||
return nil, r.validatePlugin()
|
||||
}
|
||||
|
||||
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *IaaDevicePlugin) ValidateDelete() (admission.Warnings, error) {
|
||||
iaadevicepluginlog.Info("validate delete", "name", r.Name)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *IaaDevicePlugin) validatePlugin() error {
|
||||
if err := validatePluginImage(r.Spec.Image, "intel-iaa-plugin", iaaMinVersion); err != nil {
|
||||
func (r *IaaDevicePlugin) validatePlugin(ref *commonDevicePluginValidator) error {
|
||||
if err := validatePluginImage(r.Spec.Image, ref.expectedImage, &ref.expectedVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(r.Spec.ProvisioningConfig) > 0 && len(r.Spec.InitImage) == 0 {
|
||||
return errors.Errorf("ProvisioningConfig is set with no InitImage")
|
||||
return fmt.Errorf("%w: ProvisioningConfig is set with no InitImage", errValidation)
|
||||
}
|
||||
|
||||
if len(r.Spec.InitImage) > 0 {
|
||||
return validatePluginImage(r.Spec.InitImage, "intel-idxd-config-initcontainer", iaaMinVersion)
|
||||
return validatePluginImage(r.Spec.InitImage, ref.expectedInitImage, &ref.expectedVersion)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -15,78 +15,41 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"fmt"
|
||||
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
|
||||
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers"
|
||||
)
|
||||
|
||||
var (
|
||||
// qatdevicepluginlog is for logging in this package.
|
||||
qatdevicepluginlog = logf.Log.WithName("qatdeviceplugin-resource")
|
||||
|
||||
qatMinVersion = controllers.ImageMinVersion
|
||||
)
|
||||
|
||||
// SetupWebhookWithManager sets up a webhook for QatDevicePlugin custom resources.
|
||||
func (r *QatDevicePlugin) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewWebhookManagedBy(mgr).
|
||||
For(r).
|
||||
WithDefaulter(&commonDevicePluginDefaulter{
|
||||
defaultImage: "intel/intel-qat-plugin:" + controllers.ImageMinVersion.String(),
|
||||
}).
|
||||
WithValidator(&commonDevicePluginValidator{
|
||||
expectedImage: "intel-qat-plugin",
|
||||
expectedInitImage: "intel-qat-initcontainer",
|
||||
expectedVersion: *controllers.ImageMinVersion,
|
||||
}).
|
||||
Complete()
|
||||
}
|
||||
|
||||
// +kubebuilder:webhook:path=/mutate-deviceplugin-intel-com-v1-qatdeviceplugin,mutating=true,failurePolicy=fail,groups=deviceplugin.intel.com,resources=qatdeviceplugins,verbs=create;update,versions=v1,name=mqatdeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Defaulter = &QatDevicePlugin{}
|
||||
|
||||
// Default implements webhook.Defaulter so a webhook will be registered for the type.
|
||||
func (r *QatDevicePlugin) Default() {
|
||||
qatdevicepluginlog.Info("default", "name", r.Name)
|
||||
|
||||
if len(r.Spec.Image) == 0 {
|
||||
r.Spec.Image = "intel/intel-qat-plugin:" + qatMinVersion.String()
|
||||
}
|
||||
}
|
||||
|
||||
// +kubebuilder:webhook:verbs=create;update,path=/validate-deviceplugin-intel-com-v1-qatdeviceplugin,mutating=false,failurePolicy=fail,groups=deviceplugin.intel.com,resources=qatdeviceplugins,versions=v1,name=vqatdeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Validator = &QatDevicePlugin{}
|
||||
|
||||
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *QatDevicePlugin) ValidateCreate() (admission.Warnings, error) {
|
||||
qatdevicepluginlog.Info("validate create", "name", r.Name)
|
||||
|
||||
return nil, r.validatePlugin()
|
||||
}
|
||||
|
||||
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *QatDevicePlugin) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
|
||||
qatdevicepluginlog.Info("validate update", "name", r.Name)
|
||||
|
||||
return nil, r.validatePlugin()
|
||||
}
|
||||
|
||||
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *QatDevicePlugin) ValidateDelete() (admission.Warnings, error) {
|
||||
qatdevicepluginlog.Info("validate delete", "name", r.Name)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *QatDevicePlugin) validatePlugin() error {
|
||||
func (r *QatDevicePlugin) validatePlugin(ref *commonDevicePluginValidator) error {
|
||||
if r.Spec.InitImage != "" {
|
||||
if err := validatePluginImage(r.Spec.InitImage, "intel-qat-initcontainer", qatMinVersion); err != nil {
|
||||
if err := validatePluginImage(r.Spec.InitImage, ref.expectedInitImage, &ref.expectedVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.Spec.ProvisioningConfig) > 0 {
|
||||
if len(r.Spec.InitImage) == 0 {
|
||||
return errors.Errorf("ProvisioningConfig is set with no InitImage")
|
||||
return fmt.Errorf("%w: ProvisioningConfig is set with no InitImage", errValidation)
|
||||
}
|
||||
|
||||
// check if 4xxxvf is enabled
|
||||
@ -104,9 +67,9 @@ func (r *QatDevicePlugin) validatePlugin() error {
|
||||
}
|
||||
|
||||
if !contains {
|
||||
return errors.Errorf("ProvisioningConfig is available only for 4xxx and 420xx devices")
|
||||
return fmt.Errorf("%w: ProvisioningConfig is available only for 4xxx and 420xx devices", errValidation)
|
||||
}
|
||||
}
|
||||
|
||||
return validatePluginImage(r.Spec.Image, "intel-qat-plugin", qatMinVersion)
|
||||
return validatePluginImage(r.Spec.Image, ref.expectedImage, &ref.expectedVersion)
|
||||
}
|
||||
|
@ -15,69 +15,31 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
|
||||
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers"
|
||||
)
|
||||
|
||||
var (
|
||||
// sgxdevicepluginlog is for logging in this package.
|
||||
sgxdevicepluginlog = logf.Log.WithName("sgxdeviceplugin-resource")
|
||||
|
||||
sgxMinVersion = controllers.ImageMinVersion
|
||||
)
|
||||
|
||||
// SetupWebhookWithManager sets up a webhook for SgxDevicePlugin custom resources.
|
||||
func (r *SgxDevicePlugin) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewWebhookManagedBy(mgr).
|
||||
For(r).
|
||||
WithDefaulter(&commonDevicePluginDefaulter{
|
||||
defaultImage: "intel/intel-sgx-plugin:" + controllers.ImageMinVersion.String(),
|
||||
}).
|
||||
WithValidator(&commonDevicePluginValidator{
|
||||
expectedImage: "intel-sgx-plugin",
|
||||
expectedInitImage: "intel-sgx-initcontainer",
|
||||
expectedVersion: *controllers.ImageMinVersion,
|
||||
}).
|
||||
Complete()
|
||||
}
|
||||
|
||||
// +kubebuilder:webhook:path=/mutate-deviceplugin-intel-com-v1-sgxdeviceplugin,mutating=true,failurePolicy=fail,groups=deviceplugin.intel.com,resources=sgxdeviceplugins,verbs=create;update,versions=v1,name=msgxdeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1,reinvocationPolicy=IfNeeded
|
||||
|
||||
var _ webhook.Defaulter = &SgxDevicePlugin{}
|
||||
|
||||
// Default implements webhook.Defaulter so a webhook will be registered for the type.
|
||||
func (r *SgxDevicePlugin) Default() {
|
||||
sgxdevicepluginlog.Info("default", "name", r.Name)
|
||||
|
||||
if len(r.Spec.Image) == 0 {
|
||||
r.Spec.Image = "intel/intel-sgx-plugin:" + sgxMinVersion.String()
|
||||
}
|
||||
}
|
||||
|
||||
// +kubebuilder:webhook:verbs=create;update,path=/validate-deviceplugin-intel-com-v1-sgxdeviceplugin,mutating=false,failurePolicy=fail,groups=deviceplugin.intel.com,resources=sgxdeviceplugins,versions=v1,name=vsgxdeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||
|
||||
var _ webhook.Validator = &SgxDevicePlugin{}
|
||||
|
||||
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *SgxDevicePlugin) ValidateCreate() (admission.Warnings, error) {
|
||||
sgxdevicepluginlog.Info("validate create", "name", r.Name)
|
||||
|
||||
return nil, r.validatePlugin()
|
||||
}
|
||||
|
||||
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *SgxDevicePlugin) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
|
||||
sgxdevicepluginlog.Info("validate update", "name", r.Name)
|
||||
|
||||
return nil, r.validatePlugin()
|
||||
}
|
||||
|
||||
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
|
||||
func (r *SgxDevicePlugin) ValidateDelete() (admission.Warnings, error) {
|
||||
sgxdevicepluginlog.Info("validate delete", "name", r.Name)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *SgxDevicePlugin) validatePlugin() error {
|
||||
if err := validatePluginImage(r.Spec.Image, "intel-sgx-plugin", sgxMinVersion); err != nil {
|
||||
func (r *SgxDevicePlugin) validatePlugin(ref *commonDevicePluginValidator) error {
|
||||
if err := validatePluginImage(r.Spec.Image, ref.expectedImage, &ref.expectedVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -85,5 +47,5 @@ func (r *SgxDevicePlugin) validatePlugin() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
return validatePluginImage(r.Spec.InitImage, "intel-sgx-initcontainer", sgxMinVersion)
|
||||
return validatePluginImage(r.Spec.InitImage, ref.expectedInitImage, &ref.expectedVersion)
|
||||
}
|
||||
|
@ -15,18 +15,139 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
)
|
||||
|
||||
const sha256RE = "@sha256:[0-9a-f]{64}$"
|
||||
|
||||
var errObjType = errors.New("invalid object")
|
||||
var errValidation = errors.New("invalid resource")
|
||||
|
||||
// common functions for webhooks
|
||||
|
||||
type commonDevicePluginDefaulter struct {
|
||||
defaultImage string
|
||||
}
|
||||
|
||||
var _ admission.CustomDefaulter = &commonDevicePluginDefaulter{}
|
||||
|
||||
type commonDevicePluginValidator struct {
|
||||
expectedImage string
|
||||
expectedInitImage string
|
||||
expectedVersion version.Version
|
||||
}
|
||||
|
||||
var _ admission.CustomValidator = &commonDevicePluginValidator{}
|
||||
|
||||
// Default implements admission.CustomDefaulter so a webhook will be registered for the type.
|
||||
func (r *commonDevicePluginDefaulter) Default(ctx context.Context, obj runtime.Object) error {
|
||||
logf.FromContext(ctx).Info("default")
|
||||
|
||||
// type switches can have only one type in a case so the same repeats for
|
||||
// all xDevicePlugin types.
|
||||
// TODO: implement receivers if more complex logic is needed.
|
||||
switch v := obj.(type) {
|
||||
case *DlbDevicePlugin:
|
||||
if len(v.Spec.Image) == 0 {
|
||||
v.Spec.Image = r.defaultImage
|
||||
}
|
||||
case *DsaDevicePlugin:
|
||||
if len(v.Spec.Image) == 0 {
|
||||
v.Spec.Image = r.defaultImage
|
||||
}
|
||||
case *FpgaDevicePlugin:
|
||||
if len(v.Spec.Image) == 0 {
|
||||
v.Spec.Image = r.defaultImage
|
||||
}
|
||||
case *GpuDevicePlugin:
|
||||
if len(v.Spec.Image) == 0 {
|
||||
v.Spec.Image = r.defaultImage
|
||||
}
|
||||
case *IaaDevicePlugin:
|
||||
if len(v.Spec.Image) == 0 {
|
||||
v.Spec.Image = r.defaultImage
|
||||
}
|
||||
case *QatDevicePlugin:
|
||||
if len(v.Spec.Image) == 0 {
|
||||
v.Spec.Image = r.defaultImage
|
||||
}
|
||||
case *SgxDevicePlugin:
|
||||
if len(v.Spec.Image) == 0 {
|
||||
v.Spec.Image = r.defaultImage
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("%w: expected an xDevicePlugin object but got %T", errObjType, obj)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateCreate implements admission.CustomValidator so a webhook will be registered for the type.
|
||||
func (r *commonDevicePluginValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
|
||||
logf.FromContext(ctx).Info("validate create")
|
||||
|
||||
switch v := obj.(type) {
|
||||
case *DlbDevicePlugin:
|
||||
return nil, v.validatePlugin(r)
|
||||
case *DsaDevicePlugin:
|
||||
return nil, v.validatePlugin(r)
|
||||
case *GpuDevicePlugin:
|
||||
return nil, v.validatePlugin(ctx, r)
|
||||
case *FpgaDevicePlugin:
|
||||
return nil, v.validatePlugin(r)
|
||||
case *IaaDevicePlugin:
|
||||
return nil, v.validatePlugin(r)
|
||||
case *QatDevicePlugin:
|
||||
return nil, v.validatePlugin(r)
|
||||
case *SgxDevicePlugin:
|
||||
return nil, v.validatePlugin(r)
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: expected an xDevicePlugin object but got %T", errObjType, obj)
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateUpdate implements admission.CustomValidator so a webhook will be registered for the type.
|
||||
func (r *commonDevicePluginValidator) ValidateUpdate(ctx context.Context, oldObj runtime.Object, newObj runtime.Object) (admission.Warnings, error) {
|
||||
logf.FromContext(ctx).Info("validate update")
|
||||
|
||||
switch v := oldObj.(type) {
|
||||
case *DlbDevicePlugin:
|
||||
return nil, v.validatePlugin(r)
|
||||
case *DsaDevicePlugin:
|
||||
return nil, v.validatePlugin(r)
|
||||
case *GpuDevicePlugin:
|
||||
return nil, v.validatePlugin(ctx, r)
|
||||
case *FpgaDevicePlugin:
|
||||
return nil, v.validatePlugin(r)
|
||||
case *IaaDevicePlugin:
|
||||
return nil, v.validatePlugin(r)
|
||||
case *QatDevicePlugin:
|
||||
return nil, v.validatePlugin(r)
|
||||
case *SgxDevicePlugin:
|
||||
return nil, v.validatePlugin(r)
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: expected an xDevicePlugin object but got %T", errObjType, oldObj)
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateDelete implements admission.CustomValidator so a webhook will be registered for the type.
|
||||
func (r *commonDevicePluginValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
|
||||
logf.FromContext(ctx).Info("validate delete")
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func validatePluginImage(image, expectedImageName string, expectedMinVersion *version.Version) error {
|
||||
imageRe := regexp.MustCompile(expectedImageName + sha256RE)
|
||||
if imageRe.MatchString(image) {
|
||||
@ -36,7 +157,7 @@ func validatePluginImage(image, expectedImageName string, expectedMinVersion *ve
|
||||
// Ignore registry, vendor and extract the image name with the tag
|
||||
parts := strings.SplitN(filepath.Base(image), ":", 2)
|
||||
if len(parts) != 2 {
|
||||
return errors.Errorf("incorrect image field %q", image)
|
||||
return fmt.Errorf("%w: incorrect image field %q", errValidation, image)
|
||||
}
|
||||
|
||||
imageName := parts[0]
|
||||
@ -44,16 +165,16 @@ func validatePluginImage(image, expectedImageName string, expectedMinVersion *ve
|
||||
|
||||
// If user provided faulty SHA digest, the image name may include @sha256 suffix so strip it.
|
||||
if strings.TrimSuffix(imageName, "@sha256") != expectedImageName {
|
||||
return errors.Errorf("incorrect image name %q. Make sure you use '<vendor>/%s'", imageName, expectedImageName)
|
||||
return fmt.Errorf("%w: incorrect image name %q. Make sure you use '<vendor>/%s'", errValidation, imageName, expectedImageName)
|
||||
}
|
||||
|
||||
ver, err := version.ParseSemantic(versionStr)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to parse version %q. Make sure it's either valid SHA digest or semver tag", versionStr)
|
||||
return fmt.Errorf("%w: %w: Make sure it's either valid SHA digest or semver tag", errValidation, err)
|
||||
}
|
||||
|
||||
if !ver.AtLeast(expectedMinVersion) {
|
||||
return errors.Errorf("version %q is too low. Should be at least %q", ver, expectedMinVersion)
|
||||
return fmt.Errorf("%w: version %q is too low. Should be at least %q", errValidation, ver, expectedMinVersion)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
Loading…
Reference in New Issue
Block a user