Merge pull request #15933 from swordqiu/hotfix/qj-usage-policy-filter-revisit2

fix: usage filter by policy tags revisit2
This commit is contained in:
Zexi Li
2023-02-15 10:08:54 +08:00
committed by GitHub
7 changed files with 373 additions and 24 deletions
+2 -1
View File
@@ -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,
+1 -7
View File
@@ -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 {
+22
View File
@@ -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)
+44 -16
View File
@@ -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...)
+141
View File
@@ -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())
}
}
}
+28
View File
@@ -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++ {
+135
View File
@@ -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())
}
}
}