From 006047553dd00d45f6c4df5403cc5f76adfabde8 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Fri, 20 Dec 2024 15:29:07 -0800 Subject: [PATCH 01/32] version bump to v1.25.5 --- jc/lib.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jc/lib.py b/jc/lib.py index ff0b8807..8a01282a 100644 --- a/jc/lib.py +++ b/jc/lib.py @@ -10,7 +10,7 @@ from jc import appdirs from jc import utils -__version__ = '1.25.4' +__version__ = '1.25.5' parsers: List[str] = [ 'acpi', diff --git a/setup.py b/setup.py index 321d2760..fa0d7cc7 100755 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ with open('README.md', 'r') as f: setuptools.setup( name='jc', - version='1.25.4', + version='1.25.5', author='Kelly Brazil', author_email='kellyjonbrazil@gmail.com', description='Converts the output of popular command-line tools and file-types to JSON.', From 8995ac686ae41f679c32a1504b8ea2521b7d6315 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Fri, 20 Dec 2024 15:30:41 -0800 Subject: [PATCH 02/32] doc update --- CHANGELOG | 3 + README.md | 1 + completions/jc_bash_completion.sh | 4 +- completions/jc_zsh_completion.sh | 6 +- docs/parsers/amixer.md | 117 ++++++++++++++++++++++++++++++ jc/parsers/amixer.py | 32 ++------ man/jc.1 | 7 +- 7 files changed, 141 insertions(+), 29 deletions(-) create mode 100644 docs/parsers/amixer.md diff --git a/CHANGELOG b/CHANGELOG index 0211ffaf..f4f159c0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ jc changelog +20241220 v1.25.5 +- Add `amixer` command parser + 20241125 v1.25.4 - Add `ipconfig` command parser (`ipconfig` for Windows) - Add `pacman` command parser diff --git a/README.md b/README.md index fa6933f5..25ee58f8 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,7 @@ option. | `--acpi` | `acpi` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/acpi) | | `--airport` | `airport -I` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/airport) | | `--airport-s` | `airport -s` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/airport_s) | +| `--amixer` | `amixer` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/amixer) | | `--apt-cache-show` | `apt-cache show` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/apt_cache_show) | | `--apt-get-sqq` | `apt-get -sqq` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/apt_get_sqq) | | `--arp` | `arp` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/arp) | diff --git a/completions/jc_bash_completion.sh b/completions/jc_bash_completion.sh index d122aa65..c032ed84 100644 --- a/completions/jc_bash_completion.sh +++ b/completions/jc_bash_completion.sh @@ -3,8 +3,8 @@ _jc() local cur prev words cword jc_commands jc_parsers jc_options \ jc_about_options jc_about_mod_options jc_help_options jc_special_options - jc_commands=(acpi airport apt-cache apt-get arp blkid bluetoothctl cbt certbot chage cksum crontab curl date debconf-show df dig dmidecode dpkg du efibootmgr env ethtool file findmnt finger free git gpg hciconfig host id ifconfig iostat ip ipconfig iptables iw iwconfig jobs last lastb ls lsattr lsb_release lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat needrestart netstat nmcli nsd-control ntpq os-prober pacman pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum swapon sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 tune2fs udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc wg who xrandr zipinfo zpool) - jc_parsers=(--acpi --airport --airport-s --apt-cache-show --apt-get-sqq --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --curl-head --date --datetime-iso --debconf-show --df --dig --dir --dmidecode --dpkg-l --du --efibootmgr --email-address --env --ethtool --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --host --hosts --http-headers --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --ipconfig --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --kv-dup --last --ls --ls-s --lsattr --lsb-release --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --needrestart --netstat --nmcli --nsd-control --ntpq --openvpn --os-prober --os-release --pacman --passwd --path --path-list --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --pkg-index-apk --pkg-index-deb --plist --postconf --proc --proc-buddyinfo --proc-cmdline --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-tcp --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --resolve-conf --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --swapon --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --tune2fs --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --wg-show --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status) + jc_commands=(acpi airport amixer apt-cache apt-get arp blkid bluetoothctl cbt certbot chage cksum crontab curl date debconf-show df dig dmidecode dpkg du efibootmgr env ethtool file findmnt finger free git gpg hciconfig host id ifconfig iostat ip ipconfig iptables iw iwconfig jobs last lastb ls lsattr lsb_release lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat needrestart netstat nmcli nsd-control ntpq os-prober pacman pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum swapon sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 tune2fs udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc wg who xrandr zipinfo zpool) + jc_parsers=(--acpi --airport --airport-s --amixer --apt-cache-show --apt-get-sqq --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --curl-head --date --datetime-iso --debconf-show --df --dig --dir --dmidecode --dpkg-l --du --efibootmgr --email-address --env --ethtool --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --host --hosts --http-headers --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --ipconfig --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --kv-dup --last --ls --ls-s --lsattr --lsb-release --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --needrestart --netstat --nmcli --nsd-control --ntpq --openvpn --os-prober --os-release --pacman --passwd --path --path-list --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --pkg-index-apk --pkg-index-deb --plist --postconf --proc --proc-buddyinfo --proc-cmdline --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-tcp --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --resolve-conf --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --swapon --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --tune2fs --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --wg-show --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status) jc_options=(--force-color -C --debug -d --monochrome -m --meta-out -M --pretty -p --quiet -q --raw -r --slurp -s --unbuffer -u --yaml-out -y) jc_about_options=(--about -a) jc_about_mod_options=(--pretty -p --yaml-out -y --monochrome -m --force-color -C) diff --git a/completions/jc_zsh_completion.sh b/completions/jc_zsh_completion.sh index 4b7eb226..a8802b74 100644 --- a/completions/jc_zsh_completion.sh +++ b/completions/jc_zsh_completion.sh @@ -9,10 +9,11 @@ _jc() { jc_help_options jc_help_options_describe \ jc_special_options jc_special_options_describe - jc_commands=(acpi airport apt-cache apt-get arp blkid bluetoothctl cbt certbot chage cksum crontab curl date debconf-show df dig dmidecode dpkg du efibootmgr env ethtool file findmnt finger free git gpg hciconfig host id ifconfig iostat ip ipconfig iptables iw iwconfig jobs last lastb ls lsattr lsb_release lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat needrestart netstat nmcli nsd-control ntpq os-prober pacman pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum swapon sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 tune2fs udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc wg who xrandr zipinfo zpool) + jc_commands=(acpi airport amixer apt-cache apt-get arp blkid bluetoothctl cbt certbot chage cksum crontab curl date debconf-show df dig dmidecode dpkg du efibootmgr env ethtool file findmnt finger free git gpg hciconfig host id ifconfig iostat ip ipconfig iptables iw iwconfig jobs last lastb ls lsattr lsb_release lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat needrestart netstat nmcli nsd-control ntpq os-prober pacman pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum swapon sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 tune2fs udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc wg who xrandr zipinfo zpool) jc_commands_describe=( 'acpi:run "acpi" command with magic syntax.' 'airport:run "airport" command with magic syntax.' + 'amixer:run "amixer" command with magic syntax.' 'apt-cache:run "apt-cache" command with magic syntax.' 'apt-get:run "apt-get" command with magic syntax.' 'arp:run "arp" command with magic syntax.' @@ -124,11 +125,12 @@ _jc() { 'zipinfo:run "zipinfo" command with magic syntax.' 'zpool:run "zpool" command with magic syntax.' ) - jc_parsers=(--acpi --airport --airport-s --apt-cache-show --apt-get-sqq --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --curl-head --date --datetime-iso --debconf-show --df --dig --dir --dmidecode --dpkg-l --du --efibootmgr --email-address --env --ethtool --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --host --hosts --http-headers --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --ipconfig --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --kv-dup --last --ls --ls-s --lsattr --lsb-release --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --needrestart --netstat --nmcli --nsd-control --ntpq --openvpn --os-prober --os-release --pacman --passwd --path --path-list --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --pkg-index-apk --pkg-index-deb --plist --postconf --proc --proc-buddyinfo --proc-cmdline --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-tcp --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --resolve-conf --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --swapon --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --tune2fs --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --wg-show --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status) + jc_parsers=(--acpi --airport --airport-s --amixer --apt-cache-show --apt-get-sqq --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --curl-head --date --datetime-iso --debconf-show --df --dig --dir --dmidecode --dpkg-l --du --efibootmgr --email-address --env --ethtool --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --host --hosts --http-headers --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --ipconfig --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --kv-dup --last --ls --ls-s --lsattr --lsb-release --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --needrestart --netstat --nmcli --nsd-control --ntpq --openvpn --os-prober --os-release --pacman --passwd --path --path-list --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --pkg-index-apk --pkg-index-deb --plist --postconf --proc --proc-buddyinfo --proc-cmdline --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-tcp --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --resolve-conf --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --swapon --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --tune2fs --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --wg-show --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status) jc_parsers_describe=( '--acpi:`acpi` command parser' '--airport:`airport -I` command parser' '--airport-s:`airport -s` command parser' + '--amixer:`amixer` command parser' '--apt-cache-show:`apt-cache show` command parser' '--apt-get-sqq:`apt-get -sqq` command parser' '--arp:`arp` command parser' diff --git a/docs/parsers/amixer.md b/docs/parsers/amixer.md new file mode 100644 index 00000000..71473eb2 --- /dev/null +++ b/docs/parsers/amixer.md @@ -0,0 +1,117 @@ +[Home](https://kellyjonbrazil.github.io/jc/) + + +# jc.parsers.amixer + +jc - JSON Convert `amixer sget` command output parser + +Usage (cli): + + $ amixer sget | jc --amixer + $ amixer sget Master | jc --amixer + $ amixer sget Capture | jc --amixer + $ amixer sget Speakers | jc --amixer + +Usage (module): + + import jc + result = jc.parse('amixer', ) + +Schema: + + { + "control_name": string, + "capabilities": [ + string + ], + "playback_channels": [ + string + ], + "limits": { + "playback_min": integer, + "playback_max": integer + }, + "mono": { + "playback_value": integer, + "percentage": integer, + "db": float, + "status": boolean + } + } + +Examples: + + $ amixer sget Master | jc --amixer -p + { + "control_name": "Capture", + "capabilities": [ + "cvolume", + "cswitch" + ], + "playback_channels": [], + "limits": { + "playback_min": 0, + "playback_max": 63 + }, + "front_left": { + "playback_value": 63, + "percentage": 100, + "db": 30.0, + "status": true + }, + "front_right": { + "playback_value": 63, + "percentage": 100, + "db": 30.0, + "status": true + } + } + + $ amixer sget Master | jc --amixer -p -r + { + "control_name": "Master", + "capabilities": [ + "pvolume", + "pvolume-joined", + "pswitch", + "pswitch-joined" + ], + "playback_channels": [ + "Mono" + ], + "limits": { + "playback_min": "0", + "playback_max": "87" + }, + "mono": { + "playback_value": "87", + "percentage": "100%", + "db": "0.00db", + "status": "on" + } + } + + + +### parse + +```python +def parse(data: str, raw: bool = False, quiet: bool = False) -> Dict +``` + +Main text parsing function + +Parameters: + data: (string) text data to parse + raw: (boolean) unprocessed output if True + quiet: (boolean) suppress warning messages if True + +Returns: + Dictionary. Raw or processed structured data. + +### Parser Information +Compatibility: linux + +Source: [`jc/parsers/amixer.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/amixer.py) + +Version 1.0 by Eden Refael (edenraf@hotmail.com) diff --git a/jc/parsers/amixer.py b/jc/parsers/amixer.py index e65811bb..7b5423d5 100644 --- a/jc/parsers/amixer.py +++ b/jc/parsers/amixer.py @@ -10,7 +10,7 @@ Usage (cli): Usage (module): import jc - result = jc.parse('amixer', ) + result = jc.parse('amixer', ) Schema: @@ -20,7 +20,7 @@ Schema: string ], "playback_channels": [ - string + string ], "limits": { "playback_min": integer, @@ -85,10 +85,8 @@ Examples: "status": "on" } } - - """ -from typing import List, Dict +from typing import Dict import jc.utils from jc.utils import convert_to_int @@ -107,7 +105,7 @@ class info(): __version__ = info.version -def _process(proc_data: dict) -> dict: +def _process(proc_data: Dict) -> Dict: """ Processes raw structured data to match the schema requirements. @@ -147,20 +145,17 @@ def parse( data: str, raw: bool = False, quiet: bool = False -) -> List[Dict]: +) -> Dict: """ - Main text parsing function, The amixer is alsa mixer tool and output, Will work with Linux OS only. - + Main text parsing function Parameters: data: (string) text data to parse raw: (boolean) unprocessed output if True quiet: (boolean) suppress warning messages if True - Returns: - List of Dictionaries. Raw or processed structured data. - push test + Dictionary. Raw or processed structured data. """ """ The Algorithm for parsing the `amixer sget` command, Input Explained/Rules/Pseudo Algorithm: @@ -172,7 +167,6 @@ def parse( 3b. Playback channels - List of channels 4. Limits - We'll always have the minimum limit and the maximum limit. - Input Example: 1."":~$ amixer sget Capture Simple mixer control 'Capture',0 @@ -182,9 +176,6 @@ def parse( Front Left: Capture 63 [100%] [30.00db] [on] Front Right: Capture 63 [100%] [30.00db] [on] - - - 2."":~$ amixer sget Master Simple mixer control 'Master',0 Capabilities: pvolume pvolume-joined pswitch pswitch-joined @@ -192,10 +183,6 @@ def parse( Limits: Playback 0 - 87 Mono: Playback 87 [100%] [0.00db] [on] - - - - 3."":~$ amixer sget Speaker Simple mixer control 'Speaker',0 Capabilities: pvolume pswitch @@ -205,9 +192,6 @@ def parse( Front Left: Playback 87 [100%] [0.00db] [on] Front Right: Playback 87 [100%] [0.00db] [on] - - - 4."":~$ amixer sget Headphone Simple mixer control 'Headphone',0 Capabilities: pvolume pswitch @@ -224,7 +208,7 @@ def parse( jc.utils.input_type_check(data) # starts the parsing from here - mapping = {} + mapping: Dict = {} # split lines and than work on each line lines = data.splitlines() first_line = lines[0].strip() diff --git a/man/jc.1 b/man/jc.1 index 16b0ae41..62698bbb 100644 --- a/man/jc.1 +++ b/man/jc.1 @@ -1,4 +1,4 @@ -.TH jc 1 2024-11-25 1.25.4 "JSON Convert" +.TH jc 1 2024-12-20 1.25.5 "JSON Convert" .SH NAME \fBjc\fP \- JSON Convert JSONifies the output of many CLI tools, file-types, and strings @@ -52,6 +52,11 @@ Parsers: \fB--airport-s\fP `airport -s` command parser +.TP +.B +\fB--amixer\fP +`amixer` command parser + .TP .B \fB--apt-cache-show\fP From 7fda79d84111a507eb5f5d7c920807c34794b9a3 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Fri, 20 Dec 2024 16:31:38 -0800 Subject: [PATCH 03/32] allow parser to deal with null input --- jc/parsers/amixer.py | 94 +++++++++++++++++++++++--------------------- tests/test_amixer.py | 6 +++ 2 files changed, 56 insertions(+), 44 deletions(-) diff --git a/jc/parsers/amixer.py b/jc/parsers/amixer.py index 7b5423d5..baa22c49 100644 --- a/jc/parsers/amixer.py +++ b/jc/parsers/amixer.py @@ -90,6 +90,7 @@ from typing import Dict import jc.utils from jc.utils import convert_to_int +from jc.exceptions import ParseError class info(): """Provides parser metadata (version, author, etc.)""" @@ -115,6 +116,9 @@ def _process(proc_data: Dict) -> Dict: Returns: (dict) processed structured data adhering to the schema """ + if not proc_data: + return {} + # Initialize the processed dictionary processed = { "control_name": proc_data.get("control_name", ""), @@ -209,53 +213,55 @@ def parse( # starts the parsing from here mapping: Dict = {} - # split lines and than work on each line - lines = data.splitlines() - first_line = lines[0].strip() - # Extract the control name from the first line - if first_line.startswith("Simple mixer control"): - control_name = first_line.split("'")[1] - else: - raise ValueError("Invalid amixer output format: missing control name.") - # map the control name - mapping["control_name"] = control_name + if jc.utils.has_data(data): + # split lines and than work on each line + lines = data.splitlines() + first_line = lines[0].strip() - # Process subsequent lines for capabilities, channels, limits, and channel-specific mapping. - # gets the lines from the next line - because we already took care the first line. - for line in lines[1:]: - # strip the line (maybe there are white spaces in the begin&end) - line = line.strip() + # Extract the control name from the first line + if first_line.startswith("Simple mixer control"): + control_name = first_line.split("'")[1] + else: + raise ParseError("Invalid amixer output format: missing control name.") + # map the control name + mapping["control_name"] = control_name - if line.startswith("Capabilities:"): - mapping["capabilities"] = line.split(":")[1].strip().split() - elif line.startswith("Playback channels:"): - mapping["playback_channels"] = line.split(":")[1].strip().split(" - ") - elif line.startswith("Limits:"): - limits = line.split(":")[1].strip().split(" - ") - mapping["limits"] = { - "playback_min": limits[0].split()[1], - "playback_max": limits[1] - } - elif line.startswith("Mono:") or line.startswith("Front Left:") or line.startswith("Front Right:"): - # Identify the channel name and parse its information - channel_name = line.split(":")[0].strip().lower().replace(" ", "_") - channel_info = line.split(":")[1].strip() - # Example: "Playback 255 [100%] [0.00db] [on]" - channel_data = channel_info.split(" ") - if channel_data[0] == "": - continue - playback_value = channel_data[1] - percentage = channel_data[2].strip("[]") # Extract percentage e.g., "100%" - db_value = channel_data[3].strip("[]") # Extract db value e.g., "0.00db" - status = channel_data[4].strip("[]") # Extract status e.g., "on" or "off" + # Process subsequent lines for capabilities, channels, limits, and channel-specific mapping. + # gets the lines from the next line - because we already took care the first line. + for line in lines[1:]: + # strip the line (maybe there are white spaces in the begin&end) + line = line.strip() - # Store channel mapping in the dictionary - mapping[channel_name] = { - "playback_value": playback_value, - "percentage": percentage, - "db": db_value.lower(), - "status": status - } + if line.startswith("Capabilities:"): + mapping["capabilities"] = line.split(":")[1].strip().split() + elif line.startswith("Playback channels:"): + mapping["playback_channels"] = line.split(":")[1].strip().split(" - ") + elif line.startswith("Limits:"): + limits = line.split(":")[1].strip().split(" - ") + mapping["limits"] = { + "playback_min": limits[0].split()[1], + "playback_max": limits[1] + } + elif line.startswith("Mono:") or line.startswith("Front Left:") or line.startswith("Front Right:"): + # Identify the channel name and parse its information + channel_name = line.split(":")[0].strip().lower().replace(" ", "_") + channel_info = line.split(":")[1].strip() + # Example: "Playback 255 [100%] [0.00db] [on]" + channel_data = channel_info.split(" ") + if channel_data[0] == "": + continue + playback_value = channel_data[1] + percentage = channel_data[2].strip("[]") # Extract percentage e.g., "100%" + db_value = channel_data[3].strip("[]") # Extract db value e.g., "0.00db" + status = channel_data[4].strip("[]") # Extract status e.g., "on" or "off" + + # Store channel mapping in the dictionary + mapping[channel_name] = { + "playback_value": playback_value, + "percentage": percentage, + "db": db_value.lower(), + "status": status + } return mapping if raw else _process(mapping) diff --git a/tests/test_amixer.py b/tests/test_amixer.py index bfa21616..24bcff3c 100644 --- a/tests/test_amixer.py +++ b/tests/test_amixer.py @@ -22,6 +22,12 @@ class AmixerTests(unittest.TestCase): self.test_files_json = [f'{file}.json' for file in self.TEST_FILES_NAME] self.test_files_processed_json = [f'{file}-processed.json' for file in self.TEST_FILES_NAME] + def test_amixer_sget_nodata(self): + """ + Test 'amixer' with no data + """ + self.assertEqual(jc.parsers.amixer.parse('', quiet=True), {}) + def test_amixer_sget(self): for file_out, file_json, file_processed_json in zip(self.test_files_out, self.test_files_json, self.test_files_processed_json): From 896891ad9e65a68d794d9f7d7588ca825ad025bb Mon Sep 17 00:00:00 2001 From: pettai Date: Sun, 30 Mar 2025 21:33:45 +0200 Subject: [PATCH 04/32] Switch TZ to a generic name (#635) Switch TZ to a more generic name that works under minimal chrooted builds. (America/Los_Angeles, Pacific, PST, PST8PDT) This fixes pbuilder builds on Ubuntu Co-authored-by: Kelly Brazil --- runtests.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtests.sh b/runtests.sh index 05723cc4..2a97aa55 100755 --- a/runtests.sh +++ b/runtests.sh @@ -1,5 +1,5 @@ #!/bin/bash -# system should be in "America/Los_Angeles" timezone for all tests to pass -# ensure no local plugin parsers are installed for all tests to pass +# system should be in "America/Los_Angeles" (PST8PDT) timezone for all tests +# to pass ensure no local plugin parsers are installed for all tests to pass -TZ=America/Los_Angeles python3 -m unittest -v +TZ=PST8PDT python3 -m unittest -v From fb4b4eeb58721570c0c98eb0b3dbf2d762922425 Mon Sep 17 00:00:00 2001 From: Michel Lind Date: Sun, 30 Mar 2025 14:34:54 -0500 Subject: [PATCH 05/32] Adjust for removal of typing.ByteString in Python 3.14 (#639) `typing.ByteString` has been removed: https://docs.python.org/3.14/whatsnew/3.14.html The modernizing guide suggests `collections.abc.ByteString` which has also been removed; the recommendation is to use either: - just `bytes` - `collections.abc.Buffer` - a union of `bytes`, `bytesarray`, etc. https://typing.readthedocs.io/en/latest/guides/modernizing.html#modernizing-byte-string Per discussion, using `bytes` should suffice Signed-off-by: Michel Lind --- jc/parsers/pyedid/edid.py | 5 ++--- jc/parsers/pyedid/helpers/edid_helper.py | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/jc/parsers/pyedid/edid.py b/jc/parsers/pyedid/edid.py index dbed2f0a..13dbf8f7 100755 --- a/jc/parsers/pyedid/edid.py +++ b/jc/parsers/pyedid/edid.py @@ -4,7 +4,6 @@ Edid module import struct from collections import namedtuple -from typing import ByteString __all__ = ["Edid"] @@ -108,10 +107,10 @@ class Edid: ), ) - def __init__(self, edid: ByteString): + def __init__(self, edid: bytes): self._parse_edid(edid) - def _parse_edid(self, edid: ByteString): + def _parse_edid(self, edid: bytes): """Convert edid byte string to edid object""" if struct.calcsize(self._STRUCT_FORMAT) != 128: raise ValueError("Wrong edid size.") diff --git a/jc/parsers/pyedid/helpers/edid_helper.py b/jc/parsers/pyedid/helpers/edid_helper.py index b4165ca9..b8f28572 100644 --- a/jc/parsers/pyedid/helpers/edid_helper.py +++ b/jc/parsers/pyedid/helpers/edid_helper.py @@ -3,7 +3,7 @@ EDID helper """ from subprocess import CalledProcessError, check_output -from typing import ByteString, List +from typing import List __all__ = ["EdidHelper"] @@ -12,14 +12,14 @@ class EdidHelper: """Class for working with EDID data""" @staticmethod - def hex2bytes(hex_data: str) -> ByteString: + def hex2bytes(hex_data: str) -> bytes: """Convert hex EDID string to bytes Args: hex_data (str): hex edid string Returns: - ByteString: edid byte string + bytes: edid byte string """ # delete edid 1.3 additional block if len(hex_data) > 256: @@ -32,14 +32,14 @@ class EdidHelper: return bytes(numbers) @classmethod - def get_edids(cls) -> List[ByteString]: + def get_edids(cls) -> List[bytes]: """Get edids from xrandr Raises: `RuntimeError`: if error with retrieving xrandr util data Returns: - List[ByteString]: list with edids + List[bytes]: list with edids """ try: output = check_output(["xrandr", "--verbose"]) From e9ccedf0d7a745a41f4101199433378a26cb1e38 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Sun, 30 Mar 2025 12:38:41 -0700 Subject: [PATCH 06/32] doc update --- CHANGELOG | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index f4f159c0..6fd71dbf 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,9 @@ jc changelog -20241220 v1.25.5 +20250330 v1.25.5 - Add `amixer` command parser +- Fix typing for upcoming python v3.14 +- Fix timezone setting for tests to support minimal chrooted builds 20241125 v1.25.4 - Add `ipconfig` command parser (`ipconfig` for Windows) From 1c09289d95bf13917025ec66bacc0a863f267119 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Mon, 31 Mar 2025 12:16:45 -0700 Subject: [PATCH 07/32] fix time parser for missing centiseconds --- CHANGELOG | 3 ++- jc/parsers/time.py | 13 +++++++++---- tests/test_time.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6fd71dbf..14c04b31 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,8 @@ jc changelog -20250330 v1.25.5 +20250331 v1.25.5 - Add `amixer` command parser +- Fix `time` command parser for output that does not contain centiseconds - Fix typing for upcoming python v3.14 - Fix timezone setting for tests to support minimal chrooted builds diff --git a/jc/parsers/time.py b/jc/parsers/time.py index 539de8de..f93cbc02 100644 --- a/jc/parsers/time.py +++ b/jc/parsers/time.py @@ -132,7 +132,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.4' + version = '1.5' description = '`/usr/bin/time` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -171,13 +171,18 @@ def _process(proc_data): proc_data['command_being_timed'] = proc_data['command_being_timed'][1:-1] if 'elapsed_time' in proc_data: - proc_data['elapsed_time'] = proc_data['elapsed_time'].replace('.', ':') - *hours, minutes, seconds, centiseconds = proc_data['elapsed_time'].split(':') - proc_data['elapsed_time'] = proc_data['elapsed_time'][::-1].replace(':', '.', 1)[::-1] + *hours, minutes, ss = proc_data['elapsed_time'].split(':') + if '.' in ss: + seconds, centiseconds = ss.split('.') + else: + seconds = ss + centiseconds = '0' + if hours: proc_data['elapsed_time_hours'] = jc.utils.convert_to_int(hours[0]) else: proc_data['elapsed_time_hours'] = 0 + proc_data['elapsed_time_minutes'] = jc.utils.convert_to_int(minutes) proc_data['elapsed_time_seconds'] = jc.utils.convert_to_int(seconds) proc_data['elapsed_time_centiseconds'] = jc.utils.convert_to_int(centiseconds) diff --git a/tests/test_time.py b/tests/test_time.py index eaa08b0b..795e2c75 100644 --- a/tests/test_time.py +++ b/tests/test_time.py @@ -113,6 +113,37 @@ class MyTests(unittest.TestCase): """ self.assertEqual(jc.parsers.time.parse(self.osx_10_14_6_time_lp, quiet=True), self.osx_10_14_6_time_lp_json) + def test_time_no_centiseconds(self): + """ + Test 'time' output with no centiseconds data + """ + data = ''' Command being timed: "echo" + User time (seconds): 5156.20 + System time (seconds): 0.05 + Percent of CPU this job got: 99% + Elapsed (wall clock) time (h:mm:ss or m:ss): 1:25:56 + Average shared text size (kbytes): 0 + Average unshared data size (kbytes): 0 + Average stack size (kbytes): 0 + Average total size (kbytes): 0 + Maximum resident set size (kbytes): 21760 + Average resident set size (kbytes): 0 + Major (requiring I/O) page faults: 0 + Minor (reclaiming a frame) page faults: 4975 + Voluntary context switches: 1 + Involuntary context switches: 8159 + Swaps: 0 + File system inputs: 0 + File system outputs: 6272 + Socket messages sent: 0 + Socket messages received: 0 + Signals delivered: 0 + Page size (bytes): 4096 + Exit status: 0''' + + expected = {"command_being_timed":"echo","user_time":5156.2,"system_time":0.05,"cpu_percent":99,"elapsed_time":"1:25:56","average_shared_text_size":0,"average_unshared_data_size":0,"average_stack_size":0,"average_total_size":0,"maximum_resident_set_size":21760,"average_resident_set_size":0,"major_pagefaults":0,"minor_pagefaults":4975,"voluntary_context_switches":1,"involuntary_context_switches":8159,"swaps":0,"block_input_operations":0,"block_output_operations":6272,"messages_sent":0,"messages_received":0,"signals_delivered":0,"page_size":4096,"exit_status":0,"elapsed_time_hours":1,"elapsed_time_minutes":25,"elapsed_time_seconds":56,"elapsed_time_centiseconds":0,"elapsed_time_total_seconds":5156.0} + self.assertEqual(jc.parsers.time.parse(data, quiet=True), expected) + if __name__ == '__main__': unittest.main() From dbe1757a4818f79e947f25b65ec0ed960a6990ee Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Mon, 31 Mar 2025 14:16:17 -0700 Subject: [PATCH 08/32] add mountpoints array field and convert sizes to bytes --- jc/parsers/lsblk.py | 136 ++++++++++++++++++++++++++++---------------- 1 file changed, 88 insertions(+), 48 deletions(-) diff --git a/jc/parsers/lsblk.py b/jc/parsers/lsblk.py index f25e0e02..58713710 100644 --- a/jc/parsers/lsblk.py +++ b/jc/parsers/lsblk.py @@ -17,46 +17,53 @@ Schema: [ { - "name": string, - "maj_min": string, - "rm": boolean, - "size": string, - "ro": boolean, - "type": string, - "mountpoint": string, - "kname": string, - "fstype": string, - "label": string, - "uuid": string, - "partlabel": string, - "partuuid": string, - "ra": integer, - "model": string, - "serial": string, - "state": string, - "owner": string, - "group": string, - "mode": string, - "alignment": integer, - "min_io": integer, - "opt_io": integer, - "phy_sec": integer, - "log_sec": integer, - "rota": boolean, - "sched": string, - "rq_size": integer, - "disc_aln": integer, - "disc_gran": string, - "disc_max": string, - "disc_zero": boolean, - "wsame": string, - "wwn": string, - "rand": boolean, - "pkname": string, - "hctl": string, - "tran": string, - "rev": string, - "vendor": string + "name": string, + "maj_min": string, + "rm": boolean, + "size": string, + "size_bytes": integer + "ro": boolean, + "type": string, + "mountpoint": string, + "mountpoints": [ + string # null if no mountpoints + ], + "kname": string, + "fstype": string, + "label": string, + "uuid": string, + "partlabel": string, + "partuuid": string, + "ra": integer, + "model": string, + "serial": string, + "state": string, + "owner": string, + "group": string, + "mode": string, + "alignment": integer, + "min_io": integer, + "opt_io": integer, + "phy_sec": integer, + "log_sec": integer, + "rota": boolean, + "sched": string, + "rq_size": integer, + "disc_aln": integer, + "disc_gran": string, + "disc_gran_bytes": integer, + "disc_max": string, + "disc_max_bytes": integer, + "disc_zero": boolean, + "wsame": string, + "wsame_bytes": integer, + "wwn": string, + "rand": boolean, + "pkname": string, + "hctl": string, + "tran": string, + "rev": string, + "vendor": string } ] @@ -69,6 +76,7 @@ Examples: "maj_min": "8:0", "rm": false, "size": "20G", + "size_bytes": 20000000000, "ro": false, "type": "disk", "mountpoint": null @@ -78,6 +86,7 @@ Examples: "maj_min": "8:1", "rm": false, "size": "1G", + "size_bytes": 1000000000 "ro": false, "type": "part", "mountpoint": "/boot" @@ -95,6 +104,7 @@ Examples: "maj_min": "8:0", "rm": false, "size": "20G", + "size_bytes": 20000000000, "ro": false, "type": "disk", "mountpoint": null, @@ -121,9 +131,12 @@ Examples: "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", + "disc_gran_bytes": 0, "disc_max": "0B", + "disc_max_bytes": 0, "disc_zero": false, "wsame": "32M", + "wsame_bytes": 32000000, "wwn": null, "rand": true, "pkname": null, @@ -137,6 +150,7 @@ Examples: "maj_min": "8:1", "rm": false, "size": "1G", + "size_bytes": 1000000000 "ro": false, "type": "part", "mountpoint": "/boot", @@ -163,9 +177,12 @@ Examples: "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", + "disc_gran_bytes": 0, "disc_max": "0B", + "disc_max_bytes": 0, "disc_zero": false, "wsame": "32M", + "wsame_bytes": 32000000, "wwn": null, "rand": true, "pkname": "sda", @@ -187,6 +204,7 @@ Examples: "maj_min": "8:0", "rm": "0", "size": "20G", + "size_bytes": 20000000000, "ro": "0", "type": "disk", "mountpoint": null, @@ -213,9 +231,12 @@ Examples: "rq_size": "128", "disc_aln": "0", "disc_gran": "0B", + "disc_gran_bytes": 0, "disc_max": "0B", + "disc_max_bytes": 0, "disc_zero": "0", "wsame": "32M", + "wsame_bytes": 32000000, "wwn": null, "rand": "1", "pkname": null, @@ -229,6 +250,7 @@ Examples: "maj_min": "8:1", "rm": "0", "size": "1G", + "size_bytes": 1000000000 "ro": "0", "type": "part", "mountpoint": "/boot", @@ -255,9 +277,12 @@ Examples: "rq_size": "128", "disc_aln": "0", "disc_gran": "0B", + "disc_gran_bytes": 0, "disc_max": "0B", + "disc_max_bytes": 0, "disc_zero": "0", "wsame": "32M", + "wsame_bytes": 32000000, "wwn": null, "rand": "1", "pkname": "sda", @@ -275,7 +300,7 @@ import jc.parsers.universal class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.9' + version = '1.10' description = '`lsblk` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -304,14 +329,19 @@ def _process(proc_data): int_list = {'ra', 'alignment', 'min_io', 'opt_io', 'phy_sec', 'log_sec', 'rq_size', 'disc_aln'} + size_list = {'size', 'disc_gran', 'disc_max', 'wsame'} + for entry in proc_data: - for key in entry: + for key in entry.copy(): if key in bool_list: entry[key] = jc.utils.convert_to_bool(entry[key]) if key in int_list: entry[key] = jc.utils.convert_to_int(entry[key]) + if key in size_list: + entry[key + '_bytes'] = jc.utils.convert_size_to_int(entry[key]) + return proc_data @@ -335,6 +365,7 @@ def parse(data, raw=False, quiet=False): # Clear any blank lines cleandata = list(filter(None, data.splitlines())) raw_output = [] + new_list = [] if jc.utils.has_data(data): @@ -346,11 +377,20 @@ def parse(data, raw=False, quiet=False): raw_output = jc.parsers.universal.sparse_table_parse(cleandata) - # clean up non-ascii characters, if any + # find multiple mount points and add to a single entry for entry in raw_output: - entry['name'] = entry['name'].encode('ascii', errors='ignore').decode() + if entry['name']: + if 'mountpoints' in entry and entry['mountpoints']: + entry['mountpoints'] = [entry['mountpoints']] + new_list.append(entry) + elif 'mountpoints' in entry and entry['mountpoints']: + new_list[-1]['mountpoints'].append(entry['mountpoints']) - if raw: - return raw_output - else: - return _process(raw_output) + # clean up tree characters, if any + for entry in new_list: + tree_chars = ['`-', '|-', '├─', '└─'] + for chars in tree_chars: + if entry['name'][0:2] == chars: + entry['name'] = entry['name'][2:] + + return new_list if raw else _process(new_list) From 9efc014dce1170377fab6284a176cdadfba29efd Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Mon, 31 Mar 2025 14:17:51 -0700 Subject: [PATCH 09/32] doc update --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 14c04b31..2752b80e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,8 @@ jc changelog 20250331 v1.25.5 - Add `amixer` command parser +- Fix `lsblk` command parser to support multiple mountpoints. Also, added + byte conversions for size fields. - Fix `time` command parser for output that does not contain centiseconds - Fix typing for upcoming python v3.14 - Fix timezone setting for tests to support minimal chrooted builds From ca73076b565bb91995fc804a91b1d8f0424fda05 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Mon, 31 Mar 2025 14:29:27 -0700 Subject: [PATCH 10/32] make empty mountpoints list instead of null --- jc/parsers/lsblk.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/jc/parsers/lsblk.py b/jc/parsers/lsblk.py index 58713710..e082e89a 100644 --- a/jc/parsers/lsblk.py +++ b/jc/parsers/lsblk.py @@ -26,7 +26,7 @@ Schema: "type": string, "mountpoint": string, "mountpoints": [ - string # null if no mountpoints + string ], "kname": string, "fstype": string, @@ -380,8 +380,11 @@ def parse(data, raw=False, quiet=False): # find multiple mount points and add to a single entry for entry in raw_output: if entry['name']: - if 'mountpoints' in entry and entry['mountpoints']: - entry['mountpoints'] = [entry['mountpoints']] + if 'mountpoints' in entry: + if entry['mountpoints']: + entry['mountpoints'] = [entry['mountpoints']] + else: + entry['mountpoints'] = [] new_list.append(entry) elif 'mountpoints' in entry and entry['mountpoints']: new_list[-1]['mountpoints'].append(entry['mountpoints']) From ed3046bb1b362bc2dc2503e23444e3ffebd2c1b5 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Mon, 31 Mar 2025 16:34:38 -0700 Subject: [PATCH 11/32] remove type annotations since they are not used --- tests/test_amixer.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test_amixer.py b/tests/test_amixer.py index 24bcff3c..b5eb0937 100644 --- a/tests/test_amixer.py +++ b/tests/test_amixer.py @@ -32,20 +32,20 @@ class AmixerTests(unittest.TestCase): for file_out, file_json, file_processed_json in zip(self.test_files_out, self.test_files_json, self.test_files_processed_json): with open(file_out, 'r') as f: - amixer_sget_raw_output: str = f.read() + amixer_sget_raw_output = f.read() with open(file_json, 'r') as f: - expected_amixer_sget_json_output: str = f.read() - expected_amixer_sget_json_map: dict = json.loads(expected_amixer_sget_json_output) + expected_amixer_sget_json_output = f.read() + expected_amixer_sget_json_map = json.loads(expected_amixer_sget_json_output) with open(file_processed_json, 'r') as f: - expected_amixer_sget_processed_json_output: str = f.read() - expected_amixer_sget_processed_json_map: dict = json.loads(expected_amixer_sget_processed_json_output) + expected_amixer_sget_processed_json_output = f.read() + expected_amixer_sget_processed_json_map = json.loads(expected_amixer_sget_processed_json_output) # Tests for raw=True - amixer_sget_json_map: dict = jc.parse(self.AMIXER_CMD, amixer_sget_raw_output, raw=True, + amixer_sget_json_map = jc.parse(self.AMIXER_CMD, amixer_sget_raw_output, raw=True, quiet=True) self.assertEqual(amixer_sget_json_map, expected_amixer_sget_json_map) # Tests for raw=False process - amixer_sget_json_processed_map: dict = jc.parse(self.AMIXER_CMD, amixer_sget_raw_output, raw=False, + amixer_sget_json_processed_map = jc.parse(self.AMIXER_CMD, amixer_sget_raw_output, raw=False, quiet=True) self.assertEqual(amixer_sget_json_processed_map, expected_amixer_sget_processed_json_map) From 1182c9f2635a2814549b1dd4b4bc6af24ed1e499 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Mon, 31 Mar 2025 16:50:46 -0700 Subject: [PATCH 12/32] fix for missing dB value --- jc/parsers/amixer.py | 10 ++++++++-- tests/test_amixer.py | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/jc/parsers/amixer.py b/jc/parsers/amixer.py index baa22c49..b7818cf9 100644 --- a/jc/parsers/amixer.py +++ b/jc/parsers/amixer.py @@ -251,10 +251,16 @@ def parse( channel_data = channel_info.split(" ") if channel_data[0] == "": continue + + if "dB" in channel_data[3]: + db_value = channel_data[3].strip("[]") + status = channel_data[4].strip("[]") + else: + db_value = "0.0db" + status = channel_data[3].strip("[]") + playback_value = channel_data[1] percentage = channel_data[2].strip("[]") # Extract percentage e.g., "100%" - db_value = channel_data[3].strip("[]") # Extract db value e.g., "0.00db" - status = channel_data[4].strip("[]") # Extract status e.g., "on" or "off" # Store channel mapping in the dictionary mapping[channel_name] = { diff --git a/tests/test_amixer.py b/tests/test_amixer.py index b5eb0937..d333d54f 100644 --- a/tests/test_amixer.py +++ b/tests/test_amixer.py @@ -49,6 +49,22 @@ class AmixerTests(unittest.TestCase): quiet=True) self.assertEqual(amixer_sget_json_processed_map, expected_amixer_sget_processed_json_map) + def test_amixer_missing_db(self): + data = '''Simple mixer control 'Master',0 + Capabilities: pvolume pswitch pswitch-joined + Playback channels: Front Left - Front Right + Limits: Playback 0 - 65536 + Mono: + Front Left: Playback 55039 [84%] [on] + Front Right: Playback 54383 [83%] [on] +Simple mixer control 'Capture',0 + Capabilities: cvolume cswitch cswitch-joined + Capture channels: Front Left - Front Right + Limits: Capture 0 - 65536 + Front Left: Capture 24672 [38%] [on] + Front Right: Capture 24672 [38%] [on]''' + expected = {"control_name":"Master","capabilities":["cvolume","cswitch","cswitch-joined"],"playback_channels":["Front Left","Front Right"],"limits":{"playback_min":0,"playback_max":65536},"front_left":{"playback_value":24672,"percentage":38,"db":0.0,"status":True},"front_right":{"playback_value":24672,"percentage":38,"db":0.0,"status":True}} + self.assertEqual(expected, jc.parsers.amixer.parse(data, quiet=True)) if __name__ == '__main__': unittest.main() From 834acfb2d63f957fc67ad4273ba97b16a59b6325 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Mon, 31 Mar 2025 17:06:41 -0700 Subject: [PATCH 13/32] update lsblk tests --- tests/fixtures/centos-7.7/lsblk-allcols.json | 2 +- tests/fixtures/centos-7.7/lsblk.json | 2 +- tests/fixtures/ubuntu-18.04/lsblk-allcols.json | 2 +- tests/fixtures/ubuntu-18.04/lsblk.json | 2 +- tests/test_lsblk.py | 18 ++++++++++++++++++ 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/tests/fixtures/centos-7.7/lsblk-allcols.json b/tests/fixtures/centos-7.7/lsblk-allcols.json index 408dfc2c..2bb4a8ac 100644 --- a/tests/fixtures/centos-7.7/lsblk-allcols.json +++ b/tests/fixtures/centos-7.7/lsblk-allcols.json @@ -1 +1 @@ -[{"name": "sda", "maj_min": "8:0", "rm": false, "size": "20G", "ro": false, "type": "disk", "mountpoint": null, "kname": "sda", "fstype": null, "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 4096, "model": "VMware Virtual S", "serial": null, "state": "running", "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "deadline", "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "32M", "wwn": null, "rand": true, "pkname": null, "hctl": "0:0:0:0", "tran": "spi", "rev": "1.0", "vendor": "VMware,"}, {"name": "sda1", "maj_min": "8:1", "rm": false, "size": "1G", "ro": false, "type": "part", "mountpoint": "/boot", "kname": "sda1", "fstype": "xfs", "label": null, "uuid": "05d927bb-5875-49e3-ada1-7f46cb31c932", "partlabel": null, "partuuid": null, "ra": 4096, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "deadline", "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "32M", "wwn": null, "rand": true, "pkname": "sda", "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "sda2", "maj_min": "8:2", "rm": false, "size": "19G", "ro": false, "type": "part", "mountpoint": null, "kname": "sda2", "fstype": "LVM2_member", "label": null, "uuid": "3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM", "partlabel": null, "partuuid": null, "ra": 4096, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "deadline", "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "32M", "wwn": null, "rand": true, "pkname": "sda", "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "centos-root", "maj_min": "253:0", "rm": false, "size": "17G", "ro": false, "type": "lvm", "mountpoint": "/", "kname": "dm-0", "fstype": "xfs", "label": null, "uuid": "07d718ef-950c-4e5b-98e0-42a1147b77d9", "partlabel": null, "partuuid": null, "ra": 4096, "model": null, "serial": null, "state": "running", "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": null, "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "32M", "wwn": null, "rand": false, "pkname": "sda2", "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "centos-swap", "maj_min": "253:1", "rm": false, "size": "2G", "ro": false, "type": "lvm", "mountpoint": "[SWAP]", "kname": "dm-1", "fstype": "swap", "label": null, "uuid": "615eb89d-bcbf-46ad-80e3-c483ef5c931f", "partlabel": null, "partuuid": null, "ra": 4096, "model": null, "serial": null, "state": "running", "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": null, "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "32M", "wwn": null, "rand": false, "pkname": "sda2", "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "sr0", "maj_min": "11:0", "rm": true, "size": "1024M", "ro": false, "type": "rom", "mountpoint": null, "kname": "sr0", "fstype": null, "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": "VMware IDE CDR10", "serial": "10000000000000000001", "state": "running", "owner": "root", "group": "cdrom", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "deadline", "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": true, "pkname": null, "hctl": "2:0:0:0", "tran": "ata", "rev": "1.00", "vendor": "NECVMWar"}] +[{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"kname":"sda","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":4096,"model":"VMware Virtual S","serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":true,"pkname":null,"hctl":"0:0:0:0","tran":"spi","rev":"1.0","vendor":"VMware,","size_bytes":20000000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":32000000},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1G","ro":false,"type":"part","mountpoint":"/boot","kname":"sda1","fstype":"xfs","label":null,"uuid":"05d927bb-5875-49e3-ada1-7f46cb31c932","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":true,"pkname":"sda","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":1000000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":32000000},{"name":"sda2","maj_min":"8:2","rm":false,"size":"19G","ro":false,"type":"part","mountpoint":null,"kname":"sda2","fstype":"LVM2_member","label":null,"uuid":"3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":true,"pkname":"sda","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":19000000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":32000000},{"name":"centos-root","maj_min":"253:0","rm":false,"size":"17G","ro":false,"type":"lvm","mountpoint":"/","kname":"dm-0","fstype":"xfs","label":null,"uuid":"07d718ef-950c-4e5b-98e0-42a1147b77d9","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":null,"rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":false,"pkname":"sda2","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":17000000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":32000000},{"name":"centos-swap","maj_min":"253:1","rm":false,"size":"2G","ro":false,"type":"lvm","mountpoint":"[SWAP]","kname":"dm-1","fstype":"swap","label":null,"uuid":"615eb89d-bcbf-46ad-80e3-c483ef5c931f","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":null,"rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":false,"pkname":"sda2","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":2000000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":32000000},{"name":"sr0","maj_min":"11:0","rm":true,"size":"1024M","ro":false,"type":"rom","mountpoint":null,"kname":"sr0","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":"VMware IDE CDR10","serial":"10000000000000000001","state":"running","owner":"root","group":"cdrom","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":"2:0:0:0","tran":"ata","rev":"1.00","vendor":"NECVMWar","size_bytes":1024000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0}] diff --git a/tests/fixtures/centos-7.7/lsblk.json b/tests/fixtures/centos-7.7/lsblk.json index 43c3b0ae..5ba22007 100644 --- a/tests/fixtures/centos-7.7/lsblk.json +++ b/tests/fixtures/centos-7.7/lsblk.json @@ -1 +1 @@ -[{"name": "sda", "maj_min": "8:0", "rm": false, "size": "20G", "ro": false, "type": "disk", "mountpoint": null}, {"name": "sda1", "maj_min": "8:1", "rm": false, "size": "1G", "ro": false, "type": "part", "mountpoint": "/boot"}, {"name": "sda2", "maj_min": "8:2", "rm": false, "size": "19G", "ro": false, "type": "part", "mountpoint": null}, {"name": "centos-root", "maj_min": "253:0", "rm": false, "size": "17G", "ro": false, "type": "lvm", "mountpoint": "/"}, {"name": "centos-swap", "maj_min": "253:1", "rm": false, "size": "2G", "ro": false, "type": "lvm", "mountpoint": "[SWAP]"}, {"name": "sr0", "maj_min": "11:0", "rm": true, "size": "1024M", "ro": false, "type": "rom", "mountpoint": null}] +[{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"size_bytes":20000000000},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1G","ro":false,"type":"part","mountpoint":"/boot","size_bytes":1000000000},{"name":"sda2","maj_min":"8:2","rm":false,"size":"19G","ro":false,"type":"part","mountpoint":null,"size_bytes":19000000000},{"name":"centos-root","maj_min":"253:0","rm":false,"size":"17G","ro":false,"type":"lvm","mountpoint":"/","size_bytes":17000000000},{"name":"centos-swap","maj_min":"253:1","rm":false,"size":"2G","ro":false,"type":"lvm","mountpoint":"[SWAP]","size_bytes":2000000000},{"name":"sr0","maj_min":"11:0","rm":true,"size":"1024M","ro":false,"type":"rom","mountpoint":null,"size_bytes":1024000000}] diff --git a/tests/fixtures/ubuntu-18.04/lsblk-allcols.json b/tests/fixtures/ubuntu-18.04/lsblk-allcols.json index ff3d82ca..832bd20e 100644 --- a/tests/fixtures/ubuntu-18.04/lsblk-allcols.json +++ b/tests/fixtures/ubuntu-18.04/lsblk-allcols.json @@ -1 +1 @@ -[{"name": "fd0", "maj_min": "2:0", "rm": true, "size": "1.4M", "ro": false, "type": "disk", "mountpoint": null, "kname": "fd0", "fstype": null, "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "cfq", "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": true, "pkname": null, "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "loop0", "maj_min": "7:0", "rm": false, "size": "54.5M", "ro": true, "type": "loop", "mountpoint": "/snap/core18/1223", "kname": "loop0", "fstype": "squashfs", "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "none", "rq_size": 128, "disc_aln": 0, "disc_gran": "4K", "disc_max": "4G", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": false, "pkname": null, "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "loop1", "maj_min": "7:1", "rm": false, "size": "89.1M", "ro": true, "type": "loop", "mountpoint": "/snap/core/7917", "kname": "loop1", "fstype": "squashfs", "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "none", "rq_size": 128, "disc_aln": 0, "disc_gran": "4K", "disc_max": "4G", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": false, "pkname": null, "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "loop2", "maj_min": "7:2", "rm": false, "size": "11M", "ro": true, "type": "loop", "mountpoint": "/snap/slcli/383", "kname": "loop2", "fstype": "squashfs", "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "none", "rq_size": 128, "disc_aln": 0, "disc_gran": "4K", "disc_max": "4G", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": false, "pkname": null, "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "loop3", "maj_min": "7:3", "rm": false, "size": "8.6M", "ro": true, "type": "loop", "mountpoint": "/snap/doctl/215", "kname": "loop3", "fstype": "squashfs", "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "none", "rq_size": 128, "disc_aln": 0, "disc_gran": "4K", "disc_max": "4G", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": false, "pkname": null, "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "loop4", "maj_min": "7:4", "rm": false, "size": "89.1M", "ro": true, "type": "loop", "mountpoint": "/snap/core/8039", "kname": "loop4", "fstype": "squashfs", "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "none", "rq_size": 128, "disc_aln": 0, "disc_gran": "4K", "disc_max": "4G", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": false, "pkname": null, "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "loop5", "maj_min": "7:5", "rm": false, "size": "67M", "ro": true, "type": "loop", "mountpoint": "/snap/google-cloud-sdk/106", "kname": "loop5", "fstype": "squashfs", "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "none", "rq_size": 128, "disc_aln": 0, "disc_gran": "4K", "disc_max": "4G", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": false, "pkname": null, "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "loop6", "maj_min": "7:6", "rm": false, "size": "66.8M", "ro": true, "type": "loop", "mountpoint": "/snap/google-cloud-sdk/105", "kname": "loop6", "fstype": "squashfs", "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "none", "rq_size": 128, "disc_aln": 0, "disc_gran": "4K", "disc_max": "4G", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": false, "pkname": null, "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "loop7", "maj_min": "7:7", "rm": false, "size": "3.2M", "ro": true, "type": "loop", "mountpoint": "/snap/stress-ng/1046", "kname": "loop7", "fstype": "squashfs", "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "none", "rq_size": 128, "disc_aln": 0, "disc_gran": "4K", "disc_max": "4G", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": false, "pkname": null, "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "loop8", "maj_min": "7:8", "rm": false, "size": "8.7M", "ro": true, "type": "loop", "mountpoint": "/snap/doctl/222", "kname": "loop8", "fstype": "squashfs", "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "none", "rq_size": 128, "disc_aln": 0, "disc_gran": "4K", "disc_max": "4G", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": false, "pkname": null, "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "loop9", "maj_min": "7:9", "rm": false, "size": "54.5M", "ro": true, "type": "loop", "mountpoint": "/snap/core18/1265", "kname": "loop9", "fstype": "squashfs", "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "none", "rq_size": 128, "disc_aln": 0, "disc_gran": "4K", "disc_max": "4G", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": false, "pkname": null, "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "loop10", "maj_min": "7:10", "rm": false, "size": "3.2M", "ro": true, "type": "loop", "mountpoint": "/snap/stress-ng/1076", "kname": "loop10", "fstype": "squashfs", "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "none", "rq_size": 128, "disc_aln": 0, "disc_gran": "4K", "disc_max": "4G", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": false, "pkname": null, "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "sda", "maj_min": "8:0", "rm": false, "size": "20G", "ro": false, "type": "disk", "mountpoint": null, "kname": "sda", "fstype": null, "label": null, "uuid": null, "partlabel": null, "partuuid": null, "ra": 128, "model": "VMware Virtual S", "serial": null, "state": "running", "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "cfq", "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": true, "pkname": null, "hctl": "32:0:0:0", "tran": "spi", "rev": "1.0", "vendor": "VMware,"}, {"name": "sda1", "maj_min": "8:1", "rm": false, "size": "1M", "ro": false, "type": "part", "mountpoint": null, "kname": "sda1", "fstype": null, "label": null, "uuid": null, "partlabel": null, "partuuid": "e0614271-c211-4324-a5bc-8e6bcb66da43", "ra": 128, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "cfq", "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": true, "pkname": "sda", "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "sda2", "maj_min": "8:2", "rm": false, "size": "20G", "ro": false, "type": "part", "mountpoint": "/", "kname": "sda2", "fstype": "ext4", "label": null, "uuid": "011527a0-c72a-4c00-a50e-ee90da26b6e2", "partlabel": null, "partuuid": "744589e8-5711-4750-9984-c34d66f93879", "ra": 128, "model": null, "serial": null, "state": null, "owner": "root", "group": "disk", "mode": "brw-rw----", "alignment": 0, "min_io": 512, "opt_io": 0, "phy_sec": 512, "log_sec": 512, "rota": true, "sched": "cfq", "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": true, "pkname": "sda", "hctl": null, "tran": null, "rev": null, "vendor": null}, {"name": "sr0", "maj_min": "11:0", "rm": true, "size": "64.8M", "ro": false, "type": "rom", "mountpoint": null, "kname": "sr0", "fstype": "iso9660", "label": "CDROM", "uuid": "2019-08-12-10-17-03-63", "partlabel": null, "partuuid": null, "ra": 128, "model": "VMware SATA CD00", "serial": "00000000000000000001", "state": "running", "owner": "root", "group": "cdrom", "mode": "brw-rw----", "alignment": 0, "min_io": 2048, "opt_io": 0, "phy_sec": 2048, "log_sec": 2048, "rota": true, "sched": "cfq", "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": true, "pkname": null, "hctl": "2:0:0:0", "tran": "sata", "rev": "1.00", "vendor": "NECVMWar"}, {"name": "sr1", "maj_min": "11:1", "rm": true, "size": "848M", "ro": false, "type": "rom", "mountpoint": null, "kname": "sr1", "fstype": "iso9660", "label": "Ubuntu-Server 18.04.3 LTS amd64", "uuid": "2019-08-05-20-00-00-00", "partlabel": null, "partuuid": null, "ra": 128, "model": "VMware SATA CD01", "serial": "01000000000000000001", "state": "running", "owner": "root", "group": "cdrom", "mode": "brw-rw----", "alignment": 0, "min_io": 2048, "opt_io": 0, "phy_sec": 2048, "log_sec": 2048, "rota": true, "sched": "cfq", "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", "disc_max": "0B", "disc_zero": false, "wsame": "0B", "wwn": null, "rand": true, "pkname": null, "hctl": "3:0:0:0", "tran": "sata", "rev": "1.00", "vendor": "NECVMWar"}] +[{"name":"fd0","maj_min":"2:0","rm":true,"size":"1.4M","ro":false,"type":"disk","mountpoint":null,"kname":"fd0","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":1400000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"loop0","maj_min":"7:0","rm":false,"size":"54.5M","ro":true,"type":"loop","mountpoint":"/snap/core18/1223","kname":"loop0","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":54500000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop1","maj_min":"7:1","rm":false,"size":"89.1M","ro":true,"type":"loop","mountpoint":"/snap/core/7917","kname":"loop1","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":89100000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop2","maj_min":"7:2","rm":false,"size":"11M","ro":true,"type":"loop","mountpoint":"/snap/slcli/383","kname":"loop2","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":11000000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop3","maj_min":"7:3","rm":false,"size":"8.6M","ro":true,"type":"loop","mountpoint":"/snap/doctl/215","kname":"loop3","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":8600000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop4","maj_min":"7:4","rm":false,"size":"89.1M","ro":true,"type":"loop","mountpoint":"/snap/core/8039","kname":"loop4","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":89100000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop5","maj_min":"7:5","rm":false,"size":"67M","ro":true,"type":"loop","mountpoint":"/snap/google-cloud-sdk/106","kname":"loop5","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":67000000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop6","maj_min":"7:6","rm":false,"size":"66.8M","ro":true,"type":"loop","mountpoint":"/snap/google-cloud-sdk/105","kname":"loop6","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":66800000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop7","maj_min":"7:7","rm":false,"size":"3.2M","ro":true,"type":"loop","mountpoint":"/snap/stress-ng/1046","kname":"loop7","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":3200000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop8","maj_min":"7:8","rm":false,"size":"8.7M","ro":true,"type":"loop","mountpoint":"/snap/doctl/222","kname":"loop8","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":8700000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop9","maj_min":"7:9","rm":false,"size":"54.5M","ro":true,"type":"loop","mountpoint":"/snap/core18/1265","kname":"loop9","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":54500000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop10","maj_min":"7:10","rm":false,"size":"3.2M","ro":true,"type":"loop","mountpoint":"/snap/stress-ng/1076","kname":"loop10","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":3200000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"kname":"sda","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":"VMware Virtual S","serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":"32:0:0:0","tran":"spi","rev":"1.0","vendor":"VMware,","size_bytes":20000000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1M","ro":false,"type":"part","mountpoint":null,"kname":"sda1","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":"e0614271-c211-4324-a5bc-8e6bcb66da43","ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":"sda","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":1000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"sda2","maj_min":"8:2","rm":false,"size":"20G","ro":false,"type":"part","mountpoint":"/","kname":"sda2","fstype":"ext4","label":null,"uuid":"011527a0-c72a-4c00-a50e-ee90da26b6e2","partlabel":null,"partuuid":"744589e8-5711-4750-9984-c34d66f93879","ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":"sda","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":20000000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"sr0","maj_min":"11:0","rm":true,"size":"64.8M","ro":false,"type":"rom","mountpoint":null,"kname":"sr0","fstype":"iso9660","label":"CDROM","uuid":"2019-08-12-10-17-03-63","partlabel":null,"partuuid":null,"ra":128,"model":"VMware SATA CD00","serial":"00000000000000000001","state":"running","owner":"root","group":"cdrom","mode":"brw-rw----","alignment":0,"min_io":2048,"opt_io":0,"phy_sec":2048,"log_sec":2048,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":"2:0:0:0","tran":"sata","rev":"1.00","vendor":"NECVMWar","size_bytes":64800000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"sr1","maj_min":"11:1","rm":true,"size":"848M","ro":false,"type":"rom","mountpoint":null,"kname":"sr1","fstype":"iso9660","label":"Ubuntu-Server 18.04.3 LTS amd64","uuid":"2019-08-05-20-00-00-00","partlabel":null,"partuuid":null,"ra":128,"model":"VMware SATA CD01","serial":"01000000000000000001","state":"running","owner":"root","group":"cdrom","mode":"brw-rw----","alignment":0,"min_io":2048,"opt_io":0,"phy_sec":2048,"log_sec":2048,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":"3:0:0:0","tran":"sata","rev":"1.00","vendor":"NECVMWar","size_bytes":848000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0}] diff --git a/tests/fixtures/ubuntu-18.04/lsblk.json b/tests/fixtures/ubuntu-18.04/lsblk.json index 5fc629a0..343edf3e 100644 --- a/tests/fixtures/ubuntu-18.04/lsblk.json +++ b/tests/fixtures/ubuntu-18.04/lsblk.json @@ -1 +1 @@ -[{"name": "fd0", "maj_min": "2:0", "rm": true, "size": "1.4M", "ro": false, "type": "disk", "mountpoint": null}, {"name": "loop0", "maj_min": "7:0", "rm": false, "size": "54.5M", "ro": true, "type": "loop", "mountpoint": "/snap/core18/1223"}, {"name": "loop1", "maj_min": "7:1", "rm": false, "size": "11M", "ro": true, "type": "loop", "mountpoint": "/snap/slcli/383"}, {"name": "loop2", "maj_min": "7:2", "rm": false, "size": "88.7M", "ro": true, "type": "loop", "mountpoint": "/snap/core/7396"}, {"name": "loop3", "maj_min": "7:3", "rm": false, "size": "66.5M", "ro": true, "type": "loop", "mountpoint": "/snap/google-cloud-sdk/103"}, {"name": "loop4", "maj_min": "7:4", "rm": false, "size": "66.5M", "ro": true, "type": "loop", "mountpoint": "/snap/google-cloud-sdk/104"}, {"name": "loop5", "maj_min": "7:5", "rm": false, "size": "54.4M", "ro": true, "type": "loop", "mountpoint": "/snap/core18/1074"}, {"name": "loop7", "maj_min": "7:7", "rm": false, "size": "8.6M", "ro": true, "type": "loop", "mountpoint": "/snap/doctl/187"}, {"name": "loop8", "maj_min": "7:8", "rm": false, "size": "3.1M", "ro": true, "type": "loop", "mountpoint": "/snap/stress-ng/847"}, {"name": "loop9", "maj_min": "7:9", "rm": false, "size": "8.6M", "ro": true, "type": "loop", "mountpoint": "/snap/doctl/215"}, {"name": "loop10", "maj_min": "7:10", "rm": false, "size": "89.1M", "ro": true, "type": "loop", "mountpoint": "/snap/core/7917"}, {"name": "loop11", "maj_min": "7:11", "rm": false, "size": "3.2M", "ro": true, "type": "loop", "mountpoint": "/snap/stress-ng/924"}, {"name": "sda", "maj_min": "8:0", "rm": false, "size": "20G", "ro": false, "type": "disk", "mountpoint": null}, {"name": "sda1", "maj_min": "8:1", "rm": false, "size": "1M", "ro": false, "type": "part", "mountpoint": null}, {"name": "sda2", "maj_min": "8:2", "rm": false, "size": "20G", "ro": false, "type": "part", "mountpoint": "/"}, {"name": "sr0", "maj_min": "11:0", "rm": true, "size": "64.8M", "ro": false, "type": "rom", "mountpoint": null}, {"name": "sr1", "maj_min": "11:1", "rm": true, "size": "848M", "ro": false, "type": "rom", "mountpoint": null}] +[{"name":"fd0","maj_min":"2:0","rm":true,"size":"1.4M","ro":false,"type":"disk","mountpoint":null,"size_bytes":1400000},{"name":"loop0","maj_min":"7:0","rm":false,"size":"54.5M","ro":true,"type":"loop","mountpoint":"/snap/core18/1223","size_bytes":54500000},{"name":"loop1","maj_min":"7:1","rm":false,"size":"11M","ro":true,"type":"loop","mountpoint":"/snap/slcli/383","size_bytes":11000000},{"name":"loop2","maj_min":"7:2","rm":false,"size":"88.7M","ro":true,"type":"loop","mountpoint":"/snap/core/7396","size_bytes":88700000},{"name":"loop3","maj_min":"7:3","rm":false,"size":"66.5M","ro":true,"type":"loop","mountpoint":"/snap/google-cloud-sdk/103","size_bytes":66500000},{"name":"loop4","maj_min":"7:4","rm":false,"size":"66.5M","ro":true,"type":"loop","mountpoint":"/snap/google-cloud-sdk/104","size_bytes":66500000},{"name":"loop5","maj_min":"7:5","rm":false,"size":"54.4M","ro":true,"type":"loop","mountpoint":"/snap/core18/1074","size_bytes":54400000},{"name":"loop7","maj_min":"7:7","rm":false,"size":"8.6M","ro":true,"type":"loop","mountpoint":"/snap/doctl/187","size_bytes":8600000},{"name":"loop8","maj_min":"7:8","rm":false,"size":"3.1M","ro":true,"type":"loop","mountpoint":"/snap/stress-ng/847","size_bytes":3100000},{"name":"loop9","maj_min":"7:9","rm":false,"size":"8.6M","ro":true,"type":"loop","mountpoint":"/snap/doctl/215","size_bytes":8600000},{"name":"loop10","maj_min":"7:10","rm":false,"size":"89.1M","ro":true,"type":"loop","mountpoint":"/snap/core/7917","size_bytes":89100000},{"name":"loop11","maj_min":"7:11","rm":false,"size":"3.2M","ro":true,"type":"loop","mountpoint":"/snap/stress-ng/924","size_bytes":3200000},{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"size_bytes":20000000000},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1M","ro":false,"type":"part","mountpoint":null,"size_bytes":1000000},{"name":"sda2","maj_min":"8:2","rm":false,"size":"20G","ro":false,"type":"part","mountpoint":"/","size_bytes":20000000000},{"name":"sr0","maj_min":"11:0","rm":true,"size":"64.8M","ro":false,"type":"rom","mountpoint":null,"size_bytes":64800000},{"name":"sr1","maj_min":"11:1","rm":true,"size":"848M","ro":false,"type":"rom","mountpoint":null,"size_bytes":848000000}] diff --git a/tests/test_lsblk.py b/tests/test_lsblk.py index ca549971..a9eab374 100644 --- a/tests/test_lsblk.py +++ b/tests/test_lsblk.py @@ -65,6 +65,24 @@ class MyTests(unittest.TestCase): """ self.assertEqual(jc.parsers.lsblk.parse(self.ubuntu_18_4_lsblk_allcols, quiet=True), self.ubuntu_18_4_lsblk_allcols_json) + def test_lsblk_multiple_mountpoints(self): + """ + Test 'lsblk' with multiple mountpoints + """ + data = '''NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS +sda 8:0 0 5368709120000 0 disk +|-sda1 8:1 0 1048576 0 part +|-sda2 8:2 0 1073741824 0 part /boot +|-sda3 8:3 0 1073741824 0 part /boot/efi +`-sda4 8:4 0 51536461824 0 part + |-almalinux-root 253:0 0 36075208704 0 lvm / + |-almalinux-docker 253:1 0 1073741824 0 lvm /opt/docker + |-almalinux-home 253:2 0 5368709120 0 lvm /home + `-almalinux-opt 253:3 0 9017753600 0 lvm /var/lib/kafka + /opt +sr0 11:0 1 1073741312 0 rom''' + expected = [{"name":"sda","maj_min":"8:0","rm":False,"size":"5368709120000","ro":False,"type":"disk","mountpoints":[],"size_bytes":5368709120000},{"name":"sda1","maj_min":"8:1","rm":False,"size":"1048576","ro":False,"type":"part","mountpoints":[],"size_bytes":1048576},{"name":"sda2","maj_min":"8:2","rm":False,"size":"1073741824","ro":False,"type":"part","mountpoints":["/boot"],"size_bytes":1073741824},{"name":"sda3","maj_min":"8:3","rm":False,"size":"1073741824","ro":False,"type":"part","mountpoints":["/boot/efi"],"size_bytes":1073741824},{"name":"sda4","maj_min":"8:4","rm":False,"size":"51536461824","ro":False,"type":"part","mountpoints":[],"size_bytes":51536461824},{"name":"almalinux-root","maj_min":"253:0","rm":False,"size":"36075208704","ro":False,"type":"lvm","mountpoints":["/"],"size_bytes":36075208704},{"name":"almalinux-docker","maj_min":"253:1","rm":False,"size":"1073741824","ro":False,"type":"lvm","mountpoints":["/opt/docker"],"size_bytes":1073741824},{"name":"almalinux-home","maj_min":"253:2","rm":False,"size":"5368709120","ro":False,"type":"lvm","mountpoints":["/home"],"size_bytes":5368709120},{"name":"almalinux-opt","maj_min":"253:3","rm":False,"size":"9017753600","ro":False,"type":"lvm","mountpoints":["/var/lib/kafka","/opt"],"size_bytes":9017753600},{"name":"sr0","maj_min":"11:0","rm":True,"size":"1073741312","ro":False,"type":"rom","mountpoints":[],"size_bytes":1073741312}] + self.assertEqual(jc.parsers.lsblk.parse(data, quiet=True), expected) if __name__ == '__main__': unittest.main() From ebbd4e932047468c8fb4bffd06b7647e0d7488bb Mon Sep 17 00:00:00 2001 From: Jake Ob Date: Wed, 2 Apr 2025 21:32:19 +0300 Subject: [PATCH 14/32] Fix broken controller parser schema to include power state prop (#652) This commit fixes issue #627 Co-authored-by: Kelly Brazil --- jc/parsers/bluetoothctl.py | 5 +++ .../generic/bluetoothctl_controller_2.out | 20 +++++++++ tests/test_bluetoothctl.py | 43 ++++++++++++++++++- 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/generic/bluetoothctl_controller_2.out diff --git a/jc/parsers/bluetoothctl.py b/jc/parsers/bluetoothctl.py index 3d241334..370b1d9a 100644 --- a/jc/parsers/bluetoothctl.py +++ b/jc/parsers/bluetoothctl.py @@ -139,6 +139,7 @@ try: "alias": str, "class": str, "powered": str, + "power_state": str, "discoverable": str, "discoverable_timeout": str, "pairable": str, @@ -185,6 +186,7 @@ _controller_line_pattern = ( + r"|\s*Alias:\s*(?P.+)" + r"|\s*Class:\s*(?P.+)" + r"|\s*Powered:\s*(?P.+)" + + r"|\s*PowerState:\s*(?P.+)" + r"|\s*Discoverable:\s*(?P.+)" + r"|\s*DiscoverableTimeout:\s*(?P.+)" + r"|\s*Pairable:\s*(?P.+)" @@ -219,6 +221,7 @@ def _parse_controller(next_lines: List[str]) -> Optional[Controller]: "alias": '', "class": '', "powered": '', + "power_state": '', "discoverable": '', "discoverable_timeout": '', "pairable": '', @@ -261,6 +264,8 @@ def _parse_controller(next_lines: List[str]) -> Optional[Controller]: controller["class"] = matches["class"] elif matches["powered"]: controller["powered"] = matches["powered"] + elif matches["power_state"]: + controller["power_state"] = matches["power_state"] elif matches["discoverable"]: controller["discoverable"] = matches["discoverable"] elif matches["discoverable_timeout"]: diff --git a/tests/fixtures/generic/bluetoothctl_controller_2.out b/tests/fixtures/generic/bluetoothctl_controller_2.out new file mode 100644 index 00000000..1024227f --- /dev/null +++ b/tests/fixtures/generic/bluetoothctl_controller_2.out @@ -0,0 +1,20 @@ +Controller CC:52:AF:17:6A:E4 (public) + Manufacturer: 0x000f (15) + Version: 0x05 (5) + Name: starbase + Alias: starbase + Class: 0x006c010c (7078156) + Powered: yes + PowerState: on + Discoverable: no + DiscoverableTimeout: 0x000000b4 (180) + Pairable: no + UUID: Handsfree (0000111e-0000-1000-8000-00805f9b34fb) + UUID: Audio Source (0000110a-0000-1000-8000-00805f9b34fb) + UUID: Audio Sink (0000110b-0000-1000-8000-00805f9b34fb) + UUID: PnP Information (00001200-0000-1000-8000-00805f9b34fb) + UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb) + UUID: A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb) + UUID: Handsfree Audio Gateway (0000111f-0000-1000-8000-00805f9b34fb) + Modalias: usb:v1D6Bp0246d054F + Discovering: no diff --git a/tests/test_bluetoothctl.py b/tests/test_bluetoothctl.py index 1df04213..85076103 100644 --- a/tests/test_bluetoothctl.py +++ b/tests/test_bluetoothctl.py @@ -104,7 +104,48 @@ class BluetoothctlTests(unittest.TestCase): if actual: for k, v in expected.items(): self.assertEqual(v, actual[0][k], f"Controller regex failed on {k}") - + + def test_bluetoothctl_controller_2(self): + """ + Test 'bluetoothctl' with controller 2 + """ + + with open("tests/fixtures/generic/bluetoothctl_controller_2.out", "r") as f: + output = f.read() + + actual = parse(output, quiet=True) + + self.assertIsNotNone(actual) + self.assertIsNotNone(actual[0]) + + expected = { + "address": "CC:52:AF:17:6A:E4", + "is_public": True, + "name": "starbase", + "alias": "starbase", + "class": "0x006c010c (7078156)", + "powered": "yes", + "power_state": "on", + "discoverable": "no", + "discoverable_timeout": "0x000000b4 (180)", + "pairable": "no", + "uuids": [ + "Handsfree (0000111e-0000-1000-8000-00805f9b34fb)", + "Audio Source (0000110a-0000-1000-8000-00805f9b34fb)", + "Audio Sink (0000110b-0000-1000-8000-00805f9b34fb)", + "PnP Information (00001200-0000-1000-8000-00805f9b34fb)", + "A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)", + "A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb)", + "Handsfree Audio Gateway (0000111f-0000-1000-8000-00805f9b34fb)" + ], + "modalias": "usb:v1D6Bp0246d054F", + "discovering": "no" + } + + if actual: + for k, v in expected.items(): + self.assertEqual(v, actual[0][k], f"Controller regex failed on {k}") + def test_bluetoothctl_controller_with_manufacturer(self): """ Test 'bluetoothctl' with controller having manufacturer attr From 5394d7f62d0df132761416f87cafed1c26f9bed4 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 2 Apr 2025 11:37:24 -0700 Subject: [PATCH 15/32] doc update --- CHANGELOG | 3 ++- jc/parsers/bluetoothctl.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2752b80e..38774f41 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,8 @@ jc changelog -20250331 v1.25.5 +20250402 v1.25.5 - Add `amixer` command parser +- Fix `bluetoothctl` parser failing to parse controllers with power state prop - Fix `lsblk` command parser to support multiple mountpoints. Also, added byte conversions for size fields. - Fix `time` command parser for output that does not contain centiseconds diff --git a/jc/parsers/bluetoothctl.py b/jc/parsers/bluetoothctl.py index 370b1d9a..16943bcb 100644 --- a/jc/parsers/bluetoothctl.py +++ b/jc/parsers/bluetoothctl.py @@ -112,7 +112,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.3' + version = '1.4' description = '`bluetoothctl` command parser' author = 'Jake Ob' author_email = 'iakopap at gmail.com' From 65aa6c1a9a8ba915e7e852873fcc85bb1eaad21d Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 2 Apr 2025 12:06:59 -0700 Subject: [PATCH 16/32] update copyright date --- jc/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jc/cli.py b/jc/cli.py index 72ef7997..855aaa78 100644 --- a/jc/cli.py +++ b/jc/cli.py @@ -52,7 +52,7 @@ class info(): author: str = 'Kelly Brazil' author_email: str = 'kellyjonbrazil@gmail.com' website: str = 'https://github.com/kellyjonbrazil/jc' - copyright: str = '© 2019-2024 Kelly Brazil' + copyright: str = '© 2019-2025 Kelly Brazil' license: str = 'MIT License' From 5cde110afb64004553bf0359ff979bf25d84e488 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Fri, 4 Apr 2025 16:14:20 -0700 Subject: [PATCH 17/32] set bytes conversion to posix mode --- jc/parsers/lsblk.py | 2 +- tests/fixtures/centos-7.7/lsblk-allcols.json | 2 +- tests/fixtures/centos-7.7/lsblk.json | 2 +- tests/fixtures/ubuntu-18.04/lsblk-allcols.json | 2 +- tests/fixtures/ubuntu-18.04/lsblk.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/jc/parsers/lsblk.py b/jc/parsers/lsblk.py index e082e89a..a56bdb9a 100644 --- a/jc/parsers/lsblk.py +++ b/jc/parsers/lsblk.py @@ -340,7 +340,7 @@ def _process(proc_data): entry[key] = jc.utils.convert_to_int(entry[key]) if key in size_list: - entry[key + '_bytes'] = jc.utils.convert_size_to_int(entry[key]) + entry[key + '_bytes'] = jc.utils.convert_size_to_int(entry[key], posix_mode=True) return proc_data diff --git a/tests/fixtures/centos-7.7/lsblk-allcols.json b/tests/fixtures/centos-7.7/lsblk-allcols.json index 2bb4a8ac..742ce7bf 100644 --- a/tests/fixtures/centos-7.7/lsblk-allcols.json +++ b/tests/fixtures/centos-7.7/lsblk-allcols.json @@ -1 +1 @@ -[{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"kname":"sda","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":4096,"model":"VMware Virtual S","serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":true,"pkname":null,"hctl":"0:0:0:0","tran":"spi","rev":"1.0","vendor":"VMware,","size_bytes":20000000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":32000000},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1G","ro":false,"type":"part","mountpoint":"/boot","kname":"sda1","fstype":"xfs","label":null,"uuid":"05d927bb-5875-49e3-ada1-7f46cb31c932","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":true,"pkname":"sda","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":1000000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":32000000},{"name":"sda2","maj_min":"8:2","rm":false,"size":"19G","ro":false,"type":"part","mountpoint":null,"kname":"sda2","fstype":"LVM2_member","label":null,"uuid":"3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":true,"pkname":"sda","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":19000000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":32000000},{"name":"centos-root","maj_min":"253:0","rm":false,"size":"17G","ro":false,"type":"lvm","mountpoint":"/","kname":"dm-0","fstype":"xfs","label":null,"uuid":"07d718ef-950c-4e5b-98e0-42a1147b77d9","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":null,"rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":false,"pkname":"sda2","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":17000000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":32000000},{"name":"centos-swap","maj_min":"253:1","rm":false,"size":"2G","ro":false,"type":"lvm","mountpoint":"[SWAP]","kname":"dm-1","fstype":"swap","label":null,"uuid":"615eb89d-bcbf-46ad-80e3-c483ef5c931f","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":null,"rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":false,"pkname":"sda2","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":2000000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":32000000},{"name":"sr0","maj_min":"11:0","rm":true,"size":"1024M","ro":false,"type":"rom","mountpoint":null,"kname":"sr0","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":"VMware IDE CDR10","serial":"10000000000000000001","state":"running","owner":"root","group":"cdrom","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":"2:0:0:0","tran":"ata","rev":"1.00","vendor":"NECVMWar","size_bytes":1024000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0}] +[{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"kname":"sda","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":4096,"model":"VMware Virtual S","serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":true,"pkname":null,"hctl":"0:0:0:0","tran":"spi","rev":"1.0","vendor":"VMware,","size_bytes":21474836480,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":33554432},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1G","ro":false,"type":"part","mountpoint":"/boot","kname":"sda1","fstype":"xfs","label":null,"uuid":"05d927bb-5875-49e3-ada1-7f46cb31c932","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":true,"pkname":"sda","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":1073741824,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":33554432},{"name":"sda2","maj_min":"8:2","rm":false,"size":"19G","ro":false,"type":"part","mountpoint":null,"kname":"sda2","fstype":"LVM2_member","label":null,"uuid":"3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":true,"pkname":"sda","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":20401094656,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":33554432},{"name":"centos-root","maj_min":"253:0","rm":false,"size":"17G","ro":false,"type":"lvm","mountpoint":"/","kname":"dm-0","fstype":"xfs","label":null,"uuid":"07d718ef-950c-4e5b-98e0-42a1147b77d9","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":null,"rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":false,"pkname":"sda2","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":18253611008,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":33554432},{"name":"centos-swap","maj_min":"253:1","rm":false,"size":"2G","ro":false,"type":"lvm","mountpoint":"[SWAP]","kname":"dm-1","fstype":"swap","label":null,"uuid":"615eb89d-bcbf-46ad-80e3-c483ef5c931f","partlabel":null,"partuuid":null,"ra":4096,"model":null,"serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":null,"rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"32M","wwn":null,"rand":false,"pkname":"sda2","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":2147483648,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":33554432},{"name":"sr0","maj_min":"11:0","rm":true,"size":"1024M","ro":false,"type":"rom","mountpoint":null,"kname":"sr0","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":"VMware IDE CDR10","serial":"10000000000000000001","state":"running","owner":"root","group":"cdrom","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"deadline","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":"2:0:0:0","tran":"ata","rev":"1.00","vendor":"NECVMWar","size_bytes":1073741824,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0}] diff --git a/tests/fixtures/centos-7.7/lsblk.json b/tests/fixtures/centos-7.7/lsblk.json index 5ba22007..c5cdb169 100644 --- a/tests/fixtures/centos-7.7/lsblk.json +++ b/tests/fixtures/centos-7.7/lsblk.json @@ -1 +1 @@ -[{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"size_bytes":20000000000},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1G","ro":false,"type":"part","mountpoint":"/boot","size_bytes":1000000000},{"name":"sda2","maj_min":"8:2","rm":false,"size":"19G","ro":false,"type":"part","mountpoint":null,"size_bytes":19000000000},{"name":"centos-root","maj_min":"253:0","rm":false,"size":"17G","ro":false,"type":"lvm","mountpoint":"/","size_bytes":17000000000},{"name":"centos-swap","maj_min":"253:1","rm":false,"size":"2G","ro":false,"type":"lvm","mountpoint":"[SWAP]","size_bytes":2000000000},{"name":"sr0","maj_min":"11:0","rm":true,"size":"1024M","ro":false,"type":"rom","mountpoint":null,"size_bytes":1024000000}] +[{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"size_bytes":21474836480},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1G","ro":false,"type":"part","mountpoint":"/boot","size_bytes":1073741824},{"name":"sda2","maj_min":"8:2","rm":false,"size":"19G","ro":false,"type":"part","mountpoint":null,"size_bytes":20401094656},{"name":"centos-root","maj_min":"253:0","rm":false,"size":"17G","ro":false,"type":"lvm","mountpoint":"/","size_bytes":18253611008},{"name":"centos-swap","maj_min":"253:1","rm":false,"size":"2G","ro":false,"type":"lvm","mountpoint":"[SWAP]","size_bytes":2147483648},{"name":"sr0","maj_min":"11:0","rm":true,"size":"1024M","ro":false,"type":"rom","mountpoint":null,"size_bytes":1073741824}] diff --git a/tests/fixtures/ubuntu-18.04/lsblk-allcols.json b/tests/fixtures/ubuntu-18.04/lsblk-allcols.json index 832bd20e..359d3d47 100644 --- a/tests/fixtures/ubuntu-18.04/lsblk-allcols.json +++ b/tests/fixtures/ubuntu-18.04/lsblk-allcols.json @@ -1 +1 @@ -[{"name":"fd0","maj_min":"2:0","rm":true,"size":"1.4M","ro":false,"type":"disk","mountpoint":null,"kname":"fd0","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":1400000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"loop0","maj_min":"7:0","rm":false,"size":"54.5M","ro":true,"type":"loop","mountpoint":"/snap/core18/1223","kname":"loop0","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":54500000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop1","maj_min":"7:1","rm":false,"size":"89.1M","ro":true,"type":"loop","mountpoint":"/snap/core/7917","kname":"loop1","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":89100000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop2","maj_min":"7:2","rm":false,"size":"11M","ro":true,"type":"loop","mountpoint":"/snap/slcli/383","kname":"loop2","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":11000000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop3","maj_min":"7:3","rm":false,"size":"8.6M","ro":true,"type":"loop","mountpoint":"/snap/doctl/215","kname":"loop3","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":8600000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop4","maj_min":"7:4","rm":false,"size":"89.1M","ro":true,"type":"loop","mountpoint":"/snap/core/8039","kname":"loop4","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":89100000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop5","maj_min":"7:5","rm":false,"size":"67M","ro":true,"type":"loop","mountpoint":"/snap/google-cloud-sdk/106","kname":"loop5","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":67000000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop6","maj_min":"7:6","rm":false,"size":"66.8M","ro":true,"type":"loop","mountpoint":"/snap/google-cloud-sdk/105","kname":"loop6","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":66800000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop7","maj_min":"7:7","rm":false,"size":"3.2M","ro":true,"type":"loop","mountpoint":"/snap/stress-ng/1046","kname":"loop7","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":3200000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop8","maj_min":"7:8","rm":false,"size":"8.7M","ro":true,"type":"loop","mountpoint":"/snap/doctl/222","kname":"loop8","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":8700000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop9","maj_min":"7:9","rm":false,"size":"54.5M","ro":true,"type":"loop","mountpoint":"/snap/core18/1265","kname":"loop9","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":54500000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"loop10","maj_min":"7:10","rm":false,"size":"3.2M","ro":true,"type":"loop","mountpoint":"/snap/stress-ng/1076","kname":"loop10","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":3200000,"disc_gran_bytes":4000,"disc_max_bytes":4000000000,"wsame_bytes":0},{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"kname":"sda","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":"VMware Virtual S","serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":"32:0:0:0","tran":"spi","rev":"1.0","vendor":"VMware,","size_bytes":20000000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1M","ro":false,"type":"part","mountpoint":null,"kname":"sda1","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":"e0614271-c211-4324-a5bc-8e6bcb66da43","ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":"sda","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":1000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"sda2","maj_min":"8:2","rm":false,"size":"20G","ro":false,"type":"part","mountpoint":"/","kname":"sda2","fstype":"ext4","label":null,"uuid":"011527a0-c72a-4c00-a50e-ee90da26b6e2","partlabel":null,"partuuid":"744589e8-5711-4750-9984-c34d66f93879","ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":"sda","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":20000000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"sr0","maj_min":"11:0","rm":true,"size":"64.8M","ro":false,"type":"rom","mountpoint":null,"kname":"sr0","fstype":"iso9660","label":"CDROM","uuid":"2019-08-12-10-17-03-63","partlabel":null,"partuuid":null,"ra":128,"model":"VMware SATA CD00","serial":"00000000000000000001","state":"running","owner":"root","group":"cdrom","mode":"brw-rw----","alignment":0,"min_io":2048,"opt_io":0,"phy_sec":2048,"log_sec":2048,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":"2:0:0:0","tran":"sata","rev":"1.00","vendor":"NECVMWar","size_bytes":64800000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"sr1","maj_min":"11:1","rm":true,"size":"848M","ro":false,"type":"rom","mountpoint":null,"kname":"sr1","fstype":"iso9660","label":"Ubuntu-Server 18.04.3 LTS amd64","uuid":"2019-08-05-20-00-00-00","partlabel":null,"partuuid":null,"ra":128,"model":"VMware SATA CD01","serial":"01000000000000000001","state":"running","owner":"root","group":"cdrom","mode":"brw-rw----","alignment":0,"min_io":2048,"opt_io":0,"phy_sec":2048,"log_sec":2048,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":"3:0:0:0","tran":"sata","rev":"1.00","vendor":"NECVMWar","size_bytes":848000000,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0}] +[{"name":"fd0","maj_min":"2:0","rm":true,"size":"1.4M","ro":false,"type":"disk","mountpoint":null,"kname":"fd0","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":1468006,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"loop0","maj_min":"7:0","rm":false,"size":"54.5M","ro":true,"type":"loop","mountpoint":"/snap/core18/1223","kname":"loop0","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":57147392,"disc_gran_bytes":4096,"disc_max_bytes":4294967296,"wsame_bytes":0},{"name":"loop1","maj_min":"7:1","rm":false,"size":"89.1M","ro":true,"type":"loop","mountpoint":"/snap/core/7917","kname":"loop1","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":93428121,"disc_gran_bytes":4096,"disc_max_bytes":4294967296,"wsame_bytes":0},{"name":"loop2","maj_min":"7:2","rm":false,"size":"11M","ro":true,"type":"loop","mountpoint":"/snap/slcli/383","kname":"loop2","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":11534336,"disc_gran_bytes":4096,"disc_max_bytes":4294967296,"wsame_bytes":0},{"name":"loop3","maj_min":"7:3","rm":false,"size":"8.6M","ro":true,"type":"loop","mountpoint":"/snap/doctl/215","kname":"loop3","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":9017753,"disc_gran_bytes":4096,"disc_max_bytes":4294967296,"wsame_bytes":0},{"name":"loop4","maj_min":"7:4","rm":false,"size":"89.1M","ro":true,"type":"loop","mountpoint":"/snap/core/8039","kname":"loop4","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":93428121,"disc_gran_bytes":4096,"disc_max_bytes":4294967296,"wsame_bytes":0},{"name":"loop5","maj_min":"7:5","rm":false,"size":"67M","ro":true,"type":"loop","mountpoint":"/snap/google-cloud-sdk/106","kname":"loop5","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":70254592,"disc_gran_bytes":4096,"disc_max_bytes":4294967296,"wsame_bytes":0},{"name":"loop6","maj_min":"7:6","rm":false,"size":"66.8M","ro":true,"type":"loop","mountpoint":"/snap/google-cloud-sdk/105","kname":"loop6","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":70044876,"disc_gran_bytes":4096,"disc_max_bytes":4294967296,"wsame_bytes":0},{"name":"loop7","maj_min":"7:7","rm":false,"size":"3.2M","ro":true,"type":"loop","mountpoint":"/snap/stress-ng/1046","kname":"loop7","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":3355443,"disc_gran_bytes":4096,"disc_max_bytes":4294967296,"wsame_bytes":0},{"name":"loop8","maj_min":"7:8","rm":false,"size":"8.7M","ro":true,"type":"loop","mountpoint":"/snap/doctl/222","kname":"loop8","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":9122611,"disc_gran_bytes":4096,"disc_max_bytes":4294967296,"wsame_bytes":0},{"name":"loop9","maj_min":"7:9","rm":false,"size":"54.5M","ro":true,"type":"loop","mountpoint":"/snap/core18/1265","kname":"loop9","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":57147392,"disc_gran_bytes":4096,"disc_max_bytes":4294967296,"wsame_bytes":0},{"name":"loop10","maj_min":"7:10","rm":false,"size":"3.2M","ro":true,"type":"loop","mountpoint":"/snap/stress-ng/1076","kname":"loop10","fstype":"squashfs","label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"none","rq_size":128,"disc_aln":0,"disc_gran":"4K","disc_max":"4G","disc_zero":false,"wsame":"0B","wwn":null,"rand":false,"pkname":null,"hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":3355443,"disc_gran_bytes":4096,"disc_max_bytes":4294967296,"wsame_bytes":0},{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"kname":"sda","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":null,"ra":128,"model":"VMware Virtual S","serial":null,"state":"running","owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":"32:0:0:0","tran":"spi","rev":"1.0","vendor":"VMware,","size_bytes":21474836480,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1M","ro":false,"type":"part","mountpoint":null,"kname":"sda1","fstype":null,"label":null,"uuid":null,"partlabel":null,"partuuid":"e0614271-c211-4324-a5bc-8e6bcb66da43","ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":"sda","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":1048576,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"sda2","maj_min":"8:2","rm":false,"size":"20G","ro":false,"type":"part","mountpoint":"/","kname":"sda2","fstype":"ext4","label":null,"uuid":"011527a0-c72a-4c00-a50e-ee90da26b6e2","partlabel":null,"partuuid":"744589e8-5711-4750-9984-c34d66f93879","ra":128,"model":null,"serial":null,"state":null,"owner":"root","group":"disk","mode":"brw-rw----","alignment":0,"min_io":512,"opt_io":0,"phy_sec":512,"log_sec":512,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":"sda","hctl":null,"tran":null,"rev":null,"vendor":null,"size_bytes":21474836480,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"sr0","maj_min":"11:0","rm":true,"size":"64.8M","ro":false,"type":"rom","mountpoint":null,"kname":"sr0","fstype":"iso9660","label":"CDROM","uuid":"2019-08-12-10-17-03-63","partlabel":null,"partuuid":null,"ra":128,"model":"VMware SATA CD00","serial":"00000000000000000001","state":"running","owner":"root","group":"cdrom","mode":"brw-rw----","alignment":0,"min_io":2048,"opt_io":0,"phy_sec":2048,"log_sec":2048,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":"2:0:0:0","tran":"sata","rev":"1.00","vendor":"NECVMWar","size_bytes":67947724,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0},{"name":"sr1","maj_min":"11:1","rm":true,"size":"848M","ro":false,"type":"rom","mountpoint":null,"kname":"sr1","fstype":"iso9660","label":"Ubuntu-Server 18.04.3 LTS amd64","uuid":"2019-08-05-20-00-00-00","partlabel":null,"partuuid":null,"ra":128,"model":"VMware SATA CD01","serial":"01000000000000000001","state":"running","owner":"root","group":"cdrom","mode":"brw-rw----","alignment":0,"min_io":2048,"opt_io":0,"phy_sec":2048,"log_sec":2048,"rota":true,"sched":"cfq","rq_size":128,"disc_aln":0,"disc_gran":"0B","disc_max":"0B","disc_zero":false,"wsame":"0B","wwn":null,"rand":true,"pkname":null,"hctl":"3:0:0:0","tran":"sata","rev":"1.00","vendor":"NECVMWar","size_bytes":889192448,"disc_gran_bytes":0,"disc_max_bytes":0,"wsame_bytes":0}] diff --git a/tests/fixtures/ubuntu-18.04/lsblk.json b/tests/fixtures/ubuntu-18.04/lsblk.json index 343edf3e..d710d02f 100644 --- a/tests/fixtures/ubuntu-18.04/lsblk.json +++ b/tests/fixtures/ubuntu-18.04/lsblk.json @@ -1 +1 @@ -[{"name":"fd0","maj_min":"2:0","rm":true,"size":"1.4M","ro":false,"type":"disk","mountpoint":null,"size_bytes":1400000},{"name":"loop0","maj_min":"7:0","rm":false,"size":"54.5M","ro":true,"type":"loop","mountpoint":"/snap/core18/1223","size_bytes":54500000},{"name":"loop1","maj_min":"7:1","rm":false,"size":"11M","ro":true,"type":"loop","mountpoint":"/snap/slcli/383","size_bytes":11000000},{"name":"loop2","maj_min":"7:2","rm":false,"size":"88.7M","ro":true,"type":"loop","mountpoint":"/snap/core/7396","size_bytes":88700000},{"name":"loop3","maj_min":"7:3","rm":false,"size":"66.5M","ro":true,"type":"loop","mountpoint":"/snap/google-cloud-sdk/103","size_bytes":66500000},{"name":"loop4","maj_min":"7:4","rm":false,"size":"66.5M","ro":true,"type":"loop","mountpoint":"/snap/google-cloud-sdk/104","size_bytes":66500000},{"name":"loop5","maj_min":"7:5","rm":false,"size":"54.4M","ro":true,"type":"loop","mountpoint":"/snap/core18/1074","size_bytes":54400000},{"name":"loop7","maj_min":"7:7","rm":false,"size":"8.6M","ro":true,"type":"loop","mountpoint":"/snap/doctl/187","size_bytes":8600000},{"name":"loop8","maj_min":"7:8","rm":false,"size":"3.1M","ro":true,"type":"loop","mountpoint":"/snap/stress-ng/847","size_bytes":3100000},{"name":"loop9","maj_min":"7:9","rm":false,"size":"8.6M","ro":true,"type":"loop","mountpoint":"/snap/doctl/215","size_bytes":8600000},{"name":"loop10","maj_min":"7:10","rm":false,"size":"89.1M","ro":true,"type":"loop","mountpoint":"/snap/core/7917","size_bytes":89100000},{"name":"loop11","maj_min":"7:11","rm":false,"size":"3.2M","ro":true,"type":"loop","mountpoint":"/snap/stress-ng/924","size_bytes":3200000},{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"size_bytes":20000000000},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1M","ro":false,"type":"part","mountpoint":null,"size_bytes":1000000},{"name":"sda2","maj_min":"8:2","rm":false,"size":"20G","ro":false,"type":"part","mountpoint":"/","size_bytes":20000000000},{"name":"sr0","maj_min":"11:0","rm":true,"size":"64.8M","ro":false,"type":"rom","mountpoint":null,"size_bytes":64800000},{"name":"sr1","maj_min":"11:1","rm":true,"size":"848M","ro":false,"type":"rom","mountpoint":null,"size_bytes":848000000}] +[{"name":"fd0","maj_min":"2:0","rm":true,"size":"1.4M","ro":false,"type":"disk","mountpoint":null,"size_bytes":1468006},{"name":"loop0","maj_min":"7:0","rm":false,"size":"54.5M","ro":true,"type":"loop","mountpoint":"/snap/core18/1223","size_bytes":57147392},{"name":"loop1","maj_min":"7:1","rm":false,"size":"11M","ro":true,"type":"loop","mountpoint":"/snap/slcli/383","size_bytes":11534336},{"name":"loop2","maj_min":"7:2","rm":false,"size":"88.7M","ro":true,"type":"loop","mountpoint":"/snap/core/7396","size_bytes":93008691},{"name":"loop3","maj_min":"7:3","rm":false,"size":"66.5M","ro":true,"type":"loop","mountpoint":"/snap/google-cloud-sdk/103","size_bytes":69730304},{"name":"loop4","maj_min":"7:4","rm":false,"size":"66.5M","ro":true,"type":"loop","mountpoint":"/snap/google-cloud-sdk/104","size_bytes":69730304},{"name":"loop5","maj_min":"7:5","rm":false,"size":"54.4M","ro":true,"type":"loop","mountpoint":"/snap/core18/1074","size_bytes":57042534},{"name":"loop7","maj_min":"7:7","rm":false,"size":"8.6M","ro":true,"type":"loop","mountpoint":"/snap/doctl/187","size_bytes":9017753},{"name":"loop8","maj_min":"7:8","rm":false,"size":"3.1M","ro":true,"type":"loop","mountpoint":"/snap/stress-ng/847","size_bytes":3250585},{"name":"loop9","maj_min":"7:9","rm":false,"size":"8.6M","ro":true,"type":"loop","mountpoint":"/snap/doctl/215","size_bytes":9017753},{"name":"loop10","maj_min":"7:10","rm":false,"size":"89.1M","ro":true,"type":"loop","mountpoint":"/snap/core/7917","size_bytes":93428121},{"name":"loop11","maj_min":"7:11","rm":false,"size":"3.2M","ro":true,"type":"loop","mountpoint":"/snap/stress-ng/924","size_bytes":3355443},{"name":"sda","maj_min":"8:0","rm":false,"size":"20G","ro":false,"type":"disk","mountpoint":null,"size_bytes":21474836480},{"name":"sda1","maj_min":"8:1","rm":false,"size":"1M","ro":false,"type":"part","mountpoint":null,"size_bytes":1048576},{"name":"sda2","maj_min":"8:2","rm":false,"size":"20G","ro":false,"type":"part","mountpoint":"/","size_bytes":21474836480},{"name":"sr0","maj_min":"11:0","rm":true,"size":"64.8M","ro":false,"type":"rom","mountpoint":null,"size_bytes":67947724},{"name":"sr1","maj_min":"11:1","rm":true,"size":"848M","ro":false,"type":"rom","mountpoint":null,"size_bytes":889192448}] From d5cceb77e90d63a9c922a70cab5bb8b0207cc446 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Fri, 4 Apr 2025 16:16:47 -0700 Subject: [PATCH 18/32] remove extraneous file --- tests/templates/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/templates/.DS_Store diff --git a/tests/templates/.DS_Store b/tests/templates/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Date: Sat, 12 Apr 2025 10:50:26 -0700 Subject: [PATCH 19/32] allow IDNA2008 encoded email addresses with warning --- CHANGELOG | 3 ++- jc/parsers/asn1crypto/x509.py | 2 +- tests/fixtures/generic/x509-cert-bad-email2.der | Bin 0 -> 354 bytes tests/fixtures/generic/x509-cert-bad-email2.json | 1 + tests/test_x509_cert.py | 14 +++++++++++++- 5 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 tests/fixtures/generic/x509-cert-bad-email2.der create mode 100644 tests/fixtures/generic/x509-cert-bad-email2.json diff --git a/CHANGELOG b/CHANGELOG index 38774f41..5f4703df 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,11 +1,12 @@ jc changelog -20250402 v1.25.5 +20250412 v1.25.5 - Add `amixer` command parser - Fix `bluetoothctl` parser failing to parse controllers with power state prop - Fix `lsblk` command parser to support multiple mountpoints. Also, added byte conversions for size fields. - Fix `time` command parser for output that does not contain centiseconds +- Fix `x509-cert` parser to handle IDNA2008 encoded email addresses with a warning - Fix typing for upcoming python v3.14 - Fix timezone setting for tests to support minimal chrooted builds diff --git a/jc/parsers/asn1crypto/x509.py b/jc/parsers/asn1crypto/x509.py index 563fa3bd..07beee6f 100644 --- a/jc/parsers/asn1crypto/x509.py +++ b/jc/parsers/asn1crypto/x509.py @@ -255,7 +255,7 @@ class EmailAddress(IA5String): # fix to allow incorrectly encoded email addresses to succeed with warning try: self._unicode = mailbox.decode('cp1252') + '@' + hostname.decode('idna') - except UnicodeDecodeError: + except (UnicodeDecodeError, UnicodeError): ascii_mailbox = mailbox.decode('ascii', errors='backslashreplace') ascii_hostname = hostname.decode('ascii', errors='backslashreplace') from jc.utils import warning_message diff --git a/tests/fixtures/generic/x509-cert-bad-email2.der b/tests/fixtures/generic/x509-cert-bad-email2.der new file mode 100644 index 0000000000000000000000000000000000000000..20ce02b5ffef745c9f2a41b471ffa78f31ba101a GIT binary patch literal 354 zcmXqLVvI9rVq{*x%*4pVBw{Y)y!hnn((Q@)mht?)E3agwCmu53V&l+i^EhYA!pvkK zZ769V&c+3TLi&YJj4HSWnmK9`?GLUE# zD^4v=%yp>9)7335DN0P$%`Z&UOG!ocC$lGmfg6(|!yIdi*VlrcczXMANwS2wrWyMG zJ<$6m=XhdbqXS21$|0bVp9?KsMSVD^S95UE-X99(cLS26bL+ZHHKy-3*l_zo>qh{n CK65Jo literal 0 HcmV?d00001 diff --git a/tests/fixtures/generic/x509-cert-bad-email2.json b/tests/fixtures/generic/x509-cert-bad-email2.json new file mode 100644 index 00000000..6743f076 --- /dev/null +++ b/tests/fixtures/generic/x509-cert-bad-email2.json @@ -0,0 +1 @@ +[{"tbs_certificate":{"version":"v3","serial_number":"37:12:43:a3:c9:eb:75:b7:61:6f:39:5f:0f:4d:a9:d4:6a:67:61:c2","signature":{"algorithm":"sha256_ecdsa","parameters":null},"issuer":{"common_name":"idna issues Inc."},"validity":{"not_before":1744299375,"not_after":2059659375,"not_before_iso":"2025-04-10T15:36:15+00:00","not_after_iso":"2035-04-08T15:36:15+00:00"},"subject":{"common_name":"idna issues Inc."},"subject_public_key_info":{"algorithm":{"algorithm":"ec","parameters":"secp256r1"},"public_key":"04:c4:e7:a0:b8:d0:5a:d3:77:86:e9:b2:b4:0d:4c:4f:52:25:0b:53:5b:21:5e:f1:50:1e:4f:6c:f4:8f:44:03:50:c2:ee:0e:61:2b:56:09:25:5c:4c:17:2a:78:cd:d2:ff:f5:8f:0e:68:eb:c9:4b:8a:18:0d:62:8d:9b:46:5f:71"},"issuer_unique_id":null,"subject_unique_id":null,"extensions":[{"extn_id":"subject_alt_name","critical":false,"extn_value":["sesam@xn--strae-oqa.de"]}],"serial_number_str":"314401798066465365584221074488388179068992315842"},"signature_algorithm":{"algorithm":"sha256_ecdsa","parameters":null},"signature_value":"30:46:02:21:00:9c:3b:38:eb:d6:52:e4:49:4b:4c:0a:19:04:56:45:66:31:4f:fd:c0:8d:ec:6c:c7:61:61:81:40:08:55:64:c2:02:21:00:f9:a1:38:ea:5a:f0:c1:2e:7c:c1:92:bd:f8:20:77:dd:50:63:5b:6d:7e:8a:35:28:97:bf:30:b0:db:d0:85:f1"}] diff --git a/tests/test_x509_cert.py b/tests/test_x509_cert.py index 36421d66..66a3b767 100644 --- a/tests/test_x509_cert.py +++ b/tests/test_x509_cert.py @@ -33,6 +33,9 @@ class MyTests(unittest.TestCase): with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-negative-serial.pem'), 'rb') as f: x509_cert_negative_serial = f.read() + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-cert-bad-email2.der'), 'rb') as f: + x509_cert_bad_email2 = f.read() + # output with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-ca-cert.json'), 'r', encoding='utf-8') as f: x509_ca_cert_json = json.loads(f.read()) @@ -54,10 +57,13 @@ class MyTests(unittest.TestCase): with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-cert-superfluous-bits.json'), 'r', encoding='utf-8') as f: x509_cert_superfluous_bits_json = json.loads(f.read()) - + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-negative-serial.json'), 'r', encoding='utf-8') as f: x509_cert_negative_serial_json = json.loads(f.read()) + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-cert-bad-email2.json'), 'r', encoding='utf-8') as f: + x509_cert_bad_email2_json = json.loads(f.read()) + def test_x509_cert_nodata(self): """ @@ -113,6 +119,12 @@ class MyTests(unittest.TestCase): """ self.assertEqual(jc.parsers.x509_cert.parse(self.x509_cert_negative_serial, quiet=True), self.x509_cert_negative_serial_json) + def test_x509_cert_bad_email2(self): + """ + Test 'cat x509-cert-bad-email2.der' (DER file with a non-compliant email address - IDNA2008 encoded) + """ + self.assertEqual(jc.parsers.x509_cert.parse(self.x509_cert_bad_email2, quiet=True), self.x509_cert_bad_email2_json) + if __name__ == '__main__': unittest.main() From 9b4190f1e6fb93da08945b6f579b448207887845 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Sun, 13 Apr 2025 18:13:31 -0700 Subject: [PATCH 20/32] fix mount on macOS when filesystem contains parenthesis --- jc/parsers/mount.py | 31 +++++++++++-------- .../generic/mount-parens-in-filesystem.json | 1 + .../generic/mount-parens-in-filesystem.out | 14 +++++++++ tests/test_mount.py | 12 +++++++ 4 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 tests/fixtures/generic/mount-parens-in-filesystem.json create mode 100644 tests/fixtures/generic/mount-parens-in-filesystem.out diff --git a/jc/parsers/mount.py b/jc/parsers/mount.py index 9fe67558..8e9765c4 100644 --- a/jc/parsers/mount.py +++ b/jc/parsers/mount.py @@ -77,7 +77,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.10' + version = '1.11' description = '`mount` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -111,19 +111,24 @@ def _osx_parse(data): for entry in data: output_line = {} - filesystem = entry.split(' on ') - filesystem = filesystem[0] - output_line['filesystem'] = filesystem + pattern = re.compile( + r''' + (?P.*) + \son\s + (?P.*?) + \s + \((?P.*?)\)\s* + ''', re.VERBOSE + ) - mount_point = entry.split(' on ') - mount_point = mount_point[1].split(' (') - mount_point = mount_point[0] - output_line['mount_point'] = mount_point + mymatch = pattern.match(entry) + groups = mymatch.groupdict() - options = entry.split('(', maxsplit=1) - options = options[1].rstrip(')') - options = options.split(', ') - output_line['options'] = options + if groups: + output_line['filesystem'] = groups['filesystem'] + output_line['mount_point'] = groups['mount_point'] + options = groups['options'].split(', ') + output_line['options'] = options output.append(output_line) @@ -218,7 +223,7 @@ def parse(data, raw=False, quiet=False): # check for OSX and AIX output if ' type ' not in cleandata[0]: - if 'node' in cleandata[0]: + if ' node ' in cleandata[0]: raw_output = _aix_parse(cleandata) else: raw_output = _osx_parse(cleandata) diff --git a/tests/fixtures/generic/mount-parens-in-filesystem.json b/tests/fixtures/generic/mount-parens-in-filesystem.json new file mode 100644 index 00000000..2c6cfbbe --- /dev/null +++ b/tests/fixtures/generic/mount-parens-in-filesystem.json @@ -0,0 +1 @@ +[{"filesystem":"/dev/disk3s1s1","mount_point":"/","options":["apfs","sealed","local","read-only","journaled"]},{"filesystem":"devfs","mount_point":"/dev","options":["devfs","local","nobrowse"]},{"filesystem":"/dev/disk3s6","mount_point":"/System/Volumes/VM","options":["apfs","local","noexec","journaled","noatime","nobrowse"]},{"filesystem":"/dev/disk3s2","mount_point":"/System/Volumes/Preboot","options":["apfs","local","journaled","nobrowse"]},{"filesystem":"/dev/disk3s4","mount_point":"/System/Volumes/Update","options":["apfs","local","journaled","nobrowse"]},{"filesystem":"/dev/disk2s2","mount_point":"/System/Volumes/xarts","options":["apfs","local","noexec","journaled","noatime","nobrowse"]},{"filesystem":"/dev/disk2s1","mount_point":"/System/Volumes/iSCPreboot","options":["apfs","local","journaled","nobrowse"]},{"filesystem":"/dev/disk2s3","mount_point":"/System/Volumes/Hardware","options":["apfs","local","journaled","nobrowse"]},{"filesystem":"/dev/disk3s5","mount_point":"/System/Volumes/Data","options":["apfs","local","journaled","nobrowse","protect","root data"]},{"filesystem":"map auto_home","mount_point":"/System/Volumes/Data/home","options":["autofs","automounted","nobrowse"]},{"filesystem":"MN - mydomain.com (ftp.mydomain.com):/","mount_point":"/Users/muescha/Library/Application Support/Mountain Duck/Volumes.noindex/MN - mydomain.com.localized","options":["nfs","asynchronous","nodev","nosuid","noowners","noatime","mounted by muescha"]},{"filesystem":"/dev/disk5s1","mount_point":"/Library/Developer/CoreSimulator/Volumes/iOS_21F79","options":["apfs","local","nodev","nosuid","read-only","journaled","noowners","noatime","nobrowse"]},{"filesystem":"/dev/disk7s1","mount_point":"/Library/Developer/CoreSimulator/Cryptex/Images/bundle/SimRuntimeBundle-A3CF7B3B-543B-4D71-BA03-12F939EA0B4D","options":["apfs","local","nodev","nosuid","read-only","journaled","noowners","noatime","nobrowse"]},{"filesystem":"/dev/disk9s1","mount_point":"/Library/Developer/CoreSimulator/Volumes/iOS_22C150","options":["apfs","sealed","local","nodev","nosuid","read-only","journaled","noowners","noatime","nobrowse"]}] diff --git a/tests/fixtures/generic/mount-parens-in-filesystem.out b/tests/fixtures/generic/mount-parens-in-filesystem.out new file mode 100644 index 00000000..f7d37c03 --- /dev/null +++ b/tests/fixtures/generic/mount-parens-in-filesystem.out @@ -0,0 +1,14 @@ +/dev/disk3s1s1 on / (apfs, sealed, local, read-only, journaled) +devfs on /dev (devfs, local, nobrowse) +/dev/disk3s6 on /System/Volumes/VM (apfs, local, noexec, journaled, noatime, nobrowse) +/dev/disk3s2 on /System/Volumes/Preboot (apfs, local, journaled, nobrowse) +/dev/disk3s4 on /System/Volumes/Update (apfs, local, journaled, nobrowse) +/dev/disk2s2 on /System/Volumes/xarts (apfs, local, noexec, journaled, noatime, nobrowse) +/dev/disk2s1 on /System/Volumes/iSCPreboot (apfs, local, journaled, nobrowse) +/dev/disk2s3 on /System/Volumes/Hardware (apfs, local, journaled, nobrowse) +/dev/disk3s5 on /System/Volumes/Data (apfs, local, journaled, nobrowse, protect, root data) +map auto_home on /System/Volumes/Data/home (autofs, automounted, nobrowse) +MN - mydomain.com (ftp.mydomain.com):/ on /Users/muescha/Library/Application Support/Mountain Duck/Volumes.noindex/MN - mydomain.com.localized (nfs, asynchronous, nodev, nosuid, noowners, noatime, mounted by muescha) +/dev/disk5s1 on /Library/Developer/CoreSimulator/Volumes/iOS_21F79 (apfs, local, nodev, nosuid, read-only, journaled, noowners, noatime, nobrowse) +/dev/disk7s1 on /Library/Developer/CoreSimulator/Cryptex/Images/bundle/SimRuntimeBundle-A3CF7B3B-543B-4D71-BA03-12F939EA0B4D (apfs, local, nodev, nosuid, read-only, journaled, noowners, noatime, nobrowse) +/dev/disk9s1 on /Library/Developer/CoreSimulator/Volumes/iOS_22C150 (apfs, sealed, local, nodev, nosuid, read-only, journaled, noowners, noatime, nobrowse) diff --git a/tests/test_mount.py b/tests/test_mount.py index 895730cb..2d6b88f9 100644 --- a/tests/test_mount.py +++ b/tests/test_mount.py @@ -30,6 +30,9 @@ class MyTests(unittest.TestCase): with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mount-spaces-in-filename.out'), 'r', encoding='utf-8') as f: generic_mount_spaces_in_filename = f.read() + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mount-parens-in-filesystem.out'), 'r', encoding='utf-8') as f: + generic_mount_parens_in_filesystem = f.read() + # output with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/mount.json'), 'r', encoding='utf-8') as f: @@ -53,6 +56,9 @@ class MyTests(unittest.TestCase): with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mount-spaces-in-filename.json'), 'r', encoding='utf-8') as f: generic_mount_spaces_in_filename_json = json.loads(f.read()) + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mount-parens-in-filesystem.json'), 'r', encoding='utf-8') as f: + generic_mount_parens_in_filesystem_json = json.loads(f.read()) + def test_mount_nodata(self): """ @@ -102,6 +108,12 @@ class MyTests(unittest.TestCase): """ self.assertEqual(jc.parsers.mount.parse(self.generic_mount_spaces_in_filename, quiet=True), self.generic_mount_spaces_in_filename_json) + def test_mount_parens_in_filesystem(self): + """ + Test 'mount' with parenthesis in the filesystem + """ + self.assertEqual(jc.parsers.mount.parse(self.generic_mount_parens_in_filesystem, quiet=True), self.generic_mount_parens_in_filesystem_json) + if __name__ == '__main__': unittest.main() From 65d9cc718fcc8c8b46f2408d5b2f38449f3c0a2c Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Sun, 13 Apr 2025 18:14:15 -0700 Subject: [PATCH 21/32] version bump --- jc/parsers/x509_cert.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jc/parsers/x509_cert.py b/jc/parsers/x509_cert.py index a60ce949..062503bb 100644 --- a/jc/parsers/x509_cert.py +++ b/jc/parsers/x509_cert.py @@ -413,7 +413,7 @@ from jc.parsers.asn1crypto import pem, x509, jc_global class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.3' + version = '1.4' description = 'X.509 PEM and DER certificate file parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' From c8599253fb5597f1dfb4214f7ecda9300d0dacc6 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Mon, 14 Apr 2025 15:30:35 -0700 Subject: [PATCH 22/32] formatting --- jc/parsers/mount.py | 1 - 1 file changed, 1 deletion(-) diff --git a/jc/parsers/mount.py b/jc/parsers/mount.py index 8e9765c4..3837975c 100644 --- a/jc/parsers/mount.py +++ b/jc/parsers/mount.py @@ -71,7 +71,6 @@ Example: ] """ import re - import jc.utils From 966df715666772178a40d82bd7068fc87f0e7bd0 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Tue, 15 Apr 2025 08:41:30 -0700 Subject: [PATCH 23/32] add default policy stats to iptables parser --- CHANGELOG | 3 +- jc/parsers/iptables.py | 38 ++++++++++++++++++- .../centos-7.7/iptables-filter-nv.json | 2 +- .../ubuntu-18.04/iptables-filter-nv.json | 2 +- tests/test_iptables.py | 2 +- 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5f4703df..7c4e9897 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,8 @@ jc changelog -20250412 v1.25.5 +20250414 v1.25.5 - Add `amixer` command parser +- Enhance `iptables` command parser to add default policy statistics fields - Fix `bluetoothctl` parser failing to parse controllers with power state prop - Fix `lsblk` command parser to support multiple mountpoints. Also, added byte conversions for size fields. diff --git a/jc/parsers/iptables.py b/jc/parsers/iptables.py index dcaab5eb..9dd8b7b5 100644 --- a/jc/parsers/iptables.py +++ b/jc/parsers/iptables.py @@ -20,6 +20,9 @@ Schema: [ { "chain": string, + "default_policy": string, + "default_packets": integer, + "default_bytes": integer, "rules": [ { "num" integer, @@ -44,6 +47,9 @@ Examples: [ { "chain": "PREROUTING", + "default_policy": "DROP", + "default_packets": 0, + "default_bytes": 0, "rules": [ { "num": 1, @@ -103,6 +109,9 @@ Examples: [ { "chain": "PREROUTING", + "default_policy": "DROP", + "default_packets": "0", + "default_bytes": "0", "rules": [ { "num": "1", @@ -158,12 +167,13 @@ Examples: ... ] """ +import re import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.11' + version = '1.12' description = '`iptables` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -174,6 +184,17 @@ class info(): __version__ = info.version +chain_pkt_byt_pattern = re.compile( + r''' + \s\(policy\s + (?P.+) + \s + (?P.+) + \spackets,\s + (?P.+) + \sbytes\) + ''', re.VERBOSE +) def _process(proc_data): """ @@ -188,6 +209,13 @@ def _process(proc_data): List of Dictionaries. Structured data to conform to the schema. """ for entry in proc_data: + + if 'default_packets' in entry: + entry['default_packets'] = jc.utils.convert_to_int(entry['default_packets']) + + if 'default_bytes' in entry: + entry['default_bytes'] = jc.utils.convert_size_to_int(entry['default_bytes']) + for rule in entry['rules']: int_list = ['num', 'pkts'] for key in rule: @@ -243,6 +271,14 @@ def parse(data, raw=False, quiet=False): parsed_line = line.split() chain['chain'] = parsed_line[1] + + stats_match = re.search(chain_pkt_byt_pattern, line) + if stats_match: + stats = stats_match.groupdict() + chain['default_policy'] = stats['policy_name'] + chain['default_packets'] = stats['packets'] + chain['default_bytes'] = stats['bytes'] + chain['rules'] = [] continue diff --git a/tests/fixtures/centos-7.7/iptables-filter-nv.json b/tests/fixtures/centos-7.7/iptables-filter-nv.json index 329681f4..4f542493 100644 --- a/tests/fixtures/centos-7.7/iptables-filter-nv.json +++ b/tests/fixtures/centos-7.7/iptables-filter-nv.json @@ -1 +1 @@ -[{"chain": "INPUT", "rules": [{"pkts": 4175, "bytes": 1130000, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate RELATED,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "lo", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 2383, "bytes": 204000, "target": "INPUT_direct", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 2383, "bytes": 204000, "target": "INPUT_ZONES_SOURCE", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 2383, "bytes": 204000, "target": "INPUT_ZONES", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "DROP", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate INVALID"}, {"pkts": 2382, "bytes": 204000, "target": "REJECT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "reject-with icmp-host-prohibited"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "lo", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate RELATED,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "DROP", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate INVALID"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "15.15.15.0/24", "destination": "0.0.0.0/0", "options": "tcp dpt:22 ctstate NEW,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "lo", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate RELATED,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "DROP", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate INVALID"}, {"pkts": 0, "bytes": 0, "target": "DROP", "prot": "all", "opt": null, "in": "lo", "out": "*", "source": "15.15.15.51", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "15.15.15.0/24", "destination": "0.0.0.0/0", "options": "tcp dpt:22 ctstate NEW,ESTABLISHED"}]}, {"chain": "FORWARD", "rules": [{"pkts": 0, "bytes": 0, "target": "DOCKER-ISOLATION", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "DOCKER", "prot": "all", "opt": null, "in": "*", "out": "docker0", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "docker0", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate RELATED,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "docker0", "out": "!docker0", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "docker0", "out": "docker0", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate RELATED,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "lo", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "FORWARD_direct", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "FORWARD_IN_ZONES_SOURCE", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "FORWARD_IN_ZONES", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "FORWARD_OUT_ZONES_SOURCE", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "FORWARD_OUT_ZONES", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "DROP", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate INVALID"}, {"pkts": 0, "bytes": 0, "target": "REJECT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "reject-with icmp-host-prohibited"}]}, {"chain": "OUTPUT", "rules": [{"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "lo", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 3419, "bytes": 573000, "target": "OUTPUT_direct", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "lo", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 225, "bytes": 101000, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "tcp spt:22 ctstate ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "lo", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "tcp spt:22 ctstate ESTABLISHED"}]}, {"chain": "DOCKER", "rules": []}, {"chain": "DOCKER-ISOLATION", "rules": [{"pkts": 0, "bytes": 0, "target": "RETURN", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}]}, {"chain": "FORWARD_IN_ZONES", "rules": [{"pkts": 0, "bytes": 0, "target": "FWDI_public", "prot": "all", "opt": null, "in": "ens33", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "[goto] "}, {"pkts": 0, "bytes": 0, "target": "FWDI_public", "prot": "all", "opt": null, "in": "+", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "[goto] "}]}, {"chain": "FORWARD_IN_ZONES_SOURCE", "rules": []}, {"chain": "FORWARD_OUT_ZONES", "rules": [{"pkts": 0, "bytes": 0, "target": "FWDO_public", "prot": "all", "opt": null, "in": "*", "out": "ens33", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "[goto] "}, {"pkts": 0, "bytes": 0, "target": "FWDO_public", "prot": "all", "opt": null, "in": "*", "out": "+", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "[goto] "}]}, {"chain": "FORWARD_OUT_ZONES_SOURCE", "rules": []}, {"chain": "FORWARD_direct", "rules": []}, {"chain": "FWDI_public", "rules": [{"pkts": 0, "bytes": 0, "target": "FWDI_public_log", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "FWDI_public_deny", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "FWDI_public_allow", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "icmp", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}]}, {"chain": "FWDI_public_allow", "rules": []}, {"chain": "FWDI_public_deny", "rules": []}, {"chain": "FWDI_public_log", "rules": []}, {"chain": "FWDO_public", "rules": [{"pkts": 0, "bytes": 0, "target": "FWDO_public_log", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "FWDO_public_deny", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "FWDO_public_allow", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}]}, {"chain": "FWDO_public_allow", "rules": []}, {"chain": "FWDO_public_deny", "rules": []}, {"chain": "FWDO_public_log", "rules": []}, {"chain": "INPUT_ZONES", "rules": [{"pkts": 2367, "bytes": 202000, "target": "IN_public", "prot": "all", "opt": null, "in": "ens33", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "[goto] "}, {"pkts": 1, "bytes": 330, "target": "IN_public", "prot": "all", "opt": null, "in": "+", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "[goto] "}]}, {"chain": "INPUT_ZONES_SOURCE", "rules": []}, {"chain": "INPUT_direct", "rules": []}, {"chain": "IN_public", "rules": [{"pkts": 2383, "bytes": 204000, "target": "IN_public_log", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 2383, "bytes": 204000, "target": "IN_public_deny", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 2383, "bytes": 204000, "target": "IN_public_allow", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "icmp", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}]}, {"chain": "IN_public_allow", "rules": [{"pkts": 1, "bytes": 64, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "tcp dpt:22 ctstate NEW,UNTRACKED"}]}, {"chain": "IN_public_deny", "rules": []}, {"chain": "IN_public_log", "rules": []}, {"chain": "OUTPUT_direct", "rules": []}] +[{"chain":"INPUT","default_policy":"ACCEPT","default_packets":0,"default_bytes":0,"rules":[{"pkts":4175,"bytes":1130000,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate RELATED,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"lo","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":2383,"bytes":204000,"target":"INPUT_direct","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":2383,"bytes":204000,"target":"INPUT_ZONES_SOURCE","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":2383,"bytes":204000,"target":"INPUT_ZONES","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"DROP","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate INVALID"},{"pkts":2382,"bytes":204000,"target":"REJECT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"reject-with icmp-host-prohibited"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"lo","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate RELATED,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"DROP","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate INVALID"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"15.15.15.0/24","destination":"0.0.0.0/0","options":"tcp dpt:22 ctstate NEW,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"lo","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate RELATED,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"DROP","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate INVALID"},{"pkts":0,"bytes":0,"target":"DROP","prot":"all","opt":null,"in":"lo","out":"*","source":"15.15.15.51","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"15.15.15.0/24","destination":"0.0.0.0/0","options":"tcp dpt:22 ctstate NEW,ESTABLISHED"}]},{"chain":"FORWARD","default_policy":"DROP","default_packets":0,"default_bytes":0,"rules":[{"pkts":0,"bytes":0,"target":"DOCKER-ISOLATION","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"DOCKER","prot":"all","opt":null,"in":"*","out":"docker0","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"docker0","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate RELATED,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"docker0","out":"!docker0","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"docker0","out":"docker0","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate RELATED,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"lo","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"FORWARD_direct","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"FORWARD_IN_ZONES_SOURCE","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"FORWARD_IN_ZONES","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"FORWARD_OUT_ZONES_SOURCE","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"FORWARD_OUT_ZONES","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"DROP","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate INVALID"},{"pkts":0,"bytes":0,"target":"REJECT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"reject-with icmp-host-prohibited"}]},{"chain":"OUTPUT","default_policy":"ACCEPT","default_packets":5,"default_bytes":345,"rules":[{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"lo","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":3419,"bytes":573000,"target":"OUTPUT_direct","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"lo","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":225,"bytes":101000,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"tcp spt:22 ctstate ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"lo","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"tcp spt:22 ctstate ESTABLISHED"}]},{"chain":"DOCKER","rules":[]},{"chain":"DOCKER-ISOLATION","rules":[{"pkts":0,"bytes":0,"target":"RETURN","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"}]},{"chain":"FORWARD_IN_ZONES","rules":[{"pkts":0,"bytes":0,"target":"FWDI_public","prot":"all","opt":null,"in":"ens33","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"[goto] "},{"pkts":0,"bytes":0,"target":"FWDI_public","prot":"all","opt":null,"in":"+","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"[goto] "}]},{"chain":"FORWARD_IN_ZONES_SOURCE","rules":[]},{"chain":"FORWARD_OUT_ZONES","rules":[{"pkts":0,"bytes":0,"target":"FWDO_public","prot":"all","opt":null,"in":"*","out":"ens33","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"[goto] "},{"pkts":0,"bytes":0,"target":"FWDO_public","prot":"all","opt":null,"in":"*","out":"+","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"[goto] "}]},{"chain":"FORWARD_OUT_ZONES_SOURCE","rules":[]},{"chain":"FORWARD_direct","rules":[]},{"chain":"FWDI_public","rules":[{"pkts":0,"bytes":0,"target":"FWDI_public_log","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"FWDI_public_deny","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"FWDI_public_allow","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"icmp","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"}]},{"chain":"FWDI_public_allow","rules":[]},{"chain":"FWDI_public_deny","rules":[]},{"chain":"FWDI_public_log","rules":[]},{"chain":"FWDO_public","rules":[{"pkts":0,"bytes":0,"target":"FWDO_public_log","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"FWDO_public_deny","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"FWDO_public_allow","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"}]},{"chain":"FWDO_public_allow","rules":[]},{"chain":"FWDO_public_deny","rules":[]},{"chain":"FWDO_public_log","rules":[]},{"chain":"INPUT_ZONES","rules":[{"pkts":2367,"bytes":202000,"target":"IN_public","prot":"all","opt":null,"in":"ens33","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"[goto] "},{"pkts":1,"bytes":330,"target":"IN_public","prot":"all","opt":null,"in":"+","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"[goto] "}]},{"chain":"INPUT_ZONES_SOURCE","rules":[]},{"chain":"INPUT_direct","rules":[]},{"chain":"IN_public","rules":[{"pkts":2383,"bytes":204000,"target":"IN_public_log","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":2383,"bytes":204000,"target":"IN_public_deny","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":2383,"bytes":204000,"target":"IN_public_allow","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"icmp","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"}]},{"chain":"IN_public_allow","rules":[{"pkts":1,"bytes":64,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"tcp dpt:22 ctstate NEW,UNTRACKED"}]},{"chain":"IN_public_deny","rules":[]},{"chain":"IN_public_log","rules":[]},{"chain":"OUTPUT_direct","rules":[]}] diff --git a/tests/fixtures/ubuntu-18.04/iptables-filter-nv.json b/tests/fixtures/ubuntu-18.04/iptables-filter-nv.json index 6793ed7c..d8d228a5 100644 --- a/tests/fixtures/ubuntu-18.04/iptables-filter-nv.json +++ b/tests/fixtures/ubuntu-18.04/iptables-filter-nv.json @@ -1 +1 @@ -[{"chain": "INPUT", "rules": [{"pkts": 66, "bytes": 6034, "target": "ACCEPT", "prot": "all", "opt": null, "in": "lo", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 1137, "bytes": 318000, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate RELATED,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "DROP", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate INVALID"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "15.15.15.0/24", "destination": "0.0.0.0/0", "options": "tcp dpt:22 ctstate NEW,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "lo", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate RELATED,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "DROP", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate INVALID"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "15.15.15.0/24", "destination": "0.0.0.0/0", "options": "tcp dpt:22 ctstate NEW,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "lo", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate RELATED,ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "DROP", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate INVALID"}, {"pkts": 0, "bytes": 0, "target": "DROP", "prot": "all", "opt": null, "in": "lo", "out": "*", "source": "15.15.15.51", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "15.15.15.0/24", "destination": "0.0.0.0/0", "options": "tcp dpt:22 ctstate NEW,ESTABLISHED"}]}, {"chain": "FORWARD", "rules": []}, {"chain": "OUTPUT", "rules": [{"pkts": 66, "bytes": 6034, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "lo", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 889, "bytes": 158000, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "tcp spt:22 ctstate ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "lo", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "tcp spt:22 ctstate ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "lo", "source": "0.0.0.0/0", "destination": "0.0.0.0/0"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "all", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "ctstate ESTABLISHED"}, {"pkts": 0, "bytes": 0, "target": "ACCEPT", "prot": "tcp", "opt": null, "in": "*", "out": "*", "source": "0.0.0.0/0", "destination": "0.0.0.0/0", "options": "tcp spt:22 ctstate ESTABLISHED"}]}] +[{"chain":"INPUT","default_policy":"ACCEPT","default_packets":0,"default_bytes":0,"rules":[{"pkts":66,"bytes":6034,"target":"ACCEPT","prot":"all","opt":null,"in":"lo","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":1137,"bytes":318000,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate RELATED,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"DROP","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate INVALID"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"15.15.15.0/24","destination":"0.0.0.0/0","options":"tcp dpt:22 ctstate NEW,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"lo","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate RELATED,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"DROP","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate INVALID"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"15.15.15.0/24","destination":"0.0.0.0/0","options":"tcp dpt:22 ctstate NEW,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"lo","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate RELATED,ESTABLISHED"},{"pkts":0,"bytes":0,"target":"DROP","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate INVALID"},{"pkts":0,"bytes":0,"target":"DROP","prot":"all","opt":null,"in":"lo","out":"*","source":"15.15.15.51","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"15.15.15.0/24","destination":"0.0.0.0/0","options":"tcp dpt:22 ctstate NEW,ESTABLISHED"}]},{"chain":"FORWARD","default_policy":"ACCEPT","default_packets":0,"default_bytes":0,"rules":[]},{"chain":"OUTPUT","default_policy":"ACCEPT","default_packets":4,"default_bytes":277,"rules":[{"pkts":66,"bytes":6034,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"lo","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":889,"bytes":158000,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"tcp spt:22 ctstate ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"lo","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"tcp spt:22 ctstate ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"lo","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate ESTABLISHED"},{"pkts":0,"bytes":0,"target":"ACCEPT","prot":"tcp","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"tcp spt:22 ctstate ESTABLISHED"}]}] diff --git a/tests/test_iptables.py b/tests/test_iptables.py index 124a54e0..e94ea806 100644 --- a/tests/test_iptables.py +++ b/tests/test_iptables.py @@ -200,7 +200,7 @@ class MyTests(unittest.TestCase): 128627559125 172804718595966 INPUT_ZONES all -- * * 0.0.0.0/0 0.0.0.0/0 26599 1082920 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate INVALID 1761 79571 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited''' - expected = [{"chain":"INPUT","rules":[{"pkts":11291792498,"bytes":217331852907122,"target":"ACCEPT","prot":"all","opt":None,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate RELATED,ESTABLISHED"},{"pkts":555958,"bytes":33533576,"target":"ACCEPT","prot":"all","opt":None,"in":"lo","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":128628404869,"bytes":172804745659762,"target":"INPUT_direct","prot":"all","opt":None,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":128627559128,"bytes":172804718596050,"target":"INPUT_ZONES_SOURCE","prot":"all","opt":None,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":128627559125,"bytes":172804718595966,"target":"INPUT_ZONES","prot":"all","opt":None,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"},{"pkts":26599,"bytes":1082920,"target":"DROP","prot":"all","opt":None,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"ctstate INVALID"},{"pkts":1761,"bytes":79571,"target":"REJECT","prot":"all","opt":None,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0","options":"reject-with icmp-host-prohibited"}]}] + expected = [{'chain': 'INPUT', 'default_policy': 'ACCEPT', 'default_packets': 0, 'default_bytes': 0, 'rules': [{'pkts': 11291792498, 'bytes': 217331852907122, 'target': 'ACCEPT', 'prot': 'all', 'opt': None, 'in': '*', 'out': '*', 'source': '0.0.0.0/0', 'destination': '0.0.0.0/0', 'options': 'ctstate RELATED,ESTABLISHED'}, {'pkts': 555958, 'bytes': 33533576, 'target': 'ACCEPT', 'prot': 'all', 'opt': None, 'in': 'lo', 'out': '*', 'source': '0.0.0.0/0', 'destination': '0.0.0.0/0'}, {'pkts': 128628404869, 'bytes': 172804745659762, 'target': 'INPUT_direct', 'prot': 'all', 'opt': None, 'in': '*', 'out': '*', 'source': '0.0.0.0/0', 'destination': '0.0.0.0/0'}, {'pkts': 128627559128, 'bytes': 172804718596050, 'target': 'INPUT_ZONES_SOURCE', 'prot': 'all', 'opt': None, 'in': '*', 'out': '*', 'source': '0.0.0.0/0', 'destination': '0.0.0.0/0'}, {'pkts': 128627559125, 'bytes': 172804718595966, 'target': 'INPUT_ZONES', 'prot': 'all', 'opt': None, 'in': '*', 'out': '*', 'source': '0.0.0.0/0', 'destination': '0.0.0.0/0'}, {'pkts': 26599, 'bytes': 1082920, 'target': 'DROP', 'prot': 'all', 'opt': None, 'in': '*', 'out': '*', 'source': '0.0.0.0/0', 'destination': '0.0.0.0/0', 'options': 'ctstate INVALID'}, {'pkts': 1761, 'bytes': 79571, 'target': 'REJECT', 'prot': 'all', 'opt': None, 'in': '*', 'out': '*', 'source': '0.0.0.0/0', 'destination': '0.0.0.0/0', 'options': 'reject-with icmp-host-prohibited'}]}] self.assertEqual(jc.parsers.iptables.parse(data, quiet=True), expected) From d04a175d36801a254ead8d068cba560e2a3840a1 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Tue, 15 Apr 2025 08:50:30 -0700 Subject: [PATCH 24/32] Update to ubuntu-22.04 on old version run --- .github/workflows/pythonapp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml index 319c64fe..65e1987d 100644 --- a/.github/workflows/pythonapp.yml +++ b/.github/workflows/pythonapp.yml @@ -14,7 +14,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-13, ubuntu-20.04, windows-2019] + os: [macos-13, ubuntu-22.04, windows-2019] python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] steps: From c6a13aa4d8a0da1dce8606a368a49b23dde4d68c Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Tue, 15 Apr 2025 08:51:35 -0700 Subject: [PATCH 25/32] force test run --- build-completions.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build-completions.py b/build-completions.py index ee238d19..891c706c 100755 --- a/build-completions.py +++ b/build-completions.py @@ -7,3 +7,5 @@ with open('completions/jc_bash_completion.sh', 'w') as f: with open('completions/jc_zsh_completion.sh', 'w') as f: print(zsh_completion(), file=f) + +# force test run \ No newline at end of file From ccbe36e712e5890f3078c5923c1418958234f199 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Tue, 15 Apr 2025 08:55:41 -0700 Subject: [PATCH 26/32] Create very_old, old, and latest python runs needed due to loss of python 3.6 support on some runners --- .github/workflows/pythonapp.yml | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml index 65e1987d..75f17cfa 100644 --- a/.github/workflows/pythonapp.yml +++ b/.github/workflows/pythonapp.yml @@ -9,13 +9,41 @@ on: - "**/*.py" jobs: + very_old_python: + if: github.event.pull_request.draft == false + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-13, windows-2019] + python-version: ["3.6"] + + steps: + - uses: actions/checkout@v3 + - name: "Set up timezone to America/Los_Angeles" + uses: szenius/set-timezone@v1.2 + with: + timezoneLinux: "America/Los_Angeles" + timezoneMacos: "America/Los_Angeles" + timezoneWindows: "Pacific Standard Time" + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + - name: Test with unittest + run: | + python -m unittest discover tests + old_python: if: github.event.pull_request.draft == false runs-on: ${{ matrix.os }} strategy: matrix: os: [macos-13, ubuntu-22.04, windows-2019] - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] + python-version: ["3.7", "3.8", "3.9", "3.10"] steps: - uses: actions/checkout@v3 From 34fda0905fe210c149fa137658daf4ea2ffe8e3e Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Tue, 15 Apr 2025 08:56:36 -0700 Subject: [PATCH 27/32] force test run --- build-completions.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/build-completions.py b/build-completions.py index 891c706c..ee238d19 100755 --- a/build-completions.py +++ b/build-completions.py @@ -7,5 +7,3 @@ with open('completions/jc_bash_completion.sh', 'w') as f: with open('completions/jc_zsh_completion.sh', 'w') as f: print(zsh_completion(), file=f) - -# force test run \ No newline at end of file From 222d1b72557eb3f95dd373a2c617b372d63ce697 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Sat, 3 May 2025 13:39:32 -0700 Subject: [PATCH 28/32] support json value in team.config field --- CHANGELOG | 3 ++- jc/parsers/nmcli.py | 24 +++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7c4e9897..b81f641a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,11 +1,12 @@ jc changelog -20250414 v1.25.5 +20250503 v1.25.5 - Add `amixer` command parser - Enhance `iptables` command parser to add default policy statistics fields - Fix `bluetoothctl` parser failing to parse controllers with power state prop - Fix `lsblk` command parser to support multiple mountpoints. Also, added byte conversions for size fields. +- Fix `nmcli` command parser to support `team.config` JSON field - Fix `time` command parser for output that does not contain centiseconds - Fix `x509-cert` parser to handle IDNA2008 encoded email addresses with a warning - Fix typing for upcoming python v3.14 diff --git a/jc/parsers/nmcli.py b/jc/parsers/nmcli.py index 4779725a..3c707801 100644 --- a/jc/parsers/nmcli.py +++ b/jc/parsers/nmcli.py @@ -141,6 +141,7 @@ Examples: ] """ import re +import json from typing import List, Dict, Optional import jc.utils from jc.parsers.universal import sparse_table_parse @@ -149,7 +150,7 @@ from jc.exceptions import ParseError class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.0' + version = '1.1' description = '`nmcli` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -313,8 +314,29 @@ def _device_show_parse(data: str) -> List[Dict]: def _connection_show_x_parse(data: str) -> List[Dict]: raw_output: List = [] item: Dict = {} + in_team_config: bool = False + team_config_value: List = [] for line in filter(None, data.splitlines()): + + # fix for team.config, which is multi-line JSON + if line.startswith('team.config:'): + in_team_config = True + _, value = line.split(':', maxsplit=1) + team_config_value.append(value.strip()) + item['team_config'] = [] + continue + + if not line.startswith('team.') and in_team_config: + team_config_value.append(line.strip()) + continue + + in_team_config = False + + if team_config_value: + item['team_config'] = json.loads(''.join(team_config_value)) + team_config_value = [] + key, value = line.split(':', maxsplit=1) key_n = _normalize_key(key) From ba0fc5dad9fcbb2b3bb852207c400d38a6aa21b0 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Sat, 3 May 2025 13:42:34 -0700 Subject: [PATCH 29/32] doc update --- jc/parsers/nmcli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/jc/parsers/nmcli.py b/jc/parsers/nmcli.py index 3c707801..88e00de7 100644 --- a/jc/parsers/nmcli.py +++ b/jc/parsers/nmcli.py @@ -36,6 +36,7 @@ These are documented below. [ { "": string/integer/float, # [0] + "team_config": object, "dhcp4_option_x": { "name": string, "value": string/integer/float, From 4c2775970d918f686010b70211f61b9f24e6ed9f Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Mon, 5 May 2025 11:34:30 -0700 Subject: [PATCH 30/32] change team_config to object instead of list --- jc/parsers/nmcli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jc/parsers/nmcli.py b/jc/parsers/nmcli.py index 88e00de7..16c85407 100644 --- a/jc/parsers/nmcli.py +++ b/jc/parsers/nmcli.py @@ -325,7 +325,7 @@ def _connection_show_x_parse(data: str) -> List[Dict]: in_team_config = True _, value = line.split(':', maxsplit=1) team_config_value.append(value.strip()) - item['team_config'] = [] + item['team_config'] = {} continue if not line.startswith('team.') and in_team_config: @@ -335,6 +335,7 @@ def _connection_show_x_parse(data: str) -> List[Dict]: in_team_config = False if team_config_value: + # team.config value should always be JSON item['team_config'] = json.loads(''.join(team_config_value)) team_config_value = [] From 7c9e92e284ae37e6c5d9ce593081070e8e9cff67 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Mon, 5 May 2025 14:48:12 -0700 Subject: [PATCH 31/32] add test for team.config with JSON --- tests/test_nmcli.py | 111 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/tests/test_nmcli.py b/tests/test_nmcli.py index 7f0eb4ab..5bb90dfa 100644 --- a/tests/test_nmcli.py +++ b/tests/test_nmcli.py @@ -185,6 +185,117 @@ class MyTests(unittest.TestCase): """ self.assertEqual(jc.parsers.nmcli.parse(self.fedora32_nmcli_device_show, quiet=True), self.fedora32_nmcli_device_show_json) + def test_nmcli_team_config(self): + """ + Test nmcli with team.config JSON value + """ + data = '''connection.id: Team connection 1 +connection.uuid: 258e02c2-d9f9-44bb-8d27-887e11aa1828 +connection.stable-id: -- +connection.type: team +connection.interface-name: team0 +connection.autoconnect: yes +connection.autoconnect-priority: 0 +connection.autoconnect-retries: -1 (default) +connection.multi-connect: 0 (default) +connection.auth-retries: -1 +connection.timestamp: 0 +connection.read-only: no +connection.permissions: -- +connection.zone: -- +connection.master: -- +connection.slave-type: -- +connection.autoconnect-slaves: -1 (default) +connection.secondaries: -- +connection.gateway-ping-timeout: 0 +connection.metered: unknown +connection.lldp: default +connection.mdns: -1 (default) +connection.llmnr: -1 (default) +connection.dns-over-tls: -1 (default) +connection.wait-device-timeout: -1 +ipv4.method: auto +ipv4.dns: -- +ipv4.dns-search: -- +ipv4.dns-options: -- +ipv4.dns-priority: 0 +ipv4.addresses: -- +ipv4.gateway: -- +ipv4.routes: -- +ipv4.route-metric: -1 +ipv4.route-table: 0 (unspec) +ipv4.routing-rules: -- +ipv4.ignore-auto-routes: no +ipv4.ignore-auto-dns: no +ipv4.dhcp-client-id: -- +ipv4.dhcp-iaid: -- +ipv4.dhcp-timeout: 0 (default) +ipv4.dhcp-send-hostname: yes +ipv4.dhcp-hostname: -- +ipv4.dhcp-fqdn: -- +ipv4.dhcp-hostname-flags: 0x0 (none) +ipv4.never-default: no +ipv4.may-fail: yes +ipv4.required-timeout: -1 (default) +ipv4.dad-timeout: -1 (default) +ipv4.dhcp-vendor-class-identifier: -- +ipv4.dhcp-reject-servers: -- +ipv6.method: auto +ipv6.dns: -- +ipv6.dns-search: -- +ipv6.dns-options: -- +ipv6.dns-priority: 0 +ipv6.addresses: -- +ipv6.gateway: -- +ipv6.routes: -- +ipv6.route-metric: -1 +ipv6.route-table: 0 (unspec) +ipv6.routing-rules: -- +ipv6.ignore-auto-routes: no +ipv6.ignore-auto-dns: no +ipv6.never-default: no +ipv6.may-fail: yes +ipv6.required-timeout: -1 (default) +ipv6.ip6-privacy: -1 (unknown) +ipv6.addr-gen-mode: stable-privacy +ipv6.ra-timeout: 0 (default) +ipv6.dhcp-duid: -- +ipv6.dhcp-iaid: -- +ipv6.dhcp-timeout: 0 (default) +ipv6.dhcp-send-hostname: yes +ipv6.dhcp-hostname: -- +ipv6.dhcp-hostname-flags: 0x0 (none) +ipv6.token: -- +team.config: { + "runner": { + "name": "roundrobin" + }, + "link_watch": { + "name": "ethtool" + } +} +team.notify-peers-count: -1 (unset) +team.notify-peers-interval: -1 (unset) +team.mcast-rejoin-count: -1 (unset) +team.mcast-rejoin-interval: -1 (unset) +team.runner: roundrobin +team.runner-hwaddr-policy: -- +team.runner-tx-hash: -- +team.runner-tx-balancer: -- +team.runner-tx-balancer-interval: -1 (unset) +team.runner-active: yes +team.runner-fast-rate: no +team.runner-sys-prio: -1 (unset) +team.runner-min-ports: -1 (unset) +team.runner-agg-select-policy: -- +team.link-watchers: name=ethtool +proxy.method: none +proxy.browser-only: no +proxy.pac-url: -- +proxy.pac-script: --''' + expected = [{'connection_id': 'Team connection 1', 'connection_uuid': '258e02c2-d9f9-44bb-8d27-887e11aa1828', 'connection_stable_id': None, 'connection_type': 'team', 'connection_interface_name': 'team0', 'connection_autoconnect': 'yes', 'connection_autoconnect_priority': 0, 'connection_autoconnect_retries': -1, 'connection_autoconnect_retries_text': 'default', 'connection_multi_connect': 0, 'connection_multi_connect_text': 'default', 'connection_auth_retries': -1, 'connection_timestamp': 0, 'connection_read_only': 'no', 'connection_permissions': None, 'connection_zone': None, 'connection_master': None, 'connection_slave_type': None, 'connection_autoconnect_slaves': -1, 'connection_autoconnect_slaves_text': 'default', 'connection_secondaries': None, 'connection_gateway_ping_timeout': 0, 'connection_metered': 'unknown', 'connection_lldp': 'default', 'connection_mdns': -1, 'connection_mdns_text': 'default', 'connection_llmnr': -1, 'connection_llmnr_text': 'default', 'connection_dns_over_tls': -1, 'connection_dns_over_tls_text': 'default', 'connection_wait_device_timeout': -1, 'ipv4_method': 'auto', 'ipv4_dns': None, 'ipv4_dns_search': None, 'ipv4_dns_options': None, 'ipv4_dns_priority': 0, 'ipv4_addresses': None, 'ipv4_gateway': None, 'ipv4_routes': None, 'ipv4_route_metric': -1, 'ipv4_route_table': 0, 'ipv4_route_table_text': 'unspec', 'ipv4_routing_rules': None, 'ipv4_ignore_auto_routes': 'no', 'ipv4_ignore_auto_dns': 'no', 'ipv4_dhcp_client_id': None, 'ipv4_dhcp_iaid': None, 'ipv4_dhcp_timeout': 0, 'ipv4_dhcp_timeout_text': 'default', 'ipv4_dhcp_send_hostname': 'yes', 'ipv4_dhcp_hostname': None, 'ipv4_dhcp_fqdn': None, 'ipv4_dhcp_hostname_flags': '0x0', 'ipv4_dhcp_hostname_flags_text': 'none', 'ipv4_never_default': 'no', 'ipv4_may_fail': 'yes', 'ipv4_required_timeout': -1, 'ipv4_required_timeout_text': 'default', 'ipv4_dad_timeout': -1, 'ipv4_dad_timeout_text': 'default', 'ipv4_dhcp_vendor_class_identifier': None, 'ipv4_dhcp_reject_servers': None, 'ipv6_method': 'auto', 'ipv6_dns': None, 'ipv6_dns_search': None, 'ipv6_dns_options': None, 'ipv6_dns_priority': 0, 'ipv6_addresses': None, 'ipv6_gateway': None, 'ipv6_routes': None, 'ipv6_route_metric': -1, 'ipv6_route_table': 0, 'ipv6_route_table_text': 'unspec', 'ipv6_routing_rules': None, 'ipv6_ignore_auto_routes': 'no', 'ipv6_ignore_auto_dns': 'no', 'ipv6_never_default': 'no', 'ipv6_may_fail': 'yes', 'ipv6_required_timeout': -1, 'ipv6_required_timeout_text': 'default', 'ipv6_ip6_privacy': -1, 'ipv6_ip6_privacy_text': 'unknown', 'ipv6_addr_gen_mode': 'stable-privacy', 'ipv6_ra_timeout': 0, 'ipv6_ra_timeout_text': 'default', 'ipv6_dhcp_duid': None, 'ipv6_dhcp_iaid': None, 'ipv6_dhcp_timeout': 0, 'ipv6_dhcp_timeout_text': 'default', 'ipv6_dhcp_send_hostname': 'yes', 'ipv6_dhcp_hostname': None, 'ipv6_dhcp_hostname_flags': '0x0', 'ipv6_dhcp_hostname_flags_text': 'none', 'ipv6_token': None, 'team_config': {'runner': {'name': 'roundrobin'}, 'link_watch': {'name': 'ethtool'}}, 'team_notify_peers_count': -1, 'team_notify_peers_count_text': 'unset', 'team_notify_peers_interval': -1, 'team_notify_peers_interval_text': 'unset', 'team_mcast_rejoin_count': -1, 'team_mcast_rejoin_count_text': 'unset', 'team_mcast_rejoin_interval': -1, 'team_mcast_rejoin_interval_text': 'unset', 'team_runner': 'roundrobin', 'team_runner_hwaddr_policy': None, 'team_runner_tx_hash': None, 'team_runner_tx_balancer': None, 'team_runner_tx_balancer_interval': -1, 'team_runner_tx_balancer_interval_text': 'unset', 'team_runner_active': 'yes', 'team_runner_fast_rate': 'no', 'team_runner_sys_prio': -1, 'team_runner_sys_prio_text': 'unset', 'team_runner_min_ports': -1, 'team_runner_min_ports_text': 'unset', 'team_runner_agg_select_policy': None, 'team_link_watchers': 'name=ethtool', 'proxy_method': 'none', 'proxy_browser_only': 'no', 'proxy_pac_url': None, 'proxy_pac_script': None}] + self.assertEqual(jc.parsers.nmcli.parse(data, quiet=True), expected) + if __name__ == '__main__': unittest.main() From a854f1d6b007466b02149af930d16db7a1712bc1 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Sat, 10 May 2025 11:25:41 -0700 Subject: [PATCH 32/32] doc update --- README.md | 2 +- docs/parsers/bluetoothctl.md | 2 +- docs/parsers/iptables.md | 11 +++- docs/parsers/lsblk.md | 107 +++++++++++++++++++++-------------- docs/parsers/mount.md | 2 +- docs/parsers/nmcli.md | 3 +- docs/parsers/time.md | 2 +- docs/parsers/x509_cert.md | 2 +- man/jc.1 | 4 +- 9 files changed, 85 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 25ee58f8..adf49f5a 100644 --- a/README.md +++ b/README.md @@ -1379,4 +1379,4 @@ cat istio.yaml | jc -p --yaml ] ``` -© 2019-2024 Kelly Brazil \ No newline at end of file +© 2019-2025 Kelly Brazil \ No newline at end of file diff --git a/docs/parsers/bluetoothctl.md b/docs/parsers/bluetoothctl.md index fc82d38b..428493f8 100644 --- a/docs/parsers/bluetoothctl.md +++ b/docs/parsers/bluetoothctl.md @@ -136,4 +136,4 @@ Compatibility: linux Source: [`jc/parsers/bluetoothctl.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/bluetoothctl.py) -Version 1.3 by Jake Ob (iakopap at gmail.com) +Version 1.4 by Jake Ob (iakopap at gmail.com) diff --git a/docs/parsers/iptables.md b/docs/parsers/iptables.md index 8c41a330..b1ea0ad9 100644 --- a/docs/parsers/iptables.md +++ b/docs/parsers/iptables.md @@ -25,6 +25,9 @@ Schema: [ { "chain": string, + "default_policy": string, + "default_packets": integer, + "default_bytes": integer, "rules": [ { "num" integer, @@ -49,6 +52,9 @@ Examples: [ { "chain": "PREROUTING", + "default_policy": "DROP", + "default_packets": 0, + "default_bytes": 0, "rules": [ { "num": 1, @@ -108,6 +114,9 @@ Examples: [ { "chain": "PREROUTING", + "default_policy": "DROP", + "default_packets": "0", + "default_bytes": "0", "rules": [ { "num": "1", @@ -188,4 +197,4 @@ Compatibility: linux Source: [`jc/parsers/iptables.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/iptables.py) -Version 1.11 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.12 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/lsblk.md b/docs/parsers/lsblk.md index 6b128150..2fcebda2 100644 --- a/docs/parsers/lsblk.md +++ b/docs/parsers/lsblk.md @@ -22,46 +22,53 @@ Schema: [ { - "name": string, - "maj_min": string, - "rm": boolean, - "size": string, - "ro": boolean, - "type": string, - "mountpoint": string, - "kname": string, - "fstype": string, - "label": string, - "uuid": string, - "partlabel": string, - "partuuid": string, - "ra": integer, - "model": string, - "serial": string, - "state": string, - "owner": string, - "group": string, - "mode": string, - "alignment": integer, - "min_io": integer, - "opt_io": integer, - "phy_sec": integer, - "log_sec": integer, - "rota": boolean, - "sched": string, - "rq_size": integer, - "disc_aln": integer, - "disc_gran": string, - "disc_max": string, - "disc_zero": boolean, - "wsame": string, - "wwn": string, - "rand": boolean, - "pkname": string, - "hctl": string, - "tran": string, - "rev": string, - "vendor": string + "name": string, + "maj_min": string, + "rm": boolean, + "size": string, + "size_bytes": integer + "ro": boolean, + "type": string, + "mountpoint": string, + "mountpoints": [ + string + ], + "kname": string, + "fstype": string, + "label": string, + "uuid": string, + "partlabel": string, + "partuuid": string, + "ra": integer, + "model": string, + "serial": string, + "state": string, + "owner": string, + "group": string, + "mode": string, + "alignment": integer, + "min_io": integer, + "opt_io": integer, + "phy_sec": integer, + "log_sec": integer, + "rota": boolean, + "sched": string, + "rq_size": integer, + "disc_aln": integer, + "disc_gran": string, + "disc_gran_bytes": integer, + "disc_max": string, + "disc_max_bytes": integer, + "disc_zero": boolean, + "wsame": string, + "wsame_bytes": integer, + "wwn": string, + "rand": boolean, + "pkname": string, + "hctl": string, + "tran": string, + "rev": string, + "vendor": string } ] @@ -74,6 +81,7 @@ Examples: "maj_min": "8:0", "rm": false, "size": "20G", + "size_bytes": 20000000000, "ro": false, "type": "disk", "mountpoint": null @@ -83,6 +91,7 @@ Examples: "maj_min": "8:1", "rm": false, "size": "1G", + "size_bytes": 1000000000 "ro": false, "type": "part", "mountpoint": "/boot" @@ -100,6 +109,7 @@ Examples: "maj_min": "8:0", "rm": false, "size": "20G", + "size_bytes": 20000000000, "ro": false, "type": "disk", "mountpoint": null, @@ -126,9 +136,12 @@ Examples: "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", + "disc_gran_bytes": 0, "disc_max": "0B", + "disc_max_bytes": 0, "disc_zero": false, "wsame": "32M", + "wsame_bytes": 32000000, "wwn": null, "rand": true, "pkname": null, @@ -142,6 +155,7 @@ Examples: "maj_min": "8:1", "rm": false, "size": "1G", + "size_bytes": 1000000000 "ro": false, "type": "part", "mountpoint": "/boot", @@ -168,9 +182,12 @@ Examples: "rq_size": 128, "disc_aln": 0, "disc_gran": "0B", + "disc_gran_bytes": 0, "disc_max": "0B", + "disc_max_bytes": 0, "disc_zero": false, "wsame": "32M", + "wsame_bytes": 32000000, "wwn": null, "rand": true, "pkname": "sda", @@ -192,6 +209,7 @@ Examples: "maj_min": "8:0", "rm": "0", "size": "20G", + "size_bytes": 20000000000, "ro": "0", "type": "disk", "mountpoint": null, @@ -218,9 +236,12 @@ Examples: "rq_size": "128", "disc_aln": "0", "disc_gran": "0B", + "disc_gran_bytes": 0, "disc_max": "0B", + "disc_max_bytes": 0, "disc_zero": "0", "wsame": "32M", + "wsame_bytes": 32000000, "wwn": null, "rand": "1", "pkname": null, @@ -234,6 +255,7 @@ Examples: "maj_min": "8:1", "rm": "0", "size": "1G", + "size_bytes": 1000000000 "ro": "0", "type": "part", "mountpoint": "/boot", @@ -260,9 +282,12 @@ Examples: "rq_size": "128", "disc_aln": "0", "disc_gran": "0B", + "disc_gran_bytes": 0, "disc_max": "0B", + "disc_max_bytes": 0, "disc_zero": "0", "wsame": "32M", + "wsame_bytes": 32000000, "wwn": null, "rand": "1", "pkname": "sda", @@ -299,4 +324,4 @@ Compatibility: linux Source: [`jc/parsers/lsblk.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/lsblk.py) -Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.10 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/mount.md b/docs/parsers/mount.md index fd61b63d..803c735b 100644 --- a/docs/parsers/mount.md +++ b/docs/parsers/mount.md @@ -100,4 +100,4 @@ Compatibility: linux, darwin, freebsd, aix Source: [`jc/parsers/mount.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/mount.py) -Version 1.10 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.11 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/nmcli.md b/docs/parsers/nmcli.md index 6473b2d7..4df779a1 100644 --- a/docs/parsers/nmcli.md +++ b/docs/parsers/nmcli.md @@ -41,6 +41,7 @@ These are documented below. [ { "": string/integer/float, # [0] + "team_config": object, "dhcp4_option_x": { "name": string, "value": string/integer/float, @@ -170,4 +171,4 @@ Compatibility: linux Source: [`jc/parsers/nmcli.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/nmcli.py) -Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/time.md b/docs/parsers/time.md index 1e2c3b43..8ea33f10 100644 --- a/docs/parsers/time.md +++ b/docs/parsers/time.md @@ -157,4 +157,4 @@ Compatibility: linux, darwin, cygwin, aix, freebsd Source: [`jc/parsers/time.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/time.py) -Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/x509_cert.md b/docs/parsers/x509_cert.md index a9d23725..d9e303d3 100644 --- a/docs/parsers/x509_cert.md +++ b/docs/parsers/x509_cert.md @@ -435,4 +435,4 @@ Compatibility: linux, darwin, cygwin, win32, aix, freebsd Source: [`jc/parsers/x509_cert.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/x509_cert.py) -Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/man/jc.1 b/man/jc.1 index 62698bbb..48ea6f49 100644 --- a/man/jc.1 +++ b/man/jc.1 @@ -1,4 +1,4 @@ -.TH jc 1 2024-12-20 1.25.5 "JSON Convert" +.TH jc 1 2025-05-10 1.25.5 "JSON Convert" .SH NAME \fBjc\fP \- JSON Convert JSONifies the output of many CLI tools, file-types, and strings @@ -1637,6 +1637,6 @@ Kelly Brazil (kellyjonbrazil@gmail.com) https://github.com/kellyjonbrazil/jc .SH COPYRIGHT -Copyright (c) 2019-2024 Kelly Brazil +Copyright (c) 2019-2025 Kelly Brazil License: MIT License \ No newline at end of file