mirror of
https://github.com/akvorado/akvorado.git
synced 2025-12-12 06:24:10 +01:00
console: API validation for /graph/table-interval
Also add simple HTTP tests.
This commit is contained in:
@@ -13,15 +13,9 @@ import (
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
|
||||
"akvorado/common/helpers"
|
||||
"akvorado/console/query"
|
||||
)
|
||||
|
||||
const defaultPointsNumber = 200
|
||||
|
||||
// flowsTable describe a consolidated or unconsolidated flows table.
|
||||
type flowsTable struct {
|
||||
Name string
|
||||
@@ -123,11 +117,6 @@ type context struct {
|
||||
ToStartOfInterval func(string) string
|
||||
}
|
||||
|
||||
type tableIntervalResult struct {
|
||||
Table string `json:"table"`
|
||||
Interval uint64 `json:"interval"`
|
||||
}
|
||||
|
||||
// templateEscape escapes `{{` and `}}` from a string. In fact, only
|
||||
// the opening tag needs to be escaped.
|
||||
func templateEscape(input string) string {
|
||||
@@ -151,17 +140,6 @@ func templateContext(context inputContext) string {
|
||||
return fmt.Sprintf("context `%s`", string(encoded))
|
||||
}
|
||||
|
||||
func (c *Component) getTableAndIntervalHandlerFunc(gc *gin.Context) {
|
||||
input := inputContext{Points: defaultPointsNumber}
|
||||
if err := gc.ShouldBindJSON(&input); err != nil {
|
||||
gc.JSON(http.StatusBadRequest, gin.H{"message": helpers.Capitalize(err.Error())})
|
||||
return
|
||||
}
|
||||
table, interval, _ := c.computeTableAndInterval(input)
|
||||
|
||||
gc.JSON(http.StatusOK, tableIntervalResult{Table: table, Interval: uint64(interval.Seconds())})
|
||||
}
|
||||
|
||||
func (c *Component) contextFunc(inputStr string) context {
|
||||
var input inputContext
|
||||
if err := json.Unmarshal([]byte(inputStr), &input); err != nil {
|
||||
|
||||
@@ -301,12 +301,12 @@ func TestFinalizeQuery(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTableInterval(t *testing.T) {
|
||||
func TestComputeBestTableAndInterval(t *testing.T) {
|
||||
cases := []struct {
|
||||
Description string
|
||||
Tables []flowsTable
|
||||
Context inputContext
|
||||
Expected tableIntervalResult
|
||||
Expected tableIntervalOutput
|
||||
}{
|
||||
{
|
||||
Description: "simple query without additional tables",
|
||||
@@ -315,7 +315,7 @@ func TestGetTableInterval(t *testing.T) {
|
||||
End: time.Date(2022, 4, 11, 15, 45, 10, 0, time.UTC),
|
||||
Points: 86400,
|
||||
},
|
||||
Expected: tableIntervalResult{Table: "flows", Interval: 1},
|
||||
Expected: tableIntervalOutput{Table: "flows", Interval: 1},
|
||||
}, {
|
||||
Description: "query with main table",
|
||||
Context: inputContext{
|
||||
@@ -324,7 +324,7 @@ func TestGetTableInterval(t *testing.T) {
|
||||
MainTableRequired: true,
|
||||
Points: 86400,
|
||||
},
|
||||
Expected: tableIntervalResult{Table: "flows", Interval: 1},
|
||||
Expected: tableIntervalOutput{Table: "flows", Interval: 1},
|
||||
}, {
|
||||
Description: "only flows table available",
|
||||
Tables: []flowsTable{{"flows", 0, time.Date(2022, 3, 10, 15, 45, 10, 0, time.UTC)}},
|
||||
@@ -333,7 +333,7 @@ func TestGetTableInterval(t *testing.T) {
|
||||
End: time.Date(2022, 4, 11, 15, 45, 10, 0, time.UTC),
|
||||
Points: 86400,
|
||||
},
|
||||
Expected: tableIntervalResult{Table: "flows", Interval: 1},
|
||||
Expected: tableIntervalOutput{Table: "flows", Interval: 1},
|
||||
}, {
|
||||
Description: "select flows table out of range",
|
||||
Tables: []flowsTable{
|
||||
@@ -345,7 +345,7 @@ func TestGetTableInterval(t *testing.T) {
|
||||
End: time.Date(2022, 4, 11, 15, 45, 10, 0, time.UTC),
|
||||
Points: 720, // 2-minute resolution,
|
||||
},
|
||||
Expected: tableIntervalResult{Table: "flows", Interval: 1},
|
||||
Expected: tableIntervalOutput{Table: "flows", Interval: 1},
|
||||
}, {
|
||||
Description: "select consolidated table with better resolution",
|
||||
Tables: []flowsTable{
|
||||
@@ -358,7 +358,7 @@ func TestGetTableInterval(t *testing.T) {
|
||||
End: time.Date(2022, 4, 11, 15, 45, 10, 0, time.UTC),
|
||||
Points: 720, // 2-minute resolution,
|
||||
},
|
||||
Expected: tableIntervalResult{Table: "flows_1m0s", Interval: 60},
|
||||
Expected: tableIntervalOutput{Table: "flows_1m0s", Interval: 60},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -368,7 +368,7 @@ func TestGetTableInterval(t *testing.T) {
|
||||
c.flowsTables = tc.Tables
|
||||
table, interval, _ := c.computeTableAndInterval(
|
||||
tc.Context)
|
||||
got := tableIntervalResult{
|
||||
got := tableIntervalOutput{
|
||||
Table: table,
|
||||
Interval: uint64(interval.Seconds()),
|
||||
}
|
||||
|
||||
@@ -422,3 +422,29 @@ func (c *Component) graphLineHandlerFunc(gc *gin.Context) {
|
||||
}
|
||||
gc.JSON(http.StatusOK, output)
|
||||
}
|
||||
|
||||
type tableIntervalInput struct {
|
||||
Start time.Time `json:"start" binding:"required"`
|
||||
End time.Time `json:"end" binding:"required,gtfield=Start"`
|
||||
Points uint `json:"points" binding:"required,min=5,max=2000"` // minimum number of points
|
||||
}
|
||||
|
||||
type tableIntervalOutput struct {
|
||||
Table string `json:"table"`
|
||||
Interval uint64 `json:"interval"`
|
||||
}
|
||||
|
||||
func (c *Component) getTableAndIntervalHandlerFunc(gc *gin.Context) {
|
||||
var input tableIntervalInput
|
||||
if err := gc.ShouldBindJSON(&input); err != nil {
|
||||
gc.JSON(http.StatusBadRequest, gin.H{"message": helpers.Capitalize(err.Error())})
|
||||
return
|
||||
}
|
||||
table, interval, _ := c.computeTableAndInterval(inputContext{
|
||||
Points: input.Points,
|
||||
Start: input.Start,
|
||||
End: input.End,
|
||||
})
|
||||
|
||||
gc.JSON(http.StatusOK, tableIntervalOutput{Table: table, Interval: uint64(interval.Seconds())})
|
||||
}
|
||||
|
||||
@@ -979,3 +979,35 @@ func TestGraphLineHandler(t *testing.T) {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetTableInterval(t *testing.T) {
|
||||
_, h, _, mockClock := NewMock(t, DefaultConfiguration())
|
||||
mockClock.Set(time.Date(2022, 4, 12, 15, 45, 10, 0, time.UTC))
|
||||
helpers.TestHTTPEndpoints(t, h.LocalAddr(), helpers.HTTPEndpointCases{
|
||||
{
|
||||
Description: "simple query",
|
||||
URL: "/api/v0/console/graph/table-interval",
|
||||
JSONInput: gin.H{
|
||||
"start": time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
|
||||
"end": time.Date(2022, 4, 11, 15, 45, 10, 0, time.UTC),
|
||||
"points": 300,
|
||||
},
|
||||
JSONOutput: gin.H{
|
||||
"table": "flows",
|
||||
"interval": 1,
|
||||
},
|
||||
}, {
|
||||
Description: "too many points",
|
||||
URL: "/api/v0/console/graph/table-interval",
|
||||
JSONInput: gin.H{
|
||||
"start": time.Date(2022, 4, 10, 15, 45, 10, 0, time.UTC),
|
||||
"end": time.Date(2022, 4, 11, 15, 45, 10, 0, time.UTC),
|
||||
"points": 86400,
|
||||
},
|
||||
StatusCode: 400,
|
||||
JSONOutput: gin.H{
|
||||
"message": `Key: 'tableIntervalInput.Points' Error:Field validation for 'Points' failed on the 'max' tag`,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user