Make it work inside the toolbox container itself

A truly seamless developer experience requires erasing the divide
between the host and the toolbox container as much as possible.
Currently, various tools don't work at all when used from inside the
toolbox because they expect to be run on the host. eg., flatpak,
podman, and the toolbox script itself. This puts a significant enough
cognitive burden on the developer. At the very least, the human
operator needs to keep track of the context in which those commands
are being issued.

To make things better, the toolbox script has been made aware of the
context in which it is running. If it detects that it's running inside
the toolbox container, denoted by a 'podman exec ...' parent process
and the presence of /run/.containerenv, then it tries to forward its
own invocation to the host over D-Bus using 'flatpak-spawn --host' [1].
This uses the HostCommand method on the org.freedesktop.Flatpak D-Bus
service underneath to do the forwarding.

The process offering the org.freedesktop.Flatpak service doesn't have
some variables, like COLORTERM and TERM, set in its environment, and
their absence hinders the use of interactive shells. This is addressed
by tunneling the same set of environment variables that are also passed
to podman.

[1] http://docs.flatpak.org/en/latest/flatpak-command-reference.html#flatpak-spawn

https://github.com/debarshiray/toolbox/pull/54
This commit is contained in:
Debarshi Ray 2019-02-19 13:18:29 +01:00
parent a09692aa8b
commit 5b3d234c9e
1 changed files with 137 additions and 74 deletions

211
toolbox
View File

