Skip to content

Commit

Permalink
Validate values length for prometheus scaler (#2264)
Browse files Browse the repository at this point in the history
Signed-off-by: Magdalena Andruszak <[email protected]>
  • Loading branch information
sosoftmandruszak authored Nov 10, 2021
1 parent 89d8663 commit cc95674
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
- Improve error message if `IdleReplicaCount` are equal to `MinReplicaCount` to be the same as the check ([#2212](https://github.com/kedacore/keda/pull/2212))
- Improve Cloudwatch Scaler metric exporting logic ([#2243](https://github.com/kedacore/keda/pull/2243))
- Refactor aws related scalers to reuse the aws clients instead of creating a new one for every GetMetrics call([#2255](https://github.com/kedacore/keda/pull/2255))
- Validating values length in prometheus query response ([#2264](https://github.com/kedacore/keda/pull/2264))

### Breaking Changes

Expand Down
7 changes: 7 additions & 0 deletions pkg/scalers/prometheus_scaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,13 @@ func (s *prometheusScaler) ExecutePromQuery(ctx context.Context) (float64, error
return -1, fmt.Errorf("prometheus query %s returned multiple elements", s.metadata.query)
}

valueLen := len(result.Data.Result[0].Value)
if valueLen == 0 {
return 0, nil
} else if valueLen < 2 {
return -1, fmt.Errorf("prometheus query %s didn't return enough values", s.metadata.query)
}

val := result.Data.Result[0].Value[1]
if val != nil {
s := val.(string)
Expand Down
87 changes: 87 additions & 0 deletions pkg/scalers/prometheus_scaler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ package scalers
import (
"context"
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/stretchr/testify/assert"
)

type parsePrometheusMetadataTestData struct {
Expand Down Expand Up @@ -119,3 +122,87 @@ func TestPrometheusScalerAuthParams(t *testing.T) {
}
}
}

type prometheusQromQueryResultTestData struct {
name string
bodyStr string
responseStatus int
expectedValue float64
isError bool
}

var testPromQueryResult = []prometheusQromQueryResultTestData{
{
name: "no results",
bodyStr: `{}`,
responseStatus: http.StatusOK,
expectedValue: 0,
isError: false,
},
{
name: "no values",
bodyStr: `{"data":{"result":[]}}`,
responseStatus: http.StatusOK,
expectedValue: 0,
isError: false,
},
{
name: "valid value",
bodyStr: `{"data":{"result":[{"value": ["1", "2"]}]}}`,
responseStatus: http.StatusOK,
expectedValue: 2,
isError: false,
},
{
name: "not enough values",
bodyStr: `{"data":{"result":[{"value": ["1"]}]}}`,
responseStatus: http.StatusOK,
expectedValue: -1,
isError: true,
},
{
name: "multiple results",
bodyStr: `{"data":{"result":[{},{}]}}`,
responseStatus: http.StatusOK,
expectedValue: -1,
isError: true,
},
{
name: "error status response",
bodyStr: `{}`,
responseStatus: http.StatusBadRequest,
expectedValue: -1,
isError: true,
},
}

func TestPrometheusScalerExecutePromQuery(t *testing.T) {
for _, testData := range testPromQueryResult {
t.Run(testData.name, func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
writer.WriteHeader(testData.responseStatus)

if _, err := writer.Write([]byte(testData.bodyStr)); err != nil {
t.Fatal(err)
}
}))

scaler := prometheusScaler{
metadata: &prometheusMetadata{
serverAddress: server.URL,
},
httpClient: http.DefaultClient,
}

value, err := scaler.ExecutePromQuery(context.TODO())

assert.Equal(t, testData.expectedValue, value)

if testData.isError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}

0 comments on commit cc95674

Please sign in to comment.