Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New operators #2543

Merged
merged 10 commits into from Oct 27, 2021
8 changes: 8 additions & 0 deletions pkg/api/kyverno/v1/policy_types.go
Expand Up @@ -234,8 +234,16 @@ const (
NotEquals ConditionOperator = "NotEquals"
// In evaluates if the key is contained in the set of values.
In ConditionOperator = "In"
anushkamittal20 marked this conversation as resolved.
Show resolved Hide resolved
// AnyIn evaluates if any of the keys are contained in the set of values.
AnyIn ConditionOperator = "AnyIn"
// AllIn evaluates if all the keys are contained in the set of values.
AllIn ConditionOperator = "AllIn"
// NotIn evaluates if the key is not contained in the set of values.
NotIn ConditionOperator = "NotIn"
// AnyNotIn evaluates if any of the keys are not contained in the set of values.
AnyNotIn ConditionOperator = "AnyNotIn"
// AllNotIn evaluates if all the keys are not contained in the set of values.
AllNotIn ConditionOperator = "AllNotIn"
// GreaterThanOrEquals evaluates if the key (numeric) is greater than or equal to the value (numeric).
GreaterThanOrEquals ConditionOperator = "GreaterThanOrEquals"
// GreaterThan evaluates if the key (numeric) is greater than the value (numeric).
Expand Down
270 changes: 270 additions & 0 deletions pkg/engine/variables/evaluate_test.go
Expand Up @@ -1654,6 +1654,154 @@ func Test_Eval_In_String_Set_Fail(t *testing.T) {
}
}

func Test_Eval_AnyIn_String_Set_Pass1(t *testing.T) {
ctx := context.NewContext()
key := [2]string{"1.1.1.1", "5.5.5.5"}
keyInterface := make([]interface{}, len(key))
for i := range key {
keyInterface[i] = key[i]
}

value := [3]string{"1.1.1.1", "2.2.2.2", "3.3.3.3"}
valueInterface := make([]interface{}, len(value))
for i := range value {
valueInterface[i] = value[i]
}

condition := kyverno.Condition{
Key: keyInterface,
Operator: kyverno.AnyIn,
Value: valueInterface,
}

if !Evaluate(log.Log, ctx, condition) {
t.Error("expected to pass")
}
}

func Test_Eval_AnyIn_String_Set_Pass2(t *testing.T) {
ctx := context.NewContext()
key := [3]string{"1.1.1.1", "5.5.5.5", "2.2.2.2"}
keyInterface := make([]interface{}, len(key))
for i := range key {
keyInterface[i] = key[i]
}

value := [2]string{"2.2.2.2", "3.3.3.3"}
valueInterface := make([]interface{}, len(value))
for i := range value {
valueInterface[i] = value[i]
}

condition := kyverno.Condition{
Key: keyInterface,
Operator: kyverno.AnyIn,
Value: valueInterface,
}

if !Evaluate(log.Log, ctx, condition) {
t.Error("expected to pass")
}
}

func Test_Eval_AnyIn_String_Set_Fail(t *testing.T) {
ctx := context.NewContext()
key := [2]string{"5.5.5.5", "4.4.4.4"}
keyInterface := make([]interface{}, len(key), len(key))
for i := range key {
keyInterface[i] = key[i]
}
value := [3]string{"1.1.1.1", "2.2.2.2", "3.3.3.3"}
valueInterface := make([]interface{}, len(value))
for i := range value {
valueInterface[i] = value[i]
}

condition := kyverno.Condition{
Key: keyInterface,
Operator: kyverno.AnyIn,
Value: valueInterface,
}

if Evaluate(log.Log, ctx, condition) {
t.Error("expected to fail")
}
}

func Test_Eval_AllIn_String_Set_Pass(t *testing.T) {
ctx := context.NewContext()
key := [2]string{"1.1.1.1", "3.3.3.3"}
keyInterface := make([]interface{}, len(key))
for i := range key {
keyInterface[i] = key[i]
}

value := [3]string{"1.1.1.1", "2.2.2.2", "3.3.3.3"}
valueInterface := make([]interface{}, len(value))
for i := range value {
valueInterface[i] = value[i]
}

condition := kyverno.Condition{
Key: keyInterface,
Operator: kyverno.AllIn,
Value: valueInterface,
}

if !Evaluate(log.Log, ctx, condition) {
t.Error("expected to pass")
}
}

func Test_Eval_AllIn_String_Set_Fail1(t *testing.T) {
ctx := context.NewContext()
key := [2]string{"5.5.5.5", "4.4.4.4"}
keyInterface := make([]interface{}, len(key), len(key))
for i := range key {
keyInterface[i] = key[i]
}
value := [3]string{"1.1.1.1", "2.2.2.2", "3.3.3.3"}
valueInterface := make([]interface{}, len(value))
for i := range value {
valueInterface[i] = value[i]
}

condition := kyverno.Condition{
Key: keyInterface,
Operator: kyverno.AllIn,
Value: valueInterface,
}

if Evaluate(log.Log, ctx, condition) {
t.Error("expected to fail")
}
}

