From 5b3d234c9e9ef45ff3540d5febc799277cf747d9 Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Tue, 19 Feb 2019 13:18:29 +0100 Subject: [PATCH] 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 --- toolbox | 211 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 137 insertions(+), 74 deletions(-) diff --git a/toolbox b/toolbox index 07d719a..bca6bf0 100755 --- a/toolbox +++ b/toolbox @@ -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 ;; * )