-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tekton converts double dollar symbols to one #3871
Comments
I see the same output as you. Checking the pod I can see that Tekton is passing the dollar signs through to the shell script exactly as written in the TaskRun: $ k get pod dollar-dollar-taskrun-hwfrk-pod-x527m -o jsonpath="{range .spec.initContainers[]}{.args}"
["-c","tmpfile=\"/tekton/scripts/script-0-wwkmn\"\ntouch ${tmpfile} \u0026\u0026 chmod +x ${tmpfile}\ncat \u003e ${tmpfile} \u003c\u003c 'script-heredoc-randomly-generated-n8gwj'\n#!/bin/sh\nset -xe\necho 'two dollar signs: $$'\necho 'four dollar signs: $$$$'\necho 'two dollar signs from an environment variable: ' $DOLLAR_DOLLAR_ENV\n\nscript-heredoc-randomly-generated-n8gwj\n"] and the env var: k get pod dollar-dollar-taskrun-hwfrk-pod-x527m -o jsonpath="{range .spec.containers[]}{.env}"
[{"name":"DOLLAR_DOLLAR_ENV","value":"$$"}] The way the Step script: |
for f in /tekton/scripts/* ; do
cat $f
done And it looks like it's the script
So it looks like we need to figure out a way to write that shell script tempfile that doesn't do this. I'm not entirely sure what that is yet. |
Thanks for your research, it gave me some nice insights in the workings of Tekton. I've been trying to replicate the behavior locally with Docker. I suspected the shell image that Tekton uses in the initContainer messes up the '$$'. I've found the code that creates the tempfile. I also think I found the shell image that is used in the initContainer. But trying it locally gives:
Any ideas? |
Ah, after a bit of digging I think this is how Kubernetes treats
And from https://v1-18.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#envvar-v1-core :
|
So I guess kubernetes is seeing the double dollar and, assuming that it is a variable escape, replaces it with a single dollar. I am having a really hard time finding the k8s source for this variable substitution though! I can't find the exact lines of go that perform the replacement to confirm this behaviour. |
Nice find! I'm pretty confident this is the source of the expansion. It is used here. |
Yeah, confirmed I see the same behaviour running your demo. I'm pretty well convinced now that this is indeed the source of the problem. So Tekton might be able to work around this by injecting the script a different way. We could place it in an annotation on the Pod and then project that via downward API, for example. This way we bypass k8s' |
This is indeed surprising. Nice investigation work getting to the root cause so quickly! 👍 I don't have a better idea than injecting via the downward API. |
I've created a bug report on Kubernetes. But I can understand that waiting for this to be resolved is not the way to go for Tekton. |
A workaround for this behaviour has been merged and should be released as part of 0.24 this week. |
/reopen I'm going to have to revert this change. The new workaround breaks some bash scripts: #3935 |
@sbwsg: Reopened this issue. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
Copy/pasting the findings from #3935: Bit more investigation: Kubernetes does replace instances of two dollar signs, "$$", with a single dollar sign, "$" but it also attempts to replace instances of "$(X)" with the contents of env var X. In this case k8s sees Long story short the original "fix" was too naive and we should revert this change. |
Sucks that the simple proposed solution was not enough.. I'm disappointed by Kubernetes' variable handling. Anyhow, I don't know too much about the implementation, but instead of finding workarounds for putting plaintext scripts into the containers, can't we first base64 decode it and encode it as first step in the container? Not sure if we have access to the |
Nice! I'll give this a try. |
This works quite nicely (branch with changes over here) and doesn't mangle bash scripts but there are definitely trade-offs:
We could work around trade-off (1) ( I don't think there are any great workarounds for trade-offs (2) and (3) though. I dunno, what do other folks think? |
Nicely done, @sbwsg . To me, the benefit (ensuring data integrity and no dollar wickedness) outweighs the trade-offs. Sure, scripts will increase in size (trade-off 2), but I believe we found out that Kubernetes allows a lot of data in this I doubt it, but might there be any performance concern perhaps around base64 encoding and decoding with bigger scripts? I think it should be very quick, but haven't tested it. One other tiny, tiny benefit is that the heredoc can be reduced to something simple, as long as it does not contain any base64-allowed character ;) |
Very good point about the heredoc, I will update the branch to take advantage of this! Agreed on 2 & 3. There are ways we could increase the available script size, for example by splitting multiple scripts across multiple init containers writing them. And visual inspection of the scripts in the pod has always been quite difficult so base64 encoding doesn't feel like a big drop in usability (to me). Requiring I have, for the time being, created a PR to at least document the problem on our side: #3939 |
Nice job on the docs! I'm thinking of another idea.. I'm not sure what the use-case of using a custom initContainer image is, so perhaps this will sound ignorant. We could Then again, I'm not sure what the use would be of the 'original' initContainer, if the first one can already fully prepare the script. |
I've got a workaround going which no longer requires Changes visible at: main...sbwsg:fix-dollar-signs-in-scripts-with-base64 Need to update and add unit tests, integration, dev docs, etc... Next week. |
Expected Behavior
When the script element in a Tekton Task definition has double dollar symbols, it should remain as two dollar symbols.
Actual Behavior
When the script element in a Tekton Task definition has double dollar symbols, the two symbols are reduced to one dollar symbol.
Steps to Reproduce the Problem
Additional Info
Kubernetes version:
Output of
kubectl version
:Tekton Pipeline version:
Output of
tkn version
orkubectl get pods -n tekton-pipelines -l app=tekton-pipelines-controller -o=jsonpath='{.items[0].metadata.labels.version}'
v0.22.0
Sample TaskRun:
Generated output (The lines prefixed with
+
are the result of theset -x
which is added implicitly by Tekton):The text was updated successfully, but these errors were encountered: