diff --git a/internal/datacoord/mock_test.go b/internal/datacoord/mock_test.go index a3f57fddae..fc4f25bd84 100644 --- a/internal/datacoord/mock_test.go +++ b/internal/datacoord/mock_test.go @@ -351,6 +351,14 @@ func (m *mockRootCoordClient) AlterAlias(ctx context.Context, req *milvuspb.Alte panic("implement me") } +func (m *mockRootCoordClient) DescribeAlias(ctx context.Context, req *milvuspb.DescribeAliasRequest, opts ...grpc.CallOption) (*milvuspb.DescribeAliasResponse, error) { + panic("implement me") +} + +func (m *mockRootCoordClient) ListAliases(ctx context.Context, req *milvuspb.ListAliasesRequest, opts ...grpc.CallOption) (*milvuspb.ListAliasesResponse, error) { + panic("implement me") +} + func newMockRootCoordClient() *mockRootCoordClient { return &mockRootCoordClient{state: commonpb.StateCode_Healthy} } diff --git a/internal/distributed/proxy/httpserver/handler_test.go b/internal/distributed/proxy/httpserver/handler_test.go index 7957888e22..cdfff887ca 100644 --- a/internal/distributed/proxy/httpserver/handler_test.go +++ b/internal/distributed/proxy/httpserver/handler_test.go @@ -139,6 +139,14 @@ func (m *mockProxyComponent) AlterAlias(ctx context.Context, request *milvuspb.A return testStatus, nil } +func (m *mockProxyComponent) DescribeAlias(ctx context.Context, request *milvuspb.DescribeAliasRequest) (*milvuspb.DescribeAliasResponse, error) { + return &milvuspb.DescribeAliasResponse{Status: testStatus}, nil +} + +func (m *mockProxyComponent) ListAliases(ctx context.Context, request *milvuspb.ListAliasesRequest) (*milvuspb.ListAliasesResponse, error) { + return &milvuspb.ListAliasesResponse{Status: testStatus}, nil +} + func (m *mockProxyComponent) CreateIndex(ctx context.Context, request *milvuspb.CreateIndexRequest) (*commonpb.Status, error) { return testStatus, nil } diff --git a/internal/distributed/proxy/service.go b/internal/distributed/proxy/service.go index 0c4328e3b1..04f4ad85d6 100644 --- a/internal/distributed/proxy/service.go +++ b/internal/distributed/proxy/service.go @@ -938,16 +938,14 @@ func (s *Server) AlterAlias(ctx context.Context, request *milvuspb.AlterAliasReq return s.proxy.AlterAlias(ctx, request) } +// DescribeAlias show the alias-collection relation for the specified alias. func (s *Server) DescribeAlias(ctx context.Context, request *milvuspb.DescribeAliasRequest) (*milvuspb.DescribeAliasResponse, error) { - return &milvuspb.DescribeAliasResponse{ - Status: merr.Status(merr.WrapErrServiceUnavailable("DescribeAlias unimplemented")), - }, nil + return s.proxy.DescribeAlias(ctx, request) } +// ListAliases list all the alias for the specified db, collection. func (s *Server) ListAliases(ctx context.Context, request *milvuspb.ListAliasesRequest) (*milvuspb.ListAliasesResponse, error) { - return &milvuspb.ListAliasesResponse{ - Status: merr.Status(merr.WrapErrServiceUnavailable("ListAliases unimplemented")), - }, nil + return s.proxy.ListAliases(ctx, request) } // GetCompactionState gets the state of a compaction diff --git a/internal/distributed/proxy/service_test.go b/internal/distributed/proxy/service_test.go index 1aedb9d1d1..68df2d29f2 100644 --- a/internal/distributed/proxy/service_test.go +++ b/internal/distributed/proxy/service_test.go @@ -62,7 +62,6 @@ func TestMain(m *testing.M) { } // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - type WaitOption struct { Duration time.Duration `json:"duration"` Port int `json:"port"` @@ -466,6 +465,18 @@ func Test_NewServer(t *testing.T) { assert.NoError(t, err) }) + t.Run("DescribeAlias", func(t *testing.T) { + mockProxy.EXPECT().DescribeAlias(mock.Anything, mock.Anything).Return(nil, nil) + _, err := server.DescribeAlias(ctx, nil) + assert.Nil(t, err) + }) + + t.Run("ListAliases", func(t *testing.T) { + mockProxy.EXPECT().ListAliases(mock.Anything, mock.Anything).Return(nil, nil) + _, err := server.ListAliases(ctx, nil) + assert.Nil(t, err) + }) + t.Run("GetCompactionState", func(t *testing.T) { mockProxy.EXPECT().GetCompactionState(mock.Anything, mock.Anything).Return(nil, nil) _, err := server.GetCompactionState(ctx, nil) diff --git a/internal/distributed/rootcoord/client/client.go b/internal/distributed/rootcoord/client/client.go index e5ab6f2a2c..c70f060ea6 100644 --- a/internal/distributed/rootcoord/client/client.go +++ b/internal/distributed/rootcoord/client/client.go @@ -417,6 +417,30 @@ func (c *Client) AlterAlias(ctx context.Context, req *milvuspb.AlterAliasRequest }) } +// DescribeAlias describe alias +func (c *Client) DescribeAlias(ctx context.Context, req *milvuspb.DescribeAliasRequest, opts ...grpc.CallOption) (*milvuspb.DescribeAliasResponse, error) { + req = typeutil.Clone(req) + commonpbutil.UpdateMsgBase( + req.GetBase(), + commonpbutil.FillMsgBaseFromClient(paramtable.GetNodeID(), commonpbutil.WithTargetID(c.grpcClient.GetNodeID())), + ) + return wrapGrpcCall(ctx, c, func(client rootcoordpb.RootCoordClient) (*milvuspb.DescribeAliasResponse, error) { + return client.DescribeAlias(ctx, req) + }) +} + +// ListAliases list all aliases of db or collection +func (c *Client) ListAliases(ctx context.Context, req *milvuspb.ListAliasesRequest, opts ...grpc.CallOption) (*milvuspb.ListAliasesResponse, error) { + req = typeutil.Clone(req) + commonpbutil.UpdateMsgBase( + req.GetBase(), + commonpbutil.FillMsgBaseFromClient(paramtable.GetNodeID(), commonpbutil.WithTargetID(c.grpcClient.GetNodeID())), + ) + return wrapGrpcCall(ctx, c, func(client rootcoordpb.RootCoordClient) (*milvuspb.ListAliasesResponse, error) { + return client.ListAliases(ctx, req) + }) +} + // Import data files(json, numpy, etc.) on MinIO/S3 storage, read and parse them into sealed segments func (c *Client) Import(ctx context.Context, req *milvuspb.ImportRequest, opts ...grpc.CallOption) (*milvuspb.ImportResponse, error) { return wrapGrpcCall(ctx, c, func(client rootcoordpb.RootCoordClient) (*milvuspb.ImportResponse, error) { diff --git a/internal/distributed/rootcoord/client/client_test.go b/internal/distributed/rootcoord/client/client_test.go index ce5c45a445..e38235beef 100644 --- a/internal/distributed/rootcoord/client/client_test.go +++ b/internal/distributed/rootcoord/client/client_test.go @@ -152,6 +152,14 @@ func Test_NewClient(t *testing.T) { r, err := client.AlterAlias(ctx, nil) retCheck(retNotNil, r, err) } + { + r, err := client.DescribeAlias(ctx, nil) + retCheck(retNotNil, r, err) + } + { + r, err := client.ListAliases(ctx, nil) + retCheck(retNotNil, r, err) + } { r, err := client.Import(ctx, nil) retCheck(retNotNil, r, err) @@ -366,6 +374,14 @@ func Test_NewClient(t *testing.T) { rTimeout, err := client.AlterAlias(shortCtx, nil) retCheck(rTimeout, err) } + { + rTimeout, err := client.DescribeAlias(shortCtx, nil) + retCheck(rTimeout, err) + } + { + rTimeout, err := client.ListAliases(shortCtx, nil) + retCheck(rTimeout, err) + } { rTimeout, err := client.Import(shortCtx, nil) retCheck(rTimeout, err) diff --git a/internal/distributed/rootcoord/service.go b/internal/distributed/rootcoord/service.go index 3b478fed32..7d8bb0af49 100644 --- a/internal/distributed/rootcoord/service.go +++ b/internal/distributed/rootcoord/service.go @@ -108,6 +108,16 @@ func (s *Server) AlterAlias(ctx context.Context, request *milvuspb.AlterAliasReq return s.rootCoord.AlterAlias(ctx, request) } +// DescribeAlias show the alias-collection relation for the specified alias. +func (s *Server) DescribeAlias(ctx context.Context, request *milvuspb.DescribeAliasRequest) (*milvuspb.DescribeAliasResponse, error) { + return s.rootCoord.DescribeAlias(ctx, request) +} + +// ListAliases show all alias in db. +func (s *Server) ListAliases(ctx context.Context, request *milvuspb.ListAliasesRequest) (*milvuspb.ListAliasesResponse, error) { + return s.rootCoord.ListAliases(ctx, request) +} + // NewServer create a new RootCoord grpc server. func NewServer(ctx context.Context, factory dependency.Factory) (*Server, error) { ctx1, cancel := context.WithCancel(ctx) diff --git a/internal/mocks/mock_rootcoord.go b/internal/mocks/mock_rootcoord.go index 56dcb5490a..65fe9c8d88 100644 --- a/internal/mocks/mock_rootcoord.go +++ b/internal/mocks/mock_rootcoord.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.32.4. DO NOT EDIT. +// Code generated by mockery v2.38.0. DO NOT EDIT. package mocks @@ -6,7 +6,6 @@ import ( context "context" commonpb "github.com/milvus-io/milvus-proto/go-api/v2/commonpb" - clientv3 "go.etcd.io/etcd/client/v3" internalpb "github.com/milvus-io/milvus/internal/proto/internalpb" @@ -17,13 +16,9 @@ import ( proxypb "github.com/milvus-io/milvus/internal/proto/proxypb" rootcoordpb "github.com/milvus-io/milvus/internal/proto/rootcoordpb" - - txnkv "github.com/tikv/client-go/v2/txnkv" - - types "github.com/milvus-io/milvus/internal/types" ) -// RootCoord is an autogenerated mock type for the RootCoordComponent type +// RootCoord is an autogenerated mock type for the RootCoord type type RootCoord struct { mock.Mock } @@ -40,6 +35,10 @@ func (_m *RootCoord) EXPECT() *RootCoord_Expecter { func (_m *RootCoord) AllocID(_a0 context.Context, _a1 *rootcoordpb.AllocIDRequest) (*rootcoordpb.AllocIDResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for AllocID") + } + var r0 *rootcoordpb.AllocIDResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *rootcoordpb.AllocIDRequest) (*rootcoordpb.AllocIDResponse, error)); ok { @@ -95,6 +94,10 @@ func (_c *RootCoord_AllocID_Call) RunAndReturn(run func(context.Context, *rootco func (_m *RootCoord) AllocTimestamp(_a0 context.Context, _a1 *rootcoordpb.AllocTimestampRequest) (*rootcoordpb.AllocTimestampResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for AllocTimestamp") + } + var r0 *rootcoordpb.AllocTimestampResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *rootcoordpb.AllocTimestampRequest) (*rootcoordpb.AllocTimestampResponse, error)); ok { @@ -150,6 +153,10 @@ func (_c *RootCoord_AllocTimestamp_Call) RunAndReturn(run func(context.Context, func (_m *RootCoord) AlterAlias(_a0 context.Context, _a1 *milvuspb.AlterAliasRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for AlterAlias") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.AlterAliasRequest) (*commonpb.Status, error)); ok { @@ -205,6 +212,10 @@ func (_c *RootCoord_AlterAlias_Call) RunAndReturn(run func(context.Context, *mil func (_m *RootCoord) AlterCollection(_a0 context.Context, _a1 *milvuspb.AlterCollectionRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for AlterCollection") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.AlterCollectionRequest) (*commonpb.Status, error)); ok { @@ -260,6 +271,10 @@ func (_c *RootCoord_AlterCollection_Call) RunAndReturn(run func(context.Context, func (_m *RootCoord) CheckHealth(_a0 context.Context, _a1 *milvuspb.CheckHealthRequest) (*milvuspb.CheckHealthResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for CheckHealth") + } + var r0 *milvuspb.CheckHealthResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.CheckHealthRequest) (*milvuspb.CheckHealthResponse, error)); ok { @@ -315,6 +330,10 @@ func (_c *RootCoord_CheckHealth_Call) RunAndReturn(run func(context.Context, *mi func (_m *RootCoord) CreateAlias(_a0 context.Context, _a1 *milvuspb.CreateAliasRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for CreateAlias") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.CreateAliasRequest) (*commonpb.Status, error)); ok { @@ -370,6 +389,10 @@ func (_c *RootCoord_CreateAlias_Call) RunAndReturn(run func(context.Context, *mi func (_m *RootCoord) CreateCollection(_a0 context.Context, _a1 *milvuspb.CreateCollectionRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for CreateCollection") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.CreateCollectionRequest) (*commonpb.Status, error)); ok { @@ -425,6 +448,10 @@ func (_c *RootCoord_CreateCollection_Call) RunAndReturn(run func(context.Context func (_m *RootCoord) CreateCredential(_a0 context.Context, _a1 *internalpb.CredentialInfo) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for CreateCredential") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *internalpb.CredentialInfo) (*commonpb.Status, error)); ok { @@ -480,6 +507,10 @@ func (_c *RootCoord_CreateCredential_Call) RunAndReturn(run func(context.Context func (_m *RootCoord) CreateDatabase(_a0 context.Context, _a1 *milvuspb.CreateDatabaseRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for CreateDatabase") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.CreateDatabaseRequest) (*commonpb.Status, error)); ok { @@ -535,6 +566,10 @@ func (_c *RootCoord_CreateDatabase_Call) RunAndReturn(run func(context.Context, func (_m *RootCoord) CreatePartition(_a0 context.Context, _a1 *milvuspb.CreatePartitionRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for CreatePartition") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.CreatePartitionRequest) (*commonpb.Status, error)); ok { @@ -590,6 +625,10 @@ func (_c *RootCoord_CreatePartition_Call) RunAndReturn(run func(context.Context, func (_m *RootCoord) CreateRole(_a0 context.Context, _a1 *milvuspb.CreateRoleRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for CreateRole") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.CreateRoleRequest) (*commonpb.Status, error)); ok { @@ -645,6 +684,10 @@ func (_c *RootCoord_CreateRole_Call) RunAndReturn(run func(context.Context, *mil func (_m *RootCoord) DeleteCredential(_a0 context.Context, _a1 *milvuspb.DeleteCredentialRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for DeleteCredential") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DeleteCredentialRequest) (*commonpb.Status, error)); ok { @@ -696,10 +739,73 @@ func (_c *RootCoord_DeleteCredential_Call) RunAndReturn(run func(context.Context return _c } +// DescribeAlias provides a mock function with given fields: _a0, _a1 +func (_m *RootCoord) DescribeAlias(_a0 context.Context, _a1 *milvuspb.DescribeAliasRequest) (*milvuspb.DescribeAliasResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for DescribeAlias") + } + + var r0 *milvuspb.DescribeAliasResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DescribeAliasRequest) (*milvuspb.DescribeAliasResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DescribeAliasRequest) *milvuspb.DescribeAliasResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*milvuspb.DescribeAliasResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.DescribeAliasRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// RootCoord_DescribeAlias_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DescribeAlias' +type RootCoord_DescribeAlias_Call struct { + *mock.Call +} + +// DescribeAlias is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *milvuspb.DescribeAliasRequest +func (_e *RootCoord_Expecter) DescribeAlias(_a0 interface{}, _a1 interface{}) *RootCoord_DescribeAlias_Call { + return &RootCoord_DescribeAlias_Call{Call: _e.mock.On("DescribeAlias", _a0, _a1)} +} + +func (_c *RootCoord_DescribeAlias_Call) Run(run func(_a0 context.Context, _a1 *milvuspb.DescribeAliasRequest)) *RootCoord_DescribeAlias_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*milvuspb.DescribeAliasRequest)) + }) + return _c +} + +func (_c *RootCoord_DescribeAlias_Call) Return(_a0 *milvuspb.DescribeAliasResponse, _a1 error) *RootCoord_DescribeAlias_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *RootCoord_DescribeAlias_Call) RunAndReturn(run func(context.Context, *milvuspb.DescribeAliasRequest) (*milvuspb.DescribeAliasResponse, error)) *RootCoord_DescribeAlias_Call { + _c.Call.Return(run) + return _c +} + // DescribeCollection provides a mock function with given fields: _a0, _a1 func (_m *RootCoord) DescribeCollection(_a0 context.Context, _a1 *milvuspb.DescribeCollectionRequest) (*milvuspb.DescribeCollectionResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for DescribeCollection") + } + var r0 *milvuspb.DescribeCollectionResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DescribeCollectionRequest) (*milvuspb.DescribeCollectionResponse, error)); ok { @@ -755,6 +861,10 @@ func (_c *RootCoord_DescribeCollection_Call) RunAndReturn(run func(context.Conte func (_m *RootCoord) DescribeCollectionInternal(_a0 context.Context, _a1 *milvuspb.DescribeCollectionRequest) (*milvuspb.DescribeCollectionResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for DescribeCollectionInternal") + } + var r0 *milvuspb.DescribeCollectionResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DescribeCollectionRequest) (*milvuspb.DescribeCollectionResponse, error)); ok { @@ -810,6 +920,10 @@ func (_c *RootCoord_DescribeCollectionInternal_Call) RunAndReturn(run func(conte func (_m *RootCoord) DropAlias(_a0 context.Context, _a1 *milvuspb.DropAliasRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for DropAlias") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DropAliasRequest) (*commonpb.Status, error)); ok { @@ -865,6 +979,10 @@ func (_c *RootCoord_DropAlias_Call) RunAndReturn(run func(context.Context, *milv func (_m *RootCoord) DropCollection(_a0 context.Context, _a1 *milvuspb.DropCollectionRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for DropCollection") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DropCollectionRequest) (*commonpb.Status, error)); ok { @@ -920,6 +1038,10 @@ func (_c *RootCoord_DropCollection_Call) RunAndReturn(run func(context.Context, func (_m *RootCoord) DropDatabase(_a0 context.Context, _a1 *milvuspb.DropDatabaseRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for DropDatabase") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DropDatabaseRequest) (*commonpb.Status, error)); ok { @@ -975,6 +1097,10 @@ func (_c *RootCoord_DropDatabase_Call) RunAndReturn(run func(context.Context, *m func (_m *RootCoord) DropPartition(_a0 context.Context, _a1 *milvuspb.DropPartitionRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for DropPartition") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DropPartitionRequest) (*commonpb.Status, error)); ok { @@ -1030,6 +1156,10 @@ func (_c *RootCoord_DropPartition_Call) RunAndReturn(run func(context.Context, * func (_m *RootCoord) DropRole(_a0 context.Context, _a1 *milvuspb.DropRoleRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for DropRole") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DropRoleRequest) (*commonpb.Status, error)); ok { @@ -1085,6 +1215,10 @@ func (_c *RootCoord_DropRole_Call) RunAndReturn(run func(context.Context, *milvu func (_m *RootCoord) GetComponentStates(_a0 context.Context, _a1 *milvuspb.GetComponentStatesRequest) (*milvuspb.ComponentStates, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for GetComponentStates") + } + var r0 *milvuspb.ComponentStates var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.GetComponentStatesRequest) (*milvuspb.ComponentStates, error)); ok { @@ -1140,6 +1274,10 @@ func (_c *RootCoord_GetComponentStates_Call) RunAndReturn(run func(context.Conte func (_m *RootCoord) GetCredential(_a0 context.Context, _a1 *rootcoordpb.GetCredentialRequest) (*rootcoordpb.GetCredentialResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for GetCredential") + } + var r0 *rootcoordpb.GetCredentialResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *rootcoordpb.GetCredentialRequest) (*rootcoordpb.GetCredentialResponse, error)); ok { @@ -1195,6 +1333,10 @@ func (_c *RootCoord_GetCredential_Call) RunAndReturn(run func(context.Context, * func (_m *RootCoord) GetImportState(_a0 context.Context, _a1 *milvuspb.GetImportStateRequest) (*milvuspb.GetImportStateResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for GetImportState") + } + var r0 *milvuspb.GetImportStateResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.GetImportStateRequest) (*milvuspb.GetImportStateResponse, error)); ok { @@ -1246,17 +1388,21 @@ func (_c *RootCoord_GetImportState_Call) RunAndReturn(run func(context.Context, return _c } -// GetMetrics provides a mock function with given fields: ctx, req -func (_m *RootCoord) GetMetrics(ctx context.Context, req *milvuspb.GetMetricsRequest) (*milvuspb.GetMetricsResponse, error) { - ret := _m.Called(ctx, req) +// GetMetrics provides a mock function with given fields: _a0, _a1 +func (_m *RootCoord) GetMetrics(_a0 context.Context, _a1 *milvuspb.GetMetricsRequest) (*milvuspb.GetMetricsResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for GetMetrics") + } var r0 *milvuspb.GetMetricsResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.GetMetricsRequest) (*milvuspb.GetMetricsResponse, error)); ok { - return rf(ctx, req) + return rf(_a0, _a1) } if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.GetMetricsRequest) *milvuspb.GetMetricsResponse); ok { - r0 = rf(ctx, req) + r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*milvuspb.GetMetricsResponse) @@ -1264,7 +1410,7 @@ func (_m *RootCoord) GetMetrics(ctx context.Context, req *milvuspb.GetMetricsReq } if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.GetMetricsRequest) error); ok { - r1 = rf(ctx, req) + r1 = rf(_a0, _a1) } else { r1 = ret.Error(1) } @@ -1278,13 +1424,13 @@ type RootCoord_GetMetrics_Call struct { } // GetMetrics is a helper method to define mock.On call -// - ctx context.Context -// - req *milvuspb.GetMetricsRequest -func (_e *RootCoord_Expecter) GetMetrics(ctx interface{}, req interface{}) *RootCoord_GetMetrics_Call { - return &RootCoord_GetMetrics_Call{Call: _e.mock.On("GetMetrics", ctx, req)} +// - _a0 context.Context +// - _a1 *milvuspb.GetMetricsRequest +func (_e *RootCoord_Expecter) GetMetrics(_a0 interface{}, _a1 interface{}) *RootCoord_GetMetrics_Call { + return &RootCoord_GetMetrics_Call{Call: _e.mock.On("GetMetrics", _a0, _a1)} } -func (_c *RootCoord_GetMetrics_Call) Run(run func(ctx context.Context, req *milvuspb.GetMetricsRequest)) *RootCoord_GetMetrics_Call { +func (_c *RootCoord_GetMetrics_Call) Run(run func(_a0 context.Context, _a1 *milvuspb.GetMetricsRequest)) *RootCoord_GetMetrics_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(*milvuspb.GetMetricsRequest)) }) @@ -1305,6 +1451,10 @@ func (_c *RootCoord_GetMetrics_Call) RunAndReturn(run func(context.Context, *mil func (_m *RootCoord) GetStatisticsChannel(_a0 context.Context, _a1 *internalpb.GetStatisticsChannelRequest) (*milvuspb.StringResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for GetStatisticsChannel") + } + var r0 *milvuspb.StringResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *internalpb.GetStatisticsChannelRequest) (*milvuspb.StringResponse, error)); ok { @@ -1360,6 +1510,10 @@ func (_c *RootCoord_GetStatisticsChannel_Call) RunAndReturn(run func(context.Con func (_m *RootCoord) GetTimeTickChannel(_a0 context.Context, _a1 *internalpb.GetTimeTickChannelRequest) (*milvuspb.StringResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for GetTimeTickChannel") + } + var r0 *milvuspb.StringResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *internalpb.GetTimeTickChannelRequest) (*milvuspb.StringResponse, error)); ok { @@ -1415,6 +1569,10 @@ func (_c *RootCoord_GetTimeTickChannel_Call) RunAndReturn(run func(context.Conte func (_m *RootCoord) HasCollection(_a0 context.Context, _a1 *milvuspb.HasCollectionRequest) (*milvuspb.BoolResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for HasCollection") + } + var r0 *milvuspb.BoolResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.HasCollectionRequest) (*milvuspb.BoolResponse, error)); ok { @@ -1470,6 +1628,10 @@ func (_c *RootCoord_HasCollection_Call) RunAndReturn(run func(context.Context, * func (_m *RootCoord) HasPartition(_a0 context.Context, _a1 *milvuspb.HasPartitionRequest) (*milvuspb.BoolResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for HasPartition") + } + var r0 *milvuspb.BoolResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.HasPartitionRequest) (*milvuspb.BoolResponse, error)); ok { @@ -1525,6 +1687,10 @@ func (_c *RootCoord_HasPartition_Call) RunAndReturn(run func(context.Context, *m func (_m *RootCoord) Import(_a0 context.Context, _a1 *milvuspb.ImportRequest) (*milvuspb.ImportResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for Import") + } + var r0 *milvuspb.ImportResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ImportRequest) (*milvuspb.ImportResponse, error)); ok { @@ -1580,6 +1746,10 @@ func (_c *RootCoord_Import_Call) RunAndReturn(run func(context.Context, *milvusp func (_m *RootCoord) Init() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Init") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -1621,6 +1791,10 @@ func (_c *RootCoord_Init_Call) RunAndReturn(run func() error) *RootCoord_Init_Ca func (_m *RootCoord) InvalidateCollectionMetaCache(_a0 context.Context, _a1 *proxypb.InvalidateCollMetaCacheRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for InvalidateCollectionMetaCache") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *proxypb.InvalidateCollMetaCacheRequest) (*commonpb.Status, error)); ok { @@ -1672,10 +1846,73 @@ func (_c *RootCoord_InvalidateCollectionMetaCache_Call) RunAndReturn(run func(co return _c } +// ListAliases provides a mock function with given fields: _a0, _a1 +func (_m *RootCoord) ListAliases(_a0 context.Context, _a1 *milvuspb.ListAliasesRequest) (*milvuspb.ListAliasesResponse, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for ListAliases") + } + + var r0 *milvuspb.ListAliasesResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ListAliasesRequest) (*milvuspb.ListAliasesResponse, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ListAliasesRequest) *milvuspb.ListAliasesResponse); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*milvuspb.ListAliasesResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.ListAliasesRequest) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// RootCoord_ListAliases_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListAliases' +type RootCoord_ListAliases_Call struct { + *mock.Call +} + +// ListAliases is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *milvuspb.ListAliasesRequest +func (_e *RootCoord_Expecter) ListAliases(_a0 interface{}, _a1 interface{}) *RootCoord_ListAliases_Call { + return &RootCoord_ListAliases_Call{Call: _e.mock.On("ListAliases", _a0, _a1)} +} + +func (_c *RootCoord_ListAliases_Call) Run(run func(_a0 context.Context, _a1 *milvuspb.ListAliasesRequest)) *RootCoord_ListAliases_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*milvuspb.ListAliasesRequest)) + }) + return _c +} + +func (_c *RootCoord_ListAliases_Call) Return(_a0 *milvuspb.ListAliasesResponse, _a1 error) *RootCoord_ListAliases_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *RootCoord_ListAliases_Call) RunAndReturn(run func(context.Context, *milvuspb.ListAliasesRequest) (*milvuspb.ListAliasesResponse, error)) *RootCoord_ListAliases_Call { + _c.Call.Return(run) + return _c +} + // ListCredUsers provides a mock function with given fields: _a0, _a1 func (_m *RootCoord) ListCredUsers(_a0 context.Context, _a1 *milvuspb.ListCredUsersRequest) (*milvuspb.ListCredUsersResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for ListCredUsers") + } + var r0 *milvuspb.ListCredUsersResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ListCredUsersRequest) (*milvuspb.ListCredUsersResponse, error)); ok { @@ -1731,6 +1968,10 @@ func (_c *RootCoord_ListCredUsers_Call) RunAndReturn(run func(context.Context, * func (_m *RootCoord) ListDatabases(_a0 context.Context, _a1 *milvuspb.ListDatabasesRequest) (*milvuspb.ListDatabasesResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for ListDatabases") + } + var r0 *milvuspb.ListDatabasesResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ListDatabasesRequest) (*milvuspb.ListDatabasesResponse, error)); ok { @@ -1786,6 +2027,10 @@ func (_c *RootCoord_ListDatabases_Call) RunAndReturn(run func(context.Context, * func (_m *RootCoord) ListImportTasks(_a0 context.Context, _a1 *milvuspb.ListImportTasksRequest) (*milvuspb.ListImportTasksResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for ListImportTasks") + } + var r0 *milvuspb.ListImportTasksResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ListImportTasksRequest) (*milvuspb.ListImportTasksResponse, error)); ok { @@ -1841,6 +2086,10 @@ func (_c *RootCoord_ListImportTasks_Call) RunAndReturn(run func(context.Context, func (_m *RootCoord) ListPolicy(_a0 context.Context, _a1 *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for ListPolicy") + } + var r0 *internalpb.ListPolicyResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *internalpb.ListPolicyRequest) (*internalpb.ListPolicyResponse, error)); ok { @@ -1896,6 +2145,10 @@ func (_c *RootCoord_ListPolicy_Call) RunAndReturn(run func(context.Context, *int func (_m *RootCoord) OperatePrivilege(_a0 context.Context, _a1 *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for OperatePrivilege") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.OperatePrivilegeRequest) (*commonpb.Status, error)); ok { @@ -1951,6 +2204,10 @@ func (_c *RootCoord_OperatePrivilege_Call) RunAndReturn(run func(context.Context func (_m *RootCoord) OperateUserRole(_a0 context.Context, _a1 *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for OperateUserRole") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.OperateUserRoleRequest) (*commonpb.Status, error)); ok { @@ -2006,6 +2263,10 @@ func (_c *RootCoord_OperateUserRole_Call) RunAndReturn(run func(context.Context, func (_m *RootCoord) Register() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Register") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -2047,6 +2308,10 @@ func (_c *RootCoord_Register_Call) RunAndReturn(run func() error) *RootCoord_Reg func (_m *RootCoord) RenameCollection(_a0 context.Context, _a1 *milvuspb.RenameCollectionRequest) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for RenameCollection") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.RenameCollectionRequest) (*commonpb.Status, error)); ok { @@ -2102,6 +2367,10 @@ func (_c *RootCoord_RenameCollection_Call) RunAndReturn(run func(context.Context func (_m *RootCoord) ReportImport(_a0 context.Context, _a1 *rootcoordpb.ImportResult) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for ReportImport") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *rootcoordpb.ImportResult) (*commonpb.Status, error)); ok { @@ -2157,6 +2426,10 @@ func (_c *RootCoord_ReportImport_Call) RunAndReturn(run func(context.Context, *r func (_m *RootCoord) SelectGrant(_a0 context.Context, _a1 *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for SelectGrant") + } + var r0 *milvuspb.SelectGrantResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.SelectGrantRequest) (*milvuspb.SelectGrantResponse, error)); ok { @@ -2212,6 +2485,10 @@ func (_c *RootCoord_SelectGrant_Call) RunAndReturn(run func(context.Context, *mi func (_m *RootCoord) SelectRole(_a0 context.Context, _a1 *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for SelectRole") + } + var r0 *milvuspb.SelectRoleResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.SelectRoleRequest) (*milvuspb.SelectRoleResponse, error)); ok { @@ -2267,6 +2544,10 @@ func (_c *RootCoord_SelectRole_Call) RunAndReturn(run func(context.Context, *mil func (_m *RootCoord) SelectUser(_a0 context.Context, _a1 *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for SelectUser") + } + var r0 *milvuspb.SelectUserResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.SelectUserRequest) (*milvuspb.SelectUserResponse, error)); ok { @@ -2318,226 +2599,14 @@ func (_c *RootCoord_SelectUser_Call) RunAndReturn(run func(context.Context, *mil return _c } -// SetAddress provides a mock function with given fields: address -func (_m *RootCoord) SetAddress(address string) { - _m.Called(address) -} - -// RootCoord_SetAddress_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetAddress' -type RootCoord_SetAddress_Call struct { - *mock.Call -} - -// SetAddress is a helper method to define mock.On call -// - address string -func (_e *RootCoord_Expecter) SetAddress(address interface{}) *RootCoord_SetAddress_Call { - return &RootCoord_SetAddress_Call{Call: _e.mock.On("SetAddress", address)} -} - -func (_c *RootCoord_SetAddress_Call) Run(run func(address string)) *RootCoord_SetAddress_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string)) - }) - return _c -} - -func (_c *RootCoord_SetAddress_Call) Return() *RootCoord_SetAddress_Call { - _c.Call.Return() - return _c -} - -func (_c *RootCoord_SetAddress_Call) RunAndReturn(run func(string)) *RootCoord_SetAddress_Call { - _c.Call.Return(run) - return _c -} - -// SetDataCoordClient provides a mock function with given fields: dataCoord -func (_m *RootCoord) SetDataCoordClient(dataCoord types.DataCoordClient) error { - ret := _m.Called(dataCoord) - - var r0 error - if rf, ok := ret.Get(0).(func(types.DataCoordClient) error); ok { - r0 = rf(dataCoord) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// RootCoord_SetDataCoordClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetDataCoordClient' -type RootCoord_SetDataCoordClient_Call struct { - *mock.Call -} - -// SetDataCoordClient is a helper method to define mock.On call -// - dataCoord types.DataCoordClient -func (_e *RootCoord_Expecter) SetDataCoordClient(dataCoord interface{}) *RootCoord_SetDataCoordClient_Call { - return &RootCoord_SetDataCoordClient_Call{Call: _e.mock.On("SetDataCoordClient", dataCoord)} -} - -func (_c *RootCoord_SetDataCoordClient_Call) Run(run func(dataCoord types.DataCoordClient)) *RootCoord_SetDataCoordClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.DataCoordClient)) - }) - return _c -} - -func (_c *RootCoord_SetDataCoordClient_Call) Return(_a0 error) *RootCoord_SetDataCoordClient_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *RootCoord_SetDataCoordClient_Call) RunAndReturn(run func(types.DataCoordClient) error) *RootCoord_SetDataCoordClient_Call { - _c.Call.Return(run) - return _c -} - -// SetEtcdClient provides a mock function with given fields: etcdClient -func (_m *RootCoord) SetEtcdClient(etcdClient *clientv3.Client) { - _m.Called(etcdClient) -} - -// RootCoord_SetEtcdClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetEtcdClient' -type RootCoord_SetEtcdClient_Call struct { - *mock.Call -} - -// SetEtcdClient is a helper method to define mock.On call -// - etcdClient *clientv3.Client -func (_e *RootCoord_Expecter) SetEtcdClient(etcdClient interface{}) *RootCoord_SetEtcdClient_Call { - return &RootCoord_SetEtcdClient_Call{Call: _e.mock.On("SetEtcdClient", etcdClient)} -} - -func (_c *RootCoord_SetEtcdClient_Call) Run(run func(etcdClient *clientv3.Client)) *RootCoord_SetEtcdClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*clientv3.Client)) - }) - return _c -} - -func (_c *RootCoord_SetEtcdClient_Call) Return() *RootCoord_SetEtcdClient_Call { - _c.Call.Return() - return _c -} - -func (_c *RootCoord_SetEtcdClient_Call) RunAndReturn(run func(*clientv3.Client)) *RootCoord_SetEtcdClient_Call { - _c.Call.Return(run) - return _c -} - -// SetProxyCreator provides a mock function with given fields: _a0 -func (_m *RootCoord) SetProxyCreator(_a0 func(context.Context, string, int64) (types.ProxyClient, error)) { - _m.Called(_a0) -} - -// RootCoord_SetProxyCreator_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetProxyCreator' -type RootCoord_SetProxyCreator_Call struct { - *mock.Call -} - -// SetProxyCreator is a helper method to define mock.On call -// - _a0 func(context.Context , string , int64)(types.ProxyClient , error) -func (_e *RootCoord_Expecter) SetProxyCreator(_a0 interface{}) *RootCoord_SetProxyCreator_Call { - return &RootCoord_SetProxyCreator_Call{Call: _e.mock.On("SetProxyCreator", _a0)} -} - -func (_c *RootCoord_SetProxyCreator_Call) Run(run func(_a0 func(context.Context, string, int64) (types.ProxyClient, error))) *RootCoord_SetProxyCreator_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(func(context.Context, string, int64) (types.ProxyClient, error))) - }) - return _c -} - -func (_c *RootCoord_SetProxyCreator_Call) Return() *RootCoord_SetProxyCreator_Call { - _c.Call.Return() - return _c -} - -func (_c *RootCoord_SetProxyCreator_Call) RunAndReturn(run func(func(context.Context, string, int64) (types.ProxyClient, error))) *RootCoord_SetProxyCreator_Call { - _c.Call.Return(run) - return _c -} - -// SetQueryCoordClient provides a mock function with given fields: queryCoord -func (_m *RootCoord) SetQueryCoordClient(queryCoord types.QueryCoordClient) error { - ret := _m.Called(queryCoord) - - var r0 error - if rf, ok := ret.Get(0).(func(types.QueryCoordClient) error); ok { - r0 = rf(queryCoord) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// RootCoord_SetQueryCoordClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetQueryCoordClient' -type RootCoord_SetQueryCoordClient_Call struct { - *mock.Call -} - -// SetQueryCoordClient is a helper method to define mock.On call -// - queryCoord types.QueryCoordClient -func (_e *RootCoord_Expecter) SetQueryCoordClient(queryCoord interface{}) *RootCoord_SetQueryCoordClient_Call { - return &RootCoord_SetQueryCoordClient_Call{Call: _e.mock.On("SetQueryCoordClient", queryCoord)} -} - -func (_c *RootCoord_SetQueryCoordClient_Call) Run(run func(queryCoord types.QueryCoordClient)) *RootCoord_SetQueryCoordClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.QueryCoordClient)) - }) - return _c -} - -func (_c *RootCoord_SetQueryCoordClient_Call) Return(_a0 error) *RootCoord_SetQueryCoordClient_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *RootCoord_SetQueryCoordClient_Call) RunAndReturn(run func(types.QueryCoordClient) error) *RootCoord_SetQueryCoordClient_Call { - _c.Call.Return(run) - return _c -} - -// SetTiKVClient provides a mock function with given fields: client -func (_m *RootCoord) SetTiKVClient(client *txnkv.Client) { - _m.Called(client) -} - -// RootCoord_SetTiKVClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetTiKVClient' -type RootCoord_SetTiKVClient_Call struct { - *mock.Call -} - -// SetTiKVClient is a helper method to define mock.On call -// - client *txnkv.Client -func (_e *RootCoord_Expecter) SetTiKVClient(client interface{}) *RootCoord_SetTiKVClient_Call { - return &RootCoord_SetTiKVClient_Call{Call: _e.mock.On("SetTiKVClient", client)} -} - -func (_c *RootCoord_SetTiKVClient_Call) Run(run func(client *txnkv.Client)) *RootCoord_SetTiKVClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*txnkv.Client)) - }) - return _c -} - -func (_c *RootCoord_SetTiKVClient_Call) Return() *RootCoord_SetTiKVClient_Call { - _c.Call.Return() - return _c -} - -func (_c *RootCoord_SetTiKVClient_Call) RunAndReturn(run func(*txnkv.Client)) *RootCoord_SetTiKVClient_Call { - _c.Call.Return(run) - return _c -} - // ShowCollections provides a mock function with given fields: _a0, _a1 func (_m *RootCoord) ShowCollections(_a0 context.Context, _a1 *milvuspb.ShowCollectionsRequest) (*milvuspb.ShowCollectionsResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for ShowCollections") + } + var r0 *milvuspb.ShowCollectionsResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ShowCollectionsRequest) (*milvuspb.ShowCollectionsResponse, error)); ok { @@ -2593,6 +2662,10 @@ func (_c *RootCoord_ShowCollections_Call) RunAndReturn(run func(context.Context, func (_m *RootCoord) ShowConfigurations(_a0 context.Context, _a1 *internalpb.ShowConfigurationsRequest) (*internalpb.ShowConfigurationsResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for ShowConfigurations") + } + var r0 *internalpb.ShowConfigurationsResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *internalpb.ShowConfigurationsRequest) (*internalpb.ShowConfigurationsResponse, error)); ok { @@ -2648,6 +2721,10 @@ func (_c *RootCoord_ShowConfigurations_Call) RunAndReturn(run func(context.Conte func (_m *RootCoord) ShowPartitions(_a0 context.Context, _a1 *milvuspb.ShowPartitionsRequest) (*milvuspb.ShowPartitionsResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for ShowPartitions") + } + var r0 *milvuspb.ShowPartitionsResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ShowPartitionsRequest) (*milvuspb.ShowPartitionsResponse, error)); ok { @@ -2703,6 +2780,10 @@ func (_c *RootCoord_ShowPartitions_Call) RunAndReturn(run func(context.Context, func (_m *RootCoord) ShowPartitionsInternal(_a0 context.Context, _a1 *milvuspb.ShowPartitionsRequest) (*milvuspb.ShowPartitionsResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for ShowPartitionsInternal") + } + var r0 *milvuspb.ShowPartitionsResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ShowPartitionsRequest) (*milvuspb.ShowPartitionsResponse, error)); ok { @@ -2758,6 +2839,10 @@ func (_c *RootCoord_ShowPartitionsInternal_Call) RunAndReturn(run func(context.C func (_m *RootCoord) ShowSegments(_a0 context.Context, _a1 *milvuspb.ShowSegmentsRequest) (*milvuspb.ShowSegmentsResponse, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for ShowSegments") + } + var r0 *milvuspb.ShowSegmentsResponse var r1 error if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ShowSegmentsRequest) (*milvuspb.ShowSegmentsResponse, error)); ok { @@ -2813,6 +2898,10 @@ func (_c *RootCoord_ShowSegments_Call) RunAndReturn(run func(context.Context, *m func (_m *RootCoord) Start() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Start") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -2854,6 +2943,10 @@ func (_c *RootCoord_Start_Call) RunAndReturn(run func() error) *RootCoord_Start_ func (_m *RootCoord) Stop() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Stop") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -2895,6 +2988,10 @@ func (_c *RootCoord_Stop_Call) RunAndReturn(run func() error) *RootCoord_Stop_Ca func (_m *RootCoord) UpdateChannelTimeTick(_a0 context.Context, _a1 *internalpb.ChannelTimeTickMsg) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for UpdateChannelTimeTick") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *internalpb.ChannelTimeTickMsg) (*commonpb.Status, error)); ok { @@ -2950,6 +3047,10 @@ func (_c *RootCoord_UpdateChannelTimeTick_Call) RunAndReturn(run func(context.Co func (_m *RootCoord) UpdateCredential(_a0 context.Context, _a1 *internalpb.CredentialInfo) (*commonpb.Status, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for UpdateCredential") + } + var r0 *commonpb.Status var r1 error if rf, ok := ret.Get(0).(func(context.Context, *internalpb.CredentialInfo) (*commonpb.Status, error)); ok { @@ -3001,39 +3102,6 @@ func (_c *RootCoord_UpdateCredential_Call) RunAndReturn(run func(context.Context return _c } -// UpdateStateCode provides a mock function with given fields: _a0 -func (_m *RootCoord) UpdateStateCode(_a0 commonpb.StateCode) { - _m.Called(_a0) -} - -// RootCoord_UpdateStateCode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateStateCode' -type RootCoord_UpdateStateCode_Call struct { - *mock.Call -} - -// UpdateStateCode is a helper method to define mock.On call -// - _a0 commonpb.StateCode -func (_e *RootCoord_Expecter) UpdateStateCode(_a0 interface{}) *RootCoord_UpdateStateCode_Call { - return &RootCoord_UpdateStateCode_Call{Call: _e.mock.On("UpdateStateCode", _a0)} -} - -func (_c *RootCoord_UpdateStateCode_Call) Run(run func(_a0 commonpb.StateCode)) *RootCoord_UpdateStateCode_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(commonpb.StateCode)) - }) - return _c -} - -func (_c *RootCoord_UpdateStateCode_Call) Return() *RootCoord_UpdateStateCode_Call { - _c.Call.Return() - return _c -} - -func (_c *RootCoord_UpdateStateCode_Call) RunAndReturn(run func(commonpb.StateCode)) *RootCoord_UpdateStateCode_Call { - _c.Call.Return(run) - return _c -} - // NewRootCoord creates a new instance of RootCoord. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewRootCoord(t interface { diff --git a/internal/mocks/mock_rootcoord_client.go b/internal/mocks/mock_rootcoord_client.go index b1deb3977c..30ccb664e3 100644 --- a/internal/mocks/mock_rootcoord_client.go +++ b/internal/mocks/mock_rootcoord_client.go @@ -914,6 +914,76 @@ func (_c *MockRootCoordClient_DeleteCredential_Call) RunAndReturn(run func(conte return _c } +// DescribeAlias provides a mock function with given fields: ctx, in, opts +func (_m *MockRootCoordClient) DescribeAlias(ctx context.Context, in *milvuspb.DescribeAliasRequest, opts ...grpc.CallOption) (*milvuspb.DescribeAliasResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *milvuspb.DescribeAliasResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DescribeAliasRequest, ...grpc.CallOption) (*milvuspb.DescribeAliasResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.DescribeAliasRequest, ...grpc.CallOption) *milvuspb.DescribeAliasResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*milvuspb.DescribeAliasResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.DescribeAliasRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockRootCoordClient_DescribeAlias_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DescribeAlias' +type MockRootCoordClient_DescribeAlias_Call struct { + *mock.Call +} + +// DescribeAlias is a helper method to define mock.On call +// - ctx context.Context +// - in *milvuspb.DescribeAliasRequest +// - opts ...grpc.CallOption +func (_e *MockRootCoordClient_Expecter) DescribeAlias(ctx interface{}, in interface{}, opts ...interface{}) *MockRootCoordClient_DescribeAlias_Call { + return &MockRootCoordClient_DescribeAlias_Call{Call: _e.mock.On("DescribeAlias", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockRootCoordClient_DescribeAlias_Call) Run(run func(ctx context.Context, in *milvuspb.DescribeAliasRequest, opts ...grpc.CallOption)) *MockRootCoordClient_DescribeAlias_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*milvuspb.DescribeAliasRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockRootCoordClient_DescribeAlias_Call) Return(_a0 *milvuspb.DescribeAliasResponse, _a1 error) *MockRootCoordClient_DescribeAlias_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockRootCoordClient_DescribeAlias_Call) RunAndReturn(run func(context.Context, *milvuspb.DescribeAliasRequest, ...grpc.CallOption) (*milvuspb.DescribeAliasResponse, error)) *MockRootCoordClient_DescribeAlias_Call { + _c.Call.Return(run) + return _c +} + // DescribeCollection provides a mock function with given fields: ctx, in, opts func (_m *MockRootCoordClient) DescribeCollection(ctx context.Context, in *milvuspb.DescribeCollectionRequest, opts ...grpc.CallOption) (*milvuspb.DescribeCollectionResponse, error) { _va := make([]interface{}, len(opts)) @@ -2104,6 +2174,76 @@ func (_c *MockRootCoordClient_InvalidateCollectionMetaCache_Call) RunAndReturn(r return _c } +// ListAliases provides a mock function with given fields: ctx, in, opts +func (_m *MockRootCoordClient) ListAliases(ctx context.Context, in *milvuspb.ListAliasesRequest, opts ...grpc.CallOption) (*milvuspb.ListAliasesResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *milvuspb.ListAliasesResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ListAliasesRequest, ...grpc.CallOption) (*milvuspb.ListAliasesResponse, error)); ok { + return rf(ctx, in, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, *milvuspb.ListAliasesRequest, ...grpc.CallOption) *milvuspb.ListAliasesResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*milvuspb.ListAliasesResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *milvuspb.ListAliasesRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockRootCoordClient_ListAliases_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListAliases' +type MockRootCoordClient_ListAliases_Call struct { + *mock.Call +} + +// ListAliases is a helper method to define mock.On call +// - ctx context.Context +// - in *milvuspb.ListAliasesRequest +// - opts ...grpc.CallOption +func (_e *MockRootCoordClient_Expecter) ListAliases(ctx interface{}, in interface{}, opts ...interface{}) *MockRootCoordClient_ListAliases_Call { + return &MockRootCoordClient_ListAliases_Call{Call: _e.mock.On("ListAliases", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockRootCoordClient_ListAliases_Call) Run(run func(ctx context.Context, in *milvuspb.ListAliasesRequest, opts ...grpc.CallOption)) *MockRootCoordClient_ListAliases_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + run(args[0].(context.Context), args[1].(*milvuspb.ListAliasesRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockRootCoordClient_ListAliases_Call) Return(_a0 *milvuspb.ListAliasesResponse, _a1 error) *MockRootCoordClient_ListAliases_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockRootCoordClient_ListAliases_Call) RunAndReturn(run func(context.Context, *milvuspb.ListAliasesRequest, ...grpc.CallOption) (*milvuspb.ListAliasesResponse, error)) *MockRootCoordClient_ListAliases_Call { + _c.Call.Return(run) + return _c +} + // ListCredUsers provides a mock function with given fields: ctx, in, opts func (_m *MockRootCoordClient) ListCredUsers(ctx context.Context, in *milvuspb.ListCredUsersRequest, opts ...grpc.CallOption) (*milvuspb.ListCredUsersResponse, error) { _va := make([]interface{}, len(opts)) diff --git a/internal/proto/root_coord.proto b/internal/proto/root_coord.proto index 5ea3299353..86f5d7b1d8 100644 --- a/internal/proto/root_coord.proto +++ b/internal/proto/root_coord.proto @@ -54,6 +54,8 @@ service RootCoord { rpc CreateAlias(milvus.CreateAliasRequest) returns (common.Status) {} rpc DropAlias(milvus.DropAliasRequest) returns (common.Status) {} rpc AlterAlias(milvus.AlterAliasRequest) returns (common.Status) {} + rpc DescribeAlias(milvus.DescribeAliasRequest) returns (milvus.DescribeAliasResponse) {} + rpc ListAliases(milvus.ListAliasesRequest) returns (milvus.ListAliasesResponse) {} /** * @brief This method is used to list all collections. diff --git a/internal/proxy/impl.go b/internal/proxy/impl.go index f4957527b1..9abcdac814 100644 --- a/internal/proxy/impl.go +++ b/internal/proxy/impl.go @@ -3194,16 +3194,131 @@ func (node *Proxy) CreateAlias(ctx context.Context, request *milvuspb.CreateAlia return cat.result, nil } +// DescribeAlias describe alias of collection. func (node *Proxy) DescribeAlias(ctx context.Context, request *milvuspb.DescribeAliasRequest) (*milvuspb.DescribeAliasResponse, error) { - return &milvuspb.DescribeAliasResponse{ - Status: merr.Status(merr.WrapErrServiceUnavailable("DescribeAlias unimplemented")), - }, nil + if err := merr.CheckHealthy(node.GetStateCode()); err != nil { + return &milvuspb.DescribeAliasResponse{ + Status: merr.Status(err), + }, nil + } + + ctx, sp := otel.Tracer(typeutil.ProxyRole).Start(ctx, "Proxy-DescribeAlias") + defer sp.End() + + dat := &DescribeAliasTask{ + ctx: ctx, + Condition: NewTaskCondition(ctx), + nodeID: node.session.ServerID, + DescribeAliasRequest: request, + rootCoord: node.rootCoord, + } + + method := "DescribeAlias" + tr := timerecord.NewTimeRecorder(method) + metrics.ProxyFunctionCall.WithLabelValues(strconv.FormatInt(node.session.ServerID, 10), method, metrics.TotalLabel).Inc() + + log := log.Ctx(ctx).With( + zap.String("role", typeutil.ProxyRole), + zap.String("db", request.DbName), + zap.String("alias", request.Alias)) + + log.Debug(rpcReceived(method)) + + if err := node.sched.ddQueue.Enqueue(dat); err != nil { + log.Warn( + rpcFailedToEnqueue(method), + zap.Error(err)) + metrics.ProxyFunctionCall.WithLabelValues(strconv.FormatInt(node.session.ServerID, 10), method, metrics.AbandonLabel).Inc() + + return &milvuspb.DescribeAliasResponse{ + Status: merr.Status(err), + }, nil + } + + log.Debug( + rpcEnqueued(method), + zap.Uint64("BeginTs", dat.BeginTs()), + zap.Uint64("EndTs", dat.EndTs())) + + if err := dat.WaitToFinish(); err != nil { + log.Warn(rpcFailedToWaitToFinish(method), zap.Uint64("BeginTs", dat.BeginTs()), zap.Uint64("EndTs", dat.EndTs()), zap.Error(err)) + metrics.ProxyFunctionCall.WithLabelValues(strconv.FormatInt(node.session.ServerID, 10), method, metrics.FailLabel).Inc() + return &milvuspb.DescribeAliasResponse{ + Status: merr.Status(err), + }, nil + } + + log.Debug( + rpcDone(method), + zap.Uint64("BeginTs", dat.BeginTs()), + zap.Uint64("EndTs", dat.EndTs())) + + metrics.ProxyFunctionCall.WithLabelValues(strconv.FormatInt(node.session.ServerID, 10), method, metrics.SuccessLabel).Inc() + metrics.ProxyReqLatency.WithLabelValues(strconv.FormatInt(node.session.ServerID, 10), method).Observe(float64(tr.ElapseSpan().Milliseconds())) + return dat.result, nil } +// ListAliases show all aliases of db. func (node *Proxy) ListAliases(ctx context.Context, request *milvuspb.ListAliasesRequest) (*milvuspb.ListAliasesResponse, error) { - return &milvuspb.ListAliasesResponse{ - Status: merr.Status(merr.WrapErrServiceUnavailable("ListAliases unimplemented")), - }, nil + if err := merr.CheckHealthy(node.GetStateCode()); err != nil { + return &milvuspb.ListAliasesResponse{ + Status: merr.Status(err), + }, nil + } + + ctx, sp := otel.Tracer(typeutil.ProxyRole).Start(ctx, "Proxy-ListAliases") + defer sp.End() + + lat := &ListAliasesTask{ + ctx: ctx, + Condition: NewTaskCondition(ctx), + nodeID: node.session.ServerID, + ListAliasesRequest: request, + rootCoord: node.rootCoord, + } + + method := "ListAliases" + tr := timerecord.NewTimeRecorder(method) + metrics.ProxyFunctionCall.WithLabelValues(strconv.FormatInt(node.session.ServerID, 10), method, metrics.TotalLabel).Inc() + + log := log.Ctx(ctx).With( + zap.String("role", typeutil.ProxyRole), + zap.String("db", request.DbName)) + + log.Debug(rpcReceived(method)) + + if err := node.sched.ddQueue.Enqueue(lat); err != nil { + log.Warn( + rpcFailedToEnqueue(method), + zap.Error(err)) + metrics.ProxyFunctionCall.WithLabelValues(strconv.FormatInt(node.session.ServerID, 10), method, metrics.AbandonLabel).Inc() + + return &milvuspb.ListAliasesResponse{ + Status: merr.Status(err), + }, nil + } + + log.Debug( + rpcEnqueued(method), + zap.Uint64("BeginTs", lat.BeginTs()), + zap.Uint64("EndTs", lat.EndTs())) + + if err := lat.WaitToFinish(); err != nil { + log.Warn(rpcFailedToWaitToFinish(method), zap.Uint64("BeginTs", lat.BeginTs()), zap.Uint64("EndTs", lat.EndTs()), zap.Error(err)) + metrics.ProxyFunctionCall.WithLabelValues(strconv.FormatInt(node.session.ServerID, 10), method, metrics.FailLabel).Inc() + return &milvuspb.ListAliasesResponse{ + Status: merr.Status(err), + }, nil + } + + log.Debug( + rpcDone(method), + zap.Uint64("BeginTs", lat.BeginTs()), + zap.Uint64("EndTs", lat.EndTs())) + + metrics.ProxyFunctionCall.WithLabelValues(strconv.FormatInt(node.session.ServerID, 10), method, metrics.SuccessLabel).Inc() + metrics.ProxyReqLatency.WithLabelValues(strconv.FormatInt(node.session.ServerID, 10), method).Observe(float64(tr.ElapseSpan().Milliseconds())) + return lat.result, nil } // DropAlias alter the alias of collection. diff --git a/internal/proxy/proxy_test.go b/internal/proxy/proxy_test.go index 57fa36621d..98435d0568 100644 --- a/internal/proxy/proxy_test.go +++ b/internal/proxy/proxy_test.go @@ -754,6 +754,30 @@ func TestProxy(t *testing.T) { }) }) + wg.Add(1) + t.Run("describe alias", func(t *testing.T) { + defer wg.Done() + describeAliasReq := &milvuspb.DescribeAliasRequest{ + Base: nil, + DbName: dbName, + Alias: "alias", + } + resp, err := proxy.DescribeAlias(ctx, describeAliasReq) + assert.NoError(t, err) + assert.Equal(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) + + wg.Add(1) + t.Run("list alias", func(t *testing.T) { + defer wg.Done() + listAliasReq := &milvuspb.ListAliasesRequest{ + Base: nil, + } + resp, err := proxy.ListAliases(ctx, listAliasReq) + assert.NoError(t, err) + assert.Equal(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) + wg.Add(1) t.Run("alter alias", func(t *testing.T) { defer wg.Done() @@ -2884,6 +2908,22 @@ func TestProxy(t *testing.T) { assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode) }) + wg.Add(1) + t.Run("ListAliases fail, unhealthy", func(t *testing.T) { + defer wg.Done() + resp, err := proxy.ListAliases(ctx, &milvuspb.ListAliasesRequest{}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) + + wg.Add(1) + t.Run("DescribeAlias fail, unhealthy", func(t *testing.T) { + defer wg.Done() + resp, err := proxy.DescribeAlias(ctx, &milvuspb.DescribeAliasRequest{}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) + wg.Add(1) t.Run("GetPersistentSegmentInfo fail, unhealthy", func(t *testing.T) { defer wg.Done() @@ -3202,6 +3242,22 @@ func TestProxy(t *testing.T) { assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode) }) + wg.Add(1) + t.Run("DescribeAlias fail, dd queue full", func(t *testing.T) { + defer wg.Done() + resp, err := proxy.DescribeAlias(ctx, &milvuspb.DescribeAliasRequest{}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) + + wg.Add(1) + t.Run("ListAliases fail, dd queue full", func(t *testing.T) { + defer wg.Done() + resp, err := proxy.ListAliases(ctx, &milvuspb.ListAliasesRequest{}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) + proxy.sched.ddQueue.setMaxTaskNum(ddParallel) dmParallelism := proxy.sched.dmQueue.getMaxTaskNum() @@ -3522,6 +3578,22 @@ func TestProxy(t *testing.T) { assert.NotEqual(t, commonpb.ErrorCode_Success, resp.ErrorCode) }) + wg.Add(1) + t.Run("DescribeAlias fail, timeout", func(t *testing.T) { + defer wg.Done() + resp, err := proxy.DescribeAlias(shortCtx, &milvuspb.DescribeAliasRequest{}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) + + wg.Add(1) + t.Run("ListAliases fail, timeout", func(t *testing.T) { + defer wg.Done() + resp, err := proxy.ListAliases(shortCtx, &milvuspb.ListAliasesRequest{}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) + wg.Add(1) t.Run("CreateCredential fail, timeout", func(t *testing.T) { defer wg.Done() diff --git a/internal/proxy/rootcoord_mock_test.go b/internal/proxy/rootcoord_mock_test.go index 80942da1be..d3b5bcccec 100644 --- a/internal/proxy/rootcoord_mock_test.go +++ b/internal/proxy/rootcoord_mock_test.go @@ -190,6 +190,75 @@ func (coord *RootCoordMock) AlterAlias(ctx context.Context, req *milvuspb.AlterA return merr.Success(), nil } +func (coord *RootCoordMock) DescribeAlias(ctx context.Context, req *milvuspb.DescribeAliasRequest, opts ...grpc.CallOption) (*milvuspb.DescribeAliasResponse, error) { + code := coord.state.Load().(commonpb.StateCode) + if code != commonpb.StateCode_Healthy { + return &milvuspb.DescribeAliasResponse{ + Status: &commonpb.Status{ + ErrorCode: commonpb.ErrorCode_UnexpectedError, + Reason: fmt.Sprintf("state code = %s", commonpb.StateCode_name[int32(code)]), + }, + }, nil + } + coord.collMtx.Lock() + defer coord.collMtx.Unlock() + + collID, exist := coord.collAlias2ID[req.Alias] + if !exist { + return &milvuspb.DescribeAliasResponse{ + Status: &commonpb.Status{ + ErrorCode: commonpb.ErrorCode_CollectionNotExists, + Reason: fmt.Sprintf("alias does not exist, alias = %s", req.Alias), + }, + }, nil + } + collMeta, exist := coord.collID2Meta[collID] + if !exist { + return &milvuspb.DescribeAliasResponse{ + Status: &commonpb.Status{ + ErrorCode: commonpb.ErrorCode_CollectionNotExists, + Reason: fmt.Sprintf("alias exist but not find related collection, alias = %s collID = %d", req.Alias, collID), + }, + }, nil + } + return &milvuspb.DescribeAliasResponse{ + Status: &commonpb.Status{ + ErrorCode: commonpb.ErrorCode_Success, + Reason: "", + }, + DbName: req.GetDbName(), + Alias: req.GetAlias(), + Collection: collMeta.name, + }, nil +} + +func (coord *RootCoordMock) ListAliases(ctx context.Context, req *milvuspb.ListAliasesRequest, opts ...grpc.CallOption) (*milvuspb.ListAliasesResponse, error) { + code := coord.state.Load().(commonpb.StateCode) + if code != commonpb.StateCode_Healthy { + return &milvuspb.ListAliasesResponse{ + Status: &commonpb.Status{ + ErrorCode: commonpb.ErrorCode_UnexpectedError, + Reason: fmt.Sprintf("state code = %s", commonpb.StateCode_name[int32(code)]), + }, + }, nil + } + coord.collMtx.Lock() + defer coord.collMtx.Unlock() + + var aliases []string + for alias := range coord.collAlias2ID { + aliases = append(aliases, alias) + } + return &milvuspb.ListAliasesResponse{ + Status: &commonpb.Status{ + ErrorCode: commonpb.ErrorCode_Success, + Reason: "", + }, + DbName: req.GetDbName(), + Aliases: aliases, + }, nil +} + func (coord *RootCoordMock) updateState(state commonpb.StateCode) { coord.state.Store(state) } diff --git a/internal/proxy/task.go b/internal/proxy/task.go index fc43f3821a..9bfc6beee9 100644 --- a/internal/proxy/task.go +++ b/internal/proxy/task.go @@ -73,6 +73,8 @@ const ( CreateAliasTaskName = "CreateAliasTask" DropAliasTaskName = "DropAliasTask" AlterAliasTaskName = "AlterAliasTask" + DescribeAliasTaskName = "DescribeAliasTask" + ListAliasesTaskName = "ListAliasesTask" AlterCollectionTaskName = "AlterCollectionTask" UpsertTaskName = "UpsertTask" CreateResourceGroupTaskName = "CreateResourceGroupTask" @@ -1905,241 +1907,6 @@ func (t *releasePartitionsTask) PostExecute(ctx context.Context) error { return nil } -// CreateAliasTask contains task information of CreateAlias -type CreateAliasTask struct { - Condition - *milvuspb.CreateAliasRequest - ctx context.Context - rootCoord types.RootCoordClient - result *commonpb.Status -} - -// TraceCtx returns the trace context of the task. -func (t *CreateAliasTask) TraceCtx() context.Context { - return t.ctx -} - -// ID return the id of the task -func (t *CreateAliasTask) ID() UniqueID { - return t.Base.MsgID -} - -// SetID sets the id of the task -func (t *CreateAliasTask) SetID(uid UniqueID) { - t.Base.MsgID = uid -} - -// Name returns the name of the task -func (t *CreateAliasTask) Name() string { - return CreateAliasTaskName -} - -// Type returns the type of the task -func (t *CreateAliasTask) Type() commonpb.MsgType { - return t.Base.MsgType -} - -// BeginTs returns the ts -func (t *CreateAliasTask) BeginTs() Timestamp { - return t.Base.Timestamp -} - -// EndTs returns the ts -func (t *CreateAliasTask) EndTs() Timestamp { - return t.Base.Timestamp -} - -// SetTs sets the ts -func (t *CreateAliasTask) SetTs(ts Timestamp) { - t.Base.Timestamp = ts -} - -// OnEnqueue defines the behavior task enqueued -func (t *CreateAliasTask) OnEnqueue() error { - if t.Base == nil { - t.Base = commonpbutil.NewMsgBase() - } - return nil -} - -// PreExecute defines the tion before task execution -func (t *CreateAliasTask) PreExecute(ctx context.Context) error { - t.Base.MsgType = commonpb.MsgType_CreateAlias - t.Base.SourceID = paramtable.GetNodeID() - - collAlias := t.Alias - // collection alias uses the same format as collection name - if err := ValidateCollectionAlias(collAlias); err != nil { - return err - } - - collName := t.CollectionName - if err := validateCollectionName(collName); err != nil { - return err - } - return nil -} - -// Execute defines the tual execution of create alias -func (t *CreateAliasTask) Execute(ctx context.Context) error { - var err error - t.result, err = t.rootCoord.CreateAlias(ctx, t.CreateAliasRequest) - return err -} - -// PostExecute defines the post execution, do nothing for create alias -func (t *CreateAliasTask) PostExecute(ctx context.Context) error { - return nil -} - -// DropAliasTask is the task to drop alias -type DropAliasTask struct { - Condition - *milvuspb.DropAliasRequest - ctx context.Context - rootCoord types.RootCoordClient - result *commonpb.Status -} - -// TraceCtx returns the context for trace -func (t *DropAliasTask) TraceCtx() context.Context { - return t.ctx -} - -// ID returns the MsgID -func (t *DropAliasTask) ID() UniqueID { - return t.Base.MsgID -} - -// SetID sets the MsgID -func (t *DropAliasTask) SetID(uid UniqueID) { - t.Base.MsgID = uid -} - -// Name returns the name of the task -func (t *DropAliasTask) Name() string { - return DropAliasTaskName -} - -func (t *DropAliasTask) Type() commonpb.MsgType { - return t.Base.MsgType -} - -func (t *DropAliasTask) BeginTs() Timestamp { - return t.Base.Timestamp -} - -func (t *DropAliasTask) EndTs() Timestamp { - return t.Base.Timestamp -} - -func (t *DropAliasTask) SetTs(ts Timestamp) { - t.Base.Timestamp = ts -} - -func (t *DropAliasTask) OnEnqueue() error { - if t.Base == nil { - t.Base = commonpbutil.NewMsgBase() - } - return nil -} - -func (t *DropAliasTask) PreExecute(ctx context.Context) error { - t.Base.MsgType = commonpb.MsgType_DropAlias - t.Base.SourceID = paramtable.GetNodeID() - collAlias := t.Alias - if err := ValidateCollectionAlias(collAlias); err != nil { - return err - } - return nil -} - -func (t *DropAliasTask) Execute(ctx context.Context) error { - var err error - t.result, err = t.rootCoord.DropAlias(ctx, t.DropAliasRequest) - return err -} - -func (t *DropAliasTask) PostExecute(ctx context.Context) error { - return nil -} - -// AlterAliasTask is the task to alter alias -type AlterAliasTask struct { - Condition - *milvuspb.AlterAliasRequest - ctx context.Context - rootCoord types.RootCoordClient - result *commonpb.Status -} - -func (t *AlterAliasTask) TraceCtx() context.Context { - return t.ctx -} - -func (t *AlterAliasTask) ID() UniqueID { - return t.Base.MsgID -} - -func (t *AlterAliasTask) SetID(uid UniqueID) { - t.Base.MsgID = uid -} - -func (t *AlterAliasTask) Name() string { - return AlterAliasTaskName -} - -func (t *AlterAliasTask) Type() commonpb.MsgType { - return t.Base.MsgType -} - -func (t *AlterAliasTask) BeginTs() Timestamp { - return t.Base.Timestamp -} - -func (t *AlterAliasTask) EndTs() Timestamp { - return t.Base.Timestamp -} - -func (t *AlterAliasTask) SetTs(ts Timestamp) { - t.Base.Timestamp = ts -} - -func (t *AlterAliasTask) OnEnqueue() error { - if t.Base == nil { - t.Base = commonpbutil.NewMsgBase() - } - return nil -} - -func (t *AlterAliasTask) PreExecute(ctx context.Context) error { - t.Base.MsgType = commonpb.MsgType_AlterAlias - t.Base.SourceID = paramtable.GetNodeID() - - collAlias := t.Alias - // collection alias uses the same format as collection name - if err := ValidateCollectionAlias(collAlias); err != nil { - return err - } - - collName := t.CollectionName - if err := validateCollectionName(collName); err != nil { - return err - } - - return nil -} - -func (t *AlterAliasTask) Execute(ctx context.Context) error { - var err error - t.result, err = t.rootCoord.AlterAlias(ctx, t.AlterAliasRequest) - return err -} - -func (t *AlterAliasTask) PostExecute(ctx context.Context) error { - return nil -} - type CreateResourceGroupTask struct { Condition *milvuspb.CreateResourceGroupRequest diff --git a/internal/proxy/task_alias.go b/internal/proxy/task_alias.go new file mode 100644 index 0000000000..6fd1bfa4e5 --- /dev/null +++ b/internal/proxy/task_alias.go @@ -0,0 +1,388 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proxy + +import ( + "context" + + "github.com/milvus-io/milvus-proto/go-api/v2/commonpb" + "github.com/milvus-io/milvus-proto/go-api/v2/milvuspb" + "github.com/milvus-io/milvus/internal/types" + "github.com/milvus-io/milvus/pkg/util/commonpbutil" + "github.com/milvus-io/milvus/pkg/util/paramtable" +) + +// CreateAliasTask contains task information of CreateAlias +type CreateAliasTask struct { + Condition + *milvuspb.CreateAliasRequest + ctx context.Context + rootCoord types.RootCoordClient + result *commonpb.Status +} + +// TraceCtx returns the trace context of the task. +func (t *CreateAliasTask) TraceCtx() context.Context { + return t.ctx +} + +// ID return the id of the task +func (t *CreateAliasTask) ID() UniqueID { + return t.Base.MsgID +} + +// SetID sets the id of the task +func (t *CreateAliasTask) SetID(uid UniqueID) { + t.Base.MsgID = uid +} + +// Name returns the name of the task +func (t *CreateAliasTask) Name() string { + return CreateAliasTaskName +} + +// Type returns the type of the task +func (t *CreateAliasTask) Type() commonpb.MsgType { + return t.Base.MsgType +} + +// BeginTs returns the ts +func (t *CreateAliasTask) BeginTs() Timestamp { + return t.Base.Timestamp +} + +// EndTs returns the ts +func (t *CreateAliasTask) EndTs() Timestamp { + return t.Base.Timestamp +} + +// SetTs sets the ts +func (t *CreateAliasTask) SetTs(ts Timestamp) { + t.Base.Timestamp = ts +} + +// OnEnqueue defines the behavior task enqueued +func (t *CreateAliasTask) OnEnqueue() error { + if t.Base == nil { + t.Base = commonpbutil.NewMsgBase() + } + return nil +} + +// PreExecute defines the tion before task execution +func (t *CreateAliasTask) PreExecute(ctx context.Context) error { + t.Base.MsgType = commonpb.MsgType_CreateAlias + t.Base.SourceID = paramtable.GetNodeID() + + collAlias := t.Alias + // collection alias uses the same format as collection name + if err := ValidateCollectionAlias(collAlias); err != nil { + return err + } + + collName := t.CollectionName + if err := validateCollectionName(collName); err != nil { + return err + } + return nil +} + +// Execute defines the tual execution of create alias +func (t *CreateAliasTask) Execute(ctx context.Context) error { + var err error + t.result, err = t.rootCoord.CreateAlias(ctx, t.CreateAliasRequest) + return err +} + +// PostExecute defines the post execution, do nothing for create alias +func (t *CreateAliasTask) PostExecute(ctx context.Context) error { + return nil +} + +// DropAliasTask is the task to drop alias +type DropAliasTask struct { + Condition + *milvuspb.DropAliasRequest + ctx context.Context + rootCoord types.RootCoordClient + result *commonpb.Status +} + +// TraceCtx returns the context for trace +func (t *DropAliasTask) TraceCtx() context.Context { + return t.ctx +} + +// ID returns the MsgID +func (t *DropAliasTask) ID() UniqueID { + return t.Base.MsgID +} + +// SetID sets the MsgID +func (t *DropAliasTask) SetID(uid UniqueID) { + t.Base.MsgID = uid +} + +// Name returns the name of the task +func (t *DropAliasTask) Name() string { + return DropAliasTaskName +} + +func (t *DropAliasTask) Type() commonpb.MsgType { + return t.Base.MsgType +} + +func (t *DropAliasTask) BeginTs() Timestamp { + return t.Base.Timestamp +} + +func (t *DropAliasTask) EndTs() Timestamp { + return t.Base.Timestamp +} + +func (t *DropAliasTask) SetTs(ts Timestamp) { + t.Base.Timestamp = ts +} + +func (t *DropAliasTask) OnEnqueue() error { + if t.Base == nil { + t.Base = commonpbutil.NewMsgBase() + } + return nil +} + +func (t *DropAliasTask) PreExecute(ctx context.Context) error { + t.Base.MsgType = commonpb.MsgType_DropAlias + t.Base.SourceID = paramtable.GetNodeID() + collAlias := t.Alias + if err := ValidateCollectionAlias(collAlias); err != nil { + return err + } + return nil +} + +func (t *DropAliasTask) Execute(ctx context.Context) error { + var err error + t.result, err = t.rootCoord.DropAlias(ctx, t.DropAliasRequest) + return err +} + +func (t *DropAliasTask) PostExecute(ctx context.Context) error { + return nil +} + +// AlterAliasTask is the task to alter alias +type AlterAliasTask struct { + Condition + *milvuspb.AlterAliasRequest + ctx context.Context + rootCoord types.RootCoordClient + result *commonpb.Status +} + +func (t *AlterAliasTask) TraceCtx() context.Context { + return t.ctx +} + +func (t *AlterAliasTask) ID() UniqueID { + return t.Base.MsgID +} + +func (t *AlterAliasTask) SetID(uid UniqueID) { + t.Base.MsgID = uid +} + +func (t *AlterAliasTask) Name() string { + return AlterAliasTaskName +} + +func (t *AlterAliasTask) Type() commonpb.MsgType { + return t.Base.MsgType +} + +func (t *AlterAliasTask) BeginTs() Timestamp { + return t.Base.Timestamp +} + +func (t *AlterAliasTask) EndTs() Timestamp { + return t.Base.Timestamp +} + +func (t *AlterAliasTask) SetTs(ts Timestamp) { + t.Base.Timestamp = ts +} + +func (t *AlterAliasTask) OnEnqueue() error { + if t.Base == nil { + t.Base = commonpbutil.NewMsgBase() + } + return nil +} + +func (t *AlterAliasTask) PreExecute(ctx context.Context) error { + t.Base.MsgType = commonpb.MsgType_AlterAlias + t.Base.SourceID = paramtable.GetNodeID() + + collAlias := t.Alias + // collection alias uses the same format as collection name + if err := ValidateCollectionAlias(collAlias); err != nil { + return err + } + + collName := t.CollectionName + if err := validateCollectionName(collName); err != nil { + return err + } + + return nil +} + +func (t *AlterAliasTask) Execute(ctx context.Context) error { + var err error + t.result, err = t.rootCoord.AlterAlias(ctx, t.AlterAliasRequest) + return err +} + +func (t *AlterAliasTask) PostExecute(ctx context.Context) error { + return nil +} + +// DescribeAliasTask is the task to describe alias +type DescribeAliasTask struct { + Condition + nodeID UniqueID + *milvuspb.DescribeAliasRequest + ctx context.Context + rootCoord types.RootCoordClient + result *milvuspb.DescribeAliasResponse +} + +func (a *DescribeAliasTask) TraceCtx() context.Context { + return a.ctx +} + +func (a *DescribeAliasTask) ID() UniqueID { + return a.Base.MsgID +} + +func (a *DescribeAliasTask) SetID(uid UniqueID) { + a.Base.MsgID = uid +} + +func (a *DescribeAliasTask) Name() string { + return DescribeAliasTaskName +} + +func (a *DescribeAliasTask) Type() commonpb.MsgType { + return a.Base.MsgType +} + +func (a *DescribeAliasTask) BeginTs() Timestamp { + return a.Base.Timestamp +} + +func (a *DescribeAliasTask) EndTs() Timestamp { + return a.Base.Timestamp +} + +func (a *DescribeAliasTask) SetTs(ts Timestamp) { + a.Base.Timestamp = ts +} + +func (a *DescribeAliasTask) OnEnqueue() error { + a.Base = commonpbutil.NewMsgBase() + return nil +} + +func (a *DescribeAliasTask) PreExecute(ctx context.Context) error { + a.Base.MsgType = commonpb.MsgType_DescribeAlias + a.Base.SourceID = a.nodeID + return nil +} + +func (a *DescribeAliasTask) Execute(ctx context.Context) error { + var err error + a.result, err = a.rootCoord.DescribeAlias(ctx, a.DescribeAliasRequest) + return err +} + +func (a *DescribeAliasTask) PostExecute(ctx context.Context) error { + return nil +} + +// ListAliasesTask is the task to list aliases +type ListAliasesTask struct { + Condition + nodeID UniqueID + *milvuspb.ListAliasesRequest + ctx context.Context + rootCoord types.RootCoordClient + result *milvuspb.ListAliasesResponse +} + +func (a *ListAliasesTask) TraceCtx() context.Context { + return a.ctx +} + +func (a *ListAliasesTask) ID() UniqueID { + return a.Base.MsgID +} + +func (a *ListAliasesTask) SetID(uid UniqueID) { + a.Base.MsgID = uid +} + +func (a *ListAliasesTask) Name() string { + return ListAliasesTaskName +} + +func (a *ListAliasesTask) Type() commonpb.MsgType { + return a.Base.MsgType +} + +func (a *ListAliasesTask) BeginTs() Timestamp { + return a.Base.Timestamp +} + +func (a *ListAliasesTask) EndTs() Timestamp { + return a.Base.Timestamp +} + +func (a *ListAliasesTask) SetTs(ts Timestamp) { + a.Base.Timestamp = ts +} + +func (a *ListAliasesTask) OnEnqueue() error { + a.Base = commonpbutil.NewMsgBase() + return nil +} + +func (a *ListAliasesTask) PreExecute(ctx context.Context) error { + a.Base.MsgType = commonpb.MsgType_ListAliases + a.Base.SourceID = a.nodeID + return nil +} + +func (a *ListAliasesTask) Execute(ctx context.Context) error { + var err error + a.result, err = a.rootCoord.ListAliases(ctx, a.ListAliasesRequest) + return err +} + +func (a *ListAliasesTask) PostExecute(ctx context.Context) error { + return nil +} diff --git a/internal/proxy/task_alias_test.go b/internal/proxy/task_alias_test.go new file mode 100644 index 0000000000..e3945d2958 --- /dev/null +++ b/internal/proxy/task_alias_test.go @@ -0,0 +1,237 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package proxy + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/milvus-io/milvus-proto/go-api/v2/commonpb" + "github.com/milvus-io/milvus-proto/go-api/v2/milvuspb" + "github.com/milvus-io/milvus/pkg/util/funcutil" + "github.com/milvus-io/milvus/pkg/util/merr" + "github.com/milvus-io/milvus/pkg/util/uniquegenerator" +) + +func TestCreateAlias_all(t *testing.T) { + rc := NewRootCoordMock() + + defer rc.Close() + ctx := context.Background() + prefix := "TestCreateAlias_all" + collectionName := prefix + funcutil.GenRandomStr() + task := &CreateAliasTask{ + Condition: NewTaskCondition(ctx), + CreateAliasRequest: &milvuspb.CreateAliasRequest{ + Base: nil, + CollectionName: collectionName, + Alias: "alias1", + }, + ctx: ctx, + result: merr.Success(), + rootCoord: rc, + } + + assert.NoError(t, task.OnEnqueue()) + + assert.NotNil(t, task.TraceCtx()) + + id := UniqueID(uniquegenerator.GetUniqueIntGeneratorIns().GetInt()) + task.SetID(id) + assert.Equal(t, id, task.ID()) + + task.Base.MsgType = commonpb.MsgType_CreateAlias + assert.Equal(t, commonpb.MsgType_CreateAlias, task.Type()) + ts := Timestamp(time.Now().UnixNano()) + task.SetTs(ts) + assert.Equal(t, ts, task.BeginTs()) + assert.Equal(t, ts, task.EndTs()) + + task.CreateAliasRequest.Alias = "illgal-alias:!" + assert.Error(t, task.PreExecute(ctx)) + task.CreateAliasRequest.Alias = "alias1" + task.CreateAliasRequest.CollectionName = "illgal-collection:!" + assert.Error(t, task.PreExecute(ctx)) + task.CreateAliasRequest.CollectionName = collectionName + + assert.NoError(t, task.PreExecute(ctx)) + assert.NoError(t, task.Execute(ctx)) + assert.NoError(t, task.PostExecute(ctx)) +} + +func TestDropAlias_all(t *testing.T) { + rc := NewRootCoordMock() + + defer rc.Close() + ctx := context.Background() + task := &DropAliasTask{ + Condition: NewTaskCondition(ctx), + DropAliasRequest: &milvuspb.DropAliasRequest{ + Base: nil, + Alias: "alias1", + }, + ctx: ctx, + result: merr.Success(), + rootCoord: rc, + } + + assert.NoError(t, task.OnEnqueue()) + assert.NotNil(t, task.TraceCtx()) + + id := UniqueID(uniquegenerator.GetUniqueIntGeneratorIns().GetInt()) + task.SetID(id) + assert.Equal(t, id, task.ID()) + + task.Base.MsgType = commonpb.MsgType_DropAlias + assert.Equal(t, commonpb.MsgType_DropAlias, task.Type()) + ts := Timestamp(time.Now().UnixNano()) + task.SetTs(ts) + assert.Equal(t, ts, task.BeginTs()) + assert.Equal(t, ts, task.EndTs()) + + assert.NoError(t, task.PreExecute(ctx)) + assert.NoError(t, task.Execute(ctx)) + assert.NoError(t, task.PostExecute(ctx)) +} + +func TestAlterAlias_all(t *testing.T) { + rc := NewRootCoordMock() + + defer rc.Close() + ctx := context.Background() + prefix := "TestAlterAlias_all" + collectionName := prefix + funcutil.GenRandomStr() + task := &AlterAliasTask{ + Condition: NewTaskCondition(ctx), + AlterAliasRequest: &milvuspb.AlterAliasRequest{ + Base: nil, + CollectionName: collectionName, + Alias: "alias1", + }, + ctx: ctx, + result: merr.Success(), + rootCoord: rc, + } + + assert.NoError(t, task.OnEnqueue()) + + assert.NotNil(t, task.TraceCtx()) + + id := UniqueID(uniquegenerator.GetUniqueIntGeneratorIns().GetInt()) + task.SetID(id) + assert.Equal(t, id, task.ID()) + + task.Base.MsgType = commonpb.MsgType_AlterAlias + assert.Equal(t, commonpb.MsgType_AlterAlias, task.Type()) + ts := Timestamp(time.Now().UnixNano()) + task.SetTs(ts) + assert.Equal(t, ts, task.BeginTs()) + assert.Equal(t, ts, task.EndTs()) + + task.AlterAliasRequest.Alias = "illgal-alias:!" + assert.Error(t, task.PreExecute(ctx)) + task.AlterAliasRequest.Alias = "alias1" + task.AlterAliasRequest.CollectionName = "illgal-collection:!" + assert.Error(t, task.PreExecute(ctx)) + task.AlterAliasRequest.CollectionName = collectionName + + assert.NoError(t, task.PreExecute(ctx)) + assert.NoError(t, task.Execute(ctx)) + assert.NoError(t, task.PostExecute(ctx)) +} + +func TestDescribeAlias_all(t *testing.T) { + rc := NewRootCoordMock() + + defer rc.Close() + ctx := context.Background() + task := &DescribeAliasTask{ + Condition: NewTaskCondition(ctx), + DescribeAliasRequest: &milvuspb.DescribeAliasRequest{ + Base: nil, + Alias: "alias1", + }, + ctx: ctx, + result: &milvuspb.DescribeAliasResponse{ + Status: &commonpb.Status{ + ErrorCode: commonpb.ErrorCode_Success, + }, + }, + rootCoord: rc, + } + + assert.NoError(t, task.OnEnqueue()) + + assert.NotNil(t, task.TraceCtx()) + + id := UniqueID(uniquegenerator.GetUniqueIntGeneratorIns().GetInt()) + task.SetID(id) + assert.Equal(t, id, task.ID()) + + task.Base.MsgType = commonpb.MsgType_DescribeAlias + assert.Equal(t, commonpb.MsgType_DescribeAlias, task.Type()) + ts := Timestamp(time.Now().UnixNano()) + task.SetTs(ts) + assert.Equal(t, ts, task.BeginTs()) + assert.Equal(t, ts, task.EndTs()) + + assert.NoError(t, task.PreExecute(ctx)) + assert.NoError(t, task.Execute(ctx)) + assert.NoError(t, task.PostExecute(ctx)) +} + +func TestListAliases_all(t *testing.T) { + rc := NewRootCoordMock() + + defer rc.Close() + ctx := context.Background() + task := &ListAliasesTask{ + Condition: NewTaskCondition(ctx), + ListAliasesRequest: &milvuspb.ListAliasesRequest{ + Base: nil, + }, + ctx: ctx, + result: &milvuspb.ListAliasesResponse{ + Status: &commonpb.Status{ + ErrorCode: commonpb.ErrorCode_Success, + }, + }, + rootCoord: rc, + } + + assert.NoError(t, task.OnEnqueue()) + + assert.NotNil(t, task.TraceCtx()) + + id := UniqueID(uniquegenerator.GetUniqueIntGeneratorIns().GetInt()) + task.SetID(id) + assert.Equal(t, id, task.ID()) + + task.Base.MsgType = commonpb.MsgType_ListAliases + assert.Equal(t, commonpb.MsgType_ListAliases, task.Type()) + ts := Timestamp(time.Now().UnixNano()) + task.SetTs(ts) + assert.Equal(t, ts, task.BeginTs()) + assert.Equal(t, ts, task.EndTs()) + + assert.NoError(t, task.PreExecute(ctx)) + assert.NoError(t, task.Execute(ctx)) + assert.NoError(t, task.PostExecute(ctx)) +} diff --git a/internal/proxy/task_test.go b/internal/proxy/task_test.go index dbc7c32244..59772a761d 100644 --- a/internal/proxy/task_test.go +++ b/internal/proxy/task_test.go @@ -2042,119 +2042,6 @@ func TestTask_VarCharPrimaryKey(t *testing.T) { }) } -func TestCreateAlias_all(t *testing.T) { - rc := NewRootCoordMock() - - defer rc.Close() - ctx := context.Background() - prefix := "TestCreateAlias_all" - collectionName := prefix + funcutil.GenRandomStr() - task := &CreateAliasTask{ - Condition: NewTaskCondition(ctx), - CreateAliasRequest: &milvuspb.CreateAliasRequest{ - Base: nil, - CollectionName: collectionName, - Alias: "alias1", - }, - ctx: ctx, - result: merr.Success(), - rootCoord: rc, - } - - assert.NoError(t, task.OnEnqueue()) - - assert.NotNil(t, task.TraceCtx()) - - id := UniqueID(uniquegenerator.GetUniqueIntGeneratorIns().GetInt()) - task.SetID(id) - assert.Equal(t, id, task.ID()) - - task.Base.MsgType = commonpb.MsgType_CreateAlias - assert.Equal(t, commonpb.MsgType_CreateAlias, task.Type()) - ts := Timestamp(time.Now().UnixNano()) - task.SetTs(ts) - assert.Equal(t, ts, task.BeginTs()) - assert.Equal(t, ts, task.EndTs()) - - assert.NoError(t, task.PreExecute(ctx)) - assert.NoError(t, task.Execute(ctx)) - assert.NoError(t, task.PostExecute(ctx)) -} - -func TestDropAlias_all(t *testing.T) { - rc := NewRootCoordMock() - - defer rc.Close() - ctx := context.Background() - task := &DropAliasTask{ - Condition: NewTaskCondition(ctx), - DropAliasRequest: &milvuspb.DropAliasRequest{ - Base: nil, - Alias: "alias1", - }, - ctx: ctx, - result: merr.Success(), - rootCoord: rc, - } - - assert.NoError(t, task.OnEnqueue()) - assert.NotNil(t, task.TraceCtx()) - - id := UniqueID(uniquegenerator.GetUniqueIntGeneratorIns().GetInt()) - task.SetID(id) - assert.Equal(t, id, task.ID()) - - task.Base.MsgType = commonpb.MsgType_DropAlias - assert.Equal(t, commonpb.MsgType_DropAlias, task.Type()) - ts := Timestamp(time.Now().UnixNano()) - task.SetTs(ts) - assert.Equal(t, ts, task.BeginTs()) - assert.Equal(t, ts, task.EndTs()) - - assert.NoError(t, task.PreExecute(ctx)) - assert.NoError(t, task.Execute(ctx)) - assert.NoError(t, task.PostExecute(ctx)) -} - -func TestAlterAlias_all(t *testing.T) { - rc := NewRootCoordMock() - - defer rc.Close() - ctx := context.Background() - prefix := "TestAlterAlias_all" - collectionName := prefix + funcutil.GenRandomStr() - task := &AlterAliasTask{ - Condition: NewTaskCondition(ctx), - AlterAliasRequest: &milvuspb.AlterAliasRequest{ - Base: nil, - CollectionName: collectionName, - Alias: "alias1", - }, - ctx: ctx, - result: merr.Success(), - rootCoord: rc, - } - - assert.NoError(t, task.OnEnqueue()) - - assert.NotNil(t, task.TraceCtx()) - - id := UniqueID(uniquegenerator.GetUniqueIntGeneratorIns().GetInt()) - task.SetID(id) - assert.Equal(t, id, task.ID()) - - task.Base.MsgType = commonpb.MsgType_AlterAlias - assert.Equal(t, commonpb.MsgType_AlterAlias, task.Type()) - ts := Timestamp(time.Now().UnixNano()) - task.SetTs(ts) - assert.Equal(t, ts, task.BeginTs()) - assert.Equal(t, ts, task.EndTs()) - - assert.NoError(t, task.PreExecute(ctx)) - assert.NoError(t, task.Execute(ctx)) - assert.NoError(t, task.PostExecute(ctx)) -} - func Test_createIndexTask_getIndexedField(t *testing.T) { collectionName := "test" fieldName := "test" diff --git a/internal/rootcoord/meta_table.go b/internal/rootcoord/meta_table.go index 5fef29ef34..382a1a55b5 100644 --- a/internal/rootcoord/meta_table.go +++ b/internal/rootcoord/meta_table.go @@ -65,6 +65,8 @@ type IMetaTable interface { CreateAlias(ctx context.Context, dbName string, alias string, collectionName string, ts Timestamp) error DropAlias(ctx context.Context, dbName string, alias string, ts Timestamp) error AlterAlias(ctx context.Context, dbName string, alias string, collectionName string, ts Timestamp) error + DescribeAlias(ctx context.Context, dbName string, alias string, ts Timestamp) (string, error) + ListAliases(ctx context.Context, dbName string, collectionName string, ts Timestamp) ([]string, error) AlterCollection(ctx context.Context, oldColl *model.Collection, newColl *model.Collection, ts Timestamp) error RenameCollection(ctx context.Context, dbName string, oldName string, newDBName string, newName string, ts Timestamp) error @@ -1054,6 +1056,71 @@ func (mt *MetaTable) AlterAlias(ctx context.Context, dbName string, alias string return nil } +func (mt *MetaTable) DescribeAlias(ctx context.Context, dbName string, alias string, ts Timestamp) (string, error) { + mt.ddLock.Lock() + defer mt.ddLock.Unlock() + + if dbName == "" { + log.Warn("db name is empty", zap.String("alias", alias)) + dbName = util.DefaultDBName + } + + // check if database exists. + dbExist := mt.aliases.exist(dbName) + if !dbExist { + return "", merr.WrapErrDatabaseNotFound(dbName) + } + // check if alias exists. + collectionID, ok := mt.aliases.get(dbName, alias) + if !ok { + return "", merr.WrapErrAliasNotFound(dbName, alias) + } + + collectionMeta, ok := mt.collID2Meta[collectionID] + if !ok { + return "", merr.WrapErrCollectionIDOfAliasNotFound(collectionID) + } + if collectionMeta.State == pb.CollectionState_CollectionCreated { + return collectionMeta.Name, nil + } + return "", merr.WrapErrAliasNotFound(dbName, alias) +} + +func (mt *MetaTable) ListAliases(ctx context.Context, dbName string, collectionName string, ts Timestamp) ([]string, error) { + mt.ddLock.Lock() + defer mt.ddLock.Unlock() + + if dbName == "" { + log.Warn("db name is empty", zap.String("collection", collectionName)) + dbName = util.DefaultDBName + } + + // check if database exists. + dbExist := mt.aliases.exist(dbName) + if !dbExist { + return nil, merr.WrapErrDatabaseNotFound(dbName) + } + var aliases []string + if collectionName == "" { + collections := mt.aliases.listCollections(dbName) + for name, collectionID := range collections { + if collectionMeta, ok := mt.collID2Meta[collectionID]; ok && + collectionMeta.State == pb.CollectionState_CollectionCreated { + aliases = append(aliases, name) + } + } + } else { + collectionID, exist := mt.names.get(dbName, collectionName) + collectionMeta, exist2 := mt.collID2Meta[collectionID] + if exist && exist2 && collectionMeta.State == pb.CollectionState_CollectionCreated { + aliases = mt.listAliasesByID(collectionID) + } else { + return nil, merr.WrapErrCollectionNotFound(collectionName) + } + } + return aliases, nil +} + func (mt *MetaTable) IsAlias(db, name string) bool { mt.ddLock.RLock() defer mt.ddLock.RUnlock() diff --git a/internal/rootcoord/meta_table_test.go b/internal/rootcoord/meta_table_test.go index 058e954324..3280f8cd9b 100644 --- a/internal/rootcoord/meta_table_test.go +++ b/internal/rootcoord/meta_table_test.go @@ -709,6 +709,234 @@ func TestMetaTable_AlterCollection(t *testing.T) { }) } +func TestMetaTable_DescribeAlias(t *testing.T) { + t.Run("metatable describe alias ok", func(t *testing.T) { + var collectionID int64 = 100 + collectionName := "test_metatable_describe_alias" + aliasName := "a_alias" + meta := &MetaTable{ + collID2Meta: map[typeutil.UniqueID]*model.Collection{ + collectionID: { + CollectionID: collectionID, + Name: collectionName, + }, + }, + names: newNameDb(), + aliases: newNameDb(), + } + meta.names.insert("", collectionName, collectionID) + meta.aliases.insert("", aliasName, collectionID) + + ctx := context.Background() + descCollectionName, err := meta.DescribeAlias(ctx, "", aliasName, 0) + assert.NoError(t, err) + assert.Equal(t, collectionName, descCollectionName) + }) + + t.Run("metatable describe not exist alias", func(t *testing.T) { + var collectionID int64 = 100 + aliasName1 := "a_alias" + aliasName2 := "a_alias2" + meta := &MetaTable{ + names: newNameDb(), + aliases: newNameDb(), + } + meta.aliases.insert("", aliasName1, collectionID) + ctx := context.Background() + descCollectionName, err := meta.DescribeAlias(ctx, "", aliasName2, 0) + assert.Error(t, err) + assert.Equal(t, "", descCollectionName) + }) + + t.Run("metatable describe not exist database", func(t *testing.T) { + aliasName := "a_alias" + meta := &MetaTable{ + names: newNameDb(), + aliases: newNameDb(), + } + ctx := context.Background() + descCollectionName, err := meta.DescribeAlias(ctx, "", aliasName, 0) + assert.Error(t, err) + assert.Equal(t, "", descCollectionName) + }) + + t.Run("metatable describe alias fail", func(t *testing.T) { + var collectionID int64 = 100 + collectionName := "test_metatable_describe_alias" + aliasName := "a_alias" + meta := &MetaTable{ + names: newNameDb(), + aliases: newNameDb(), + } + meta.names.insert("", collectionName, collectionID) + meta.aliases.insert("", aliasName, collectionID) + ctx := context.Background() + _, err := meta.DescribeAlias(ctx, "", aliasName, 0) + assert.Error(t, err) + }) + + t.Run("metatable describe alias dropped collection", func(t *testing.T) { + var collectionID int64 = 100 + collectionName := "test_metatable_describe_alias" + aliasName := "a_alias" + meta := &MetaTable{ + collID2Meta: map[typeutil.UniqueID]*model.Collection{ + collectionID: { + CollectionID: collectionID, + Name: collectionName, + }, + }, + names: newNameDb(), + aliases: newNameDb(), + } + meta.names.insert("", collectionName, collectionID) + meta.aliases.insert("", aliasName, collectionID) + + ctx := context.Background() + meta.collID2Meta[collectionID] = &model.Collection{State: pb.CollectionState_CollectionDropped} + alias, err := meta.DescribeAlias(ctx, "", aliasName, 0) + assert.Equal(t, "", alias) + assert.Error(t, err) + }) +} + +func TestMetaTable_ListAliases(t *testing.T) { + t.Run("metatable list alias ok", func(t *testing.T) { + var collectionID1 int64 = 101 + collectionName1 := "test_metatable_list_alias1" + aliasName1 := "a_alias" + var collectionID2 int64 = 102 + collectionName2 := "test_metatable_list_alias2" + aliasName2 := "a_alias2" + var collectionID3 int64 = 103 + collectionName3 := "test_metatable_list_alias3" + aliasName3 := "a_alias3" + aliasName4 := "a_alias4" + meta := &MetaTable{ + collID2Meta: map[typeutil.UniqueID]*model.Collection{ + collectionID1: { + CollectionID: collectionID1, + Name: collectionName1, + }, + collectionID1: { + CollectionID: collectionID2, + Name: collectionName2, + }, + }, + names: newNameDb(), + aliases: newNameDb(), + } + meta.names.insert("", collectionName1, collectionID1) + meta.names.insert("", collectionName2, collectionID2) + meta.names.insert("db2", collectionName3, collectionID3) + + meta.aliases.insert("", aliasName1, collectionID1) + meta.aliases.insert("", aliasName2, collectionID2) + meta.aliases.insert("db2", aliasName3, collectionID3) + meta.aliases.insert("db2", aliasName4, collectionID3) + + meta.collID2Meta[collectionID1] = &model.Collection{State: pb.CollectionState_CollectionCreated} + meta.collID2Meta[collectionID2] = &model.Collection{State: pb.CollectionState_CollectionCreated} + meta.collID2Meta[collectionID3] = &model.Collection{State: pb.CollectionState_CollectionCreated} + + ctx := context.Background() + aliases, err := meta.ListAliases(ctx, "", "", 0) + assert.NoError(t, err) + assert.Equal(t, 2, len(aliases)) + + aliases2, err := meta.ListAliases(ctx, "", collectionName1, 0) + assert.NoError(t, err) + assert.Equal(t, 1, len(aliases2)) + + aliases3, err := meta.ListAliases(ctx, "db2", "", 0) + assert.NoError(t, err) + assert.Equal(t, 2, len(aliases3)) + + aliases4, err := meta.ListAliases(ctx, "db2", collectionName3, 0) + assert.NoError(t, err) + assert.Equal(t, 2, len(aliases4)) + }) + + t.Run("metatable list alias in not exist database", func(t *testing.T) { + aliasName := "a_alias" + meta := &MetaTable{ + names: newNameDb(), + aliases: newNameDb(), + } + ctx := context.Background() + aliases, err := meta.ListAliases(ctx, "", aliasName, 0) + assert.Error(t, err) + assert.Equal(t, 0, len(aliases)) + }) + + t.Run("metatable list alias error", func(t *testing.T) { + var collectionID1 int64 = 101 + collectionName1 := "test_metatable_list_alias1" + aliasName1 := "a_alias" + var collectionID2 int64 = 102 + collectionName2 := "test_metatable_list_alias2" + aliasName2 := "a_alias2" + meta := &MetaTable{ + collID2Meta: map[typeutil.UniqueID]*model.Collection{ + collectionID1: { + CollectionID: collectionID1, + Name: collectionName1, + }, + collectionID1: { + CollectionID: collectionID2, + Name: collectionName2, + }, + }, + names: newNameDb(), + aliases: newNameDb(), + } + meta.aliases.insert("", aliasName1, collectionID1) + meta.aliases.insert("", aliasName2, collectionID2) + ctx := context.Background() + _, err := meta.ListAliases(ctx, "", collectionName1, 0) + assert.Error(t, err) + }) + + t.Run("metatable list alias Dropping collection", func(t *testing.T) { + ctx := context.Background() + + var collectionID1 int64 = 101 + collectionName1 := "test_metatable_list_alias1" + aliasName1 := "a_alias" + var collectionID2 int64 = 102 + collectionName2 := "test_metatable_list_alias2" + aliasName2 := "a_alias2" + meta := &MetaTable{ + collID2Meta: map[typeutil.UniqueID]*model.Collection{ + collectionID1: { + CollectionID: collectionID1, + Name: collectionName1, + }, + collectionID1: { + CollectionID: collectionID2, + Name: collectionName2, + }, + }, + names: newNameDb(), + aliases: newNameDb(), + } + meta.names.insert("", collectionName1, collectionID1) + meta.names.insert("", collectionName2, collectionID2) + meta.aliases.insert("", aliasName1, collectionID1) + meta.aliases.insert("", aliasName2, collectionID2) + meta.collID2Meta[collectionID1] = &model.Collection{State: pb.CollectionState_CollectionCreated} + meta.collID2Meta[collectionID2] = &model.Collection{State: pb.CollectionState_CollectionDropped} + + aliases, err := meta.ListAliases(ctx, "", "", 0) + assert.NoError(t, err) + assert.Equal(t, 1, len(aliases)) + + aliases2, err := meta.ListAliases(ctx, "", collectionName1, 0) + assert.NoError(t, err) + assert.Equal(t, 1, len(aliases2)) + }) +} + func Test_filterUnavailable(t *testing.T) { coll := &model.Collection{} nPartition := 10 diff --git a/internal/rootcoord/mock_test.go b/internal/rootcoord/mock_test.go index 3e603b2f88..eb53ed9ce9 100644 --- a/internal/rootcoord/mock_test.go +++ b/internal/rootcoord/mock_test.go @@ -72,6 +72,8 @@ type mockMetaTable struct { AlterAliasFunc func(ctx context.Context, dbName string, alias string, collectionName string, ts Timestamp) error DropAliasFunc func(ctx context.Context, dbName string, alias string, ts Timestamp) error IsAliasFunc func(dbName, name string) bool + DescribeAliasFunc func(ctx context.Context, dbName, alias string, ts Timestamp) (string, error) + ListAliasesFunc func(ctx context.Context, dbName, collectionName string, ts Timestamp) ([]string, error) ListAliasesByIDFunc func(collID UniqueID) []string GetCollectionIDByNameFunc func(name string) (UniqueID, error) GetPartitionByNameFunc func(collID UniqueID, partitionName string, ts Timestamp) (UniqueID, error) @@ -151,6 +153,14 @@ func (m mockMetaTable) IsAlias(dbName, name string) bool { return m.IsAliasFunc(dbName, name) } +func (m mockMetaTable) DescribeAlias(ctx context.Context, dbName, alias string, ts Timestamp) (string, error) { + return m.DescribeAliasFunc(ctx, dbName, alias, ts) +} + +func (m mockMetaTable) ListAliases(ctx context.Context, dbName, collectionName string, ts Timestamp) ([]string, error) { + return m.ListAliasesFunc(ctx, dbName, collectionName, ts) +} + func (m mockMetaTable) ListAliasesByID(collID UniqueID) []string { return m.ListAliasesByIDFunc(collID) } @@ -510,6 +520,12 @@ func withInvalidMeta() Opt { meta.ListUserRoleFunc = func(tenant string) ([]string, error) { return nil, errors.New("error mock ListUserRole") } + meta.DescribeAliasFunc = func(ctx context.Context, dbName, alias string, ts Timestamp) (string, error) { + return "", errors.New("error mock DescribeAlias") + } + meta.ListAliasesFunc = func(ctx context.Context, dbName, collectionName string, ts Timestamp) ([]string, error) { + return nil, errors.New("error mock ListAliases") + } return withMeta(meta) } diff --git a/internal/rootcoord/mocks/meta_table.go b/internal/rootcoord/mocks/meta_table.go index de3274b034..7d67ea825a 100644 --- a/internal/rootcoord/mocks/meta_table.go +++ b/internal/rootcoord/mocks/meta_table.go @@ -555,6 +555,61 @@ func (_c *IMetaTable_DeleteCredential_Call) RunAndReturn(run func(string) error) return _c } +// DescribeAlias provides a mock function with given fields: ctx, dbName, alias, ts +func (_m *IMetaTable) DescribeAlias(ctx context.Context, dbName string, alias string, ts uint64) (string, error) { + ret := _m.Called(ctx, dbName, alias, ts) + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, uint64) (string, error)); ok { + return rf(ctx, dbName, alias, ts) + } + if rf, ok := ret.Get(0).(func(context.Context, string, string, uint64) string); ok { + r0 = rf(ctx, dbName, alias, ts) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(context.Context, string, string, uint64) error); ok { + r1 = rf(ctx, dbName, alias, ts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// IMetaTable_DescribeAlias_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DescribeAlias' +type IMetaTable_DescribeAlias_Call struct { + *mock.Call +} + +// DescribeAlias is a helper method to define mock.On call +// - ctx context.Context +// - dbName string +// - alias string +// - ts uint64 +func (_e *IMetaTable_Expecter) DescribeAlias(ctx interface{}, dbName interface{}, alias interface{}, ts interface{}) *IMetaTable_DescribeAlias_Call { + return &IMetaTable_DescribeAlias_Call{Call: _e.mock.On("DescribeAlias", ctx, dbName, alias, ts)} +} + +func (_c *IMetaTable_DescribeAlias_Call) Run(run func(ctx context.Context, dbName string, alias string, ts uint64)) *IMetaTable_DescribeAlias_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(uint64)) + }) + return _c +} + +func (_c *IMetaTable_DescribeAlias_Call) Return(_a0 string, _a1 error) *IMetaTable_DescribeAlias_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *IMetaTable_DescribeAlias_Call) RunAndReturn(run func(context.Context, string, string, uint64) (string, error)) *IMetaTable_DescribeAlias_Call { + _c.Call.Return(run) + return _c +} + // DropAlias provides a mock function with given fields: ctx, dbName, alias, ts func (_m *IMetaTable) DropAlias(ctx context.Context, dbName string, alias string, ts uint64) error { ret := _m.Called(ctx, dbName, alias, ts) @@ -1206,6 +1261,63 @@ func (_c *IMetaTable_IsAlias_Call) RunAndReturn(run func(string, string) bool) * return _c } +// ListAliases provides a mock function with given fields: ctx, dbName, collectionName, ts +func (_m *IMetaTable) ListAliases(ctx context.Context, dbName string, collectionName string, ts uint64) ([]string, error) { + ret := _m.Called(ctx, dbName, collectionName, ts) + + var r0 []string + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, uint64) ([]string, error)); ok { + return rf(ctx, dbName, collectionName, ts) + } + if rf, ok := ret.Get(0).(func(context.Context, string, string, uint64) []string); ok { + r0 = rf(ctx, dbName, collectionName, ts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]string) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, string, uint64) error); ok { + r1 = rf(ctx, dbName, collectionName, ts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// IMetaTable_ListAliases_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListAliases' +type IMetaTable_ListAliases_Call struct { + *mock.Call +} + +// ListAliases is a helper method to define mock.On call +// - ctx context.Context +// - dbName string +// - collectionName string +// - ts uint64 +func (_e *IMetaTable_Expecter) ListAliases(ctx interface{}, dbName interface{}, collectionName interface{}, ts interface{}) *IMetaTable_ListAliases_Call { + return &IMetaTable_ListAliases_Call{Call: _e.mock.On("ListAliases", ctx, dbName, collectionName, ts)} +} + +func (_c *IMetaTable_ListAliases_Call) Run(run func(ctx context.Context, dbName string, collectionName string, ts uint64)) *IMetaTable_ListAliases_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(uint64)) + }) + return _c +} + +func (_c *IMetaTable_ListAliases_Call) Return(_a0 []string, _a1 error) *IMetaTable_ListAliases_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *IMetaTable_ListAliases_Call) RunAndReturn(run func(context.Context, string, string, uint64) ([]string, error)) *IMetaTable_ListAliases_Call { + _c.Call.Return(run) + return _c +} + // ListAliasesByID provides a mock function with given fields: collID func (_m *IMetaTable) ListAliasesByID(collID int64) []string { ret := _m.Called(collID) diff --git a/internal/rootcoord/name_db.go b/internal/rootcoord/name_db.go index 5f87558873..4d839ebf47 100644 --- a/internal/rootcoord/name_db.go +++ b/internal/rootcoord/name_db.go @@ -1,3 +1,19 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package rootcoord import ( @@ -5,6 +21,7 @@ import ( "golang.org/x/exp/maps" + "github.com/milvus-io/milvus/pkg/util" "github.com/milvus-io/milvus/pkg/util/typeutil" ) @@ -35,6 +52,9 @@ func (n *nameDb) dropDb(dbName string) { } func (n *nameDb) insert(dbName string, collectionName string, collectionID UniqueID) { + if dbName == "" { + dbName = util.DefaultDBName + } n.createDbIfNotExist(dbName) n.db2Name2ID[dbName][collectionName] = collectionID } @@ -55,6 +75,14 @@ func (n *nameDb) listDB() []string { return dbs } +func (n *nameDb) listCollections(dbName string) map[string]UniqueID { + res, ok := n.db2Name2ID[dbName] + if ok { + return res + } + return map[string]UniqueID{} +} + func (n *nameDb) listCollectionID(dbName string) ([]typeutil.UniqueID, error) { name2ID, ok := n.db2Name2ID[dbName] if !ok { diff --git a/internal/rootcoord/root_coord.go b/internal/rootcoord/root_coord.go index 928f8444fe..430778e288 100644 --- a/internal/rootcoord/root_coord.go +++ b/internal/rootcoord/root_coord.go @@ -1853,6 +1853,86 @@ func (c *Core) AlterAlias(ctx context.Context, in *milvuspb.AlterAliasRequest) ( return merr.Success(), nil } +// DescribeAlias describe collection alias +func (c *Core) DescribeAlias(ctx context.Context, in *milvuspb.DescribeAliasRequest) (*milvuspb.DescribeAliasResponse, error) { + if err := merr.CheckHealthy(c.GetStateCode()); err != nil { + return &milvuspb.DescribeAliasResponse{ + Status: merr.Status(err), + }, nil + } + + log := log.Ctx(ctx).With( + zap.String("role", typeutil.RootCoordRole), + zap.String("db", in.GetDbName()), + zap.String("alias", in.GetAlias())) + method := "DescribeAlias" + metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.TotalLabel).Inc() + tr := timerecord.NewTimeRecorder("DescribeAlias") + + log.Info("received request to describe alias") + + if in.GetAlias() == "" { + return &milvuspb.DescribeAliasResponse{ + Status: merr.Status(merr.WrapErrParameterMissing("alias", "no input alias")), + }, nil + } + + collectionName, err := c.meta.DescribeAlias(ctx, in.GetDbName(), in.GetAlias(), 0) + if err != nil { + log.Warn("fail to DescribeAlias", zap.Error(err)) + return &milvuspb.DescribeAliasResponse{ + Status: merr.Status(err), + }, nil + } + metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc() + metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds())) + + log.Info("done to describe alias") + return &milvuspb.DescribeAliasResponse{ + Status: merr.Status(nil), + DbName: in.GetDbName(), + Alias: in.GetAlias(), + Collection: collectionName, + }, nil +} + +// ListAliases list aliases +func (c *Core) ListAliases(ctx context.Context, in *milvuspb.ListAliasesRequest) (*milvuspb.ListAliasesResponse, error) { + if err := merr.CheckHealthy(c.GetStateCode()); err != nil { + return &milvuspb.ListAliasesResponse{ + Status: merr.Status(err), + }, nil + } + + method := "ListAliases" + metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.TotalLabel).Inc() + tr := timerecord.NewTimeRecorder(method) + + log := log.Ctx(ctx).With( + zap.String("role", typeutil.RootCoordRole), + zap.String("db", in.GetDbName()), + zap.String("collectionName", in.GetCollectionName())) + log.Info("received request to list aliases") + + aliases, err := c.meta.ListAliases(ctx, in.GetDbName(), in.GetCollectionName(), 0) + if err != nil { + log.Warn("fail to ListAliases", zap.Error(err)) + return &milvuspb.ListAliasesResponse{ + Status: merr.Status(err), + }, nil + } + + metrics.RootCoordDDLReqCounter.WithLabelValues(method, metrics.SuccessLabel).Inc() + metrics.RootCoordDDLReqLatency.WithLabelValues(method).Observe(float64(tr.ElapseSpan().Milliseconds())) + + log.Info("done to list aliases") + return &milvuspb.ListAliasesResponse{ + Status: merr.Status(nil), + DbName: in.GetDbName(), + Aliases: aliases, + }, nil +} + // Import imports large files (json, numpy, etc.) on MinIO/S3 storage into Milvus storage. func (c *Core) Import(ctx context.Context, req *milvuspb.ImportRequest) (*milvuspb.ImportResponse, error) { if err := merr.CheckHealthy(c.GetStateCode()); err != nil { diff --git a/internal/rootcoord/root_coord_test.go b/internal/rootcoord/root_coord_test.go index 08a1d998c1..836f057797 100644 --- a/internal/rootcoord/root_coord_test.go +++ b/internal/rootcoord/root_coord_test.go @@ -462,6 +462,109 @@ func TestRootCoord_AlterAlias(t *testing.T) { }) } +func TestRootCoord_DescribeAlias(t *testing.T) { + t.Run("not healthy", func(t *testing.T) { + c := newTestCore(withAbnormalCode()) + ctx := context.Background() + resp, err := c.DescribeAlias(ctx, &milvuspb.DescribeAliasRequest{Alias: "test"}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) + + t.Run("failed to add task", func(t *testing.T) { + c := newTestCore(withHealthyCode(), + withInvalidScheduler(), + withInvalidMeta()) + ctx := context.Background() + resp, err := c.DescribeAlias(ctx, &milvuspb.DescribeAliasRequest{Alias: "test"}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) + + t.Run("failed to execute", func(t *testing.T) { + c := newTestCore(withHealthyCode(), + withTaskFailScheduler(), + withInvalidMeta()) + ctx := context.Background() + resp, err := c.DescribeAlias(ctx, &milvuspb.DescribeAliasRequest{Alias: "test"}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) + + t.Run("input alias is empty", func(t *testing.T) { + c := newTestCore(withHealthyCode(), + withValidScheduler()) + meta := newMockMetaTable() + meta.DescribeAliasFunc = func(ctx context.Context, dbName, alias string, ts Timestamp) (string, error) { + return "", nil + } + c.meta = meta + ctx := context.Background() + resp, err := c.DescribeAlias(ctx, &milvuspb.DescribeAliasRequest{}) + assert.NoError(t, err) + assert.Equal(t, commonpb.ErrorCode_UnexpectedError, resp.GetStatus().GetErrorCode()) + assert.Equal(t, int32(1101), resp.GetStatus().GetCode()) + }) + + t.Run("normal case, everything is ok", func(t *testing.T) { + c := newTestCore(withHealthyCode(), + withValidScheduler()) + meta := newMockMetaTable() + meta.DescribeAliasFunc = func(ctx context.Context, dbName, alias string, ts Timestamp) (string, error) { + return "", nil + } + c.meta = meta + ctx := context.Background() + resp, err := c.DescribeAlias(ctx, &milvuspb.DescribeAliasRequest{Alias: "test"}) + assert.NoError(t, err) + assert.Equal(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) +} + +func TestRootCoord_ListAliases(t *testing.T) { + t.Run("not healthy", func(t *testing.T) { + c := newTestCore(withAbnormalCode()) + ctx := context.Background() + resp, err := c.ListAliases(ctx, &milvuspb.ListAliasesRequest{}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) + + t.Run("failed to add task", func(t *testing.T) { + c := newTestCore(withHealthyCode(), + withInvalidScheduler(), + withInvalidMeta()) + ctx := context.Background() + resp, err := c.ListAliases(ctx, &milvuspb.ListAliasesRequest{}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) + + t.Run("failed to execute", func(t *testing.T) { + c := newTestCore(withHealthyCode(), + withTaskFailScheduler(), + withInvalidMeta()) + ctx := context.Background() + resp, err := c.ListAliases(ctx, &milvuspb.ListAliasesRequest{}) + assert.NoError(t, err) + assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) + + t.Run("normal case, everything is ok", func(t *testing.T) { + c := newTestCore(withHealthyCode(), + withValidScheduler()) + meta := newMockMetaTable() + meta.ListAliasesFunc = func(ctx context.Context, dbName, collectionName string, ts Timestamp) ([]string, error) { + return nil, nil + } + c.meta = meta + ctx := context.Background() + resp, err := c.ListAliases(ctx, &milvuspb.ListAliasesRequest{}) + assert.NoError(t, err) + assert.Equal(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode()) + }) +} + func TestRootCoord_DescribeCollection(t *testing.T) { t.Run("not healthy", func(t *testing.T) { c := newTestCore(withAbnormalCode()) diff --git a/internal/util/mock/grpc_rootcoord_client.go b/internal/util/mock/grpc_rootcoord_client.go index 98be9c7c4f..ff2cfcabcc 100644 --- a/internal/util/mock/grpc_rootcoord_client.go +++ b/internal/util/mock/grpc_rootcoord_client.go @@ -142,6 +142,14 @@ func (m *GrpcRootCoordClient) AlterAlias(ctx context.Context, in *milvuspb.Alter return &commonpb.Status{}, m.Err } +func (m *GrpcRootCoordClient) DescribeAlias(ctx context.Context, in *milvuspb.DescribeAliasRequest, opts ...grpc.CallOption) (*milvuspb.DescribeAliasResponse, error) { + return &milvuspb.DescribeAliasResponse{}, m.Err +} + +func (m *GrpcRootCoordClient) ListAliases(ctx context.Context, in *milvuspb.ListAliasesRequest, opts ...grpc.CallOption) (*milvuspb.ListAliasesResponse, error) { + return &milvuspb.ListAliasesResponse{}, m.Err +} + func (m *GrpcRootCoordClient) ShowCollections(ctx context.Context, in *milvuspb.ShowCollectionsRequest, opts ...grpc.CallOption) (*milvuspb.ShowCollectionsResponse, error) { return &milvuspb.ShowCollectionsResponse{}, m.Err } diff --git a/pkg/util/merr/errors.go b/pkg/util/merr/errors.go index 411e108749..fcd588f544 100644 --- a/pkg/util/merr/errors.go +++ b/pkg/util/merr/errors.go @@ -28,7 +28,7 @@ const ( // Define leaf errors here, // WARN: take care to add new error, -// check whehter you can use the erorrs below before adding a new one. +// check whether you can use the errors below before adding a new one. // Name: Err + related prefix + error name var ( // Service related @@ -99,6 +99,7 @@ var ( // Parameter related ErrParameterInvalid = newMilvusError("invalid parameter", 1100, false) + ErrParameterMissing = newMilvusError("missing parameter", 1101, false) // Metrics related ErrMetricNotFound = newMilvusError("metric not found", 1200, false) @@ -119,6 +120,7 @@ var ( ErrAliasNotFound = newMilvusError("alias not found", 1600, false) ErrAliasCollectionNameConfilct = newMilvusError("alias and collection name conflict", 1601, false) ErrAliasAlreadyExist = newMilvusError("alias already exist", 1602, false) + ErrCollectionIDOfAliasNotFound = newMilvusError("collection id of alias not found", 1603, false) // field related ErrFieldNotFound = newMilvusError("field not found", 1700, false) diff --git a/pkg/util/merr/errors_test.go b/pkg/util/merr/errors_test.go index adead2617f..f2d5064dfc 100644 --- a/pkg/util/merr/errors_test.go +++ b/pkg/util/merr/errors_test.go @@ -128,6 +128,7 @@ func (s *ErrSuite) TestWrap() { // Parameter related s.ErrorIs(WrapErrParameterInvalid(8, 1, "failed to create"), ErrParameterInvalid) s.ErrorIs(WrapErrParameterInvalidRange(1, 1<<16, 0, "topk should be in range"), ErrParameterInvalid) + s.ErrorIs(WrapErrParameterMissing("alias_name", "no alias parameter"), ErrParameterMissing) // Metrics related s.ErrorIs(WrapErrMetricNotFound("unknown", "failed to get metric"), ErrMetricNotFound) @@ -139,6 +140,10 @@ func (s *ErrSuite) TestWrap() { // field related s.ErrorIs(WrapErrFieldNotFound("meta", "failed to get field"), ErrFieldNotFound) + + // alias related + s.ErrorIs(WrapErrAliasNotFound("alias", "failed to get collection id"), ErrAliasNotFound) + s.ErrorIs(WrapErrCollectionIDOfAliasNotFound(1000, "failed to get collection id"), ErrCollectionIDOfAliasNotFound) } func (s *ErrSuite) TestOldCode() { diff --git a/pkg/util/merr/utils.go b/pkg/util/merr/utils.go index 9310edb0d5..dacd238ebb 100644 --- a/pkg/util/merr/utils.go +++ b/pkg/util/merr/utils.go @@ -448,6 +448,14 @@ func WrapErrCollectionNumLimitExceeded(limit int, msg ...string) error { return err } +func WrapErrCollectionIDOfAliasNotFound(collectionID int64, msg ...string) error { + err := wrapFields(ErrCollectionIDOfAliasNotFound, value("collectionID", collectionID)) + if len(msg) > 0 { + err = errors.Wrap(err, strings.Join(msg, "; ")) + } + return err +} + func WrapErrCollectionNotFullyLoaded(collection any, msg ...string) error { err := wrapFields(ErrCollectionNotFullyLoaded, value("collection", collection)) if len(msg) > 0 { @@ -778,6 +786,16 @@ func WrapErrParameterInvalidMsg(fmt string, args ...any) error { return errors.Wrapf(ErrParameterInvalid, fmt, args...) } +func WrapErrParameterMissing[T any](param T, msg ...string) error { + err := wrapFields(ErrParameterMissing, + value("missing_param", param), + ) + if len(msg) > 0 { + err = errors.Wrap(err, strings.Join(msg, "->")) + } + return err +} + // Metrics related func WrapErrMetricNotFound(name string, msg ...string) error { err := wrapFields(ErrMetricNotFound, value("metric", name)) diff --git a/tests/integration/alias/alias_test.go b/tests/integration/alias/alias_test.go new file mode 100644 index 0000000000..85dfb1eda6 --- /dev/null +++ b/tests/integration/alias/alias_test.go @@ -0,0 +1,212 @@ +// Licensed to the LF AI & Data foundation under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package alias + +import ( + "context" + "testing" + + "github.com/golang/protobuf/proto" + "github.com/stretchr/testify/suite" + "go.uber.org/zap" + + "github.com/milvus-io/milvus-proto/go-api/v2/commonpb" + "github.com/milvus-io/milvus-proto/go-api/v2/milvuspb" + "github.com/milvus-io/milvus-proto/go-api/v2/schemapb" + "github.com/milvus-io/milvus/pkg/log" + "github.com/milvus-io/milvus/pkg/util/funcutil" + "github.com/milvus-io/milvus/tests/integration" +) + +type AliasSuite struct { + integration.MiniClusterSuite +} + +func (s *AliasSuite) TestAliasOperations() { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + c := s.Cluster + + // create 2 collection + const ( + prefix = "TestAliasOperations" + dim = 128 + dbName = "" + rowNum = 3000 + ) + collectionName := prefix + funcutil.GenRandomStr() + collectionName1 := collectionName + "1" + collectionName2 := collectionName + "2" + + schema1 := integration.ConstructSchema(collectionName1, dim, true) + marshaledSchema1, err := proto.Marshal(schema1) + s.NoError(err) + createCollectionStatus, err := c.Proxy.CreateCollection(ctx, &milvuspb.CreateCollectionRequest{ + DbName: dbName, + CollectionName: collectionName1, + Schema: marshaledSchema1, + }) + s.NoError(err) + log.Info("CreateCollection 1 result", zap.Any("createCollectionStatus", createCollectionStatus)) + + schema2 := integration.ConstructSchema(collectionName2, dim, true) + marshaledSchema2, err := proto.Marshal(schema2) + s.NoError(err) + createCollectionStatus2, err := c.Proxy.CreateCollection(ctx, &milvuspb.CreateCollectionRequest{ + DbName: dbName, + CollectionName: collectionName2, + Schema: marshaledSchema2, + }) + s.NoError(err) + log.Info("CreateCollection 2 result", zap.Any("createCollectionStatus", createCollectionStatus2)) + + fVecColumn := integration.NewFloatVectorFieldData(integration.FloatVecField, rowNum, dim) + hashKeys := integration.GenerateHashKeys(rowNum) + insertResult, err := c.Proxy.Insert(ctx, &milvuspb.InsertRequest{ + DbName: dbName, + CollectionName: collectionName1, + FieldsData: []*schemapb.FieldData{fVecColumn}, + HashKeys: hashKeys, + NumRows: uint32(rowNum), + }) + s.NoError(err) + s.Equal(insertResult.GetStatus().GetErrorCode(), commonpb.ErrorCode_Success) + insertResult2, err := c.Proxy.Insert(ctx, &milvuspb.InsertRequest{ + DbName: dbName, + CollectionName: collectionName2, + FieldsData: []*schemapb.FieldData{fVecColumn}, + HashKeys: hashKeys, + NumRows: uint32(rowNum), + }) + s.NoError(err) + s.Equal(insertResult2.GetStatus().GetErrorCode(), commonpb.ErrorCode_Success) + + // flush + flushResp, err := c.Proxy.Flush(ctx, &milvuspb.FlushRequest{ + DbName: dbName, + CollectionNames: []string{collectionName1}, + }) + s.NoError(err) + segmentIDs, has := flushResp.GetCollSegIDs()[collectionName1] + ids := segmentIDs.GetData() + s.Require().NotEmpty(segmentIDs) + s.Require().True(has) + flushTs, has := flushResp.GetCollFlushTs()[collectionName1] + s.Require().True(has) + s.WaitForFlush(ctx, ids, flushTs, dbName, collectionName1) + + flushResp2, err := c.Proxy.Flush(ctx, &milvuspb.FlushRequest{ + DbName: dbName, + CollectionNames: []string{collectionName2}, + }) + s.NoError(err) + segmentIDs2, has2 := flushResp2.GetCollSegIDs()[collectionName2] + ids2 := segmentIDs2.GetData() + s.Require().NotEmpty(segmentIDs) + s.Require().True(has2) + flushTs2, has2 := flushResp2.GetCollFlushTs()[collectionName2] + s.Require().True(has2) + s.WaitForFlush(ctx, ids2, flushTs2, dbName, collectionName2) + + // create alias + // alias11 -> collection1 + // alias12 -> collection1 + // alias21 -> collection2 + createAliasResp1, err := c.Proxy.CreateAlias(ctx, &milvuspb.CreateAliasRequest{ + CollectionName: collectionName1, + Alias: "alias11", + }) + s.NoError(err) + s.Equal(createAliasResp1.GetErrorCode(), commonpb.ErrorCode_Success) + createAliasResp2, err := c.Proxy.CreateAlias(ctx, &milvuspb.CreateAliasRequest{ + CollectionName: collectionName1, + Alias: "alias12", + }) + s.NoError(err) + s.Equal(createAliasResp2.GetErrorCode(), commonpb.ErrorCode_Success) + createAliasResp3, err := c.Proxy.CreateAlias(ctx, &milvuspb.CreateAliasRequest{ + CollectionName: collectionName2, + Alias: "alias21", + }) + s.NoError(err) + s.Equal(createAliasResp3.GetErrorCode(), commonpb.ErrorCode_Success) + + describeAliasResp1, err := c.Proxy.DescribeAlias(ctx, &milvuspb.DescribeAliasRequest{ + Alias: "alias11", + }) + s.NoError(err) + s.Equal(describeAliasResp1.GetStatus().GetErrorCode(), commonpb.ErrorCode_Success) + s.Equal(collectionName1, describeAliasResp1.GetCollection()) + log.Info("describeAliasResp1", + zap.String("alias", describeAliasResp1.GetAlias()), + zap.String("collection", describeAliasResp1.GetCollection())) + + describeAliasResp2, err := c.Proxy.DescribeAlias(ctx, &milvuspb.DescribeAliasRequest{ + Alias: "alias12", + }) + s.NoError(err) + s.Equal(describeAliasResp2.GetStatus().GetErrorCode(), commonpb.ErrorCode_Success) + s.Equal(collectionName1, describeAliasResp2.GetCollection()) + log.Info("describeAliasResp2", + zap.String("alias", describeAliasResp2.GetAlias()), + zap.String("collection", describeAliasResp2.GetCollection())) + + describeAliasResp3, err := c.Proxy.DescribeAlias(ctx, &milvuspb.DescribeAliasRequest{ + Alias: "alias21", + }) + s.NoError(err) + s.Equal(describeAliasResp3.GetStatus().GetErrorCode(), commonpb.ErrorCode_Success) + s.Equal(collectionName2, describeAliasResp3.GetCollection()) + log.Info("describeAliasResp3", + zap.String("alias", describeAliasResp3.GetAlias()), + zap.String("collection", describeAliasResp3.GetCollection())) + + listAliasesResp, err := c.Proxy.ListAliases(ctx, &milvuspb.ListAliasesRequest{}) + s.NoError(err) + s.Equal(listAliasesResp.GetStatus().GetErrorCode(), commonpb.ErrorCode_Success) + s.Equal(3, len(listAliasesResp.Aliases)) + + log.Info("listAliasesResp", zap.Strings("aliases", listAliasesResp.Aliases)) + + dropAliasResp1, err := c.Proxy.DropAlias(ctx, &milvuspb.DropAliasRequest{ + Alias: "alias11", + }) + s.NoError(err) + s.Equal(dropAliasResp1.GetErrorCode(), commonpb.ErrorCode_Success) + + dropAliasResp3, err := c.Proxy.DropAlias(ctx, &milvuspb.DropAliasRequest{ + Alias: "alias21", + }) + s.NoError(err) + s.Equal(dropAliasResp3.GetErrorCode(), commonpb.ErrorCode_Success) + + listAliasesRespNew, err := c.Proxy.ListAliases(ctx, &milvuspb.ListAliasesRequest{}) + s.NoError(err) + s.Equal(listAliasesRespNew.GetStatus().GetErrorCode(), commonpb.ErrorCode_Success) + s.Equal(1, len(listAliasesRespNew.Aliases)) + log.Info("listAliasesResp after drop", zap.Strings("aliases", listAliasesResp.Aliases)) + + log.Info("======================") + log.Info("======================") + log.Info("TestAliasOperations succeed") + log.Info("======================") + log.Info("======================") +} + +func TestAliasOperations(t *testing.T) { + suite.Run(t, new(AliasSuite)) +}