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
|
- typeIsLike
|
||||||
- kindOf
|
- kindOf
|
||||||
- kindIs
|
- kindIs
|
||||||
|
- default
|
||||||
|
- empty
|
||||||
|
|
||||||
See the [Helm Documentation](https://helm.sh/docs/chart_template_guide/function_list/) for more information. Please
|
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.
|
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,
|
"typeIsLike": FuncTypeIsLike,
|
||||||
"kindOf": FuncKindOf,
|
"kindOf": FuncKindOf,
|
||||||
"kindIs": FuncKindIs,
|
"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.
|
// FuncB64Enc is a helper function that provides similar functionality to the helm b64enc func.
|
||||||
func FuncB64Enc(input string) string {
|
func FuncB64Enc(input string) string {
|
||||||
return base64.StdEncoding.EncodeToString([]byte(input))
|
return base64.StdEncoding.EncodeToString([]byte(input))
|
||||||
|
@ -292,58 +226,6 @@ func FuncStringQuote(in ...any) string {
|
||||||
return strings.Join(out, " ")
|
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.
|
// 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) {
|
func FuncIterate(count *uint) (out []uint) {
|
||||||
var i uint
|
var i uint
|
||||||
|
@ -398,3 +280,107 @@ func FuncStringJoinX(elems []string, sep string, n int, p string) string {
|
||||||
|
|
||||||
return buf.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"}},
|
{"ShouldSortStrings", []string{"a", "c", "b"}, []string{"a", "b", "c"}},
|
||||||
{"ShouldSortIntegers", []int{2, 3, 1}, []string{"1", "2", "3"}},
|
{"ShouldSortIntegers", []int{2, 3, 1}, []string{"1", "2", "3"}},
|
||||||
|
{"ShouldSortSingleValue", 1, []string{"1"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
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": 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))
|
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"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
tt "text/template"
|
tt "text/template"
|
||||||
)
|
)
|
||||||
|
@ -118,3 +119,55 @@ func loadEmailTemplate(name, overridePath string) (t *EmailTemplate, err error)
|
||||||
|
|
||||||
return t, nil
|
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