From f6a9b77698830a6cd720e0882f9229cd1cba2a65 Mon Sep 17 00:00:00 2001 From: Jian Qiu Date: Wed, 7 Feb 2024 11:52:03 +0800 Subject: [PATCH] fix: project tag value tree can return sum of any field (#19465) Co-authored-by: Qiu Jian --- pkg/cloudcommon/db/db_dispatcher.go | 5 ++--- pkg/cloudcommon/db/domainresource.go | 1 + pkg/cloudcommon/db/metadataresource.go | 7 ++++--- pkg/cloudcommon/db/standalone_anon.go | 17 ++++++++++++++--- pkg/cloudcommon/db/tagvaluetree.go | 4 ++-- pkg/cloudcommon/db/virtualresource.go | 1 + pkg/keystone/models/identitybase.go | 1 + pkg/keystone/models/organizations.go | 4 ++-- 8 files changed, 27 insertions(+), 13 deletions(-) diff --git a/pkg/cloudcommon/db/db_dispatcher.go b/pkg/cloudcommon/db/db_dispatcher.go index 1639a037c6..3de8831eb7 100644 --- a/pkg/cloudcommon/db/db_dispatcher.go +++ b/pkg/cloudcommon/db/db_dispatcher.go @@ -979,8 +979,7 @@ func getItemDetails(manager IModelManager, item IModel, ctx context.Context, use return nil, httperrors.NewInternalServerError("FetchCustomizeColumns returns incorrect results(expect 1 actual %d)", len(extraRows)) } -func tryGetModelProperty(manager IModelManager, ctx context.Context, property string, query jsonutils.JSONObject) (jsonutils.JSONObject, error) { - userCred := fetchUserCredential(ctx) +func tryGetModelProperty(manager IModelManager, ctx context.Context, userCred mcclient.TokenCredential, property string, query jsonutils.JSONObject) (jsonutils.JSONObject, error) { funcName := fmt.Sprintf("GetProperty%s", utils.Kebab2Camel(property, "-")) modelValue := reflect.ValueOf(manager) @@ -1023,7 +1022,7 @@ func (dispatcher *DBModelDispatcher) Get(ctx context.Context, idStr string, quer manager := dispatcher.manager.GetImmutableInstance(ctx, userCred, query) ctx = manager.PrepareQueryContext(ctx, userCred, query) - data, err := tryGetModelProperty(manager, ctx, idStr, query) + data, err := tryGetModelProperty(manager, ctx, userCred, idStr, query) if err != nil { return nil, err } else if data != nil { diff --git a/pkg/cloudcommon/db/domainresource.go b/pkg/cloudcommon/db/domainresource.go index 5259bce695..944554c87c 100644 --- a/pkg/cloudcommon/db/domainresource.go +++ b/pkg/cloudcommon/db/domainresource.go @@ -326,6 +326,7 @@ func (manager *SDomainLevelResourceBaseManager) GetPropertyDomainTagValueTree( manager.GetIDomainLevelModelManager(), "domain", "domain_id", + "", ctx, userCred, query, diff --git a/pkg/cloudcommon/db/metadataresource.go b/pkg/cloudcommon/db/metadataresource.go index 1028642c24..a783ccb14a 100644 --- a/pkg/cloudcommon/db/metadataresource.go +++ b/pkg/cloudcommon/db/metadataresource.go @@ -83,11 +83,12 @@ func objIdQueryWithTags(ctx context.Context, modelName string, tagsList []map[st if len(tags) == 0 { continue } - metadataView := metadataResQ.Query(metadataResQ.Field("obj_id")) + metadataView := metadataResQ.Query(metadataResQ.Field("obj_id").Label("obj_id")) for key, val := range tags { - q := metadataResQ.Query().Equals("key", key) + q := metadataResQ.Query(metadataResQ.Field("id")) + q = q.Equals("key", key) if len(val) > 0 { - q = q.Equals("key", key).In("value", val) + q = q.In("value", val) } sq := q.SubQuery() metadataView = metadataView.Join(sq, sqlchemy.Equals(metadataView.Field("id"), sq.Field("id"))) diff --git a/pkg/cloudcommon/db/standalone_anon.go b/pkg/cloudcommon/db/standalone_anon.go index 089a837737..5139d3353b 100644 --- a/pkg/cloudcommon/db/standalone_anon.go +++ b/pkg/cloudcommon/db/standalone_anon.go @@ -944,6 +944,7 @@ func (manager *SStandaloneAnonResourceBaseManager) GetPropertyTagValueTree( manager.GetIStandaloneModelManager(), manager.Keyword(), "id", + "", ctx, userCred, query, @@ -954,6 +955,7 @@ func GetPropertyTagValueTree( manager IModelManager, tagObjType string, tagIdField string, + sumField string, ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, @@ -964,7 +966,7 @@ func GetPropertyTagValueTree( return nil, errors.Wrap(err, "Unmarshal") } - valueMap, err := GetTagValueCountMap(manager, tagObjType, tagIdField, input.Keys, ctx, userCred, query) + valueMap, err := GetTagValueCountMap(manager, tagObjType, tagIdField, sumField, input.Keys, ctx, userCred, query) if err != nil { return nil, errors.Wrap(err, "AllStringAmp") } @@ -981,6 +983,7 @@ func GetTagValueCountMap( manager IModelManager, tagObjType string, tagIdField string, + sumField string, keys []string, ctx context.Context, userCred mcclient.TokenCredential, @@ -988,14 +991,22 @@ func GetTagValueCountMap( ) ([]map[string]string, error) { var err error objSubQ := manager.Query().SubQuery() - objQ := objSubQ.Query(objSubQ.Field(tagIdField), sqlchemy.COUNT("_sub_count_")) + var sumFieldQ sqlchemy.IQueryField + if len(sumField) > 0 { + sumFieldQ = sqlchemy.SUM("_sub_count_", objSubQ.Field(sumField)) + } else { + sumFieldQ = sqlchemy.COUNT("_sub_count_") + } + objQ := objSubQ.Query(objSubQ.Field(tagIdField), sumFieldQ) objQ, err = ListItemQueryFilters(manager, ctx, objQ, userCred, query, policy.PolicyActionList) if err != nil { return nil, errors.Wrap(err, "ListItemQueryFilters") } objQ = objQ.GroupBy(objSubQ.Field(tagIdField)) q := objQ.SubQuery().Query(sqlchemy.SUM(tagValueCountKey, objQ.Field("_sub_count_"))) - metadataSQ := Metadata.Query().Equals("obj_type", tagObjType).In("key", keys).SubQuery() + + metadataMan := GetMetadaManagerInContext(ctx) + metadataSQ := metadataMan.Query().Equals("obj_type", tagObjType).In("key", keys).SubQuery() groupBy := make([]interface{}, 0) for i, key := range keys { valueFieldName := TagValueKey(i) diff --git a/pkg/cloudcommon/db/tagvaluetree.go b/pkg/cloudcommon/db/tagvaluetree.go index e65a7db663..9f95a70277 100644 --- a/pkg/cloudcommon/db/tagvaluetree.go +++ b/pkg/cloudcommon/db/tagvaluetree.go @@ -33,7 +33,7 @@ func TagValueKey(idx int) string { type sTagValueTreeNode struct { Key string `json:"key"` Value string `json:"value"` - Count int `json:"count"` + Count float64 `json:"count"` Tags tagutils.TTagSet `json:"tags"` Children []*sTagValueTreeNode `json:"children"` @@ -100,7 +100,7 @@ func constructTree(data []map[string]string, keys []string) *sTagValueTreeNode { } func processOneRow(node *sTagValueTreeNode, row map[string]string, keys []string) { - rowCount, _ := strconv.Atoi(row[tagValueCountKey]) + rowCount, _ := strconv.ParseFloat(row[tagValueCountKey], 64) node.Count += rowCount for i := range keys { key := keys[i] diff --git a/pkg/cloudcommon/db/virtualresource.go b/pkg/cloudcommon/db/virtualresource.go index 42bff407c7..a7d9be80bb 100644 --- a/pkg/cloudcommon/db/virtualresource.go +++ b/pkg/cloudcommon/db/virtualresource.go @@ -655,6 +655,7 @@ func (manager *SVirtualResourceBaseManager) GetPropertyProjectTagValueTree( manager.GetIVirtualModelManager(), "project", "tenant_id", + "", ctx, userCred, query, diff --git a/pkg/keystone/models/identitybase.go b/pkg/keystone/models/identitybase.go index 709ee2bbc5..44adad54eb 100644 --- a/pkg/keystone/models/identitybase.go +++ b/pkg/keystone/models/identitybase.go @@ -418,6 +418,7 @@ func (manager *SIdentityBaseResourceManager) GetPropertyDomainTagValueTree( manager.GetIIdentityModelManager(), "domain", "domain_id", + "", ctx, userCred, query, diff --git a/pkg/keystone/models/organizations.go b/pkg/keystone/models/organizations.go index d2b7887768..ca80f5d748 100644 --- a/pkg/keystone/models/organizations.go +++ b/pkg/keystone/models/organizations.go @@ -529,7 +529,7 @@ func (org *SOrganization) syncIModelManagerTags(ctx context.Context, userCred mc orgKeys[i] = fmt.Sprintf("%s%s", db.ORGANIZATION_TAG_PREFIX, keys[i]) } { - tagValMaps, err := db.GetTagValueCountMap(manager, manager.Keyword(), "id", userKeys, ctx, userCred, query) + tagValMaps, err := db.GetTagValueCountMap(manager, manager.Keyword(), "id", "", userKeys, ctx, userCred, query) if err != nil { return errors.Wrap(err, "GetTagValueCountMap") } @@ -545,7 +545,7 @@ func (org *SOrganization) syncIModelManagerTags(ctx context.Context, userCred mc } } { - tagValMaps, err := db.GetTagValueCountMap(manager, manager.Keyword(), "id", orgKeys, ctx, userCred, query) + tagValMaps, err := db.GetTagValueCountMap(manager, manager.Keyword(), "id", "", orgKeys, ctx, userCred, query) if err != nil { return errors.Wrap(err, "GetTagValueCountMap") }