mirror of
https://github.com/kubevirt/containerized-data-importer.git
synced 2025-06-03 06:30:22 +00:00

Switch admissionregistration.k8s.io/v1beta, apiregistration.k8s.io/v1beta1 to v1 as they are deprecated and will be removed from k8s-1.22. apiextensions.k8s.io/v1beta1 was updated to v1 by https://github.com/kubevirt/containerized-data-importer/pull/1307. Signed-off-by: Alex Kalenyuk <akalenyu@redhat.com>
112 lines
3.4 KiB
Go
112 lines
3.4 KiB
Go
/*
|
|
* This file is part of the CDI project
|
|
*
|
|
* 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.
|
|
*
|
|
* Copyright 2020 Red Hat, Inc.
|
|
*
|
|
*/
|
|
|
|
package webhooks
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
admissionv1 "k8s.io/api/admission/v1"
|
|
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
|
"k8s.io/apimachinery/pkg/api/errors"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/kubernetes"
|
|
"k8s.io/klog/v2"
|
|
|
|
cdiv1 "kubevirt.io/containerized-data-importer/pkg/apis/core/v1beta1"
|
|
cdiclient "kubevirt.io/containerized-data-importer/pkg/client/clientset/versioned"
|
|
)
|
|
|
|
type objectTransferValidatingWebhook struct {
|
|
k8sClient kubernetes.Interface
|
|
cdiClient cdiclient.Interface
|
|
}
|
|
|
|
func (wh *objectTransferValidatingWebhook) Admit(ar admissionv1.AdmissionReview) *admissionv1.AdmissionResponse {
|
|
klog.V(3).Infof("Got AdmissionReview %+v", ar)
|
|
|
|
if ar.Request.Resource.Group != cdiv1.CDIGroupVersionKind.Group || ar.Request.Resource.Resource != "objecttransfers" {
|
|
klog.V(3).Infof("Got unexpected resource type %s", ar.Request.Resource.Resource)
|
|
return toAdmissionResponseError(fmt.Errorf("unexpected resource: %s", ar.Request.Resource.Resource))
|
|
}
|
|
|
|
switch ar.Request.Operation {
|
|
case admissionv1.Create:
|
|
case admissionv1.Update:
|
|
default:
|
|
klog.V(3).Infof("Got unexpected operation type %s", ar.Request.Operation)
|
|
return allowedAdmissionResponse()
|
|
}
|
|
|
|
obj := &cdiv1.ObjectTransfer{}
|
|
if err := json.Unmarshal(ar.Request.Object.Raw, obj); err != nil {
|
|
return toAdmissionResponseError(err)
|
|
}
|
|
|
|
if ar.Request.Operation == admissionv1.Update {
|
|
oldObj := &cdiv1.ObjectTransfer{}
|
|
if err := json.Unmarshal(ar.Request.OldObject.Raw, oldObj); err != nil {
|
|
return toAdmissionResponseError(err)
|
|
}
|
|
|
|
if !apiequality.Semantic.DeepEqual(obj.Spec, oldObj.Spec) {
|
|
return toAdmissionResponseError(fmt.Errorf("ObjectTransfer spec is immutable"))
|
|
}
|
|
|
|
return allowedAdmissionResponse()
|
|
}
|
|
|
|
if obj.Spec.Target.Namespace == nil && obj.Spec.Target.Name == nil {
|
|
return toAdmissionResponseError(fmt.Errorf("Target namespace and/or target name must be supplied"))
|
|
}
|
|
|
|
var err error
|
|
ns := obj.Spec.Source.Namespace
|
|
name := obj.Spec.Source.Name
|
|
|
|
if obj.Spec.Target.Namespace != nil {
|
|
ns = *obj.Spec.Target.Namespace
|
|
}
|
|
|
|
if obj.Spec.Target.Name != nil {
|
|
name = *obj.Spec.Target.Name
|
|
}
|
|
|
|
switch obj.Spec.Source.Kind {
|
|
case "DataVolume":
|
|
_, err = wh.cdiClient.CdiV1beta1().DataVolumes(ns).Get(context.TODO(), name, metav1.GetOptions{})
|
|
case "PersistentVolumeClaim":
|
|
_, err = wh.k8sClient.CoreV1().PersistentVolumeClaims(ns).Get(context.TODO(), name, metav1.GetOptions{})
|
|
default:
|
|
return toAdmissionResponseError(fmt.Errorf("Unsupported kind %q", obj.Spec.Source.Kind))
|
|
}
|
|
|
|
if err == nil {
|
|
return toAdmissionResponseError(fmt.Errorf("ObjectTransfer target \"%s/%s\" already exists", ns, name))
|
|
}
|
|
|
|
if !errors.IsNotFound(err) {
|
|
return toAdmissionResponseError(err)
|
|
}
|
|
|
|
return allowedAdmissionResponse()
|
|
}
|