diff --git a/pkg/compute/usages/handler.go b/pkg/compute/usages/handler.go index 268b773626..d77035ec62 100644 --- a/pkg/compute/usages/handler.go +++ b/pkg/compute/usages/handler.go @@ -950,12 +950,13 @@ func guestHypervisorsUsage( count := make(map[string]interface{}) results := db.UsagePolicyCheck(userToken, models.GuestManager, scope) + log.Debugf("guestHypervisorsUsage origin %s", results.String()) results = results.Merge(policyResult) if results.Result.IsDeny() { // deny return count } - log.Debugf("guestHypervisorsUsage results %s", results.String()) + log.Debugf("guestHypervisorsUsage policyResults %s results %s", policyResult.String(), results.String()) // temporarily hide system resources // XXX needs more work later guest := models.GuestManager.TotalCount(scope, ownerId, rangeObjs, status, hypervisors, diff --git a/pkg/util/rbacutils/results.go b/pkg/util/rbacutils/results.go index 2d158fa476..f40557609b 100644 --- a/pkg/util/rbacutils/results.go +++ b/pkg/util/rbacutils/results.go @@ -75,13 +75,7 @@ func (result SPolicyResult) Json() jsonutils.JSONObject { } func mergeTagList(t1, t2 tagutils.TTagSetList) tagutils.TTagSetList { - ret := tagutils.TTagSetList{} - for i := range t1 { - for j := range t2 { - ret = append(ret, t1[i].Append(t2[j]...)) - } - } - return ret + return t1.IntersectList(t2) } func (r1 SPolicyResult) Merge(r2 SPolicyResult) SPolicyResult { diff --git a/pkg/util/tagutils/tag_test.go b/pkg/util/tagutils/tag_test.go index 20eb02e913..27d47e0ccd 100644 --- a/pkg/util/tagutils/tag_test.go +++ b/pkg/util/tagutils/tag_test.go @@ -59,6 +59,28 @@ func TestSTagCompare(t *testing.T) { }, cmp: -1, }, + { + t1: STag{ + Key: "a", + Value: AnyValue, + }, + t2: STag{ + Key: "a", + Value: NoValue, + }, + cmp: -1, + }, + { + t1: STag{ + Key: "a", + Value: NoValue, + }, + t2: STag{ + Key: "a", + Value: AnyValue, + }, + cmp: 1, + }, } for _, c := range cases { got := Compare(c.t1, c.t2) diff --git a/pkg/util/tagutils/tagset.go b/pkg/util/tagutils/tagset.go index 4f2d64a871..823e8f6a08 100644 --- a/pkg/util/tagutils/tagset.go +++ b/pkg/util/tagutils/tagset.go @@ -47,6 +47,19 @@ func (ts TTagSet) index(needle STag) (int, bool) { return j + 1, false } +/* + * TagSet Append + * 对相同的key,是并集 + * 对不同的key,是交集 + * 逻辑上有些问题,暂时这样 + * + * TODO: + * type STag struct { + * Key string + * Values []string + * } + * + */ func (ts TTagSet) Append(ele ...STag) TTagSet { for _, e := range ele { ts = ts.add(e) @@ -65,24 +78,32 @@ func (ts TTagSet) add(e STag) TTagSet { ts = append(ts, e) copy(ts[pos+1:], ts[pos:]) ts[pos] = e - if e.Value == AnyValue { - for i := pos + 1; i < len(ts); i++ { - if ts[i].Key != e.Key { - if i > pos+1 { - copy(ts[pos+1:], ts[i:]) - ts = ts[:len(ts)-i+pos+1] - } - break - } else if ts[i].Value == NoValue { - // remove this key completely - copy(ts[pos:], ts[i+1:]) - ts = ts[:len(ts)-i+pos-1] - break + start := pos + for start > 0 && ts[start-1].Key == e.Key { + start-- + } + end := pos + for end < len(ts)-1 && ts[end+1].Key == e.Key { + end++ + } + if ts[start].Value == AnyValue { + if ts[end].Value == NoValue { + // remove start ... end + if end < len(ts)-1 { + copy(ts[start:], ts[end+1:]) + ts = ts[0 : len(ts)-end+start-1] + } else { + ts = ts[0:start] + } + } else { + // remove start + 1 ... end + if end < len(ts)-1 { + copy(ts[start+1:], ts[end+1:]) + ts = ts[0 : len(ts)-end+start] + } else { + ts = ts[0 : start+1] } } - } else if e.Value == NoValue && pos > 0 && ts[pos-1].Key == e.Key && ts[pos-1].Value == AnyValue { - copy(ts[pos-1:], ts[pos:]) - ts = ts[:len(ts)-1] } return ts } @@ -107,6 +128,13 @@ func (ts TTagSet) Remove(ele ...STag) TTagSet { return ts } +func (a TTagSet) Len() int { return len(a) } +func (a TTagSet) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a TTagSet) Less(i, j int) bool { + r := Compare(a[i], a[j]) + return r < 0 +} + func (a TTagSet) Compact() TTagSet { ret := make(TTagSet, 0, len(a)) ret = ret.Append(a...) diff --git a/pkg/util/tagutils/tagset_test.go b/pkg/util/tagutils/tagset_test.go index 9bc842061a..604528cdc6 100644 --- a/pkg/util/tagutils/tagset_test.go +++ b/pkg/util/tagutils/tagset_test.go @@ -434,3 +434,144 @@ func TestTagset2MapString(t *testing.T) { } } } + +func TestTagSetAppend(t *testing.T) { + cases := []struct { + set1 TTagSet + set2 TTagSet + want TTagSet + }{ + { + set1: TTagSet{ + { + Key: "a", + Value: "1", + }, + }, + set2: TTagSet{ + { + Key: "b", + Value: "2", + }, + }, + want: TTagSet{ + { + Key: "a", + Value: "1", + }, + { + Key: "b", + Value: "2", + }, + }, + }, + { + set1: TTagSet{ + { + Key: "a", + Value: AnyValue, + }, + }, + set2: TTagSet{ + { + Key: "a", + Value: "1", + }, + { + Key: "b", + Value: "2", + }, + }, + want: TTagSet{ + { + Key: "a", + Value: AnyValue, + }, + { + Key: "b", + Value: "2", + }, + }, + }, + { + set1: TTagSet{ + { + Key: "a", + Value: AnyValue, + }, + }, + set2: TTagSet{ + { + Key: "a", + Value: NoValue, + }, + { + Key: "b", + Value: "2", + }, + }, + want: TTagSet{ + { + Key: "b", + Value: "2", + }, + }, + }, + { + set1: TTagSet{ + { + Key: "a", + Value: AnyValue, + }, + }, + set2: TTagSet{ + { + Key: "a", + Value: NoValue, + }, + }, + want: TTagSet{}, + }, + { + set1: TTagSet{ + { + Key: "a", + Value: AnyValue, + }, + }, + set2: TTagSet{}, + want: TTagSet{ + { + Key: "a", + Value: AnyValue, + }, + }, + }, + { + set1: TTagSet{ + { + Key: "a", + Value: AnyValue, + }, + }, + set2: TTagSet{ + { + Key: "a", + Value: AnyValue, + }, + }, + want: TTagSet{ + { + Key: "a", + Value: AnyValue, + }, + }, + }, + } + for _, c := range cases { + got := c.set1.Append(c.set2...) + if jsonutils.Marshal(got).String() != jsonutils.Marshal(c.want).String() { + t.Errorf("got: %s want: %s", jsonutils.Marshal(got).String(), jsonutils.Marshal(c.want).String()) + } + } +} diff --git a/pkg/util/tagutils/tagsetlist.go b/pkg/util/tagutils/tagsetlist.go index 56ee086d1d..9d09d0a1a7 100644 --- a/pkg/util/tagutils/tagsetlist.go +++ b/pkg/util/tagutils/tagsetlist.go @@ -89,6 +89,34 @@ func (tsl TTagSetList) Append(t TTagSet) TTagSetList { return ret } +func (tsl TTagSetList) Intersect(t TTagSet) TTagSetList { + ret := TTagSetList{} + for i := 0; i < len(tsl); i++ { + ret = ret.Append(tsl[i].Append(t...)) + } + return ret +} + +func (tsl TTagSetList) IntersectList(t TTagSetList) TTagSetList { + if len(tsl) == 0 && len(t) == 0 { + return TTagSetList{} + } + if len(tsl) == 0 && len(t) > 0 { + return t + } + if len(tsl) > 0 && len(t) == 0 { + return tsl + } + ret := TTagSetList{} + for i := 0; i < len(t); i++ { + tmp := tsl.Intersect(t[i]) + for j := 0; j < len(tmp); j++ { + ret = ret.Append(tmp[j]) + } + } + return ret +} + func (tsl TTagSetList) String() string { tss := make([]string, len(tsl)) for i := 0; i < len(tss); i++ { diff --git a/pkg/util/tagutils/tagsetlist_test.go b/pkg/util/tagutils/tagsetlist_test.go index 192dcc1735..8fb7df0018 100644 --- a/pkg/util/tagutils/tagsetlist_test.go +++ b/pkg/util/tagutils/tagsetlist_test.go @@ -292,3 +292,138 @@ func TestTTagSetList_Flattern(t *testing.T) { } } } + +func TestIntersect(t *testing.T) { + cases := []struct { + tsl TTagSetList + ts TTagSet + want TTagSetList + }{ + { + tsl: TTagSetList{ + TTagSet{ + { + Key: "a", + Value: "1", + }, + }, + }, + ts: TTagSet{ + { + Key: "b", + Value: "2", + }, + }, + want: TTagSetList{ + TTagSet{ + { + Key: "a", + Value: "1", + }, + { + Key: "b", + Value: "2", + }, + }, + }, + }, + } + for _, c := range cases { + got := c.tsl.Intersect(c.ts) + if jsonutils.Marshal(got).String() != jsonutils.Marshal(c.want).String() { + t.Errorf("got %s want %s", jsonutils.Marshal(got).String(), jsonutils.Marshal(c.want).String()) + } + } +} + +func TestIntersects(t *testing.T) { + cases := []struct { + tsl TTagSetList + ts2 TTagSetList + want TTagSetList + }{ + { + tsl: TTagSetList{ + TTagSet{ + { + Key: "a", + Value: "1", + }, + }, + TTagSet{ + { + Key: "b", + Value: "1", + }, + }, + }, + ts2: TTagSetList{ + TTagSet{ + { + Key: "c", + Value: "2", + }, + }, + }, + want: TTagSetList{ + TTagSet{ + { + Key: "a", + Value: "1", + }, + { + Key: "c", + Value: "2", + }, + }, + TTagSet{ + { + Key: "b", + Value: "1", + }, + { + Key: "c", + Value: "2", + }, + }, + }, + }, + { + tsl: TTagSetList{ + TTagSet{ + { + Key: "a", + Value: "1", + }, + }, + TTagSet{ + { + Key: "b", + Value: "1", + }, + }, + }, + ts2: TTagSetList{}, + want: TTagSetList{ + TTagSet{ + { + Key: "a", + Value: "1", + }, + }, + TTagSet{ + { + Key: "b", + Value: "1", + }, + }, + }, + }, + } + for _, c := range cases { + got := c.tsl.IntersectList(c.ts2) + if jsonutils.Marshal(got).String() != jsonutils.Marshal(c.want).String() { + t.Errorf("got %s want %s", jsonutils.Marshal(got).String(), jsonutils.Marshal(c.want).String()) + } + } +}