Upgrade dependent version: github.com/open-policy-agent/opa (#5315)
Upgrade dependent version: github.com/open-policy-agent/opa v0.18.0 -> v0.45.0 Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io> Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>
This commit is contained in:
263
vendor/github.com/open-policy-agent/opa/topdown/subset.go
generated
vendored
Normal file
263
vendor/github.com/open-policy-agent/opa/topdown/subset.go
generated
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
// Copyright 2022 The OPA Authors. All rights reserved.
|
||||
// Use of this source code is governed by an Apache2
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package topdown
|
||||
|
||||
import (
|
||||
"github.com/open-policy-agent/opa/ast"
|
||||
"github.com/open-policy-agent/opa/topdown/builtins"
|
||||
)
|
||||
|
||||
func bothObjects(t1, t2 *ast.Term) (bool, ast.Object, ast.Object) {
|
||||
if (t1 == nil) || (t2 == nil) {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
obj1, ok := t1.Value.(ast.Object)
|
||||
if !ok {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
obj2, ok := t2.Value.(ast.Object)
|
||||
if !ok {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
return true, obj1, obj2
|
||||
}
|
||||
|
||||
func bothSets(t1, t2 *ast.Term) (bool, ast.Set, ast.Set) {
|
||||
if (t1 == nil) || (t2 == nil) {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
set1, ok := t1.Value.(ast.Set)
|
||||
if !ok {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
set2, ok := t2.Value.(ast.Set)
|
||||
if !ok {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
return true, set1, set2
|
||||
}
|
||||
|
||||
func bothArrays(t1, t2 *ast.Term) (bool, *ast.Array, *ast.Array) {
|
||||
if (t1 == nil) || (t2 == nil) {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
array1, ok := t1.Value.(*ast.Array)
|
||||
if !ok {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
array2, ok := t2.Value.(*ast.Array)
|
||||
if !ok {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
return true, array1, array2
|
||||
}
|
||||
|
||||
func arraySet(t1, t2 *ast.Term) (bool, *ast.Array, ast.Set) {
|
||||
if (t1 == nil) || (t2 == nil) {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
array, ok := t1.Value.(*ast.Array)
|
||||
if !ok {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
set, ok := t2.Value.(ast.Set)
|
||||
if !ok {
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
return true, array, set
|
||||
}
|
||||
|
||||
// objectSubset implements the subset operation on a pair of objects.
|
||||
//
|
||||
// This function will try to recursively apply the subset operation where it
|
||||
// can, such as if both super and sub have an object or set as the value
|
||||
// associated with a key.
|
||||
func objectSubset(super ast.Object, sub ast.Object) bool {
|
||||
var superTerm *ast.Term
|
||||
isSubset := true
|
||||
|
||||
sub.Until(func(key, subTerm *ast.Term) bool {
|
||||
// This really wants to be a for loop, hence the somewhat
|
||||
// weird internal structure. However, using Until() in this
|
||||
// was is a performance optimization, as it avoids performing
|
||||
// any key hashing on the sub-object.
|
||||
|
||||
superTerm = super.Get(key)
|
||||
|
||||
// subTerm is can't be nil because we got it from Until(), so
|
||||
// we only need to verify that super is non-nil.
|
||||
if superTerm == nil {
|
||||
isSubset = false
|
||||
return true // break, not a subset
|
||||
}
|
||||
|
||||
if subTerm.Equal(superTerm) {
|
||||
return false // continue
|
||||
}
|
||||
|
||||
// If both of the terms are objects then we want to apply
|
||||
// the subset operation recursively, otherwise we just compare
|
||||
// them normally. If only one term is an object, then we
|
||||
// do a normal comparison which will come up false.
|
||||
if ok, superObj, subObj := bothObjects(superTerm, subTerm); ok {
|
||||
if !objectSubset(superObj, subObj) {
|
||||
isSubset = false
|
||||
return true // break, not a subset
|
||||
}
|
||||
|
||||
return false // continue
|
||||
}
|
||||
|
||||
if ok, superSet, subSet := bothSets(superTerm, subTerm); ok {
|
||||
if !setSubset(superSet, subSet) {
|
||||
isSubset = false
|
||||
return true // break, not a subset
|
||||
}
|
||||
|
||||
return false // continue
|
||||
}
|
||||
|
||||
if ok, superArray, subArray := bothArrays(superTerm, subTerm); ok {
|
||||
if !arraySubset(superArray, subArray) {
|
||||
isSubset = false
|
||||
return true // break, not a subset
|
||||
}
|
||||
|
||||
return false // continue
|
||||
}
|
||||
|
||||
// We have already checked for exact equality, as well as for
|
||||
// all of the types of nested subsets we care about, so if we
|
||||
// get here it means this isn't a subset.
|
||||
isSubset = false
|
||||
return true // break, not a subset
|
||||
})
|
||||
|
||||
return isSubset
|
||||
}
|
||||
|
||||
// setSubset implements the subset operation on sets.
|
||||
//
|
||||
// Unlike in the object case, this is not recursive, we just compare values
|
||||
// using ast.Set.Contains() because we have no well defined way to "match up"
|
||||
// objects that are in different sets.
|
||||
func setSubset(super ast.Set, sub ast.Set) bool {
|
||||
isSubset := true
|
||||
sub.Until(func(t *ast.Term) bool {
|
||||
if !super.Contains(t) {
|
||||
isSubset = false
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
return isSubset
|
||||
}
|
||||
|
||||
// arraySubset implements the subset operation on arrays.
|
||||
//
|
||||
// This is defined to mean that the entire "sub" array must appear in
|
||||
// the "super" array. For the same rationale as setSubset(), we do not attempt
|
||||
// to recurse into values.
|
||||
func arraySubset(super, sub *ast.Array) bool {
|
||||
// Notice that this is essentially string search. The naive approach
|
||||
// used here is O(n^2). This should probably be rewritten later to use
|
||||
// Boyer-Moore or something.
|
||||
|
||||
if sub.Len() > super.Len() {
|
||||
return false
|
||||
}
|
||||
|
||||
if sub.Equal(super) {
|
||||
return true
|
||||
}
|
||||
|
||||
superCursor := 0
|
||||
subCursor := 0
|
||||
for {
|
||||
if subCursor == sub.Len() {
|
||||
return true
|
||||
}
|
||||
|
||||
if superCursor == super.Len() {
|
||||
return false
|
||||
}
|
||||
|
||||
subElem := sub.Elem(subCursor)
|
||||
superElem := sub.Elem(superCursor + subCursor)
|
||||
if superElem == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if superElem.Value.Compare(subElem.Value) == 0 {
|
||||
subCursor++
|
||||
} else {
|
||||
superCursor++
|
||||
subCursor = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// arraySetSubset implements the subset operation on array and set.
|
||||
//
|
||||
// This is defined to mean that the entire "sub" set must appear in
|
||||
// the "super" array with no consideration of ordering.
|
||||
// For the same rationale as setSubset(), we do not attempt
|
||||
// to recurse into values.
|
||||
func arraySetSubset(super *ast.Array, sub ast.Set) bool {
|
||||
unmatched := sub.Len()
|
||||
return super.Until(func(t *ast.Term) bool {
|
||||
if sub.Contains(t) {
|
||||
unmatched--
|
||||
}
|
||||
if unmatched == 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
func builtinObjectSubset(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
superTerm := operands[0]
|
||||
subTerm := operands[1]
|
||||
|
||||
if ok, superObj, subObj := bothObjects(superTerm, subTerm); ok {
|
||||
// Both operands are objects.
|
||||
return iter(ast.BooleanTerm(objectSubset(superObj, subObj)))
|
||||
}
|
||||
|
||||
if ok, superSet, subSet := bothSets(superTerm, subTerm); ok {
|
||||
// Both operands are sets.
|
||||
return iter(ast.BooleanTerm(setSubset(superSet, subSet)))
|
||||
}
|
||||
|
||||
if ok, superArray, subArray := bothArrays(superTerm, subTerm); ok {
|
||||
// Both operands are sets.
|
||||
return iter(ast.BooleanTerm(arraySubset(superArray, subArray)))
|
||||
}
|
||||
|
||||
if ok, superArray, subSet := arraySet(superTerm, subTerm); ok {
|
||||
// Super operand is array and sub operand is set
|
||||
return iter(ast.BooleanTerm(arraySetSubset(superArray, subSet)))
|
||||
}
|
||||
|
||||
return builtins.ErrOperand("both arguments object.subset must be of the same type or array and set")
|
||||
}
|
||||
|
||||
func init() {
|
||||
RegisterBuiltinFunc(ast.ObjectSubset.Name, builtinObjectSubset)
|
||||
}
|
||||
Reference in New Issue
Block a user