I have observed that kubectl
inserts an additional \
to linefeed characters when using the --from-literal
option. It works as expected when loading "the same" content from a file. Clearly, there must be a difference because the stdout looks different but I fail to see why.
echo "api_key" >> .tmp
echo "api_value" >> .tmp
cat -e .tmp
kubectl delete secrets api-env
kubectl create secret generic api-env --from-file=.api=.tmp
rm .tmp
kubectl get secret api-env -o json | jq '.data | map_values(@base64d)'
#prints:
#api_key$
#api_value$
#secret "api-env" deleted
#secret/api-env created
#{
# ".api": "api_key\napi_value\n"
#}
The commands above create a single linefeed character on each line. Demonstrated by cat -e
there are two linefeed characters in the file, each at the end.
Doing the same using a string results in the \n
to be escaped.
api="api_key\napi_value\n"
echo $api
kubectl delete secrets api-env
kubectl create secret generic api-env --from-literal=.api=$api
kubectl get secret api-env -o json | jq '.data | map_values(@base64d)'
#prints:
#api_key\napi_value\n
#secret "api-env" deleted
#secret/api-env created
#{
# ".api": "api_key\\napi_value\\n"
#}
The echo
command shows the string as it was supplied to the variable, however after loading that to kubernetes the \n
are escaped and the content is considered to be a single line.
This is important because in several instances where I am working with kubectl
I am not allowed to write to the local file system.
What is happening here and how to stop kubernetes from escaping the \n
character?
Environment:
- zsh 5.8 (x86_64-apple-darwin21.0)
- Darwin Kernel Version 21.4.0: root:xnu-8020.101.4~15/RELEASE_X86_64 x86_64
- kubectl Client:"v1.20.10"
- kubectl Server: "v1.23.3"
- minikube version: v1.25.2
CodePudding user response:
When you use echo $api
, echo
itself changes the contents: On POSIX-compliant shells with XSI extensions enabled (and while zsh isn't POSIX-compliant in general, it does implement this aspect), the \n
s are replaced with literal newlines.
That doesn't happen with --from-literal=.api=$api
; there, your \n
s are still two-character sequences, first a backslash, then a n
.
Given that you're on a shell that supports using $'\n'
as a way to represent a newline literal directly, consider --from-literal=.api="api_key"$'\n'"api_value"