-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Add TERM iff TERM not defined in container when podman exec -t #20357
Conversation
@edsantiago Not sure what is going on, but the out put of env from inside of container seems to have a ^M associated with it, not sure how to remove it nicely. |
@@ -713,6 +713,13 @@ func (c *Container) LinuxResources() *spec.LinuxResources { | |||
return nil | |||
} | |||
|
|||
func (c *Container) Env() []string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a doc comment.
pkg/util/utils.go
Outdated
@@ -1219,3 +1219,28 @@ func ConvertTimeout(timeout int) uint { | |||
} | |||
return uint(timeout) | |||
} | |||
|
|||
func ExecAddTERM(useTTY bool, existingEnv []string, execEnvs map[string]string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since there's only one caller and no uni tests, can we move it directly to pkg/domain/infra/abi/containers.go
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two callers, one from api/handlers an one from domain/infra/abi
test/system/075-exec.bats
Outdated
|
||
@test "podman exec --tty" { | ||
run_podman run -d --name test $IMAGE top | ||
run_podman 1 exec test printenv echo $TERM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The printenv echo $TERM
confuses me. Do you want to echo
or printenv
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not only that, the echo $TERM
(without single quotes) will interpret $TERM
in the context of the running shell (BATS), not the container. This should be printenv TERM
, as it is below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes this was a leak, attempting to get this, should all be printenv TERM.
test/system/075-exec.bats
Outdated
fi | ||
run_podman rm -f -t 0 test | ||
|
||
run_podman run -t -d --name test $IMAGE top |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This entire block looks a duplicate of the previous one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First one is a container run without a -t
Second one is a container run with -t
Third is container run with -t --env TERM=banana
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Way too many confusing combinations. Might I make a suggestion?
@test "podman exec --tty" {
# Outer loops: different variations on the RUN container
for run_opt_t in "" "-t"; do
for run_term_env in "" "explicit_RUN_term"; do
local run_opt_env=
if [[ -n "$run_term_env" ]]; then
run_opt_env="--env=TERM=$run_term_env"
fi
run_podman run -d $run_opt_t $run_opt_env --name test $IMAGE top
# Inner loops: different variations on EXEC
for exec_opt_t in "" "-t"; do
for exec_term_env in "" "explicit_EXEC_term"; do
# What to expect.
local expected=
# "exec -t" defaults to current $TERM
if [[ -n "$exec_opt_t" ]]; then
expected="$TERM"
fi
# ...unless "run -t", which forces xterm (always xterm)
if [[ -n "$run_opt_t" ]]; then
expected="xterm"
fi
# ...unless overridden by explicit --env
if [[ -n "$run_term_env$exec_term_env" ]]; then
# (exec overrides run)
expected="${exec_term_env:-$run_term_env}"
fi
local exec_opt_env=
if [[ -n "$exec_term_env" ]]; then
exec_opt_env="--env=TERM=$exec_term_env"
fi
run_podman exec $exec_opt_t $exec_opt_env test sh -c 'echo -n $TERM'
assert "$output" = "$expected" "run $run_opt_t $run_opt_env, exec $exec_opt_t $exec_opt_env"
done
done
run_podman rm -f -t0 test
done
done
This very clearly demonstrates what I consider a confusing aspect of run -t
with exec -t
. If it's deliberate, fine, but to me it violates POLA that exec -t
depends on whether the container was run
with/without -t
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine, it does loose the test to make sure TERM is not set in the non run -t
and non exec -t
case, since theoretically TERM="" versus TERM not set. But really not important.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be fairly easy to fix:
local expect_rc=0
if [[ -z "$expect_output" ]]; then
expect_rc=1
fi
...
run_podman $expect_rc exec [...] printenv TERM
...but that then requires defining cr=$'\r'
and requiring it in the -t
cases. Which I think might be fine, but it makes the test more complicated, and the loop is already too unwieldy. LMK if you'd like the full \r
set of changes.
pkg/api/handlers/compat/exec.go
Outdated
@@ -58,6 +59,7 @@ func ExecCreateHandler(w http.ResponseWriter, r *http.Request) { | |||
libpodConfig.WorkDir = input.WorkingDir | |||
libpodConfig.Privileged = input.Privileged | |||
libpodConfig.User = input.User | |||
util.ExecAddTERM(input.Tty && !ctr.Terminal(), ctr.Env(), libpodConfig.Environment) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see why this should ever depend on ctr.Terminal()
? Either exec is started with tty or not, I don't see why the container option matters in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you are right, originally I was checking that to look for TERM, but now, I just can use TERM if it is defined within the container and only force it if it is not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^M
is the result of -t
. For a tighter test, I recommend:
cr=$'\r'
...
assert "$output" = "whatever$cr" "..."
test/system/075-exec.bats
Outdated
|
||
@test "podman exec --tty" { | ||
run_podman run -d --name test $IMAGE top | ||
run_podman 1 exec test printenv echo $TERM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not only that, the echo $TERM
(without single quotes) will interpret $TERM
in the context of the running shell (BATS), not the container. This should be printenv TERM
, as it is below.
3947965
to
25bf9c1
Compare
@edsantiago it is blowing up with an unexpected terminal name |
Argh! I can reproduce via |
This fixes the tests..... but only for local podman. For remote, diff --git a/test/system/075-exec.bats b/test/system/075-exec.bats
index ec7d59536..324c9bbfe 100644
--- a/test/system/075-exec.bats
+++ b/test/system/075-exec.bats
@@ -177,3 +177,3 @@ load helpers
fi
- run_podman run -d $run_opt_t $run_opt_env --name test $IMAGE top
+ TERM=run-term run_podman run -d $run_opt_t $run_opt_env --name test $IMAGE top
@@ -184,5 +184,5 @@ load helpers
local expected=
- # "exec -t" defaults to current $TERM
+ # "exec -t" defaults to the process TERM
if [[ -n "$exec_opt_t" ]]; then
- expected="$TERM"
+ expected="exec-term"
fi
@@ -203,3 +203,3 @@ load helpers
- run_podman exec $exec_opt_t $exec_opt_env test sh -c 'echo -n $TERM'
+ TERM=exec-term run_podman exec $exec_opt_t $exec_opt_env test sh -c 'echo -n $TERM'
assert "$output" = "$expected" "run $run_opt_t $run_opt_env, exec $exec_opt_t $exec_opt_env" Note that this does not test the |
@rhatdan this is going to fail. I guess I wasn't clear in my comments, sorry. The podman-remote case uses $ TERM=sdfsdf bin/podman system service --timeout=0
Note that Anyhow, tests will fail until this is resolved. Either skip part of the tests under remote, or fix the underlying code, and I would prefer to fix the underlying code. I think |
@edsantiago I changed the |
I'm not sure this is better? It still fails remote (no change), and now I think the Anyhow, this is going to fail all system tests, not just remote. |
My bad. This is actually a very small net gain ( diff --git a/test/system/075-exec.bats b/test/system/075-exec.bats
index 324c9bbfe..14f965063 100644
--- a/test/system/075-exec.bats
+++ b/test/system/075-exec.bats
@@ -188,5 +188,5 @@ load helpers
fi
- # ...unless "run -t", which forces xterm (always xterm)
+ # ...unless "run -t", which forces the run-process TERM
if [[ -n "$run_opt_t" ]]; then
- expected="xterm"
+ expected="run-term"
fi ...but remote is still 100% broken and I still lean toward thinking that it should be fixed in the code, not the tests. What I can do, though, is kludge up the tests so they pass under remote, then sweep the podman-remote-exec problem under the rug for another bug week. Should I do that? |
copy-paste this, it will work under local and remote. I've made the warning messages very obnoxious as an incentive to getting that bug fixed (or at least getting the issue resolved one way or another). @test "podman exec --tty" {
# Outer loops: different variations on the RUN container
for run_opt_t in "" "-t"; do
for run_term_env in "" "explicit_RUN_term"; do
local run_opt_env=
if [[ -n "$run_term_env" ]]; then
run_opt_env="--env=TERM=$run_term_env"
fi
TERM=run-term run_podman run -d $run_opt_t $run_opt_env --name test $IMAGE top
# Inner loops: different variations on EXEC
for exec_opt_t in "" "-t"; do
for exec_term_env in "" "explicit_EXEC_term"; do
# What to expect.
local expected=
# "exec -t" defaults to the process TERM
if [[ -n "$exec_opt_t" ]]; then
expected="exec-term"
fi
# ...unless "run -t", which forces the run-process TERM
if [[ -n "$run_opt_t" ]]; then
expected="run-term"
fi
# ...unless overridden by explicit --env
if [[ -n "$run_term_env$exec_term_env" ]]; then
# (exec overrides run)
expected="${exec_term_env:-$run_term_env}"
fi
local exec_opt_env=
if [[ -n "$exec_term_env" ]]; then
exec_opt_env="--env=TERM=$exec_term_env"
fi
local desc="run $run_opt_t $run_opt_env, exec $exec_opt_t $exec_opt_env"
TERM=exec-term run_podman exec $exec_opt_t $exec_opt_env test sh -c 'echo -n $TERM'
# FIXME FIXME FIXME! #xxxxx: podman-remote run/exec -t use server TERM, not client
if is_remote && [[ -n "$run_opt_t$exec_opt_t" ]] && [[ -z "$run_term_env$exec_term_env" ]]; then
echo "# [[ FIXME: podman-remote -t uses server TERM, not client : $desc ]]" >&3
else
# The normal case
assert "$output" = "$expected" "$desc"
fi
done
done
run_podman rm -f -t0 test
done
done
} |
Switching to TERM on the client side is a potential breaking change, but might make the most sense. Up til now, exec used TERM from the Container, the change that triggered this PR was that podman run --tty=false, no longer sets a TERM environment variable. This was causing podman exec --tty=true to said terminals to not work correctly without a TERM set. This PR still takes the TERM from the container if it is set, and then takes if from the client, when it is not set. Changing to always take TERM from the client for podman exec, might make the most sense, although in the server case, you could have a TERM on the client side that is not understood on the server side. Perhaps a TERM from a Mac or Windows is not understood in linux. (The current code is susceptible to the same issue). @vrothberg @Luap99 @edsantiago @baude Thoughts? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am OK with the change
LGTM
Why are we looking up the TERM from the host environment exactly? This seems to be a new change made by this PR so I don't see how this effects any kind of backwards compatibility. More the other way around using the TERM env from the environment might be breaking (although I don't see how but I don't really understand how $TERM is used by applications so I wouldn't really comment on that) I don't see why we should make such change, nobody seems to have asked for that. The old logic is use |
Also worth pointing out before committing to such changes we should verify what docker does. If docker doesn't read from the environment neither should we IMO. |
My fault: I got sick of all the churn on this, and added tests, and my new test found what I consider to be weird behavior. But yeah, I guess we should figure out what docker does and copy it. |
Basically docker sets the TERM=xterm if it not defined in the container image on docker run. |
Something changed in And, I'm ultra-concerned that we have a brand-new test, |
exec something leak, @giuseppe PTAL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have to repush (once #20404 merges) to fix CI anyway, so, some fix requests
test/system/075-exec.bats
Outdated
for exec_term_env in "" "explicit_EXEC_term"; do | ||
# What to expect. | ||
local expected= | ||
# "exec -t" defaults to the process xterm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just "xterm", not "the process xterm". (You global-replaced TERM, that yielded some nonsense results)
test/system/075-exec.bats
Outdated
if [[ -n "$exec_opt_t" ]]; then | ||
expected="xterm" | ||
fi | ||
# ...unless "run -t", which forces the run-process xterm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, this block is now absurd. It should be collapsed, both if
s should become:
# if -t is set anywhere, either run or exec, go with xterm
if [[ -n "$run_opt_t$exec_opt_t" ]]; then
test/system/075-exec.bats
Outdated
|
||
local desc="run $run_opt_t $run_opt_env, exec $exec_opt_t $exec_opt_env" | ||
TERM=exec-term run_podman exec $exec_opt_t $exec_opt_env test sh -c 'echo -n $TERM' | ||
# The normal case |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for this comment any more, please remove
20404 (CI fix) is merged. You can now rebase. Please do fix the issues I reported above. |
Fixes: containers#20334 Signed-off-by: Daniel J Walsh <[email protected]>
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: edsantiago, rhatdan, vrothberg The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Flake is new to me. Restarted. /lgtm This has been quite the ordeal. Thank you @rhatdan for your patience with my obnoxious insistence on testing. |
/hold cancel |
Fixes: #20334
Does this PR introduce a user-facing change?