Repository: kyverno/kyverno
Pull request #6229 (2023-02-06 08:19:58)

fix: jp divide quantities
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

## Explanation

This PR fixes division of quantities in jmespath.

Fixes https://github.com/kyverno/kyverno/issues/6222


codecov[bot]: # [Codecov](https://codecov.io/gh/kyverno/kyverno/pull/6229?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) Report
> Merging [#6229](https://codecov.io/gh/kyverno/kyverno/pull/6229?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) (dcc073f) into [main](https://codecov.io/gh/kyverno/kyverno/commit/81888115d6f990345e300edc8143a7d2f7283560?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) (8188811) will **decrease** coverage by `0.01%`.
> The diff coverage is `100.00%`.

```diff
@@            Coverage Diff             @@
##             main    #6229      +/-   ##
==========================================
- Coverage   37.26%   37.26%   -0.01%     
==========================================
  Files         200      200              
  Lines       20986    20985       -1     
==========================================
- Hits         7821     7820       -1     
  Misses      12355    12355              
  Partials      810      810              
```


| [Impacted Files](https://codecov.io/gh/kyverno/kyverno/pull/6229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) | Coverage Δ | |
|---|---|---|
| [pkg/engine/jmespath/arithmetic.go](https://codecov.io/gh/kyverno/kyverno/pull/6229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno#diff-cGtnL2VuZ2luZS9qbWVzcGF0aC9hcml0aG1ldGljLmdv) | `85.56% <100.00%> (-0.08%)` | :arrow_down: |

:mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno)

eddycharly: /cherry-pick release-1.9

Patch:
diff --git a/pkg/engine/jmespath/arithmetic.go b/pkg/engine/jmespath/arithmetic.go
index 379e9ec5c..6c8e29292 100644
--- a/pkg/engine/jmespath/arithmetic.go
+++ b/pkg/engine/jmespath/arithmetic.go
@@ -5,7 +5,6 @@ import (
 	"fmt"
 	"math"
 	"reflect"
-	"strconv"
 	"time"
 
 	"gopkg.in/inf.v0"
@@ -197,13 +196,12 @@ func (op1 Scalar) Multiply(op2 interface{}) (interface{}, error) {
 func (op1 Quantity) Divide(op2 interface{}) (interface{}, error) {
 	switch v := op2.(type) {
 	case Quantity:
-		if v.ToDec().AsApproximateFloat64() == 0 {
+		divisor := v.AsApproximateFloat64()
+		if divisor == 0 {
 			return nil, fmt.Errorf(zeroDivisionError, divide)
 		}
-		var quo inf.Dec
-		scale := inf.Scale(math.Max(float64(op1.AsDec().Scale()), float64(v.AsDec().Scale())))
-		quo.QuoRound(op1.AsDec(), v.AsDec(), scale, inf.RoundDown)
-		return strconv.ParseFloat(quo.String(), 64)
+		dividend := op1.AsApproximateFloat64()
+		return dividend / divisor, nil
 	case Scalar:
 		if v.float64 == 0 {
 			return nil, fmt.Errorf(zeroDivisionError, divide)


Test patch:
diff --git a/pkg/engine/jmespath/functions_test.go b/pkg/engine/jmespath/functions_test.go
index 9769ada5c..fc6328139 100644
--- a/pkg/engine/jmespath/functions_test.go
+++ b/pkg/engine/jmespath/functions_test.go
@@ -844,6 +844,30 @@ func Test_Divide(t *testing.T) {
 		retFloat       bool
 	}{
 		// Quantity
+		{
+			name:           "Quantity / Quantity -> Scalar",
+			test:           "divide('256M', '256M')",
+			expectedResult: 1.0,
+			retFloat:       true,
+		},
+		{
+			name:           "Quantity / Quantity -> Scalar",
+			test:           "divide('512M', '256M')",
+			expectedResult: 2.0,
+			retFloat:       true,
+		},
+		{
+			name:           "Quantity / Quantity -> Scalar",
+			test:           "divide('8', '3')",
+			expectedResult: 8.0 / 3.0,
+			retFloat:       true,
+		},
+		{
+			name:           "Quantity / Quantity -> Scalar",
+			test:           "divide('128M', '256M')",
+			expectedResult: 0.5,
+			retFloat:       true,
+		},
 		{
 			name:           "Quantity / Scalar -> Quantity",
 			test:           "divide('12Ki', `3`)",
@@ -858,7 +882,7 @@ func Test_Divide(t *testing.T) {
 		{
 			name:           "Quantity / Quantity -> Scalar",
 			test:           "divide('12Ki', '200')",
-			expectedResult: 61.0,
+			expectedResult: 61.44,
 			retFloat:       true,
 		},
 		{