Skip to content

Commit

Permalink
feat(metrics-operator): introduce range operators in AnalysisDefinition
Browse files Browse the repository at this point in the history
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
  • Loading branch information
odubajDT committed Aug 29, 2023
1 parent cd4cb9f commit ac62d9e
Show file tree
Hide file tree
Showing 9 changed files with 298 additions and 2 deletions.
17 changes: 17 additions & 0 deletions docs/content/en/docs/crd-ref/metrics/v1alpha3/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,8 @@ _Appears in:_
| `greaterThan` _[OperatorValue](#operatorvalue)_ | GreaterThan represents '>' operator |
| `greaterThanOrEqual` _[OperatorValue](#operatorvalue)_ | GreaterThanOrEqual represents '>=' operator |
| `equalTo` _[OperatorValue](#operatorvalue)_ | EqualTo represents '==' operator |
| `inRange` _[RangeValue](#rangevalue)_ | InRange represents operator checking the value is inclusively in the defined range |
| `notInRange` _[RangeValue](#rangevalue)_ | NotInRange represents operator checking the value is exclusively out of the defined range |


#### OperatorValue
Expand Down Expand Up @@ -388,6 +390,21 @@ _Appears in:_
| `aggregation` _string_ | Aggregation defines the type of aggregation function to be applied on the data. Accepted values: p90, p95, p99, max, min, avg, median |


#### RangeValue



RangeValue represents a range which the value should fit

_Appears in:_
- [Operator](#operator)

| Field | Description |
| --- | --- |
| `lowBound` _Quantity_ | LowBound defines the lower bound of the range |
| `highBound` _Quantity_ | LowBound defines the higher bound of the range |


#### Target


Expand Down
12 changes: 12 additions & 0 deletions metrics-operator/api/v1alpha3/analysisdefinition_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ type OperatorValue struct {
FixedValue resource.Quantity `json:"fixedValue"`
}

// RangeValue represents a range which the value should fit
type RangeValue struct {
// LowBound defines the lower bound of the range
LowBound resource.Quantity `json:"lowBound"`
// LowBound defines the higher bound of the range
HighBound resource.Quantity `json:"highBound"`
}

// Operator specifies the supported operators for value comparisons
type Operator struct {
// LessThanOrEqual represents '<=' operator
Expand All @@ -81,6 +89,10 @@ type Operator struct {
GreaterThanOrEqual *OperatorValue `json:"greaterThanOrEqual,omitempty"`
// EqualTo represents '==' operator
EqualTo *OperatorValue `json:"equalTo,omitempty"`
// InRange represents operator checking the value is inclusively in the defined range
InRange *RangeValue `json:"inRange,omitempty"`
// NotInRange represents operator checking the value is exclusively out of the defined range
NotInRange *RangeValue `json:"notInRange,omitempty"`
}

//+kubebuilder:object:root=true
Expand Down
19 changes: 19 additions & 0 deletions metrics-operator/api/v1alpha3/analysisdefinition_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,30 @@ func (o *Operator) validate() error {
if o.EqualTo != nil {
counter++
}
if o.InRange != nil {
counter++
}
if o.NotInRange != nil {
counter++
}
if counter > 1 {
return fmt.Errorf("Operator: multiple operators can not be set")
}
if counter == 0 {
return fmt.Errorf("Operator: no operator set")
}
if o.InRange != nil {
return o.InRange.validate()
}
if o.NotInRange != nil {
return o.NotInRange.validate()
}
return nil
}

func (r *RangeValue) validate() error {
if r.LowBound.AsApproximateFloat64() >= r.HighBound.AsApproximateFloat64() {
return fmt.Errorf("RangeValue: lower bound of the range needs to be smaller than higher bound")
}
return nil
}
43 changes: 43 additions & 0 deletions metrics-operator/api/v1alpha3/analysisdefinition_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ func TestOperator_validate(t *testing.T) {
LessThan: &OperatorValue{
FixedValue: *resource.NewQuantity(5, resource.DecimalSI),
},
InRange: &RangeValue{
LowBound: *resource.NewQuantity(5, resource.DecimalSI),
HighBound: *resource.NewQuantity(15, resource.DecimalSI),
},
},
wantErr: fmt.Errorf("Operator: multiple operators can not be set"),
},
Expand All @@ -49,6 +53,45 @@ func TestOperator_validate(t *testing.T) {
}
}

func TestRangeValue_validate(t *testing.T) {
tests := []struct {
name string
r RangeValue
wantErr error
}{
{
name: "happy path",
r: RangeValue{
LowBound: *resource.NewQuantity(5, resource.DecimalSI),
HighBound: *resource.NewQuantity(15, resource.DecimalSI),
},
wantErr: nil,
},
{
name: "equal bounds",
r: RangeValue{
LowBound: *resource.NewQuantity(5, resource.DecimalSI),
HighBound: *resource.NewQuantity(5, resource.DecimalSI),
},
wantErr: fmt.Errorf("RangeValue: lower bound of the range needs to be smaller than higher bound"),
},
{
name: "lower greater that higher bound",
r: RangeValue{
LowBound: *resource.NewQuantity(15, resource.DecimalSI),
HighBound: *resource.NewQuantity(5, resource.DecimalSI),
},
wantErr: fmt.Errorf("RangeValue: lower bound of the range needs to be smaller than higher bound"),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.wantErr, tt.r.validate())
})
}
}

func TestScore_validate(t *testing.T) {
tests := []struct {
name string
Expand Down
27 changes: 27 additions & 0 deletions metrics-operator/api/v1alpha3/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,30 @@ spec:
required:
- fixedValue
type: object
inRange:
description: InRange represents operator checking the
value is inclusively in the defined range
properties:
highBound:
anyOf:
- type: integer
- type: string
description: LowBound defines the higher bound of
the range
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
lowBound:
anyOf:
- type: integer
- type: string
description: LowBound defines the lower bound of
the range
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
required:
- highBound
- lowBound
type: object
lessThan:
description: LessThan represents '<' operator
properties:
Expand All @@ -132,6 +156,30 @@ spec:
required:
- fixedValue
type: object
notInRange:
description: NotInRange represents operator checking
the value is exclusively out of the defined range
properties:
highBound:
anyOf:
- type: integer
- type: string
description: LowBound defines the higher bound of
the range
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
lowBound:
anyOf:
- type: integer
- type: string
description: LowBound defines the lower bound of
the range
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
required:
- highBound
- lowBound
type: object
type: object
warning:
description: Warning defines limits where the result does
Expand Down Expand Up @@ -176,6 +224,30 @@ spec:
required:
- fixedValue
type: object
inRange:
description: InRange represents operator checking the
value is inclusively in the defined range
properties:
highBound:
anyOf:
- type: integer
- type: string
description: LowBound defines the higher bound of
the range
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
lowBound:
anyOf:
- type: integer
- type: string
description: LowBound defines the lower bound of
the range
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
required:
- highBound
- lowBound
type: object
lessThan:
description: LessThan represents '<' operator
properties:
Expand All @@ -202,6 +274,30 @@ spec:
required:
- fixedValue
type: object
notInRange:
description: NotInRange represents operator checking
the value is exclusively out of the defined range
properties:
highBound:
anyOf:
- type: integer
- type: string
description: LowBound defines the higher bound of
the range
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
lowBound:
anyOf:
- type: integer
- type: string
description: LowBound defines the lower bound of
the range
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
required:
- highBound
- lowBound
type: object
type: object
type: object
weight:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ spec:
lessThan:
fixedValue: 600
warning:
greaterThanOrEqual:
fixedValue: 800
inRange:
lowBound: 300
highBound: 500
weight: 1
keyObjective: false
totalScore:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ func (te *OperatorEvaluator) Evaluate(val float64, t *v1alpha3.Operator) types.O
result.Fulfilled = (val >= t.GreaterThanOrEqual.GetFloatValue())
} else if t.GreaterThan != nil {
result.Fulfilled = (val > t.GreaterThan.GetFloatValue())
} else if t.InRange != nil {
result.Fulfilled = (val >= t.InRange.LowBound.AsApproximateFloat64() && val <= t.InRange.HighBound.AsApproximateFloat64())
} else if t.NotInRange != nil {
result.Fulfilled = (val < t.NotInRange.LowBound.AsApproximateFloat64() || val > t.NotInRange.HighBound.AsApproximateFloat64())
}

return result
Expand Down
Loading

0 comments on commit ac62d9e

Please sign in to comment.