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

211
toolbox
View file

@ -18,6 +18,7 @@
exec 42>/dev/null
arguments="$@"
base_toolbox_command=$(basename "$0" 2>&42)
base_toolbox_image=""
environment_variables="COLORTERM \
@ -43,6 +44,7 @@ fgc=""
. /etc/os-release
release=$VERSION_ID
podman_pid=""
prefix_sudo=""
registry="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()
{
base_toolbox_image="fedora-toolbox:$release"
@ -590,6 +605,42 @@ while has_prefix "$1" -; do
shift
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
echo "$base_toolbox_command: missing command"
echo "Try '$base_toolbox_command --help' for more information."
@ -601,88 +652,100 @@ shift
case $op in
create )
while has_prefix "$1" -; do
case $1 in
--candidate-registry )
registry=$registry_candidate
;;
--container )
shift
exit_if_missing_argument --container "$1"
toolbox_container=$1
;;
--image )
shift
exit_if_missing_argument --image "$1"
toolbox_image=$1
;;
--release )
shift
exit_if_missing_argument --release "$1"
arg=$(echo $1 | sed "s/^F\|^f//" 2>&42)
exit_if_non_positive_argument --release "$arg"
release=$arg
;;
* )
exit_if_unrecognized_option $1
esac
shift
done
exit_if_extra_operand $1
update_container_and_image_names
create
if is_integer "$podman_pid"; then
forward_to_host
else
while has_prefix "$1" -; do
case $1 in
--candidate-registry )
registry=$registry_candidate
;;
--container )
shift
exit_if_missing_argument --container "$1"
toolbox_container=$1
;;
--image )
shift
exit_if_missing_argument --image "$1"
toolbox_image=$1
;;
--release )
shift
exit_if_missing_argument --release "$1"
arg=$(echo $1 | sed "s/^F\|^f//" 2>&42)
exit_if_non_positive_argument --release "$arg"
release=$arg
;;
* )
exit_if_unrecognized_option $1
esac
shift
done
exit_if_extra_operand $1
update_container_and_image_names
create
fi
exit
;;
enter )
while has_prefix "$1" -; do
case $1 in
--container )
shift
exit_if_missing_argument --container "$1"
toolbox_container=$1
;;
--release )
shift
exit_if_missing_argument --release "$1"
arg=$(echo $1 | sed "s/^F\|^f//" 2>&42)
exit_if_non_positive_argument --release "$arg"
release=$arg
;;
* )
exit_if_unrecognized_option $1
esac
shift
done
exit_if_extra_operand $1
update_container_and_image_names
enter
if is_integer "$podman_pid"; then
forward_to_host
else
while has_prefix "$1" -; do
case $1 in
--container )
shift
exit_if_missing_argument --container "$1"
toolbox_container=$1
;;
--release )
shift
exit_if_missing_argument --release "$1"
arg=$(echo $1 | sed "s/^F\|^f//" 2>&42)
exit_if_non_positive_argument --release "$arg"
release=$arg
;;
* )
exit_if_unrecognized_option $1
esac
shift
done
exit_if_extra_operand $1
update_container_and_image_names
enter
fi
exit
;;
list )
ls_images=false
ls_containers=false
while has_prefix "$1" -; do
case $1 in
-c | --containers )
ls_containers=true
;;
-i | --images )
ls_images=true
;;
* )
exit_if_unrecognized_option $1
esac
shift
done
exit_if_extra_operand $1
if is_integer "$podman_pid"; then
forward_to_host
else
ls_images=false
ls_containers=false
while has_prefix "$1" -; do
case $1 in
-c | --containers )
ls_containers=true
;;
-i | --images )
ls_images=true
;;
* )
exit_if_unrecognized_option $1
esac
shift
done
exit_if_extra_operand $1
if ! $ls_containers && ! $ls_images; then
ls_containers=true
ls_images=true
if ! $ls_containers && ! $ls_images; then
ls_containers=true
ls_images=true
fi
$ls_images && list_images
$ls_containers && list_containers
fi
$ls_images && list_images
$ls_containers && list_containers
exit
;;
* )