From 4cd721be8595db52b620cc26cd455d95bf56b85b Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Sun, 30 Jul 2023 10:08:39 -0700 Subject: [PATCH] Dev v1.23.4 (#439) * version bump * fix regex for crlf line endings * Completed Ip_route parser (#429) * tests * Merge pull request #398 from kellyjonbrazil/dev Dev v1.23.2 * Merge pull request #398 from kellyjonbrazil/dev Dev v1.23.2 --------- Co-authored-by: Kelly Brazil Co-authored-by: Jjack3032 * formatting * doc update * use splitlines * formatting * formatting * Parser for `find` linux command (#434) * Added find parser and tests for Centos 7.7 and Ubuntu 18.04 * Added a test file, changed logic, and included a case for permission denied returned by find. * Added a few more lines to the tests * Changed logic for setting values to null and updated test cases. * doc update * doc update * Added proc_net_tcp parser (#421) Co-authored-by: Kelly Brazil * clean up net_tcp parser * add resolve.conf test files * doc update * add resolve.conf parser * doc update * add sortlist functionality * add resolve.conf parser tests * doc update --------- Co-authored-by: Julian5555 <58196809+Julian5555@users.noreply.github.com> Co-authored-by: Jjack3032 Co-authored-by: solomonleang <124934439+solomonleang@users.noreply.github.com> Co-authored-by: AlvinSolomon <41175627+AlvinSolomon@users.noreply.github.com> --- CHANGELOG | 8 +- README.md | 3 + completions/jc_bash_completion.sh | 4 +- completions/jc_zsh_completion.sh | 9 +- docs/parsers/certbot.md | 2 +- docs/parsers/find.md | 82 ++++++ docs/parsers/ip_route.md | 74 ++++++ docs/parsers/proc_net_tcp.md | 186 +++++++++++++ docs/parsers/resolve_conf.md | 83 ++++++ jc/lib.py | 6 +- jc/parsers/certbot.py | 4 +- jc/parsers/find.py | 137 ++++++++++ jc/parsers/ip_route.py | 145 ++++++++++ jc/parsers/proc.py | 2 + jc/parsers/proc_net_tcp.py | 293 +++++++++++++++++++++ jc/parsers/resolve_conf.py | 171 ++++++++++++ man/jc.1 | 22 +- setup.py | 2 +- tests/fixtures/centos-7.7/find.json | 13 + tests/fixtures/centos-7.7/find.out | 13 + tests/fixtures/centos-7.7/ip_route.json | 31 +++ tests/fixtures/centos-7.7/ip_route.out | 4 + tests/fixtures/generic/resolve.conf-1 | 12 + tests/fixtures/generic/resolve.conf-1.json | 1 + tests/fixtures/generic/resolve.conf-2 | 4 + tests/fixtures/generic/resolve.conf-2.json | 1 + tests/fixtures/generic/resolve.conf-3 | 7 + tests/fixtures/generic/resolve.conf-3.json | 1 + tests/fixtures/generic/resolve.conf-4 | 5 + tests/fixtures/generic/resolve.conf-4.json | 1 + tests/fixtures/linux-proc/net_tcp | 28 ++ tests/fixtures/linux-proc/net_tcp.json | 1 + tests/fixtures/linux-proc/net_tcp6 | 9 + tests/fixtures/linux-proc/net_tcp6.json | 1 + tests/fixtures/ubuntu-18.04/find.json | 13 + tests/fixtures/ubuntu-18.04/find.out | 13 + tests/fixtures/ubuntu-18.04/ip_route.json | 31 +++ tests/fixtures/ubuntu-18.04/ip_route.out | 4 + tests/test_find.py | 43 +++ tests/test_ip_route.py | 51 ++++ tests/test_proc_net_tcp.py | 53 ++++ tests/test_resolve_conf.py | 83 ++++++ 42 files changed, 1645 insertions(+), 11 deletions(-) create mode 100644 docs/parsers/find.md create mode 100644 docs/parsers/ip_route.md create mode 100644 docs/parsers/proc_net_tcp.md create mode 100644 docs/parsers/resolve_conf.md create mode 100644 jc/parsers/find.py create mode 100644 jc/parsers/ip_route.py create mode 100644 jc/parsers/proc_net_tcp.py create mode 100644 jc/parsers/resolve_conf.py create mode 100644 tests/fixtures/centos-7.7/find.json create mode 100644 tests/fixtures/centos-7.7/find.out create mode 100644 tests/fixtures/centos-7.7/ip_route.json create mode 100644 tests/fixtures/centos-7.7/ip_route.out create mode 100644 tests/fixtures/generic/resolve.conf-1 create mode 100644 tests/fixtures/generic/resolve.conf-1.json create mode 100644 tests/fixtures/generic/resolve.conf-2 create mode 100644 tests/fixtures/generic/resolve.conf-2.json create mode 100644 tests/fixtures/generic/resolve.conf-3 create mode 100644 tests/fixtures/generic/resolve.conf-3.json create mode 100644 tests/fixtures/generic/resolve.conf-4 create mode 100644 tests/fixtures/generic/resolve.conf-4.json create mode 100644 tests/fixtures/linux-proc/net_tcp create mode 100644 tests/fixtures/linux-proc/net_tcp.json create mode 100644 tests/fixtures/linux-proc/net_tcp6 create mode 100644 tests/fixtures/linux-proc/net_tcp6.json create mode 100644 tests/fixtures/ubuntu-18.04/find.json create mode 100644 tests/fixtures/ubuntu-18.04/find.out create mode 100644 tests/fixtures/ubuntu-18.04/ip_route.json create mode 100644 tests/fixtures/ubuntu-18.04/ip_route.out create mode 100644 tests/test_find.py create mode 100644 tests/test_ip_route.py create mode 100644 tests/test_proc_net_tcp.py create mode 100644 tests/test_resolve_conf.py diff --git a/CHANGELOG b/CHANGELOG index 9200b6f6..3d5645f6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,12 @@ jc changelog +20230730 v1.23.4 +- Add `/etc/resolve.conf` file parser +- Add `/proc/net/tcp` and `/proc/net/tcp6` file parser +- Add `find` command parser +- Add `ip route` command parser +- Fix `certbot` command parser to be more robust with different line endings + 20230621 v1.23.3 - Add `lsattr` command parser - Add `srt` file parser @@ -13,7 +20,6 @@ jc changelog - Enhance `ss` command parser to support extended options - Enhance the compatibility warning message - Fix `bluetoothctl` command parser for some mouse devices -- Fix `certbot` command parser to be more robust with different line endings - Fix `ping` command parsers for output with missing hostname - Fix `stat` command parser for older versions that may not contain all fields - Fix deprecated option in `setup.cfg` diff --git a/README.md b/README.md index d2663ff2..dfa0ddf6 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,7 @@ option. | `--email-address` | Email Address string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/email_address) | | `--env` | `env` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/env) | | `--file` | `file` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/file) | +| `--find` | `find` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/find) | | `--findmnt` | `findmnt` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/findmnt) | | `--finger` | `finger` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/finger) | | `--free` | `free` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/free) | @@ -210,6 +211,7 @@ option. | `--iostat-s` | `iostat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat_s) | | `--ip-address` | IPv4 and IPv6 Address string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ip_address) | | `--iptables` | `iptables` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iptables) | +| `--ip-route` | `ip route` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ip_route) | | `--iw-scan` | `iw dev [device] scan` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iw_scan) | | `--iwconfig` | `iwconfig` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iwconfig) | | `--jar-manifest` | Java MANIFEST.MF file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/jar_manifest) | @@ -248,6 +250,7 @@ option. | `--postconf` | `postconf -M` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/postconf) | | `--proc` | `/proc/` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/proc) | | `--ps` | `ps` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ps) | +| `--resolve-conf` | `/etc/resolve.conf` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/resolve_conf) | | `--route` | `route` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/route) | | `--rpm-qi` | `rpm -qi` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/rpm_qi) | | `--rsync` | `rsync` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync) | diff --git a/completions/jc_bash_completion.sh b/completions/jc_bash_completion.sh index 04f9fe99..2c02ac30 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 arp blkid bluetoothctl cbt certbot chage cksum crontab date df dig dmidecode dpkg du env file findmnt finger free git gpg hciconfig id ifconfig iostat iptables iw iwconfig jobs last lastb ls lsattr lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq os-prober pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc who xrandr zipinfo zpool) - jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --date --datetime-iso --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --iptables --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsattr --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --openvpn --os-prober --passwd --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --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-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 --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --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 --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status) + jc_commands=(acpi airport arp blkid bluetoothctl cbt certbot chage cksum crontab date df dig dmidecode dpkg du env file findmnt finger free git gpg hciconfig id ifconfig iostat ip iptables iw iwconfig jobs last lastb ls lsattr lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq os-prober pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc who xrandr zipinfo zpool) + jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --date --datetime-iso --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsattr --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --openvpn --os-prober --passwd --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --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 --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 --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --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 --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 a1ad1678..0625204d 100644 --- a/completions/jc_zsh_completion.sh +++ b/completions/jc_zsh_completion.sh @@ -9,7 +9,7 @@ _jc() { jc_help_options jc_help_options_describe \ jc_special_options jc_special_options_describe - jc_commands=(acpi airport arp blkid bluetoothctl cbt certbot chage cksum crontab date df dig dmidecode dpkg du env file findmnt finger free git gpg hciconfig id ifconfig iostat iptables iw iwconfig jobs last lastb ls lsattr lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq os-prober pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc who xrandr zipinfo zpool) + jc_commands=(acpi airport arp blkid bluetoothctl cbt certbot chage cksum crontab date df dig dmidecode dpkg du env file findmnt finger free git gpg hciconfig id ifconfig iostat ip iptables iw iwconfig jobs last lastb ls lsattr lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq os-prober pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc who xrandr zipinfo zpool) jc_commands_describe=( 'acpi:run "acpi" command with magic syntax.' 'airport:run "airport" command with magic syntax.' @@ -38,6 +38,7 @@ _jc() { 'id:run "id" command with magic syntax.' 'ifconfig:run "ifconfig" command with magic syntax.' 'iostat:run "iostat" command with magic syntax.' + 'ip:run "ip" command with magic syntax.' 'iptables:run "iptables" command with magic syntax.' 'iw:run "iw" command with magic syntax.' 'iwconfig:run "iwconfig" command with magic syntax.' @@ -108,7 +109,7 @@ _jc() { 'zipinfo:run "zipinfo" command with magic syntax.' 'zpool:run "zpool" command with magic syntax.' ) - jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --date --datetime-iso --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --iptables --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsattr --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --openvpn --os-prober --passwd --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --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-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 --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --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 --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status) + jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --date --datetime-iso --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsattr --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --openvpn --os-prober --passwd --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --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 --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 --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --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' @@ -141,6 +142,7 @@ _jc() { '--email-address:Email Address string parser' '--env:`env` command parser' '--file:`file` command parser' + '--find:`find` command parser' '--findmnt:`findmnt` command parser' '--finger:`finger` command parser' '--free:`free` command parser' @@ -164,6 +166,7 @@ _jc() { '--iostat-s:`iostat` command streaming parser' '--ip-address:IPv4 and IPv6 Address string parser' '--iptables:`iptables` command parser' + '--ip-route:`ip route` command parser' '--iw-scan:`iw dev [device] scan` command parser' '--iwconfig:`iwconfig` command parser' '--jar-manifest:Java MANIFEST.MF file parser' @@ -240,6 +243,7 @@ _jc() { '--proc-net-packet:`/proc/net/packet` file parser' '--proc-net-protocols:`/proc/net/protocols` file parser' '--proc-net-route:`/proc/net/route` file parser' + '--proc-net-tcp:`/proc/net/tcp` and `/proc/net/tcp6` file parser' '--proc-net-unix:`/proc/net/unix` file parser' '--proc-pid-fdinfo:`/proc//fdinfo/` file parser' '--proc-pid-io:`/proc//io` file parser' @@ -251,6 +255,7 @@ _jc() { '--proc-pid-statm:`/proc//statm` file parser' '--proc-pid-status:`/proc//status` file parser' '--ps:`ps` command parser' + '--resolve-conf:`/etc/resolve.conf` file parser' '--route:`route` command parser' '--rpm-qi:`rpm -qi` command parser' '--rsync:`rsync` command parser' diff --git a/docs/parsers/certbot.md b/docs/parsers/certbot.md index ec23f55c..70be947c 100644 --- a/docs/parsers/certbot.md +++ b/docs/parsers/certbot.md @@ -158,4 +158,4 @@ Returns: ### Parser Information Compatibility: linux, darwin, cygwin, win32, aix, freebsd -Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/docs/parsers/find.md b/docs/parsers/find.md new file mode 100644 index 00000000..ce77c63f --- /dev/null +++ b/docs/parsers/find.md @@ -0,0 +1,82 @@ +[Home](https://kellyjonbrazil.github.io/jc/) + + +# jc.parsers.find + +jc - JSON Convert `find` command output parser + +This parser returns a list of objects by default and a list of strings if +the `--raw` option is used. + +Usage (cli): + + $ find | jc --find + +Usage (module): + + import jc + result = jc.parse('find', find_command_output) + +Schema: + + [ + { + "path": string, + "node": string, + "error": string + } + ] + +Examples: + + $ find | jc --find -p + [ + { + "path": "./directory" + "node": "filename" + }, + { + "path": "./anotherdirectory" + "node": "anotherfile" + }, + { + "path": null + "node": null + "error": "find: './inaccessible': Permission denied" + } + ... + ] + + $ find | jc --find -p -r + [ + "./templates/readme_template", + "./templates/manpage_template", + "./.github/workflows/pythonapp.yml", + ... + ] + + + +### parse + +```python +def parse(data, raw=False, quiet=False) +``` + +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 raw strings or + List of Dictionaries of processed structured data + +### Parser Information +Compatibility: linux + +Version 1.0 by Solomon Leang (solomonleang@gmail.com) diff --git a/docs/parsers/ip_route.md b/docs/parsers/ip_route.md new file mode 100644 index 00000000..d0125321 --- /dev/null +++ b/docs/parsers/ip_route.md @@ -0,0 +1,74 @@ +[Home](https://kellyjonbrazil.github.io/jc/) + + +# jc.parsers.ip\_route + +jc - JSON Convert `ip route` command output parser + +Usage (cli): + + $ ip route | jc --ip-route + +or + + $ jc ip-route + +Usage (module): + + import jc + result = jc.parse('ip_route', ip_route_command_output) + +Schema: + + [ + { + "ip": string, + "via": string, + "dev": string, + "metric": integer, + "proto": string, + "scope": string, + "src": string, + "via": string, + "status": string + } + ] + +Examples: + + $ ip route | jc --ip-route -p + [ + { + "ip": "10.0.2.0/24", + "dev": "enp0s3", + "proto": "kernel", + "scope": "link", + "src": "10.0.2.15", + "metric": 100 + } + ] + + + +### parse + +```python +def parse(data, raw=False, quiet=False) +``` + +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 Json objects if data is processed and Raw data if raw = true. + +### Parser Information +Compatibility: linux + +Version 1.0 by Julian Jackson (jackson.julian55@yahoo.com) diff --git a/docs/parsers/proc_net_tcp.md b/docs/parsers/proc_net_tcp.md new file mode 100644 index 00000000..3a276976 --- /dev/null +++ b/docs/parsers/proc_net_tcp.md @@ -0,0 +1,186 @@ +[Home](https://kellyjonbrazil.github.io/jc/) + + +# jc.parsers.proc\_net\_tcp + +jc - JSON Convert `/proc/net/tcp` and `proc/net/tcp6` file parser + +IPv4 and IPv6 addresses are converted to standard notation unless the raw +(--raw) option is used. + +Usage (cli): + + $ cat /proc/net/tcp | jc --proc + +or + + $ jc /proc/net/tcp + +or + + $ cat /proc/net/tcp | jc --proc-net-tcp + +Usage (module): + + import jc + result = jc.parse('proc', proc_net_tcp_file) + +or + + import jc + result = jc.parse('proc_net_tcp', proc_net_tcp_file) + +Schema: + +Field names and types gathered from the following: + +https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt + +https://github.com/torvalds/linux/blob/master/net/ipv4/tcp_ipv4.c + +https://github.com/torvalds/linux/blob/master/net/ipv6/tcp_ipv6.c + + [ + { + "entry": integer, + "local_address": string, + "local_port": integer, + "remote_address": string, + "remote_port": integer, + "state": string, + "tx_queue": string, + "rx_queue": string, + "timer_active": integer, + "jiffies_until_timer_expires": string, + "unrecovered_rto_timeouts": string, + "uid": integer, + "unanswered_0_window_probes": integer, + "inode": integer, + "sock_ref_count": integer, + "sock_mem_loc": string, + "retransmit_timeout": integer, + "soft_clock_tick": integer, + "ack_quick_pingpong": integer, + "sending_congestion_window": integer, + "slow_start_size_threshold": integer + } + ] + +Examples: + + $ cat /proc/net/tcp | jc --proc -p + [ + { + "entry": "0", + "local_address": "10.0.0.28", + "local_port": 42082, + "remote_address": "64.12.0.108", + "remote_port": 80, + "state": "04", + "tx_queue": "00000001", + "rx_queue": "00000000", + "timer_active": 1, + "jiffies_until_timer_expires": "00000015", + "unrecovered_rto_timeouts": "00000000", + "uid": 0, + "unanswered_0_window_probes": 0, + "inode": 0, + "sock_ref_count": 3, + "sock_mem_loc": "ffff8c7a0de930c0", + "retransmit_timeout": 21, + "soft_clock_tick": 4, + "ack_quick_pingpong": 30, + "sending_congestion_window": 10, + "slow_start_size_threshold": -1 + }, + { + "entry": "1", + "local_address": "10.0.0.28", + "local_port": 38864, + "remote_address": "104.244.42.65", + "remote_port": 80, + "state": "06", + "tx_queue": "00000000", + "rx_queue": "00000000", + "timer_active": 3, + "jiffies_until_timer_expires": "000007C5", + "unrecovered_rto_timeouts": "00000000", + "uid": 0, + "unanswered_0_window_probes": 0, + "inode": 0, + "sock_ref_count": 3, + "sock_mem_loc": "ffff8c7a12d31aa0" + }, + ... + ] + + $ cat /proc/net/tcp | jc --proc -p -r + [ + { + "entry": "1", + "local_address": "1C00000A", + "local_port": "A462", + "remote_address": "6C000C40", + "remote_port": "0050", + "state": "04", + "tx_queue": "00000001", + "rx_queue": "00000000", + "timer_active": "01", + "jiffies_until_timer_expires": "00000015", + "unrecovered_rto_timeouts": "00000000", + "uid": "0", + "unanswered_0_window_probes": "0", + "inode": "0", + "sock_ref_count": "3", + "sock_mem_loc": "ffff8c7a0de930c0", + "retransmit_timeout": "21", + "soft_clock_tick": "4", + "ack_quick_pingpong": "30", + "sending_congestion_window": "10", + "slow_start_size_threshold": "-1" + }, + { + "entry": "2", + "local_address": "1C00000A", + "local_port": "97D0", + "remote_address": "412AF468", + "remote_port": "0050", + "state": "06", + "tx_queue": "00000000", + "rx_queue": "00000000", + "timer_active": "03", + "jiffies_until_timer_expires": "000007C5", + "unrecovered_rto_timeouts": "00000000", + "uid": "0", + "unanswered_0_window_probes": "0", + "inode": "0", + "sock_ref_count": "3", + "sock_mem_loc": "ffff8c7a12d31aa0" + }, + ... + ] + + + +### parse + +```python +def parse(data: str, raw: bool = False, quiet: bool = False) -> List[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: + + List of Dictionaries. Raw or processed structured data. + +### Parser Information +Compatibility: linux + +Version 1.0 by Alvin Solomon (alvinms01@gmail.com) diff --git a/docs/parsers/resolve_conf.md b/docs/parsers/resolve_conf.md new file mode 100644 index 00000000..278c0fb8 --- /dev/null +++ b/docs/parsers/resolve_conf.md @@ -0,0 +1,83 @@ +[Home](https://kellyjonbrazil.github.io/jc/) + + +# jc.parsers.resolve\_conf + +jc - JSON Convert `/etc/resolve.conf` file parser + +This parser may be more forgiving than the system parser. For example, if +multiple `search` lists are defined, this parser will append all entries to +the `search` field, while the system parser may only use the list from the +last defined instance. + +Usage (cli): + + $ cat /etc/resolve.conf | jc --resolve-conf + +Usage (module): + + import jc + result = jc.parse('resolve_conf', resolve_conf_output) + +Schema: + + { + "domain": string, + "search": [ + string + ], + "nameservers": [ + string + ], + "options": [ + string + ], + "sortlist": [ + string + ] + } + + +Examples: + + $ cat /etc/resolve.conf | jc --resolve-conf -p + { + "search": [ + "eng.myprime.com", + "dev.eng.myprime.com", + "labs.myprime.com", + "qa.myprime.com" + ], + "nameservers": [ + "10.136.17.15" + ], + "options": [ + "rotate", + "ndots:1" + ] + } + + + +### parse + +```python +def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType +``` + +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, darwin, cygwin, win32, aix, freebsd + +Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/jc/lib.py b/jc/lib.py index 526a8606..36f02fda 100644 --- a/jc/lib.py +++ b/jc/lib.py @@ -9,7 +9,7 @@ from .jc_types import ParserInfoType, JSONDictType from jc import appdirs -__version__ = '1.23.3' +__version__ = '1.23.4' parsers: List[str] = [ 'acpi', @@ -43,6 +43,7 @@ parsers: List[str] = [ 'email-address', 'env', 'file', + 'find', 'findmnt', 'finger', 'free', @@ -66,6 +67,7 @@ parsers: List[str] = [ 'iostat-s', 'ip-address', 'iptables', + 'ip-route', 'iso-datetime', 'iw-scan', 'iwconfig', @@ -143,6 +145,7 @@ parsers: List[str] = [ 'proc-net-packet', 'proc-net-protocols', 'proc-net-route', + 'proc-net-tcp', 'proc-net-unix', 'proc-pid-fdinfo', 'proc-pid-io', @@ -154,6 +157,7 @@ parsers: List[str] = [ 'proc-pid-statm', 'proc-pid-status', 'ps', + 'resolve-conf', 'route', 'rpm-qi', 'rsync', diff --git a/jc/parsers/certbot.py b/jc/parsers/certbot.py index 4fa7c65d..1bf442c0 100644 --- a/jc/parsers/certbot.py +++ b/jc/parsers/certbot.py @@ -138,7 +138,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.1' + version = '1.2' description = '`certbot` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -201,7 +201,7 @@ def parse( if jc.utils.has_data(data): - cert_pattern = re.compile(r'^Found the following certs:$', re.MULTILINE) + cert_pattern = re.compile(r'^Found the following certs:\r?$', re.MULTILINE) if re.search(cert_pattern, data): cmd_option = 'certificates' diff --git a/jc/parsers/find.py b/jc/parsers/find.py new file mode 100644 index 00000000..059cf30d --- /dev/null +++ b/jc/parsers/find.py @@ -0,0 +1,137 @@ +"""jc - JSON Convert `find` command output parser + +This parser returns a list of objects by default and a list of strings if +the `--raw` option is used. + +Usage (cli): + + $ find | jc --find + +Usage (module): + + import jc + result = jc.parse('find', find_command_output) + +Schema: + + [ + { + "path": string, + "node": string, + "error": string + } + ] + +Examples: + + $ find | jc --find -p + [ + { + "path": "./directory" + "node": "filename" + }, + { + "path": "./anotherdirectory" + "node": "anotherfile" + }, + { + "path": null + "node": null + "error": "find: './inaccessible': Permission denied" + } + ... + ] + + $ find | jc --find -p -r + [ + "./templates/readme_template", + "./templates/manpage_template", + "./.github/workflows/pythonapp.yml", + ... + ] +""" +import jc.utils + + +class info(): + """Provides parser metadata (version, author, etc.)""" + version = '1.0' + description = '`find` command parser' + author = 'Solomon Leang' + author_email = 'solomonleang@gmail.com' + compatible = ['linux'] + tags = ['command'] + + +__version__ = info.version + + +def _process(proc_data): + """ + Final processing to conform to the schema. + + Parameters: + + proc_data: (List of Strings) raw structured data to process + + Returns: + + List of Dictionaries. Structured data to conform to the schema. + """ + processed = [] + + for index in proc_data: + path, node, error = "", "", "" + + if index == ".": + node = "." + elif index.startswith('find: '): + error = index + else: + try: + path, node = index.rsplit('/', maxsplit=1) + except ValueError: + pass + + proc_line = { + 'path': path if path else None, + 'node': node if node else None + } + + if error: + proc_line.update( + {'error': error} + ) + + processed.append(proc_line) + + return processed + + +def parse(data, raw=False, quiet=False): + """ + 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 raw strings or + List of Dictionaries of processed structured data + """ + jc.utils.compatibility(__name__, info.compatible, quiet) + jc.utils.input_type_check(data) + + raw_output = [] + + if jc.utils.has_data(data): + raw_output = data.splitlines() + + if raw: + return raw_output + else: + return _process(raw_output) \ No newline at end of file diff --git a/jc/parsers/ip_route.py b/jc/parsers/ip_route.py new file mode 100644 index 00000000..0396dd32 --- /dev/null +++ b/jc/parsers/ip_route.py @@ -0,0 +1,145 @@ +"""jc - JSON Convert `ip route` command output parser + +Usage (cli): + + $ ip route | jc --ip-route + +or + + $ jc ip-route + +Usage (module): + + import jc + result = jc.parse('ip_route', ip_route_command_output) + +Schema: + + [ + { + "ip": string, + "via": string, + "dev": string, + "metric": integer, + "proto": string, + "scope": string, + "src": string, + "via": string, + "status": string + } + ] + +Examples: + + $ ip route | jc --ip-route -p + [ + { + "ip": "10.0.2.0/24", + "dev": "enp0s3", + "proto": "kernel", + "scope": "link", + "src": "10.0.2.15", + "metric": 100 + } + ] +""" +from typing import Dict + +import jc.utils + + +class info: + """Provides parser metadata (version, author, etc.)""" + version = '1.0' + description = '`ip route` command parser' + author = 'Julian Jackson' + author_email = 'jackson.julian55@yahoo.com' + compatible = ['linux'] + magic_commands = ['ip route'] + tags = ['command'] + + +__version__ = info.version + + +def parse(data, raw=False, quiet=False): + """ + 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 Json objects if data is processed and Raw data if raw = true. + """ + structure = {} + items = [] + lines = data.splitlines() + index = 0 + place = 0 + inc = 0 + + for line in lines: + temp = line.split() + for word in temp: + if word == 'via': + y = {'via': temp[place + 1]} + place += 1 + structure.update(y) + elif word == 'dev': + y = {'dev': temp[place + 1]} + place += 1 + structure.update(y) + elif word == 'metric': + if raw: + y = {'metric': temp[place + 1]} + else: + y = {'metric': jc.utils.convert_to_int(temp[place+1])} + place += 1 + structure.update(y) + elif word == 'proto': + y = {'proto': temp[place + 1]} + place += 1 + structure.update(y) + elif word == 'scope': + y = {'scope': temp[place + 1]} + place += 1 + structure.update(y) + elif word == 'src': + y = {'src': temp[place + 1]} + place += 1 + structure.update(y) + elif word == 'status': + y = {'status': temp[place + 1]} + place += 1 + structure.update(y) + elif word == 'default': + y = {'ip': 'default'} + place += 1 + structure.update(y) + elif word == 'linkdown': + y = {'status': 'linkdown'} + place += 1 + structure.update(y) + else: + y = {'ip': temp[0]} + place += 1 + structure.update(y) + if y.get("ip") != "": + items.append(structure) + structure = {} + place = 0 + index += 1 + inc += 1 + + jc.utils.compatibility(__name__, info.compatible, quiet) + jc.utils.input_type_check(data) + + if not jc.utils.has_data(data): + return [] + + return items diff --git a/jc/parsers/proc.py b/jc/parsers/proc.py index 628578e6..7d2ac8b1 100644 --- a/jc/parsers/proc.py +++ b/jc/parsers/proc.py @@ -194,6 +194,7 @@ def parse( net_packet_p = re.compile(r'^sk RefCnt Type Proto Iface R Rmem User Inode\n') net_protocols_p = re.compile(r'^protocol size sockets memory press maxhdr slab module cl co di ac io in de sh ss gs se re sp bi br ha uh gp em\n') net_route_p = re.compile(r'^Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\tIRTT\s+\n') + net_tcp_p = re.compile(r'^\s+sl\s+local_address\s+(?:rem_address|remote_address)\s+st\s+tx_queue\s+rx_queue\s+tr\s+tm->when\s+retrnsmt\s+uid\s+timeout\s+inode') net_unix_p = re.compile(r'^Num RefCount Protocol Flags Type St Inode Path\n') pid_fdinfo_p = re.compile(r'^pos:\t\d+\nflags:\t\d+\nmnt_id:\t\d+\n') @@ -249,6 +250,7 @@ def parse( net_packet_p: 'proc_net_packet', net_protocols_p: 'proc_net_protocols', net_route_p: 'proc_net_route', + net_tcp_p: 'proc_net_tcp', net_unix_p: 'proc_net_unix', net_ipv6_route_p: 'proc_net_ipv6_route', # before net_dev_mcast net_dev_mcast_p: 'proc_net_dev_mcast', # after net_ipv6_route diff --git a/jc/parsers/proc_net_tcp.py b/jc/parsers/proc_net_tcp.py new file mode 100644 index 00000000..99c3ddac --- /dev/null +++ b/jc/parsers/proc_net_tcp.py @@ -0,0 +1,293 @@ +"""jc - JSON Convert `/proc/net/tcp` and `proc/net/tcp6` file parser + +IPv4 and IPv6 addresses are converted to standard notation unless the raw +(--raw) option is used. + +Usage (cli): + + $ cat /proc/net/tcp | jc --proc + +or + + $ jc /proc/net/tcp + +or + + $ cat /proc/net/tcp | jc --proc-net-tcp + +Usage (module): + + import jc + result = jc.parse('proc', proc_net_tcp_file) + +or + + import jc + result = jc.parse('proc_net_tcp', proc_net_tcp_file) + +Schema: + +Field names and types gathered from the following: + +https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt + +https://github.com/torvalds/linux/blob/master/net/ipv4/tcp_ipv4.c + +https://github.com/torvalds/linux/blob/master/net/ipv6/tcp_ipv6.c + + [ + { + "entry": integer, + "local_address": string, + "local_port": integer, + "remote_address": string, + "remote_port": integer, + "state": string, + "tx_queue": string, + "rx_queue": string, + "timer_active": integer, + "jiffies_until_timer_expires": string, + "unrecovered_rto_timeouts": string, + "uid": integer, + "unanswered_0_window_probes": integer, + "inode": integer, + "sock_ref_count": integer, + "sock_mem_loc": string, + "retransmit_timeout": integer, + "soft_clock_tick": integer, + "ack_quick_pingpong": integer, + "sending_congestion_window": integer, + "slow_start_size_threshold": integer + } + ] + +Examples: + + $ cat /proc/net/tcp | jc --proc -p + [ + { + "entry": "0", + "local_address": "10.0.0.28", + "local_port": 42082, + "remote_address": "64.12.0.108", + "remote_port": 80, + "state": "04", + "tx_queue": "00000001", + "rx_queue": "00000000", + "timer_active": 1, + "jiffies_until_timer_expires": "00000015", + "unrecovered_rto_timeouts": "00000000", + "uid": 0, + "unanswered_0_window_probes": 0, + "inode": 0, + "sock_ref_count": 3, + "sock_mem_loc": "ffff8c7a0de930c0", + "retransmit_timeout": 21, + "soft_clock_tick": 4, + "ack_quick_pingpong": 30, + "sending_congestion_window": 10, + "slow_start_size_threshold": -1 + }, + { + "entry": "1", + "local_address": "10.0.0.28", + "local_port": 38864, + "remote_address": "104.244.42.65", + "remote_port": 80, + "state": "06", + "tx_queue": "00000000", + "rx_queue": "00000000", + "timer_active": 3, + "jiffies_until_timer_expires": "000007C5", + "unrecovered_rto_timeouts": "00000000", + "uid": 0, + "unanswered_0_window_probes": 0, + "inode": 0, + "sock_ref_count": 3, + "sock_mem_loc": "ffff8c7a12d31aa0" + }, + ... + ] + + $ cat /proc/net/tcp | jc --proc -p -r + [ + { + "entry": "1", + "local_address": "1C00000A", + "local_port": "A462", + "remote_address": "6C000C40", + "remote_port": "0050", + "state": "04", + "tx_queue": "00000001", + "rx_queue": "00000000", + "timer_active": "01", + "jiffies_until_timer_expires": "00000015", + "unrecovered_rto_timeouts": "00000000", + "uid": "0", + "unanswered_0_window_probes": "0", + "inode": "0", + "sock_ref_count": "3", + "sock_mem_loc": "ffff8c7a0de930c0", + "retransmit_timeout": "21", + "soft_clock_tick": "4", + "ack_quick_pingpong": "30", + "sending_congestion_window": "10", + "slow_start_size_threshold": "-1" + }, + { + "entry": "2", + "local_address": "1C00000A", + "local_port": "97D0", + "remote_address": "412AF468", + "remote_port": "0050", + "state": "06", + "tx_queue": "00000000", + "rx_queue": "00000000", + "timer_active": "03", + "jiffies_until_timer_expires": "000007C5", + "unrecovered_rto_timeouts": "00000000", + "uid": "0", + "unanswered_0_window_probes": "0", + "inode": "0", + "sock_ref_count": "3", + "sock_mem_loc": "ffff8c7a12d31aa0" + }, + ... + ] +""" +import binascii +import socket +import struct +from typing import List, Dict +import jc.utils + + +class info(): + """Provides parser metadata (version, author, etc.)""" + version = '1.0' + description = '`/proc/net/tcp` and `/proc/net/tcp6` file parser' + author = 'Alvin Solomon' + author_email = 'alvinms01@gmail.com' + compatible = ['linux'] + tags = ['file'] + hidden = True + + +__version__ = info.version + + +def hex_to_ip(hexaddr: str) -> str: + if len(hexaddr) == 8: + addr_long = int(hexaddr, 16) + return socket.inet_ntop(socket.AF_INET, struct.pack("IIII', addr) + addr_bytes = struct.pack('@IIII', *addr_tup) + return socket.inet_ntop(socket.AF_INET6, addr_bytes) + + return '' + + +def _process(proc_data: List[Dict]) -> List[Dict]: + """ + Final processing to conform to the schema. + + Parameters: + + proc_data: (List of Dictionaries) raw structured data to process + + Returns: + + List of Dictionaries. Structured to conform to the schema. + """ + int_list = { + 'timer_active', 'uid', 'unanswered_0_window_probes', 'inode', + 'sock_ref_count', 'retransmit_timeout', 'soft_clock_tick', + 'ack_quick_pingpong', 'sending_congestion_window', + 'slow_start_size_threshold' + } + + for entry in proc_data: + if 'local_address' in entry: + entry['local_address'] = hex_to_ip(entry['local_address']) + entry['local_port'] = int(entry['local_port'], 16) + entry['remote_address'] = hex_to_ip(entry['remote_address']) + entry['remote_port'] = int(entry['remote_port'], 16) + + for item in int_list: + if item in entry: + entry[item] = jc.utils.convert_to_int(entry[item]) + + return proc_data + + +def parse( + data: str, + raw: bool = False, + quiet: bool = False +) -> List[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: + + List of Dictionaries. Raw or processed structured data. + """ + jc.utils.compatibility(__name__, info.compatible, quiet) + jc.utils.input_type_check(data) + + raw_output: List = [] + + if jc.utils.has_data(data): + + line_data = data.splitlines()[1:] + + for entry in line_data: + line = entry.split() + output_line = {} + output_line['entry'] = line[0][:-1] + + local_ip_port = line[1] + local_ip = local_ip_port.split(':')[0] + local_port = local_ip_port.split(':')[1] + + output_line['local_address'] = local_ip + output_line['local_port'] = local_port + + remote_ip_port = line[2] + remote_ip = remote_ip_port.split(':')[0] + remote_port = remote_ip_port.split(':')[1] + + output_line['remote_address'] = remote_ip + output_line['remote_port'] = remote_port + + output_line['state'] = line[3] + output_line['tx_queue'] = line[4][:8] + output_line['rx_queue'] = line[4][9:] + output_line['timer_active'] = line[5][:2] + output_line['jiffies_until_timer_expires'] = line[5][3:] + output_line['unrecovered_rto_timeouts'] = line[6] + output_line['uid'] = line[7] + output_line['unanswered_0_window_probes'] = line[8] + output_line['inode'] = line[9] + output_line['sock_ref_count'] = line[10] + output_line['sock_mem_loc'] = line[11] + + # fields not always included + if len(line) > 12: + output_line['retransmit_timeout'] = line[12] + output_line['soft_clock_tick'] = line[13] + output_line['ack_quick_pingpong'] = line[14] + output_line['sending_congestion_window'] = line[15] + output_line['slow_start_size_threshold'] = line[16] + + raw_output.append(output_line) + + return raw_output if raw else _process(raw_output) diff --git a/jc/parsers/resolve_conf.py b/jc/parsers/resolve_conf.py new file mode 100644 index 00000000..82f22129 --- /dev/null +++ b/jc/parsers/resolve_conf.py @@ -0,0 +1,171 @@ +"""jc - JSON Convert `/etc/resolve.conf` file parser + +This parser may be more forgiving than the system parser. For example, if +multiple `search` lists are defined, this parser will append all entries to +the `search` field, while the system parser may only use the list from the +last defined instance. + +Usage (cli): + + $ cat /etc/resolve.conf | jc --resolve-conf + +Usage (module): + + import jc + result = jc.parse('resolve_conf', resolve_conf_output) + +Schema: + + { + "domain": string, + "search": [ + string + ], + "nameservers": [ + string + ], + "options": [ + string + ], + "sortlist": [ + string + ] + } + + +Examples: + + $ cat /etc/resolve.conf | jc --resolve-conf -p + { + "search": [ + "eng.myprime.com", + "dev.eng.myprime.com", + "labs.myprime.com", + "qa.myprime.com" + ], + "nameservers": [ + "10.136.17.15" + ], + "options": [ + "rotate", + "ndots:1" + ] + } +""" +import re +from typing import List, Dict +from jc.jc_types import JSONDictType +import jc.utils + + +class info(): + """Provides parser metadata (version, author, etc.)""" + version = '1.0' + description = '`/etc/resolve.conf` file parser' + author = 'Kelly Brazil' + author_email = 'kellyjonbrazil@gmail.com' + compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] + tags = ['file'] + + +__version__ = info.version + + +def _process(proc_data: JSONDictType) -> JSONDictType: + """ + Final processing to conform to the schema. + + Parameters: + + proc_data: Dictionary raw structured data to process + + Returns: + + Dictionary. Structured to conform to the schema. + """ + return proc_data + + +def parse( + data: str, + raw: bool = False, + quiet: bool = False +) -> JSONDictType: + """ + 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. + """ + jc.utils.compatibility(__name__, info.compatible, quiet) + jc.utils.input_type_check(data) + + raw_output: Dict = {} + search: List[str] = [] + nameservers: List[str] = [] + options: List[str] = [] + sortlist: List[str] = [] + + if jc.utils.has_data(data): + + for line in filter(None, data.splitlines()): + + # comments start with # or ; and can be inline + if '#' in line or ';' in line: + userdata = list(filter(None, re.split("[#;]+", line, maxsplit=1))) + userdata = [x for x in userdata if x.strip()] + if len(userdata) <= 1: # whole line is a comment + continue + + userdata_str = userdata[0].strip() + + else: + userdata_str = line.strip() + + if userdata_str.startswith('domain'): + raw_output['domain'] = userdata_str.split()[1].strip() + continue + + if userdata_str.startswith('search'): + search_items = userdata_str.split(maxsplit=1)[1] + search_list = search_items.split() + search.extend(search_list) + continue + + if userdata_str.startswith('nameserver'): + ns_str = userdata_str.split()[1] + nameservers.append(ns_str) + continue + + if userdata_str.startswith('options'): + option_items = userdata_str.split(maxsplit=1)[1] + option_list = option_items.split() + options.extend(option_list) + continue + + if userdata_str.startswith('sortlist'): + sortlist_items = userdata_str.split(maxsplit=1)[1] + sortlist_list = sortlist_items.split() + sortlist.extend(sortlist_list) + continue + + if search: + raw_output['search'] = search + + if nameservers: + raw_output['nameservers'] = nameservers + + if options: + raw_output['options'] = options + + if sortlist: + raw_output['sortlist'] = sortlist + + return raw_output if raw else _process(raw_output) diff --git a/man/jc.1 b/man/jc.1 index 2adb907f..c1581d05 100644 --- a/man/jc.1 +++ b/man/jc.1 @@ -1,4 +1,4 @@ -.TH jc 1 2023-06-21 1.23.3 "JSON Convert" +.TH jc 1 2023-07-30 1.23.4 "JSON Convert" .SH NAME \fBjc\fP \- JSON Convert JSONifies the output of many CLI tools, file-types, and strings @@ -192,6 +192,11 @@ Email Address string parser \fB--file\fP `file` command parser +.TP +.B +\fB--find\fP +`find` command parser + .TP .B \fB--findmnt\fP @@ -307,6 +312,11 @@ IPv4 and IPv6 Address string parser \fB--iptables\fP `iptables` command parser +.TP +.B +\fB--ip-route\fP +`ip route` command parser + .TP .B \fB--iso-datetime\fP @@ -692,6 +702,11 @@ PLIST file parser \fB--proc-net-route\fP `/proc/net/route` file parser +.TP +.B +\fB--proc-net-tcp\fP +`/proc/net/tcp` and `/proc/net/tcp6` file parser + .TP .B \fB--proc-net-unix\fP @@ -747,6 +762,11 @@ PLIST file parser \fB--ps\fP `ps` command parser +.TP +.B +\fB--resolve-conf\fP +`/etc/resolve.conf` file parser + .TP .B \fB--route\fP diff --git a/setup.py b/setup.py index 15819127..dc15a04a 100755 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ with open('README.md', 'r') as f: setuptools.setup( name='jc', - version='1.23.3', + version='1.23.4', author='Kelly Brazil', author_email='kellyjonbrazil@gmail.com', description='Converts the output of popular command-line tools and file-types to JSON.', diff --git a/tests/fixtures/centos-7.7/find.json b/tests/fixtures/centos-7.7/find.json new file mode 100644 index 00000000..4ae23e90 --- /dev/null +++ b/tests/fixtures/centos-7.7/find.json @@ -0,0 +1,13 @@ +[{"path": null, "node": "."}, +{"path":".","node":null}, +{"path": ".","node": "jc"}, +{"path": "./jc","node": "tests"}, +{"path": "./jc/tests","node": "test_find.py"}, +{"path": "./jc/tests","node": "test_history.py"}, +{"path": "./jc/tests","node": "test_hosts.py"}, +{"path": "./jc","node": "anotherdirectory"}, +{"path": null,"node": null,"error": "find: './inaccessible': Permission denied"}, +{"path": "./jc","node": "directory2"}, +{"path": "./jc/directory2","node": "file.txt"}, +{"path": "./jc/directory2","node": "file2.txt"}, +{"path": ".","node": "newfile.txt"}] \ No newline at end of file diff --git a/tests/fixtures/centos-7.7/find.out b/tests/fixtures/centos-7.7/find.out new file mode 100644 index 00000000..d7526181 --- /dev/null +++ b/tests/fixtures/centos-7.7/find.out @@ -0,0 +1,13 @@ +. +./ +./jc +./jc/tests +./jc/tests/test_find.py +./jc/tests/test_history.py +./jc/tests/test_hosts.py +./jc/anotherdirectory +find: './inaccessible': Permission denied +./jc/directory2 +./jc/directory2/file.txt +./jc/directory2/file2.txt +./newfile.txt \ No newline at end of file diff --git a/tests/fixtures/centos-7.7/ip_route.json b/tests/fixtures/centos-7.7/ip_route.json new file mode 100644 index 00000000..72b42e4f --- /dev/null +++ b/tests/fixtures/centos-7.7/ip_route.json @@ -0,0 +1,31 @@ +[ + { + "ip": "default", + "via": "10.0.2.2", + "dev": "enp0s3", + "proto": "dhcp", + "metric": 100 + }, + { + "ip": "10.0.2.0/24", + "dev": "enp0s3", + "proto": "kernel", + "scope": "link", + "src": "10.0.2.15", + "metric": 100 + }, + { + "ip": "169.254.0.0/16", + "dev": "enp0s3", + "scope": "link", + "metric": 1000 + }, + { + "ip": "172.17.0.0/16", + "dev": "docker0", + "proto": "kernel", + "scope": "link", + "src": "172.17.0.1", + "status": "linkdown" + } +] \ No newline at end of file diff --git a/tests/fixtures/centos-7.7/ip_route.out b/tests/fixtures/centos-7.7/ip_route.out new file mode 100644 index 00000000..6135b2c2 --- /dev/null +++ b/tests/fixtures/centos-7.7/ip_route.out @@ -0,0 +1,4 @@ +default via 10.0.2.2 dev enp0s3 proto dhcp metric 100 +10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15 metric 100 +169.254.0.0/16 dev enp0s3 scope link metric 1000 +172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown diff --git a/tests/fixtures/generic/resolve.conf-1 b/tests/fixtures/generic/resolve.conf-1 new file mode 100644 index 00000000..531d380a --- /dev/null +++ b/tests/fixtures/generic/resolve.conf-1 @@ -0,0 +1,12 @@ +# Generated by NetworkManager +search hsd1.ca.comcast.net +nameserver 75.75.75.75 ; test inline comment +nameserver 75.75.76.76 # test inline comment + nameserver 2001:558:feed::1 +# NOTE: the libc resolver may not support more than 3 nameservers. +# The nameservers listed below may not be recognized. +nameserver 2001:558:feed::2 + + +sortlist 130.155.160.0/255.255.240.0 130.155.0.0 +search hello.com world.com # add another search list for fun diff --git a/tests/fixtures/generic/resolve.conf-1.json b/tests/fixtures/generic/resolve.conf-1.json new file mode 100644 index 00000000..4a43ca25 --- /dev/null +++ b/tests/fixtures/generic/resolve.conf-1.json @@ -0,0 +1 @@ +{"search":["hsd1.ca.comcast.net","hello.com","world.com"],"nameservers":["75.75.75.75","75.75.76.76","2001:558:feed::1","2001:558:feed::2"],"sortlist":["130.155.160.0/255.255.240.0","130.155.0.0"]} diff --git a/tests/fixtures/generic/resolve.conf-2 b/tests/fixtures/generic/resolve.conf-2 new file mode 100644 index 00000000..a876fbb5 --- /dev/null +++ b/tests/fixtures/generic/resolve.conf-2 @@ -0,0 +1,4 @@ +search eng.myprime.com dev.eng.myprime.com labs.myprime.com qa.myprime.com +options rotate +options ndots:1 +nameserver 10.136.17.15 diff --git a/tests/fixtures/generic/resolve.conf-2.json b/tests/fixtures/generic/resolve.conf-2.json new file mode 100644 index 00000000..57526714 --- /dev/null +++ b/tests/fixtures/generic/resolve.conf-2.json @@ -0,0 +1 @@ +{"search":["eng.myprime.com","dev.eng.myprime.com","labs.myprime.com","qa.myprime.com"],"nameservers":["10.136.17.15"],"options":["rotate","ndots:1"]} diff --git a/tests/fixtures/generic/resolve.conf-3 b/tests/fixtures/generic/resolve.conf-3 new file mode 100644 index 00000000..f9c2aeb9 --- /dev/null +++ b/tests/fixtures/generic/resolve.conf-3 @@ -0,0 +1,7 @@ + +; +; /etc/resolv.conf file for dnsmaster (sirius) +; +domain doc.com +nameserver 0.0.0.0 +nameserver 111.22.3.5 diff --git a/tests/fixtures/generic/resolve.conf-3.json b/tests/fixtures/generic/resolve.conf-3.json new file mode 100644 index 00000000..a31e3b23 --- /dev/null +++ b/tests/fixtures/generic/resolve.conf-3.json @@ -0,0 +1 @@ +{"domain":"doc.com","nameservers":["0.0.0.0","111.22.3.5"]} diff --git a/tests/fixtures/generic/resolve.conf-4 b/tests/fixtures/generic/resolve.conf-4 new file mode 100644 index 00000000..23baf863 --- /dev/null +++ b/tests/fixtures/generic/resolve.conf-4 @@ -0,0 +1,5 @@ +; generated by /sbin/dhclient-script +search example.com +options rotate timeout:1 retries:1 +nameserver 10.1.1.2 +nameserver 10.1.1.1 diff --git a/tests/fixtures/generic/resolve.conf-4.json b/tests/fixtures/generic/resolve.conf-4.json new file mode 100644 index 00000000..5defeae4 --- /dev/null +++ b/tests/fixtures/generic/resolve.conf-4.json @@ -0,0 +1 @@ +{"search":["example.com"],"nameservers":["10.1.1.2","10.1.1.1"],"options":["rotate","timeout:1","retries:1"]} diff --git a/tests/fixtures/linux-proc/net_tcp b/tests/fixtures/linux-proc/net_tcp new file mode 100644 index 00000000..2e5e2933 --- /dev/null +++ b/tests/fixtures/linux-proc/net_tcp @@ -0,0 +1,28 @@ + sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode + 0: 3500007F:0035 00000000:0000 0A 00000000:00000000 00:00000000 00000000 101 0 34000 1 0000000000000000 100 0 0 10 5 + 1: 0100007F:89E7 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 140054 1 0000000000000000 100 0 0 10 0 + 2: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 34523 1 0000000000000000 100 0 0 10 0 + 3: 802AA8C0:D450 2104C798:01BB 08 00000000:00000052 02:00000A6F 00000000 1000 0 149098 2 0000000000000000 20 4 0 10 -1 + 0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 23459 1 ffff8c7a0de93a80 100 0 0 10 0 + 1: 1C00000A:A462 6C000C40:0050 04 00000001:00000000 01:00000015 00000000 0 0 0 3 ffff8c7a0de930c0 21 4 30 10 -1 + 2: 1C00000A:97D0 412AF468:0050 06 00000000:00000000 03:000007C5 00000000 0 0 0 3 ffff8c7a12d31aa0 + 3: 1C00000A:B082 E4BDFA8E:0050 06 00000000:00000000 03:00000799 00000000 0 0 0 3 ffff8c7a12d31990 + 4: 1C00000A:A858 A6644468:0050 06 00000000:00000000 03:000007C4 00000000 0 0 0 3 ffff8c7a12d31000 + 5: 1C00000A:BD06 2316F09D:0050 06 00000000:00000000 03:000007C4 00000000 0 0 0 3 ffff8c7a12d31880 + 6: 1C00000A:9572 69769736:0050 04 00000001:00000000 01:00000015 00000000 0 0 0 3 ffff8c7a0de94e00 21 4 30 10 -1 + 7: 1C00000A:A530 DA436C68:0050 04 00000001:00000000 01:00000016 00000000 0 0 0 3 ffff8c7a0de91380 22 4 30 10 -1 + 8: 1C00000A:8DDC 9F426597:0050 06 00000000:00000000 03:000007B5 00000000 0 0 0 3 ffff8c7a12d31110 + 9: 1C00000A:C7DE A9664468:0050 04 00000001:00000000 01:00000015 00000000 0 0 0 3 ffff8c7a0de96b40 21 4 18 10 -1 + 10: 1C00000A:DF22 412AF468:0050 06 00000000:00000000 03:00001747 00000000 0 0 0 3 ffff8c7a12d31cc0 + 11: 1C00000A:0016 9200000A:DDCB 01 00000000:00000000 02:000AB71D 00000000 0 0 41558 2 ffff8c7a0de957c0 20 4 1 10 -1 + 12: 1C00000A:DFF8 A40B8962:0050 06 00000000:00000000 03:00001722 00000000 0 0 0 3 ffff8c7a12d31660 + 13: 1C00000A:A5BE A6644468:0050 06 00000000:00000000 03:00001768 00000000 0 0 0 3 ffff8c7a12d31770 + 14: 1C00000A:DA30 9F426597:0050 06 00000000:00000000 03:00001731 00000000 0 0 0 3 ffff8c7a12d31dd0 + 15: 1C00000A:9F62 192E3E17:0050 04 00000001:00000000 01:00000015 00000000 0 0 0 3 ffff8c7a0de909c0 21 4 30 10 -1 + 16: 1C00000A:DA50 E4BDFA8E:0050 06 00000000:00000000 03:00001716 00000000 0 0 0 3 ffff8c7a12d31ee0 + 17: 1C00000A:C362 2316F09D:0050 06 00000000:00000000 03:00001748 00000000 0 0 0 3 ffff8c7a12d31330 + 18: 1C00000A:A734 15E7064A:0050 06 00000000:00000000 03:000007A7 00000000 0 0 0 3 ffff8c7a12d31440 + 19: 1C00000A:EA10 A9664468:0050 06 00000000:00000000 03:000007C4 00000000 0 0 0 3 ffff8c7a12d31550 + 20: 1C00000A:D7C6 B0D4B136:0050 06 00000000:00000000 03:000007C4 00000000 0 0 0 3 ffff8c7a12d31bb0 + 21: 1C00000A:DD12 DA436C68:0050 06 00000000:00000000 03:000007C4 00000000 0 0 0 3 ffff8c7a12d31220 + 22: 1C00000A:D514 8000C798:0050 04 00000001:00000000 01:00000015 00000000 0 0 0 3 ffff8c7a0de94440 21 4 30 10 -1 diff --git a/tests/fixtures/linux-proc/net_tcp.json b/tests/fixtures/linux-proc/net_tcp.json new file mode 100644 index 00000000..0c0d5ef1 --- /dev/null +++ b/tests/fixtures/linux-proc/net_tcp.json @@ -0,0 +1 @@ +[{"entry":"0","local_address":"127.0.0.53","local_port":53,"remote_address":"0.0.0.0","remote_port":0,"state":"0A","tx_queue":"00000000","rx_queue":"00000000","timer_active":0,"jiffies_until_timer_expires":"00000000","unrecovered_rto_timeouts":"00000000","uid":101,"unanswered_0_window_probes":0,"inode":34000,"sock_ref_count":1,"sock_mem_loc":"0000000000000000","retransmit_timeout":100,"soft_clock_tick":0,"ack_quick_pingpong":0,"sending_congestion_window":10,"slow_start_size_threshold":5},{"entry":"1","local_address":"127.0.0.1","local_port":35303,"remote_address":"0.0.0.0","remote_port":0,"state":"0A","tx_queue":"00000000","rx_queue":"00000000","timer_active":0,"jiffies_until_timer_expires":"00000000","unrecovered_rto_timeouts":"00000000","uid":1000,"unanswered_0_window_probes":0,"inode":140054,"sock_ref_count":1,"sock_mem_loc":"0000000000000000","retransmit_timeout":100,"soft_clock_tick":0,"ack_quick_pingpong":0,"sending_congestion_window":10,"slow_start_size_threshold":0},{"entry":"2","local_address":"127.0.0.1","local_port":631,"remote_address":"0.0.0.0","remote_port":0,"state":"0A","tx_queue":"00000000","rx_queue":"00000000","timer_active":0,"jiffies_until_timer_expires":"00000000","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":34523,"sock_ref_count":1,"sock_mem_loc":"0000000000000000","retransmit_timeout":100,"soft_clock_tick":0,"ack_quick_pingpong":0,"sending_congestion_window":10,"slow_start_size_threshold":0},{"entry":"3","local_address":"192.168.42.128","local_port":54352,"remote_address":"152.199.4.33","remote_port":443,"state":"08","tx_queue":"00000000","rx_queue":"00000052","timer_active":2,"jiffies_until_timer_expires":"00000A6F","unrecovered_rto_timeouts":"00000000","uid":1000,"unanswered_0_window_probes":0,"inode":149098,"sock_ref_count":2,"sock_mem_loc":"0000000000000000","retransmit_timeout":20,"soft_clock_tick":4,"ack_quick_pingpong":0,"sending_congestion_window":10,"slow_start_size_threshold":-1},{"entry":"0","local_address":"0.0.0.0","local_port":22,"remote_address":"0.0.0.0","remote_port":0,"state":"0A","tx_queue":"00000000","rx_queue":"00000000","timer_active":0,"jiffies_until_timer_expires":"00000000","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":23459,"sock_ref_count":1,"sock_mem_loc":"ffff8c7a0de93a80","retransmit_timeout":100,"soft_clock_tick":0,"ack_quick_pingpong":0,"sending_congestion_window":10,"slow_start_size_threshold":0},{"entry":"1","local_address":"10.0.0.28","local_port":42082,"remote_address":"64.12.0.108","remote_port":80,"state":"04","tx_queue":"00000001","rx_queue":"00000000","timer_active":1,"jiffies_until_timer_expires":"00000015","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a0de930c0","retransmit_timeout":21,"soft_clock_tick":4,"ack_quick_pingpong":30,"sending_congestion_window":10,"slow_start_size_threshold":-1},{"entry":"2","local_address":"10.0.0.28","local_port":38864,"remote_address":"104.244.42.65","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"000007C5","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31aa0"},{"entry":"3","local_address":"10.0.0.28","local_port":45186,"remote_address":"142.250.189.228","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"00000799","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31990"},{"entry":"4","local_address":"10.0.0.28","local_port":43096,"remote_address":"104.68.100.166","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"000007C4","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31000"},{"entry":"5","local_address":"10.0.0.28","local_port":48390,"remote_address":"157.240.22.35","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"000007C4","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31880"},{"entry":"6","local_address":"10.0.0.28","local_port":38258,"remote_address":"54.151.118.105","remote_port":80,"state":"04","tx_queue":"00000001","rx_queue":"00000000","timer_active":1,"jiffies_until_timer_expires":"00000015","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a0de94e00","retransmit_timeout":21,"soft_clock_tick":4,"ack_quick_pingpong":30,"sending_congestion_window":10,"slow_start_size_threshold":-1},{"entry":"7","local_address":"10.0.0.28","local_port":42288,"remote_address":"104.108.67.218","remote_port":80,"state":"04","tx_queue":"00000001","rx_queue":"00000000","timer_active":1,"jiffies_until_timer_expires":"00000016","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a0de91380","retransmit_timeout":22,"soft_clock_tick":4,"ack_quick_pingpong":30,"sending_congestion_window":10,"slow_start_size_threshold":-1},{"entry":"8","local_address":"10.0.0.28","local_port":36316,"remote_address":"151.101.66.159","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"000007B5","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31110"},{"entry":"9","local_address":"10.0.0.28","local_port":51166,"remote_address":"104.68.102.169","remote_port":80,"state":"04","tx_queue":"00000001","rx_queue":"00000000","timer_active":1,"jiffies_until_timer_expires":"00000015","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a0de96b40","retransmit_timeout":21,"soft_clock_tick":4,"ack_quick_pingpong":18,"sending_congestion_window":10,"slow_start_size_threshold":-1},{"entry":"10","local_address":"10.0.0.28","local_port":57122,"remote_address":"104.244.42.65","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"00001747","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31cc0"},{"entry":"11","local_address":"10.0.0.28","local_port":22,"remote_address":"10.0.0.146","remote_port":56779,"state":"01","tx_queue":"00000000","rx_queue":"00000000","timer_active":2,"jiffies_until_timer_expires":"000AB71D","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":41558,"sock_ref_count":2,"sock_mem_loc":"ffff8c7a0de957c0","retransmit_timeout":20,"soft_clock_tick":4,"ack_quick_pingpong":1,"sending_congestion_window":10,"slow_start_size_threshold":-1},{"entry":"12","local_address":"10.0.0.28","local_port":57336,"remote_address":"98.137.11.164","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"00001722","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31660"},{"entry":"13","local_address":"10.0.0.28","local_port":42430,"remote_address":"104.68.100.166","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"00001768","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31770"},{"entry":"14","local_address":"10.0.0.28","local_port":55856,"remote_address":"151.101.66.159","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"00001731","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31dd0"},{"entry":"15","local_address":"10.0.0.28","local_port":40802,"remote_address":"23.62.46.25","remote_port":80,"state":"04","tx_queue":"00000001","rx_queue":"00000000","timer_active":1,"jiffies_until_timer_expires":"00000015","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a0de909c0","retransmit_timeout":21,"soft_clock_tick":4,"ack_quick_pingpong":30,"sending_congestion_window":10,"slow_start_size_threshold":-1},{"entry":"16","local_address":"10.0.0.28","local_port":55888,"remote_address":"142.250.189.228","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"00001716","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31ee0"},{"entry":"17","local_address":"10.0.0.28","local_port":50018,"remote_address":"157.240.22.35","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"00001748","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31330"},{"entry":"18","local_address":"10.0.0.28","local_port":42804,"remote_address":"74.6.231.21","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"000007A7","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31440"},{"entry":"19","local_address":"10.0.0.28","local_port":59920,"remote_address":"104.68.102.169","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"000007C4","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31550"},{"entry":"20","local_address":"10.0.0.28","local_port":55238,"remote_address":"54.177.212.176","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"000007C4","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31bb0"},{"entry":"21","local_address":"10.0.0.28","local_port":56594,"remote_address":"104.108.67.218","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"000007C4","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a12d31220"},{"entry":"22","local_address":"10.0.0.28","local_port":54548,"remote_address":"152.199.0.128","remote_port":80,"state":"04","tx_queue":"00000001","rx_queue":"00000000","timer_active":1,"jiffies_until_timer_expires":"00000015","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a0de94440","retransmit_timeout":21,"soft_clock_tick":4,"ack_quick_pingpong":30,"sending_congestion_window":10,"slow_start_size_threshold":-1}] diff --git a/tests/fixtures/linux-proc/net_tcp6 b/tests/fixtures/linux-proc/net_tcp6 new file mode 100644 index 00000000..8f69e33c --- /dev/null +++ b/tests/fixtures/linux-proc/net_tcp6 @@ -0,0 +1,9 @@ + sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode + 0: 00000000000000000000000000000000:0016 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 23556 1 ffff8c7a0dee0000 100 0 0 10 0 + 1: 4606012600F1019E000000004C3A0000:E700 8028032A830031F10CB0CEFADE250000:0050 06 00000000:00000000 03:000003D1 00000000 0 0 0 3 ffff8c7a1c76d000 + 2: 4606012600F1019E000000004C3A0000:E9E6 98490120073544000000000000800000:0050 06 00000000:00000000 03:000003AD 00000000 0 0 0 3 ffff8c7a1c76d440 + 3: 4606012600F1019E000000004C3A0000:95E2 061400268F01003A000000003A0C0000:0050 06 00000000:00000000 03:00000400 00000000 0 0 0 3 ffff8c7a1c76daa0 + 4: 4606012600F1019E000000004C3A0000:AFE4 59050120916019000000000020070000:0050 06 00000000:00000000 03:000003EC 00000000 0 0 0 3 ffff8c7a1c76d550 + 5: 4606012600F1019E000000004C3A0000:9D18 B0F80726010805400000000004200000:0050 06 00000000:00000000 03:00000396 00000000 0 0 0 3 ffff8c7a1c76dcc0 + 6: 4606012600F1019E000000004C3A0000:EE0A 590501208F60190000000000330B0000:0050 06 00000000:00000000 03:000003FC 00000000 0 0 0 3 ffff8c7a1c76d110 + 7: 4606012600F1019E000000004C3A0000:80A8 5905012000C01900000000001333C517:0050 06 00000000:00000000 03:000003FC 00000000 0 0 0 3 ffff8c7a1c76d330 diff --git a/tests/fixtures/linux-proc/net_tcp6.json b/tests/fixtures/linux-proc/net_tcp6.json new file mode 100644 index 00000000..291e9cf2 --- /dev/null +++ b/tests/fixtures/linux-proc/net_tcp6.json @@ -0,0 +1 @@ +[{"entry":"0","local_address":"::","local_port":22,"remote_address":"::","remote_port":0,"state":"0A","tx_queue":"00000000","rx_queue":"00000000","timer_active":0,"jiffies_until_timer_expires":"00000000","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":23556,"sock_ref_count":1,"sock_mem_loc":"ffff8c7a0dee0000","retransmit_timeout":100,"soft_clock_tick":0,"ack_quick_pingpong":0,"sending_congestion_window":10,"slow_start_size_threshold":0},{"entry":"1","local_address":"2601:646:9e01:f100::3a4c","local_port":59136,"remote_address":"2a03:2880:f131:83:face:b00c:0:25de","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"000003D1","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a1c76d000"},{"entry":"2","local_address":"2601:646:9e01:f100::3a4c","local_port":59878,"remote_address":"2001:4998:44:3507::8000","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"000003AD","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a1c76d440"},{"entry":"3","local_address":"2601:646:9e01:f100::3a4c","local_port":38370,"remote_address":"2600:1406:3a00:18f::c3a","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"00000400","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a1c76daa0"},{"entry":"4","local_address":"2601:646:9e01:f100::3a4c","local_port":45028,"remote_address":"2001:559:19:6091::720","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"000003EC","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a1c76d550"},{"entry":"5","local_address":"2601:646:9e01:f100::3a4c","local_port":40216,"remote_address":"2607:f8b0:4005:801::2004","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"00000396","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a1c76dcc0"},{"entry":"6","local_address":"2601:646:9e01:f100::3a4c","local_port":60938,"remote_address":"2001:559:19:608f::b33","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"000003FC","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a1c76d110"},{"entry":"7","local_address":"2601:646:9e01:f100::3a4c","local_port":32936,"remote_address":"2001:559:19:c000::17c5:3313","remote_port":80,"state":"06","tx_queue":"00000000","rx_queue":"00000000","timer_active":3,"jiffies_until_timer_expires":"000003FC","unrecovered_rto_timeouts":"00000000","uid":0,"unanswered_0_window_probes":0,"inode":0,"sock_ref_count":3,"sock_mem_loc":"ffff8c7a1c76d330"}] diff --git a/tests/fixtures/ubuntu-18.04/find.json b/tests/fixtures/ubuntu-18.04/find.json new file mode 100644 index 00000000..4ae23e90 --- /dev/null +++ b/tests/fixtures/ubuntu-18.04/find.json @@ -0,0 +1,13 @@ +[{"path": null, "node": "."}, +{"path":".","node":null}, +{"path": ".","node": "jc"}, +{"path": "./jc","node": "tests"}, +{"path": "./jc/tests","node": "test_find.py"}, +{"path": "./jc/tests","node": "test_history.py"}, +{"path": "./jc/tests","node": "test_hosts.py"}, +{"path": "./jc","node": "anotherdirectory"}, +{"path": null,"node": null,"error": "find: './inaccessible': Permission denied"}, +{"path": "./jc","node": "directory2"}, +{"path": "./jc/directory2","node": "file.txt"}, +{"path": "./jc/directory2","node": "file2.txt"}, +{"path": ".","node": "newfile.txt"}] \ No newline at end of file diff --git a/tests/fixtures/ubuntu-18.04/find.out b/tests/fixtures/ubuntu-18.04/find.out new file mode 100644 index 00000000..d7526181 --- /dev/null +++ b/tests/fixtures/ubuntu-18.04/find.out @@ -0,0 +1,13 @@ +. +./ +./jc +./jc/tests +./jc/tests/test_find.py +./jc/tests/test_history.py +./jc/tests/test_hosts.py +./jc/anotherdirectory +find: './inaccessible': Permission denied +./jc/directory2 +./jc/directory2/file.txt +./jc/directory2/file2.txt +./newfile.txt \ No newline at end of file diff --git a/tests/fixtures/ubuntu-18.04/ip_route.json b/tests/fixtures/ubuntu-18.04/ip_route.json new file mode 100644 index 00000000..72b42e4f --- /dev/null +++ b/tests/fixtures/ubuntu-18.04/ip_route.json @@ -0,0 +1,31 @@ +[ + { + "ip": "default", + "via": "10.0.2.2", + "dev": "enp0s3", + "proto": "dhcp", + "metric": 100 + }, + { + "ip": "10.0.2.0/24", + "dev": "enp0s3", + "proto": "kernel", + "scope": "link", + "src": "10.0.2.15", + "metric": 100 + }, + { + "ip": "169.254.0.0/16", + "dev": "enp0s3", + "scope": "link", + "metric": 1000 + }, + { + "ip": "172.17.0.0/16", + "dev": "docker0", + "proto": "kernel", + "scope": "link", + "src": "172.17.0.1", + "status": "linkdown" + } +] \ No newline at end of file diff --git a/tests/fixtures/ubuntu-18.04/ip_route.out b/tests/fixtures/ubuntu-18.04/ip_route.out new file mode 100644 index 00000000..d9a08f9a --- /dev/null +++ b/tests/fixtures/ubuntu-18.04/ip_route.out @@ -0,0 +1,4 @@ +default via 10.0.2.2 dev enp0s3 proto dhcp metric 100 +10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15 metric 100 +169.254.0.0/16 dev enp0s3 scope link metric 1000 +172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown \ No newline at end of file diff --git a/tests/test_find.py b/tests/test_find.py new file mode 100644 index 00000000..b7dca7d4 --- /dev/null +++ b/tests/test_find.py @@ -0,0 +1,43 @@ +import os +import unittest +import json +import jc.parsers.find + +THIS_DIR = os.path.dirname(os.path.abspath(__file__)) + +class MyTests(unittest.TestCase): + + # input + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/find.out'), 'r', encoding='utf-8') as f: + centos_7_7_find = f.read() + + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/find.out'), 'r', encoding='utf-8') as f: + ubuntu_18_4_find = f.read() + + #output + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/find.json'), 'r', encoding='utf-8') as f: + centos_7_7_find_json = json.loads(f.read()) + + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/find.json'), 'r', encoding='utf-8') as f: + ubuntu_18_4_find_json = json.loads(f.read()) + + def test_find_nodata(self): + """ + Test 'find' with no data + """ + self.assertEqual(jc.parsers.find.parse('', quiet=True), []) + + def test_find_centos_7_7(self): + """ + Test 'find' on Centos 7.7 + """ + self.assertEqual(jc.parsers.find.parse(self.centos_7_7_find, quiet=True), self.centos_7_7_find_json) + + def test_find_ubuntu_18_4(self): + """ + Test 'find' on Ubuntu 18.4 + """ + self.assertEqual(jc.parsers.find.parse(self.ubuntu_18_4_find, quiet=True), self.ubuntu_18_4_find_json) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tests/test_ip_route.py b/tests/test_ip_route.py new file mode 100644 index 00000000..50b77f59 --- /dev/null +++ b/tests/test_ip_route.py @@ -0,0 +1,51 @@ +import os +import json +import unittest +import jc.parsers.ip_route + +THIS_DIR = os.path.dirname(os.path.abspath(__file__)) + + +class MyTests(unittest.TestCase): + + # INPUT + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ip_route.out'), 'r', + encoding='utf-8') as f: + ubuntu_18_4_ip_route = f.read() + + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/ip_route.out'), 'r', + encoding='utf-8') as f: + centos_7_7_ip_route = f.read() + + # OUTPUT + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ip_route.json'), 'r', + encoding='utf-8') as f: + ubuntu_18_4_ip_route_json = json.loads(f.read()) + + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/ip_route.json'), 'r', + encoding='utf-8') as f: + centos_7_7_ip_route_json = json.loads(f.read()) + + def test_ip_route_nodata(self): + """ + Test 'ip_route' with no data + """ + self.assertEqual(jc.parsers.ip_route.parse('', quiet=True), []) + + def test_ip_route_ubuntu_18_4(self): + """ + Test 'ip_route' on Ubuntu 18.4 + """ + self.assertEqual(jc.parsers.ip_route.parse(self.ubuntu_18_4_ip_route, quiet=True), + self.ubuntu_18_4_ip_route_json) + + def test_ip_route_centos_7_7(self): + """ + Test 'history' on Centos 7.7 + """ + self.assertEqual(jc.parsers.ip_route.parse(self.centos_7_7_ip_route, quiet=True), + self.centos_7_7_ip_route_json) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_proc_net_tcp.py b/tests/test_proc_net_tcp.py new file mode 100644 index 00000000..2deed69b --- /dev/null +++ b/tests/test_proc_net_tcp.py @@ -0,0 +1,53 @@ +import os +import unittest +import json +from typing import Dict +import jc.parsers.proc_net_tcp + +THIS_DIR = os.path.dirname(os.path.abspath(__file__)) + +class MyTests(unittest.TestCase): + f_in: Dict = {} + f_json: Dict = {} + + @classmethod + def setUpClass(cls): + fixtures = { + 'proc_net_tcp': ( + 'fixtures/linux-proc/net_tcp', + 'fixtures/linux-proc/net_tcp.json'), + 'proc_net_tcp6': ( + 'fixtures/linux-proc/net_tcp6', + 'fixtures/linux-proc/net_tcp6.json') + } + + for file, filepaths in fixtures.items(): + with open(os.path.join(THIS_DIR, filepaths[0]), 'r', encoding='utf-8') as a, \ + open(os.path.join(THIS_DIR, filepaths[1]), 'r', encoding='utf-8') as b: + cls.f_in[file] = a.read() + cls.f_json[file] = json.loads(b.read()) + + + def test_proc_net_tcp_nodata(self): + """ + Test 'proc_net_tcp' with no data + """ + self.assertEqual(jc.parsers.proc_net_tcp.parse('', quiet=True), []) + + def test_proc_net_tcp(self): + """ + Test '/proc/net/tcp' + """ + self.assertEqual(jc.parsers.proc_net_tcp.parse(self.f_in['proc_net_tcp'], quiet=True), + self.f_json['proc_net_tcp']) + + def test_proc_net_tcp6(self): + """ + Test '/proc/net/tcp6' + """ + self.assertEqual(jc.parsers.proc_net_tcp.parse(self.f_in['proc_net_tcp6'], quiet=True), + self.f_json['proc_net_tcp6']) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_resolve_conf.py b/tests/test_resolve_conf.py new file mode 100644 index 00000000..a503a388 --- /dev/null +++ b/tests/test_resolve_conf.py @@ -0,0 +1,83 @@ +import os +import unittest +import json +from typing import Dict +from jc.parsers.resolve_conf import parse + +THIS_DIR = os.path.dirname(os.path.abspath(__file__)) + + +class MyTests(unittest.TestCase): + f_in: Dict = {} + f_json: Dict = {} + + @classmethod + def setUpClass(cls): + fixtures = { + 'resolve_conf_1': ( + 'fixtures/generic/resolve.conf-1', + 'fixtures/generic/resolve.conf-1.json'), + 'resolve_conf_2': ( + 'fixtures/generic/resolve.conf-2', + 'fixtures/generic/resolve.conf-2.json'), + 'resolve_conf_3': ( + 'fixtures/generic/resolve.conf-3', + 'fixtures/generic/resolve.conf-3.json'), + 'resolve_conf_4': ( + 'fixtures/generic/resolve.conf-4', + 'fixtures/generic/resolve.conf-4.json') + } + + for file, filepaths in fixtures.items(): + with open(os.path.join(THIS_DIR, filepaths[0]), 'r', encoding='utf-8') as a, \ + open(os.path.join(THIS_DIR, filepaths[1]), 'r', encoding='utf-8') as b: + cls.f_in[file] = a.read() + cls.f_json[file] = json.loads(b.read()) + + + def test_resolve_conf_nodata(self): + """ + Test 'resolve_conf' with no data + """ + self.assertEqual(parse('', quiet=True), {}) + + + def test_resolve_conf_1(self): + """ + Test 'resolve_conf' file 1 + """ + self.assertEqual( + parse(self.f_in['resolve_conf_1'], quiet=True), + self.f_json['resolve_conf_1'] + ) + + def test_resolve_conf_2(self): + """ + Test 'resolve_conf' file 2 + """ + self.assertEqual( + parse(self.f_in['resolve_conf_2'], quiet=True), + self.f_json['resolve_conf_2'] + ) + + def test_resolve_conf_3(self): + """ + Test 'resolve_conf' file 3 + """ + self.assertEqual( + parse(self.f_in['resolve_conf_3'], quiet=True), + self.f_json['resolve_conf_3'] + ) + + def test_resolve_conf_4(self): + """ + Test 'resolve_conf' file 4 + """ + self.assertEqual( + parse(self.f_in['resolve_conf_4'], quiet=True), + self.f_json['resolve_conf_4'] + ) + + +if __name__ == '__main__': + unittest.main()