mirror of
https://gitee.com/milvus-io/milvus.git
synced 2026-01-07 19:31:51 +08:00
fix: restful v2 (#32162)
issue: #31176 master pr: #32144 2.4 pr: #32160 1. cannot get dbName correctly while describe alias [Bug]: [restful v2]The dbName parameter of the describe alias interface did not take effect #31978 2. return a valid json string even if the user doesn't have the whole privileges to describe collection [Bug]: [restful v2]When accessing the interface with a user without permission, the response will contain multiple results, some of which will report an error of lack of permission, while one will return the correct result #31635 3. rename IndexParam.IndexConfig to IndexParam.Params 4. FieldSchema.ElementTypeParams, IndexParam.Params can not only accept string Signed-off-by: PowderLi <min.li@zilliz.com>
This commit is contained in:
parent
8da82afb59
commit
0f118e7083
@ -3,6 +3,7 @@ package httpserver
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@ -10,7 +11,7 @@ import (
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-playground/validator/v10"
|
||||
validator "github.com/go-playground/validator/v10"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/tidwall/gjson"
|
||||
"go.opentelemetry.io/otel"
|
||||
@ -205,13 +206,32 @@ func wrapperTraceLog(v2 handlerFuncV2) handlerFuncV2 {
|
||||
}
|
||||
}
|
||||
|
||||
func checkAuthorizationV2(ctx context.Context, c *gin.Context, ignoreErr bool, req interface{}) error {
|
||||
username, ok := c.Get(ContextUsername)
|
||||
if !ok || username.(string) == "" {
|
||||
if !ignoreErr {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{HTTPReturnCode: merr.Code(merr.ErrNeedAuthenticate), HTTPReturnMessage: merr.ErrNeedAuthenticate.Error()})
|
||||
}
|
||||
return merr.ErrNeedAuthenticate
|
||||
}
|
||||
_, authErr := proxy.PrivilegeInterceptor(ctx, req)
|
||||
if authErr != nil {
|
||||
if !ignoreErr {
|
||||
c.JSON(http.StatusForbidden, gin.H{HTTPReturnCode: merr.Code(authErr), HTTPReturnMessage: authErr.Error()})
|
||||
}
|
||||
return authErr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func wrapperProxy(ctx context.Context, c *gin.Context, req any, checkAuth bool, ignoreErr bool, handler func(reqCtx context.Context, req any) (any, error)) (interface{}, error) {
|
||||
if baseGetter, ok := req.(BaseGetter); ok {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
span.AddEvent(baseGetter.GetBase().GetMsgType().String())
|
||||
}
|
||||
if checkAuth {
|
||||
err := checkAuthorization(ctx, c, req)
|
||||
err := checkAuthorizationV2(ctx, c, ignoreErr, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -314,6 +334,7 @@ func (h *HandlersV2) getCollectionDetails(ctx context.Context, c *gin.Context, a
|
||||
} else {
|
||||
autoID = primaryField.AutoID
|
||||
}
|
||||
errMessage := ""
|
||||
loadStateReq := &milvuspb.GetLoadStateRequest{
|
||||
DbName: dbName,
|
||||
CollectionName: collectionName,
|
||||
@ -324,6 +345,8 @@ func (h *HandlersV2) getCollectionDetails(ctx context.Context, c *gin.Context, a
|
||||
collLoadState := ""
|
||||
if err == nil {
|
||||
collLoadState = stateResp.(*milvuspb.GetLoadStateResponse).State.String()
|
||||
} else {
|
||||
errMessage += err.Error() + ";"
|
||||
}
|
||||
vectorField := ""
|
||||
for _, field := range coll.Schema.Fields {
|
||||
@ -338,22 +361,26 @@ func (h *HandlersV2) getCollectionDetails(ctx context.Context, c *gin.Context, a
|
||||
CollectionName: collectionName,
|
||||
FieldName: vectorField,
|
||||
}
|
||||
indexResp, err := wrapperProxy(ctx, c, descIndexReq, false, true, func(reqCtx context.Context, req any) (any, error) {
|
||||
indexResp, err := wrapperProxy(ctx, c, descIndexReq, h.checkAuth, true, func(reqCtx context.Context, req any) (any, error) {
|
||||
return h.proxy.DescribeIndex(reqCtx, req.(*milvuspb.DescribeIndexRequest))
|
||||
})
|
||||
if err == nil {
|
||||
indexDesc = printIndexes(indexResp.(*milvuspb.DescribeIndexResponse).IndexDescriptions)
|
||||
} else {
|
||||
errMessage += err.Error() + ";"
|
||||
}
|
||||
var aliases []string
|
||||
aliasReq := &milvuspb.ListAliasesRequest{
|
||||
DbName: dbName,
|
||||
CollectionName: collectionName,
|
||||
}
|
||||
aliasResp, err := wrapperProxy(ctx, c, aliasReq, h.checkAuth, false, func(reqCtx context.Context, req any) (interface{}, error) {
|
||||
aliasResp, err := wrapperProxy(ctx, c, aliasReq, h.checkAuth, true, func(reqCtx context.Context, req any) (interface{}, error) {
|
||||
return h.proxy.ListAliases(reqCtx, req.(*milvuspb.ListAliasesRequest))
|
||||
})
|
||||
if err == nil {
|
||||
aliases = aliasResp.(*milvuspb.ListAliasesResponse).GetAliases()
|
||||
} else {
|
||||
errMessage += err.Error() + "."
|
||||
}
|
||||
if aliases == nil {
|
||||
aliases = []string{}
|
||||
@ -375,7 +402,7 @@ func (h *HandlersV2) getCollectionDetails(ctx context.Context, c *gin.Context, a
|
||||
"consistencyLevel": commonpb.ConsistencyLevel_name[int32(coll.ConsistencyLevel)],
|
||||
"enableDynamicField": coll.Schema.EnableDynamicField,
|
||||
"properties": coll.Properties,
|
||||
}})
|
||||
}, HTTPReturnMessage: errMessage})
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@ -426,8 +453,11 @@ func (h *HandlersV2) getCollectionLoadState(ctx context.Context, c *gin.Context,
|
||||
return h.proxy.GetLoadingProgress(reqCtx, req.(*milvuspb.GetLoadingProgressRequest))
|
||||
})
|
||||
progress := int64(-1)
|
||||
errMessage := ""
|
||||
if err == nil {
|
||||
progress = progressResp.(*milvuspb.GetLoadingProgressResponse).Progress
|
||||
} else {
|
||||
errMessage += err.Error() + "."
|
||||
}
|
||||
state := commonpb.LoadState_LoadStateLoading.String()
|
||||
if progress >= 100 {
|
||||
@ -436,7 +466,7 @@ func (h *HandlersV2) getCollectionLoadState(ctx context.Context, c *gin.Context,
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: http.StatusOK, HTTPReturnData: gin.H{
|
||||
HTTPReturnLoadState: state,
|
||||
HTTPReturnLoadProgress: progress,
|
||||
}})
|
||||
}, HTTPReturnMessage: errMessage})
|
||||
return resp, err
|
||||
}
|
||||
|
||||
@ -985,7 +1015,7 @@ func (h *HandlersV2) createCollection(ctx context.Context, c *gin.Context, anyRe
|
||||
}
|
||||
}
|
||||
for key, fieldParam := range field.ElementTypeParams {
|
||||
fieldSchema.TypeParams = append(fieldSchema.TypeParams, &commonpb.KeyValuePair{Key: key, Value: fieldParam})
|
||||
fieldSchema.TypeParams = append(fieldSchema.TypeParams, &commonpb.KeyValuePair{Key: key, Value: fmt.Sprintf("%v", fieldParam)})
|
||||
}
|
||||
collSchema.Fields = append(collSchema.Fields, &fieldSchema)
|
||||
fieldNames[field.FieldName] = true
|
||||
@ -1079,8 +1109,8 @@ func (h *HandlersV2) createCollection(ctx context.Context, c *gin.Context, anyRe
|
||||
IndexName: indexParam.IndexName,
|
||||
ExtraParams: []*commonpb.KeyValuePair{{Key: common.MetricTypeKey, Value: indexParam.MetricType}},
|
||||
}
|
||||
for key, value := range indexParam.IndexConfig {
|
||||
createIndexReq.ExtraParams = append(createIndexReq.ExtraParams, &commonpb.KeyValuePair{Key: key, Value: value})
|
||||
for key, value := range indexParam.Params {
|
||||
createIndexReq.ExtraParams = append(createIndexReq.ExtraParams, &commonpb.KeyValuePair{Key: key, Value: fmt.Sprintf("%v", value)})
|
||||
}
|
||||
statusResponse, err := wrapperProxy(ctx, c, createIndexReq, h.checkAuth, false, func(reqCtx context.Context, req any) (interface{}, error) {
|
||||
return h.proxy.CreateIndex(ctx, req.(*milvuspb.CreateIndexRequest))
|
||||
@ -1507,8 +1537,8 @@ func (h *HandlersV2) createIndex(ctx context.Context, c *gin.Context, anyReq any
|
||||
{Key: common.MetricTypeKey, Value: indexParam.MetricType},
|
||||
},
|
||||
}
|
||||
for key, value := range indexParam.IndexConfig {
|
||||
req.ExtraParams = append(req.ExtraParams, &commonpb.KeyValuePair{Key: key, Value: value})
|
||||
for key, value := range indexParam.Params {
|
||||
req.ExtraParams = append(req.ExtraParams, &commonpb.KeyValuePair{Key: key, Value: fmt.Sprintf("%v", value)})
|
||||
}
|
||||
resp, err := wrapperProxy(ctx, c, req, false, false, func(reqCtx context.Context, req any) (interface{}, error) {
|
||||
return h.proxy.CreateIndex(reqCtx, req.(*milvuspb.CreateIndexRequest))
|
||||
|
||||
@ -283,6 +283,39 @@ func TestGrpcWrapper(t *testing.T) {
|
||||
fmt.Println(w.Body.String())
|
||||
})
|
||||
}
|
||||
|
||||
path = "/wrapper/grpc/auth"
|
||||
app.GET(path, func(c *gin.Context) {
|
||||
wrapperProxy(context.Background(), c, &milvuspb.DescribeCollectionRequest{}, true, false, handle)
|
||||
})
|
||||
appNeedAuth.GET(path, func(c *gin.Context) {
|
||||
ctx := proxy.NewContextWithMetadata(c, "test", DefaultDbName)
|
||||
wrapperProxy(ctx, c, &milvuspb.LoadCollectionRequest{}, true, false, handle)
|
||||
})
|
||||
t.Run("check authorization", func(t *testing.T) {
|
||||
req := httptest.NewRequest(http.MethodGet, path, nil)
|
||||
w := httptest.NewRecorder()
|
||||
ginHandler.ServeHTTP(w, req)
|
||||
assert.Equal(t, http.StatusUnauthorized, w.Code)
|
||||
returnBody := &ReturnErrMsg{}
|
||||
err := json.Unmarshal(w.Body.Bytes(), returnBody)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int32(1800), returnBody.Code)
|
||||
assert.Equal(t, "user hasn't authenticated", returnBody.Message)
|
||||
fmt.Println(w.Body.String())
|
||||
|
||||
paramtable.Get().Save(proxy.Params.CommonCfg.AuthorizationEnabled.Key, "true")
|
||||
req = httptest.NewRequest(http.MethodGet, needAuthPrefix+path, nil)
|
||||
req.SetBasicAuth("test", util.DefaultRootPassword)
|
||||
w = httptest.NewRecorder()
|
||||
ginHandler.ServeHTTP(w, req)
|
||||
assert.Equal(t, http.StatusForbidden, w.Code)
|
||||
err = json.Unmarshal(w.Body.Bytes(), returnBody)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int32(2), returnBody.Code)
|
||||
assert.Equal(t, "service unavailable: internal: Milvus Proxy is not ready yet. please wait", returnBody.Message)
|
||||
fmt.Println(w.Body.String())
|
||||
})
|
||||
}
|
||||
|
||||
type headerTestCase struct {
|
||||
@ -441,8 +474,8 @@ func TestCreateCollection(t *testing.T) {
|
||||
"fields": [
|
||||
{"fieldName": "book_id", "dataType": "Int64", "isPrimary": true, "elementTypeParams": {}},
|
||||
{"fieldName": "word_count", "dataType": "Int64", "isPartitionKey": false, "elementTypeParams": {}},
|
||||
{"fieldName": "partition_field", "dataType": "VarChar", "isPartitionKey": true, "elementTypeParams": {"max_length": "256"}},
|
||||
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": "2"}}
|
||||
{"fieldName": "partition_field", "dataType": "VarChar", "isPartitionKey": true, "elementTypeParams": {"max_length": 256}},
|
||||
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": 2}}
|
||||
]
|
||||
}, "params": {"partitionsNum": "32"}}`),
|
||||
})
|
||||
@ -452,7 +485,7 @@ func TestCreateCollection(t *testing.T) {
|
||||
"fields": [
|
||||
{"fieldName": "book_id", "dataType": "Int64", "isPrimary": true, "elementTypeParams": {}},
|
||||
{"fieldName": "word_count", "dataType": "Int64", "elementTypeParams": {}},
|
||||
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": "2"}}
|
||||
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": 2}}
|
||||
]
|
||||
}, "indexParams": [{"fieldName": "book_intro", "indexName": "book_intro_vector", "metricType": "L2"}]}`),
|
||||
})
|
||||
@ -462,7 +495,7 @@ func TestCreateCollection(t *testing.T) {
|
||||
"fields": [
|
||||
{"fieldName": "book_id", "dataType": "int64", "isPrimary": true, "elementTypeParams": {}},
|
||||
{"fieldName": "word_count", "dataType": "Int64", "elementTypeParams": {}},
|
||||
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": "2"}}
|
||||
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": 2}}
|
||||
]
|
||||
}}`),
|
||||
errMsg: "invalid parameter, data type int64 is invalid(case sensitive).",
|
||||
@ -473,8 +506,8 @@ func TestCreateCollection(t *testing.T) {
|
||||
requestBody: []byte(`{"collectionName": "` + DefaultCollectionName + `", "schema": {
|
||||
"fields": [
|
||||
{"fieldName": "book_id", "dataType": "Int64", "isPrimary": true, "elementTypeParams": {}},
|
||||
{"fieldName": "word_count", "dataType": "Array", "elementDataType": "Int64", "elementTypeParams": {"max_capacity": "2"}},
|
||||
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": "2"}}
|
||||
{"fieldName": "word_count", "dataType": "Array", "elementDataType": "Int64", "elementTypeParams": {"max_capacity": 2}},
|
||||
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": 2}}
|
||||
]
|
||||
}}`),
|
||||
})
|
||||
@ -484,7 +517,7 @@ func TestCreateCollection(t *testing.T) {
|
||||
"fields": [
|
||||
{"fieldName": "book_id", "dataType": "Int64", "isPrimary": true, "elementTypeParams": {}},
|
||||
{"fieldName": "word_count", "dataType": "Array", "elementDataType": "int64", "elementTypeParams": {}},
|
||||
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": "2"}}
|
||||
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": 2}}
|
||||
]
|
||||
}}`),
|
||||
errMsg: "invalid parameter, element data type int64 is invalid(case sensitive).",
|
||||
@ -496,7 +529,7 @@ func TestCreateCollection(t *testing.T) {
|
||||
"fields": [
|
||||
{"fieldName": "book_id", "dataType": "Int64", "isPrimary": true, "elementTypeParams": {}},
|
||||
{"fieldName": "word_count", "dataType": "Int64", "elementTypeParams": {}},
|
||||
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": "2"}}
|
||||
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": 2}}
|
||||
]
|
||||
}, "indexParams": [{"fieldName": "book_xxx", "indexName": "book_intro_vector", "metricType": "L2"}]}`),
|
||||
errMsg: "missing required parameters, error: `book_xxx` hasn't defined in schema",
|
||||
@ -514,7 +547,7 @@ func TestCreateCollection(t *testing.T) {
|
||||
"fields": [
|
||||
{"fieldName": "book_id", "dataType": "Int64", "isPrimary": true, "elementTypeParams": {}},
|
||||
{"fieldName": "word_count", "dataType": "Int64", "elementTypeParams": {}},
|
||||
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": "2"}}
|
||||
{"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": 2}}
|
||||
]
|
||||
}, "indexParams": [{"fieldName": "book_intro", "indexName": "book_intro_vector", "metricType": "L2"}]}`),
|
||||
errMsg: "",
|
||||
@ -629,9 +662,11 @@ func TestMethodGet(t *testing.T) {
|
||||
Schema: generateCollectionSchema(schemapb.DataType_Int64),
|
||||
ShardsNum: ShardNumDefault,
|
||||
Status: &StatusSuccess,
|
||||
}, nil).Once()
|
||||
}, nil).Twice()
|
||||
mp.EXPECT().DescribeCollection(mock.Anything, mock.Anything).Return(&milvuspb.DescribeCollectionResponse{Status: commonErrorStatus}, nil).Once()
|
||||
mp.EXPECT().GetLoadState(mock.Anything, mock.Anything).Return(&DefaultLoadStateResp, nil).Twice()
|
||||
mp.EXPECT().GetLoadState(mock.Anything, mock.Anything).Return(&milvuspb.GetLoadStateResponse{Status: commonErrorStatus}, nil).Once()
|
||||
mp.EXPECT().GetLoadState(mock.Anything, mock.Anything).Return(&DefaultLoadStateResp, nil).Times(3)
|
||||
mp.EXPECT().DescribeIndex(mock.Anything, mock.Anything).Return(&milvuspb.DescribeIndexResponse{Status: commonErrorStatus}, nil).Once()
|
||||
mp.EXPECT().DescribeIndex(mock.Anything, mock.Anything).Return(&DefaultDescIndexesReqp, nil).Times(3)
|
||||
mp.EXPECT().DescribeIndex(mock.Anything, mock.Anything).Return(nil, merr.WrapErrIndexNotFoundForCollection(DefaultCollectionName)).Once()
|
||||
mp.EXPECT().DescribeIndex(mock.Anything, mock.Anything).Return(&milvuspb.DescribeIndexResponse{
|
||||
@ -653,6 +688,7 @@ func TestMethodGet(t *testing.T) {
|
||||
Status: commonSuccessStatus,
|
||||
Progress: int64(77),
|
||||
}, nil).Once()
|
||||
mp.EXPECT().GetLoadingProgress(mock.Anything, mock.Anything).Return(&milvuspb.GetLoadingProgressResponse{Status: commonErrorStatus}, nil).Once()
|
||||
mp.EXPECT().ShowPartitions(mock.Anything, mock.Anything).Return(&milvuspb.ShowPartitionsResponse{
|
||||
Status: &StatusSuccess,
|
||||
PartitionNames: []string{DefaultPartitionName},
|
||||
@ -700,6 +736,7 @@ func TestMethodGet(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}, nil).Once()
|
||||
mp.EXPECT().ListAliases(mock.Anything, mock.Anything).Return(&milvuspb.ListAliasesResponse{Status: commonErrorStatus}, nil).Once()
|
||||
mp.EXPECT().ListAliases(mock.Anything, mock.Anything).Return(&milvuspb.ListAliasesResponse{
|
||||
Status: &StatusSuccess,
|
||||
}, nil).Once()
|
||||
@ -731,6 +768,9 @@ func TestMethodGet(t *testing.T) {
|
||||
queryTestCases = append(queryTestCases, rawTestCase{
|
||||
path: versionalV2(CollectionCategory, DescribeAction),
|
||||
})
|
||||
queryTestCases = append(queryTestCases, rawTestCase{
|
||||
path: versionalV2(CollectionCategory, DescribeAction),
|
||||
})
|
||||
queryTestCases = append(queryTestCases, rawTestCase{
|
||||
path: versionalV2(CollectionCategory, DescribeAction),
|
||||
errMsg: "",
|
||||
@ -745,6 +785,9 @@ func TestMethodGet(t *testing.T) {
|
||||
queryTestCases = append(queryTestCases, rawTestCase{
|
||||
path: versionalV2(CollectionCategory, LoadStateAction),
|
||||
})
|
||||
queryTestCases = append(queryTestCases, rawTestCase{
|
||||
path: versionalV2(CollectionCategory, LoadStateAction),
|
||||
})
|
||||
queryTestCases = append(queryTestCases, rawTestCase{
|
||||
path: versionalV2(PartitionCategory, ListAction),
|
||||
})
|
||||
@ -958,8 +1001,8 @@ func TestMethodPost(t *testing.T) {
|
||||
bodyReader := bytes.NewReader([]byte(`{` +
|
||||
`"collectionName": "` + DefaultCollectionName + `", "newCollectionName": "test", "newDbName": "",` +
|
||||
`"partitionName": "` + DefaultPartitionName + `", "partitionNames": ["` + DefaultPartitionName + `"],` +
|
||||
`"schema": {"fields": [{"fieldName": "book_id", "dataType": "Int64", "elementTypeParams": {}}, {"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": "2"}}]},` +
|
||||
`"indexParams": [{"indexName": "` + DefaultIndexName + `", "fieldName": "book_intro", "metricType": "L2", "indexConfig": {"nlist": "30", "index_type": "IVF_FLAT"}}],` +
|
||||
`"schema": {"fields": [{"fieldName": "book_id", "dataType": "Int64", "elementTypeParams": {}}, {"fieldName": "book_intro", "dataType": "FloatVector", "elementTypeParams": {"dim": 2}}]},` +
|
||||
`"indexParams": [{"indexName": "` + DefaultIndexName + `", "fieldName": "book_intro", "metricType": "L2", "params": {"nlist": 30, "index_type": "IVF_FLAT"}}],` +
|
||||
`"userName": "` + util.UserRoot + `", "password": "Milvus", "newPassword": "milvus", "roleName": "` + util.RoleAdmin + `",` +
|
||||
`"roleName": "` + util.RoleAdmin + `", "objectType": "Global", "objectName": "*", "privilege": "*",` +
|
||||
`"aliasName": "` + DefaultAliasName + `",` +
|
||||
|
||||
@ -205,10 +205,10 @@ type GrantReq struct {
|
||||
}
|
||||
|
||||
type IndexParam struct {
|
||||
FieldName string `json:"fieldName" binding:"required"`
|
||||
IndexName string `json:"indexName" binding:"required"`
|
||||
MetricType string `json:"metricType" binding:"required"`
|
||||
IndexConfig map[string]string `json:"indexConfig"`
|
||||
FieldName string `json:"fieldName" binding:"required"`
|
||||
IndexName string `json:"indexName" binding:"required"`
|
||||
MetricType string `json:"metricType" binding:"required"`
|
||||
Params map[string]interface{} `json:"params"`
|
||||
}
|
||||
|
||||
type IndexParamReq struct {
|
||||
@ -235,12 +235,12 @@ func (req *IndexReq) GetIndexName() string {
|
||||
}
|
||||
|
||||
type FieldSchema struct {
|
||||
FieldName string `json:"fieldName" binding:"required"`
|
||||
DataType string `json:"dataType" binding:"required"`
|
||||
ElementDataType string `json:"elementDataType"`
|
||||
IsPrimary bool `json:"isPrimary"`
|
||||
IsPartitionKey bool `json:"isPartitionKey"`
|
||||
ElementTypeParams map[string]string `json:"elementTypeParams" binding:"required"`
|
||||
FieldName string `json:"fieldName" binding:"required"`
|
||||
DataType string `json:"dataType" binding:"required"`
|
||||
ElementDataType string `json:"elementDataType"`
|
||||
IsPrimary bool `json:"isPrimary"`
|
||||
IsPartitionKey bool `json:"isPartitionKey"`
|
||||
ElementTypeParams map[string]interface{} `json:"elementTypeParams" binding:"required"`
|
||||
}
|
||||
|
||||
type CollectionSchema struct {
|
||||
@ -270,6 +270,8 @@ type AliasReq struct {
|
||||
AliasName string `json:"aliasName" binding:"required"`
|
||||
}
|
||||
|
||||
func (req *AliasReq) GetDbName() string { return req.DbName }
|
||||
|
||||
func (req *AliasReq) GetAliasName() string {
|
||||
return req.AliasName
|
||||
}
|
||||
|
||||
@ -72,9 +72,9 @@ class TestCreateIndex(TestBase):
|
||||
"metricType": f"{metric_type}"}]
|
||||
}
|
||||
if index_type == "HNSW":
|
||||
payload["indexParams"][0]["indexConfig"] = {"index_type": "HNSW", "M": "16", "efConstruction": "200"}
|
||||
payload["indexParams"][0]["params"] = {"index_type": "HNSW", "M": "16", "efConstruction": "200"}
|
||||
if index_type == "AUTOINDEX":
|
||||
payload["indexParams"][0]["indexConfig"] = {"index_type": "AUTOINDEX"}
|
||||
payload["indexParams"][0]["params"] = {"index_type": "AUTOINDEX"}
|
||||
rsp = self.index_client.index_create(payload)
|
||||
assert rsp['code'] == 200
|
||||
time.sleep(10)
|
||||
@ -90,7 +90,7 @@ class TestCreateIndex(TestBase):
|
||||
assert expected_index[i]['fieldName'] == actual_index[i]['fieldName']
|
||||
assert expected_index[i]['indexName'] == actual_index[i]['indexName']
|
||||
assert expected_index[i]['metricType'] == actual_index[i]['metricType']
|
||||
assert expected_index[i]["indexConfig"]['index_type'] == actual_index[i]['indexType']
|
||||
assert expected_index[i]["params"]['index_type'] == actual_index[i]['indexType']
|
||||
|
||||
# drop index
|
||||
for i in range(len(actual_index)):
|
||||
@ -154,10 +154,10 @@ class TestCreateIndex(TestBase):
|
||||
payload = {
|
||||
"collectionName": name,
|
||||
"indexParams": [{"fieldName": "binary_vector", "indexName": index_name, "metricType": metric_type,
|
||||
"indexConfig": {"index_type": index_type}}]
|
||||
"params": {"index_type": index_type}}]
|
||||
}
|
||||
if index_type == "BIN_IVF_FLAT":
|
||||
payload["indexParams"][0]["indexConfig"]["nlist"] = "16384"
|
||||
payload["indexParams"][0]["params"]["nlist"] = "16384"
|
||||
rsp = self.index_client.index_create(payload)
|
||||
assert rsp['code'] == 200
|
||||
time.sleep(10)
|
||||
@ -172,7 +172,7 @@ class TestCreateIndex(TestBase):
|
||||
for i in range(len(expected_index)):
|
||||
assert expected_index[i]['fieldName'] == actual_index[i]['fieldName']
|
||||
assert expected_index[i]['indexName'] == actual_index[i]['indexName']
|
||||
assert expected_index[i]['indexConfig']['index_type'] == actual_index[i]['indexType']
|
||||
assert expected_index[i]['params']['index_type'] == actual_index[i]['indexType']
|
||||
|
||||
|
||||
@pytest.mark.L1
|
||||
@ -228,9 +228,9 @@ class TestCreateIndexNegative(TestBase):
|
||||
payload = {
|
||||
"collectionName": name,
|
||||
"indexParams": [{"fieldName": "binary_vector", "indexName": index_name, "metricType": metric_type,
|
||||
"indexConfig": {"index_type": index_type}}]
|
||||
"params": {"index_type": index_type}}]
|
||||
}
|
||||
if index_type == "BIN_IVF_FLAT":
|
||||
payload["indexParams"][0]["indexConfig"]["nlist"] = "16384"
|
||||
payload["indexParams"][0]["params"]["nlist"] = "16384"
|
||||
rsp = self.index_client.index_create(payload)
|
||||
assert rsp['code'] == 65535
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user