mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #188 in YUNIONIO/onecloud from ~QIUJIAN/onecloud:hotfix/qj-redundant-params to release/2.2.0
* commit '1a30516b0f82d34401c0f78ff69317a343c0aafa': minor fixes 修正:radix match params只包含匹配的参数
This commit is contained in:
+64
-31
@@ -3,24 +3,26 @@ package appsrv
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
)
|
||||
|
||||
type RadixNode struct {
|
||||
data interface{}
|
||||
fullPath []string
|
||||
next []*RadixNode
|
||||
parent *RadixNode
|
||||
matchNext *RadixNode
|
||||
matchTable []string
|
||||
// matchTable []string
|
||||
segment string
|
||||
}
|
||||
|
||||
func NewRadix() *RadixNode {
|
||||
return &RadixNode{data: nil,
|
||||
next: make([]*RadixNode, 0),
|
||||
matchNext: nil,
|
||||
matchTable: nil,
|
||||
parent: nil,
|
||||
segment: ""}
|
||||
fullPath: nil,
|
||||
next: make([]*RadixNode, 0),
|
||||
matchNext: nil,
|
||||
parent: nil,
|
||||
segment: ""}
|
||||
}
|
||||
|
||||
func (r *RadixNode) String() string {
|
||||
@@ -50,11 +52,21 @@ func isMatchSegment(seg string) bool {
|
||||
}
|
||||
|
||||
func (r *RadixNode) Add(segments []string, data interface{}) error {
|
||||
return r.add(segments, segments, data)
|
||||
}
|
||||
|
||||
func (r *RadixNode) add(path []string, segments []string, data interface{}) error {
|
||||
// log.Debugf("add %#v %#v", path, segments)
|
||||
|
||||
if len(segments) == 0 {
|
||||
if r.data != nil {
|
||||
return fmt.Errorf("Duplicate data for node %s", r.String())
|
||||
} else {
|
||||
r.data = data
|
||||
r.fullPath = make([]string, len(path))
|
||||
for i := 0; i < len(path); i += 1 {
|
||||
r.fullPath[i] = path[i]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -65,18 +77,18 @@ func (r *RadixNode) Add(segments []string, data interface{}) error {
|
||||
return fmt.Errorf("%s has been registered, %s conflict with %s", r.matchNext.String(), r.matchNext.segment, segments[0])
|
||||
} */
|
||||
nextNode = r.matchNext
|
||||
nextNode.matchTable = append(nextNode.matchTable, segments[0])
|
||||
// nextNode.matchTable = append(nextNode.matchTable, segments[0])
|
||||
} else {
|
||||
nextNode = NewRadix()
|
||||
nextNode.segment = "<*>"
|
||||
nextNode.parent = r
|
||||
nextNode.matchTable = []string{segments[0]}
|
||||
// nextNode.matchTable = []string{segments[0]}
|
||||
r.matchNext = nextNode
|
||||
}
|
||||
} else {
|
||||
for _, node := range r.next {
|
||||
if node.segment == segments[0] {
|
||||
nextNode = node
|
||||
for i := 0; i < len(r.next); i += 1 {
|
||||
if r.next[i].segment == segments[0] {
|
||||
nextNode = r.next[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -87,42 +99,46 @@ func (r *RadixNode) Add(segments []string, data interface{}) error {
|
||||
r.next = append(r.next, nextNode)
|
||||
}
|
||||
}
|
||||
return nextNode.Add(segments[1:], data)
|
||||
return nextNode.add(path, segments[1:], data)
|
||||
}
|
||||
|
||||
func (r *RadixNode) Match(segments []string, params map[string]string) interface{} {
|
||||
data, allPaths := r.match(segments)
|
||||
// log.Debugf("%#v", allPaths)
|
||||
for i := 0; i < len(segments); i += 1 {
|
||||
for j := 0; j < len(allPaths); j += 1 {
|
||||
if i < len(allPaths[j]) && isMatchSegment(allPaths[j][i]) {
|
||||
params[allPaths[j][i]] = segments[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (r *RadixNode) match(segments []string) (interface{}, [][]string) {
|
||||
if len(segments) == 0 {
|
||||
return r.data
|
||||
return r.data, r.getAllFullPaths()
|
||||
} else {
|
||||
var ret interface{} = nil
|
||||
var retData interface{} = nil
|
||||
var retPath [][]string = nil
|
||||
exactMatch := false
|
||||
for _, node := range r.next {
|
||||
if node.segment == segments[0] {
|
||||
ret = node.Match(segments[1:], params)
|
||||
if ret != nil {
|
||||
// log.Debugf("Match %s ret %#v", node.segment, ret)
|
||||
retData, retPath = node.match(segments[1:])
|
||||
if retData != nil {
|
||||
exactMatch = true
|
||||
} else {
|
||||
// log.Debugf("No match %s ret %#v", node.segment, ret)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if ret != nil {
|
||||
return ret
|
||||
if retData != nil {
|
||||
return retData, retPath
|
||||
} else {
|
||||
if !exactMatch && r.matchNext != nil {
|
||||
ret = r.matchNext.Match(segments[1:], params)
|
||||
if ret != nil {
|
||||
for _, segname := range r.matchNext.matchTable {
|
||||
if _, ok := params[segname]; !ok {
|
||||
params[segname] = segments[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
retData, retPath = r.matchNext.match(segments[1:])
|
||||
return retData, retPath
|
||||
} else {
|
||||
return r.data
|
||||
return r.data, r.getAllFullPaths()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,3 +155,20 @@ func (r *RadixNode) Walk(f func(path string, data interface{})) {
|
||||
r.matchNext.Walk(f)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RadixNode) getAllFullPaths() [][]string {
|
||||
if r.fullPath != nil {
|
||||
return [][]string{r.fullPath}
|
||||
}else {
|
||||
ret := make([][]string, 0)
|
||||
for _, node := range r.next {
|
||||
fp := node.getAllFullPaths()
|
||||
ret = append(ret, fp...)
|
||||
}
|
||||
if r.matchNext != nil {
|
||||
fp := r.matchNext.getAllFullPaths()
|
||||
ret = append(ret, fp...)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,10 +61,16 @@ func TestRadixNode(t *testing.T) {
|
||||
|
||||
func TestParams(t *testing.T) {
|
||||
r := NewRadix()
|
||||
r.Add([]string{"POST", "clouds", "<action>"}, "classAction")
|
||||
r.Add([]string{"POST", "clouds", "<resid>", "<action>"}, "objectAction")
|
||||
r.Add([]string{"POST", "clouds", "<cls_action>"}, "classAction")
|
||||
r.Add([]string{"POST", "clouds", "<resid>", "sync"}, "objectSyncAction")
|
||||
r.Add([]string{"POST", "clouds", "<resid>", "<obj_action>"}, "objectAction")
|
||||
params := make(map[string]string)
|
||||
ret := r.Match([]string{"POST", "clouds", "id", "sync"}, params)
|
||||
ret := r.Match([]string{"POST", "clouds", "myid", "sync"}, params)
|
||||
t.Logf("match: %s", ret)
|
||||
t.Logf("params: %s", params)
|
||||
|
||||
params = make(map[string]string)
|
||||
ret = r.Match([]string{"POST", "clouds", "myid", "start"}, params)
|
||||
t.Logf("match: %s", ret)
|
||||
t.Logf("params: %s", params)
|
||||
|
||||
|
||||
@@ -31,10 +31,10 @@ func fetchById(manager IModelManager, idStr string) (IModel, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func fetchByName(manager IModelManager, ownerProjId string, idStr string) (IModel, error) {
|
||||
func fetchByName(manager IModelManager, owner string, idStr string) (IModel, error) {
|
||||
q := manager.Query()
|
||||
q = manager.FilterByName(q, idStr)
|
||||
q = manager.FilterByOwner(q, ownerProjId)
|
||||
q = manager.FilterByOwner(q, owner)
|
||||
count := q.Count()
|
||||
if count == 1 {
|
||||
obj, err := NewModelObject(manager)
|
||||
@@ -101,7 +101,7 @@ func fetchItemByName(manager IModelManager, ctx context.Context, userCred mcclie
|
||||
}
|
||||
}
|
||||
q = manager.FilterByName(q, idStr)
|
||||
q = manager.FilterByOwner(q, userCred.GetProjectId())
|
||||
q = manager.FilterByOwner(q, manager.GetOwnerId(userCred))
|
||||
count := q.Count()
|
||||
if count == 1 {
|
||||
item, err := NewModelObject(manager)
|
||||
|
||||
@@ -37,7 +37,7 @@ type IModelManager interface {
|
||||
FilterById(q *sqlchemy.SQuery, idStr string) *sqlchemy.SQuery
|
||||
FilterByNotId(q *sqlchemy.SQuery, idStr string) *sqlchemy.SQuery
|
||||
FilterByName(q *sqlchemy.SQuery, name string) *sqlchemy.SQuery
|
||||
FilterByOwner(q *sqlchemy.SQuery, ownerProjId string) *sqlchemy.SQuery
|
||||
FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery
|
||||
|
||||
GetOwnerId(userCred mcclient.TokenCredential) string
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ func (manager *SModelBaseManager) FilterByName(q *sqlchemy.SQuery, name string)
|
||||
return q
|
||||
}
|
||||
|
||||
func (manager *SModelBaseManager) FilterByOwner(q *sqlchemy.SQuery, ownerProjId string) *sqlchemy.SQuery {
|
||||
func (manager *SModelBaseManager) FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery {
|
||||
return q
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
)
|
||||
|
||||
func isNameUnique(manager IModelManager, ownerProjId string, name string) bool {
|
||||
func isNameUnique(manager IModelManager, owner string, name string) bool {
|
||||
q := manager.Query()
|
||||
q = manager.FilterByName(q, name)
|
||||
if !globalVirtualResourceNamespace {
|
||||
q = manager.FilterByOwner(q, ownerProjId)
|
||||
q = manager.FilterByOwner(q, owner)
|
||||
}
|
||||
return q.Count() == 0
|
||||
}
|
||||
|
||||
@@ -349,9 +349,9 @@ func (self *SOpsLogManager) FilterByName(q *sqlchemy.SQuery, name string) *sqlch
|
||||
return q
|
||||
}
|
||||
|
||||
func (self *SOpsLogManager) FilterByOwner(q *sqlchemy.SQuery, ownerProjId string) *sqlchemy.SQuery {
|
||||
if len(ownerProjId) > 0 {
|
||||
return q.Equals("owner_project_id", ownerProjId)
|
||||
func (self *SOpsLogManager) FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery {
|
||||
if len(owner) > 0 {
|
||||
return q.Equals("owner_project_id", owner)
|
||||
} else {
|
||||
return q
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ func NewSharableVirtualResourceBaseManager(dt interface{}, tableName string, key
|
||||
return SSharableVirtualResourceBaseManager{SVirtualResourceBaseManager: NewVirtualResourceBaseManager(dt, tableName, keyword, keywordPlural)}
|
||||
}
|
||||
|
||||
func (manager *SSharableVirtualResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, ownerProjId string) *sqlchemy.SQuery {
|
||||
q = q.Filter(sqlchemy.OR(sqlchemy.Equals(q.Field("tenant_id"), ownerProjId), sqlchemy.IsTrue(q.Field("is_public"))))
|
||||
func (manager *SSharableVirtualResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery {
|
||||
q = q.Filter(sqlchemy.OR(sqlchemy.Equals(q.Field("tenant_id"), owner), sqlchemy.IsTrue(q.Field("is_public"))))
|
||||
q = q.Filter(sqlchemy.OR(sqlchemy.IsNull(q.Field("pending_deleted")), sqlchemy.IsFalse(q.Field("pending_deleted"))))
|
||||
q = q.Filter(sqlchemy.OR(sqlchemy.IsNull(q.Field("is_system")), sqlchemy.IsFalse(q.Field("is_system"))))
|
||||
return q
|
||||
|
||||
@@ -87,7 +87,7 @@ func (manager *STaskManager) FilterByName(q *sqlchemy.SQuery, name string) *sqlc
|
||||
return q
|
||||
}
|
||||
|
||||
func (manager *STaskManager) FilterByOwner(q *sqlchemy.SQuery, ownerProjId string) *sqlchemy.SQuery {
|
||||
func (manager *STaskManager) FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery {
|
||||
return q
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ func (model *SVirtualResourceBase) GetOwnerProjectId() string {
|
||||
return model.ProjectId
|
||||
}
|
||||
|
||||
func (manager *SVirtualResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, ownerProjId string) *sqlchemy.SQuery {
|
||||
q = q.Equals("tenant_id", ownerProjId)
|
||||
func (manager *SVirtualResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery {
|
||||
q = q.Equals("tenant_id", owner)
|
||||
q = q.Filter(sqlchemy.OR(sqlchemy.IsNull(q.Field("pending_deleted")), sqlchemy.IsFalse(q.Field("pending_deleted"))))
|
||||
q = q.Filter(sqlchemy.OR(sqlchemy.IsNull(q.Field("is_system")), sqlchemy.IsFalse(q.Field("is_system"))))
|
||||
return q
|
||||
|
||||
@@ -116,8 +116,8 @@ func totalKeypairCount(userId string) int {
|
||||
return q.Count()
|
||||
}
|
||||
|
||||
func (manager *SKeypairManager) FilterByOwner(q *sqlchemy.SQuery, ownerId string) *sqlchemy.SQuery {
|
||||
return q.Equals("owner_id", ownerId)
|
||||
func (manager *SKeypairManager) FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery {
|
||||
return q.Equals("owner_id", owner)
|
||||
}
|
||||
|
||||
func (self *SKeypair) GetOwnerProjectId() string {
|
||||
|
||||
Reference in New Issue
Block a user