github.com/openebs/node-disk-manager@v1.9.1-0.20230225014141-4531f06ffa1e/pkg/controllers/blockdeviceclaim/blockdeviceclaim_controller_test.go (about)

     1  /*
     2  Copyright 2019 The OpenEBS Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package blockdeviceclaim
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/openebs/node-disk-manager/db/kubernetes"
    26  
    27  	openebsv1alpha1 "github.com/openebs/node-disk-manager/api/v1alpha1"
    28  	ndm "github.com/openebs/node-disk-manager/cmd/ndm_daemonset/controller"
    29  
    30  	"github.com/stretchr/testify/assert"
    31  	corev1 "k8s.io/api/core/v1"
    32  	"k8s.io/apimachinery/pkg/api/errors"
    33  	"k8s.io/apimachinery/pkg/api/resource"
    34  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    35  	"k8s.io/apimachinery/pkg/runtime"
    36  	"k8s.io/apimachinery/pkg/types"
    37  	"k8s.io/client-go/kubernetes/scheme"
    38  	"k8s.io/client-go/tools/record"
    39  	"sigs.k8s.io/controller-runtime/pkg/client"
    40  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    41  	logf "sigs.k8s.io/controller-runtime/pkg/log"
    42  	"sigs.k8s.io/controller-runtime/pkg/log/zap"
    43  	"sigs.k8s.io/controller-runtime/pkg/reconcile"
    44  )
    45  
    46  var (
    47  	fakeHostName                   = "fake-hostname"
    48  	diskName                       = "disk-example"
    49  	deviceName                     = "blockdevice-example"
    50  	blockDeviceClaimName           = "blockdeviceclaim-example"
    51  	blockDeviceClaimUID  types.UID = "blockDeviceClaim-example-UID"
    52  	namespace                      = ""
    53  	capacity             uint64    = 1024000
    54  	claimCapacity                  = resource.MustParse("1024000")
    55  	fakeRecorder                   = record.NewFakeRecorder(50)
    56  )
    57  
    58  // TestBlockDeviceClaimController runs ReconcileBlockDeviceClaim.Reconcile() against a
    59  // fake client that tracks a BlockDeviceClaim object.
    60  func TestBlockDeviceClaimController(t *testing.T) {
    61  
    62  	// Set the logger to development mode for verbose logs.
    63  	logf.SetLogger(zap.New(zap.UseDevMode(true)))
    64  
    65  	// Create a fake client to mock API calls.
    66  	cl, s := CreateFakeClient()
    67  	deviceR := GetFakeDeviceObject(deviceName, capacity)
    68  	deviceR.Labels[kubernetes.KubernetesHostNameLabel] = fakeHostName
    69  
    70  	deviceClaimR := GetFakeBlockDeviceClaimObject()
    71  	// Create a new blockdevice obj
    72  	err := cl.Create(context.TODO(), deviceR)
    73  	if err != nil {
    74  		fmt.Println("BlockDevice object is not created", err)
    75  	}
    76  
    77  	// Create a new deviceclaim obj
    78  	err = cl.Create(context.TODO(), deviceClaimR)
    79  	if err != nil {
    80  		fmt.Println("BlockDeviceClaim object is not created", err)
    81  	}
    82  
    83  	// Create a ReconcileDevice object with the scheme and fake client.
    84  	r := &BlockDeviceClaimReconciler{Client: cl, Scheme: s, Recorder: fakeRecorder}
    85  
    86  	// Mock request to simulate Reconcile() being called on an event for a
    87  	// watched resource .
    88  	req := reconcile.Request{
    89  		NamespacedName: types.NamespacedName{
    90  			Name:      blockDeviceClaimName,
    91  			Namespace: namespace,
    92  		},
    93  	}
    94  
    95  	// Check status of deviceClaim it should be empty(Not bound)
    96  	r.CheckBlockDeviceClaimStatus(t, req, openebsv1alpha1.BlockDeviceClaimStatusEmpty)
    97  
    98  	// Fetch the BlockDeviceClaim CR and change capacity to invalid
    99  	// Since Capacity is invalid, it delete device claim CR
   100  	r.InvalidCapacityTest(t, req)
   101  
   102  	// Create new BlockDeviceClaim CR with right capacity,
   103  	// trigger reconciliation event. This time, it should
   104  	// bound.
   105  	deviceClaim := &openebsv1alpha1.BlockDeviceClaim{}
   106  	err = r.Client.Get(context.TODO(), req.NamespacedName, deviceClaim)
   107  	if err != nil {
   108  		t.Errorf("Get deviceClaim: (%v)", err)
   109  	}
   110  	orignalDeviceClaim := deviceClaim.DeepCopy()
   111  	deviceClaim.Spec.Resources.Requests[openebsv1alpha1.ResourceStorage] = claimCapacity
   112  	// resetting status to empty
   113  	deviceClaim.Status.Phase = openebsv1alpha1.BlockDeviceClaimStatusEmpty
   114  	err = r.Client.Patch(context.TODO(), deviceClaim, client.MergeFrom(orignalDeviceClaim))
   115  	if err != nil {
   116  		t.Errorf("Update deviceClaim: (%v)", err)
   117  	}
   118  
   119  	res, err := r.Reconcile(context.TODO(), req)
   120  	if err != nil {
   121  		t.Logf("reconcile: (%v)", err)
   122  	}
   123  
   124  	// Check the result of reconciliation to make sure it has the desired state.
   125  	if !res.Requeue {
   126  		t.Log("reconcile did not requeue request as expected")
   127  	}
   128  	r.CheckBlockDeviceClaimStatus(t, req, openebsv1alpha1.BlockDeviceClaimStatusDone)
   129  
   130  	r.DeviceRequestedHappyPathTest(t, req)
   131  	//TODO: Need to find a way to update deletion timestamp
   132  	//r.DeleteBlockDeviceClaimedTest(t, req)
   133  }
   134  
   135  func (r *BlockDeviceClaimReconciler) DeleteBlockDeviceClaimedTest(t *testing.T,
   136  	req reconcile.Request) {
   137  
   138  	devRequestInst := &openebsv1alpha1.BlockDeviceClaim{}
   139  
   140  	// Fetch the BlockDeviceClaim CR
   141  	err := r.Client.Get(context.TODO(), req.NamespacedName, devRequestInst)
   142  	if err != nil {
   143  		t.Errorf("Get devClaimInst: (%v)", err)
   144  	}
   145  
   146  	err = r.Client.Delete(context.TODO(), devRequestInst)
   147  	if err != nil {
   148  		t.Errorf("Delete devClaimInst: (%v)", err)
   149  	}
   150  
   151  	res, err := r.Reconcile(context.TODO(), req)
   152  	if err != nil {
   153  		t.Logf("reconcile: (%v)", err)
   154  	}
   155  
   156  	// Check the result of reconciliation to make sure it has the desired state.
   157  	if !res.Requeue {
   158  		t.Log("reconcile did not requeue request as expected")
   159  	}
   160  
   161  	dvRequestInst := &openebsv1alpha1.BlockDeviceClaim{}
   162  	err = r.Client.Get(context.TODO(), req.NamespacedName, dvRequestInst)
   163  	if errors.IsNotFound(err) {
   164  		t.Logf("BlockDeviceClaim is deleted, expected")
   165  		err = nil
   166  	} else if err != nil {
   167  		t.Errorf("Get dvClaimInst: (%v)", err)
   168  	}
   169  
   170  	time.Sleep(10 * time.Second)
   171  	// Fetch the BlockDevice CR
   172  	devInst := &openebsv1alpha1.BlockDevice{}
   173  	err = r.Client.Get(context.TODO(), types.NamespacedName{Name: deviceName, Namespace: namespace}, devInst)
   174  	if err != nil {
   175  		t.Errorf("get devInst: (%v)", err)
   176  	}
   177  
   178  	if devInst.Spec.ClaimRef.UID == dvRequestInst.ObjectMeta.UID {
   179  		t.Logf("BlockDevice ObjRef UID:%v match expected deviceRequest UID:%v",
   180  			devInst.Spec.ClaimRef.UID, dvRequestInst.ObjectMeta.UID)
   181  	} else {
   182  		t.Fatalf("BlockDevice ObjRef UID:%v did not match expected deviceRequest UID:%v",
   183  			devInst.Spec.ClaimRef.UID, dvRequestInst.ObjectMeta.UID)
   184  	}
   185  
   186  	if devInst.Status.ClaimState == openebsv1alpha1.BlockDeviceClaimed {
   187  		t.Logf("BlockDevice Obj state:%v match expected state:%v",
   188  			devInst.Status.ClaimState, openebsv1alpha1.BlockDeviceClaimed)
   189  	} else {
   190  		t.Fatalf("BlockDevice Obj state:%v did not match expected state:%v",
   191  			devInst.Status.ClaimState, openebsv1alpha1.BlockDeviceClaimed)
   192  	}
   193  }
   194  
   195  func (r *BlockDeviceClaimReconciler) DeviceRequestedHappyPathTest(t *testing.T,
   196  	req reconcile.Request) {
   197  
   198  	devRequestInst := &openebsv1alpha1.BlockDeviceClaim{}
   199  	// Fetch the BlockDeviceClaim CR
   200  	err := r.Client.Get(context.TODO(), req.NamespacedName, devRequestInst)
   201  	if err != nil {
   202  		t.Errorf("Get devRequestInst: (%v)", err)
   203  	}
   204  
   205  	// Fetch the BlockDevice CR
   206  	devInst := &openebsv1alpha1.BlockDevice{}
   207  	err = r.Client.Get(context.TODO(), types.NamespacedName{Name: deviceName, Namespace: namespace}, devInst)
   208  	if err != nil {
   209  		t.Errorf("get devInst: (%v)", err)
   210  	}
   211  
   212  	if devInst.Spec.ClaimRef.UID == devRequestInst.ObjectMeta.UID {
   213  		t.Logf("BlockDevice ObjRef UID:%v match expected deviceRequest UID:%v",
   214  			devInst.Spec.ClaimRef.UID, devRequestInst.ObjectMeta.UID)
   215  	} else {
   216  		t.Fatalf("BlockDevice ObjRef UID:%v did not match expected deviceRequest UID:%v",
   217  			devInst.Spec.ClaimRef.UID, devRequestInst.ObjectMeta.UID)
   218  	}
   219  
   220  	if devInst.Status.ClaimState == openebsv1alpha1.BlockDeviceClaimed {
   221  		t.Logf("BlockDevice Obj state:%v match expected state:%v",
   222  			devInst.Status.ClaimState, openebsv1alpha1.BlockDeviceClaimed)
   223  	} else {
   224  		t.Fatalf("BlockDevice Obj state:%v did not match expected state:%v",
   225  			devInst.Status.ClaimState, openebsv1alpha1.BlockDeviceClaimed)
   226  	}
   227  }
   228  
   229  func (r *BlockDeviceClaimReconciler) InvalidCapacityTest(t *testing.T,
   230  	req reconcile.Request) {
   231  
   232  	devRequestInst := &openebsv1alpha1.BlockDeviceClaim{}
   233  	err := r.Client.Get(context.TODO(), req.NamespacedName, devRequestInst)
   234  	if err != nil {
   235  		t.Errorf("Get devRequestInst: (%v)", err)
   236  	}
   237  
   238  	orignalDevRequestInst := devRequestInst.DeepCopy()
   239  	devRequestInst.Spec.Resources.Requests[openebsv1alpha1.ResourceStorage] = resource.MustParse("0")
   240  	err = r.Client.Patch(context.TODO(), devRequestInst, client.MergeFrom(orignalDevRequestInst))
   241  	if err != nil {
   242  		t.Errorf("Update devRequestInst: (%v)", err)
   243  	}
   244  
   245  	res, err := r.Reconcile(context.TODO(), req)
   246  	if err != nil {
   247  		t.Logf("reconcile: (%v)", err)
   248  	}
   249  
   250  	// Check the result of reconciliation to make sure it has the desired state.
   251  	if !res.Requeue {
   252  		t.Log("reconcile did not requeue request as expected")
   253  	}
   254  
   255  	dvC := &openebsv1alpha1.BlockDeviceClaim{}
   256  	err = r.Client.Get(context.TODO(), req.NamespacedName, dvC)
   257  	if err != nil {
   258  		t.Errorf("Get devRequestInst: (%v)", err)
   259  	}
   260  	r.CheckBlockDeviceClaimStatus(t, req, openebsv1alpha1.BlockDeviceClaimStatusPending)
   261  }
   262  
   263  func TestBlockDeviceClaimsLabelSelector(t *testing.T) {
   264  	// Set the logger to development mode for verbose logs.
   265  	logf.SetLogger(zap.New(zap.UseDevMode(true)))
   266  
   267  	tests := map[string]struct {
   268  		bdLabels           map[string]string
   269  		selector           *metav1.LabelSelector
   270  		expectedClaimPhase openebsv1alpha1.DeviceClaimPhase
   271  	}{
   272  		"only hostname label is present and no selector": {
   273  			bdLabels: map[string]string{
   274  				kubernetes.KubernetesHostNameLabel: fakeHostName,
   275  			},
   276  			selector:           nil,
   277  			expectedClaimPhase: openebsv1alpha1.BlockDeviceClaimStatusDone,
   278  		},
   279  		"custom label and hostname present on bd and selector": {
   280  			bdLabels: map[string]string{
   281  				ndm.KubernetesHostNameLabel: fakeHostName,
   282  				"ndm.io/test":               "1234",
   283  			},
   284  			selector: &metav1.LabelSelector{
   285  				MatchLabels: map[string]string{
   286  					ndm.KubernetesHostNameLabel: fakeHostName,
   287  					"ndm.io/test":               "1234",
   288  				},
   289  			},
   290  			expectedClaimPhase: openebsv1alpha1.BlockDeviceClaimStatusDone,
   291  		},
   292  		"custom labels and hostname": {
   293  			bdLabels: map[string]string{
   294  				ndm.KubernetesHostNameLabel: fakeHostName,
   295  				"ndm.io/test":               "1234",
   296  			},
   297  			selector: &metav1.LabelSelector{
   298  				MatchLabels: map[string]string{
   299  					"ndm.io/test": "1234",
   300  				},
   301  			},
   302  			expectedClaimPhase: openebsv1alpha1.BlockDeviceClaimStatusDone,
   303  		},
   304  	}
   305  	for name, test := range tests {
   306  		t.Run(name, func(t *testing.T) {
   307  			// pinning the variables
   308  			bdLabels := test.bdLabels
   309  			selector := test.selector
   310  			expectedClaimPhase := test.expectedClaimPhase
   311  
   312  			// Create a fake client to mock API calls.
   313  			cl, s := CreateFakeClient()
   314  
   315  			// Create a ReconcileDevice object with the scheme and fake client.
   316  			r := &BlockDeviceClaimReconciler{Client: cl, Scheme: s, Recorder: fakeRecorder}
   317  
   318  			// Mock request to simulate Reconcile() being called on an event for a
   319  			// watched resource .
   320  			req := reconcile.Request{
   321  				NamespacedName: types.NamespacedName{
   322  					Name:      blockDeviceClaimName,
   323  					Namespace: namespace,
   324  				},
   325  			}
   326  
   327  			bdcR := GetFakeBlockDeviceClaimObject()
   328  			if err := cl.Create(context.TODO(), bdcR); err != nil {
   329  				t.Fatal(err)
   330  			}
   331  
   332  			bd := GetFakeDeviceObject("bd-1", capacity*10)
   333  
   334  			bd.Labels = bdLabels
   335  			// mark the device as unclaimed
   336  			bd.Spec.ClaimRef = nil
   337  			bd.Status.ClaimState = openebsv1alpha1.BlockDeviceUnclaimed
   338  
   339  			err := cl.Create(context.TODO(), bd)
   340  			if err != nil {
   341  				t.Fatalf("error updating BD. %v", err)
   342  			}
   343  			bdc := GetFakeBlockDeviceClaimObject()
   344  			orignalBDC := bdc.DeepCopy()
   345  			bdc.Spec.BlockDeviceName = ""
   346  			bdc.Spec.Selector = selector
   347  			err = cl.Patch(context.TODO(), bdc, client.MergeFrom(orignalBDC))
   348  			if err != nil {
   349  				t.Fatalf("error updating BDC. %v", err)
   350  			}
   351  			_, _ = r.Reconcile(context.TODO(), req)
   352  
   353  			err = cl.Get(context.TODO(), req.NamespacedName, bdc)
   354  			if err != nil {
   355  				t.Fatalf("error getting BDC. %v", err)
   356  			}
   357  
   358  			err = cl.Delete(context.TODO(), bd)
   359  			if err != nil {
   360  				t.Fatalf("error deleting BDC. %v", err)
   361  			}
   362  			assert.Equal(t, expectedClaimPhase, bdc.Status.Phase)
   363  		})
   364  	}
   365  }
   366  
   367  func (r *BlockDeviceClaimReconciler) CheckBlockDeviceClaimStatus(t *testing.T,
   368  	req reconcile.Request, phase openebsv1alpha1.DeviceClaimPhase) {
   369  
   370  	devRequestCR := &openebsv1alpha1.BlockDeviceClaim{}
   371  	err := r.Client.Get(context.TODO(), req.NamespacedName, devRequestCR)
   372  	if err != nil {
   373  		t.Errorf("get devRequestCR : (%v)", err)
   374  	}
   375  
   376  	// BlockDeviceClaim should yet to bound.
   377  	if devRequestCR.Status.Phase == phase {
   378  		t.Logf("BlockDeviceClaim Object status:%v match expected status:%v",
   379  			devRequestCR.Status.Phase, phase)
   380  	} else {
   381  		t.Fatalf("BlockDeviceClaim Object status:%v did not match expected status:%v",
   382  			devRequestCR.Status.Phase, phase)
   383  	}
   384  }
   385  
   386  func GetFakeBlockDeviceClaimObject() *openebsv1alpha1.BlockDeviceClaim {
   387  	deviceRequestCR := &openebsv1alpha1.BlockDeviceClaim{}
   388  
   389  	TypeMeta := metav1.TypeMeta{
   390  		Kind:       "BlockDeviceClaim",
   391  		APIVersion: ndm.NDMVersion,
   392  	}
   393  
   394  	ObjectMeta := metav1.ObjectMeta{
   395  		Labels:    make(map[string]string),
   396  		Name:      blockDeviceClaimName,
   397  		Namespace: namespace,
   398  		UID:       blockDeviceClaimUID,
   399  	}
   400  
   401  	Requests := corev1.ResourceList{openebsv1alpha1.ResourceStorage: claimCapacity}
   402  
   403  	Requirements := openebsv1alpha1.DeviceClaimResources{
   404  		Requests: Requests,
   405  	}
   406  
   407  	Spec := openebsv1alpha1.DeviceClaimSpec{
   408  		Resources:  Requirements,
   409  		DeviceType: "",
   410  		HostName:   fakeHostName,
   411  	}
   412  
   413  	deviceRequestCR.ObjectMeta = ObjectMeta
   414  	deviceRequestCR.TypeMeta = TypeMeta
   415  	deviceRequestCR.Spec = Spec
   416  	deviceRequestCR.Status.Phase = openebsv1alpha1.BlockDeviceClaimStatusEmpty
   417  	return deviceRequestCR
   418  }
   419  
   420  func GetFakeDeviceObject(bdName string, bdCapacity uint64) *openebsv1alpha1.BlockDevice {
   421  	device := &openebsv1alpha1.BlockDevice{}
   422  
   423  	TypeMeta := metav1.TypeMeta{
   424  		Kind:       ndm.NDMBlockDeviceKind,
   425  		APIVersion: ndm.NDMVersion,
   426  	}
   427  
   428  	ObjectMeta := metav1.ObjectMeta{
   429  		Labels:    make(map[string]string),
   430  		Name:      bdName,
   431  		Namespace: namespace,
   432  	}
   433  
   434  	Spec := openebsv1alpha1.DeviceSpec{
   435  		Path: "dev/disk-fake-path",
   436  		Capacity: openebsv1alpha1.DeviceCapacity{
   437  			Storage: bdCapacity, // Set blockdevice size.
   438  		},
   439  		DevLinks:    make([]openebsv1alpha1.DeviceDevLink, 0),
   440  		Partitioned: ndm.NDMNotPartitioned,
   441  	}
   442  
   443  	device.ObjectMeta = ObjectMeta
   444  	device.TypeMeta = TypeMeta
   445  	device.Status.ClaimState = openebsv1alpha1.BlockDeviceUnclaimed
   446  	device.Status.State = ndm.NDMActive
   447  	device.Spec = Spec
   448  	return device
   449  }
   450  
   451  func CreateFakeClient() (client.Client, *runtime.Scheme) {
   452  
   453  	deviceR := GetFakeDeviceObject(deviceName, capacity)
   454  
   455  	deviceList := &openebsv1alpha1.BlockDeviceList{
   456  		TypeMeta: metav1.TypeMeta{
   457  			Kind:       "BlockDevice",
   458  			APIVersion: "",
   459  		},
   460  	}
   461  
   462  	deviceClaimR := GetFakeBlockDeviceClaimObject()
   463  	deviceclaimList := &openebsv1alpha1.BlockDeviceClaimList{
   464  		TypeMeta: metav1.TypeMeta{
   465  			Kind:       "BlockDeviceClaim",
   466  			APIVersion: "",
   467  		},
   468  	}
   469  
   470  	s := scheme.Scheme
   471  
   472  	s.AddKnownTypes(openebsv1alpha1.GroupVersion, deviceR)
   473  	s.AddKnownTypes(openebsv1alpha1.GroupVersion, deviceList)
   474  	s.AddKnownTypes(openebsv1alpha1.GroupVersion, deviceClaimR)
   475  	s.AddKnownTypes(openebsv1alpha1.GroupVersion, deviceclaimList)
   476  
   477  	fakeNdmClient := fake.NewFakeClientWithScheme(s)
   478  	if fakeNdmClient == nil {
   479  		fmt.Println("NDMClient is not created")
   480  	}
   481  
   482  	return fakeNdmClient, s
   483  }
   484  
   485  func TestGenerateSelector(t *testing.T) {
   486  	tests := map[string]struct {
   487  		bdc  openebsv1alpha1.BlockDeviceClaim
   488  		want *metav1.LabelSelector
   489  	}{
   490  		"hostname/node attributes not given and no selector": {
   491  			bdc: openebsv1alpha1.BlockDeviceClaim{
   492  				Spec: openebsv1alpha1.DeviceClaimSpec{},
   493  			},
   494  			want: &metav1.LabelSelector{
   495  				MatchLabels: make(map[string]string),
   496  			},
   497  		},
   498  		"hostname is given, node attributes not given and no selector": {
   499  			bdc: openebsv1alpha1.BlockDeviceClaim{
   500  				Spec: openebsv1alpha1.DeviceClaimSpec{
   501  					HostName: "hostname",
   502  				},
   503  			},
   504  			want: &metav1.LabelSelector{
   505  				MatchLabels: map[string]string{
   506  					ndm.KubernetesHostNameLabel: "hostname",
   507  				},
   508  			},
   509  		},
   510  		"hostname is not given, node attribute is given and no selector": {
   511  			bdc: openebsv1alpha1.BlockDeviceClaim{
   512  				Spec: openebsv1alpha1.DeviceClaimSpec{
   513  					BlockDeviceNodeAttributes: openebsv1alpha1.BlockDeviceNodeAttributes{
   514  						HostName: "hostname",
   515  					},
   516  				},
   517  			},
   518  			want: &metav1.LabelSelector{
   519  				MatchLabels: map[string]string{
   520  					ndm.KubernetesHostNameLabel: "hostname",
   521  				},
   522  			},
   523  		},
   524  		"same hostname, node attribute is given and no selector": {
   525  			bdc: openebsv1alpha1.BlockDeviceClaim{
   526  				Spec: openebsv1alpha1.DeviceClaimSpec{
   527  					HostName: "hostname",
   528  					BlockDeviceNodeAttributes: openebsv1alpha1.BlockDeviceNodeAttributes{
   529  						HostName: "hostname",
   530  					},
   531  				},
   532  			},
   533  			want: &metav1.LabelSelector{
   534  				MatchLabels: map[string]string{
   535  					ndm.KubernetesHostNameLabel: "hostname",
   536  				},
   537  			},
   538  		},
   539  		"different hostname and node attributes is given and no selector": {
   540  			bdc: openebsv1alpha1.BlockDeviceClaim{
   541  				Spec: openebsv1alpha1.DeviceClaimSpec{
   542  					HostName: "hostname1",
   543  					BlockDeviceNodeAttributes: openebsv1alpha1.BlockDeviceNodeAttributes{
   544  						HostName: "hostname2",
   545  					},
   546  				},
   547  			},
   548  			want: &metav1.LabelSelector{
   549  				MatchLabels: map[string]string{
   550  					ndm.KubernetesHostNameLabel: "hostname2",
   551  				},
   552  			},
   553  		},
   554  		"no hostname and custom selector is given": {
   555  			bdc: openebsv1alpha1.BlockDeviceClaim{
   556  				Spec: openebsv1alpha1.DeviceClaimSpec{
   557  					Selector: &metav1.LabelSelector{
   558  						MatchLabels: map[string]string{
   559  							"ndm.io/test": "test",
   560  						},
   561  					},
   562  				},
   563  			},
   564  			want: &metav1.LabelSelector{
   565  				MatchLabels: map[string]string{
   566  					"ndm.io/test": "test",
   567  				},
   568  			},
   569  		},
   570  		"hostname given and selector also contains custom label name": {
   571  			bdc: openebsv1alpha1.BlockDeviceClaim{
   572  				Spec: openebsv1alpha1.DeviceClaimSpec{
   573  					Selector: &metav1.LabelSelector{
   574  						MatchLabels: map[string]string{
   575  							ndm.KubernetesHostNameLabel: "hostname1",
   576  							"ndm.io/test":               "test",
   577  						},
   578  					},
   579  					HostName: "hostname2",
   580  				},
   581  			},
   582  			want: &metav1.LabelSelector{
   583  				MatchLabels: map[string]string{
   584  					ndm.KubernetesHostNameLabel: "hostname2",
   585  					"ndm.io/test":               "test",
   586  				},
   587  			},
   588  		},
   589  	}
   590  	for name, test := range tests {
   591  		t.Run(name, func(t *testing.T) {
   592  			got := generateSelector(test.bdc)
   593  			assert.Equal(t, test.want, got)
   594  		})
   595  	}
   596  }