feat(pkger): adds gauge chart support (#15775)

pull/15786/head
Deary Hudson III 2019-11-06 13:22:36 -06:00 committed by GitHub
parent 1e7b5c7164
commit 57ffddd9cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 385 additions and 3 deletions

View File

@ -171,11 +171,12 @@ const (
ChartKindSingleStat ChartKind = "single_stat"
ChartKindSingleStatPlusLine ChartKind = "single_stat_plus_line"
ChartKindXY ChartKind = "xy"
ChartKindGauge ChartKind = "gauge"
)
func (c ChartKind) ok() bool {
switch c {
case ChartKindSingleStat, ChartKindSingleStatPlusLine, ChartKindXY:
case ChartKindSingleStat, ChartKindSingleStatPlusLine, ChartKindXY, ChartKindGauge:
return true
default:
return false
@ -519,6 +520,20 @@ func (c chart) properties() influxdb.ViewProperties {
Axes: c.Axes.influxAxes(),
Geom: c.Geom,
}
case ChartKindGauge:
return influxdb.GaugeViewProperties{
Type: "gauge",
Queries: c.Queries.influxDashQueries(),
Prefix: c.Prefix,
Suffix: c.Suffix,
ViewColors: c.Colors.influxViewColors(),
DecimalPlaces: influxdb.DecimalPlaces{
IsEnforced: c.EnforceDecimals,
Digits: int32(c.DecimalPlaces),
},
Note: c.Note,
ShowNoteWhenEmpty: c.NoteOnEmpty,
}
default:
return nil
}
@ -547,6 +562,8 @@ func (c chart) validProperties() []failure {
fails = append(fails, c.Colors.hasTypes(colorTypeScale)...)
fails = append(fails, validGeometry(c.Geom)...)
fails = append(fails, c.Axes.hasAxes("x", "y")...)
case ChartKindGauge:
fails = append(fails, c.Colors.hasTypes(colorTypeMin, colorTypeThreshold, colorTypeMax)...)
}
return fails
@ -589,8 +606,11 @@ func (c chart) validBaseProps() []failure {
}
const (
colorTypeText = "text"
colorTypeScale = "scale"
colorTypeText = "text"
colorTypeScale = "scale"
colorTypeMin = "min"
colorTypeThreshold = "threshold"
colorTypeMax = "max"
)
type color struct {

View File

@ -1413,6 +1413,272 @@ spec:
})
})
t.Run("pkg with single dashboard gauge chart", func(t *testing.T) {
t.Run("gauge chart", func(t *testing.T) {
testfileRunner(t, "testdata/dashboard_gauge", func(t *testing.T, pkg *Pkg) {
sum := pkg.Summary()
require.Len(t, sum.Dashboards, 1)
actual := sum.Dashboards[0]
assert.Equal(t, "dash_1", actual.Name)
assert.Equal(t, "desc1", actual.Description)
require.Len(t, actual.Charts, 1)
actualChart := actual.Charts[0]
assert.Equal(t, ChartKindGauge, actualChart.Kind)
assert.Equal(t, 3, actualChart.Height)
assert.Equal(t, 6, actualChart.Width)
assert.Equal(t, 1, actualChart.XPosition)
assert.Equal(t, 2, actualChart.YPosition)
props, ok := actualChart.Properties.(influxdb.GaugeViewProperties)
require.True(t, ok)
assert.Equal(t, "gauge", props.GetType())
assert.Equal(t, "gauge note", props.Note)
assert.True(t, props.ShowNoteWhenEmpty)
require.Len(t, props.Queries, 1)
q := props.Queries[0]
queryText := `from(bucket: v.bucket) |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == "boltdb_writes_total") |> filter(fn: (r) => r._field == "counter")`
assert.Equal(t, queryText, q.Text)
assert.Equal(t, "advanced", q.EditMode)
require.Len(t, props.ViewColors, 3)
c := props.ViewColors[0]
assert.NotZero(t, c.ID)
assert.Equal(t, "laser", c.Name)
assert.Equal(t, "min", c.Type)
assert.Equal(t, "#8F8AF4", c.Hex)
assert.Equal(t, 0.0, c.Value)
})
t.Run("handles invalid config", func(t *testing.T) {
tests := []struct {
name string
jsonStr string
numErrs int
errFields []string
}{
{
name: "color a gauge type",
numErrs: 1,
errFields: []string{"charts[0].colors"},
jsonStr: `
{
"apiVersion": "0.1.0",
"kind": "Package",
"meta": {
"pkgName": "pkg_name",
"pkgVersion": "1",
"description": "pack description"
},
"spec": {
"resources": [
{
"kind": "Dashboard",
"name": "dash_1",
"description": "desc1",
"charts": [
{
"kind": "gauge",
"name": "gauge",
"prefix": "prefix",
"suffix": "suffix",
"note": "gauge note",
"noteOnEmpty": true,
"xPos": 1,
"yPos": 2,
"width": 6,
"height": 3,
"decimalPlaces": 1,
"xColumn": "_time",
"yColumn": "_value",
"queries": [
{
"query": "from(bucket: v.bucket) |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"boltdb_writes_total\") |> filter(fn: (r) => r._field == \"counter\")"
}
],
"colors": [
{
"name": "laser",
"type": "min",
"hex": "#8F8AF4",
"value": 0
},
{
"name": "comet",
"type": "max",
"hex": "#F4CF31",
"value": 5000
}
]
}
]
}
]
}
}
`,
},
{
name: "color mixing a hex value",
numErrs: 1,
errFields: []string{"charts[0].colors[0].hex"},
jsonStr: `
{
"apiVersion": "0.1.0",
"kind": "Package",
"meta": {
"pkgName": "pkg_name",
"pkgVersion": "1",
"description": "pack description"
},
"spec": {
"resources": [
{
"kind": "Dashboard",
"name": "dash_1",
"description": "desc1",
"charts": [
{
"kind": "gauge",
"name": "gauge",
"prefix": "prefix",
"suffix": "suffix",
"note": "gauge note",
"noteOnEmpty": true,
"xPos": 1,
"yPos": 2,
"width": 6,
"height": 3,
"decimalPlaces": 1,
"xColumn": "_time",
"yColumn": "_value",
"queries": [
{
"query": "from(bucket: v.bucket) |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"boltdb_writes_total\") |> filter(fn: (r) => r._field == \"counter\")"
}
],
"colors": [
{
"name": "laser",
"type": "min",
"value": 0
},
{
"name": "pool",
"type": "threshold",
"hex": "#F4CF31",
"value": 700
},
{
"name": "comet",
"type": "max",
"hex": "#F4CF31",
"value": 5000
}
]
}
]
}
]
}
}
`,
},
{
name: "missing a query value",
numErrs: 1,
errFields: []string{"charts[0].queries[0].query"},
jsonStr: `
{
"apiVersion": "0.1.0",
"kind": "Package",
"meta": {
"pkgName": "pkg_name",
"pkgVersion": "1",
"description": "pack description"
},
"spec": {
"resources": [
{
"kind": "Dashboard",
"name": "dash_1",
"description": "desc1",
"charts": [
{
"kind": "gauge",
"name": "gauge",
"prefix": "prefix",
"suffix": "suffix",
"note": "gauge note",
"noteOnEmpty": true,
"xPos": 1,
"yPos": 2,
"width": 6,
"height": 3,
"decimalPlaces": 1,
"xColumn": "_time",
"yColumn": "_value",
"queries": [
{
"query": null
}
],
"colors": [
{
"name": "laser",
"type": "min",
"hex": "#FFF000",
"value": 0
},
{
"name": "pool",
"type": "threshold",
"hex": "#F4CF31",
"value": 700
},
{
"name": "comet",
"type": "max",
"hex": "#F4CF31",
"value": 5000
}
]
}
]
}
]
}
}
`,
},
}
for _, tt := range tests {
fn := func(t *testing.T) {
_, err := Parse(EncodingJSON, FromString(tt.jsonStr))
require.Error(t, err)
pErr, ok := IsParseErr(err)
require.True(t, ok, err)
require.Len(t, pErr.Resources, 1)
resErr := pErr.Resources[0]
assert.Equal(t, "dashboard", resErr.Kind)
require.Len(t, resErr.ValidationFails, tt.numErrs)
for i, vFail := range resErr.ValidationFails {
assert.Equal(t, tt.errFields[i], vFail.Field)
}
}
t.Run(tt.name, fn)
}
})
})
})
t.Run("pkg with dashboard and labels associated", func(t *testing.T) {
testfileRunner(t, "testdata/dashboard_associates_label", func(t *testing.T, pkg *Pkg) {
sum := pkg.Summary()

60
pkger/testdata/dashboard_gauge.json vendored Normal file
View File

@ -0,0 +1,60 @@
{
"apiVersion": "0.1.0",
"kind": "Package",
"meta": {
"pkgName": "pkg_name",
"pkgVersion": "1",
"description": "pack description"
},
"spec": {
"resources": [
{
"kind": "Dashboard",
"name": "dash_1",
"description": "desc1",
"charts": [
{
"kind": "gauge",
"name": "gauge",
"prefix": "prefix",
"suffix": "suffix",
"note": "gauge note",
"noteOnEmpty": true,
"xPos": 1,
"yPos": 2,
"width": 6,
"height": 3,
"decimalPlaces": 1,
"xColumn": "_time",
"yColumn": "_value",
"queries": [
{
"query": "from(bucket: v.bucket) |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"boltdb_writes_total\") |> filter(fn: (r) => r._field == \"counter\")"
}
],
"colors": [
{
"name": "laser",
"type": "min",
"hex": "#8F8AF4",
"value": 0
},
{
"name": "pool",
"type": "threshold",
"hex": "#F4CF31",
"value": 700
},
{
"name": "comet",
"type": "max",
"hex": "#F4CF31",
"value": 5000
}
]
}
]
}
]
}
}

36
pkger/testdata/dashboard_gauge.yml vendored Normal file
View File

@ -0,0 +1,36 @@
apiVersion: 0.1.0
kind: Package
meta:
pkgName: pkg_name
pkgVersion: 1
description: pack description
spec:
resources:
- kind: Dashboard
name: dash_1
description: desc1
charts:
- kind: gauge
name: gauge
note: gauge note
noteOnEmpty: true
xPos: 1
yPos: 2
width: 6
height: 3
queries:
- query: >
from(bucket: v.bucket) |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == "boltdb_writes_total") |> filter(fn: (r) => r._field == "counter")
colors:
- name: laser
type: min
hex: "#8F8AF4"
value: 0
- name: laser
type: threshold
hex: "#8F8AF4"
value: 700
- name: laser
type: max
hex: "#8F8AF4"
value: 5000