github.com/openebs/node-disk-manager@v1.9.1-0.20230225014141-4531f06ffa1e/pkg/select/blockdevice/filters_test.go (about)

     1  /*
     2  Copyright 2020 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 blockdevice
    18  
    19  import (
    20  	"fmt"
    21  
    22  	apis "github.com/openebs/node-disk-manager/api/v1alpha1"
    23  	"github.com/openebs/node-disk-manager/db/kubernetes"
    24  
    25  	"github.com/stretchr/testify/assert"
    26  	"k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"testing"
    28  )
    29  
    30  const (
    31  	TestNoOfBDs = 6
    32  )
    33  
    34  type BDLabel map[string]string
    35  type BDLabelList []BDLabel
    36  
    37  func TestFilterBlockDeviceTag(t *testing.T) {
    38  
    39  	// label list with no additional labels
    40  	bdLabelList1 := []BDLabel{
    41  		map[string]string{
    42  			kubernetes.KubernetesHostNameLabel: "host1",
    43  		},
    44  		map[string]string{
    45  			kubernetes.KubernetesHostNameLabel: "host2",
    46  		},
    47  		map[string]string{
    48  			kubernetes.KubernetesHostNameLabel: "host3",
    49  		},
    50  		map[string]string{
    51  			kubernetes.KubernetesHostNameLabel: "host4",
    52  		},
    53  		map[string]string{
    54  			kubernetes.KubernetesHostNameLabel: "host5",
    55  		},
    56  		map[string]string{
    57  			kubernetes.KubernetesHostNameLabel: "host6",
    58  		},
    59  	}
    60  
    61  	// label list with all devices having same tag
    62  	bdLabelList2 := []BDLabel{
    63  		map[string]string{
    64  			kubernetes.KubernetesHostNameLabel: "host1",
    65  			kubernetes.BlockDeviceTagLabel:     "X",
    66  		},
    67  		map[string]string{
    68  			kubernetes.KubernetesHostNameLabel: "host2",
    69  			kubernetes.BlockDeviceTagLabel:     "X",
    70  		},
    71  		map[string]string{
    72  			kubernetes.KubernetesHostNameLabel: "host3",
    73  			kubernetes.BlockDeviceTagLabel:     "X",
    74  		},
    75  		map[string]string{
    76  			kubernetes.KubernetesHostNameLabel: "host4",
    77  			kubernetes.BlockDeviceTagLabel:     "X",
    78  		},
    79  		map[string]string{
    80  			kubernetes.KubernetesHostNameLabel: "host5",
    81  			kubernetes.BlockDeviceTagLabel:     "X",
    82  		},
    83  		map[string]string{
    84  			kubernetes.KubernetesHostNameLabel: "host6",
    85  			kubernetes.BlockDeviceTagLabel:     "X",
    86  		},
    87  	}
    88  
    89  	// label list with some devices having default label and some devices
    90  	// with device tag
    91  	bdLabelList3 := []BDLabel{
    92  		map[string]string{
    93  			kubernetes.KubernetesHostNameLabel: "host1",
    94  		},
    95  		map[string]string{
    96  			kubernetes.KubernetesHostNameLabel: "host2",
    97  		},
    98  		map[string]string{
    99  			kubernetes.KubernetesHostNameLabel: "host3",
   100  			kubernetes.BlockDeviceTagLabel:     "X",
   101  		},
   102  		map[string]string{
   103  			kubernetes.KubernetesHostNameLabel: "host4",
   104  			kubernetes.BlockDeviceTagLabel:     "X",
   105  		},
   106  		map[string]string{
   107  			kubernetes.KubernetesHostNameLabel: "host5",
   108  			kubernetes.BlockDeviceTagLabel:     "Y",
   109  		},
   110  		map[string]string{
   111  			kubernetes.KubernetesHostNameLabel: "host6",
   112  			kubernetes.BlockDeviceTagLabel:     "Y",
   113  		},
   114  	}
   115  
   116  	// label list with some devices having default label and some devices
   117  	// with device tag, and some devices with empty tag
   118  	bdLabelList4 := []BDLabel{
   119  		map[string]string{
   120  			kubernetes.KubernetesHostNameLabel: "host1",
   121  		},
   122  		map[string]string{
   123  			kubernetes.KubernetesHostNameLabel: "host2",
   124  		},
   125  		map[string]string{
   126  			kubernetes.KubernetesHostNameLabel: "host3",
   127  			kubernetes.BlockDeviceTagLabel:     "X",
   128  		},
   129  		map[string]string{
   130  			kubernetes.KubernetesHostNameLabel: "host4",
   131  			kubernetes.BlockDeviceTagLabel:     "X",
   132  		},
   133  		map[string]string{
   134  			kubernetes.KubernetesHostNameLabel: "host5",
   135  			kubernetes.BlockDeviceTagLabel:     "",
   136  		},
   137  		map[string]string{
   138  			kubernetes.KubernetesHostNameLabel: "host6",
   139  			kubernetes.BlockDeviceTagLabel:     "",
   140  		},
   141  	}
   142  
   143  	type args struct {
   144  		bdLabelList BDLabelList
   145  		spec        *apis.DeviceClaimSpec
   146  	}
   147  	tests := map[string]struct {
   148  		args          args
   149  		wantedNoofBDs int
   150  	}{
   151  		"no labels on any BD and no selector on BDC": {
   152  			args: args{
   153  				bdLabelList: bdLabelList1,
   154  				spec:        &apis.DeviceClaimSpec{},
   155  			},
   156  			wantedNoofBDs: 6,
   157  		},
   158  		"all BDs have same device tag label and no selector": {
   159  			args: args{
   160  				bdLabelList: bdLabelList2,
   161  				spec:        &apis.DeviceClaimSpec{},
   162  			},
   163  			wantedNoofBDs: 0,
   164  		},
   165  		"all BDs have same device tag label and selector for tag": {
   166  			args: args{
   167  				bdLabelList: bdLabelList2,
   168  				spec: &apis.DeviceClaimSpec{
   169  					Selector: &v1.LabelSelector{
   170  						MatchLabels: map[string]string{kubernetes.BlockDeviceTagLabel: "X"},
   171  					},
   172  				},
   173  			},
   174  			wantedNoofBDs: 6,
   175  		},
   176  		"all BDs have same device tag label and custom label used in selector": {
   177  			args: args{
   178  				bdLabelList: bdLabelList2,
   179  				spec: &apis.DeviceClaimSpec{
   180  					Selector: &v1.LabelSelector{
   181  						MatchLabels: map[string]string{"ndm.io/test": "test"},
   182  					},
   183  				},
   184  			},
   185  			wantedNoofBDs: 0,
   186  		},
   187  		"some BDs with tag and some without tag, combined with no selector": {
   188  			args: args{
   189  				bdLabelList: bdLabelList3,
   190  				spec: &apis.DeviceClaimSpec{
   191  					Selector: &v1.LabelSelector{},
   192  				},
   193  			},
   194  			wantedNoofBDs: 2,
   195  		},
   196  		"some BDs with tag key, but with empty selector": {
   197  			args: args{
   198  				bdLabelList: bdLabelList4,
   199  				spec: &apis.DeviceClaimSpec{
   200  					Selector: &v1.LabelSelector{},
   201  				},
   202  			},
   203  			wantedNoofBDs: 2,
   204  		},
   205  		"some BDs with tag key, with selector matching empty tag": {
   206  			args: args{
   207  				bdLabelList: bdLabelList4,
   208  				spec: &apis.DeviceClaimSpec{
   209  					Selector: &v1.LabelSelector{
   210  						MatchLabels: map[string]string{kubernetes.BlockDeviceTagLabel: ""},
   211  					},
   212  				},
   213  			},
   214  			wantedNoofBDs: 4,
   215  		},
   216  		"some BDs with tag key, with selector matching tag exists operation": {
   217  			args: args{
   218  				bdLabelList: bdLabelList4,
   219  				spec: &apis.DeviceClaimSpec{
   220  					Selector: &v1.LabelSelector{
   221  						MatchExpressions: []v1.LabelSelectorRequirement{
   222  							{
   223  								Key:      kubernetes.BlockDeviceTagLabel,
   224  								Operator: v1.LabelSelectorOpExists,
   225  							},
   226  						},
   227  					},
   228  				},
   229  			},
   230  			wantedNoofBDs: 4,
   231  		},
   232  	}
   233  	for name, test := range tests {
   234  		t.Run(name, func(t *testing.T) {
   235  			bdLabelList := test.args.bdLabelList
   236  			spec := test.args.spec
   237  			wantedNoOfBDs := test.wantedNoofBDs
   238  			originalBDList := createFakeBlockDeviceList(bdLabelList, TestNoOfBDs)
   239  			got := filterBlockDeviceTag(originalBDList, spec)
   240  			assert.Equal(t, wantedNoOfBDs, len(got.Items))
   241  		})
   242  	}
   243  }
   244  
   245  func createFakeBlockDeviceList(labelList BDLabelList, noOfBDs int) *apis.BlockDeviceList {
   246  	bdListAPI := &apis.BlockDeviceList{
   247  		TypeMeta: v1.TypeMeta{
   248  			Kind:       "BlockDevice",
   249  			APIVersion: "openebs.io/v1alpha1",
   250  		},
   251  		Items: []apis.BlockDevice{},
   252  	}
   253  	for i := 0; i < noOfBDs; i++ {
   254  		bdName := fmt.Sprint("bd", i)
   255  		bdListAPI.Items = append(bdListAPI.Items, createFakeBlockDevice(bdName, labelList[i]))
   256  	}
   257  	return bdListAPI
   258  }
   259  
   260  func createFakeBlockDevice(name string, label map[string]string) apis.BlockDevice {
   261  	bdAPI := apis.BlockDevice{
   262  		TypeMeta: v1.TypeMeta{
   263  			Kind:       "BlockDevice",
   264  			APIVersion: "openebs.io/v1alpha1",
   265  		},
   266  	}
   267  	bdAPI.Name = name
   268  	bdAPI.Labels = label
   269  	return bdAPI
   270  }