[Fix] Allow literal @ in flags that have nodefilters (#421)

- literal @s can now be escaped with a preceeding backslash
  - use case e.g. `--env HTTPS_PROXY=user:pass\@myproxy.com`
- if the last char before a non-literal @ (designating a following
nodefilter) is a backslash, then it can be escaped with another
backslash (no cascading escapes though)
pull/431/head
Thorsten Klein 4 years ago committed by GitHub
parent 15f35b02b5
commit 0f15ca34d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 33
      cmd/util/filter.go
  2. 5
      tests/test_basic.sh

@ -50,18 +50,41 @@ func SplitFiltersFromFlag(flag string) (string, []string, error) {
/* Case 2) filter indicated using '@' in flag */
split := strings.Split(flag, "@")
newsplit := []string{}
buffer := ""
for i, it := range split {
// Case 1: There's a '\' just before the '@' sign -> Should it be escaped (aka be a literal '@')?
if strings.HasSuffix(it, "\\") && i != len(split)-1 {
// Case 1.1: Escaped backslash
if strings.HasSuffix(it, "\\\\") {
it = strings.TrimSuffix(it, "\\")
log.Warnf("The part '%s' of the flag input '%s' ends with a double backslash, so we assume you want to escape the backslash before the '@'. That's the only time we do this.", it, flag)
} else {
// Case 1.2: Unescaped backslash -> Escaping the '@' -> remove suffix and append it to buffer, followed by the escaped @ sign
log.Tracef("Item '%s' just before an '@' ends with '\\', so we assume it's escaping a literal '@'", it)
buffer += strings.TrimSuffix(it, "\\") + "@"
continue
}
}
// Case 2: There's no '\': append item to buffer, save it to new slice, empty buffer and continue
newsplit = append(newsplit, buffer+it)
buffer = ""
continue
}
// max number of pieces after split = 2 (only one @ allowed in flag)
if len(split) > 2 {
return "", nil, fmt.Errorf("Invalid flag '%s': only one '@' for node filter allowed", flag)
if len(newsplit) > 2 {
return "", nil, fmt.Errorf("Invalid flag '%s': only one unescaped '@' allowed for node filter(s) (Escape literal '@' with '\\')", flag)
}
// trailing or leading '@'
if len(split) < 2 {
return "", nil, fmt.Errorf("Invalid flag '%s' includes '@' but is missing either an object or a filter", flag)
if len(newsplit) < 2 {
return "", nil, fmt.Errorf("Invalid flag '%s' includes unescaped '@' but is missing a node filter (Escape literal '@' with '\\')", flag)
}
return split[0], strings.Split(split[1], ";"), nil
return newsplit[0], strings.Split(newsplit[1], ";"), nil
}

@ -7,7 +7,7 @@ CURR_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source "$CURR_DIR/common.sh"
info "Creating two clusters..."
$EXE cluster create c1 --wait --timeout 60s --api-port 6443 || failed "could not create cluster c1"
$EXE cluster create c1 --wait --timeout 60s --api-port 6443 --env 'TEST_VAR=user\@pass\\@server[0]' || failed "could not create cluster c1"
$EXE cluster create c2 --wait --timeout 60s || failed "could not create cluster c2"
info "Checking that we can get both clusters..."
@ -16,6 +16,9 @@ check_cluster_count 2
info "Checking we have access to both clusters..."
check_clusters "c1" "c2" || failed "error checking cluster"
info "Checking cluster env var with escaped @ signs..."
docker exec k3d-c1-server-0 env | grep -E '^TEST_VAR=user@pass\\$' || failed "Failed to lookup proper env var in container"
info "Check k3s token retrieval"
check_cluster_token_exist "c1" || failed "could not find cluster token c1"
check_cluster_token_exist "c2" || failed "could not find cluster token c2"

Loading…
Cancel
Save