diff --git a/cli/internal/mapper/ad/ad.go b/cli/internal/mapper/ad/ad.go index 2167ae54..8a041325 100644 --- a/cli/internal/mapper/ad/ad.go +++ b/cli/internal/mapper/ad/ad.go @@ -42,7 +42,7 @@ func getFeatureAggregationQuery(name string, agg string, field string) ([]byte, for key := range userTypeToESType { allowedTypes = append(allowedTypes, key) } - return nil, fmt.Errorf("invlaid aggeration type: '%s', only allowed types are: %s ", agg, strings.Join(allowedTypes, ",")) + return nil, fmt.Errorf("invalid aggeration type: '%s', only allowed types are: %s ", agg, strings.Join(allowedTypes, ",")) } agg = val return []byte(fmt.Sprintf(`{ @@ -77,16 +77,24 @@ func getUnit(request string) (*string, error) { //extract last character unit := strings.ToLower(request[len(request)-1:]) if unit != minutesKey { - return nil, fmt.Errorf("invlaid unit: '%v' in %v, only %s (%s) is supported", unit, request, minutesKey, minutes) + return nil, fmt.Errorf("invalid unit: '%v' in %v, only %s (%s) is supported", unit, request, minutesKey, minutes) } return mapper.StringToStringPtr(minutes), nil } +func getUnitKey(request string) (*string, error) { + + if request != minutes { + return nil, fmt.Errorf("invalid request: '%v', only %s is supported", request, minutes) + } + return mapper.StringToStringPtr(minutesKey), nil +} + func getDuration(request string) (*int32, error) { //extract last but one character duration, err := strconv.Atoi(request[:len(request)-1]) if err != nil { - return nil, fmt.Errorf("invlaid duration: %v, due to {%v}", request, err) + return nil, fmt.Errorf("invalid duration: %v, due to {%v}", request, err) } if duration < 0 { return nil, fmt.Errorf("duration must be positive integer") @@ -114,6 +122,15 @@ func mapToInterval(request string) (*ad.Interval, error) { }, nil } +func mapIntervalToStringPtr(request ad.Interval) (*string, error) { + duration := request.Period.Duration + unit, err := getUnitKey(request.Period.Unit) + if err != nil { + return nil, err + } + return mapper.StringToStringPtr(fmt.Sprintf("%d%s", duration, *unit)), nil +} + //MapToCreateDetector maps to CreateDetector func MapToCreateDetector(request ad.CreateDetectorRequest) (*ad.CreateDetector, error) { @@ -184,3 +201,27 @@ func MapToDetectors(searchResponse []byte, name string) ([]ad.Detector, error) { } return result, nil } + +func MapToDetectorOutput(response ad.DetectorResponse) (*ad.DetectorOutput, error) { + delay, err := mapIntervalToStringPtr(response.AnomalyDetector.Delay) + if err != nil { + return nil, err + } + interval, err := mapIntervalToStringPtr(response.AnomalyDetector.Interval) + if err != nil { + return nil, err + } + return &ad.DetectorOutput{ + ID: response.ID, + Name: response.AnomalyDetector.Name, + Description: response.AnomalyDetector.Description, + TimeField: response.AnomalyDetector.TimeField, + Index: response.AnomalyDetector.Index, + Features: response.AnomalyDetector.Features, + Filter: response.AnomalyDetector.Filter, + Interval: mapper.StringPtrToString(interval), + Delay: mapper.StringPtrToString(delay), + LastUpdatedAt: response.AnomalyDetector.LastUpdateTime, + SchemaVersion: response.AnomalyDetector.SchemaVersion, + }, nil +} diff --git a/cli/internal/mapper/ad/ad_test.go b/cli/internal/mapper/ad/ad_test.go index c7d1dd4f..7beeb4c5 100644 --- a/cli/internal/mapper/ad/ad_test.go +++ b/cli/internal/mapper/ad/ad_test.go @@ -195,3 +195,74 @@ func TestMapToDetectors(t *testing.T) { assert.ElementsMatch(t, []ad.Detector{}, actual) }) } + +func TestMapToDetectorOutput(t *testing.T) { + expected := ad.DetectorOutput{ + ID: "m4ccEnIBTXsGi3mvMt9p", + Name: "test-detector", + Description: "Test detector", + TimeField: "timestamp", + Index: []string{"order*"}, + Features: []ad.Feature{ + { + Name: "total_order", + Enabled: true, + AggregationQuery: []byte(`{"total_order":{"sum":{"field":"value"}}}`), + }, + }, + Filter: []byte(`{"bool" : {"filter" : [{"exists" : {"field" : "value","boost" : 1.0}}],"adjust_pure_negative" : true,"boost" : 1.0}}`), + Interval: "5m", + Delay: "1m", + LastUpdatedAt: 1589441737319, + SchemaVersion: 0, + } + input := ad.DetectorResponse{ + ID: "m4ccEnIBTXsGi3mvMt9p", + AnomalyDetector: ad.AnomalyDetector{ + Metadata: ad.Metadata{ + Name: "test-detector", + Description: "Test detector", + TimeField: "timestamp", + Index: []string{"order*"}, + Features: []ad.Feature{ + { + Name: "total_order", + Enabled: true, + AggregationQuery: []byte(`{"total_order":{"sum":{"field":"value"}}}`), + }, + }, + Filter: []byte(`{"bool" : {"filter" : [{"exists" : {"field" : "value","boost" : 1.0}}],"adjust_pure_negative" : true,"boost" : 1.0}}`), + Interval: ad.Interval{ + Period: ad.Period{ + Duration: 5, + Unit: "Minutes", + }, + }, + Delay: ad.Interval{ + Period: ad.Period{ + Duration: 1, + Unit: "Minutes", + }, + }, + }, + SchemaVersion: 0, + LastUpdateTime: 1589441737319, + }, + } + t.Run("maps output success", func(t *testing.T) { + actual, err := MapToDetectorOutput(input) + assert.NoError(t, err) + assert.EqualValues(t, *actual, expected) + }) + t.Run("maps output failed", func(t *testing.T) { + corruptIntervalInput := input + corruptIntervalInput.AnomalyDetector.Delay = ad.Interval{ + Period: ad.Period{ + Duration: 5, + Unit: "Hour", + }, + } + _, err := MapToDetectorOutput(corruptIntervalInput) + assert.EqualError(t, err, "invalid request: 'Hour', only Minutes is supported") + }) +}