func Test_Eval_AllIn_String_Set_Fail2(t *testing.T) {
ctx := context.NewContext()
key := [2]string{"1.1.1.1", "4.4.4.4"}
keyInterface := make([]interface{}, len(key), len(key))
anushkamittal20 marked this conversation as resolved.
Show resolved Hide resolved
for i := range key {
keyInterface[i] = key[i]
}

value := [3]string{"1.1.1.1", "2.2.2.2", "3.3.3.3"}
valueInterface := make([]interface{}, len(value))
for i := range value {
valueInterface[i] = value[i]
}

condition := kyverno.Condition{
Key: keyInterface,
Operator: kyverno.AllIn,
Value: valueInterface,
}

if Evaluate(log.Log, ctx, condition) {
t.Error("expected to fail")
}
}

// test passes if ONE of the values in "key" is NOT in "value" ("key" is not a subset of "value")
func Test_Eval_NotIn_String_Set_Pass(t *testing.T) {
ctx := context.NewContext()
Expand Down Expand Up @@ -1703,3 +1851,125 @@ func Test_Eval_NotIn_String_Set_Fail(t *testing.T) {
t.Error("expected to fail")
}
}

func Test_Eval_AnyNotIn_String_Set_Pass(t *testing.T) {
ctx := context.NewContext()
key := [3]string{"1.1.1.1", "4.4.4.4", "5.5.5.5"}
keyInterface := make([]interface{}, len(key))
for i := range key {
keyInterface[i] = key[i]
}
value := [3]string{"1.1.1.1", "2.2.2.2", "3.3.3.3"}
valueInterface := make([]interface{}, len(value))
for i := range value {
valueInterface[i] = value[i]
}

condition := kyverno.Condition{
Key: keyInterface,
Operator: kyverno.AnyNotIn,
Value: valueInterface,
}

if !Evaluate(log.Log, ctx, condition) {
t.Error("expected to pass")
}
}

// test passes if ALL of the values in "key" are in "value" ("key" is a subset of "value")
func Test_Eval_AnyNotIn_String_Set_Fail(t *testing.T) {
ctx := context.NewContext()
key := [2]string{"1.1.1.1", "2.2.2.2"}
keyInterface := make([]interface{}, len(key))
for i := range key {
keyInterface[i] = key[i]
}
value := [3]string{"1.1.1.1", "2.2.2.2", "3.3.3.3"}
valueInterface := make([]interface{}, len(value))
for i := range value {
valueInterface[i] = value[i]
}

condition := kyverno.Condition{
Key: keyInterface,
Operator: kyverno.AnyNotIn,
Value: valueInterface,
}

if Evaluate(log.Log, ctx, condition) {
t.Error("expected to fail")
}
}

func Test_Eval_AllNotIn_String_Set_Pass(t *testing.T) {
ctx := context.NewContext()
key := [2]string{"4.4.4.4", "5.5.5.5"}
keyInterface := make([]interface{}, len(key))
for i := range key {
keyInterface[i] = key[i]
}
value := [3]string{"1.1.1.1", "2.2.2.2", "3.3.3.3"}
valueInterface := make([]interface{}, len(value))
for i := range value {
valueInterface[i] = value[i]
}

condition := kyverno.Condition{
Key: keyInterface,
Operator: kyverno.AllNotIn,
Value: valueInterface,
}

if !Evaluate(log.Log, ctx, condition) {
t.Error("expected to pass")
}
}

// test passes if ALL of the values in "key" are in "value" ("key" is a subset of "value")
func Test_Eval_AllNotIn_String_Set_Fail1(t *testing.T) {
ctx := context.NewContext()
key := [2]string{"1.1.1.1", "2.2.2.2"}
keyInterface := make([]interface{}, len(key))
for i := range key {
keyInterface[i] = key[i]
}
value := [3]string{"1.1.1.1", "2.2.2.2", "3.3.3.3"}
valueInterface := make([]interface{}, len(value))
for i := range value {
valueInterface[i] = value[i]
}

condition := kyverno.Condition{
Key: keyInterface,
Operator: kyverno.AllNotIn,
Value: valueInterface,
}

if Evaluate(log.Log, ctx, condition) {
t.Error("expected to fail")
}
}

func Test_Eval_AllNotIn_String_Set_Fail2(t *testing.T) {
ctx := context.NewContext()
key := [2]string{"1.1.1.1", "5.5.5.5"}
keyInterface := make([]interface{}, len(key))
for i := range key {
keyInterface[i] = key[i]
}
value := [3]string{"1.1.1.1", "2.2.2.2", "3.3.3.3"}
valueInterface := make([]interface{}, len(value))
for i := range value {
valueInterface[i] = value[i]
}

condition := kyverno.Condition{
Key: keyInterface,
Operator: kyverno.AllNotIn,
Value: valueInterface,
}

if Evaluate(log.Log, ctx, condition) {
t.Error("expected to fail")
}
}