Templates: keep large numeric params parseable (#32528)
Co-authored-by: Dennis Klipp <6085348+DennisKlipp@users.noreply.github.com>
This commit is contained in:
parent
124edaa32c
commit
dbae128094
2 changed files with 55 additions and 1 deletions
38
util/templates/formatvalue_test.go
Normal file
38
util/templates/formatvalue_test.go
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package templates
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// JSON numbers arrive as float64. Large integers must not be rendered in
|
||||
// exponential notation, which would no longer parse as an integer.
|
||||
func TestFormatValue(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
in any
|
||||
want string
|
||||
}{
|
||||
{float64(3), "3"},
|
||||
{float64(8899), "8899"},
|
||||
{float64(3493601102), "3493601102"}, // ten digit device serial
|
||||
{float64(1.5), "1.5"},
|
||||
{int(42), "42"},
|
||||
{"text", "text"},
|
||||
} {
|
||||
assert.Equal(t, tc.want, formatValue(tc.in))
|
||||
}
|
||||
}
|
||||
|
||||
// end-to-end: a required int param supplied as a JSON number must satisfy the
|
||||
// required check, e.g. a ten digit device serial
|
||||
func TestRequiredLargeNumber(t *testing.T) {
|
||||
tmpl := &Template{
|
||||
Params: []Param{{Name: "serial", Type: TypeInt, Required: true}},
|
||||
}
|
||||
|
||||
_, _, err := tmpl.RenderResult(RenderModeUnitTest, map[string]any{
|
||||
"serial": float64(3493601102),
|
||||
})
|
||||
assert.NoError(t, err, "large serial supplied as JSON number")
|
||||
}
|
||||
|
|
@ -274,6 +274,8 @@ func (t *Template) RenderProxyWithValues(values map[string]any, lang string) ([]
|
|||
t.Params[index].Value = p.yamlQuote(v)
|
||||
case int:
|
||||
t.Params[index].Value = strconv.Itoa(v)
|
||||
case float64, float32:
|
||||
t.Params[index].Value = formatValue(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -308,6 +310,20 @@ func (t *Template) RenderProxyWithValues(values map[string]any, lang string) ([]
|
|||
return bytes.TrimSpace(out.Bytes()), err
|
||||
}
|
||||
|
||||
// formatValue renders a parameter value for yaml. JSON numbers arrive as float64,
|
||||
// which %v would render in exponential notation for large values, e.g. a ten digit
|
||||
// serial number. Those are no longer parseable as integers.
|
||||
func formatValue(val any) string {
|
||||
switch v := val.(type) {
|
||||
case float64:
|
||||
return strconv.FormatFloat(v, 'f', -1, 64)
|
||||
case float32:
|
||||
return strconv.FormatFloat(float64(v), 'f', -1, 32)
|
||||
default:
|
||||
return fmt.Sprintf("%v", val)
|
||||
}
|
||||
}
|
||||
|
||||
// RenderResult renders the result template to instantiate the proxy
|
||||
func (t *Template) RenderResult(renderMode int, other map[string]any) ([]byte, map[string]any, error) {
|
||||
values := t.Defaults(renderMode)
|
||||
|
|
@ -383,7 +399,7 @@ func (t *Template) RenderResult(renderMode int, other map[string]any) ([]byte, m
|
|||
// prevent rendering nil interfaces as "<nil>" string
|
||||
var s string
|
||||
if val != nil {
|
||||
s = p.yamlQuote(fmt.Sprintf("%v", val))
|
||||
s = p.yamlQuote(formatValue(val))
|
||||
}
|
||||
|
||||
// validate required fields from yaml
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue