Skip to content

Commit

Permalink
fix(): New UTs for SliceValidationWebhook
Browse files Browse the repository at this point in the history
Merge pull request #202 from kubeslice/feature-no-comm-unit-tests
  • Loading branch information
priyank-upadhyay authored Apr 18, 2024
2 parents 896ea15 + fd84e2e commit 97566d4
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 6 deletions.
1 change: 0 additions & 1 deletion service/slice_config_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ func (s *SliceConfigService) ReconcileSliceConfig(ctx context.Context, req ctrl.
ownershipLabel := util.GetOwnerLabel(completeResourceName)

if sliceConfig.Spec.OverlayNetworkDeploymentMode == v1alpha1.NONET {
// Try Cleanup
err = s.ms.CreateMinimalWorkerSliceConfigForNoNetworkSlice(ctx, sliceConfig.Spec.Clusters, req.Namespace, ownershipLabel, sliceConfig.Name)
return ctrl.Result{}, err
}
Expand Down
34 changes: 34 additions & 0 deletions service/slice_config_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func TestSliceConfigSuite(t *testing.T) {

var SliceConfigTestBed = map[string]func(*testing.T){
"SliceConfig_ReconciliationCompleteHappyCase": SliceConfigReconciliationCompleteHappyCase,
"SliceConfigReconciliationNoNetCompleteHappyCase": SliceConfigReconciliationNoNetCompleteHappyCase,
"SliceConfig_GetObjectErrorOtherThanNotFound": SliceConfigGetObjectErrorOtherThanNotFound,
"SliceConfig_GetObjectErrorNotFound": SliceConfigGetObjectErrorNotFound,
"SliceConfig_DeleteTheObjectHappyCase": SliceConfigDeleteTheObjectHappyCase,
Expand Down Expand Up @@ -131,6 +132,39 @@ func SliceConfigReconciliationCompleteHappyCase(t *testing.T) {
mMock.AssertExpectations(t)
}

func SliceConfigReconciliationNoNetCompleteHappyCase(t *testing.T) {
_, workerSliceConfigMock, _, _, _, clientMock, sliceConfig, ctx, sliceConfigService, requestObj, mMock := setupSliceConfigTest("slice_config", "namespace")
mMock.On("WithProject", mock.AnythingOfType("string")).Return(&metrics.MetricRecorder{}).Once()
clientMock.On("Get", ctx, requestObj.NamespacedName, sliceConfig).Return(nil).Run(func(args mock.Arguments) {
arg := args.Get(2).(*controllerv1alpha1.SliceConfig)
arg.Spec.OverlayNetworkDeploymentMode = controllerv1alpha1.NONET
}).Once()
clientMock.On("Update", ctx, mock.Anything).Return(nil).Once()
clientMock.On("Get", ctx, mock.Anything, mock.Anything).Return(nil).Once()
namespace := corev1.Namespace{}
clientMock.On("Get", ctx, mock.Anything, &namespace).Return(nil).Run(func(args mock.Arguments) {
arg := args.Get(2).(*corev1.Namespace)
if arg.Labels == nil {
arg.Labels = make(map[string]string)
}
arg.Name = requestObj.Namespace
arg.Labels[util.LabelName] = fmt.Sprintf(util.LabelValue, "Project", requestObj.Namespace)
}).Once()
clientMock.On("Get", ctx, mock.Anything, mock.Anything).Return(nil)

workerSliceConfigMock.On("CreateMinimalWorkerSliceConfigForNoNetworkSlice", ctx, mock.Anything, requestObj.Namespace, mock.Anything, mock.Anything).Return(nil).Once()

result, err := sliceConfigService.ReconcileSliceConfig(ctx, requestObj)
expectedResult := ctrl.Result{}
require.NoError(t, nil)
require.Equal(t, expectedResult, result)
require.Nil(t, err)
require.False(t, result.Requeue)
clientMock.AssertExpectations(t)
workerSliceConfigMock.AssertExpectations(t)
mMock.AssertExpectations(t)
}

func SliceConfigGetObjectErrorOtherThanNotFound(t *testing.T) {
_, _, _, _, _, clientMock, sliceConfig, ctx, sliceConfigService, requestObj, _ := setupSliceConfigTest("slice_config", "namespace")
err1 := errors.New("internal_error")
Expand Down
6 changes: 1 addition & 5 deletions service/slice_config_webhook_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,8 @@ func ValidateSliceConfigCreate(ctx context.Context, sliceConfig *controllerv1alp
func ValidateSliceConfigUpdate(ctx context.Context, sliceConfig *controllerv1alpha1.SliceConfig, old runtime.Object) error {
oldSc := old.(*controllerv1alpha1.SliceConfig)
isNetworkTransitioning := sliceConfig.Spec.OverlayNetworkDeploymentMode != oldSc.Spec.OverlayNetworkDeploymentMode
// Do NOT allow transition from overlay network to nonet mode
// And multi-network to single-network mode
isTransitioningToNonet := isNetworkTransitioning && sliceConfig.Spec.OverlayNetworkDeploymentMode == controllerv1alpha1.NONET
isTransitioningToSingleNetFromMultiNetwork := isNetworkTransitioning && oldSc.Spec.OverlayNetworkDeploymentMode == controllerv1alpha1.MULTINET && sliceConfig.Spec.OverlayNetworkDeploymentMode == controllerv1alpha1.SINGLENET

if isTransitioningToNonet || isTransitioningToSingleNetFromMultiNetwork {
if isNetworkTransitioning && oldSc.Spec.OverlayNetworkDeploymentMode != controllerv1alpha1.NONET {
return apierrors.NewInvalid(schema.GroupKind{Group: apiGroupKubeSliceControllers, Kind: "SliceConfig"}, sliceConfig.Name, field.ErrorList{
field.Forbidden(field.NewPath("Spec").Child("OverlayNetworkDeploymentMode"), fmt.Sprintf("Slice cannot be transitioned to %v mode from %v mode", sliceConfig.Spec.OverlayNetworkDeploymentMode, oldSc.Spec.OverlayNetworkDeploymentMode)),
})
Expand Down
151 changes: 151 additions & 0 deletions service/slice_config_webhook_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2150,6 +2150,157 @@ func TestValidateRotationInterval_Change_Decreased(t *testing.T) {
require.Nil(t, err)
require.Equal(t, &expectedResp, gotResp.Spec.CertificateExpiryTime)
}

func TestValidateSliceConfigCreate_NoNetHappyCase(t *testing.T) {
name := "slice_config"
namespace := "random"
clientMock, sliceConfig, ctx := setupSliceConfigWebhookValidationTest(name, namespace)
clientMock.On("Get", ctx, client.ObjectKey{
Name: namespace,
}, &corev1.Namespace{}).Return(nil).Run(func(args mock.Arguments) {
arg := args.Get(2).(*corev1.Namespace)
if arg.Labels == nil {
arg.Labels = make(map[string]string)
}
arg.Name = namespace
arg.Labels[util.LabelName] = fmt.Sprintf(util.LabelValue, "Project", namespace)
}).Once()
sliceConfig.Spec.OverlayNetworkDeploymentMode = controllerv1alpha1.NONET
sliceConfig.Spec.Clusters = []string{"cluster-1", "cluster-2"}
if sliceConfig.Spec.NamespaceIsolationProfile.ApplicationNamespaces == nil {
sliceConfig.Spec.NamespaceIsolationProfile.ApplicationNamespaces = make([]controllerv1alpha1.SliceNamespaceSelection, 1)
}
if sliceConfig.Spec.NamespaceIsolationProfile.ApplicationNamespaces[0].Clusters == nil {
sliceConfig.Spec.NamespaceIsolationProfile.ApplicationNamespaces[0].Clusters = make([]string, 1)
}
sliceConfig.Spec.NamespaceIsolationProfile.ApplicationNamespaces[0].Namespace = "randomNamespace"
sliceConfig.Spec.NamespaceIsolationProfile.ApplicationNamespaces[0].Clusters = []string{"cluster-1"}
sliceConfig.Spec.MaxClusters = 2
clientMock.On("Get", ctx, client.ObjectKey{
Name: sliceConfig.Spec.Clusters[0],
Namespace: namespace,
}, &controllerv1alpha1.Cluster{}).Return(nil).Run(func(args mock.Arguments) {
arg := args.Get(2).(*controllerv1alpha1.Cluster)
arg.Spec.NodeIPs = []string{"10.10.1.1"}
arg.Status.RegistrationStatus = controllerv1alpha1.RegistrationStatusRegistered
arg.Status.ClusterHealth = &controllerv1alpha1.ClusterHealth{
ClusterHealthStatus: controllerv1alpha1.ClusterHealthStatusNormal,
}
arg.Status.NetworkPresent = false
}).Once()
clientMock.On("Get", ctx, client.ObjectKey{
Name: sliceConfig.Spec.Clusters[1],
Namespace: namespace,
}, &controllerv1alpha1.Cluster{}).Return(nil).Run(func(args mock.Arguments) {
arg := args.Get(2).(*controllerv1alpha1.Cluster)
arg.Spec.NodeIPs = []string{"10.10.1.1"}
arg.Status.RegistrationStatus = controllerv1alpha1.RegistrationStatusRegistered
arg.Status.ClusterHealth = &controllerv1alpha1.ClusterHealth{
ClusterHealthStatus: controllerv1alpha1.ClusterHealthStatusNormal,
}
arg.Status.NetworkPresent = false
}).Once()
clientMock.On("Get", ctx, client.ObjectKey{
Name: sliceConfig.Spec.Clusters[0],
Namespace: namespace,
}, &controllerv1alpha1.Cluster{}).Return(nil).Run(func(args mock.Arguments) {
arg := args.Get(2).(*controllerv1alpha1.Cluster)
arg.Spec.NodeIPs = []string{"10.10.1.1"}
arg.Status.RegistrationStatus = controllerv1alpha1.RegistrationStatusRegistered
arg.Status.ClusterHealth = &controllerv1alpha1.ClusterHealth{
ClusterHealthStatus: controllerv1alpha1.ClusterHealthStatusNormal,
}
arg.Status.NetworkPresent = false
}).Once()

err := ValidateSliceConfigCreate(ctx, sliceConfig)
require.Nil(t, err)
clientMock.AssertExpectations(t)
}

func TestValidateSliceConfigCreate_SingleNetWithNoNetCLustersError(t *testing.T) {
name := "slice_config"
namespace := "random"
clientMock, sliceConfig, ctx := setupSliceConfigWebhookValidationTest(name, namespace)
clientMock.On("Get", ctx, client.ObjectKey{
Name: namespace,
}, &corev1.Namespace{}).Return(nil).Run(func(args mock.Arguments) {
arg := args.Get(2).(*corev1.Namespace)
if arg.Labels == nil {
arg.Labels = make(map[string]string)
}
arg.Name = namespace
arg.Labels[util.LabelName] = fmt.Sprintf(util.LabelValue, "Project", namespace)
}).Once()
sliceConfig.Spec.OverlayNetworkDeploymentMode = controllerv1alpha1.SINGLENET
sliceConfig.Spec.Clusters = []string{"cluster-1"}
if sliceConfig.Spec.NamespaceIsolationProfile.ApplicationNamespaces == nil {
sliceConfig.Spec.NamespaceIsolationProfile.ApplicationNamespaces = make([]controllerv1alpha1.SliceNamespaceSelection, 1)
}
if sliceConfig.Spec.NamespaceIsolationProfile.ApplicationNamespaces[0].Clusters == nil {
sliceConfig.Spec.NamespaceIsolationProfile.ApplicationNamespaces[0].Clusters = make([]string, 1)
}
sliceConfig.Spec.NamespaceIsolationProfile.ApplicationNamespaces[0].Namespace = "randomNamespace"
sliceConfig.Spec.NamespaceIsolationProfile.ApplicationNamespaces[0].Clusters = []string{"cluster-1"}
sliceConfig.Spec.MaxClusters = 2
clientMock.On("Get", ctx, client.ObjectKey{
Name: sliceConfig.Spec.Clusters[0],
Namespace: namespace,
}, &controllerv1alpha1.Cluster{}).Return(nil).Run(func(args mock.Arguments) {
arg := args.Get(2).(*controllerv1alpha1.Cluster)
arg.Spec.NodeIPs = []string{"10.10.1.1"}
arg.Status.RegistrationStatus = controllerv1alpha1.RegistrationStatusRegistered
arg.Status.ClusterHealth = &controllerv1alpha1.ClusterHealth{
ClusterHealthStatus: controllerv1alpha1.ClusterHealthStatusNormal,
}
arg.Status.NetworkPresent = false
}).Once()

err := ValidateSliceConfigCreate(ctx, sliceConfig)
require.NotNil(t, err)
require.Contains(t, err.Error(), "cluster network is not present")
clientMock.AssertExpectations(t)
}
func TestValidateSliceConfigUpdate_SingleToNoNetError(t *testing.T) {
oldSliceConfig := &controllerv1alpha1.SliceConfig{}
oldSliceConfig.Spec.OverlayNetworkDeploymentMode = controllerv1alpha1.SINGLENET
clientMock, newSliceConfig, ctx := setupSliceConfigWebhookValidationTest("slice_config", "random")
newSliceConfig.Spec.OverlayNetworkDeploymentMode = controllerv1alpha1.NONET

err := ValidateSliceConfigUpdate(ctx, newSliceConfig, runtime.Object(oldSliceConfig))
require.NotNil(t, err)
require.Contains(t, err.Error(), "Forbidden: Slice cannot be transitioned to no-network mode from single-network mode")
clientMock.AssertExpectations(t)

}

func TestValidateClustersOnUpdate_NetworkSliceOnNoNetClustersError(t *testing.T) {
oldSliceConfig := &controllerv1alpha1.SliceConfig{}
oldSliceConfig.Spec.OverlayNetworkDeploymentMode = controllerv1alpha1.SINGLENET
clientMock, newSliceConfig, ctx := setupSliceConfigWebhookValidationTest("slice_config", "random")
newSliceConfig.Spec.OverlayNetworkDeploymentMode = controllerv1alpha1.SINGLENET
newSliceConfig.Spec.Clusters = []string{"cluster-1"}

clientMock.On("Get", ctx, client.ObjectKey{
Name: newSliceConfig.Spec.Clusters[0],
Namespace: "random",
}, &controllerv1alpha1.Cluster{}).Return(nil).Run(func(args mock.Arguments) {
arg := args.Get(2).(*controllerv1alpha1.Cluster)
arg.Status.NodeIPs = []string{"1.1.1.1"}
arg.Status.NetworkPresent = false
arg.Status.RegistrationStatus = controllerv1alpha1.RegistrationStatusRegistered
arg.Status.ClusterHealth = &controllerv1alpha1.ClusterHealth{
ClusterHealthStatus: controllerv1alpha1.ClusterHealthStatusNormal,
}
}).Twice()

err := validateClustersOnUpdate(ctx, newSliceConfig, oldSliceConfig)
require.NotNil(t, err)
require.Contains(t, err.Error(), "cluster network is not present")
clientMock.AssertExpectations(t)

}

func setupSliceConfigWebhookValidationTest(name string, namespace string) (*utilMock.Client, *controllerv1alpha1.SliceConfig, context.Context) {
clientMock := &utilMock.Client{}
sliceConfig := &controllerv1alpha1.SliceConfig{
Expand Down

0 comments on commit 97566d4

Please sign in to comment.