2021-04-17 02:17:00 +03:00
package jmespath
import (
2022-09-28 19:15:39 +01:00
"bytes"
"crypto/x509"
"encoding/asn1"
2021-10-14 19:46:06 +01:00
"encoding/base64"
2022-01-10 21:42:02 +00:00
"encoding/json"
2022-09-28 19:15:39 +01:00
"encoding/pem"
2021-04-17 02:17:00 +03:00
"errors"
"fmt"
2022-09-14 11:57:32 +05:30
"math/rand"
2021-12-06 19:10:34 +08:00
"path/filepath"
2021-04-17 02:17:00 +03:00
"reflect"
"regexp"
2022-05-04 06:33:24 -04:00
"sort"
2021-04-17 02:17:00 +03:00
"strconv"
"strings"
2021-11-18 01:47:17 +05:30
"time"
2021-04-17 02:17:00 +03:00
2021-12-17 02:52:52 -05:00
trunc "github.com/aquilax/truncate"
2021-12-21 21:42:35 +05:30
"github.com/blang/semver/v4"
2021-04-17 02:17:00 +03:00
gojmespath "github.com/jmespath/go-jmespath"
2022-08-25 07:23:01 +02:00
wildcard "github.com/kyverno/kyverno/pkg/utils/wildcard"
2022-09-07 21:52:30 +05:30
regen "github.com/zach-klippenstein/goregen"
2022-09-28 19:15:39 +01:00
"golang.org/x/crypto/cryptobyte"
cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
2022-01-17 13:41:08 +00:00
"sigs.k8s.io/yaml"
2021-04-17 02:17:00 +03:00
)
var (
JpObject = gojmespath . JpObject
JpString = gojmespath . JpString
JpNumber = gojmespath . JpNumber
JpArray = gojmespath . JpArray
JpArrayString = gojmespath . JpArrayString
2021-12-07 21:14:46 +05:30
JpAny = gojmespath . JpAny
2022-02-04 05:23:12 +00:00
JpBool = gojmespath . JpType ( "bool" )
2021-04-17 02:17:00 +03:00
)
type (
JpType = gojmespath . JpType
ArgSpec = gojmespath . ArgSpec
)
2022-09-28 19:15:39 +01:00
type PublicKey struct {
N string
E int
}
2021-04-17 02:17:00 +03:00
// function names
var (
compare = "compare"
equalFold = "equal_fold"
replace = "replace"
replaceAll = "replace_all"
toUpper = "to_upper"
toLower = "to_lower"
trim = "trim"
split = "split"
regexReplaceAll = "regex_replace_all"
regexReplaceAllLiteral = "regex_replace_all_literal"
regexMatch = "regex_match"
2021-11-29 17:13:07 +01:00
patternMatch = "pattern_match"
2021-05-04 18:28:30 +02:00
labelMatch = "label_match"
2021-09-23 03:10:45 +05:30
add = "add"
subtract = "subtract"
multiply = "multiply"
divide = "divide"
modulo = "modulo"
2021-10-14 19:46:06 +01:00
base64Decode = "base64_decode"
base64Encode = "base64_encode"
2021-11-18 01:47:17 +05:30
timeSince = "time_since"
2023-01-02 20:05:01 +05:30
timeNow = "time_now"
2021-12-06 19:10:34 +08:00
pathCanonicalize = "path_canonicalize"
2021-12-17 02:52:52 -05:00
truncate = "truncate"
2021-12-21 21:42:35 +05:30
semverCompare = "semver_compare"
2022-01-10 21:42:02 +00:00
parseJson = "parse_json"
2022-01-17 13:41:08 +00:00
parseYAML = "parse_yaml"
2022-05-04 06:33:24 -04:00
items = "items"
2022-05-07 13:05:04 +01:00
objectFromLists = "object_from_lists"
2022-09-07 21:52:30 +05:30
random = "random"
2022-09-28 19:15:39 +01:00
x509_decode = "x509_decode"
2023-01-06 22:18:13 +05:30
timeAdd = "time_add"
timeParse = "time_parse"
2023-01-06 12:57:57 +05:30
timeToCron = "time_to_cron"
2021-04-17 02:17:00 +03:00
)
2022-05-17 08:19:03 +02:00
const (
errorPrefix = "JMESPath function '%s': "
invalidArgumentTypeError = errorPrefix + "%d argument is expected of %s type"
genericError = errorPrefix + "%s"
zeroDivisionError = errorPrefix + "Zero divisor passed"
undefinedQuoError = errorPrefix + "Undefined quotient"
nonIntModuloError = errorPrefix + "Non-integer argument(s) passed for modulo"
)
2021-04-17 02:17:00 +03:00
2022-02-04 05:23:12 +00:00
type FunctionEntry struct {
Entry * gojmespath . FunctionEntry
Note string
ReturnType [ ] JpType
}
func ( f * FunctionEntry ) String ( ) string {
args := [ ] string { }
for _ , a := range f . Entry . Arguments {
aTypes := [ ] string { }
for _ , t := range a . Types {
aTypes = append ( aTypes , string ( t ) )
}
args = append ( args , strings . Join ( aTypes , "|" ) )
}
returnArgs := [ ] string { }
for _ , ra := range f . ReturnType {
returnArgs = append ( returnArgs , string ( ra ) )
}
output := fmt . Sprintf ( "%s(%s) %s" , f . Entry . Name , strings . Join ( args , ", " ) , strings . Join ( returnArgs , "," ) )
if f . Note != "" {
output += fmt . Sprintf ( " (%s)" , f . Note )
}
return output
}
func GetFunctions ( ) [ ] * FunctionEntry {
return [ ] * FunctionEntry {
2021-04-17 02:17:00 +03:00
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : compare ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpfCompare ,
2021-04-17 02:17:00 +03:00
} ,
2022-05-17 02:41:43 +05:30
ReturnType : [ ] JpType { JpNumber } ,
2023-01-02 13:30:25 +05:30
Note : "compares two strings lexicographically" ,
2021-04-17 02:17:00 +03:00
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : equalFold ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpfEqualFold ,
2021-04-17 02:17:00 +03:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpBool } ,
2023-01-02 13:30:25 +05:30
Note : "allows comparing two strings for equivalency where the only differences are letter cases" ,
2021-04-17 02:17:00 +03:00
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : replace ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpNumber } } ,
} ,
Handler : jpfReplace ,
2021-04-17 02:17:00 +03:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpString } ,
2023-01-02 13:30:25 +05:30
Note : "replaces a specified number of instances of the source string with the replacement string in a parent " ,
2021-04-17 02:17:00 +03:00
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : replaceAll ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpfReplaceAll ,
2021-04-17 02:17:00 +03:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpString } ,
2023-01-02 13:30:25 +05:30
Note : "replace all instances of one string with another in an overall parent string" ,
2021-04-17 02:17:00 +03:00
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : toUpper ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpfToUpper ,
2021-04-17 02:17:00 +03:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpString } ,
2023-01-02 13:30:25 +05:30
Note : "takes in a string and outputs the same string with all upper-case letters" ,
2021-04-17 02:17:00 +03:00
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : toLower ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpfToLower ,
2021-04-17 02:17:00 +03:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpString } ,
2023-01-02 13:30:25 +05:30
Note : "takes in a string and outputs the same string with all lower-case letters" ,
2021-04-17 02:17:00 +03:00
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : trim ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpfTrim ,
2021-04-17 02:17:00 +03:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpString } ,
2023-01-02 13:30:25 +05:30
Note : "trims both ends of the source string by characters appearing in the second string" ,
2021-04-17 02:17:00 +03:00
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : split ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpfSplit ,
2021-04-17 02:17:00 +03:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpArrayString } ,
2023-01-02 13:30:25 +05:30
Note : "splits the first string when the second string is found and converts it into an array " ,
2021-04-17 02:17:00 +03:00
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : regexReplaceAll ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString , JpNumber } } ,
{ Types : [ ] JpType { JpString , JpNumber } } ,
} ,
Handler : jpRegexReplaceAll ,
2021-04-17 02:17:00 +03:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpString } ,
Note : "converts all parameters to string" ,
2021-04-17 02:17:00 +03:00
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : regexReplaceAllLiteral ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString , JpNumber } } ,
{ Types : [ ] JpType { JpString , JpNumber } } ,
} ,
Handler : jpRegexReplaceAllLiteral ,
2021-04-17 02:17:00 +03:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpString } ,
Note : "converts all parameters to string" ,
2021-04-17 02:17:00 +03:00
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : regexMatch ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString , JpNumber } } ,
} ,
Handler : jpRegexMatch ,
2021-04-17 02:17:00 +03:00
} ,
2022-04-11 13:04:14 +05:30
ReturnType : [ ] JpType { JpBool } ,
2023-01-02 13:30:25 +05:30
Note : "first string is the regular exression which is compared with second input which can be a number or string" ,
2021-04-17 02:17:00 +03:00
} ,
2021-11-29 17:13:07 +01:00
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : patternMatch ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString , JpNumber } } ,
} ,
Handler : jpPatternMatch ,
2021-11-29 17:13:07 +01:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpBool } ,
Note : "'*' matches zero or more alphanumeric characters, '?' matches a single alphanumeric character" ,
2021-11-29 17:13:07 +01:00
} ,
2021-05-04 18:28:30 +02:00
{
// Validates if label (param1) would match pod/host/etc labels (param2)
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : labelMatch ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpObject } } ,
{ Types : [ ] JpType { JpObject } } ,
} ,
Handler : jpLabelMatch ,
2021-05-04 18:28:30 +02:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpBool } ,
Note : "object arguments must be enclosed in backticks; ex. `{{request.object.spec.template.metadata.labels}}`" ,
2021-05-04 18:28:30 +02:00
} ,
2021-09-23 03:10:45 +05:30
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : add ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpAny } } ,
{ Types : [ ] JpType { JpAny } } ,
} ,
Handler : jpAdd ,
2021-09-23 03:10:45 +05:30
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpAny } ,
2023-01-02 13:30:25 +05:30
Note : "does arithmetic addition of two specified values of numbers, quantities, and durations" ,
2021-09-23 03:10:45 +05:30
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : subtract ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpAny } } ,
{ Types : [ ] JpType { JpAny } } ,
} ,
Handler : jpSubtract ,
2021-09-23 03:10:45 +05:30
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpAny } ,
2023-01-02 13:30:25 +05:30
Note : "does arithmetic subtraction of two specified values of numbers, quantities, and durations" ,
2021-09-23 03:10:45 +05:30
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : multiply ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpAny } } ,
{ Types : [ ] JpType { JpAny } } ,
} ,
Handler : jpMultiply ,
2021-09-23 03:10:45 +05:30
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpAny } ,
2023-01-02 13:30:25 +05:30
Note : "does arithmetic multiplication of two specified values of numbers, quantities, and durations" ,
2021-09-23 03:10:45 +05:30
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : divide ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpAny } } ,
{ Types : [ ] JpType { JpAny } } ,
} ,
Handler : jpDivide ,
2021-09-23 03:10:45 +05:30
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpAny } ,
Note : "divisor must be non zero" ,
2021-09-23 03:10:45 +05:30
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : modulo ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpAny } } ,
{ Types : [ ] JpType { JpAny } } ,
} ,
Handler : jpModulo ,
2021-09-23 03:10:45 +05:30
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpAny } ,
Note : "divisor must be non-zero, arguments must be integers" ,
2021-09-23 03:10:45 +05:30
} ,
2021-10-14 19:46:06 +01:00
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : base64Decode ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpBase64Decode ,
2021-10-14 19:46:06 +01:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpString } ,
2023-01-02 13:30:25 +05:30
Note : "decodes a base 64 string" ,
2021-10-14 19:46:06 +01:00
} ,
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : base64Encode ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpBase64Encode ,
2021-10-14 19:46:06 +01:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpString } ,
2023-01-02 13:30:25 +05:30
Note : "encodes a regular, plaintext and unencoded string to base64" ,
2021-10-14 19:46:06 +01:00
} ,
2021-11-18 01:47:17 +05:30
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : timeSince ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpTimeSince ,
2021-11-18 01:47:17 +05:30
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpString } ,
2023-01-02 13:30:25 +05:30
Note : "calculate the difference between a start and end period of time where the end may either be a static definition or the then-current time" ,
2021-11-18 01:47:17 +05:30
} ,
2023-01-02 20:05:01 +05:30
{
Entry : & gojmespath . FunctionEntry {
Name : timeNow ,
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpTimeNow ,
} ,
ReturnType : [ ] JpType { JpString } ,
Note : "returns current time in RFC 3339 format" ,
} ,
2021-12-06 19:10:34 +08:00
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : pathCanonicalize ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpPathCanonicalize ,
2021-12-06 19:10:34 +08:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpString } ,
2023-01-02 13:30:25 +05:30
Note : "normalizes or canonicalizes a given path by removing excess slashes" ,
2021-12-06 19:10:34 +08:00
} ,
2021-12-17 02:52:52 -05:00
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : truncate ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpNumber } } ,
} ,
Handler : jpTruncate ,
2021-12-17 02:52:52 -05:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpString } ,
Note : "length argument must be enclosed in backticks; ex. \"{{request.object.metadata.name | truncate(@, `9`)}}\"" ,
2021-12-17 02:52:52 -05:00
} ,
2021-12-21 21:42:35 +05:30
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : semverCompare ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpSemverCompare ,
2021-12-21 21:42:35 +05:30
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpBool } ,
2023-01-02 13:30:25 +05:30
Note : "compares two strings which comply with the semantic versioning schema and outputs a boolean response as to the position of the second relative to the first" ,
2021-12-21 21:42:35 +05:30
} ,
2022-01-10 21:42:02 +00:00
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : parseJson ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpParseJson ,
2022-01-10 21:42:02 +00:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpAny } ,
Note : "decodes a valid JSON encoded string to the appropriate type. Opposite of `to_string` function" ,
2022-01-10 21:42:02 +00:00
} ,
2022-01-17 13:41:08 +00:00
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : parseYAML ,
2022-02-04 05:23:12 +00:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpParseYAML ,
2022-01-17 13:41:08 +00:00
} ,
2022-02-04 05:23:12 +00:00
ReturnType : [ ] JpType { JpAny } ,
Note : "decodes a valid YAML encoded string to the appropriate type provided it can be represented as JSON" ,
2022-01-17 13:41:08 +00:00
} ,
2022-05-04 06:33:24 -04:00
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : items ,
2022-05-04 06:33:24 -04:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpObject } } ,
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpItems ,
} ,
ReturnType : [ ] JpType { JpArray } ,
Note : "converts a map to an array of objects where each key:value is an item in the array" ,
} ,
2022-05-07 13:05:04 +01:00
{
2022-05-17 08:19:03 +02:00
Entry : & gojmespath . FunctionEntry {
Name : objectFromLists ,
2022-05-07 13:05:04 +01:00
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpArray } } ,
{ Types : [ ] JpType { JpArray } } ,
} ,
Handler : jpObjectFromLists ,
} ,
ReturnType : [ ] JpType { JpObject } ,
Note : "converts a pair of lists containing keys and values to an object" ,
} ,
2022-09-07 21:52:30 +05:30
{
Entry : & gojmespath . FunctionEntry {
Name : random ,
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpRandom ,
} ,
ReturnType : [ ] JpType { JpString } ,
Note : "Generates a random sequence of characters" ,
} ,
2022-09-28 19:15:39 +01:00
{
Entry : & gojmespath . FunctionEntry {
Name : x509_decode ,
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpX509Decode ,
} ,
ReturnType : [ ] JpType { JpObject } ,
2022-10-03 13:56:19 +05:30
Note : "decodes an x.509 certificate to an object. you may also use this in conjunction with `base64_decode` jmespath function to decode a base64-encoded certificate" ,
2022-09-28 19:15:39 +01:00
} ,
2023-01-06 12:57:57 +05:30
{
Entry : & gojmespath . FunctionEntry {
Name : timeToCron ,
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpTimeToCron ,
} ,
ReturnType : [ ] JpType { JpString } ,
Note : "converts an absolute time (RFC 3339) to a cron expression (string)." ,
} ,
2023-01-06 22:18:13 +05:30
{
Entry : & gojmespath . FunctionEntry {
Name : timeAdd ,
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpTimeAdd ,
} ,
ReturnType : [ ] JpType { JpString } ,
Note : "adds duration (third string) to a time value (second string) of a specified layout (first string)" ,
} ,
{
Entry : & gojmespath . FunctionEntry {
Name : timeParse ,
Arguments : [ ] ArgSpec {
{ Types : [ ] JpType { JpString } } ,
{ Types : [ ] JpType { JpString } } ,
} ,
Handler : jpTimeParse ,
} ,
ReturnType : [ ] JpType { JpString } ,
Note : "changes a time value of a given layout to RFC 3339" ,
} ,
2021-04-17 02:17:00 +03:00
}
}
func jpfCompare ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
a , err := validateArg ( compare , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
b , err := validateArg ( compare , arguments , 1 , reflect . String )
if err != nil {
return nil , err
}
return strings . Compare ( a . String ( ) , b . String ( ) ) , nil
}
func jpfEqualFold ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
a , err := validateArg ( equalFold , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
b , err := validateArg ( equalFold , arguments , 1 , reflect . String )
if err != nil {
return nil , err
}
return strings . EqualFold ( a . String ( ) , b . String ( ) ) , nil
}
func jpfReplace ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
str , err := validateArg ( replace , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
old , err := validateArg ( replace , arguments , 1 , reflect . String )
if err != nil {
return nil , err
}
new , err := validateArg ( replace , arguments , 2 , reflect . String )
if err != nil {
return nil , err
}
n , err := validateArg ( replace , arguments , 3 , reflect . Float64 )
if err != nil {
return nil , err
}
return strings . Replace ( str . String ( ) , old . String ( ) , new . String ( ) , int ( n . Float ( ) ) ) , nil
}
func jpfReplaceAll ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
str , err := validateArg ( replaceAll , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
old , err := validateArg ( replaceAll , arguments , 1 , reflect . String )
if err != nil {
return nil , err
}
new , err := validateArg ( replaceAll , arguments , 2 , reflect . String )
if err != nil {
return nil , err
}
return strings . ReplaceAll ( str . String ( ) , old . String ( ) , new . String ( ) ) , nil
}
func jpfToUpper ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
str , err := validateArg ( toUpper , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
return strings . ToUpper ( str . String ( ) ) , nil
}
func jpfToLower ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
str , err := validateArg ( toLower , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
return strings . ToLower ( str . String ( ) ) , nil
}
func jpfTrim ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
str , err := validateArg ( trim , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
cutset , err := validateArg ( trim , arguments , 1 , reflect . String )
if err != nil {
return nil , err
}
return strings . Trim ( str . String ( ) , cutset . String ( ) ) , nil
}
func jpfSplit ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
str , err := validateArg ( split , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
sep , err := validateArg ( split , arguments , 1 , reflect . String )
if err != nil {
return nil , err
}
2021-10-29 11:26:18 +05:30
split := strings . Split ( str . String ( ) , sep . String ( ) )
arr := make ( [ ] interface { } , len ( split ) )
for i , v := range split {
arr [ i ] = v
}
return arr , nil
2021-04-17 02:17:00 +03:00
}
func jpRegexReplaceAll ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
regex , err := validateArg ( regexReplaceAll , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
src , err := ifaceToString ( arguments [ 1 ] )
if err != nil {
return nil , fmt . Errorf ( invalidArgumentTypeError , regexReplaceAll , 2 , "String or Real" )
}
repl , err := ifaceToString ( arguments [ 2 ] )
if err != nil {
return nil , fmt . Errorf ( invalidArgumentTypeError , regexReplaceAll , 3 , "String or Real" )
}
reg , err := regexp . Compile ( regex . String ( ) )
if err != nil {
return nil , fmt . Errorf ( genericError , regexReplaceAll , err . Error ( ) )
}
return string ( reg . ReplaceAll ( [ ] byte ( src ) , [ ] byte ( repl ) ) ) , nil
}
func jpRegexReplaceAllLiteral ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
regex , err := validateArg ( regexReplaceAllLiteral , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
src , err := ifaceToString ( arguments [ 1 ] )
if err != nil {
return nil , fmt . Errorf ( invalidArgumentTypeError , regexReplaceAllLiteral , 2 , "String or Real" )
}
repl , err := ifaceToString ( arguments [ 2 ] )
if err != nil {
return nil , fmt . Errorf ( invalidArgumentTypeError , regexReplaceAllLiteral , 3 , "String or Real" )
}
reg , err := regexp . Compile ( regex . String ( ) )
if err != nil {
return nil , fmt . Errorf ( genericError , regexReplaceAllLiteral , err . Error ( ) )
}
return string ( reg . ReplaceAllLiteral ( [ ] byte ( src ) , [ ] byte ( repl ) ) ) , nil
}
func jpRegexMatch ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
regex , err := validateArg ( regexMatch , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
src , err := ifaceToString ( arguments [ 1 ] )
if err != nil {
return nil , fmt . Errorf ( invalidArgumentTypeError , regexMatch , 2 , "String or Real" )
}
return regexp . Match ( regex . String ( ) , [ ] byte ( src ) )
}
2021-11-29 17:13:07 +01:00
func jpPatternMatch ( arguments [ ] interface { } ) ( interface { } , error ) {
pattern , err := validateArg ( regexMatch , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
src , err := ifaceToString ( arguments [ 1 ] )
if err != nil {
return nil , fmt . Errorf ( invalidArgumentTypeError , regexMatch , 2 , "String or Real" )
}
return wildcard . Match ( pattern . String ( ) , src ) , nil
}
2021-05-04 18:28:30 +02:00
func jpLabelMatch ( arguments [ ] interface { } ) ( interface { } , error ) {
labelMap , ok := arguments [ 0 ] . ( map [ string ] interface { } )
if ! ok {
return nil , fmt . Errorf ( invalidArgumentTypeError , labelMatch , 0 , "Object" )
}
matchMap , ok := arguments [ 1 ] . ( map [ string ] interface { } )
if ! ok {
return nil , fmt . Errorf ( invalidArgumentTypeError , labelMatch , 1 , "Object" )
}
for key , value := range labelMap {
if val , ok := matchMap [ key ] ; ! ok || val != value {
return false , nil
}
}
return true , nil
}
2021-09-23 03:10:45 +05:30
func jpAdd ( arguments [ ] interface { } ) ( interface { } , error ) {
2021-12-07 21:14:46 +05:30
op1 , op2 , err := ParseArithemticOperands ( arguments , add )
2021-09-23 03:10:45 +05:30
if err != nil {
return nil , err
}
2021-12-07 21:14:46 +05:30
return op1 . Add ( op2 )
2021-09-23 03:10:45 +05:30
}
func jpSubtract ( arguments [ ] interface { } ) ( interface { } , error ) {
2021-12-07 21:14:46 +05:30
op1 , op2 , err := ParseArithemticOperands ( arguments , subtract )
2021-09-23 03:10:45 +05:30
if err != nil {
return nil , err
}
2021-12-07 21:14:46 +05:30
return op1 . Subtract ( op2 )
2021-09-23 03:10:45 +05:30
}
func jpMultiply ( arguments [ ] interface { } ) ( interface { } , error ) {
2021-12-07 21:14:46 +05:30
op1 , op2 , err := ParseArithemticOperands ( arguments , multiply )
2021-09-23 03:10:45 +05:30
if err != nil {
return nil , err
}
2021-12-07 21:14:46 +05:30
return op1 . Multiply ( op2 )
2021-09-23 03:10:45 +05:30
}
func jpDivide ( arguments [ ] interface { } ) ( interface { } , error ) {
2021-12-07 21:14:46 +05:30
op1 , op2 , err := ParseArithemticOperands ( arguments , divide )
2021-09-23 03:10:45 +05:30
if err != nil {
return nil , err
}
2021-12-07 21:14:46 +05:30
return op1 . Divide ( op2 )
2021-09-23 03:10:45 +05:30
}
func jpModulo ( arguments [ ] interface { } ) ( interface { } , error ) {
2021-12-07 21:14:46 +05:30
op1 , op2 , err := ParseArithemticOperands ( arguments , modulo )
2021-09-23 03:10:45 +05:30
if err != nil {
return nil , err
}
2021-12-07 21:14:46 +05:30
return op1 . Modulo ( op2 )
2021-09-23 03:10:45 +05:30
}
2021-10-14 19:46:06 +01:00
func jpBase64Decode ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
str , err := validateArg ( "" , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
decodedStr , err := base64 . StdEncoding . DecodeString ( str . String ( ) )
if err != nil {
return nil , err
}
return string ( decodedStr ) , nil
}
func jpBase64Encode ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
str , err := validateArg ( "" , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
return base64 . StdEncoding . EncodeToString ( [ ] byte ( str . String ( ) ) ) , nil
}
2021-11-18 01:47:17 +05:30
func jpTimeSince ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
layout , err := validateArg ( "" , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
ts1 , err := validateArg ( "" , arguments , 1 , reflect . String )
if err != nil {
return nil , err
}
ts2 , err := validateArg ( "" , arguments , 2 , reflect . String )
if err != nil {
return nil , err
}
var t1 , t2 time . Time
if layout . String ( ) != "" {
t1 , err = time . Parse ( layout . String ( ) , ts1 . String ( ) )
} else {
t1 , err = time . Parse ( time . RFC3339 , ts1 . String ( ) )
}
if err != nil {
return nil , err
}
t2 = time . Now ( )
if ts2 . String ( ) != "" {
if layout . String ( ) != "" {
t2 , err = time . Parse ( layout . String ( ) , ts2 . String ( ) )
} else {
t2 , err = time . Parse ( time . RFC3339 , ts2 . String ( ) )
}
if err != nil {
return nil , err
}
}
return t2 . Sub ( t1 ) . String ( ) , nil
}
2023-01-02 20:05:01 +05:30
func jpTimeNow ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
layout , err := validateArg ( "" , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
var t time . Time
t = time . Now ( )
if layout . String ( ) != "" {
t , err = time . Parse ( layout . String ( ) , t . String ( ) )
} else {
t , err = time . Parse ( time . RFC3339 , t . String ( ) )
}
if err != nil {
return nil , err
}
return t . String ( ) , nil
}
2021-12-06 19:10:34 +08:00
func jpPathCanonicalize ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
str , err := validateArg ( pathCanonicalize , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
return filepath . Join ( str . String ( ) ) , nil
}
2021-12-17 02:52:52 -05:00
func jpTruncate ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
2021-12-20 01:50:46 -05:00
var normalizedLength float64
2021-12-17 02:52:52 -05:00
str , err := validateArg ( truncate , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
length , err := validateArg ( truncate , arguments , 1 , reflect . Float64 )
if err != nil {
return nil , err
}
2021-12-20 01:50:46 -05:00
if length . Float ( ) < 0 {
normalizedLength = float64 ( 0 )
} else {
normalizedLength = length . Float ( )
}
return trunc . Truncator ( str . String ( ) , int ( normalizedLength ) , trunc . CutStrategy { } ) , nil
2021-12-17 02:52:52 -05:00
}
2021-12-21 21:42:35 +05:30
func jpSemverCompare ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
v , err := validateArg ( semverCompare , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
r , err := validateArg ( semverCompare , arguments , 1 , reflect . String )
if err != nil {
return nil , err
}
version , _ := semver . Parse ( v . String ( ) )
expectedRange , err := semver . ParseRange ( r . String ( ) )
if err != nil {
return nil , err
}
if expectedRange ( version ) {
return true , nil
}
return false , nil
}
2022-01-10 21:42:02 +00:00
func jpParseJson ( arguments [ ] interface { } ) ( interface { } , error ) {
input , err := validateArg ( parseJson , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
var output interface { }
err = json . Unmarshal ( [ ] byte ( input . String ( ) ) , & output )
return output , err
}
2022-01-17 13:41:08 +00:00
func jpParseYAML ( arguments [ ] interface { } ) ( interface { } , error ) {
input , err := validateArg ( parseYAML , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
jsonData , err := yaml . YAMLToJSON ( [ ] byte ( input . String ( ) ) )
if err != nil {
return nil , err
}
var output interface { }
err = json . Unmarshal ( jsonData , & output )
return output , err
}
2022-05-04 06:33:24 -04:00
func jpItems ( arguments [ ] interface { } ) ( interface { } , error ) {
input , ok := arguments [ 0 ] . ( map [ string ] interface { } )
if ! ok {
return nil , fmt . Errorf ( invalidArgumentTypeError , arguments , 0 , "Object" )
}
keyName , ok := arguments [ 1 ] . ( string )
if ! ok {
return nil , fmt . Errorf ( invalidArgumentTypeError , arguments , 1 , "String" )
}
valName , ok := arguments [ 2 ] . ( string )
if ! ok {
return nil , fmt . Errorf ( invalidArgumentTypeError , arguments , 2 , "String" )
}
arrayOfObj := make ( [ ] map [ string ] interface { } , 0 )
keys := [ ] string { }
// Sort the keys so that the output is deterministic
for key := range input {
keys = append ( keys , key )
}
sort . Strings ( keys )
for _ , key := range keys {
m := make ( map [ string ] interface { } )
m [ keyName ] = key
m [ valName ] = input [ key ]
arrayOfObj = append ( arrayOfObj , m )
}
return arrayOfObj , nil
}
2022-05-07 13:05:04 +01:00
func jpObjectFromLists ( arguments [ ] interface { } ) ( interface { } , error ) {
keys , ok := arguments [ 0 ] . ( [ ] interface { } )
if ! ok {
return nil , fmt . Errorf ( invalidArgumentTypeError , arguments , 0 , "Array" )
}
values , ok := arguments [ 1 ] . ( [ ] interface { } )
if ! ok {
return nil , fmt . Errorf ( invalidArgumentTypeError , arguments , 1 , "Array" )
}
output := map [ string ] interface { } { }
for i , ikey := range keys {
key , err := ifaceToString ( ikey )
if err != nil {
return nil , fmt . Errorf ( invalidArgumentTypeError , arguments , 0 , "StringArray" )
}
if i < len ( values ) {
output [ key ] = values [ i ]
} else {
output [ key ] = nil
}
}
return output , nil
}
2021-04-17 02:17:00 +03:00
// InterfaceToString casts an interface to a string type
func ifaceToString ( iface interface { } ) ( string , error ) {
2021-10-14 01:00:41 +02:00
switch i := iface . ( type ) {
2021-04-17 02:17:00 +03:00
case int :
2021-10-14 01:00:41 +02:00
return strconv . Itoa ( i ) , nil
2021-04-17 02:17:00 +03:00
case float64 :
2021-10-14 01:00:41 +02:00
return strconv . FormatFloat ( i , 'f' , - 1 , 32 ) , nil
2021-04-17 02:17:00 +03:00
case float32 :
2021-10-14 01:00:41 +02:00
return strconv . FormatFloat ( float64 ( i ) , 'f' , - 1 , 32 ) , nil
2021-04-17 02:17:00 +03:00
case string :
2021-10-14 01:00:41 +02:00
return i , nil
2021-04-17 02:17:00 +03:00
case bool :
2021-10-14 01:00:41 +02:00
return strconv . FormatBool ( i ) , nil
2021-04-17 02:17:00 +03:00
default :
return "" , errors . New ( "error, undefined type cast" )
}
}
func validateArg ( f string , arguments [ ] interface { } , index int , expectedType reflect . Kind ) ( reflect . Value , error ) {
arg := reflect . ValueOf ( arguments [ index ] )
if arg . Type ( ) . Kind ( ) != expectedType {
2022-01-10 21:42:02 +00:00
return reflect . Value { } , fmt . Errorf ( invalidArgumentTypeError , f , index + 1 , expectedType . String ( ) )
2021-04-17 02:17:00 +03:00
}
return arg , nil
}
2022-09-07 21:52:30 +05:30
func jpRandom ( arguments [ ] interface { } ) ( interface { } , error ) {
pattern := arguments [ 0 ] . ( string )
if pattern == "" {
return "" , errors . New ( "no pattern provided" )
}
2022-09-14 11:57:32 +05:30
rand . Seed ( time . Now ( ) . UnixNano ( ) )
2022-09-07 21:52:30 +05:30
ans , err := regen . Generate ( pattern )
if err != nil {
2022-09-26 15:33:52 +02:00
return nil , err
2022-09-07 21:52:30 +05:30
}
return ans , nil
}
2022-09-28 19:15:39 +01:00
func jpX509Decode ( arguments [ ] interface { } ) ( interface { } , error ) {
res := make ( map [ string ] interface { } )
input , err := validateArg ( x509_decode , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
p , _ := pem . Decode ( [ ] byte ( input . String ( ) ) )
if p == nil {
return res , errors . New ( "invalid certificate" )
}
cert , err := x509 . ParseCertificate ( p . Bytes )
if err != nil {
return res , err
}
buf := new ( bytes . Buffer )
if fmt . Sprint ( cert . PublicKeyAlgorithm ) == "RSA" {
spki := cryptobyte . String ( cert . RawSubjectPublicKeyInfo )
if ! spki . ReadASN1 ( & spki , cryptobyte_asn1 . SEQUENCE ) {
return res , errors . New ( "writing asn.1 element to 'spki' failed" )
}
var pkAISeq cryptobyte . String
if ! spki . ReadASN1 ( & pkAISeq , cryptobyte_asn1 . SEQUENCE ) {
return res , errors . New ( "writing asn.1 element to 'pkAISeq' failed" )
}
var spk asn1 . BitString
if ! spki . ReadASN1BitString ( & spk ) {
return res , errors . New ( "writing asn.1 bit string to 'spk' failed" )
}
kk , err := x509 . ParsePKCS1PublicKey ( spk . Bytes )
if err != nil {
return res , err
}
cert . PublicKey = PublicKey {
N : kk . N . String ( ) ,
E : kk . E ,
}
enc := json . NewEncoder ( buf )
err = enc . Encode ( cert )
if err != nil {
return res , err
}
}
if err := json . Unmarshal ( buf . Bytes ( ) , & res ) ; err != nil {
return res , err
}
return res , nil
}
2023-01-06 12:57:57 +05:30
func jpTimeToCron ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
ts , err := validateArg ( "" , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
var t time . Time
t , err = time . Parse ( time . RFC3339 , ts . String ( ) )
if err != nil {
return nil , err
}
t = t . UTC ( )
var cron string = ""
cron += strconv . Itoa ( t . Minute ( ) ) + " "
cron += strconv . Itoa ( t . Hour ( ) ) + " "
cron += strconv . Itoa ( t . Day ( ) ) + " "
cron += strconv . Itoa ( int ( t . Month ( ) ) ) + " "
cron += strconv . Itoa ( int ( t . Weekday ( ) ) )
return cron , nil
}
2023-01-06 22:18:13 +05:30
func jpTimeAdd ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
layout , err := validateArg ( "" , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
ts , err := validateArg ( "" , arguments , 1 , reflect . String )
if err != nil {
return nil , err
}
dr , err := validateArg ( "" , arguments , 2 , reflect . String )
if err != nil {
return nil , err
}
var t time . Time
if layout . String ( ) != "" {
t , err = time . Parse ( layout . String ( ) , ts . String ( ) )
} else {
t , err = time . Parse ( time . RFC3339 , ts . String ( ) )
}
if err != nil {
return nil , err
}
var d time . Duration
d , err = time . ParseDuration ( dr . String ( ) )
if err != nil {
return nil , err
}
return t . Add ( d ) . Format ( time . RFC3339 ) , nil
}
func jpTimeParse ( arguments [ ] interface { } ) ( interface { } , error ) {
var err error
layout , err := validateArg ( "" , arguments , 0 , reflect . String )
if err != nil {
return nil , err
}
ts , err := validateArg ( "" , arguments , 1 , reflect . String )
if err != nil {
return nil , err
}
var t time . Time
t , err = time . Parse ( layout . String ( ) , ts . String ( ) )
if err != nil {
return nil , err
}
return t . Format ( time . RFC3339 ) , nil
}