github.com/milvus-io/milvus-sdk-go/v2@v2.4.1/test/testcases/resource_group_test.go (about) 1 //go:build L3 2 3 package testcases 4 5 import ( 6 "context" 7 "log" 8 "testing" 9 "time" 10 11 "github.com/milvus-io/milvus-sdk-go/v2/client" 12 13 "github.com/milvus-io/milvus-sdk-go/v2/test/base" 14 "github.com/stretchr/testify/require" 15 16 "github.com/milvus-io/milvus-sdk-go/v2/entity" 17 18 "github.com/milvus-io/milvus-sdk-go/v2/test/common" 19 ) 20 21 const configQnNodes = int32(4) 22 const newRgNode = int32(2) 23 24 func resetRgs(t *testing.T, ctx context.Context, mc *base.MilvusClient) { 25 // release and drop all collections 26 collections, _ := mc.ListCollections(ctx) 27 for _, coll := range collections { 28 mc.ReleaseCollection(ctx, coll.Name) 29 err := mc.DropCollection(ctx, coll.Name) 30 common.CheckErr(t, err, true) 31 } 32 33 // reset resource groups 34 rgs, errList := mc.ListResourceGroups(ctx) 35 common.CheckErr(t, errList, true) 36 for _, rg := range rgs { 37 if rg != common.DefaultRgName { 38 // describe rg and get available node 39 rgInfo, errDescribe := mc.DescribeResourceGroup(ctx, rg) 40 common.CheckErr(t, errDescribe, true) 41 42 // transfer available nodes into default rg 43 if rgInfo.AvailableNodesNumber > 0 { 44 errTransfer := mc.TransferNode(ctx, rg, common.DefaultRgName, rgInfo.AvailableNodesNumber) 45 common.CheckErr(t, errTransfer, true) 46 } 47 48 // drop rg 49 errDrop := mc.DropResourceGroup(ctx, rg) 50 common.CheckErr(t, errDrop, true) 51 } 52 } 53 54 rgs2, errList2 := mc.ListResourceGroups(ctx) 55 common.CheckErr(t, errList2, true) 56 require.Len(t, rgs2, 1) 57 } 58 59 // test rg default: list rg, create rg, describe rg, transfer node 60 func TestRgDefault(t *testing.T) { 61 ctx := createContext(t, time.Second*common.DefaultTimeout) 62 // connect 63 mc := createMilvusClient(ctx, t) 64 resetRgs(t, ctx, mc) 65 66 // describe default rg and check default rg info 67 defaultRg, errDescribe := mc.DescribeResourceGroup(ctx, common.DefaultRgName) 68 common.CheckErr(t, errDescribe, true) 69 expDefaultRg := &entity.ResourceGroup{ 70 Name: common.DefaultRgName, 71 Capacity: common.DefaultRgCapacity, 72 AvailableNodesNumber: configQnNodes, 73 } 74 common.CheckResourceGroup(t, defaultRg, expDefaultRg) 75 76 // create new rg 77 rgName := common.GenRandomString(6) 78 errCreate := mc.CreateResourceGroup(ctx, rgName) 79 common.CheckErr(t, errCreate, true) 80 81 // list rgs 82 rgs, errList := mc.ListResourceGroups(ctx) 83 common.CheckErr(t, errList, true) 84 require.ElementsMatch(t, rgs, []string{common.DefaultRgName, rgName}) 85 86 // describe new rg and check new rg info 87 myRg, errDescribe2 := mc.DescribeResourceGroup(ctx, rgName) 88 common.CheckErr(t, errDescribe2, true) 89 expRg := &entity.ResourceGroup{ 90 Name: rgName, 91 Capacity: 0, 92 AvailableNodesNumber: 0, 93 } 94 common.CheckResourceGroup(t, myRg, expRg) 95 96 // transfer node from default rg into new rg 97 errTransfer := mc.TransferNode(ctx, common.DefaultRgName, rgName, newRgNode) 98 common.CheckErr(t, errTransfer, true) 99 100 // check rg info after transfer nodes 101 myRg2, _ := mc.DescribeResourceGroup(ctx, rgName) 102 transferRg := &entity.ResourceGroup{ 103 Name: rgName, 104 Capacity: newRgNode, 105 AvailableNodesNumber: newRgNode, 106 } 107 common.CheckResourceGroup(t, myRg2, transferRg) 108 109 // check default rg info 110 defaultRg2, _ := mc.DescribeResourceGroup(ctx, common.DefaultRgName) 111 expDefaultRg2 := &entity.ResourceGroup{ 112 Name: common.DefaultRgName, 113 Capacity: common.DefaultRgCapacity, 114 AvailableNodesNumber: configQnNodes - newRgNode, 115 } 116 common.CheckResourceGroup(t, defaultRg2, expDefaultRg2) 117 118 // try to drop default rg 119 errDropDefault := mc.DropResourceGroup(ctx, common.DefaultRgName) 120 common.CheckErr(t, errDropDefault, false, "default resource group is not deletable") 121 } 122 123 // test create rg with invalid name 124 func TestCreateRgInvalidNames(t *testing.T) { 125 t.Parallel() 126 ctx := createContext(t, time.Second*common.DefaultTimeout) 127 // connect 128 mc := createMilvusClient(ctx, t) 129 130 type invalidNameStruct struct { 131 name string 132 errMsg string 133 } 134 135 invalidNames := []invalidNameStruct{ 136 {name: "", errMsg: "resource group name couldn't be empty"}, 137 {name: "12-s", errMsg: "name must be an underscore or letter"}, 138 {name: "(mn)", errMsg: "name must be an underscore or letter"}, 139 {name: "中文", errMsg: "name must be an underscore or letter"}, 140 {name: "%$#", errMsg: "name must be an underscore or letter"}, 141 {name: common.GenLongString(common.MaxCollectionNameLen + 1), errMsg: "name must be less than 255 characters"}, 142 } 143 // create rg with invalid name 144 for _, invalidName := range invalidNames { 145 errCreate := mc.CreateResourceGroup(ctx, invalidName.name) 146 common.CheckErr(t, errCreate, false, invalidName.errMsg) 147 } 148 } 149 150 // describe rg with not existed name 151 func TestDescribeRgNotExisted(t *testing.T) { 152 ctx := createContext(t, time.Second*common.DefaultTimeout) 153 // connect 154 mc := createMilvusClient(ctx, t) 155 156 _, errDescribe := mc.DescribeResourceGroup(ctx, common.GenRandomString(6)) 157 common.CheckErr(t, errDescribe, false, "resource group not found") 158 } 159 160 // drop rg with not existed name -> successfully 161 func TestDropRgNotExisted(t *testing.T) { 162 ctx := createContext(t, time.Second*common.DefaultTimeout) 163 // connect 164 mc := createMilvusClient(ctx, t) 165 166 errDrop := mc.DropResourceGroup(ctx, common.GenRandomString(6)) 167 common.CheckErr(t, errDrop, true) 168 } 169 170 // drop rg 171 func TestDropRgNonEmpty(t *testing.T) { 172 ctx := createContext(t, time.Second*common.DefaultTimeout) 173 // connect 174 mc := createMilvusClient(ctx, t) 175 resetRgs(t, ctx, mc) 176 177 // create new rg 178 rgName := common.GenRandomString(6) 179 errCreate := mc.CreateResourceGroup(ctx, rgName) 180 common.CheckErr(t, errCreate, true) 181 182 // transfer node 183 errTransfer := mc.TransferNode(ctx, common.DefaultRgName, rgName, 1) 184 common.CheckErr(t, errTransfer, true) 185 186 // drop rg and rg available node is not 0 187 errDrop := mc.DropResourceGroup(ctx, rgName) 188 common.CheckErr(t, errDrop, false, "resource group's limits node num is not 0") 189 } 190 191 // drop empty default rg 192 func TestDropEmptyRg(t *testing.T) { 193 ctx := createContext(t, time.Second*common.DefaultTimeout) 194 // connect 195 mc := createMilvusClient(ctx, t) 196 resetRgs(t, ctx, mc) 197 198 // create new rg 199 rgName := common.GenRandomString(6) 200 errCreate := mc.CreateResourceGroup(ctx, rgName) 201 common.CheckErr(t, errCreate, true) 202 203 // transfer node 204 errTransfer := mc.TransferNode(ctx, common.DefaultRgName, rgName, configQnNodes) 205 common.CheckErr(t, errTransfer, true) 206 207 // describe default rg 208 defaultRg, errDescribe := mc.DescribeResourceGroup(ctx, common.DefaultRgName) 209 common.CheckErr(t, errDescribe, true) 210 transferRg := &entity.ResourceGroup{ 211 Name: common.DefaultRgName, 212 Capacity: common.DefaultRgCapacity, 213 AvailableNodesNumber: 0, 214 } 215 common.CheckResourceGroup(t, defaultRg, transferRg) 216 217 // drop empty default rg 218 errDrop := mc.DropResourceGroup(ctx, common.DefaultRgName) 219 common.CheckErr(t, errDrop, false, "default resource group is not deletable") 220 } 221 222 // test list rgs 223 func TestListRgs(t *testing.T) { 224 ctx := createContext(t, time.Second*common.DefaultTimeout) 225 // connect 226 mc := createMilvusClient(ctx, t) 227 resetRgs(t, ctx, mc) 228 229 // create 10 new rgs 230 rgNum := 10 231 rgs := make([]string, 0, rgNum) 232 for i := 1; i <= rgNum; i++ { 233 rgName := common.GenRandomString(6) 234 errCreate := mc.CreateResourceGroup(ctx, rgName) 235 common.CheckErr(t, errCreate, true) 236 rgs = append(rgs, rgName) 237 } 238 239 // list rgs 240 listRgs, errList := mc.ListResourceGroups(ctx) 241 common.CheckErr(t, errList, true) 242 243 rgs = append(rgs, common.DefaultRgName) 244 require.ElementsMatch(t, listRgs, rgs) 245 } 246 247 // test transfer node invalid number 248 func TestTransferInvalidNodes(t *testing.T) { 249 ctx := createContext(t, time.Second*common.DefaultTimeout) 250 // connect 251 mc := createMilvusClient(ctx, t) 252 resetRgs(t, ctx, mc) 253 254 // create new rg 255 rgName := common.GenRandomString(6) 256 errCreate := mc.CreateResourceGroup(ctx, rgName) 257 common.CheckErr(t, errCreate, true) 258 type invalidNodesStruct struct { 259 nodesNum int32 260 errMsg string 261 } 262 invalidNodes := []invalidNodesStruct{ 263 {nodesNum: 0, errMsg: "invalid parameter[expected=NumNode > 0][actual=invalid NumNode 0]"}, 264 {nodesNum: -1, errMsg: "invalid parameter[expected=NumNode > 0][actual=invalid NumNode -1]"}, 265 {nodesNum: 99, errMsg: "resource group node not enough"}, 266 } 267 // transfer node 268 for _, invalidNode := range invalidNodes { 269 errTransfer := mc.TransferNode(ctx, common.DefaultRgName, rgName, invalidNode.nodesNum) 270 common.CheckErr(t, errTransfer, false, invalidNode.errMsg) 271 } 272 } 273 274 // test transfer node rg not exist 275 func TestTransferRgNotExisted(t *testing.T) { 276 ctx := createContext(t, time.Second*common.DefaultTimeout) 277 // connect 278 mc := createMilvusClient(ctx, t) 279 resetRgs(t, ctx, mc) 280 281 // source not exist 282 errSource := mc.TransferNode(ctx, common.GenRandomString(6), common.DefaultRgName, newRgNode) 283 common.CheckErr(t, errSource, false, "resource group not found") 284 285 // target not exist 286 errTarget := mc.TransferNode(ctx, common.DefaultRgName, common.GenRandomString(6), newRgNode) 287 common.CheckErr(t, errTarget, false, "resource group not found") 288 289 // transfer to self 290 errSelf := mc.TransferNode(ctx, common.DefaultRgName, common.DefaultRgName, newRgNode) 291 common.CheckErr(t, errSelf, false, "source resource group and target resource group should not be the same") 292 293 defaultRg, _ := mc.DescribeResourceGroup(ctx, common.DefaultRgName) 294 require.Equal(t, configQnNodes, defaultRg.AvailableNodesNumber) 295 } 296 297 // test transfer 2 replica2 from default to new rg 298 func TestTransferReplicas(t *testing.T) { 299 ctx := createContext(t, time.Second*common.DefaultTimeout) 300 // connect 301 mc := createMilvusClient(ctx, t) 302 resetRgs(t, ctx, mc) 303 304 // create new rg 305 rgName := common.GenRandomString(6) 306 errCreate := mc.CreateResourceGroup(ctx, rgName) 307 common.CheckErr(t, errCreate, true) 308 309 // transfer nodes into new rg 310 errTransfer := mc.TransferNode(ctx, common.DefaultRgName, rgName, newRgNode) 311 common.CheckErr(t, errTransfer, true) 312 313 // load two replicas 314 collName, _ := createCollectionWithDataIndex(ctx, t, mc, true, true) 315 316 // load two replicas into default rg 317 errLoad := mc.LoadCollection(ctx, collName, false, client.WithReplicaNumber(2), client.WithResourceGroups([]string{common.DefaultRgName})) 318 common.CheckErr(t, errLoad, true) 319 defaultRg, errDescribe := mc.DescribeResourceGroup(ctx, common.DefaultRgName) 320 common.CheckErr(t, errDescribe, true) 321 transferRg := &entity.ResourceGroup{ 322 Name: common.DefaultRgName, 323 Capacity: common.DefaultRgCapacity, 324 AvailableNodesNumber: configQnNodes - newRgNode, 325 LoadedReplica: map[string]int32{collName: 2}, 326 } 327 common.CheckResourceGroup(t, defaultRg, transferRg) 328 329 // transfer replica into new rg 330 errReplica := mc.TransferReplica(ctx, common.DefaultRgName, rgName, collName, 2) 331 common.CheckErr(t, errReplica, true) 332 333 // check default rg 334 defaultRg2, _ := mc.DescribeResourceGroup(ctx, common.DefaultRgName) 335 transferRg2 := &entity.ResourceGroup{ 336 Name: common.DefaultRgName, 337 Capacity: common.DefaultRgCapacity, 338 AvailableNodesNumber: configQnNodes - newRgNode, 339 IncomingNodeNum: map[string]int32{collName: 2}, 340 } 341 common.CheckResourceGroup(t, defaultRg2, transferRg2) 342 343 // check new rg after transfer replica 344 newRg, _ := mc.DescribeResourceGroup(ctx, rgName) 345 expRg := &entity.ResourceGroup{ 346 Name: rgName, 347 Capacity: newRgNode, 348 AvailableNodesNumber: newRgNode, 349 LoadedReplica: map[string]int32{collName: 2}, 350 OutgoingNodeNum: map[string]int32{collName: 2}, 351 } 352 common.CheckResourceGroup(t, newRg, expRg) 353 354 // drop new rg that loaded collection 355 err := mc.DropResourceGroup(ctx, rgName) 356 common.CheckErr(t, err, false, "some replicas still loaded in resource group") 357 358 // search 359 sp, err := entity.NewIndexHNSWSearchParam(74) 360 searchRes, _ := mc.Search( 361 ctx, collName, 362 []string{common.DefaultPartition}, 363 "", 364 []string{common.DefaultFloatFieldName}, 365 common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector), 366 common.DefaultFloatVecFieldName, 367 entity.L2, 368 common.DefaultTopK, 369 sp, 370 ) 371 // check search result contains search vector, which from all partitions 372 common.CheckErr(t, err, true) 373 common.CheckSearchResult(t, searchRes, common.DefaultNq, common.DefaultTopK) 374 375 } 376 377 // test transfer replica of not existed collection 378 func TestTransferReplicaNotExistedCollection(t *testing.T) { 379 ctx := createContext(t, time.Second*common.DefaultTimeout) 380 // connect 381 mc := createMilvusClient(ctx, t) 382 resetRgs(t, ctx, mc) 383 384 // create new rg 385 rgName := common.GenRandomString(6) 386 errCreate := mc.CreateResourceGroup(ctx, rgName) 387 common.CheckErr(t, errCreate, true) 388 389 // transfer replica 390 errTransfer := mc.TransferReplica(ctx, common.DefaultRgName, rgName, common.GenRandomString(3), 1) 391 common.CheckErr(t, errTransfer, false, "collection not found") 392 } 393 394 // test transfer replicas with invalid replica number 395 func TestTransferReplicaInvalidReplicaNumber(t *testing.T) { 396 ctx := createContext(t, time.Second*common.DefaultTimeout) 397 // connect 398 mc := createMilvusClient(ctx, t) 399 resetRgs(t, ctx, mc) 400 401 // create new rg 402 rgName := common.GenRandomString(6) 403 errCreate := mc.CreateResourceGroup(ctx, rgName) 404 common.CheckErr(t, errCreate, true) 405 406 // create collection 407 collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards) 408 409 // invalid replicas 410 type invalidReplicasStruct struct { 411 replicaNumber int64 412 errMsg string 413 } 414 invalidReplicas := []invalidReplicasStruct{ 415 {replicaNumber: 0, errMsg: "invalid parameter[expected=NumReplica > 0][actual=invalid NumReplica 0]"}, 416 {replicaNumber: -1, errMsg: "invalid parameter[expected=NumReplica > 0][actual=invalid NumReplica -1]"}, 417 {replicaNumber: 1, errMsg: "Collection not loaded"}, 418 } 419 420 for _, invalidReplica := range invalidReplicas { 421 // transfer replica 422 errTransfer := mc.TransferReplica(ctx, common.DefaultRgName, rgName, collName, invalidReplica.replicaNumber) 423 common.CheckErr(t, errTransfer, false, invalidReplica.errMsg) 424 } 425 } 426 427 // test transfer replicas rg not exist 428 func TestTransferReplicaRgNotExisted(t *testing.T) { 429 ctx := createContext(t, time.Second*common.DefaultTimeout) 430 // connect 431 mc := createMilvusClient(ctx, t) 432 resetRgs(t, ctx, mc) 433 434 // create new rg and transfer nodes 435 rgName := common.GenRandomString(6) 436 errCreate := mc.CreateResourceGroup(ctx, rgName) 437 common.CheckErr(t, errCreate, true) 438 mc.TransferNode(ctx, common.DefaultRgName, rgName, newRgNode) 439 440 // init collection: create -> insert -> index -> load 441 collName, _ := createCollectionWithDataIndex(ctx, t, mc, true, true) 442 mc.LoadCollection(ctx, collName, false, client.WithResourceGroups([]string{rgName})) 443 444 // source not exist 445 errSource := mc.TransferReplica(ctx, common.GenRandomString(6), common.DefaultRgName, collName, 1) 446 common.CheckErr(t, errSource, false, "resource group not found") 447 448 // target not exist 449 errTarget := mc.TransferReplica(ctx, common.DefaultRgName, common.GenRandomString(6), collName, 1) 450 common.CheckErr(t, errTarget, false, "resource group not found") 451 452 // transfer to self -> error 453 errSelf := mc.TransferReplica(ctx, rgName, rgName, collName, 1) 454 common.CheckErr(t, errSelf, false, "source resource group and target resource group should not be the same") 455 456 // transfer to default rg 457 errTransfer := mc.TransferReplica(ctx, rgName, common.DefaultRgName, collName, 1) 458 common.CheckErr(t, errTransfer, true) 459 newRg, _ := mc.DescribeResourceGroup(ctx, rgName) 460 log.Print(newRg) 461 expRg := &entity.ResourceGroup{ 462 Name: rgName, 463 Capacity: newRgNode, 464 AvailableNodesNumber: newRgNode, 465 IncomingNodeNum: map[string]int32{collName: newRgNode}, 466 } 467 common.CheckResourceGroup(t, newRg, expRg) 468 }