1
0
mirror of https://github.com/mviereck/x11docker.git synced 2021-09-19 22:38:46 +03:00

use python to parse json output of inspect.

This commit is contained in:
mviereck
2021-06-23 23:49:12 +02:00
parent 038af50b33
commit 19b16a9fda
4 changed files with 106 additions and 77 deletions

View File

@@ -10,6 +10,7 @@ Project website: https://github.com/mviereck/x11docker
### Changed
- `--backend=nerdctl`: Disallow `--home` in rootless mode.
- `--backend`: Allow `--share` in all rootless modes.
- Use `python` to parse json output of `inspect`.
### Fixed
- `--interactive`: Fix output redirection.
[(#364)](https://github.com/mviereck/x11docker/issues/364)

View File

@@ -260,14 +260,14 @@ and [nerdctl](https://github.com/containerd/nerdctl) with option `--backend=BACK
- Test status:
- x11docker was devolped with rootful `docker`, this is well tested.
- Basically tested is `podman`, rootless and rootful.
- Barely tested are rootless `docker` and `nerdctl` in rootless and rootful mode.
- Barely tested:
- rootless `docker`
- `nerdctl` in rootless and rootful mode.
- Some fixes and adjustments for the less tested setups can be expected.
- For rootless mode `podman` is recommended.
- Only `podman` allows option `--home` in rootless mode yet.
- Only `podman` provides useful file ownerships with option `--share` in rootless mode yet.
- For rootful mode `docker` or `podman` are recommended.
- `nerdctl` has some limitations because it supports only a subset of `docker` cli options yet.
- To allow most of x11docker options with `nerdctl` please provide a container command additional to the image name.
- To switch between rootless or rootful mode of `podman` and `nerdctl` just use (or leave) `sudo` or set (or leave) option `--pw`.
- For [rootless docker](https://docs.docker.com/engine/security/rootless/) set environment variable `DOCKER_HOST` accordingly.
@@ -363,10 +363,10 @@ As root you can install, update and remove x11docker in system directories to be
- Note: This does not remove `~/.local/share/x11docker` where it stores persistent files of option `--home`.
What the installation does (just for information):
- Copies `x11docker` and `x11docker-gui` to `/usr/bin`.
- Creates an icon in `/usr/share/icons`.
- Creates `x11docker.desktop` in `/usr/share/applications`.
- Copies `README.md`, `CHANGELOG.md` and `LICENSE.txt` to `/usr/share/doc/x11docker`.
- Copies scripts `x11docker` and `x11docker-gui` to `/usr/bin`.
- Copies icon `x11docker.png` to `/usr/share/icons`.
- Creates menu entry `x11docker.desktop` in `/usr/share/applications`.
- Copies documentation `README.md`, `CHANGELOG.md` and `LICENSE.txt` to `/usr/share/doc/x11docker`.
### Shortest way for first installation:
- For systems using `sudo`:

View File

@@ -5,6 +5,7 @@ x11docker ToDo notes
- check `--init=` in all backends rootful and rootless.
- `--user`: Check in all rootless modes, maybe disallow except for `--user=root`.
- `--user=root --home` in rootless docker and nerdctl: Set up HOME in host user ~/x11docker.
- `--backend=podman` rootless: disallow `--home` for different `--user`.
- `--init=systemd`: cgroupv2 support #349
- replace word 'docker' in messages, variable names and documentation to generalize for podman and nerdctl, too.
- check, maybe drop container wm using `x11docker/openbox`. Currently likely fails with different backends.

167
x11docker
View File

@@ -11,7 +11,7 @@
# Run 'x11docker --help' or scroll down to read usage information.
# More documentation at: https://github.com/mviereck/x11docker
Version="6.9.1-beta-1"
Version="6.9.1-beta-2"
# --enforce-i: Enforce running in interactive mode to allow commands tty and weston-launch in special setups.
grep -q -- "--enforce-i" <<< "$*" && case $- in
@@ -831,7 +831,7 @@ $(for Line in $Watchpidlist; do pspid "$Line" || echo "(pid $Line not found)" ;
done
# Container PID not watchable in MSYS2/Cygwin/WSL11.
[ "$Containername" ] && {
[ "$($Containerbackendbin inspect -f {{.State.Running}} $Containername)" == "true" ] || {
$Containerbackendbin inspect $Containername >/dev/null || {
debugnote "watchpidlist(): Container $Containername has terminated"
saygoodbye "watchpidlist $Containername"
}
@@ -920,6 +920,62 @@ makecookie() { # bake a cookie
mysleep() { # catch cases where sleep only supports integer
sleep "${1:-1}" 2>/dev/null || sleep 1
}
parse_inspect() { # parse json of inspect output using python
# parse for keys in output of docker|podman|nerdctl inspect.
# Uses python json parser.
# $1 String containg inspect output
# $2...$n Key. For second level keys provide e.g. "jsonstring" "Config" "Cmd"
local Parserscript
Parserscript="$Cachefolder/parse_inspect.py"
Parserscript="$(cat << EOF
#! /usr/bin/env python
import json,sys
def parse_inspect(*args):
"""
parse output of docker|podman|nerdctl inspect
args:
0: ignored
1: string containing inspect output
2..n: json keys. For second level keys provide e.g. "Config","Cmd"
Prints key value as a string.
Prints empty string if key not found.
A list is printed as a string with '' around each element.
"""
output=""
inspect=args[1]
inspect=inspect.strip()
if inspect[0] == "[" :
inspect=inspect[1:-2] # remove enclosing [ ]
obj=json.loads(inspect)
for arg in args[2:]: # recursivly find the desired object. Command.Cmd is found with args "Command" , "Cmd"
try:
obj=obj[arg]
except:
obj=""
objtype=str(type(obj))
if objtype == "<type 'list'>":
for i in obj:
output=output+"'"+str(i)+"' "
else:
output=str(obj)
if output == "None":
output=""
print(output)
parse_inspect(*sys.argv)
EOF
)"
echo "$Parserscript" | python - "$@"
}
storeinfo() { # store some information for later use
# store and provide pieces of information
# replace entry if codeword is already present
@@ -1229,7 +1285,7 @@ writeaccess() { # check if useruid $1 has write access to folder
cleanup() { # --cleanup : check for non-removed containers and left cache files
# Cleanes x11docker cache and removes running and stopped x11docker containers.
# Does not change --home folders.
local Orphanedcontainers= Orphanedfolders= Line=
local Orphanedcontainers= Orphanedfolders= Line= Inspect Containerid
note "x11docker will check for orphaned containers from earlier sessions.
This can happen if docker was not closed successfully.
@@ -1241,20 +1297,20 @@ cleanup() { # --cleanup : check for non-removed containers a
grep -q .cache/x11docker <<<$Cachebasefolder && Orphanedfolders="$(find "$Cachebasefolder" -mindepth 1 -maxdepth 1 -type d | sed s%$Cachebasefolder/%% | grep -w -v x11docker-gui)"
# e X11DOCKER_LASTCLEANFOLDER may be set by x11docker-gui to spare its cache folder.
[ "${X11DOCKER_LASTCLEANFOLDER:-}" ] && Orphanedfolders="$(echo "$Orphanedfolders" | grep -v $X11DOCKER_LASTCLEANFOLDER)"
Orphanedcontainers="$($Containerbackendbin ps -a --filter name=x11docker_X | grep -v NAMES | rev | cut -d' ' -f1 | rev)"
Orphanedcontainers="$($Containerbackendbin ps -a | grep x11docker_X | rev | cut -d' ' -f1 | rev)"
Orphanedcontainers="$Orphanedcontainers $(find "$Cachebasefolder" -mindepth 2 -maxdepth 2 -type f -name 'container.id' -exec cat {} \;)"
Orphanedcontainers="$(env IFS='' echo $Orphanedcontainers)"
# check for double entrys name/id, check for already non-existing containers
for Line in $Orphanedcontainers; do
$Containerbackendbin inspect $Line -f '{{.Id}}' >/dev/null 2>/dev/null && {
echo $Line | grep -q x11docker_X && {
$Containerbackendbin inspect $Line -f '{{.Id}}'
Line="$($Containerbackendbin inspect $Line -f '{{.Id}}')"
Orphanedcontainers="$(sed s/$Line// <<< $Orphanedcontainers)"
} ||:
Inspect="$($Containerbackendbin inspect $Line 2>/dev/null)"
[ -n "$Inspect" ] && {
Containerid="$(parse_inspect "$Inspect" "Id")"
Orphanedcontainers="$(sed "s%$Line%$Containerid%" <<< "$Orphanedcontainers")"
:
} || Orphanedcontainers="$(sed s/$Line// <<< $Orphanedcontainers)"
done
Orphanedcontainers="$(sort <<< "$Orphanedcontainers" | uniq)"
[ -z "$Orphanedcontainers$Orphanedfolders" ] && {
note "No orphaned containers or cache files found. good luck!"
@@ -5593,6 +5649,7 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
declare -f checkpid
declare -f escapestring
declare -f mysleep
declare -f parse_inspect
declare -f pspid
declare -f rmcr
declare -f rocknroll
@@ -5609,6 +5666,7 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
echo ""
}
echo "Cachefolder='$Cachefolder'"
echo "Containercommand=\"$Containercommand\""
echo "Imagename=\"$Imagename\""
echo "Messagefile='$Messagefifo'"
@@ -5717,7 +5775,6 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
ask)
[ "$Runsinterminal" = "yes" ] && {
echo "grep -x -q '$Imagename' < $Dockerimagelistfile || grep -x -q '$Imagename:latest' < $Dockerimagelistfile || {"
# echo " $Containerbackendbin inspect $Imagename >>$Containerlogfile 2>&1 || {"
echo " $Containerbackendbin images | grep -q '^$Imagename ' || {"
echo " echo 'Image $Imagename not found locally.' >&2"
echo " echo 'Do you want to pull it from docker hub?' >&2"
@@ -5748,19 +5805,16 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
case "$Inspectimage" in
no) ;;
yes)
echo "Inspect=\"\$($Containerbackendbin inspect $Imagename --format='{{.Config.User}}|{{.Config.WorkingDir}}|{{.Architecture}}')\""
echo ""
echo "Inspect=\"\$($Containerbackendbin inspect $Imagename)\""
echo "# Check architecture"
echo "Containerarchitecture=\"\$(cut -d'|' -f3 <<< \"\$Inspect\")\""
echo 'Containerarchitecture=$(parse_inspect "$Inspect" "Architecture")'
echo "debugnote \"dockerrc: Image architecture: \$Containerarchitecture\""
echo "# Check CMD"
echo "[ -z \"\$Containercommand\" ] && {"
echo " # extract image command from image if not given on cli"
echo " Containercommand=\"\$($Containerbackendbin inspect $Imagename --format='{{.Config.Cmd}}')\""
echo " Containercommand=\"\${Containercommand#[}\""
echo " Containercommand=\"\${Containercommand%]}\""
echo ' Containercommand="$(parse_inspect "$Inspect" "Config" "Cmd")"'
echo " debugnote \"dockerrc: Image CMD: \$Containercommand\""
echo " echo \"\$Containercommand\" | grep -q $(convertpath share $Containerrc) && error 'Recursion error: Found CMD $(convertpath share $Containerrc) in image.
Did you use 'docker commit' with an x11docker container?
@@ -5771,7 +5825,7 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
echo "# Check USER"
echo "Imageuser=\"\$(cut -d'|' -f1 <<< \"\$Inspect\")\""
echo 'Imageuser="$(parse_inspect "$Inspect" "Config" "User")"'
echo "debugnote \"dockerrc: Image USER: \$Imageuser\""
case $Createcontaineruser in
yes)
@@ -5790,9 +5844,7 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
yes) echo "Entrypoint=" ;;
no)
echo "# Check ENTRYPOINT"
echo "Entrypoint=\"\$($Containerbackendbin inspect $Imagename --format='{{.Config.Entrypoint}}')\""
echo "Entrypoint=\"\${Entrypoint#[}\""
echo "Entrypoint=\"\${Entrypoint%]}\""
echo 'Entrypoint="$(parse_inspect "$Inspect" "Config" "Entrypoint")"'
echo "debugnote \"dockerrc: Image ENTRYPOINT: \$Entrypoint\""
case $Initsystem in
systemd|sysvinit|runit|openrc|tini)
@@ -5826,7 +5878,7 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
[ -z "$Workdir" ] && {
echo "# Check WORKDIR"
echo "Workdir=\"\$(cut -d'|' -f2 <<< \"\$Inspect\")\""
echo 'Workdir="$(parse_inspect "$Inspect" "Config" "Workdir")"'
echo "debugnote \"dockerrc: Image WORKDIR: \$Workdir\""
echo "[ \"\$Workdir\" ] && note \"Found 'WORKDIR \$Workdir' in image.
You can change it with option --workdir=DIR.\""
@@ -6121,7 +6173,7 @@ create_dockerrc() { ### create dockerrc: This script runs as root (o
echo "rocknroll || exit 64"
echo ""
[ "$Windowmanagermode" = "none" ] || { ### FIXME: check with podman and nerdctl. Or drop at all?
[ "$Windowmanagermode" = "none" ] || { ### FIXME: drop at all?
echo "# run window manager (in image or from host)"
echo "Windowmanagermode=\"$Windowmanagermode\""
echo "Windowmanagercommand=\"$Windowmanagercommand\""
@@ -6137,7 +6189,8 @@ $Wmdockercommand"'
echo ' [ "$Wmcontainerid" ] && {'
echo ' debugnote "dockerrc: Window manager container: $Wmcontainerid"'
echo " for ((Count=1 ; Count<=10 ; Count++)); do"
echo " Pid1pid=\"\$($Containerbackendbin inspect --format '{{.State.Pid}}' \$Wmcontainerid 2>>$Containerlogfile | rmcr)\""
echo " Inspect=\"\$($Containerbackendbin inspect \$Wmcontainerid 2>>$Containerlogfile | rmcr)\""
echo ' Pid1pid="$(parse_inspect "$Inspect" "State" "Pid")"'
echo " debugnote \"dockerrc: Window manager container: \$Count. check for PID 1: \$Pid1pid\""
case $Mobyvm in
no) echo ' checkpid "$Pid1pid" && break' ;;
@@ -6221,15 +6274,8 @@ $Wmdockercommand"'
echo "# Wait for pid 1 in container"
echo "for ((Count=1 ; Count<=40 ; Count++)); do"
case $Containerbackend in
nerdctl)
echo " Pid1pid=\"\$($Containerbackendbin inspect $Containername 2>>$Containerlogfile | rmcr)\""
echo ' Pid1pid="$(grep "\"Pid\"" <<< "$Pid1pid" | tr -dc "0-9")"'
;;
*)
echo " Pid1pid=\"\$($Containerbackendbin inspect --format '{{.State.Pid}}' $Containername 2>>$Containerlogfile | rmcr)\""
;;
esac
echo " Inspect=\"\$($Containerbackendbin inspect $Containername 2>>$Containerlogfile | rmcr)\""
echo ' Pid1pid="$(parse_inspect "$Inspect" "State" "Pid")"'
echo " debugnote \"dockerrc: \$Count. check for PID 1: \$Pid1pid\""
case $Mobyvm in
no) echo ' checkpid "$Pid1pid" && break' ;;
@@ -6253,15 +6299,7 @@ $(rmcr < '$Containerlogfile' | uniq )"'
echo ""
echo "# Get IP of container"
case "$Containerbackend" in
nerdctl)
echo "Containerip=\"\$($Containerbackendbin inspect $Containername 2>>$Containerlogfile)\""
echo 'Containerip="$(grep IPAddress <<< "$Containerip" | head -n1 | tr -cd "[.0-9]")"'
;;
*)
echo "Containerip=\"\$($Containerbackendbin inspect --format '{{ .NetworkSettings.IPAddress }}' $Containername 2>>$Containerlogfile)\""
;;
esac
echo 'Containerip="$(parse_inspect "$Inspect" "NetworkSettings" "IPAddress")"'
echo 'storeinfo containerip=$Containerip'
echo ""
@@ -6648,7 +6686,6 @@ check_host() { # check host environment
*)
#Hostip="$(hostname -I | cut -d' ' -f1)"
[ "$Hostip" ] || Hostip="$(ip -4 -o a | grep 'docker0' | awk '{print $4}' | cut -d/ -f1 | grep "172.17.0.1" ||: )"
#[ "$Hostip" ] || Hostip="$($Containerbackendbin network inspect bridge --format='{{.IPAM.Config}}' 2>/dev/null | awk '{print $2}')"
[ "$Hostip" ] || Hostip="$(ip -4 -o a | grep 'docker0' | awk '{print $4}' | cut -d/ -f1 | head -n1)"
[ "$Hostip" ] || Hostip="$(ip -4 -o a | awk '{print $4}' | cut -d/ -f1 | grep "^192\.168\.*" | head -n1)"
[ "$Hostip" ] || Hostip="$(ip -4 -o a | awk '{print $4}' | cut -d/ -f1 | grep -v "127.0.0.1" | head -n1)"
@@ -7137,7 +7174,17 @@ check_option_interferences() { # check multiple option interferences, change se
;;
esac
command -v python >/dev/null || {
[ "$Containersetup" = "yes" ] && {
note "x11docker needs 'python' to parse output of '$Containerbackend inspect'.
This is needed to check ENTRYPOINT and CMD that in turn is needed to set up
some x11docker features. To allow more features, please install 'python'
or provide a container command to execute.
Fallback: Enabling option --no-setup."
Containersetup="no"
}
}
# --cap-default
[ "$Capdropall" = "no" ] && {
warning "Option --cap-default disables security hardening
@@ -7591,35 +7638,15 @@ check_option_interferences() { # check multiple option interferences, change se
nerdctl)
note "Option --backend=nerdctl: nerdctl only supports a subset
of docker options. That limits support of x11docker features."
Inspectimage="no"
case "$Containercommand" in
"")
[ "$Containersetup" = "yes" ] && {
note "Option --backend=nerdctl: nerdctl does not support 'inspect'
for images that is needed to check ENTRYPOINT and CMD
that in turn is needed to set up some x11docker features.
To allow more features, please provide a container command to execute.
Fallback: Enabling option --no-setup."
Containersetup="no"
}
;;
*)
Switchcontaineruser="yes"
[ "$Capdropall" = "yes" ] && note "Option --backend=nerdctl: x11docker
Switchcontaineruser="yes"
[ "$Capdropall" = "yes" ] && warning "Option --backend=nerdctl: x11docker
will allow some user switching capabilities that would be dropped with
other backends. (Because 'nerdctl --exec' does not support option --user.)"
[ "$Noentrypoint" = "yes" ] || {
note "Option --backend=nerdctl: nerdctl does not support 'inspect'
for images that is needed to check ENTRYPOINT and CMD
that in turn is needed to set up some x11docker features.
Fallback: Disabling ENTRYPOINT with option --no-entrypoint."
Noentrypoint="yes"
}
;;
esac
other backends. (Because 'nerdctl --exec' does not support option --user.)
Though, these are still within nerdctl default capabilities."
;;
*) note "Option --backend=$Containerbackend: Unknown backend. Will try anyway.
You might need option --no-setup." ;;
You might need option --no-setup.
Known backends are docker, podman and nerdctl." ;;
esac
# Docker installed in Ubuntu snap