From 401739b0362d0f6b88648953d517d58df1869e89 Mon Sep 17 00:00:00 2001 From: Laurence Jones Date: Thu, 29 Dec 2022 14:53:06 +0000 Subject: [PATCH] Add unix expr helper (#1952) * Add unix expr helper * Add original value not parsed error * return early if cannot parse * Add tests * Fix negative value --- pkg/exprhelpers/exprlib.go | 15 +++++++-- pkg/exprhelpers/exprlib_test.go | 60 +++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/pkg/exprhelpers/exprlib.go b/pkg/exprhelpers/exprlib.go index 26d29b5c2..20797f6fa 100644 --- a/pkg/exprhelpers/exprlib.go +++ b/pkg/exprhelpers/exprlib.go @@ -68,6 +68,7 @@ func GetExprEnv(ctx map[string]interface{}) map[string]interface{} { "GetDecisionsCount": GetDecisionsCount, "GetDecisionsSinceCount": GetDecisionsSinceCount, "Sprintf": fmt.Sprintf, + "ParseUnix": ParseUnix, } for k, v := range ctx { ExprLib[k] = v @@ -283,10 +284,20 @@ func GetDecisionsSinceCount(value string, since string) int { } func LookupHost(value string) []string { - addresses , err := net.LookupHost(value) + addresses, err := net.LookupHost(value) if err != nil { log.Errorf("Failed to lookup host '%s' : %s", value, err) - return []string{} + return []string{} } return addresses } + +func ParseUnix(value string) string { + //Splitting string here as some unix timestamp may have milliseconds and break ParseInt + i, err := strconv.ParseInt(strings.Split(value, ".")[0], 10, 64) + if err != nil || i <= 0 { + log.Errorf("Unable to parse %s as unix timestamp.", value) + return "" + } + return time.Unix(i, 0).Format(time.RFC3339) +} diff --git a/pkg/exprhelpers/exprlib_test.go b/pkg/exprhelpers/exprlib_test.go index 8b5664cbe..fa953cb7c 100644 --- a/pkg/exprhelpers/exprlib_test.go +++ b/pkg/exprhelpers/exprlib_test.go @@ -971,3 +971,63 @@ func TestGetDecisionsSinceCount(t *testing.T) { log.Printf("test '%s' : OK", test.name) } } + +func TestParseUnix(t *testing.T) { + tests := []struct { + name string + env map[string]interface{} + code string + result string + err string + }{ + { + name: "ParseUnix() test: valid value with milli", + env: map[string]interface{}{ + "unix": "1672239773.3590894", + "ParseUnix": ParseUnix, + }, + code: "ParseUnix(unix)", + result: "2022-12-28T15:02:53Z", + err: "", + }, + { + name: "ParseUnix() test: valid value without milli", + env: map[string]interface{}{ + "unix": "1672239773", + "ParseUnix": ParseUnix, + }, + code: "ParseUnix(unix)", + result: "2022-12-28T15:02:53Z", + err: "", + }, + { + name: "ParseUnix() test: invalid input", + env: map[string]interface{}{ + "unix": "AbcDefG!#", + "ParseUnix": ParseUnix, + }, + code: "ParseUnix(unix)", + result: "", + err: "", + }, + { + name: "ParseUnix() test: negative value", + env: map[string]interface{}{ + "unix": "-1000", + "ParseUnix": ParseUnix, + }, + code: "ParseUnix(unix)", + result: "", + err: "", + }, + } + + for _, test := range tests { + program, err := expr.Compile(test.code, expr.Env(test.env)) + require.NoError(t, err) + output, err := expr.Run(program, test.env) + require.NoError(t, err) + require.Equal(t, test.result, output) + log.Printf("test '%s' : OK", test.name) + } +}