diff --git a/internal/template/reflect.go b/internal/template/reflect.go index f329f28d..6a5f3b9b 100644 --- a/internal/template/reflect.go +++ b/internal/template/reflect.go @@ -41,7 +41,24 @@ func deepGetImpl(v reflect.Value, path []string) interface{} { case reflect.Struct: return deepGetImpl(v.FieldByName(path[0]), path[1:]) case reflect.Map: - return deepGetImpl(v.MapIndex(reflect.ValueOf(path[0])), path[1:]) + // If the first part of the path is a key in the map, we use it directly + if mapValue := v.MapIndex(reflect.ValueOf(path[0])); mapValue.IsValid() { + return deepGetImpl(mapValue, path[1:]) + } + + // If the first part of the path is not a key in the map, we try to find a valid key by joining the path parts + for i := 2; i <= len(path); i++ { + joinedPath := strings.Join(path[0:i], ".") + if mapValue := v.MapIndex(reflect.ValueOf(joinedPath)); mapValue.IsValid() { + if i == len(path) { + return mapValue.Interface() + } + return deepGetImpl(mapValue, path[i:]) + } + } + + log.Printf("unable to find key from the path expression %s in map %v\n", strings.Join(path, "."), v) + return nil case reflect.Slice, reflect.Array: i, err := parseAllocateInt(path[0]) if err != nil { diff --git a/internal/template/reflect_test.go b/internal/template/reflect_test.go index 2c43eb3b..5246fb31 100644 --- a/internal/template/reflect_test.go +++ b/internal/template/reflect_test.go @@ -74,6 +74,28 @@ func TestDeepGet(t *testing.T) { "...", "foo", }, + { + "map with dot in key", + map[string]map[string]string{ + "Foo": { + "foo.bar.baz.qux": "quux", + }, + }, + "Foo.foo.bar.baz.qux", + "quux", + }, + { + "nested maps with dot in keys", + map[string]map[string]map[string]string{ + "Foo": { + "foo.bar": { + "baz.qux": "quux", + }, + }, + }, + "Foo.foo.bar.baz.qux", + "quux", + }, {"struct", s, "X", "foo"}, {"pointer to struct", sp, "X", "foo"}, {"double pointer to struct", &sp, ".X", nil}, diff --git a/internal/template/sort.go b/internal/template/sort.go index ef71258f..b4efd4c9 100644 --- a/internal/template/sort.go +++ b/internal/template/sort.go @@ -90,6 +90,14 @@ func getFieldAsString(item interface{}, path string) string { func (s sortableByKey) Less(i, j int) bool { dataI := getFieldAsString(s.data[i], s.key) dataJ := getFieldAsString(s.data[j], s.key) + + if intI, err := strconv.ParseInt(dataI, 10, 64); err == nil { + if intJ, err := strconv.ParseInt(dataJ, 10, 64); err == nil { + // If both are integers, compare as integers + return intI < intJ + } + } + return dataI < dataJ } diff --git a/internal/template/sort_test.go b/internal/template/sort_test.go index e5c5ff44..68a4e48d 100644 --- a/internal/template/sort_test.go +++ b/internal/template/sort_test.go @@ -55,7 +55,7 @@ func TestSortObjectsByKeys(t *testing.T) { Env: map[string]string{ "VIRTUAL_HOST": "bar.localhost", }, - ID: "9", + ID: "11", } o1 := &context.RuntimeContainer{ Created: time.Date(2021, 1, 2, 0, 0, 10, 0, time.UTC),