@ -18,6 +18,7 @@
exec 42>/dev/null exec 42>/dev/null
arguments="$@"
base_toolbox_command=$(basename "$0" 2>&42) base_toolbox_command=$(basename "$0" 2>&42)
base_toolbox_image="" base_toolbox_image=""
environment_variables="COLORTERM \ environment_variables="COLORTERM \
@ -43,6 +44,7 @@ fgc=""
. /etc/os-release . /etc/os-release
release=$VERSION_ID release=$VERSION_ID
podman_pid=""
prefix_sudo="" prefix_sudo=""
registry="registry.fedoraproject.org" registry="registry.fedoraproject.org"
registry_candidate="candidate-registry.fedoraproject.org" registry_candidate="candidate-registry.fedoraproject.org"
@ -546,6 +548,19 @@ exit_if_unrecognized_option()
} }
forward_to_host()
(
if [ "$DBUS_SYSTEM_BUS_ADDRESS" != "" ]; then
set_dbus_system_bus_address="--env=DBUS_SYSTEM_BUS_ADDRESS=$DBUS_SYSTEM_BUS_ADDRESS"
fi
set_environment=$(create_environment_options)
echo "$base_toolbox_command: forwarding to host: $0 $arguments" >&42
flatpak-spawn $set_dbus_system_bus_address $set_environment --host "$0" $arguments 2>&42
)
update_container_and_image_names() update_container_and_image_names()
{ {
base_toolbox_image="fedora-toolbox:$release" base_toolbox_image="fedora-toolbox:$release"
@ -590,6 +605,42 @@ while has_prefix "$1" -; do
shift shift
done done
if [ -f /run/.containerenv ] 2>&42; then
if ! which flatpak-spawn >/dev/null 2>&42; then
echo "$base_toolbox_command: flatpak-spawn not found"
exit 1
fi
echo "$base_toolbox_command: looking for podman PID" >&42
pid_i=$$
while [ "$pid_i" -gt 1 ] 2>&42; do
cmdline=$(cat /proc/$pid_i/cmdline 2>&42 | sed "s/\x0/ /g" 2>&42)
if has_prefix "$cmdline" "podman exec "; then
podman_pid=$pid_i
break
fi
pid_i=$(ps -p $pid_i -o ppid= 2>&42 | sed "s/ //" 2>&42)
if ! is_integer "$pid_i"; then
echo "$base_toolbox_command: invalid parent PID"
break
fi
done
if ! is_integer "$podman_pid"; then
echo "$base_toolbox_command: invalid podman PID"
podman_pid=""
fi
if [ "$podman_pid" = "" ]; then
echo "$base_toolbox_command: cannot be used outside podman exec"
exit 1
fi
echo "$base_toolbox_command: podman PID is $podman_pid" >&42
fi
if [ "$1" = "" ]; then if [ "$1" = "" ]; then
echo "$base_toolbox_command: missing command" echo "$base_toolbox_command: missing command"
echo "Try '$base_toolbox_command --help' for more information." echo "Try '$base_toolbox_command --help' for more information."
@ -601,88 +652,100 @@ shift
case $op in case $op in
create ) create )
while has_prefix "$1" -; do if is_integer "$podman_pid"; then
case $1 in forward_to_host
--candidate-registry ) else
registry=$registry_candidate while has_prefix "$1" -; do
;; case $1 in
--container ) --candidate-registry )
shift registry=$registry_candidate
exit_if_missing_argument --container "$1" ;;
toolbox_container=$1 --container )
;; shift
--image ) exit_if_missing_argument --container "$1"
shift toolbox_container=$1
exit_if_missing_argument --image "$1" ;;
toolbox_image=$1 --image )
;; shift
--release ) exit_if_missing_argument --image "$1"
shift toolbox_image=$1
exit_if_missing_argument --release "$1" ;;
arg=$(echo $1 | sed "s/^F\|^f//" 2>&42) --release )
exit_if_non_positive_argument --release "$arg" shift
release=$arg exit_if_missing_argument --release "$1"
;; arg=$(echo $1 | sed "s/^F\|^f//" 2>&42)
* ) exit_if_non_positive_argument --release "$arg"
exit_if_unrecognized_option $1 release=$arg
esac ;;
shift * )
done exit_if_unrecognized_option $1
exit_if_extra_operand $1 esac
update_container_and_image_names shift
create done
exit_if_extra_operand $1
update_container_and_image_names
create
fi
exit exit
;; ;;
enter ) enter )
while has_prefix "$1" -; do if is_integer "$podman_pid"; then
case $1 in forward_to_host
--container ) else
shift while has_prefix "$1" -; do
exit_if_missing_argument --container "$1" case $1 in
toolbox_container=$1 --container )
;; shift
--release ) exit_if_missing_argument --container "$1"
shift toolbox_container=$1
exit_if_missing_argument --release "$1" ;;
arg=$(echo $1 | sed "s/^F\|^f//" 2>&42) --release )
exit_if_non_positive_argument --release "$arg" shift
release=$arg exit_if_missing_argument --release "$1"
;; arg=$(echo $1 | sed "s/^F\|^f//" 2>&42)
* ) exit_if_non_positive_argument --release "$arg"
exit_if_unrecognized_option $1 release=$arg
esac ;;
shift * )
done exit_if_unrecognized_option $1
exit_if_extra_operand $1 esac
update_container_and_image_names shift
enter done
exit_if_extra_operand $1
update_container_and_image_names
enter
fi
exit exit
;; ;;
list ) list )
ls_images=false if is_integer "$podman_pid"; then
ls_containers=false forward_to_host
while has_prefix "$1" -; do else
case $1 in ls_images=false
-c | --containers ) ls_containers=false
ls_containers=true while has_prefix "$1" -; do
;; case $1 in
-i | --images ) -c | --containers )
ls_images=true ls_containers=true
;; ;;
* ) -i | --images )
exit_if_unrecognized_option $1 ls_images=true
esac ;;
shift * )
done exit_if_unrecognized_option $1
exit_if_extra_operand $1 esac
shift
done
exit_if_extra_operand $1
if ! $ls_containers && ! $ls_images; then if ! $ls_containers && ! $ls_images; then
ls_containers=true ls_containers=true
ls_images=true ls_images=true
fi
$ls_images && list_images
$ls_containers && list_containers
fi fi
$ls_images && list_images
$ls_containers && list_containers
exit exit
;; ;;
* ) * )