k9s/internal/view/env.go

71 lines
1.8 KiB
Go

// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of K9s
package view
import (
"fmt"
"log/slog"
"regexp"
"sort"
"strconv"
"strings"
"github.com/derailed/k9s/internal/slogs"
)
// Env represent K9s and K8s available environment variables.
type Env map[string]string
// EnvRX match $XXX, $!XXX, ${XXX} or ${!XXX} custom arg.
// |
// | (g2)(group 3) (g5)( group 6 )
// | ( group 1 ) ( group 4 )
// | ( group 0 )
var envRX = regexp.MustCompile(`(\$(!?)([\w\-]+))|(\$\{(!?)([\w\-%/: ]+)})`)
// keyFromSubmatch extracts the name and inverse flag of a match.
func keyFromSubmatch(m []string) (key string, inverse bool) {
// group 1 matches $XXX and $!XXX args.
if m[1] != "" {
return m[3], m[2] == "!"
}
// group 4 matches ${XXX} and ${!XXX} args.
return m[6], m[5] == "!"
}
// Substitute replaces env variable keys from in a string with their corresponding values.
func (e Env) Substitute(arg string) (string, error) {
matches := envRX.FindAllStringSubmatch(arg, -1)
if len(matches) == 0 {
return arg, nil
}
// To prevent the substitution starts with the shorter environment variable,
// sort with the length of the found environment variables.
sort.Slice(matches, func(i, j int) bool {
return len(matches[i][0]) > len(matches[j][0])
})
for _, m := range matches {
key, inverse := keyFromSubmatch(m)
v, ok := e[strings.ToUpper(key)]
if !ok {
slog.Warn("No k9s environment matching key",
slogs.Matches, matches,
slogs.Key, key,
)
continue
}
if b, err := strconv.ParseBool(v); err == nil {
if inverse {
b = !b
}
v = fmt.Sprintf("%t", b)
}
arg = strings.ReplaceAll(arg, m[0], v)
}
return arg, nil
}