refactor: include additional important template funcs (#4690)
* refactor: include additional important template funcs * fix: use of interface * test: improve test casespull/4675/head^2
parent
a4718e4fd0
commit
08cda5d165
|
@ -76,6 +76,8 @@ The following functions which mimic the behaviour of helm exist in most templati
|
|||
- typeIsLike
|
||||
- kindOf
|
||||
- kindIs
|
||||
- default
|
||||
- empty
|
||||
|
||||
See the [Helm Documentation](https://helm.sh/docs/chart_template_guide/function_list/) for more information. Please
|
||||
note that only the functions listed above are supported and the functions don't necessarily behave exactly the same.
|
||||
|
|
|
@ -71,77 +71,11 @@ func FuncMap() map[string]any {
|
|||
"typeIsLike": FuncTypeIsLike,
|
||||
"kindOf": FuncKindOf,
|
||||
"kindIs": FuncKindIs,
|
||||
"default": FuncDefault,
|
||||
"empty": FuncEmpty,
|
||||
}
|
||||
}
|
||||
|
||||
// FuncTypeIs is a helper function that provides similar functionality to the helm typeIs func.
|
||||
func FuncTypeIs(is string, v any) bool {
|
||||
return is == FuncTypeOf(v)
|
||||
}
|
||||
|
||||
// FuncTypeIsLike is a helper function that provides similar functionality to the helm typeIsLike func.
|
||||
func FuncTypeIsLike(is string, v any) bool {
|
||||
t := FuncTypeOf(v)
|
||||
|
||||
return is == t || "*"+is == t
|
||||
}
|
||||
|
||||
// FuncTypeOf is a helper function that provides similar functionality to the helm typeOf func.
|
||||
func FuncTypeOf(v any) string {
|
||||
return reflect.ValueOf(v).Type().String()
|
||||
}
|
||||
|
||||
// FuncKindIs is a helper function that provides similar functionality to the helm kindIs func.
|
||||
func FuncKindIs(is string, v any) bool {
|
||||
return is == FuncKindOf(v)
|
||||
}
|
||||
|
||||
// FuncKindOf is a helper function that provides similar functionality to the helm kindOf func.
|
||||
func FuncKindOf(v any) string {
|
||||
return reflect.ValueOf(v).Kind().String()
|
||||
}
|
||||
|
||||
// FuncList is a helper function that provides similar functionality to the helm list func.
|
||||
func FuncList(items ...any) []any {
|
||||
return items
|
||||
}
|
||||
|
||||
// FuncDict is a helper function that provides similar functionality to the helm dict func.
|
||||
func FuncDict(pairs ...any) map[string]any {
|
||||
m := map[string]any{}
|
||||
p := len(pairs)
|
||||
|
||||
for i := 0; i < p; i += 2 {
|
||||
key := strval(pairs[i])
|
||||
|
||||
if i+1 >= p {
|
||||
m[key] = ""
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
m[key] = pairs[i+1]
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// FuncGet is a helper function that provides similar functionality to the helm get func.
|
||||
func FuncGet(m map[string]any, key string) any {
|
||||
if val, ok := m[key]; ok {
|
||||
return val
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// FuncSet is a helper function that provides similar functionality to the helm set func.
|
||||
func FuncSet(m map[string]any, key string, value any) map[string]any {
|
||||
m[key] = value
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// FuncB64Enc is a helper function that provides similar functionality to the helm b64enc func.
|
||||
func FuncB64Enc(input string) string {
|
||||
return base64.StdEncoding.EncodeToString([]byte(input))
|
||||
|
@ -292,58 +226,6 @@ func FuncStringQuote(in ...any) string {
|
|||
return strings.Join(out, " ")
|
||||
}
|
||||
|
||||
func strval(v any) string {
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
return v
|
||||
case []byte:
|
||||
return string(v)
|
||||
case fmt.Stringer:
|
||||
return v.String()
|
||||
default:
|
||||
return fmt.Sprintf("%v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func strslice(v any) []string {
|
||||
switch v := v.(type) {
|
||||
case []string:
|
||||
return v
|
||||
case []any:
|
||||
b := make([]string, 0, len(v))
|
||||
|
||||
for _, s := range v {
|
||||
if s != nil {
|
||||
b = append(b, strval(s))
|
||||
}
|
||||
}
|
||||
|
||||
return b
|
||||
default:
|
||||
val := reflect.ValueOf(v)
|
||||
switch val.Kind() {
|
||||
case reflect.Array, reflect.Slice:
|
||||
l := val.Len()
|
||||
b := make([]string, 0, l)
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
value := val.Index(i).Interface()
|
||||
if value != nil {
|
||||
b = append(b, strval(value))
|
||||
}
|
||||
}
|
||||
|
||||
return b
|
||||
default:
|
||||
if v == nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
return []string{strval(v)}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FuncIterate is a template function which takes a single uint returning a slice of units from 0 up to that number.
|
||||
func FuncIterate(count *uint) (out []uint) {
|
||||
var i uint
|
||||
|
@ -398,3 +280,107 @@ func FuncStringJoinX(elems []string, sep string, n int, p string) string {
|
|||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// FuncTypeIs is a helper function that provides similar functionality to the helm typeIs func.
|
||||
func FuncTypeIs(is string, v any) bool {
|
||||
return is == FuncTypeOf(v)
|
||||
}
|
||||
|
||||
// FuncTypeIsLike is a helper function that provides similar functionality to the helm typeIsLike func.
|
||||
func FuncTypeIsLike(is string, v any) bool {
|
||||
t := FuncTypeOf(v)
|
||||
|
||||
return is == t || "*"+is == t
|
||||
}
|
||||
|
||||
// FuncTypeOf is a helper function that provides similar functionality to the helm typeOf func.
|
||||
func FuncTypeOf(v any) string {
|
||||
return reflect.ValueOf(v).Type().String()
|
||||
}
|
||||
|
||||
// FuncKindIs is a helper function that provides similar functionality to the helm kindIs func.
|
||||
func FuncKindIs(is string, v any) bool {
|
||||
return is == FuncKindOf(v)
|
||||
}
|
||||
|
||||
// FuncKindOf is a helper function that provides similar functionality to the helm kindOf func.
|
||||
func FuncKindOf(v any) string {
|
||||
return reflect.ValueOf(v).Kind().String()
|
||||
}
|
||||
|
||||
// FuncList is a helper function that provides similar functionality to the helm list func.
|
||||
func FuncList(items ...any) []any {
|
||||
return items
|
||||
}
|
||||
|
||||
// FuncDict is a helper function that provides similar functionality to the helm dict func.
|
||||
func FuncDict(pairs ...any) map[string]any {
|
||||
m := map[string]any{}
|
||||
p := len(pairs)
|
||||
|
||||
for i := 0; i < p; i += 2 {
|
||||
key := strval(pairs[i])
|
||||
|
||||
if i+1 >= p {
|
||||
m[key] = ""
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
m[key] = pairs[i+1]
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// FuncGet is a helper function that provides similar functionality to the helm get func.
|
||||
func FuncGet(m map[string]any, key string) any {
|
||||
if val, ok := m[key]; ok {
|
||||
return val
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// FuncSet is a helper function that provides similar functionality to the helm set func.
|
||||
func FuncSet(m map[string]any, key string, value any) map[string]any {
|
||||
m[key] = value
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// FuncDefault is a helper function that provides similar functionality to the helm default func.
|
||||
func FuncDefault(d any, vals ...any) any {
|
||||
if FuncEmpty(vals) || FuncEmpty(vals[0]) {
|
||||
return d
|
||||
}
|
||||
|
||||
return vals[0]
|
||||
}
|
||||
|
||||
// FuncEmpty is a helper function that provides similar functionality to the helm empty func.
|
||||
func FuncEmpty(v any) bool {
|
||||
rv := reflect.ValueOf(v)
|
||||
if !rv.IsValid() {
|
||||
return true
|
||||
}
|
||||
|
||||
switch rv.Kind() {
|
||||
default:
|
||||
return rv.IsNil()
|
||||
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
|
||||
return rv.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !rv.Bool()
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
return rv.Complex() == 0
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return rv.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return rv.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return rv.Float() == 0
|
||||
case reflect.Struct:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -357,6 +357,7 @@ func TestFuncSortAlpha(t *testing.T) {
|
|||
}{
|
||||
{"ShouldSortStrings", []string{"a", "c", "b"}, []string{"a", "b", "c"}},
|
||||
{"ShouldSortIntegers", []int{2, 3, 1}, []string{"1", "2", "3"}},
|
||||
{"ShouldSortSingleValue", 1, []string{"1"}},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
@ -563,3 +564,77 @@ func TestFuncSet(t *testing.T) {
|
|||
assert.Equal(t, map[string]any{"abc": 123, "123": true}, FuncSet(map[string]any{"abc": 123}, "123", true))
|
||||
assert.Equal(t, map[string]any{"abc": true}, FuncSet(map[string]any{"abc": 123}, "abc", true))
|
||||
}
|
||||
|
||||
func TestFuncDefault(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
value []any
|
||||
have any
|
||||
expected any
|
||||
}{
|
||||
{"ShouldDefaultEmptyString", []any{""}, "default", "default"},
|
||||
{"ShouldNotDefaultString", []any{"not default"}, "default", "not default"},
|
||||
{"ShouldDefaultEmptyInteger", []any{0}, 1, 1},
|
||||
{"ShouldNotDefaultInteger", []any{20}, 1, 20},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assert.Equal(t, tc.expected, FuncDefault(tc.have, tc.value...))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuncEmpty(t *testing.T) {
|
||||
var nilv *string
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
value any
|
||||
expected bool
|
||||
}{
|
||||
{"ShouldBeEmptyNil", nilv, true},
|
||||
{"ShouldBeEmptyNilNil", nil, true},
|
||||
{"ShouldBeEmptyString", "", true},
|
||||
{"ShouldNotBeEmptyString", "abc", false},
|
||||
{"ShouldBeEmptyArray", []string{}, true},
|
||||
{"ShouldNotBeEmptyArray", []string{"abc"}, false},
|
||||
{"ShouldBeEmptyInteger", 0, true},
|
||||
{"ShouldNotBeEmptyInteger", 1, false},
|
||||
{"ShouldBeEmptyInteger8", int8(0), true},
|
||||
{"ShouldNotBeEmptyInteger8", int8(1), false},
|
||||
{"ShouldBeEmptyInteger16", int16(0), true},
|
||||
{"ShouldNotBeEmptyInteger16", int16(1), false},
|
||||
{"ShouldBeEmptyInteger32", int32(0), true},
|
||||
{"ShouldNotBeEmptyInteger32", int32(1), false},
|
||||
{"ShouldBeEmptyInteger64", int64(0), true},
|
||||
{"ShouldNotBeEmptyInteger64", int64(1), false},
|
||||
{"ShouldBeEmptyUnsignedInteger", uint(0), true},
|
||||
{"ShouldNotBeEmptyUnsignedInteger", uint(1), false},
|
||||
{"ShouldBeEmptyUnsignedInteger8", uint8(0), true},
|
||||
{"ShouldNotBeEmptyUnsignedInteger8", uint8(1), false},
|
||||
{"ShouldBeEmptyUnsignedInteger16", uint16(0), true},
|
||||
{"ShouldNotBeEmptyUnsignedInteger16", uint16(1), false},
|
||||
{"ShouldBeEmptyUnsignedInteger32", uint32(0), true},
|
||||
{"ShouldNotBeEmptyUnsignedInteger32", uint32(1), false},
|
||||
{"ShouldBeEmptyUnsignedInteger64", uint64(0), true},
|
||||
{"ShouldNotBeEmptyUnsignedInteger64", uint64(1), false},
|
||||
{"ShouldBeEmptyComplex64", complex64(complex(0, 0)), true},
|
||||
{"ShouldNotBeEmptyComplex64", complex64(complex(100000, 7.5)), false},
|
||||
{"ShouldBeEmptyComplex128", complex128(complex(0, 0)), true},
|
||||
{"ShouldNotBeEmptyComplex128", complex128(complex(100000, 7.5)), false},
|
||||
{"ShouldBeEmptyFloat32", float32(0), true},
|
||||
{"ShouldNotBeEmptyFloat32", float32(1), false},
|
||||
{"ShouldBeEmptyFloat64", float64(0), true},
|
||||
{"ShouldNotBeEmptyFloat64", float64(1), false},
|
||||
{"ShouldBeEmptyBoolean", false, true},
|
||||
{"ShouldNotBeEmptyBoolean", true, false},
|
||||
{"ShouldNotBeEmptyStruct", struct{}{}, false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assert.Equal(t, tc.expected, FuncEmpty(tc.value))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
tt "text/template"
|
||||
)
|
||||
|
@ -118,3 +119,55 @@ func loadEmailTemplate(name, overridePath string) (t *EmailTemplate, err error)
|
|||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func strval(v any) string {
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
return v
|
||||
case []byte:
|
||||
return string(v)
|
||||
case fmt.Stringer:
|
||||
return v.String()
|
||||
default:
|
||||
return fmt.Sprintf("%v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func strslice(v any) []string {
|
||||
switch v := v.(type) {
|
||||
case []string:
|
||||
return v
|
||||
case []any:
|
||||
b := make([]string, 0, len(v))
|
||||
|
||||
for _, s := range v {
|
||||
if s != nil {
|
||||
b = append(b, strval(s))
|
||||
}
|
||||
}
|
||||
|
||||
return b
|
||||
default:
|
||||
val := reflect.ValueOf(v)
|
||||
switch val.Kind() {
|
||||
case reflect.Array, reflect.Slice:
|
||||
l := val.Len()
|
||||
b := make([]string, 0, l)
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
value := val.Index(i).Interface()
|
||||
if value != nil {
|
||||
b = append(b, strval(value))
|
||||
}
|
||||
}
|
||||
|
||||
return b
|
||||
default:
|
||||
if v == nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
return []string{strval(v)}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue