Add InfluxQL template rendering

pull/10616/head
Chris Goller 2017-04-19 11:03:53 -05:00
parent 8781d1fedc
commit f17cf6bb09
2 changed files with 192 additions and 0 deletions

53
influx/templates.go Normal file
View File

@ -0,0 +1,53 @@
package influx
import "strings"
// TempValue is a value use to replace a template in an InfluxQL query
type TempValue struct {
Value string `json:"value"`
Type string `json:"type"`
}
// TempVar is a named variable within an InfluxQL query to be replaced with Values
type TempVar struct {
Var string `json:"tempVar"`
Values []TempValue `json:"values"`
}
// String converts the template variable into a correct InfluxQL string based
// on its type
func (t TempVar) String() string {
if len(t.Values) == 0 {
return ""
}
switch t.Values[0].Type {
case "tagKey", "fieldKey":
return `"` + t.Values[0].Value + `"`
case "tagValue":
return `'` + t.Values[0].Value + `'`
case "csv":
return t.Values[0].Value
default:
return ""
}
}
// TempVars are template variables to replace within an InfluxQL query
type TempVars struct {
Vars []TempVar `json:"tempVars"`
}
// TemplateReplace replaces templates with values within the query string
func TemplateReplace(query string, templates TempVars) string {
replacements := []string{}
for _, v := range templates.Vars {
newVal := v.String()
if newVal != "" {
replacements = append(replacements, v.Var, newVal)
}
}
replacer := strings.NewReplacer(replacements...)
replaced := replacer.Replace(query)
return replaced
}

139
influx/templates_test.go Normal file
View File

@ -0,0 +1,139 @@
package influx
import (
"testing"
)
func TestTemplateReplace(t *testing.T) {
tests := []struct {
name string
query string
vars TempVars
want string
}{
{
name: "select with parameters",
query: "$METHOD field1, $field FROM $measurement WHERE temperature > $temperature",
vars: TempVars{
Vars: []TempVar{
{
Var: "$temperature",
Values: []TempValue{
{
Type: "csv",
Value: "10",
},
},
},
{
Var: "$field",
Values: []TempValue{
{
Type: "fieldKey",
Value: "field2",
},
},
},
{
Var: "$METHOD",
Values: []TempValue{
{
Type: "csv",
Value: "SELECT",
},
},
},
{
Var: "$measurement",
Values: []TempValue{
{
Type: "csv",
Value: `"cpu"`,
},
},
},
},
},
want: `SELECT field1, "field2" FROM "cpu" WHERE temperature > 10`,
},
{
name: "select with parameters and aggregates",
query: `SELECT mean($field) FROM "cpu" WHERE $tag = $value GROUP BY $tag`,
vars: TempVars{
Vars: []TempVar{
{
Var: "$value",
Values: []TempValue{
{
Type: "tagValue",
Value: "howdy.com",
},
},
},
{
Var: "$tag",
Values: []TempValue{
{
Type: "tagKey",
Value: "host",
},
},
},
{
Var: "$field",
Values: []TempValue{
{
Type: "fieldKey",
Value: "field",
},
},
},
},
},
want: `SELECT mean("field") FROM "cpu" WHERE "host" = 'howdy.com' GROUP BY "host"`,
},
{
name: "Non-existant parameters",
query: `SELECT $field FROM "cpu"`,
want: `SELECT $field FROM "cpu"`,
},
{
name: "var without a value",
query: `SELECT $field FROM "cpu"`,
vars: TempVars{
Vars: []TempVar{
{
Var: "$field",
},
},
},
want: `SELECT $field FROM "cpu"`,
},
{
name: "var with unknown type",
query: `SELECT $field FROM "cpu"`,
vars: TempVars{
Vars: []TempVar{
{
Var: "$field",
Values: []TempValue{
{
Type: "who knows?",
Value: "field",
},
},
},
},
},
want: `SELECT $field FROM "cpu"`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := TemplateReplace(tt.query, tt.vars)
if got != tt.want {
t.Errorf("TestParse %s =\n%s\nwant\n%s", tt.name, got, tt.want)
}
})
}
}