diff --git a/build/yaml/crd/vpc/crd.nsx.vmware.com_subnetports.yaml b/build/yaml/crd/vpc/crd.nsx.vmware.com_subnetports.yaml index 3737aa586..90ca69041 100644 --- a/build/yaml/crd/vpc/crd.nsx.vmware.com_subnetports.yaml +++ b/build/yaml/crd/vpc/crd.nsx.vmware.com_subnetports.yaml @@ -59,6 +59,10 @@ spec: description: SubnetSet defines the parent SubnetSet name of the SubnetPort. type: string type: object + x-kubernetes-validations: + - message: Only one of subnet or subnetSet can be specified + rule: has(self.subnet) && !has(self.subnetSet) || !has(self.subnet) + && has(self.subnetSet) status: description: SubnetPortStatus defines the observed state of SubnetPort. properties: diff --git a/pkg/apis/vpc/v1alpha1/subnetport_types.go b/pkg/apis/vpc/v1alpha1/subnetport_types.go index 34b592f9c..685ff3f56 100644 --- a/pkg/apis/vpc/v1alpha1/subnetport_types.go +++ b/pkg/apis/vpc/v1alpha1/subnetport_types.go @@ -7,6 +7,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +// +kubebuilder:validation:XValidation:rule="has(self.subnet) && !has(self.subnetSet) || !has(self.subnet) && has(self.subnetSet)",message="Only one of subnet or subnetSet can be specified" // SubnetPortSpec defines the desired state of SubnetPort. type SubnetPortSpec struct { // Subnet defines the parent Subnet name of the SubnetPort. diff --git a/pkg/controllers/subnetport/subnetport_controller.go b/pkg/controllers/subnetport/subnetport_controller.go index f4bc256b2..cc5190513 100644 --- a/pkg/controllers/subnetport/subnetport_controller.go +++ b/pkg/controllers/subnetport/subnetport_controller.go @@ -5,7 +5,6 @@ package subnetport import ( "context" - "errors" "fmt" "os" "reflect" @@ -79,12 +78,6 @@ func (r *SubnetPortReconciler) Reconcile(ctx context.Context, req ctrl.Request) log.Error(err, "unable to fetch SubnetPort CR", "SubnetPort", req.NamespacedName) return common.ResultRequeue, err } - if len(subnetPort.Spec.SubnetSet) > 0 && len(subnetPort.Spec.Subnet) > 0 { - err := errors.New("subnet and subnetset should not be configured at the same time") - log.Error(err, "failed to get subnet/subnetset of the subnetport", "subnetport", req.NamespacedName) - updateFail(r, ctx, subnetPort, &err) - return common.ResultNormal, err - } if subnetPort.ObjectMeta.DeletionTimestamp.IsZero() { metrics.CounterInc(r.SubnetPortService.NSXConfig, metrics.ControllerUpdateTotal, MetricResTypeSubnetPort) diff --git a/pkg/controllers/subnetport/subnetport_controller_test.go b/pkg/controllers/subnetport/subnetport_controller_test.go index e389902ba..c3a4af547 100644 --- a/pkg/controllers/subnetport/subnetport_controller_test.go +++ b/pkg/controllers/subnetport/subnetport_controller_test.go @@ -124,24 +124,12 @@ func TestSubnetPortReconciler_Reconcile(t *testing.T) { _, ret = r.Reconcile(ctx, req) assert.Equal(t, err, ret) - // both subnet and subnetset are configured + // CheckAndGetSubnetPathForSubnetPort fails sp := &v1alpha1.SubnetPort{} - k8sClient.EXPECT().Get(ctx, gomock.Any(), sp).Return(nil).Do( - func(_ context.Context, _ client.ObjectKey, obj client.Object, option ...client.GetOption) error { - v1sp := obj.(*v1alpha1.SubnetPort) - v1sp.Spec.Subnet = "subnet1" - v1sp.Spec.SubnetSet = "subnetset2" - return nil - }) patchesUpdateFail := gomonkey.ApplyFunc(updateFail, func(r *SubnetPortReconciler, c context.Context, o *v1alpha1.SubnetPort, e *error) { }) defer patchesUpdateFail.Reset() - err = errors.New("subnet and subnetset should not be configured at the same time") - _, ret = r.Reconcile(ctx, req) - assert.Equal(t, err, ret) - - // CheckAndGetSubnetPathForSubnetPort fails err = errors.New("CheckAndGetSubnetPathForSubnetPort failed") patchesCheckAndGetSubnetPathForSubnetPort := gomonkey.ApplyFunc((*SubnetPortReconciler).CheckAndGetSubnetPathForSubnetPort, func(r *SubnetPortReconciler, ctx context.Context, obj *v1alpha1.SubnetPort) (bool, string, error) {