feat(region): add no_tags options to filter guests

no_tags filter the guests without `no_tags`
This commit is contained in:
rainzm
2021-08-30 16:39:16 +08:00
parent 3774e118f4
commit a48c43220c
3 changed files with 73 additions and 18 deletions
+5 -2
View File
@@ -195,10 +195,13 @@ type STag struct {
}
type MetadataResourceListInput struct {
// 通过标签过滤
// 通过标签过滤(包含这些标签)
Tags []STag `json:"tags"`
// 通过标签过滤
// 通过标签过滤(不包含这些标签)
NoTags []STag `json:"no_tags"`
// 通过标签排序
OrderByTag string `json:"order_by_tag"`
// deprecated
+27 -9
View File
@@ -30,13 +30,9 @@ import (
type SMetadataResourceBaseModelManager struct{}
func (meta *SMetadataResourceBaseModelManager) ListItemFilter(
manager IModelManager,
q *sqlchemy.SQuery,
input apis.MetadataResourceListInput,
) *sqlchemy.SQuery {
func (meta *SMetadataResourceBaseModelManager) objIdQueryWithTags(modelName string, oTags ...apis.STag) *sqlchemy.SQuery {
tags := map[string][]string{}
for _, tag := range input.Tags {
for _, tag := range oTags {
if _, ok := tags[tag.Key]; !ok {
tags[tag.Key] = []string{}
}
@@ -46,7 +42,7 @@ func (meta *SMetadataResourceBaseModelManager) ListItemFilter(
}
if len(tags) > 0 {
metadataResQ := Metadata.Query().Equals("obj_type", manager.Keyword()).SubQuery()
metadataResQ := Metadata.Query().Equals("obj_type", modelName).SubQuery()
metadataView := metadataResQ.Query()
idx := 0
for key, values := range tags {
@@ -66,8 +62,30 @@ func (meta *SMetadataResourceBaseModelManager) ListItemFilter(
idx++
}
metadatas := metadataView.SubQuery()
sq := metadatas.Query(metadatas.Field("obj_id")).Distinct().SubQuery()
q = q.Filter(sqlchemy.In(q.Field("id"), sq))
return metadatas.Query(metadatas.Field("obj_id")).Distinct()
}
return nil
}
func (meta *SMetadataResourceBaseModelManager) ListItemFilter(
manager IModelManager,
q *sqlchemy.SQuery,
input apis.MetadataResourceListInput,
) *sqlchemy.SQuery {
if len(input.Tags) > 0 {
sq := meta.objIdQueryWithTags(manager.Keyword(), input.Tags...)
if sq != nil {
q = q.Filter(sqlchemy.In(q.Field("id"), sq.SubQuery()))
}
}
if len(input.NoTags) > 0 {
for _, tag := range input.NoTags {
sq := meta.objIdQueryWithTags(manager.Keyword(), tag)
if sq != nil {
q = q.Filter(sqlchemy.NotIn(q.Field("id"), sq.SubQuery()))
}
}
}
if input.WithoutUserMeta != nil || input.WithUserMeta != nil {
+41 -7
View File
@@ -221,6 +221,7 @@ type BaseListOptions struct {
ExtraListOptions
Tags []string `help:"Tags info, eg: hypervisor=aliyun, os_type=Linux, os_version" json:"-"`
NoTags []string `help:"List resources without this tags, eg: os_type=Linux, os_version" json:"-"`
UserTags []string `help:"UserTags info, eg: group=rd" json:"-"`
CloudTags []string `help:"CloudTags info, eg: price_key=cn-beijing" json:"-"`
@@ -240,21 +241,47 @@ type BaseListOptions struct {
}
func (opts *BaseListOptions) addTag(prefix, tag string, idx int, params *jsonutils.JSONDict) error {
tagInfo := strings.Split(tag, "=")
if len(tagInfo) > 2 {
return fmt.Errorf("Too many equal characters %s", tag)
key, value, err := opts.spliteTag(tag)
if err != nil {
return err
}
key := tagInfo[0]
if len(key) == 0 {
return fmt.Errorf("Key must not be empty")
}
params.Add(jsonutils.NewString(prefix+key), fmt.Sprintf("tags.%d.key", idx))
if len(tagInfo) == 2 {
params.Add(jsonutils.NewString(tagInfo[1]), fmt.Sprintf("tags.%d.value", idx))
if len(value) > 0 {
params.Add(jsonutils.NewString(value), fmt.Sprintf("tags.%d.value", idx))
}
return nil
}
func (opts *BaseListOptions) addNoTag(prefix, tag string, idx int, params *jsonutils.JSONDict) error {
key, value, err := opts.spliteTag(tag)
if err != nil {
return err
}
if len(key) == 0 {
return fmt.Errorf("Key must not be empty")
}
params.Add(jsonutils.NewString(prefix+key), fmt.Sprintf("no_tags.%d.key", idx))
if len(value) > 0 {
params.Add(jsonutils.NewString(value), fmt.Sprintf("no_tags.%d.value", idx))
}
return nil
}
func (opts *BaseListOptions) spliteTag(tag string) (key string, value string, err error) {
tagInfo := strings.Split(tag, "=")
if len(tagInfo) > 2 {
return "", "", fmt.Errorf("Too many equal characters %s", tag)
}
key = tagInfo[0]
if len(tagInfo) > 1 {
value = tagInfo[1]
}
return key, value, nil
}
func (opts *BaseListOptions) Params() (*jsonutils.JSONDict, error) {
params, err := optionsStructToParams(opts)
if err != nil {
@@ -279,7 +306,7 @@ func (opts *BaseListOptions) Params() (*jsonutils.JSONDict, error) {
params.Set("admin", jsonutils.JSONTrue)
}
}*/
tagIdx := 0
tagIdx, noTagIdx := 0, 0
for _, tag := range opts.Tags {
err = opts.addTag("", tag, tagIdx, params)
if err != nil {
@@ -287,6 +314,13 @@ func (opts *BaseListOptions) Params() (*jsonutils.JSONDict, error) {
}
tagIdx++
}
for _, tag := range opts.NoTags {
err = opts.addNoTag("", tag, noTagIdx, params)
if err != nil {
return nil, err
}
noTagIdx++
}
for _, tag := range opts.UserTags {
err = opts.addTag(dbapi.USER_TAG_PREFIX, tag, tagIdx, params)
if err != nil {