1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2026-04-03 17:44:07 +02:00

Compare commits

...

72 Commits

Author SHA1 Message Date
Kelly Brazil
7f869b4b18 change colors to ansi and match jello style 2020-04-09 07:31:21 -07:00
Kelly Brazil
9665f4ee84 add pypi badge 2020-04-07 08:44:15 -07:00
Kelly Brazil
606904d48b Merge pull request #53 from kellyjonbrazil/dev
Dev v1.10.1
2020-04-04 17:28:21 -07:00
Kelly Brazil
3f5279b97c version bump to 1.10.1 2020-04-04 17:25:55 -07:00
Kelly Brazil
f5ec21e6ac use in instead of find() 2020-04-04 17:19:32 -07:00
Kelly Brazil
578a284465 use in instead of find() 2020-04-04 17:18:39 -07:00
Kelly Brazil
422e392d9d use in instead of find() 2020-04-04 17:17:43 -07:00
Kelly Brazil
54dfffd34a use in instead of find() 2020-04-04 17:16:25 -07:00
Kelly Brazil
cffba64d2b use in and startswith() instead of find() 2020-04-04 17:15:03 -07:00
Kelly Brazil
56a0c12a59 use in instead of find() 2020-04-04 17:12:22 -07:00
Kelly Brazil
c174d3de18 use in and startswith() instead of find() 2020-04-04 17:10:46 -07:00
Kelly Brazil
a9c59ef9fc fix logic to not for ' type ' in cleandata[0] 2020-04-04 17:07:38 -07:00
Kelly Brazil
abdb9b2673 use in instead of find() 2020-04-04 17:05:17 -07:00
Kelly Brazil
548aaab626 remove old commented code 2020-04-04 17:04:20 -07:00
Kelly Brazil
20571c87ae us in instead of find() 2020-04-04 17:01:56 -07:00
Kelly Brazil
19e49200de version bump 2020-04-04 16:59:48 -07:00
Kelly Brazil
d32f5c67a9 use startswith() instead of find() 2020-04-04 16:59:03 -07:00
Kelly Brazil
b83b626435 use startswith() instead of find() 2020-04-04 16:57:23 -07:00
Kelly Brazil
ab2c1b25ec use startswith() and in instead of find() 2020-04-04 16:56:11 -07:00
Kelly Brazil
f2d46313a4 use startswith() instead of find() 2020-04-04 16:53:55 -07:00
Kelly Brazil
87e4796a6c use in instead of .find() 2020-04-04 16:52:45 -07:00
Kelly Brazil
0014a5c2f4 us startswith() and in instead of .find() 2020-04-04 16:51:36 -07:00
Kelly Brazil
7af56e0dad use startswith() and in instead of find() 2020-04-04 16:50:05 -07:00
Kelly Brazil
a5ae6e3c01 use startswith() instead of find() 2020-04-04 16:48:16 -07:00
Kelly Brazil
fe1a0d1faf use in instead of .find() 2020-04-04 16:46:09 -07:00
Kelly Brazil
302f05cdda prettify style block 2020-04-03 14:50:20 -07:00
Kelly Brazil
c0044be7b0 rename color grey to gray 2020-04-03 14:48:19 -07:00
Kelly Brazil
0110078807 update badge 2020-04-03 14:47:08 -07:00
Kelly Brazil
42eacb45f8 rename to Tests 2020-04-03 14:45:04 -07:00
Kelly Brazil
a43e2e1991 add -m option info 2020-04-02 17:40:06 -07:00
Kelly Brazil
c8b721d4f6 version bump to 1.10.0 2020-04-02 17:35:35 -07:00
Kelly Brazil
d0bfddc3d9 add color and -m monochrome option 2020-04-02 17:29:25 -07:00
Kelly Brazil
6b925a16c8 add tests badge 2020-04-02 10:55:32 -07:00
Kelly Brazil
89ebd9fc22 add axfr info to schema 2020-03-27 07:31:08 -07:00
Kelly Brazil
6b4ba66231 Merge pull request #52 from kellyjonbrazil/dev
Dev v1.9.3
2020-03-26 17:15:13 -07:00
Kelly Brazil
5b697dc381 add more dig tests 2020-03-26 17:09:29 -07:00
Kelly Brazil
9ba73c95d1 add tests 2020-03-26 16:45:29 -07:00
Kelly Brazil
93aa390447 version bump to v1.9.3 2020-03-26 16:30:17 -07:00
Kelly Brazil
3cfb8945dd use startswith() instead of find 2020-03-26 16:29:59 -07:00
Kelly Brazil
cd8d38f2a1 add axfr support 2020-03-26 16:22:53 -07:00
Kelly Brazil
8ec8cd6294 Merge pull request #50 from kellyjonbrazil/dev
Dev v1.9.2
2020-03-12 17:09:04 -07:00
Kelly Brazil
c028113561 version bump to v1.9.2 2020-03-12 17:06:55 -07:00
Kelly Brazil
5f22e1c803 fix and test for osx arp entries without ifscope 2020-03-12 17:02:26 -07:00
Kelly Brazil
d3351787e5 change osx detection 2020-03-12 16:52:33 -07:00
Kelly Brazil
e5bea9ae3b version bump 2020-03-12 08:52:01 -07:00
Kelly Brazil
93c710abe9 Merge pull request #49 from kellyjonbrazil/dev
Dev v1.9.1
2020-03-12 08:23:10 -07:00
Kelly Brazil
c29e7cfe5c version bump to 1.9.1 2020-03-12 08:17:28 -07:00
Kelly Brazil
cb5c1ba00d add tests for fix to make the file parser splitting more robust 2020-03-11 17:04:48 -07:00
Kelly Brazil
9a012b94e1 make splitting more robust 2020-03-11 15:40:34 -07:00
Kelly Brazil
400f5a44ec Merge pull request #48 from kellyjonbrazil/dev
Dev v1.9.0
2020-03-11 13:37:22 -07:00
Kelly Brazil
a2ab5bab91 version bump to v1.9.0 2020-03-11 13:32:58 -07:00
Kelly Brazil
fc8ab27361 bugfix for misaligned columns and additional test for ntpq #31 2020-03-11 13:24:55 -07:00
Kelly Brazil
59f19d33a5 add file command tests for #41 2020-03-11 12:39:59 -07:00
Kelly Brazil
dfc9618115 add file parser for issue #41 2020-03-11 12:20:58 -07:00
Kelly Brazil
8e02e5c75a fix issue with getting options with some commands #47 2020-03-11 09:21:14 -07:00
Kelly Brazil
970493ab93 add magic commands 2020-03-11 06:22:54 -07:00
Kelly Brazil
64d78956eb update acknowledgment 2020-03-10 22:18:26 -07:00
Kelly Brazil
40c05346f4 re-adding optimizations from https://github.com/philippeitis 2020-03-10 22:16:40 -07:00
Kelly Brazil
e9b0bc1409 doc update 2020-03-10 22:03:54 -07:00
Kelly Brazil
798e6bb7d9 tests passing for airport -s. issue #46 2020-03-10 22:03:44 -07:00
Kelly Brazil
12a370deed add airport -s parser for issue #46 2020-03-10 21:51:02 -07:00
Kelly Brazil
553bfbe1a0 tests passing for airport -I. Issue #46 2020-03-10 21:02:17 -07:00
Kelly Brazil
52494321fc fixes and docs for airport parser issue #46 2020-03-10 20:55:07 -07:00
Kelly Brazil
c6c9e06496 added airport command parser 2020-03-10 20:35:52 -07:00
Kelly Brazil
e3a6c05a58 timedatectl fixes, tests, and fixtures for issue #42 2020-03-10 20:26:53 -07:00
Kelly Brazil
391d06f68d change selection_state to state 2020-03-10 20:16:41 -07:00
Kelly Brazil
99804ea06e added timedatectl status parser 2020-03-10 18:37:55 -07:00
Kelly Brazil
51935deb2a timedatectl test fixtures 2020-03-10 18:00:47 -07:00
Kelly Brazil
b24d0c3a47 ntpq docs 2020-03-10 18:00:26 -07:00
Kelly Brazil
762a886d6f add ntpq tests 2020-03-10 15:17:25 -07:00
Kelly Brazil
2c3e9ddfe4 add ntpq parser for issue #31 2020-03-10 14:18:55 -07:00
Kelly Brazil
c7cd2b63c8 delete unused test file 2020-03-09 11:46:17 -07:00
82 changed files with 2829 additions and 245 deletions

View File

@@ -1,4 +1,4 @@
name: Test code
name: Tests
on:
push:

152
README.md
View File

@@ -1,3 +1,6 @@
![Tests](https://github.com/kellyjonbrazil/jc/workflows/Tests/badge.svg?branch=master)
![Pypi](https://img.shields.io/pypi/v/jc.svg)
# JC
JSON CLI output utility
@@ -82,6 +85,8 @@ jc [OPTIONS] COMMAND
The JSON output can be compact (default) or pretty formatted with the `-p` option.
### Parsers
- `--airport` enables the `airport -I` command parser (OSX)
- `--airport-s` enables the `airport -s` command parser (OSX)
- `--arp` enables the `arp` command parser
- `--blkid` enables the `blkid` command parser
- `--crontab` enables the `crontab` command and file parser
@@ -91,6 +96,7 @@ The JSON output can be compact (default) or pretty formatted with the `-p` optio
- `--dig` enables the `dig` command parser
- `--du` enables the `du` command parser
- `--env` enables the `env` command parser
- `--file` enables the `file` command parser
- `--free` enables the `free` command parser
- `--fstab` enables the `/etc/fstab` file parser
- `--group` enables the `/etc/group` file parser
@@ -109,6 +115,7 @@ The JSON output can be compact (default) or pretty formatted with the `-p` optio
- `--lsof` enables the `lsof` command parser
- `--mount` enables the `mount` command parser
- `--netstat` enables the `netstat` command parser
- `--ntpq` enables the `ntpq -p` command parser
- `--passwd` enables the `/etc/passwd` file parser
- `--pip-list` enables the `pip list` command parser
- `--pip-show` enables the `pip show` command parser
@@ -121,6 +128,7 @@ The JSON output can be compact (default) or pretty formatted with the `-p` optio
- `--systemctl-lj` enables the `systemctl list-jobs` command parser
- `--systemctl-ls` enables the `systemctl list-sockets` command parser
- `--systemctl-luf` enables the `systemctl list-unit-files` command parser
- `--timedatectl` enables the `timedatectl status` command parser
- `--uname` enables the `uname -a` command parser
- `--uptime` enables the `uptime` command parser
- `--w` enables the `w` command parser
@@ -131,6 +139,7 @@ The JSON output can be compact (default) or pretty formatted with the `-p` optio
### Options
- `-a` about `jc`. Prints information about `jc` and the parsers (in JSON, of course!)
- `-d` debug mode. Prints trace messages if parsing issues encountered
- `-m` monochrome JSON output
- `-p` pretty format the JSON output
- `-q` quiet mode. Suppresses warning messages
- `-r` raw output. Provides a more literal JSON output with all values as text and no additional sematic processing
@@ -155,6 +164,7 @@ Tested on:
- OSX 10.14.6
## Acknowledgments
- CI automation and code optimizations from https://github.com/philippeitis
- `ifconfig-parser` module from https://github.com/KnightWhoSayNi/ifconfig-parser
- `xmltodict` module from https://github.com/martinblech/xmltodict by Martín Blech
- `ruamel.yaml` library from https://pypi.org/project/ruamel.yaml by Anthon van der Neut
@@ -162,6 +172,67 @@ Tested on:
- Excellent constructive feedback from Ilya Sher (https://github.com/ilyash-b)
## Examples
### airport -I
```
$ airport -I | jc --airport -p # or: jc -p airport -I
{
"agrctlrssi": -66,
"agrextrssi": 0,
"agrctlnoise": -90,
"agrextnoise": 0,
"state": "running",
"op_mode": "station",
"lasttxrate": 195,
"maxrate": 867,
"lastassocstatus": 0,
"802_11_auth": "open",
"link_auth": "wpa2-psk",
"bssid": "3c:37:86:15:ad:f9",
"ssid": "SnazzleDazzle",
"mcs": 0,
"channel": "48,80"
}
```
### airport -s
```
$ airport -s | jc --airport-s -p # or: jc -p airport -s
[
{
"ssid": "DIRECT-4A-HP OfficeJet 3830",
"bssid": "00:67:eb:2a:a7:3b",
"rssi": -90,
"channel": "6",
"ht": true,
"cc": "--",
"security": [
"WPA2(PSK/AES/AES)"
]
},
{
"ssid": "Latitude38",
"bssid": "c0:ff:d5:d2:7a:f3",
"rssi": -85,
"channel": "11",
"ht": true,
"cc": "US",
"security": [
"WPA2(PSK/AES/AES)"
]
},
{
"ssid": "xfinitywifi",
"bssid": "6e:e3:0e:b8:45:99",
"rssi": -83,
"channel": "11",
"ht": true,
"cc": "US",
"security": [
"NONE"
]
},
...
]
```
### arp
```
$ arp | jc --arp -p # or: jc -p arp
@@ -695,6 +766,41 @@ $ env | jc --env -p # or: jc -p env
...
]
```
### file
```
$ file * | jc --file -p # or: jc -p file *
[
{
"filename": "Applications",
"type": "directory"
},
{
"filename": "another file with spaces",
"type": "empty"
},
{
"filename": "argstest.py",
"type": "Python script text executable, ASCII text"
},
{
"filename": "blkid-p.out",
"type": "ASCII text"
},
{
"filename": "blkid-pi.out",
"type": "ASCII text, with very long lines"
},
{
"filename": "cd_catalog.xml",
"type": "XML 1.0 document text, ASCII text, with CRLF line terminators"
},
{
"filename": "centosserial.sh",
"type": "Bourne-Again shell script text executable, UTF-8 Unicode text"
},
...
]
```
### free
```
$ free | jc --free -p # or: jc -p free
@@ -1484,6 +1590,38 @@ $ sudo netstat -apee | jc --netstat -p # or: sudo jc -p netstat -apee
...
]
```
### ntpq
```
$ ntpq -p | jc --ntpq -p # or: jc -p ntpq -p
[
{
"remote": "44.190.6.254",
"refid": "127.67.113.92",
"st": 2,
"t": "u",
"when": 1,
"poll": 64,
"reach": 1,
"delay": 23.399,
"offset": -2.805,
"jitter": 2.131,
"state": null
},
{
"remote": "mirror1.sjc02.s",
"refid": "216.218.254.202",
"st": 2,
"t": "u",
"when": 2,
"poll": 64,
"reach": 1,
"delay": 29.325,
"offset": 1.044,
"jitter": 4.069,
"state": null
}
]
```
### /etc/passwd file
```
$ cat /etc/passwd | jc --passwd -p
@@ -1991,6 +2129,20 @@ $ systemctl list-unit-files | jc --systemctl-luf -p # or: jc -p system
...
]
```
### timedatectl status
```
$ timedatectl | jc --timedatectl -p # or: jc -p timedatectl
{
"local_time": "Tue 2020-03-10 17:53:21 PDT",
"universal_time": "Wed 2020-03-11 00:53:21 UTC",
"rtc_time": "Wed 2020-03-11 00:53:21",
"time_zone": "America/Los_Angeles (PDT, -0700)",
"ntp_enabled": true,
"ntp_synchronized": true,
"rtc_in_local_tz": false,
"dst_active": true
}
```
### uname -a
```
$ uname -a | jc --uname -p # or: jc -p uname -a

View File

@@ -1,7 +1,34 @@
jc changelog
20200409 v1.10.2
- Change colors to ansi and match jello colors
20200402 v1.10.1
- Code cleanup
20200402 v1.10.0
- Add color output by default when not piping data to another program
- Add -m option for monochrome output
20200326 v1.9.3
- Add axfr support for dig command parser
20200312 v1.9.2
- Updated arp parser to fix OSX detection for some edge cases
20200312 v1.9.1
- Updated file command parser to make filename splitting more robust
20200311 v1.9.0
- Added ntpq command parser
- Added timedatectl status command parser
- Added airport -I and airport -s command parser
- Added file command parser
- Optimized history command parser by https://github.com/philippeitis
- Magic syntax fix for certain edge cases
20200308 v1.8.1
- CLI and history parser optimizations by https://github.com/philippeitis
- CLI optimizations by https://github.com/philippeitis
- Refactored magic syntax function and added tests (https://github.com/philippeitis)
- Github actions for CI testing on multiple platforms by https://github.com/philippeitis
- Updated ls parser to fix parsing error in OSX with -lR when there are empty folders

View File

@@ -4,6 +4,8 @@
cd jc
pydocmd simple jc+ > ../docs/readme.md
pydocmd simple utils+ > ../docs/utils.md
pydocmd simple jc.parsers.airport+ > ../docs/parsers/airport.md
pydocmd simple jc.parsers.airport_s+ > ../docs/parsers/airport_s.md
pydocmd simple jc.parsers.arp+ > ../docs/parsers/arp.md
pydocmd simple jc.parsers.blkid+ > ../docs/parsers/blkid.md
pydocmd simple jc.parsers.crontab+ > ../docs/parsers/crontab.md
@@ -13,6 +15,7 @@ pydocmd simple jc.parsers.df+ > ../docs/parsers/df.md
pydocmd simple jc.parsers.dig+ > ../docs/parsers/dig.md
pydocmd simple jc.parsers.du+ > ../docs/parsers/du.md
pydocmd simple jc.parsers.env+ > ../docs/parsers/env.md
pydocmd simple jc.parsers.file+ > ../docs/parsers/file.md
pydocmd simple jc.parsers.free+ > ../docs/parsers/free.md
pydocmd simple jc.parsers.fstab+ > ../docs/parsers/fstab.md
pydocmd simple jc.parsers.group+ > ../docs/parsers/group.md
@@ -31,6 +34,7 @@ pydocmd simple jc.parsers.lsmod+ > ../docs/parsers/lsmod.md
pydocmd simple jc.parsers.lsof+ > ../docs/parsers/lsof.md
pydocmd simple jc.parsers.mount+ > ../docs/parsers/mount.md
pydocmd simple jc.parsers.netstat+ > ../docs/parsers/netstat.md
pydocmd simple jc.parsers.ntpq+ > ../docs/parsers/ntpq.md
pydocmd simple jc.parsers.passwd+ > ../docs/parsers/passwd.md
pydocmd simple jc.parsers.pip_list+ > ../docs/parsers/pip_list.md
pydocmd simple jc.parsers.pip_show+ > ../docs/parsers/pip_show.md
@@ -43,6 +47,7 @@ pydocmd simple jc.parsers.systemctl+ > ../docs/parsers/systemctl.md
pydocmd simple jc.parsers.systemctl_lj+ > ../docs/parsers/systemctl_lj.md
pydocmd simple jc.parsers.systemctl_ls+ > ../docs/parsers/systemctl_ls.md
pydocmd simple jc.parsers.systemctl_luf+ > ../docs/parsers/systemctl_luf.md
pydocmd simple jc.parsers.timedatectl+ > ../docs/parsers/timedatectl.md
pydocmd simple jc.parsers.uname+ > ../docs/parsers/uname.md
pydocmd simple jc.parsers.uptime+ > ../docs/parsers/uptime.md
pydocmd simple jc.parsers.w+ > ../docs/parsers/w.md

109
docs/parsers/airport.md Normal file
View File

@@ -0,0 +1,109 @@
# jc.parsers.airport
jc - JSON CLI output utility airport -I Parser
Usage:
specify --airport as the first argument if the piped input is coming from airport -I (OSX)
This program can be found at:
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport
Compatibility:
'darwin'
Examples:
$ airport -I | jc --airport -p
{
"agrctlrssi": -66,
"agrextrssi": 0,
"agrctlnoise": -90,
"agrextnoise": 0,
"state": "running",
"op_mode": "station",
"lasttxrate": 195,
"maxrate": 867,
"lastassocstatus": 0,
"802_11_auth": "open",
"link_auth": "wpa2-psk",
"bssid": "3c:37:86:15:ad:f9",
"ssid": "SnazzleDazzle",
"mcs": 0,
"channel": "48,80"
}
$ airport -I | jc --airport -p -r
{
"agrctlrssi": "-66",
"agrextrssi": "0",
"agrctlnoise": "-90",
"agrextnoise": "0",
"state": "running",
"op_mode": "station",
"lasttxrate": "195",
"maxrate": "867",
"lastassocstatus": "0",
"802_11_auth": "open",
"link_auth": "wpa2-psk",
"bssid": "3c:37:86:15:ad:f9",
"ssid": "SnazzleDazzle",
"mcs": "0",
"channel": "48,80"
}
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary. Structured data with the following schema:
{
"agrctlrssi": integer,
"agrextrssi": integer,
"agrctlnoise": integer,
"agrextnoise": integer,
"state": string,
"op_mode": string,
"lasttxrate": integer,
"maxrate": integer,
"lastassocstatus": integer,
"802_11_auth": string,
"link_auth": string,
"bssid": string,
"ssid": string,
"mcs": integer,
"channel": string
}
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.

136
docs/parsers/airport_s.md Normal file
View File

@@ -0,0 +1,136 @@
# jc.parsers.airport_s
jc - JSON CLI output utility airport -s Parser
Usage:
specify --airport as the first argument if the piped input is coming from airport -s (OSX)
This program can be found at:
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport
Compatibility:
'darwin'
Examples:
$ airport -s | jc --airport-s -p
[
{
"ssid": "DIRECT-4A-HP OfficeJet 3830",
"bssid": "00:67:eb:2a:a7:3b",
"rssi": -90,
"channel": "6",
"ht": true,
"cc": "--",
"security": [
"WPA2(PSK/AES/AES)"
]
},
{
"ssid": "Latitude38",
"bssid": "c0:ff:d5:d2:7a:f3",
"rssi": -85,
"channel": "11",
"ht": true,
"cc": "US",
"security": [
"WPA2(PSK/AES/AES)"
]
},
{
"ssid": "xfinitywifi",
"bssid": "6e:e3:0e:b8:45:99",
"rssi": -83,
"channel": "11",
"ht": true,
"cc": "US",
"security": [
"NONE"
]
},
...
]
$ airport -s | jc --airport -p -r
[
{
"ssid": "DIRECT-F3-HP ENVY 5660 series",
"bssid": "b0:5a:da:6f:0a:d4",
"rssi": "-93",
"channel": "1",
"ht": "Y",
"cc": "--",
"security": "WPA2(PSK/AES/AES)"
},
{
"ssid": "YouAreInfected-5",
"bssid": "5c:e3:0e:c2:85:da",
"rssi": "-85",
"channel": "36",
"ht": "Y",
"cc": "US",
"security": "WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)"
},
{
"ssid": "YuanFamily",
"bssid": "5c:e3:0e:b8:5f:9a",
"rssi": "-84",
"channel": "11",
"ht": "Y",
"cc": "US",
"security": "WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)"
},
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"ssid": string,
"bssid": string,
"rssi": integer,
"channel": string,
"ht": boolean,
"cc": string,
"security": [
string,
]
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

View File

@@ -353,6 +353,15 @@ Returns:
"answer_num": integer,
"authority_num": integer,
"additional_num": integer,
"axfr": [
{
"name": string,
"class": string,
"type": string,
"ttl": integer,
"data": string
}
],
"question": {
"name": string,
"class": string,
@@ -380,6 +389,7 @@ Returns:
"server": string,
"when": string,
"rcvd": integer
"size": string
}
]

90
docs/parsers/file.md Normal file
View File

@@ -0,0 +1,90 @@
# jc.parsers.file
jc - JSON CLI output utility file command Parser
Usage:
specify --file as the first argument if the piped input is coming from file.
Compatibility:
'linux', 'aix', 'freebsd', 'darwin'
Examples:
$ file * | jc --file -p
[
{
"filename": "Applications",
"type": "directory"
},
{
"filename": "another file with spaces",
"type": "empty"
},
{
"filename": "argstest.py",
"type": "Python script text executable, ASCII text"
},
{
"filename": "blkid-p.out",
"type": "ASCII text"
},
{
"filename": "blkid-pi.out",
"type": "ASCII text, with very long lines"
},
{
"filename": "cd_catalog.xml",
"type": "XML 1.0 document text, ASCII text, with CRLF line terminators"
},
{
"filename": "centosserial.sh",
"type": "Bourne-Again shell script text executable, UTF-8 Unicode text"
},
...
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"filename": string,
"type ": string
}
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

235
docs/parsers/ntpq.md Normal file
View File

@@ -0,0 +1,235 @@
# jc.parsers.ntpq
jc - JSON CLI output utility ntpq Parser
Usage:
specify --ntpq as the first argument if the piped input is coming from ntpq -p
Compatibility:
'linux'
Examples:
$ ntpq -p | jc --ntpq -p
[
{
"remote": "44.190.6.254",
"refid": "127.67.113.92",
"st": 2,
"t": "u",
"when": 1,
"poll": 64,
"reach": 1,
"delay": 23.399,
"offset": -2.805,
"jitter": 2.131,
"state": null
},
{
"remote": "ntp.wdc1.us.lea",
"refid": "130.133.1.10",
"st": 2,
"t": "u",
"when": null,
"poll": 64,
"reach": 1,
"delay": 93.053,
"offset": -0.807,
"jitter": 2.839,
"state": null
},
{
"remote": "clock.team-cymr",
"refid": "204.9.54.119",
"st": 2,
"t": "u",
"when": null,
"poll": 64,
"reach": 1,
"delay": 70.337,
"offset": -2.909,
"jitter": 2.6,
"state": null
},
{
"remote": "mirror1.sjc02.s",
"refid": "216.218.254.202",
"st": 2,
"t": "u",
"when": 2,
"poll": 64,
"reach": 1,
"delay": 29.325,
"offset": 1.044,
"jitter": 4.069,
"state": null,
}
]
$ ntpq -pn| jc --ntpq -p
[
{
"remote": "44.190.6.254",
"refid": "127.67.113.92",
"st": 2,
"t": "u",
"when": 66,
"poll": 64,
"reach": 377,
"delay": 22.69,
"offset": -0.392,
"jitter": 2.085,
"state": "+"
},
{
"remote": "108.59.2.24",
"refid": "130.133.1.10",
"st": 2,
"t": "u",
"when": 63,
"poll": 64,
"reach": 377,
"delay": 90.805,
"offset": 2.84,
"jitter": 1.908,
"state": "-"
},
{
"remote": "38.229.71.1",
"refid": "204.9.54.119",
"st": 2,
"t": "u",
"when": 64,
"poll": 64,
"reach": 377,
"delay": 68.699,
"offset": -0.61,
"jitter": 2.576,
"state": "+"
},
{
"remote": "72.5.72.15",
"refid": "216.218.254.202",
"st": 2,
"t": "u",
"when": 63,
"poll": 64,
"reach": 377,
"delay": 22.654,
"offset": 0.231,
"jitter": 1.964,
"state": "*"
}
]
$ ntpq -pn| jc --ntpq -p -r
[
{
"s": "+",
"remote": "44.190.6.254",
"refid": "127.67.113.92",
"st": "2",
"t": "u",
"when": "66",
"poll": "64",
"reach": "377",
"delay": "22.690",
"offset": "-0.392",
"jitter": "2.085"
},
{
"s": "-",
"remote": "108.59.2.24",
"refid": "130.133.1.10",
"st": "2",
"t": "u",
"when": "63",
"poll": "64",
"reach": "377",
"delay": "90.805",
"offset": "2.840",
"jitter": "1.908"
},
{
"s": "+",
"remote": "38.229.71.1",
"refid": "204.9.54.119",
"st": "2",
"t": "u",
"when": "64",
"poll": "64",
"reach": "377",
"delay": "68.699",
"offset": "-0.610",
"jitter": "2.576"
},
{
"s": "*",
"remote": "72.5.72.15",
"refid": "216.218.254.202",
"st": "2",
"t": "u",
"when": "63",
"poll": "64",
"reach": "377",
"delay": "22.654",
"offset": "0.231",
"jitter": "1.964"
}
]
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"state": string, # space/~ converted to null
"remote": string,
"refid": string,
"st": integer,
"t": string,
"when": integer, # - converted to null
"poll": integer,
"reach": integer,
"delay": float,
"offset": float,
"jitter": float
},
]
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.

View File

@@ -0,0 +1,87 @@
# jc.parsers.timedatectl
jc - JSON CLI output utility timedatectl Parser
Usage:
specify --timedatectl as the first argument if the piped input is coming from timedatectl or timedatectl status
Compatibility:
'linux'
Examples:
$ timedatectl | jc --timedatectl -p
{
"local_time": "Tue 2020-03-10 17:53:21 PDT",
"universal_time": "Wed 2020-03-11 00:53:21 UTC",
"rtc_time": "Wed 2020-03-11 00:53:21",
"time_zone": "America/Los_Angeles (PDT, -0700)",
"ntp_enabled": true,
"ntp_synchronized": true,
"rtc_in_local_tz": false,
"dst_active": true
}
$ timedatectl | jc --timedatectl -p -r
{
"local_time": "Tue 2020-03-10 17:53:21 PDT",
"universal_time": "Wed 2020-03-11 00:53:21 UTC",
"rtc_time": "Wed 2020-03-11 00:53:21",
"time_zone": "America/Los_Angeles (PDT, -0700)",
"ntp_enabled": "yes",
"ntp_synchronized": "yes",
"rtc_in_local_tz": "no",
"dst_active": "yes"
}
## info
```python
info(self, /, *args, **kwargs)
```
## process
```python
process(proc_data)
```
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary. Structured data with the following schema:
{
"local_time": string,
"universal_time": string,
"rtc_time": string,
"time_zone": string,
"ntp_enabled": boolean,
"ntp_synchronized": boolean,
"system_clock_synchronized": boolean,
"systemd-timesyncd.service_active": boolean,
"rtc_in_local_tz": boolean,
"dst_active": boolean
}
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.

View File

@@ -9,11 +9,16 @@ import importlib
import textwrap
import signal
import json
from pygments import highlight
from pygments.style import Style
from pygments.token import (Name, Number, String, Keyword)
from pygments.lexers import JsonLexer
from pygments.formatters import Terminal256Formatter
import jc.utils
class info():
version = '1.8.1'
version = '1.10.2'
description = 'jc cli output JSON conversion tool'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -22,6 +27,8 @@ class info():
__version__ = info.version
parsers = [
'airport',
'airport-s',
'arp',
'blkid',
'crontab',
@@ -31,6 +38,7 @@ parsers = [
'dig',
'du',
'env',
'file',
'free',
'fstab',
'group',
@@ -49,6 +57,7 @@ parsers = [
'lsof',
'mount',
'netstat',
'ntpq',
'passwd',
'pip-list',
'pip-show',
@@ -61,6 +70,7 @@ parsers = [
'systemctl-lj',
'systemctl-ls',
'systemctl-luf',
'timedatectl',
'uname',
'uptime',
'w',
@@ -70,6 +80,23 @@ parsers = [
]
class JcStyle(Style):
styles = {
Name.Tag: 'bold ansiblue', # key names
Keyword: 'ansibrightblack', # true, false, null
Number: 'ansimagenta', # int, float
String: 'ansigreen' # string
}
def piped_output():
"""returns False if stdout is a TTY. True if output is being piped to another program"""
if sys.stdout.isatty():
return False
else:
return True
def ctrlc(signum, frame):
"""exit with error on SIGINT"""
sys.exit(1)
@@ -162,6 +189,7 @@ def helptext(message):
Options:
-a about jc
-d debug - show trace messages
-m monochrome output
-p pretty print output
-q quiet - suppress warnings
-r raw JSON output
@@ -176,11 +204,17 @@ def helptext(message):
print(textwrap.dedent(helptext_string), file=sys.stderr)
def json_out(data, pretty=False):
if pretty:
print(json.dumps(data, indent=2))
def json_out(data, pretty=False, mono=False, piped_out=False):
if not mono and not piped_out:
if pretty:
print(highlight(json.dumps(data, indent=2), JsonLexer(), Terminal256Formatter(style=JcStyle))[0:-1])
else:
print(highlight(json.dumps(data), JsonLexer(), Terminal256Formatter(style=JcStyle))[0:-1])
else:
print(json.dumps(data))
if pretty:
print(json.dumps(data, indent=2))
else:
print(json.dumps(data))
def generate_magic_command(args):
@@ -194,20 +228,18 @@ def generate_magic_command(args):
return False, None
# correctly parse escape characters and spaces with shlex
args_given = " ".join(map(shlex.quote, args[1:])).split()
args_given = ' '.join(map(shlex.quote, args[1:])).split()
options = []
# find the options
popped = 0
for i, arg in enumerate(args_given):
for arg in list(args_given):
# parser found - use standard syntax
if arg.startswith('--'):
return False, None
# option found - populate option list
elif arg.startswith('-'):
options.append(args_given.pop(i - popped)[1:])
popped += 1
options.extend(args_given.pop(0)[1:])
# command found if iterator didn't already stop - stop iterating
else:
@@ -268,12 +300,13 @@ def main():
options.extend(opt[1:])
debug = 'd' in options
mono = 'm' in options
pretty = 'p' in options
quiet = 'q' in options
raw = 'r' in options
if 'a' in options:
json_out(about_jc(), pretty=pretty)
json_out(about_jc(), pretty=pretty, mono=mono, piped_out=piped_output())
exit()
if sys.stdin.isatty():
@@ -314,7 +347,7 @@ def main():
helptext('missing or incorrect arguments')
sys.exit(1)
json_out(result, pretty=pretty)
json_out(result, pretty=pretty, mono=mono, piped_out=piped_output())
if __name__ == '__main__':

141
jc/parsers/airport.py Normal file
View File

@@ -0,0 +1,141 @@
"""jc - JSON CLI output utility airport -I Parser
Usage:
specify --airport as the first argument if the piped input is coming from airport -I (OSX)
This program can be found at:
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport
Compatibility:
'darwin'
Examples:
$ airport -I | jc --airport -p
{
"agrctlrssi": -66,
"agrextrssi": 0,
"agrctlnoise": -90,
"agrextnoise": 0,
"state": "running",
"op_mode": "station",
"lasttxrate": 195,
"maxrate": 867,
"lastassocstatus": 0,
"802_11_auth": "open",
"link_auth": "wpa2-psk",
"bssid": "3c:37:86:15:ad:f9",
"ssid": "SnazzleDazzle",
"mcs": 0,
"channel": "48,80"
}
$ airport -I | jc --airport -p -r
{
"agrctlrssi": "-66",
"agrextrssi": "0",
"agrctlnoise": "-90",
"agrextnoise": "0",
"state": "running",
"op_mode": "station",
"lasttxrate": "195",
"maxrate": "867",
"lastassocstatus": "0",
"802_11_auth": "open",
"link_auth": "wpa2-psk",
"bssid": "3c:37:86:15:ad:f9",
"ssid": "SnazzleDazzle",
"mcs": "0",
"channel": "48,80"
}
"""
import jc.utils
class info():
version = '1.0'
description = 'airport -I command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['darwin']
magic_commands = ['airport -I']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary. Structured data with the following schema:
{
"agrctlrssi": integer,
"agrextrssi": integer,
"agrctlnoise": integer,
"agrextnoise": integer,
"state": string,
"op_mode": string,
"lasttxrate": integer,
"maxrate": integer,
"lastassocstatus": integer,
"802_11_auth": string,
"link_auth": string,
"bssid": string,
"ssid": string,
"mcs": integer,
"channel": string
}
"""
# integer changes
int_list = ['agrctlrssi', 'agrextrssi', 'agrctlnoise', 'agrextnoise',
'lasttxrate', 'maxrate', 'lastassocstatus', 'mcs']
for key in proc_data:
if key in int_list:
try:
proc_data[key] = int(proc_data[key])
except (ValueError):
proc_data[key] = None
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = {}
for line in filter(None, data.splitlines()):
linedata = line.split(':', maxsplit=1)
raw_output[linedata[0].strip().lower().replace(' ', '_').replace('.', '_')] = linedata[1].strip()
if raw:
return raw_output
else:
return process(raw_output)

186
jc/parsers/airport_s.py Normal file
View File

@@ -0,0 +1,186 @@
"""jc - JSON CLI output utility airport -s Parser
Usage:
specify --airport as the first argument if the piped input is coming from airport -s (OSX)
This program can be found at:
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport
Compatibility:
'darwin'
Examples:
$ airport -s | jc --airport-s -p
[
{
"ssid": "DIRECT-4A-HP OfficeJet 3830",
"bssid": "00:67:eb:2a:a7:3b",
"rssi": -90,
"channel": "6",
"ht": true,
"cc": "--",
"security": [
"WPA2(PSK/AES/AES)"
]
},
{
"ssid": "Latitude38",
"bssid": "c0:ff:d5:d2:7a:f3",
"rssi": -85,
"channel": "11",
"ht": true,
"cc": "US",
"security": [
"WPA2(PSK/AES/AES)"
]
},
{
"ssid": "xfinitywifi",
"bssid": "6e:e3:0e:b8:45:99",
"rssi": -83,
"channel": "11",
"ht": true,
"cc": "US",
"security": [
"NONE"
]
},
...
]
$ airport -s | jc --airport -p -r
[
{
"ssid": "DIRECT-F3-HP ENVY 5660 series",
"bssid": "b0:5a:da:6f:0a:d4",
"rssi": "-93",
"channel": "1",
"ht": "Y",
"cc": "--",
"security": "WPA2(PSK/AES/AES)"
},
{
"ssid": "YouAreInfected-5",
"bssid": "5c:e3:0e:c2:85:da",
"rssi": "-85",
"channel": "36",
"ht": "Y",
"cc": "US",
"security": "WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)"
},
{
"ssid": "YuanFamily",
"bssid": "5c:e3:0e:b8:5f:9a",
"rssi": "-84",
"channel": "11",
"ht": "Y",
"cc": "US",
"security": "WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)"
},
...
]
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.0'
description = 'airport -s command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['darwin']
magic_commands = ['airport -s']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"ssid": string,
"bssid": string,
"rssi": integer,
"channel": string,
"ht": boolean,
"cc": string,
"security": [
string,
]
}
]
"""
for entry in proc_data:
# integers
int_list = ['rssi']
for key in int_list:
if key in entry:
try:
entry[key] = int(entry[key])
except (ValueError):
entry[key] = None
# booleans
bool_list = ['ht']
for key in entry:
if key in bool_list:
try:
entry[key] = True if entry[key] == 'Y' else False
except (ValueError):
entry[key] = None
if 'security' in entry:
entry['security'] = entry['security'].split()
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
cleandata = data.splitlines()
# fix headers
cleandata[0] = cleandata[0].lower()
cleandata[0] = cleandata[0].replace('-', '_')
cleandata[0] = cleandata[0].replace('security (auth/unicast/group)', 'security')
# parse the data
raw_output = jc.parsers.universal.sparse_table_parse(cleandata)
if raw:
return raw_output
else:
return process(raw_output)

View File

@@ -91,7 +91,7 @@ import jc.parsers.universal
class info():
version = '1.1'
version = '1.3'
description = 'arp command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -156,20 +156,21 @@ def parse(data, raw=False, quiet=False):
cleandata = data.splitlines()
# remove final Entries row if -v was used
if cleandata[-1].find('Entries:') == 0:
if cleandata[-1].startswith('Entries:'):
cleandata.pop(-1)
# detect if osx style was used
if cleandata[0].find(' ifscope ') != -1:
if cleandata[0][-1] == ']':
raw_output = []
for line in cleandata:
line = line.split()
output_line = {}
output_line['name'] = line[0]
output_line['address'] = line[1].lstrip('(').rstrip(')')
output_line['hwtype'] = line[-1].lstrip('[').rstrip(']')
output_line['hwaddress'] = line[3]
output_line['iface'] = line[5]
splitline = line.split()
output_line = {
'name': splitline[0],
'address': splitline[1].lstrip('(').rstrip(')'),
'hwtype': splitline[-1].lstrip('[').rstrip(']'),
'hwaddress': splitline[3],
'iface': splitline[5]
}
raw_output.append(output_line)
if raw:
@@ -178,7 +179,7 @@ def parse(data, raw=False, quiet=False):
return process(raw_output)
# detect if linux style was used
elif cleandata[0].find('Address') == 0:
elif cleandata[0].startswith('Address'):
# fix header row to change Flags Mask to flags_mask
cleandata[0] = cleandata[0].replace('Flags Mask', 'flags_mask')

View File

@@ -132,7 +132,7 @@ import jc.parsers.universal
class info():
version = '1.1'
version = '1.2'
description = 'crontab command and file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -227,13 +227,13 @@ def parse(data, raw=False, quiet=False):
# Clear any commented lines
for i, line in reversed(list(enumerate(cleandata))):
if line.strip().find('#') == 0:
if line.strip().startswith('#'):
cleandata.pop(i)
# Pop any variable assignment lines
cron_var = []
for i, line in reversed(list(enumerate(cleandata))):
if line.find('=') != -1:
if '=' in line:
var_line = cleandata.pop(i)
var_name = var_line.split('=', maxsplit=1)[0].strip()
var_value = var_line.split('=', maxsplit=1)[1].strip()

View File

@@ -133,7 +133,7 @@ import jc.parsers.universal
class info():
version = '1.0'
version = '1.1'
description = 'crontab file parser with user support'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -228,13 +228,13 @@ def parse(data, raw=False, quiet=False):
# Clear any commented lines
for i, line in reversed(list(enumerate(cleandata))):
if line.strip().find('#') == 0:
if line.strip().startswith('#'):
cleandata.pop(i)
# Pop any variable assignment lines
cron_var = []
for i, line in reversed(list(enumerate(cleandata))):
if line.find('=') != -1:
if '=' in line:
var_line = cleandata.pop(i)
var_name = var_line.split('=', maxsplit=1)[0].strip()
var_value = var_line.split('=', maxsplit=1)[1].strip()

View File

@@ -73,7 +73,7 @@ import jc.parsers.universal
class info():
version = '1.1'
version = '1.2'
description = 'df command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -135,7 +135,7 @@ def process(proc_data):
# change any entry for key with '_blocks' in the name to int
for k in entry:
if str(k).find('_blocks') != -1:
if '_blocks' in str(k):
try:
blocks_int = int(entry[k])
entry[k] = blocks_int

View File

@@ -324,7 +324,7 @@ import jc.utils
class info():
version = '1.0'
version = '1.2'
description = 'dig command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -361,6 +361,15 @@ def process(proc_data):
"answer_num": integer,
"authority_num": integer,
"additional_num": integer,
"axfr": [
{
"name": string,
"class": string,
"type": string,
"ttl": integer,
"data": string
}
],
"question": {
"name": string,
"class": string,
@@ -388,6 +397,7 @@ def process(proc_data):
"server": string,
"when": string,
"rcvd": integer
"size": string
}
]
"""
@@ -402,6 +412,14 @@ def process(proc_data):
except (ValueError):
entry[key] = None
if 'axfr' in entry:
for ax in entry['axfr']:
try:
ttl_int = int(ax['ttl'])
ax['ttl'] = ttl_int
except (ValueError):
ax['ttl'] = None
if 'answer' in entry:
for ans in entry['answer']:
try:
@@ -508,6 +526,25 @@ def parse_answer(answer):
'data': answer_data}
def parse_axfr(axfr):
# ; <<>> DiG 9.11.14-3-Debian <<>> @81.4.108.41 axfr zonetransfer.me +nocookie
# ; (1 server found)
# ;; global options: +cmd
# zonetransfer.me. 7200 IN A 5.196.105.14
axfr = axfr.split(maxsplit=4)
axfr_name = axfr[0]
axfr_ttl = axfr[1]
axfr_class = axfr[2]
axfr_type = axfr[3]
axfr_data = axfr[4]
return {'name': axfr_name,
'ttl': axfr_ttl,
'class': axfr_class,
'type': axfr_type,
'data': axfr_data}
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
@@ -534,23 +571,38 @@ def parse(data, raw=False, quiet=False):
question = False
authority = False
answer = False
axfr = False
output_entry = {}
for line in cleandata:
if line.find(';; ->>HEADER<<-') == 0:
if line.startswith('; <<>> ') and ' axfr ' in line.lower():
question = False
authority = False
answer = False
axfr = True
axfr_list = []
continue
if ';' not in line and axfr:
axfr_list.append(parse_axfr(line))
output_entry.update({'axfr': axfr_list})
continue
if line.startswith(';; ->>HEADER<<-'):
output_entry = {}
output_entry.update(parse_header(line))
continue
if line.find(';; flags:') == 0:
if line.startswith(';; flags:'):
output_entry.update(parse_flags_line(line))
continue
if line.find(';; QUESTION SECTION:') == 0:
if line.startswith(';; QUESTION SECTION:'):
question = True
authority = False
answer = False
axfr = False
continue
if question:
@@ -558,52 +610,60 @@ def parse(data, raw=False, quiet=False):
question = False
authority = False
answer = False
axfr = False
continue
if line.find(';; AUTHORITY SECTION:') == 0:
if line.startswith(';; AUTHORITY SECTION:'):
question = False
authority = True
answer = False
axfr = False
authority_list = []
continue
if line.find(';') == -1 and authority:
if ';' not in line and authority:
authority_list.append(parse_authority(line))
output_entry.update({'authority': authority_list})
continue
if line.find(';; ANSWER SECTION:') == 0:
if line.startswith(';; ANSWER SECTION:'):
question = False
authority = False
answer = True
axfr = False
answer_list = []
continue
if line.find(';') == -1 and answer:
if ';' not in line and answer:
answer_list.append(parse_answer(line))
output_entry.update({'answer': answer_list})
continue
# footer consists of 4 lines
# footer line 1
if line.find(';; Query time:') == 0:
if line.startswith(';; Query time:'):
output_entry.update({'query_time': line.split(':')[1].lstrip()})
continue
# footer line 2
if line.find(';; SERVER:') == 0:
if line.startswith(';; SERVER:'):
output_entry.update({'server': line.split(':')[1].lstrip()})
continue
# footer line 3
if line.find(';; WHEN:') == 0:
if line.startswith(';; WHEN:'):
output_entry.update({'when': line.split(':', maxsplit=1)[1].lstrip()})
continue
# footer line 4 (last line)
if line.find(';; MSG SIZE rcvd:') == 0:
if line.startswith(';; MSG SIZE rcvd:'):
output_entry.update({'rcvd': line.split(':')[1].lstrip()})
if output_entry:
raw_output.append(output_entry)
elif line.startswith(';; XFR size:'):
output_entry.update({'size': line.split(':')[1].lstrip()})
if output_entry:
raw_output.append(output_entry)

128
jc/parsers/file.py Normal file
View File

@@ -0,0 +1,128 @@
"""jc - JSON CLI output utility file command Parser
Usage:
specify --file as the first argument if the piped input is coming from file.
Compatibility:
'linux', 'aix', 'freebsd', 'darwin'
Examples:
$ file * | jc --file -p
[
{
"filename": "Applications",
"type": "directory"
},
{
"filename": "another file with spaces",
"type": "empty"
},
{
"filename": "argstest.py",
"type": "Python script text executable, ASCII text"
},
{
"filename": "blkid-p.out",
"type": "ASCII text"
},
{
"filename": "blkid-pi.out",
"type": "ASCII text, with very long lines"
},
{
"filename": "cd_catalog.xml",
"type": "XML 1.0 document text, ASCII text, with CRLF line terminators"
},
{
"filename": "centosserial.sh",
"type": "Bourne-Again shell script text executable, UTF-8 Unicode text"
},
...
]
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.1'
description = 'file command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux', 'aix', 'freebsd', 'darwin']
magic_commands = ['file']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"filename": string,
"type ": string
}
]
"""
# No further processing
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
warned = False
for line in filter(None, data.splitlines()):
linedata = line.rsplit(': ', maxsplit=1)
try:
filename = linedata[0].strip()
filetype = linedata[1].strip()
raw_output.append(
{
'filename': filename,
'type': filetype
}
)
except IndexError:
if not warned:
jc.utils.warning_message('Filenames with newline characters detected. Some filenames may be truncated.')
warned = True
if raw:
return raw_output
else:
return process(raw_output)

View File

@@ -70,7 +70,7 @@ import jc.utils
class info():
version = '1.0'
version = '1.1'
description = 'fstab file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -145,7 +145,7 @@ def parse(data, raw=False, quiet=False):
for line in cleandata:
output_line = {}
# ignore commented lines
if line.strip().find('#') == 0:
if line.strip().startswith('#'):
continue
line_list = line.split(maxsplit=6)

View File

@@ -80,21 +80,11 @@ def process(proc_data):
# rebuild output for added semantic information
processed = []
for k, v in proc_data.items():
proc_line = {}
proc_line['line'] = k
proc_line['command'] = v
proc_line = {
'line': int(k) if k.isdigit() else None,
'command': v,
}
processed.append(proc_line)
for entry in processed:
int_list = ['line']
for key in int_list:
if key in entry:
try:
key_int = int(entry[key])
entry[key] = key_int
except (ValueError):
entry[key] = None
return processed
@@ -121,17 +111,14 @@ def parse(data, raw=False, quiet=False):
# split lines and clear out any non-ascii chars
linedata = data.encode('ascii', errors='ignore').decode().splitlines()
# Clear any blank lines
cleandata = list(filter(None, linedata))
if cleandata:
for entry in cleandata:
try:
parsed_line = entry.split(maxsplit=1)
raw_output[parsed_line[0]] = parsed_line[1]
except IndexError:
# need to catch indexerror in case there is weird input from prior commands
pass
# Skip any blank lines
for entry in filter(None, linedata):
try:
parsed_line = entry.split(maxsplit=1)
raw_output[parsed_line[0]] = parsed_line[1]
except IndexError:
# need to catch indexerror in case there is weird input from prior commands
pass
if raw:
return raw_output

View File

@@ -61,7 +61,7 @@ import jc.utils
class info():
version = '1.0'
version = '1.1'
description = '/etc/hosts file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -126,7 +126,7 @@ def parse(data, raw=False, quiet=False):
for line in cleandata:
output_line = {}
# ignore commented lines
if line.strip().find('#') == 0:
if line.strip().startswith('#'):
continue
line_list = line.split(maxsplit=1)
@@ -136,7 +136,7 @@ def parse(data, raw=False, quiet=False):
comment_found = False
for i, item in enumerate(hosts_list):
if item.find('#') != -1:
if '#' in item:
comment_found = True
comment_item = i
break

View File

@@ -146,7 +146,7 @@ from ifconfigparser import IfconfigParser
class info():
version = '1.5'
version = '1.6'
description = 'ifconfig command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -220,7 +220,7 @@ def process(proc_data):
# convert OSX-style subnet mask to dotted quad
if 'ipv4_mask' in entry:
try:
if entry['ipv4_mask'].find('0x') == 0:
if entry['ipv4_mask'].startswith('0x'):
new_mask = entry['ipv4_mask']
new_mask = new_mask.lstrip('0x')
new_mask = '.'.join(str(int(i, 16)) for i in [new_mask[i:i + 2] for i in range(0, len(new_mask), 2)])

View File

@@ -134,7 +134,7 @@ import jc.utils
class info():
version = '1.1'
version = '1.2'
description = 'iptables command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -247,7 +247,7 @@ def parse(data, raw=False, quiet=False):
for line in cleandata:
if line.find('Chain') == 0:
if line.startswith('Chain'):
raw_output.append(chain)
chain = {}
headers = []
@@ -259,7 +259,7 @@ def parse(data, raw=False, quiet=False):
continue
elif line.find('target') == 0 or line.find('pkts') == 1 or line.find('num') == 0:
elif line.startswith('target') or line.find('pkts') == 1 or line.startswith('num'):
headers = []
headers = [h for h in ' '.join(line.lower().strip().split()).split() if h]
headers.append("options")

View File

@@ -77,7 +77,7 @@ import jc.utils
class info():
version = '1.0'
version = '1.1'
description = 'jobs command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -176,11 +176,11 @@ def parse(data, raw=False, quiet=False):
parsed_line.insert(0, job_number)
# check for + or - in first field
if parsed_line[0].find('+') != -1:
if '+' in parsed_line[0]:
job_history = 'current'
parsed_line[0] = parsed_line[0].rstrip('+')
if parsed_line[0].find('-') != -1:
if '-' in parsed_line[0]:
job_history = 'previous'
parsed_line[0] = parsed_line[0].rstrip('-')

View File

@@ -97,7 +97,7 @@ import jc.parsers.universal
class info():
version = '1.0'
version = '1.1'
description = 'lsof command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -180,47 +180,6 @@ def parse(data, raw=False, quiet=False):
raw_output = jc.parsers.universal.sparse_table_parse(cleandata)
'''
# find column value of last character of each header
header_text = cleandata.pop(0).lower()
# clean up 'size/off' header
# even though forward slash in a key is valid json, it can make things difficult
header_row = header_text.replace('/', '_')
headers = header_row.split()
header_spec = []
for i, h in enumerate(headers):
# header tuple is (index, header_name, col)
header_spec.append((i, h, header_row.find(h) + len(h)))
# parse lines
for entry in cleandata:
output_line = {}
# normalize data by inserting Null for missing data
temp_line = entry.split(maxsplit=len(headers) - 1)
for spec in header_spec:
index = spec[0]
header_name = spec[1]
col = spec[2] - 1 # subtract one since column starts at 0 instead of 1
if header_name == 'command' or header_name == 'name':
continue
if entry[col] in string.whitespace:
temp_line.insert(index, None)
name = ' '.join(temp_line[9:])
fixed_line = temp_line[0:9]
fixed_line.append(name)
output_line = dict(zip(headers, fixed_line))
raw_output.append(output_line)
'''
if raw:
return raw_output
else:

View File

@@ -56,7 +56,7 @@ import jc.utils
class info():
version = '1.1'
version = '1.2'
description = 'mount command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -165,7 +165,7 @@ def parse(data, raw=False, quiet=False):
if cleandata:
# check for OSX output
if cleandata[0].find(' type ') == -1:
if ' type ' not in cleandata[0]:
raw_output = osx_parse(cleandata)
else:

View File

@@ -313,7 +313,7 @@ import jc.utils
class info():
version = '1.2'
version = '1.3'
description = 'netstat command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -498,14 +498,14 @@ def parse_post(raw_data):
if 'proto' in entry and 'kind' in entry:
if entry['kind'] == 'network':
if entry['proto'].find('tcp') != -1:
if 'tcp' in entry['proto']:
entry['transport_protocol'] = 'tcp'
elif entry['proto'].find('udp') != -1:
elif 'udp' in entry['proto']:
entry['transport_protocol'] = 'udp'
else:
entry['transport_protocol'] = None
if entry['proto'].find('6') != -1:
if '6' in entry['proto']:
entry['network_protocol'] = 'ipv6'
else:
entry['network_protocol'] = 'ipv4'
@@ -542,19 +542,19 @@ def parse(data, raw=False, quiet=False):
for line in cleandata:
if line.find('Active Internet') == 0:
if line.startswith('Active Internet'):
network_list = []
network = True
socket = False
continue
if line.find('Active UNIX') == 0:
if line.startswith('Active UNIX'):
socket_list = []
network = False
socket = True
continue
if line.find('Proto') == 0:
if line.startswith('Proto'):
header_text = normalize_headers(line)
headers = header_text.split()
continue

297
jc/parsers/ntpq.py Normal file
View File

@@ -0,0 +1,297 @@
"""jc - JSON CLI output utility ntpq Parser
Usage:
specify --ntpq as the first argument if the piped input is coming from ntpq -p
Compatibility:
'linux'
Examples:
$ ntpq -p | jc --ntpq -p
[
{
"remote": "44.190.6.254",
"refid": "127.67.113.92",
"st": 2,
"t": "u",
"when": 1,
"poll": 64,
"reach": 1,
"delay": 23.399,
"offset": -2.805,
"jitter": 2.131,
"state": null
},
{
"remote": "ntp.wdc1.us.lea",
"refid": "130.133.1.10",
"st": 2,
"t": "u",
"when": null,
"poll": 64,
"reach": 1,
"delay": 93.053,
"offset": -0.807,
"jitter": 2.839,
"state": null
},
{
"remote": "clock.team-cymr",
"refid": "204.9.54.119",
"st": 2,
"t": "u",
"when": null,
"poll": 64,
"reach": 1,
"delay": 70.337,
"offset": -2.909,
"jitter": 2.6,
"state": null
},
{
"remote": "mirror1.sjc02.s",
"refid": "216.218.254.202",
"st": 2,
"t": "u",
"when": 2,
"poll": 64,
"reach": 1,
"delay": 29.325,
"offset": 1.044,
"jitter": 4.069,
"state": null,
}
]
$ ntpq -pn| jc --ntpq -p
[
{
"remote": "44.190.6.254",
"refid": "127.67.113.92",
"st": 2,
"t": "u",
"when": 66,
"poll": 64,
"reach": 377,
"delay": 22.69,
"offset": -0.392,
"jitter": 2.085,
"state": "+"
},
{
"remote": "108.59.2.24",
"refid": "130.133.1.10",
"st": 2,
"t": "u",
"when": 63,
"poll": 64,
"reach": 377,
"delay": 90.805,
"offset": 2.84,
"jitter": 1.908,
"state": "-"
},
{
"remote": "38.229.71.1",
"refid": "204.9.54.119",
"st": 2,
"t": "u",
"when": 64,
"poll": 64,
"reach": 377,
"delay": 68.699,
"offset": -0.61,
"jitter": 2.576,
"state": "+"
},
{
"remote": "72.5.72.15",
"refid": "216.218.254.202",
"st": 2,
"t": "u",
"when": 63,
"poll": 64,
"reach": 377,
"delay": 22.654,
"offset": 0.231,
"jitter": 1.964,
"state": "*"
}
]
$ ntpq -pn| jc --ntpq -p -r
[
{
"s": "+",
"remote": "44.190.6.254",
"refid": "127.67.113.92",
"st": "2",
"t": "u",
"when": "66",
"poll": "64",
"reach": "377",
"delay": "22.690",
"offset": "-0.392",
"jitter": "2.085"
},
{
"s": "-",
"remote": "108.59.2.24",
"refid": "130.133.1.10",
"st": "2",
"t": "u",
"when": "63",
"poll": "64",
"reach": "377",
"delay": "90.805",
"offset": "2.840",
"jitter": "1.908"
},
{
"s": "+",
"remote": "38.229.71.1",
"refid": "204.9.54.119",
"st": "2",
"t": "u",
"when": "64",
"poll": "64",
"reach": "377",
"delay": "68.699",
"offset": "-0.610",
"jitter": "2.576"
},
{
"s": "*",
"remote": "72.5.72.15",
"refid": "216.218.254.202",
"st": "2",
"t": "u",
"when": "63",
"poll": "64",
"reach": "377",
"delay": "22.654",
"offset": "0.231",
"jitter": "1.964"
}
]
"""
import jc.utils
import jc.parsers.universal
class info():
version = '1.0'
description = 'ntpq -p command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['ntpq']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
List of dictionaries. Structured data with the following schema:
[
{
"state": string, # space/~ converted to null
"remote": string,
"refid": string,
"st": integer,
"t": string,
"when": integer, # - converted to null
"poll": integer,
"reach": integer,
"delay": float,
"offset": float,
"jitter": float
},
]
"""
for entry in proc_data:
if entry['s'] == '~':
entry['s'] = None
entry['state'] = entry.pop('s')
int_list = ['st', 'when', 'poll', 'reach']
for key in int_list:
if key in entry:
try:
entry[key] = int(entry[key])
except (ValueError):
entry[key] = None
float_list = ['delay', 'offset', 'jitter']
for key in float_list:
if key in entry:
try:
entry[key] = float(entry[key])
except (ValueError):
entry[key] = None
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = []
cleandata = data.splitlines()
cleandata[0] = 's ' + cleandata[0]
cleandata[0] = cleandata[0].lower()
# delete header delimiter
del cleandata[1]
# separate first character with a space for easier parsing
for i, line in list(enumerate(cleandata[1:])):
if line[0] == ' ':
# fixup for no-state
cleandata[i + 1] = '~ ' + line[1:]
else:
# fixup - realign columns since we added the 's' column
cleandata[i + 1] = line[:1] + ' ' + line[1:]
# fixup for occaisional ip/hostname fields with a space
cleandata[i + 1] = cleandata[i + 1].replace(' (', '_(')
raw_output = jc.parsers.universal.simple_table_parse(cleandata)
if raw:
return raw_output
else:
return process(raw_output)

View File

@@ -32,7 +32,7 @@ import jc.parsers.universal
class info():
version = '1.0'
version = '1.1'
description = 'pip list command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -94,7 +94,7 @@ def parse(data, raw=False, quiet=False):
cleandata = list(filter(None, linedata))
# detect legacy output type
if cleandata[0].find(' (') != -1:
if ' (' in cleandata[0]:
for row in cleandata:
raw_output.append({'package': row.split(' (')[0],
'version': row.split(' (')[1].rstrip(')')})
@@ -103,7 +103,7 @@ def parse(data, raw=False, quiet=False):
else:
# clear separator line
for i, line in reversed(list(enumerate(cleandata))):
if line.find('---') != -1:
if '---' in line:
cleandata.pop(i)
cleandata[0] = cleandata[0].lower()

View File

@@ -104,7 +104,7 @@ import jc.utils
class info():
version = '1.0'
version = '1.1'
description = 'stat command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -208,7 +208,7 @@ def parse(data, raw=False, quiet=False):
output_line['file'] = line_list[1]
# populate link_to field if -> found
if output_line['file'].find(' -> ') != -1:
if ' -> ' in output_line['file']:
filename = output_line['file'].split(' -> ')[0].strip('\u2018').rstrip('\u2019')
link = output_line['file'].split(' -> ')[1].strip('\u2018').rstrip('\u2019')
output_line['file'] = filename
@@ -229,7 +229,7 @@ def parse(data, raw=False, quiet=False):
continue
# line #3
if line.find('Device:') == 0:
if line.startswith('Device:'):
line_list = line.split()
output_line['device'] = line_list[1]
output_line['inode'] = line_list[3]
@@ -237,7 +237,7 @@ def parse(data, raw=False, quiet=False):
continue
# line #4
if line.find('Access: (') == 0:
if line.startswith('Access: ('):
line = line.replace('(', ' ').replace(')', ' ').replace('/', ' ')
line_list = line.split()
output_line['access'] = line_list[1]
@@ -249,19 +249,19 @@ def parse(data, raw=False, quiet=False):
continue
# line #5
if line.find('Access: 2') == 0:
if line.startswith('Access: 2'):
line_list = line.split(maxsplit=1)
output_line['access_time'] = line_list[1]
continue
# line #6
if line.find('Modify:') == 0:
if line.startswith('Modify:'):
line_list = line.split(maxsplit=1)
output_line['modify_time'] = line_list[1]
continue
# line #7
if line.find('Change:') == 0:
if line.startswith('Change:'):
line_list = line.split(maxsplit=1)
output_line['change_time'] = line_list[1]
continue

View File

@@ -40,7 +40,7 @@ import jc.utils
class info():
version = '1.0'
version = '1.1'
description = 'systemctl command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -110,7 +110,7 @@ def parse(data, raw=False, quiet=False):
raw_output = []
for entry in cleandata[1:]:
if entry.find('LOAD = ') != -1:
if 'LOAD = ' in entry:
break
else:

View File

@@ -59,7 +59,7 @@ import jc.utils
class info():
version = '1.0'
version = '1.1'
description = 'systemctl list-jobs command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -137,7 +137,7 @@ def parse(data, raw=False, quiet=False):
raw_output = []
for entry in cleandata[1:]:
if entry.find('No jobs running.') != -1 or entry.find('jobs listed.') != -1:
if 'No jobs running.' in entry or 'jobs listed.' in entry:
break
else:

View File

@@ -34,7 +34,7 @@ import jc.utils
class info():
version = '1.0'
version = '1.1'
description = 'systemctl list-sockets command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -102,7 +102,7 @@ def parse(data, raw=False, quiet=False):
raw_output = []
for entry in cleandata[1:]:
if entry.find('sockets listed.') != -1:
if 'sockets listed.' in entry:
break
else:

View File

@@ -31,7 +31,7 @@ import jc.utils
class info():
version = '1.0'
version = '1.1'
description = 'systemctl list-unit-files command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -99,7 +99,7 @@ def parse(data, raw=False, quiet=False):
raw_output = []
for entry in cleandata[1:]:
if entry.find('unit files listed.') != -1:
if 'unit files listed.' in entry:
break
else:

122
jc/parsers/timedatectl.py Normal file
View File

@@ -0,0 +1,122 @@
"""jc - JSON CLI output utility timedatectl Parser
Usage:
specify --timedatectl as the first argument if the piped input is coming from timedatectl or timedatectl status
Compatibility:
'linux'
Examples:
$ timedatectl | jc --timedatectl -p
{
"local_time": "Tue 2020-03-10 17:53:21 PDT",
"universal_time": "Wed 2020-03-11 00:53:21 UTC",
"rtc_time": "Wed 2020-03-11 00:53:21",
"time_zone": "America/Los_Angeles (PDT, -0700)",
"ntp_enabled": true,
"ntp_synchronized": true,
"rtc_in_local_tz": false,
"dst_active": true
}
$ timedatectl | jc --timedatectl -p -r
{
"local_time": "Tue 2020-03-10 17:53:21 PDT",
"universal_time": "Wed 2020-03-11 00:53:21 UTC",
"rtc_time": "Wed 2020-03-11 00:53:21",
"time_zone": "America/Los_Angeles (PDT, -0700)",
"ntp_enabled": "yes",
"ntp_synchronized": "yes",
"rtc_in_local_tz": "no",
"dst_active": "yes"
}
"""
import jc.utils
class info():
version = '1.0'
description = 'timedatectl status command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# details = 'enter any other details here'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
compatible = ['linux']
magic_commands = ['timedatectl', 'timedatectl status']
__version__ = info.version
def process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (dictionary) raw structured data to process
Returns:
Dictionary. Structured data with the following schema:
{
"local_time": string,
"universal_time": string,
"rtc_time": string,
"time_zone": string,
"ntp_enabled": boolean,
"ntp_synchronized": boolean,
"system_clock_synchronized": boolean,
"systemd-timesyncd.service_active": boolean,
"rtc_in_local_tz": boolean,
"dst_active": boolean
}
"""
# boolean changes
bool_list = ['ntp_enabled', 'ntp_synchronized', 'rtc_in_local_tz', 'dst_active',
'system_clock_synchronized', 'systemd-timesyncd.service_active']
for key in proc_data:
if key in bool_list:
try:
proc_data[key] = True if proc_data[key] == 'yes' else False
except (ValueError):
proc_data[key] = None
return proc_data
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
raw_output = {}
for line in filter(None, data.splitlines()):
linedata = line.split(':', maxsplit=1)
raw_output[linedata[0].strip().lower().replace(' ', '_')] = linedata[1].strip()
if linedata[0].strip() == 'DST active':
break
if raw:
return raw_output
else:
return process(raw_output)

View File

@@ -1,3 +1,4 @@
ifconfig-parser>=0.0.5
ruamel.yaml>=0.15.0
xmltodict>=0.12.0
Pygments>=2.5.2

View File

@@ -5,14 +5,15 @@ with open('README.md', 'r') as f:
setuptools.setup(
name='jc',
version='1.8.1',
version='1.10.2',
author='Kelly Brazil',
author_email='kellyjonbrazil@gmail.com',
description='This tool serializes the output of popular command line tools and filetypes to structured JSON output.',
install_requires=[
'ifconfig-parser>=0.0.5',
'ruamel.yaml>=0.15.0',
'xmltodict>=0.12.0'
'xmltodict>=0.12.0',
'Pygments>=2.5.2'
],
license='MIT',
long_description=long_description,

File diff suppressed because one or more lines are too long

60
tests/fixtures/centos-7.7/dig-axfr.out vendored Normal file
View File

@@ -0,0 +1,60 @@
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-9.P2.el7 <<>> @81.4.108.41 AXFR zonetransfer.me +nocookie
; (1 server found)
;; global options: +cmd
zonetransfer.me. 7200 IN SOA nsztm1.digi.ninja. robin.digi.ninja. 2019100801 172800 900 1209600 3600
zonetransfer.me. 300 IN HINFO "Casio fx-700G" "Windows XP"
zonetransfer.me. 301 IN TXT "google-site-verification=tyP28J7JAUHA9fw2sHXMgcCC0I6XBmmoVi04VlMewxA"
zonetransfer.me. 7200 IN MX 0 ASPMX.L.GOOGLE.COM.
zonetransfer.me. 7200 IN MX 10 ALT1.ASPMX.L.GOOGLE.COM.
zonetransfer.me. 7200 IN MX 10 ALT2.ASPMX.L.GOOGLE.COM.
zonetransfer.me. 7200 IN MX 20 ASPMX2.GOOGLEMAIL.COM.
zonetransfer.me. 7200 IN MX 20 ASPMX3.GOOGLEMAIL.COM.
zonetransfer.me. 7200 IN MX 20 ASPMX4.GOOGLEMAIL.COM.
zonetransfer.me. 7200 IN MX 20 ASPMX5.GOOGLEMAIL.COM.
zonetransfer.me. 7200 IN A 5.196.105.14
zonetransfer.me. 7200 IN NS nsztm1.digi.ninja.
zonetransfer.me. 7200 IN NS nsztm2.digi.ninja.
_acme-challenge.zonetransfer.me. 301 IN TXT "6Oa05hbUJ9xSsvYy7pApQvwCUSSGgxvrbdizjePEsZI"
_sip._tcp.zonetransfer.me. 14000 IN SRV 0 0 5060 www.zonetransfer.me.
14.105.196.5.IN-ADDR.ARPA.zonetransfer.me. 7200 IN PTR www.zonetransfer.me.
asfdbauthdns.zonetransfer.me. 7900 IN AFSDB 1 asfdbbox.zonetransfer.me.
asfdbbox.zonetransfer.me. 7200 IN A 127.0.0.1
asfdbvolume.zonetransfer.me. 7800 IN AFSDB 1 asfdbbox.zonetransfer.me.
canberra-office.zonetransfer.me. 7200 IN A 202.14.81.230
cmdexec.zonetransfer.me. 300 IN TXT "; ls"
contact.zonetransfer.me. 2592000 IN TXT "Remember to call or email Pippa on +44 123 4567890 or pippa@zonetransfer.me when making DNS changes"
dc-office.zonetransfer.me. 7200 IN A 143.228.181.132
deadbeef.zonetransfer.me. 7201 IN AAAA dead:beaf::
dr.zonetransfer.me. 300 IN LOC 53 20 56.558 N 1 38 33.526 W 0.00m 1m 10000m 10m
DZC.zonetransfer.me. 7200 IN TXT "AbCdEfG"
email.zonetransfer.me. 2222 IN NAPTR 1 1 "P" "E2U+email" "" email.zonetransfer.me.zonetransfer.me.
email.zonetransfer.me. 7200 IN A 74.125.206.26
Hello.zonetransfer.me. 7200 IN TXT "Hi to Josh and all his class"
home.zonetransfer.me. 7200 IN A 127.0.0.1
Info.zonetransfer.me. 7200 IN TXT "ZoneTransfer.me service provided by Robin Wood - robin@digi.ninja. See http://digi.ninja/projects/zonetransferme.php for more information."
internal.zonetransfer.me. 300 IN NS intns1.zonetransfer.me.
internal.zonetransfer.me. 300 IN NS intns2.zonetransfer.me.
intns1.zonetransfer.me. 300 IN A 81.4.108.41
intns2.zonetransfer.me. 300 IN A 167.88.42.94
office.zonetransfer.me. 7200 IN A 4.23.39.254
ipv6actnow.org.zonetransfer.me. 7200 IN AAAA 2001:67c:2e8:11::c100:1332
owa.zonetransfer.me. 7200 IN A 207.46.197.32
robinwood.zonetransfer.me. 302 IN TXT "Robin Wood"
rp.zonetransfer.me. 321 IN RP robin.zonetransfer.me. robinwood.zonetransfer.me.
sip.zonetransfer.me. 3333 IN NAPTR 2 3 "P" "E2U+sip" "!^.*$!sip:customer-service@zonetransfer.me!" .
sqli.zonetransfer.me. 300 IN TXT "' or 1=1 --"
sshock.zonetransfer.me. 7200 IN TXT "() { :]}; echo ShellShocked"
staging.zonetransfer.me. 7200 IN CNAME www.sydneyoperahouse.com.
alltcpportsopen.firewall.test.zonetransfer.me. 301 IN A 127.0.0.1
testing.zonetransfer.me. 301 IN CNAME www.zonetransfer.me.
vpn.zonetransfer.me. 4000 IN A 174.36.59.154
www.zonetransfer.me. 7200 IN A 5.196.105.14
xss.zonetransfer.me. 300 IN TXT "'><script>alert('Boo')</script>"
zonetransfer.me. 7200 IN SOA nsztm1.digi.ninja. robin.digi.ninja. 2019100801 172800 900 1209600 3600
;; Query time: 182 msec
;; SERVER: 81.4.108.41#53(81.4.108.41)
;; WHEN: Wed Mar 25 20:01:47 PDT 2020
;; XFR size: 50 records (messages 1, bytes 1994)

1
tests/fixtures/centos-7.7/file.json vendored Normal file
View File

@@ -0,0 +1 @@
[{"filename": "bin", "type": "directory"}, {"filename": "digout", "type": "ASCII text"}, {"filename": "file with spaces in the name", "type": "empty"}, {"filename": "git", "type": "directory"}, {"filename": "id-centos.out", "type": "ASCII text"}, {"filename": "ifcfg.json", "type": "ASCII text, with very long lines"}, {"filename": "ifconfig.out", "type": "ASCII text"}, {"filename": "iptables-tests", "type": "directory"}, {"filename": "journaljson", "type": "ASCII text, with very long lines"}, {"filename": "jp", "type": "ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped"}, {"filename": "jp_1.1.12_linux_x86_64.zip", "type": "Zip archive data, at least v2.0 to extract"}, {"filename": "lastb.out", "type": "ASCII text"}, {"filename": "lsblk-cols", "type": "UTF-8 Unicode text"}, {"filename": "psfile.txt", "type": "ASCII text, with very long lines"}, {"filename": "resizeterm.sh", "type": "Bourne-Again shell script, ASCII text executable"}, {"filename": "routeout", "type": "ASCII text"}, {"filename": "ss-aeep.out", "type": "ASCII text"}, {"filename": "ssout", "type": "ASCII text"}, {"filename": "systemctl.out", "type": "UTF-8 Unicode text"}, {"filename": "testfiles", "type": "directory"}, {"filename": "tmp", "type": "directory"}, {"filename": "top.out", "type": "ASCII text, with escape sequences"}, {"filename": "who-aH.out", "type": "ASCII text"}, {"filename": "who.out", "type": "ASCII text"}, {"filename": "whotext", "type": "ASCII text"}]

25
tests/fixtures/centos-7.7/file.out vendored Normal file
View File

@@ -0,0 +1,25 @@
bin: directory
digout: ASCII text
file with spaces in the name: empty
git: directory
id-centos.out: ASCII text
ifcfg.json: ASCII text, with very long lines
ifconfig.out: ASCII text
iptables-tests: directory
journaljson: ASCII text, with very long lines
jp: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
jp_1.1.12_linux_x86_64.zip: Zip archive data, at least v2.0 to extract
lastb.out: ASCII text
lsblk-cols: UTF-8 Unicode text
psfile.txt: ASCII text, with very long lines
resizeterm.sh: Bourne-Again shell script, ASCII text executable
routeout: ASCII text
ss-aeep.out: ASCII text
ssout: ASCII text
systemctl.out: UTF-8 Unicode text
testfiles: directory
tmp: directory
top.out: ASCII text, with escape sequences
who-aH.out: ASCII text
who.out: ASCII text
whotext: ASCII text

1
tests/fixtures/centos-7.7/ntpq-p.json vendored Normal file
View File

@@ -0,0 +1 @@
[{"state": null, "remote": "44.190.6.254", "refid": "127.67.113.92", "st": 2, "t": "u", "when": 1, "poll": 64, "reach": 1, "delay": 23.399, "offset": -2.805, "jitter": 2.131}, {"state": null, "remote": "ntp.wdc1.us.lea", "refid": "130.133.1.10", "st": 2, "t": "u", "when": null, "poll": 64, "reach": 1, "delay": 93.053, "offset": -0.807, "jitter": 2.839}, {"state": null, "remote": "clock.team-cymr", "refid": "204.9.54.119", "st": 2, "t": "u", "when": null, "poll": 64, "reach": 1, "delay": 70.337, "offset": -2.909, "jitter": 2.6}, {"state": null, "remote": "mirror1.sjc02.s", "refid": "216.218.254.202", "st": 2, "t": "u", "when": 2, "poll": 64, "reach": 1, "delay": 29.325, "offset": 1.044, "jitter": 4.069}]

6
tests/fixtures/centos-7.7/ntpq-p.out vendored Normal file
View File

@@ -0,0 +1,6 @@
remote refid st t when poll reach delay offset jitter
==============================================================================
44.190.6.254 127.67.113.92 2 u 1 64 1 23.399 -2.805 2.131
ntp.wdc1.us.lea 130.133.1.10 2 u - 64 1 93.053 -0.807 2.839
clock.team-cymr 204.9.54.119 2 u - 64 1 70.337 -2.909 2.600
mirror1.sjc02.s 216.218.254.202 2 u 2 64 1 29.325 1.044 4.069

View File

@@ -0,0 +1 @@
[{"state": "+", "remote": "44.190.6.254", "refid": "127.67.113.92", "st": 2, "t": "u", "when": 66, "poll": 64, "reach": 377, "delay": 22.69, "offset": -0.392, "jitter": 2.085}, {"state": "-", "remote": "108.59.2.24", "refid": "130.133.1.10", "st": 2, "t": "u", "when": 63, "poll": 64, "reach": 377, "delay": 90.805, "offset": 2.84, "jitter": 1.908}, {"state": "+", "remote": "38.229.71.1", "refid": "204.9.54.119", "st": 2, "t": "u", "when": 64, "poll": 64, "reach": 377, "delay": 68.699, "offset": -0.61, "jitter": 2.576}, {"state": "*", "remote": "72.5.72.15", "refid": "216.218.254.202", "st": 2, "t": "u", "when": 63, "poll": 64, "reach": 377, "delay": 22.654, "offset": 0.231, "jitter": 1.964}]

6
tests/fixtures/centos-7.7/ntpq-pn.out vendored Normal file
View File

@@ -0,0 +1,6 @@
remote refid st t when poll reach delay offset jitter
==============================================================================
+44.190.6.254 127.67.113.92 2 u 66 64 377 22.690 -0.392 2.085
-108.59.2.24 130.133.1.10 2 u 63 64 377 90.805 2.840 1.908
+38.229.71.1 204.9.54.119 2 u 64 64 377 68.699 -0.610 2.576
*72.5.72.15 216.218.254.202 2 u 63 64 377 22.654 0.231 1.964

View File

@@ -0,0 +1 @@
{"local_time": "Tue 2020-03-10 17:53:21 PDT", "universal_time": "Wed 2020-03-11 00:53:21 UTC", "rtc_time": "Wed 2020-03-11 00:53:21", "time_zone": "America/Los_Angeles (PDT, -0700)", "ntp_enabled": true, "ntp_synchronized": true, "rtc_in_local_tz": false, "dst_active": true}

View File

@@ -0,0 +1,14 @@
Local time: Tue 2020-03-10 17:53:21 PDT
Universal time: Wed 2020-03-11 00:53:21 UTC
RTC time: Wed 2020-03-11 00:53:21
Time zone: America/Los_Angeles (PDT, -0700)
NTP enabled: yes
NTP synchronized: yes
RTC in local TZ: no
DST active: yes
Last DST change: DST began at
Sun 2020-03-08 01:59:59 PST
Sun 2020-03-08 03:00:00 PDT
Next DST change: DST ends (the clock jumps one hour backwards) at
Sun 2020-11-01 01:59:59 PDT
Sun 2020-11-01 01:00:00 PST

View File

@@ -1,91 +0,0 @@
"Index", "Year", "Age", "Name", "Movie"
1, 1928, 44, "Emil Jannings", "The Last Command, The Way of All Flesh"
2, 1929, 41, "Warner Baxter", "In Old Arizona"
3, 1930, 62, "George Arliss", "Disraeli"
4, 1931, 53, "Lionel Barrymore", "A Free Soul"
5, 1932, 47, "Wallace Beery", "The Champ"
6, 1933, 35, "Fredric March", "Dr. Jekyll and Mr. Hyde"
7, 1934, 34, "Charles Laughton", "The Private Life of Henry VIII"
8, 1935, 34, "Clark Gable", "It Happened One Night"
9, 1936, 49, "Victor McLaglen", "The Informer"
10, 1937, 41, "Paul Muni", "The Story of Louis Pasteur"
11, 1938, 37, "Spencer Tracy", "Captains Courageous"
12, 1939, 38, "Spencer Tracy", "Boys Town"
13, 1940, 34, "Robert Donat", "Goodbye, Mr. Chips"
14, 1941, 32, "James Stewart", "The Philadelphia Story"
15, 1942, 40, "Gary Cooper", "Sergeant York"
16, 1943, 43, "James Cagney", "Yankee Doodle Dandy"
17, 1944, 48, "Paul Lukas", "Watch on the Rhine"
18, 1945, 41, "Bing Crosby", "Going My Way"
19, 1946, 39, "Ray Milland", "The Lost Weekend"
20, 1947, 49, "Fredric March", "The Best Years of Our Lives"
21, 1948, 57, "Ronald Colman", "A Double Life"
22, 1949, 41, "Laurence Olivier", "Hamlet"
23, 1950, 38, "Broderick Crawford", "All the King's Men"
24, 1951, 39, "José Ferrer", "Cyrano de Bergerac"
25, 1952, 52, "Humphrey Bogart", "The African Queen"
26, 1953, 51, "Gary Cooper", "High Noon"
27, 1954, 35, "William Holden", "Stalag 17"
28, 1955, 30, "Marlon Brando", "On the Waterfront"
29, 1956, 39, "Ernest Borgnine", "Marty"
30, 1957, 36, "Yul Brynner", "The King and I"
31, 1958, 43, "Alec Guinness", "The Bridge on the River Kwai"
32, 1959, 49, "David Niven", "Separate Tables"
33, 1960, 36, "Charlton Heston", "Ben-Hur"
34, 1961, 47, "Burt Lancaster", "Elmer Gantry"
35, 1962, 31, "Maximilian Schell", "Judgment at Nuremberg"
36, 1963, 47, "Gregory Peck", "To Kill a Mockingbird"
37, 1964, 37, "Sidney Poitier", "Lilies of the Field"
38, 1965, 57, "Rex Harrison", "My Fair Lady"
39, 1966, 42, "Lee Marvin", "Cat Ballou"
40, 1967, 45, "Paul Scofield", "A Man for All Seasons"
41, 1968, 42, "Rod Steiger", "In the Heat of the Night"
42, 1969, 45, "Cliff Robertson", "Charly"
43, 1970, 62, "John Wayne", "True Grit"
44, 1971, 43, "George C. Scott", "Patton"
45, 1972, 42, "Gene Hackman", "The French Connection"
46, 1973, 48, "Marlon Brando", "The Godfather"
47, 1974, 49, "Jack Lemmon", "Save the Tiger"
48, 1975, 56, "Art Carney", "Harry and Tonto"
49, 1976, 38, "Jack Nicholson", "One Flew Over the Cuckoo's Nest"
50, 1977, 60, "Peter Finch", "Network"
51, 1978, 30, "Richard Dreyfuss", "The Goodbye Girl"
52, 1979, 40, "Jon Voight", "Coming Home"
53, 1980, 42, "Dustin Hoffman", "Kramer vs. Kramer"
54, 1981, 37, "Robert De Niro", "Raging Bull"
55, 1982, 76, "Henry Fonda", "On Golden Pond"
56, 1983, 39, "Ben Kingsley", "Gandhi"
57, 1984, 53, "Robert Duvall", "Tender Mercies"
58, 1985, 45, "F. Murray Abraham", "Amadeus"
59, 1986, 36, "William Hurt", "Kiss of the Spider Woman"
60, 1987, 62, "Paul Newman", "The Color of Money"
61, 1988, 43, "Michael Douglas", "Wall Street"
62, 1989, 51, "Dustin Hoffman", "Rain Man"
63, 1990, 32, "Daniel Day-Lewis", "My Left Foot"
64, 1991, 42, "Jeremy Irons", "Reversal of Fortune"
65, 1992, 54, "Anthony Hopkins", "The Silence of the Lambs"
66, 1993, 52, "Al Pacino", "Scent of a Woman"
67, 1994, 37, "Tom Hanks", "Philadelphia"
68, 1995, 38, "Tom Hanks", "Forrest Gump"
69, 1996, 32, "Nicolas Cage", "Leaving Las Vegas"
70, 1997, 45, "Geoffrey Rush", "Shine"
71, 1998, 60, "Jack Nicholson", "As Good as It Gets"
72, 1999, 46, "Roberto Benigni", "Life Is Beautiful"
73, 2000, 40, "Kevin Spacey", "American Beauty"
74, 2001, 36, "Russell Crowe", "Gladiator"
75, 2002, 47, "Denzel Washington", "Training Day"
76, 2003, 29, "Adrien Brody", "The Pianist"
77, 2004, 43, "Sean Penn", "Mystic River"
78, 2005, 37, "Jamie Foxx", "Ray"
79, 2006, 38, "Philip Seymour Hoffman", "Capote"
80, 2007, 45, "Forest Whitaker", "The Last King of Scotland"
81, 2008, 50, "Daniel Day-Lewis", "There Will Be Blood"
82, 2009, 48, "Sean Penn", "Milk"
83, 2010, 60, "Jeff Bridges", "Crazy Heart"
84, 2011, 50, "Colin Firth", "The King's Speech"
85, 2012, 39, "Jean Dujardin", "The Artist"
86, 2013, 55, "Daniel Day-Lewis", "Lincoln"
87, 2014, 44, "Matthew McConaughey", "Dallas Buyers Club"
88, 2015, 33, "Eddie Redmayne", "The Theory of Everything"
89, 2016, 41, "Leonardo DiCaprio", "The Revenant"
Can't render this file because it contains an unexpected character in line 10 and column 47.

View File

@@ -0,0 +1 @@
{"agrctlrssi": -66, "agrextrssi": 0, "agrctlnoise": -90, "agrextnoise": 0, "state": "running", "op_mode": "station", "lasttxrate": 195, "maxrate": 867, "lastassocstatus": 0, "802_11_auth": "open", "link_auth": "wpa2-psk", "bssid": "3c:37:86:15:ad:f9", "ssid": "SnazzleDazzle", "mcs": 0, "channel": "48,80"}

View File

@@ -0,0 +1,15 @@
agrCtlRSSI: -66
agrExtRSSI: 0
agrCtlNoise: -90
agrExtNoise: 0
state: running
op mode: station
lastTxRate: 195
maxRate: 867
lastAssocStatus: 0
802.11 auth: open
link auth: wpa2-psk
BSSID: 3c:37:86:15:ad:f9
SSID: SnazzleDazzle
MCS: 0
channel: 48,80

View File

@@ -0,0 +1 @@
[{"ssid": "DIRECT-4A-HP OfficeJet 3830", "bssid": "00:68:eb:2b:b7:3b", "rssi": -91, "channel": "6", "ht": true, "cc": "--", "security": ["WPA2(PSK/AES/AES)"]}, {"ssid": "xfinitywifi", "bssid": "6e:e3:0e:c1:74:df", "rssi": -87, "channel": "36", "ht": true, "cc": "US", "security": ["NONE"]}, {"ssid": "XFINITY", "bssid": "8e:e3:0e:c1:74:df", "rssi": -86, "channel": "36", "ht": true, "cc": "US", "security": ["WPA2(802.1x/AES/AES)"]}, {"ssid": "YouAreInfected-5", "bssid": "5c:e3:0e:c1:74:df", "rssi": -86, "channel": "36", "ht": true, "cc": "US", "security": ["WPA(PSK/AES,TKIP/TKIP)", "WPA2(PSK/AES,TKIP/TKIP)"]}, {"ssid": "xfinitywifi", "bssid": "6e:e3:0e:b8:55:8f", "rssi": -85, "channel": "11", "ht": true, "cc": "US", "security": ["NONE"]}, {"ssid": "xfinitywifi", "bssid": "6e:e3:0e:c1:74:de", "rssi": -79, "channel": "6", "ht": true, "cc": "US", "security": ["NONE"]}, {"ssid": "ngHub_319451N814D6D", "bssid": "04:a1:51:56:5c:eb", "rssi": -77, "channel": "11", "ht": true, "cc": "US", "security": ["WPA2(PSK/AES/AES)"]}, {"ssid": "YouAreInfected", "bssid": "5c:e3:0e:c1:74:de", "rssi": -76, "channel": "6", "ht": true, "cc": "US", "security": ["WPA(PSK/AES,TKIP/TKIP)", "WPA2(PSK/AES,TKIP/TKIP)"]}, {"ssid": "YuanFamily_Extender2G", "bssid": "a0:04:60:86:11:89", "rssi": -76, "channel": "11", "ht": true, "cc": "--", "security": ["WPA(PSK/AES,TKIP/TKIP)", "WPA2(PSK/AES,TKIP/TKIP)"]}, {"ssid": "YuanFamily", "bssid": "5c:e3:0e:b8:15:9f", "rssi": -73, "channel": "11", "ht": true, "cc": "US", "security": ["WPA(PSK/AES,TKIP/TKIP)", "WPA2(PSK/AES,TKIP/TKIP)"]}, {"ssid": "SnazzleDazzle", "bssid": "3c:37:86:15:fd:b5", "rssi": -70, "channel": "48", "ht": true, "cc": "US", "security": ["WPA2(PSK/AES/AES)"]}, {"ssid": "SnazzleDazzle", "bssid": "42:37:86:15:fd:b3", "rssi": -62, "channel": "3,+1", "ht": true, "cc": "US", "security": ["WPA2(PSK/AES/AES)"]}, {"ssid": "SnazzleDazzle", "bssid": "42:37:86:15:aa:f7", "rssi": -54, "channel": "3", "ht": true, "cc": "US", "security": ["WPA2(PSK/AES/AES)"]}, {"ssid": "SnazzleDazzle", "bssid": "3c:37:86:15:aa:f9", "rssi": -64, "channel": "48", "ht": true, "cc": "US", "security": ["WPA2(PSK/AES/AES)"]}]

View File

@@ -0,0 +1,15 @@
SSID BSSID RSSI CHANNEL HT CC SECURITY (auth/unicast/group)
DIRECT-4A-HP OfficeJet 3830 00:68:eb:2b:b7:3b -91 6 Y -- WPA2(PSK/AES/AES)
xfinitywifi 6e:e3:0e:c1:74:df -87 36 Y US NONE
XFINITY 8e:e3:0e:c1:74:df -86 36 Y US WPA2(802.1x/AES/AES)
YouAreInfected-5 5c:e3:0e:c1:74:df -86 36 Y US WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)
xfinitywifi 6e:e3:0e:b8:55:8f -85 11 Y US NONE
xfinitywifi 6e:e3:0e:c1:74:de -79 6 Y US NONE
ngHub_319451N814D6D 04:a1:51:56:5c:eb -77 11 Y US WPA2(PSK/AES/AES)
YouAreInfected 5c:e3:0e:c1:74:de -76 6 Y US WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)
YuanFamily_Extender2G a0:04:60:86:11:89 -76 11 Y -- WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)
YuanFamily 5c:e3:0e:b8:15:9f -73 11 Y US WPA(PSK/AES,TKIP/TKIP) WPA2(PSK/AES,TKIP/TKIP)
SnazzleDazzle 3c:37:86:15:fd:b5 -70 48 Y US WPA2(PSK/AES/AES)
SnazzleDazzle 42:37:86:15:fd:b3 -62 3,+1 Y US WPA2(PSK/AES/AES)
SnazzleDazzle 42:37:86:15:aa:f7 -54 3 Y US WPA2(PSK/AES/AES)
SnazzleDazzle 3c:37:86:15:aa:f9 -64 48 Y US WPA2(PSK/AES/AES)

View File

@@ -0,0 +1 @@
[{"name": null, "address": "169.254.81.142", "hwtype": "ethernet", "hwaddress": "60:93:17:3a:28:fc", "iface": "en0"}, {"name": "my-iphone.attlocal.net", "address": "192.168.1.64", "hwtype": "ethernet", "hwaddress": "e0:33:8f:68:39:d6", "iface": "en0"}, {"name": "my-mbp.attlocal.net", "address": "192.168.1.72", "hwtype": "ethernet", "hwaddress": "f0:18:98:3:d7:34", "iface": "en0"}, {"name": "c6180.attlocal.net", "address": "192.168.1.74", "hwtype": "ethernet", "hwaddress": "9c:b6:54:5f:fa:7c", "iface": "en0"}, {"name": "ipad.attlocal.net", "address": "192.168.1.75", "hwtype": "ethernet", "hwaddress": "4c:56:9e:5f:c7:4c", "iface": "en0"}, {"name": "mycloudex2ultra.attlocal.net", "address": "192.168.1.80", "hwtype": "ethernet", "hwaddress": "0:90:a9:ed:f4:3f", "iface": "en0"}, {"name": "family-room-5.attlocal.net", "address": "192.168.1.88", "hwtype": "ethernet", "hwaddress": "c8:d0:84:c3:e3:2d", "iface": "en0"}, {"name": "bedroom.attlocal.net", "address": "192.168.1.89", "hwtype": "ethernet", "hwaddress": "d0:3:4b:3b:29:a5", "iface": "en0"}, {"name": "heriphone.attlocal.net", "address": "192.168.1.178", "hwtype": "ethernet", "hwaddress": "90:e1:7b:ef:1:45", "iface": "en0"}, {"name": "upstairs.attlocal.net", "address": "192.168.1.186", "hwtype": "ethernet", "hwaddress": "50:32:37:d7:e5:7b", "iface": "en0"}, {"name": "rbr50.attlocal.net", "address": "192.168.1.216", "hwtype": "ethernet", "hwaddress": "3c:37:86:25:fd:f7", "iface": "en0"}, {"name": "my-mac.attlocal.net", "address": "192.168.1.221", "hwtype": "ethernet", "hwaddress": "a4:83:e7:2e:f2:8f", "iface": "en0"}, {"name": "irobot-d41934.attlocal.net", "address": "192.168.1.242", "hwtype": "ethernet", "hwaddress": "50:14:79:f2:4f:3e", "iface": "en0"}, {"name": "rbs50.attlocal.net", "address": "192.168.1.253", "hwtype": "ethernet", "hwaddress": "3c:37:86:1f:dd:a3", "iface": "en0"}, {"name": "dsldevice.attlocal.net", "address": "192.168.1.254", "hwtype": "ethernet", "hwaddress": "fc:ae:34:f1:3f:80", "iface": "en0"}, {"name": null, "address": "192.168.1.255", "hwtype": "ethernet", "hwaddress": "ff:ff:ff:ff:ff:ff", "iface": "en0"}, {"name": null, "address": "192.168.71.255", "hwtype": "ethernet", "hwaddress": "ff:ff:ff:ff:ff:ff", "iface": "vmnet8"}, {"name": null, "address": "192.168.101.255", "hwtype": "ethernet", "hwaddress": "ff:ff:ff:ff:ff:ff", "iface": "vmnet1"}, {"name": null, "address": "224.0.0.251", "hwtype": "ethernet", "hwaddress": "1:0:5e:0:0:eb", "iface": "en0"}, {"name": null, "address": "239.255.255.250", "hwtype": "ethernet", "hwaddress": "1:0:5e:7f:ff:fe", "iface": "en0"}]

20
tests/fixtures/osx-10.14.6/arp-a2.out vendored Normal file
View File

@@ -0,0 +1,20 @@
? (169.254.81.142) at 60:93:17:3a:28:fc on en0 [ethernet]
my-iphone.attlocal.net (192.168.1.64) at e0:33:8f:68:39:d6 on en0 ifscope [ethernet]
my-mbp.attlocal.net (192.168.1.72) at f0:18:98:3:d7:34 on en0 ifscope [ethernet]
c6180.attlocal.net (192.168.1.74) at 9c:b6:54:5f:fa:7c on en0 ifscope [ethernet]
ipad.attlocal.net (192.168.1.75) at 4c:56:9e:5f:c7:4c on en0 ifscope [ethernet]
mycloudex2ultra.attlocal.net (192.168.1.80) at 0:90:a9:ed:f4:3f on en0 ifscope [ethernet]
family-room-5.attlocal.net (192.168.1.88) at c8:d0:84:c3:e3:2d on en0 ifscope [ethernet]
bedroom.attlocal.net (192.168.1.89) at d0:3:4b:3b:29:a5 on en0 ifscope [ethernet]
heriphone.attlocal.net (192.168.1.178) at 90:e1:7b:ef:1:45 on en0 ifscope [ethernet]
upstairs.attlocal.net (192.168.1.186) at 50:32:37:d7:e5:7b on en0 ifscope [ethernet]
rbr50.attlocal.net (192.168.1.216) at 3c:37:86:25:fd:f7 on en0 ifscope [ethernet]
my-mac.attlocal.net (192.168.1.221) at a4:83:e7:2e:f2:8f on en0 ifscope permanent [ethernet]
irobot-d41934.attlocal.net (192.168.1.242) at 50:14:79:f2:4f:3e on en0 ifscope [ethernet]
rbs50.attlocal.net (192.168.1.253) at 3c:37:86:1f:dd:a3 on en0 ifscope [ethernet]
dsldevice.attlocal.net (192.168.1.254) at fc:ae:34:f1:3f:80 on en0 ifscope [ethernet]
? (192.168.1.255) at ff:ff:ff:ff:ff:ff on en0 ifscope [ethernet]
? (192.168.71.255) at ff:ff:ff:ff:ff:ff on vmnet8 ifscope [ethernet]
? (192.168.101.255) at ff:ff:ff:ff:ff:ff on vmnet1 ifscope [ethernet]
? (224.0.0.251) at 1:0:5e:0:0:eb on en0 ifscope permanent [ethernet]
? (239.255.255.250) at 1:0:5e:7f:ff:fe on en0 ifscope permanent [ethernet]

File diff suppressed because one or more lines are too long

59
tests/fixtures/osx-10.14.6/dig-axfr.out vendored Normal file
View File

@@ -0,0 +1,59 @@
; <<>> DiG 9.10.6 <<>> @81.4.108.41 AXFR zonetransfer.me
; (1 server found)
;; global options: +cmd
zonetransfer.me. 7200 IN SOA nsztm1.digi.ninja. robin.digi.ninja. 2019100801 172800 900 1209600 3600
zonetransfer.me. 300 IN HINFO "Casio fx-700G" "Windows XP"
zonetransfer.me. 301 IN TXT "google-site-verification=tyP28J7JAUHA9fw2sHXMgcCC0I6XBmmoVi04VlMewxA"
zonetransfer.me. 7200 IN MX 0 ASPMX.L.GOOGLE.COM.
zonetransfer.me. 7200 IN MX 10 ALT1.ASPMX.L.GOOGLE.COM.
zonetransfer.me. 7200 IN MX 10 ALT2.ASPMX.L.GOOGLE.COM.
zonetransfer.me. 7200 IN MX 20 ASPMX2.GOOGLEMAIL.COM.
zonetransfer.me. 7200 IN MX 20 ASPMX3.GOOGLEMAIL.COM.
zonetransfer.me. 7200 IN MX 20 ASPMX4.GOOGLEMAIL.COM.
zonetransfer.me. 7200 IN MX 20 ASPMX5.GOOGLEMAIL.COM.
zonetransfer.me. 7200 IN A 5.196.105.14
zonetransfer.me. 7200 IN NS nsztm1.digi.ninja.
zonetransfer.me. 7200 IN NS nsztm2.digi.ninja.
_acme-challenge.zonetransfer.me. 301 IN TXT "6Oa05hbUJ9xSsvYy7pApQvwCUSSGgxvrbdizjePEsZI"
_sip._tcp.zonetransfer.me. 14000 IN SRV 0 0 5060 www.zonetransfer.me.
14.105.196.5.IN-ADDR.ARPA.zonetransfer.me. 7200 IN PTR www.zonetransfer.me.
asfdbauthdns.zonetransfer.me. 7900 IN AFSDB 1 asfdbbox.zonetransfer.me.
asfdbbox.zonetransfer.me. 7200 IN A 127.0.0.1
asfdbvolume.zonetransfer.me. 7800 IN AFSDB 1 asfdbbox.zonetransfer.me.
canberra-office.zonetransfer.me. 7200 IN A 202.14.81.230
cmdexec.zonetransfer.me. 300 IN TXT "; ls"
contact.zonetransfer.me. 2592000 IN TXT "Remember to call or email Pippa on +44 123 4567890 or pippa@zonetransfer.me when making DNS changes"
dc-office.zonetransfer.me. 7200 IN A 143.228.181.132
deadbeef.zonetransfer.me. 7201 IN AAAA dead:beaf::
dr.zonetransfer.me. 300 IN LOC 53 20 56.558 N 1 38 33.526 W 0.00m 1m 10000m 10m
DZC.zonetransfer.me. 7200 IN TXT "AbCdEfG"
email.zonetransfer.me. 2222 IN NAPTR 1 1 "P" "E2U+email" "" email.zonetransfer.me.zonetransfer.me.
email.zonetransfer.me. 7200 IN A 74.125.206.26
Hello.zonetransfer.me. 7200 IN TXT "Hi to Josh and all his class"
home.zonetransfer.me. 7200 IN A 127.0.0.1
Info.zonetransfer.me. 7200 IN TXT "ZoneTransfer.me service provided by Robin Wood - robin@digi.ninja. See http://digi.ninja/projects/zonetransferme.php for more information."
internal.zonetransfer.me. 300 IN NS intns1.zonetransfer.me.
internal.zonetransfer.me. 300 IN NS intns2.zonetransfer.me.
intns1.zonetransfer.me. 300 IN A 81.4.108.41
intns2.zonetransfer.me. 300 IN A 167.88.42.94
office.zonetransfer.me. 7200 IN A 4.23.39.254
ipv6actnow.org.zonetransfer.me. 7200 IN AAAA 2001:67c:2e8:11::c100:1332
owa.zonetransfer.me. 7200 IN A 207.46.197.32
robinwood.zonetransfer.me. 302 IN TXT "Robin Wood"
rp.zonetransfer.me. 321 IN RP robin.zonetransfer.me. robinwood.zonetransfer.me.
sip.zonetransfer.me. 3333 IN NAPTR 2 3 "P" "E2U+sip" "!^.*$!sip:customer-service@zonetransfer.me!" .
sqli.zonetransfer.me. 300 IN TXT "' or 1=1 --"
sshock.zonetransfer.me. 7200 IN TXT "() { :]}; echo ShellShocked"
staging.zonetransfer.me. 7200 IN CNAME www.sydneyoperahouse.com.
alltcpportsopen.firewall.test.zonetransfer.me. 301 IN A 127.0.0.1
testing.zonetransfer.me. 301 IN CNAME www.zonetransfer.me.
vpn.zonetransfer.me. 4000 IN A 174.36.59.154
www.zonetransfer.me. 7200 IN A 5.196.105.14
xss.zonetransfer.me. 300 IN TXT "'><script>alert('Boo')</script>"
zonetransfer.me. 7200 IN SOA nsztm1.digi.ninja. robin.digi.ninja. 2019100801 172800 900 1209600 3600
;; Query time: 170 msec
;; SERVER: 81.4.108.41#53(81.4.108.41)
;; WHEN: Thu Mar 26 16:31:06 PDT 2020
;; XFR size: 50 records (messages 1, bytes 1994)

1
tests/fixtures/osx-10.14.6/file.json vendored Normal file
View File

@@ -0,0 +1 @@
[{"filename": "Applications", "type": "directory"}, {"filename": "Desktop", "type": "directory"}, {"filename": "Documents", "type": "directory"}, {"filename": "Downloads", "type": "directory"}, {"filename": "Library", "type": "directory"}, {"filename": "Movies", "type": "directory"}, {"filename": "Music", "type": "directory"}, {"filename": "Pictures", "type": "directory"}, {"filename": "Postman", "type": "directory"}, {"filename": "Public", "type": "directory"}, {"filename": "Virtual Machines.localized", "type": "directory"}, {"filename": "another file with spaces", "type": "empty"}, {"filename": "ansible", "type": "directory"}, {"filename": "api", "type": "directory"}, {"filename": "argstest.py", "type": "Python script text executable, ASCII text"}, {"filename": "blkid-p.out", "type": "ASCII text"}, {"filename": "blkid-pi.out", "type": "ASCII text, with very long lines"}, {"filename": "blkid-ubuntu.out", "type": "ASCII text"}, {"filename": "blkid-udev-mult.out", "type": "ASCII text"}, {"filename": "blkid-udev.out", "type": "ASCII text"}, {"filename": "blkid.out", "type": "ASCII text"}, {"filename": "cd_catalog.xml", "type": "XML 1.0 document text, ASCII text, with CRLF line terminators"}, {"filename": "centosserial.sh", "type": "Bourne-Again shell script text executable, UTF-8 Unicode text"}, {"filename": "coreosserial.sh", "type": "Bourne-Again shell script text executable, UTF-8 Unicode text"}, {"filename": "fazserial.sh", "type": "Bourne-Again shell script text executable, UTF-8 Unicode text"}, {"filename": "fgt1serial.sh", "type": "Bourne-Again shell script text executable, UTF-8 Unicode text"}, {"filename": "fgt2serial.sh", "type": "Bourne-Again shell script text executable, UTF-8 Unicode text"}, {"filename": "file with spaces", "type": "empty"}, {"filename": "fortiweb-docker.sh", "type": "Bourne-Again shell script text executable, ASCII text"}, {"filename": "ftmgr.sh", "type": "Bourne-Again shell script text executable, ASCII text"}, {"filename": "git", "type": "directory"}, {"filename": "google-cloud-sdk", "type": "directory"}, {"filename": "ifconfiglines.json", "type": "ASCII text, with very long lines"}, {"filename": "jc-jq-jp-ps-cpu.gif", "type": "GIF image data, version 89a, 1572 x 1212"}, {"filename": "jc-jq-jp-uptime-small.gif", "type": "GIF image data, version 89a, 800 x 617"}, {"filename": "jc-jq-jp-uptime.gif", "type": "GIF image data, version 89a, 1572 x 1212"}, {"filename": "jp", "type": "Mach-O 64-bit executable x86_64"}, {"filename": "jp_1.1.12_osx_x86_64.zip", "type": "Zip archive data, at least v2.0 to extract"}, {"filename": "jupyter.sh", "type": "ASCII text"}, {"filename": "kb.sh", "type": "Bourne-Again shell script text executable, ASCII text"}, {"filename": "kbtesting.txt", "type": "ASCII text"}, {"filename": "kelly-aws.pem", "type": "PEM RSA private key"}, {"filename": "kellyargtest.py", "type": "Python script text executable, ASCII text"}, {"filename": "loadplot.sh", "type": "Bourne-Again shell script text executable, ASCII text"}, {"filename": "ls-R.out", "type": "UTF-8 Unicode text"}, {"filename": "ls-lR-empty-folder.out", "type": "ASCII text"}, {"filename": "ls-lR.out", "type": "UTF-8 Unicode text"}, {"filename": "myrecording", "type": "data"}, {"filename": "smcclient.jnlp", "type": "XML 1.0 document text, ASCII text"}, {"filename": "table.py", "type": "Python script text executable, ASCII text"}, {"filename": "test.ini", "type": "ASCII text"}, {"filename": "ubuntuserial.sh", "type": "Bourne-Again shell script text executable, UTF-8 Unicode text"}, {"filename": "utils", "type": "directory"}]

53
tests/fixtures/osx-10.14.6/file.out vendored Normal file
View File

@@ -0,0 +1,53 @@
Applications: directory
Desktop: directory
Documents: directory
Downloads: directory
Library: directory
Movies: directory
Music: directory
Pictures: directory
Postman: directory
Public: directory
Virtual Machines.localized: directory
another file with spaces: empty
ansible: directory
api: directory
argstest.py: Python script text executable, ASCII text
blkid-p.out: ASCII text
blkid-pi.out: ASCII text, with very long lines
blkid-ubuntu.out: ASCII text
blkid-udev-mult.out: ASCII text
blkid-udev.out: ASCII text
blkid.out: ASCII text
cd_catalog.xml: XML 1.0 document text, ASCII text, with CRLF line terminators
centosserial.sh: Bourne-Again shell script text executable, UTF-8 Unicode text
coreosserial.sh: Bourne-Again shell script text executable, UTF-8 Unicode text
fazserial.sh: Bourne-Again shell script text executable, UTF-8 Unicode text
fgt1serial.sh: Bourne-Again shell script text executable, UTF-8 Unicode text
fgt2serial.sh: Bourne-Again shell script text executable, UTF-8 Unicode text
file with spaces: empty
fortiweb-docker.sh: Bourne-Again shell script text executable, ASCII text
ftmgr.sh: Bourne-Again shell script text executable, ASCII text
git: directory
google-cloud-sdk: directory
ifconfiglines.json: ASCII text, with very long lines
jc-jq-jp-ps-cpu.gif: GIF image data, version 89a, 1572 x 1212
jc-jq-jp-uptime-small.gif: GIF image data, version 89a, 800 x 617
jc-jq-jp-uptime.gif: GIF image data, version 89a, 1572 x 1212
jp: Mach-O 64-bit executable x86_64
jp_1.1.12_osx_x86_64.zip: Zip archive data, at least v2.0 to extract
jupyter.sh: ASCII text
kb.sh: Bourne-Again shell script text executable, ASCII text
kbtesting.txt: ASCII text
kelly-aws.pem: PEM RSA private key
kellyargtest.py: Python script text executable, ASCII text
loadplot.sh: Bourne-Again shell script text executable, ASCII text
ls-R.out: UTF-8 Unicode text
ls-lR-empty-folder.out: ASCII text
ls-lR.out: UTF-8 Unicode text
myrecording: data
smcclient.jnlp: XML 1.0 document text, ASCII text
table.py: Python script text executable, ASCII text
test.ini: ASCII text
ubuntuserial.sh: Bourne-Again shell script text executable, UTF-8 Unicode text
utils: directory

1
tests/fixtures/osx-10.14.6/file2.json vendored Normal file
View File

@@ -0,0 +1 @@
[{"filename": "AFP.conf", "type": "data"}, {"filename": "afpovertcp.cfg", "type": "ASCII text"}, {"filename": "aliases", "type": "ASCII text"}, {"filename": "aliases.db", "type": "Berkeley DB 1.85 (Hash, version 2, native byte-order)"}, {"filename": "apache2", "type": "directory"}, {"filename": "asl", "type": "directory"}, {"filename": "asl.conf", "type": "ASCII text"}, {"filename": "auto_home", "type": "ASCII text"}, {"filename": "auto_master", "type": "ASCII text"}, {"filename": "autofs.conf", "type": "ASCII text"}, {"filename": "bashrc", "type": "ASCII text"}, {"filename": "bashrc_Apple_Terminal", "type": "ASCII text"}, {"filename": "com.apple.screensharing.agent.launchd", "type": "ASCII text, with no line terminators"}, {"filename": "csh.cshrc", "type": "ASCII text"}, {"filename": "csh.login", "type": "ASCII text"}, {"filename": "csh.logout", "type": "ASCII text"}, {"filename": "cups", "type": "directory"}, {"filename": "defaults", "type": "directory"}, {"filename": "dnsextd.conf", "type": "ASCII text"}, {"filename": "emond.d", "type": "directory"}, {"filename": "find.codes", "type": "empty"}, {"filename": "fstab.hd", "type": "ASCII text"}, {"filename": "ftpusers", "type": "ASCII text"}, {"filename": "gettytab", "type": "ASCII text"}, {"filename": "group", "type": "ASCII text"}, {"filename": "hosts", "type": "ASCII text"}, {"filename": "hosts.equiv", "type": "empty"}, {"filename": "irbrc", "type": "Ruby script text, ASCII text"}, {"filename": "kern_loader.conf", "type": "empty"}, {"filename": "krb5.keytab", "type": "Kerberos Keytab file, realm=LKDC:SHA1.15090DD365668FBA1B0D2D3DD43FCB7CB9381160, principal=afpserver/LKDC:SHA1.15090DD365668FBA1B0D2D3DD43FCB7CB9381160, type=1, date=Tue Jul 2 15:52:04 2019, kvno=2"}, {"filename": "localtime", "type": "timezone data, version 2, 4 gmt time flags, 4 std time flags, no leap seconds, 185 transition times, 4 abbreviation chars"}, {"filename": "locate.rc", "type": "ASCII text"}, {"filename": "mach_init.d", "type": "directory"}, {"filename": "mach_init_per_login_session.d", "type": "directory"}, {"filename": "mach_init_per_user.d", "type": "directory"}, {"filename": "mail.rc", "type": "ASCII text"}, {"filename": "man.conf", "type": "ASCII text"}, {"filename": "manpaths", "type": "ASCII text"}, {"filename": "manpaths.d", "type": "directory"}, {"filename": "master.passwd", "type": "ASCII text"}, {"filename": "nanorc", "type": "ASCII text"}, {"filename": "networks", "type": "ASCII text"}, {"filename": "newsyslog.conf", "type": "ASCII text"}, {"filename": "newsyslog.d", "type": "directory"}, {"filename": "nfs.conf", "type": "ASCII text"}, {"filename": "notify.conf", "type": "ASCII text"}, {"filename": "ntp.conf", "type": "ASCII text"}, {"filename": "ntp_opendirectory.conf", "type": "ASCII text"}, {"filename": "openldap", "type": "directory"}, {"filename": "pam.d", "type": "directory"}, {"filename": "passwd", "type": "ASCII text"}, {"filename": "paths", "type": "ASCII text"}, {"filename": "paths.d", "type": "directory"}, {"filename": "periodic", "type": "directory"}, {"filename": "pf.anchors", "type": "directory"}, {"filename": "pf.conf", "type": "ASCII text"}, {"filename": "pf.os", "type": "ASCII text"}, {"filename": "php-fpm.conf.default", "type": "ASCII text"}, {"filename": "php-fpm.d", "type": "directory"}, {"filename": "php.ini.default", "type": "ASCII text"}, {"filename": "postfix", "type": "directory"}, {"filename": "ppp", "type": "directory"}, {"filename": "profile", "type": "ASCII text"}, {"filename": "protocols", "type": "ASCII text"}, {"filename": "racoon", "type": "directory"}, {"filename": "rc.common", "type": "ASCII text"}, {"filename": "rc.netboot", "type": "POSIX shell script text executable, ASCII text"}, {"filename": "resolv.conf", "type": "ASCII text"}, {"filename": "rmtab", "type": "empty"}, {"filename": "rpc", "type": "ASCII text"}, {"filename": "rtadvd.conf", "type": "ASCII text"}, {"filename": "security", "type": "directory"}, {"filename": "services", "type": "ASCII text"}, {"filename": "services.broker", "type": "ASCII text"}, {"filename": "shells", "type": "ASCII text"}, {"filename": "snmp", "type": "directory"}, {"filename": "ssh", "type": "directory"}, {"filename": "ssl", "type": "directory"}, {"filename": "sudo_lecture", "type": "ASCII text"}, {"filename": "sudoers", "type": "c program text, ASCII text"}, {"filename": "sudoers.d", "type": "directory"}, {"filename": "syslog.conf", "type": "ASCII text"}, {"filename": "thnuclnt", "type": "directory"}, {"filename": "ttys", "type": "ASCII text"}, {"filename": "wfs", "type": "directory"}, {"filename": "xtab", "type": "empty"}, {"filename": "zprofile", "type": "ASCII text"}, {"filename": "zshrc", "type": "ASCII text"}]

88
tests/fixtures/osx-10.14.6/file2.out vendored Normal file
View File

@@ -0,0 +1,88 @@
AFP.conf: data
afpovertcp.cfg: ASCII text
aliases: ASCII text
aliases.db: Berkeley DB 1.85 (Hash, version 2, native byte-order)
apache2: directory
asl: directory
asl.conf: ASCII text
auto_home: ASCII text
auto_master: ASCII text
autofs.conf: ASCII text
bashrc: ASCII text
bashrc_Apple_Terminal: ASCII text
com.apple.screensharing.agent.launchd: ASCII text, with no line terminators
csh.cshrc: ASCII text
csh.login: ASCII text
csh.logout: ASCII text
cups: directory
defaults: directory
dnsextd.conf: ASCII text
emond.d: directory
find.codes: empty
fstab.hd: ASCII text
ftpusers: ASCII text
gettytab: ASCII text
group: ASCII text
hosts: ASCII text
hosts.equiv: empty
irbrc: Ruby script text, ASCII text
kern_loader.conf: empty
krb5.keytab: Kerberos Keytab file, realm=LKDC:SHA1.15090DD365668FBA1B0D2D3DD43FCB7CB9381160, principal=afpserver/LKDC:SHA1.15090DD365668FBA1B0D2D3DD43FCB7CB9381160, type=1, date=Tue Jul 2 15:52:04 2019, kvno=2
localtime: timezone data, version 2, 4 gmt time flags, 4 std time flags, no leap seconds, 185 transition times, 4 abbreviation chars
locate.rc: ASCII text
mach_init.d: directory
mach_init_per_login_session.d: directory
mach_init_per_user.d: directory
mail.rc: ASCII text
man.conf: ASCII text
manpaths: ASCII text
manpaths.d: directory
master.passwd: ASCII text
nanorc: ASCII text
networks: ASCII text
newsyslog.conf: ASCII text
newsyslog.d: directory
nfs.conf: ASCII text
notify.conf: ASCII text
ntp.conf: ASCII text
ntp_opendirectory.conf: ASCII text
openldap: directory
pam.d: directory
passwd: ASCII text
paths: ASCII text
paths.d: directory
periodic: directory
pf.anchors: directory
pf.conf: ASCII text
pf.os: ASCII text
php-fpm.conf.default: ASCII text
php-fpm.d: directory
php.ini.default: ASCII text
postfix: directory
ppp: directory
profile: ASCII text
protocols: ASCII text
racoon: directory
rc.common: ASCII text
rc.netboot: POSIX shell script text executable, ASCII text
resolv.conf: ASCII text
rmtab: empty
rpc: ASCII text
rtadvd.conf: ASCII text
security: directory
services: ASCII text
services.broker: ASCII text
shells: ASCII text
snmp: directory
ssh: directory
ssl: directory
sudo_lecture: ASCII text
sudoers: c program text, ASCII text
sudoers.d: directory
syslog.conf: ASCII text
thnuclnt: directory
ttys: ASCII text
wfs: directory
xtab: empty
zprofile: ASCII text
zshrc: ASCII text

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,57 @@
; <<>> DiG 9.11.14-3-Debian <<>> @81.4.108.41 axfr zonetransfer.me +nocookie
; (1 server found)
;; global options: +cmd
zonetransfer.me. 7200 IN SOA nsztm1.digi.ninja. robin.digi.ninja. 2019100801 172800 900 1209600 3600
zonetransfer.me. 300 IN HINFO "Casio fx-700G" "Windows XP"
zonetransfer.me. 301 IN TXT "google-site-verification=tyP28J7JAUHA9fw2sHXMgcCC0I6XBmmoVi04VlMewxA"
zonetransfer.me. 7200 IN MX 0 ASPMX.L.GOOGLE.COM.
zonetransfer.me. 7200 IN MX 10 ALT1.ASPMX.L.GOOGLE.COM.
zonetransfer.me. 7200 IN MX 10 ALT2.ASPMX.L.GOOGLE.COM.
zonetransfer.me. 7200 IN MX 20 ASPMX2.GOOGLEMAIL.COM.
zonetransfer.me. 7200 IN MX 20 ASPMX3.GOOGLEMAIL.COM.
zonetransfer.me. 7200 IN MX 20 ASPMX4.GOOGLEMAIL.COM.
zonetransfer.me. 7200 IN MX 20 ASPMX5.GOOGLEMAIL.COM.
zonetransfer.me. 7200 IN A 5.196.105.14
zonetransfer.me. 7200 IN NS nsztm1.digi.ninja.
zonetransfer.me. 7200 IN NS nsztm2.digi.ninja.
_acme-challenge.zonetransfer.me. 301 IN TXT "6Oa05hbUJ9xSsvYy7pApQvwCUSSGgxvrbdizjePEsZI"
_sip._tcp.zonetransfer.me. 14000 IN SRV 0 0 5060 www.zonetransfer.me.
14.105.196.5.IN-ADDR.ARPA.zonetransfer.me. 7200 IN PTR www.zonetransfer.me.
asfdbauthdns.zonetransfer.me. 7900 IN AFSDB 1 asfdbbox.zonetransfer.me.
asfdbbox.zonetransfer.me. 7200 IN A 127.0.0.1
asfdbvolume.zonetransfer.me. 7800 IN AFSDB 1 asfdbbox.zonetransfer.me.
canberra-office.zonetransfer.me. 7200 IN A 202.14.81.230
cmdexec.zonetransfer.me. 300 IN TXT "; ls"
contact.zonetransfer.me. 2592000 IN TXT "Remember to call or email Pippa on +44 123 4567890 or pippa@zonetransfer.me when making DNS changes"
dc-office.zonetransfer.me. 7200 IN A 143.228.181.132
deadbeef.zonetransfer.me. 7201 IN AAAA dead:beaf::
dr.zonetransfer.me. 300 IN LOC 53 20 56.558 N 1 38 33.526 W 0.00m 1m 10000m 10m
DZC.zonetransfer.me. 7200 IN TXT "AbCdEfG"
email.zonetransfer.me. 2222 IN NAPTR 1 1 "P" "E2U+email" "" email.zonetransfer.me.zonetransfer.me.
email.zonetransfer.me. 7200 IN A 74.125.206.26
Hello.zonetransfer.me. 7200 IN TXT "Hi to Josh and all his class"
home.zonetransfer.me. 7200 IN A 127.0.0.1
Info.zonetransfer.me. 7200 IN TXT "ZoneTransfer.me service provided by Robin Wood - robin@digi.ninja. See http://digi.ninja/projects/zonetransferme.php for more information."
internal.zonetransfer.me. 300 IN NS intns1.zonetransfer.me.
internal.zonetransfer.me. 300 IN NS intns2.zonetransfer.me.
intns1.zonetransfer.me. 300 IN A 81.4.108.41
intns2.zonetransfer.me. 300 IN A 167.88.42.94
office.zonetransfer.me. 7200 IN A 4.23.39.254
ipv6actnow.org.zonetransfer.me. 7200 IN AAAA 2001:67c:2e8:11::c100:1332
owa.zonetransfer.me. 7200 IN A 207.46.197.32
robinwood.zonetransfer.me. 302 IN TXT "Robin Wood"
rp.zonetransfer.me. 321 IN RP robin.zonetransfer.me. robinwood.zonetransfer.me.
sip.zonetransfer.me. 3333 IN NAPTR 2 3 "P" "E2U+sip" "!^.*$!sip:customer-service@zonetransfer.me!" .
sqli.zonetransfer.me. 300 IN TXT "' or 1=1 --"
sshock.zonetransfer.me. 7200 IN TXT "() { :]}; echo ShellShocked"
staging.zonetransfer.me. 7200 IN CNAME www.sydneyoperahouse.com.
alltcpportsopen.firewall.test.zonetransfer.me. 301 IN A 127.0.0.1
testing.zonetransfer.me. 301 IN CNAME www.zonetransfer.me.
vpn.zonetransfer.me. 4000 IN A 174.36.59.154
www.zonetransfer.me. 7200 IN A 5.196.105.14
xss.zonetransfer.me. 300 IN TXT "'><script>alert('Boo')</script>"
zonetransfer.me. 7200 IN SOA nsztm1.digi.ninja. robin.digi.ninja. 2019100801 172800 900 1209600 3600
;; Query time: 105 msec
;; SERVER: 81.4.108.41#53(81.4.108.41)
;; WHEN: Wed Mar 25 14:34:55 EDT 2020
;; XFR size: 50 records (messages 1, bytes 1994)

1
tests/fixtures/ubuntu-18.04/file.json vendored Normal file
View File

@@ -0,0 +1 @@
[{"filename": "crayaml.yaml", "type": "ASCII text"}, {"filename": "git", "type": "directory"}, {"filename": "ifconfig-ubuntu.out", "type": "ASCII text"}, {"filename": "iptables-tests", "type": "directory"}, {"filename": "lastb.out", "type": "ASCII text"}, {"filename": "listjobs", "type": "ASCII text"}, {"filename": "ls-lR.out", "type": "ASCII text"}, {"filename": "ls-R.out", "type": "ASCII text"}, {"filename": "netstat-ae.out", "type": "ASCII text"}, {"filename": "netstat-aew.out", "type": "ASCII text"}, {"filename": "netstat-a.out", "type": "ASCII text"}, {"filename": "netstat-aw.out", "type": "ASCII text"}, {"filename": "resizeterm.sh", "type": "Bourne-Again shell script, ASCII text executable"}, {"filename": "snap", "type": "directory"}, {"filename": "ssout", "type": "ASCII text"}, {"filename": "sudofix", "type": "ASCII text"}, {"filename": "testfiles", "type": "directory"}, {"filename": "tmp", "type": "directory"}, {"filename": "trafficgen.sh", "type": "Bourne-Again shell script, ASCII text executable"}, {"filename": "xmltest.xml", "type": "XML 1.0 document, ASCII text"}]

20
tests/fixtures/ubuntu-18.04/file.out vendored Normal file
View File

@@ -0,0 +1,20 @@
crayaml.yaml: ASCII text
git: directory
ifconfig-ubuntu.out: ASCII text
iptables-tests: directory
lastb.out: ASCII text
listjobs: ASCII text
ls-lR.out: ASCII text
ls-R.out: ASCII text
netstat-ae.out: ASCII text
netstat-aew.out: ASCII text
netstat-a.out: ASCII text
netstat-aw.out: ASCII text
resizeterm.sh: Bourne-Again shell script, ASCII text executable
snap: directory
ssout: ASCII text
sudofix: ASCII text
testfiles: directory
tmp: directory
trafficgen.sh: Bourne-Again shell script, ASCII text executable
xmltest.xml: XML 1.0 document, ASCII text

View File

@@ -0,0 +1 @@
[{"state": null, "remote": "0.ubuntu.pool.n", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0}, {"state": null, "remote": "1.ubuntu.pool.n", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0}, {"state": null, "remote": "2.ubuntu.pool.n", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0}, {"state": null, "remote": "3.ubuntu.pool.n", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0}, {"state": null, "remote": "ntp.ubuntu.com", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0}, {"state": "+", "remote": "216.126.233.109", "refid": "128.227.205.3", "st": 2, "t": "u", "when": 24, "poll": 64, "reach": 1, "delay": 95.876, "offset": -65.426, "jitter": 4.502}, {"state": "+", "remote": "time.cloudflare", "refid": "10.4.0.197", "st": 3, "t": "u", "when": 33, "poll": 64, "reach": 1, "delay": 25.239, "offset": -69.809, "jitter": 3.313}, {"state": "+", "remote": "titan.crash-ove", "refid": "139.78.97.128", "st": 2, "t": "u", "when": 35, "poll": 64, "reach": 1, "delay": 60.008, "offset": -70.991, "jitter": 2.884}, {"state": "*", "remote": "clock.nyc.he.ne", "refid": ".CDMA.", "st": 1, "t": "u", "when": 31, "poll": 64, "reach": 1, "delay": 90.113, "offset": -65.938, "jitter": 4.621}, {"state": "-", "remote": "vf2.bbnx.net", "refid": "252.74.143.178", "st": 2, "t": "u", "when": 34, "poll": 64, "reach": 1, "delay": 209.667, "offset": -81.337, "jitter": 5.547}, {"state": "+", "remote": "t2.time.bf1.yah", "refid": "98.139.133.62", "st": 3, "t": "u", "when": 35, "poll": 64, "reach": 1, "delay": 104.541, "offset": -67.956, "jitter": 5.731}, {"state": null, "remote": "pugot.canonical", "refid": "17.253.34.125", "st": 2, "t": "u", "when": 43, "poll": 64, "reach": 1, "delay": 176.609, "offset": -65.874, "jitter": 0.0}, {"state": "-", "remote": "50-205-244-110-", "refid": "50.205.244.27", "st": 2, "t": "u", "when": 30, "poll": 64, "reach": 1, "delay": 76.322, "offset": -65.135, "jitter": 2.334}, {"state": "+", "remote": "1.time.dbsinet.", "refid": "146.186.222.14", "st": 2, "t": "u", "when": 31, "poll": 64, "reach": 1, "delay": 110.723, "offset": -65.056, "jitter": 6.198}, {"state": null, "remote": "golem.canonical", "refid": "17.253.34.123", "st": 2, "t": "u", "when": 40, "poll": 64, "reach": 1, "delay": 186.589, "offset": -61.769, "jitter": 0.0}, {"state": "-", "remote": "103.105.51.156", "refid": "206.55.191.142", "st": 2, "t": "u", "when": 30, "poll": 64, "reach": 1, "delay": 38.164, "offset": -65.286, "jitter": 6.412}, {"state": null, "remote": "alphyn.canonica", "refid": "17.253.108.125", "st": 2, "t": "u", "when": 44, "poll": 64, "reach": 1, "delay": 105.626, "offset": -63.73, "jitter": 0.0}, {"state": "-", "remote": "vf1.bbnx.net", "refid": "253.109.221.150", "st": 2, "t": "u", "when": 31, "poll": 64, "reach": 1, "delay": 101.941, "offset": -73.597, "jitter": 3.39}, {"state": null, "remote": "chilipepper.can", "refid": "145.238.203.14", "st": 2, "t": "u", "when": 40, "poll": 64, "reach": 1, "delay": 188.989, "offset": -59.352, "jitter": 0.0}]

21
tests/fixtures/ubuntu-18.04/ntpq-p.out vendored Normal file
View File

@@ -0,0 +1,21 @@
remote refid st t when poll reach delay offset jitter
==============================================================================
0.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
1.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
2.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
3.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
ntp.ubuntu.com .POOL. 16 p - 64 0 0.000 0.000 0.000
+216.126.233.109 128.227.205.3 2 u 24 64 1 95.876 -65.426 4.502
+time.cloudflare 10.4.0.197 3 u 33 64 1 25.239 -69.809 3.313
+titan.crash-ove 139.78.97.128 2 u 35 64 1 60.008 -70.991 2.884
*clock.nyc.he.ne .CDMA. 1 u 31 64 1 90.113 -65.938 4.621
-vf2.bbnx.net 252.74.143.178 2 u 34 64 1 209.667 -81.337 5.547
+t2.time.bf1.yah 98.139.133.62 3 u 35 64 1 104.541 -67.956 5.731
pugot.canonical 17.253.34.125 2 u 43 64 1 176.609 -65.874 0.000
-50-205-244-110- 50.205.244.27 2 u 30 64 1 76.322 -65.135 2.334
+1.time.dbsinet. 146.186.222.14 2 u 31 64 1 110.723 -65.056 6.198
golem.canonical 17.253.34.123 2 u 40 64 1 186.589 -61.769 0.000
-103.105.51.156 206.55.191.142 2 u 30 64 1 38.164 -65.286 6.412
alphyn.canonica 17.253.108.125 2 u 44 64 1 105.626 -63.730 0.000
-vf1.bbnx.net 253.109.221.150 2 u 31 64 1 101.941 -73.597 3.390
chilipepper.can 145.238.203.14 2 u 40 64 1 188.989 -59.352 0.000

View File

@@ -0,0 +1 @@
[{"remote": "0.ubuntu.pool.n", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0, "state": null}, {"remote": "1.ubuntu.pool.n", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0, "state": null}, {"remote": "2.ubuntu.pool.n", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0, "state": null}, {"remote": "3.ubuntu.pool.n", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0, "state": null}, {"remote": "ntp.ubuntu.com", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0, "state": null}, {"remote": "45.79.36.123_(t", "refid": "216.218.254.202", "st": 2, "t": "u", "when": 11, "poll": 64, "reach": 7, "delay": 68.172, "offset": 4.404, "jitter": 4.878, "state": "+"}, {"remote": "199.188.64.12_(", "refid": "173.161.33.165", "st": 2, "t": "u", "when": 9, "poll": 64, "reach": 7, "delay": 78.823, "offset": 2.148, "jitter": 8.739, "state": "+"}, {"remote": "ntp2.wiktel.com", "refid": ".GPS.", "st": 1, "t": "u", "when": 25, "poll": 64, "reach": 7, "delay": 76.857, "offset": 0.473, "jitter": 7.89, "state": "*"}, {"remote": "atl0.jane.mattn", "refid": "35.73.197.144", "st": 2, "t": "u", "when": 32, "poll": 64, "reach": 7, "delay": 87.536, "offset": 8.641, "jitter": 4.544, "state": "#"}, {"remote": "x.ns.gin.ntt.ne", "refid": "249.224.99.213", "st": 2, "t": "u", "when": 28, "poll": 64, "reach": 7, "delay": 25.021, "offset": 3.361, "jitter": 7.793, "state": "+"}, {"remote": "srcf-ntp.stanfo", "refid": "171.64.7.105", "st": 2, "t": "u", "when": 26, "poll": 64, "reach": 7, "delay": 28.053, "offset": 7.253, "jitter": 4.524, "state": "-"}, {"remote": "linode.ibendit.", "refid": "64.250.105.227", "st": 2, "t": "u", "when": 28, "poll": 64, "reach": 7, "delay": 56.841, "offset": -0.305, "jitter": 8.279, "state": "#"}, {"remote": "71.66.197.233", "refid": ".GPS.", "st": 1, "t": "u", "when": 26, "poll": 64, "reach": 7, "delay": 127.766, "offset": -0.769, "jitter": 3.465, "state": "+"}, {"remote": "time.aja.com", "refid": "198.169.208.144", "st": 2, "t": "u", "when": 32, "poll": 64, "reach": 7, "delay": 39.673, "offset": 4.684, "jitter": 4.916, "state": "+"}, {"remote": "23.152.160.126", "refid": "84.168.88.243", "st": 2, "t": "u", "when": 28, "poll": 64, "reach": 7, "delay": 21.553, "offset": 3.245, "jitter": 8.612, "state": "+"}, {"remote": "ntp.backplanedn", "refid": "152.2.133.52", "st": 2, "t": "u", "when": 30, "poll": 64, "reach": 7, "delay": 93.009, "offset": 9.337, "jitter": 10.03, "state": "#"}, {"remote": "chilipepper.can", "refid": "193.79.237.14", "st": 2, "t": "u", "when": 32, "poll": 64, "reach": 7, "delay": 165.084, "offset": 5.872, "jitter": 3.797, "state": null}, {"remote": "198.255.68.106", "refid": "192.168.1.193", "st": 2, "t": "u", "when": 26, "poll": 64, "reach": 7, "delay": 30.911, "offset": 3.034, "jitter": 8.201, "state": "+"}, {"remote": "golem.canonical", "refid": "17.253.34.251", "st": 2, "t": "u", "when": 28, "poll": 64, "reach": 7, "delay": 156.657, "offset": 3.767, "jitter": 5.448, "state": null}, {"remote": "vps.jan-jaap.ne", "refid": "132.163.96.1", "st": 2, "t": "u", "when": 23, "poll": 64, "reach": 7, "delay": 184.394, "offset": -7.118, "jitter": 4.585, "state": "#"}, {"remote": "vf2.bbnx.net", "refid": "252.74.143.178", "st": 2, "t": "u", "when": 28, "poll": 64, "reach": 7, "delay": 97.275, "offset": 0.824, "jitter": 18.08, "state": "+"}, {"remote": "pugot.canonical", "refid": "17.253.34.253", "st": 2, "t": "u", "when": 29, "poll": 64, "reach": 7, "delay": 157.069, "offset": 3.709, "jitter": 8.753, "state": null}]

24
tests/fixtures/ubuntu-18.04/ntpq-p2.out vendored Normal file
View File

@@ -0,0 +1,24 @@
remote refid st t when poll reach delay offset jitter
==============================================================================
0.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
1.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
2.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
3.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
ntp.ubuntu.com .POOL. 16 p - 64 0 0.000 0.000 0.000
+45.79.36.123 (t 216.218.254.202 2 u 11 64 7 68.172 4.404 4.878
+199.188.64.12 ( 173.161.33.165 2 u 9 64 7 78.823 2.148 8.739
*ntp2.wiktel.com .GPS. 1 u 25 64 7 76.857 0.473 7.890
#atl0.jane.mattn 35.73.197.144 2 u 32 64 7 87.536 8.641 4.544
+x.ns.gin.ntt.ne 249.224.99.213 2 u 28 64 7 25.021 3.361 7.793
-srcf-ntp.stanfo 171.64.7.105 2 u 26 64 7 28.053 7.253 4.524
#linode.ibendit. 64.250.105.227 2 u 28 64 7 56.841 -0.305 8.279
+71.66.197.233 .GPS. 1 u 26 64 7 127.766 -0.769 3.465
+time.aja.com 198.169.208.144 2 u 32 64 7 39.673 4.684 4.916
+23.152.160.126 84.168.88.243 2 u 28 64 7 21.553 3.245 8.612
#ntp.backplanedn 152.2.133.52 2 u 30 64 7 93.009 9.337 10.030
chilipepper.can 193.79.237.14 2 u 32 64 7 165.084 5.872 3.797
+198.255.68.106 192.168.1.193 2 u 26 64 7 30.911 3.034 8.201
golem.canonical 17.253.34.251 2 u 28 64 7 156.657 3.767 5.448
#vps.jan-jaap.ne 132.163.96.1 2 u 23 64 7 184.394 -7.118 4.585
+vf2.bbnx.net 252.74.143.178 2 u 28 64 7 97.275 0.824 18.080
pugot.canonical 17.253.34.253 2 u 29 64 7 157.069 3.709 8.753

View File

@@ -0,0 +1 @@
[{"state": null, "remote": "0.ubuntu.pool.n", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0}, {"state": null, "remote": "1.ubuntu.pool.n", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0}, {"state": null, "remote": "2.ubuntu.pool.n", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0}, {"state": null, "remote": "3.ubuntu.pool.n", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0}, {"state": null, "remote": "ntp.ubuntu.com", "refid": ".POOL.", "st": 16, "t": "p", "when": null, "poll": 64, "reach": 0, "delay": 0.0, "offset": 0.0, "jitter": 0.0}, {"state": "+", "remote": "216.126.233.109", "refid": "128.227.205.3", "st": 2, "t": "u", "when": 40, "poll": 64, "reach": 1, "delay": 95.876, "offset": -65.426, "jitter": 4.502}, {"state": "+", "remote": "162.159.200.123", "refid": "10.4.0.197", "st": 3, "t": "u", "when": 39, "poll": 64, "reach": 1, "delay": 25.239, "offset": -69.809, "jitter": 3.313}, {"state": "+", "remote": "47.190.36.235", "refid": "139.78.97.128", "st": 2, "t": "u", "when": 41, "poll": 64, "reach": 1, "delay": 60.008, "offset": -70.991, "jitter": 2.884}, {"state": "*", "remote": "209.51.161.238", "refid": ".CDMA.", "st": 1, "t": "u", "when": 37, "poll": 64, "reach": 1, "delay": 90.113, "offset": -65.938, "jitter": 4.621}, {"state": "-", "remote": "23.31.21.164", "refid": "252.74.143.178", "st": 2, "t": "u", "when": 40, "poll": 64, "reach": 1, "delay": 209.667, "offset": -81.337, "jitter": 5.547}, {"state": "+", "remote": "72.30.35.88", "refid": "98.139.133.62", "st": 3, "t": "u", "when": 40, "poll": 64, "reach": 1, "delay": 104.541, "offset": -67.956, "jitter": 5.731}, {"state": null, "remote": "91.189.94.4", "refid": "17.253.34.125", "st": 2, "t": "u", "when": 48, "poll": 64, "reach": 1, "delay": 176.609, "offset": -65.874, "jitter": 0.0}, {"state": "-", "remote": "50.205.244.110", "refid": "50.205.244.27", "st": 2, "t": "u", "when": 35, "poll": 64, "reach": 1, "delay": 76.322, "offset": -65.135, "jitter": 2.334}, {"state": "+", "remote": "199.223.248.99", "refid": "146.186.222.14", "st": 2, "t": "u", "when": 36, "poll": 64, "reach": 1, "delay": 110.723, "offset": -65.056, "jitter": 6.198}, {"state": null, "remote": "91.189.89.199", "refid": "17.253.34.123", "st": 2, "t": "u", "when": 45, "poll": 64, "reach": 1, "delay": 186.589, "offset": -61.769, "jitter": 0.0}, {"state": "-", "remote": "103.105.51.156", "refid": "206.55.191.142", "st": 2, "t": "u", "when": 34, "poll": 64, "reach": 1, "delay": 38.164, "offset": -65.286, "jitter": 6.412}, {"state": null, "remote": "91.189.91.157", "refid": "17.253.108.125", "st": 2, "t": "u", "when": 48, "poll": 64, "reach": 1, "delay": 105.626, "offset": -63.73, "jitter": 0.0}, {"state": "-", "remote": "23.31.21.163", "refid": "253.109.221.150", "st": 2, "t": "u", "when": 35, "poll": 64, "reach": 1, "delay": 101.941, "offset": -73.597, "jitter": 3.39}, {"state": null, "remote": "91.189.89.198", "refid": "145.238.203.14", "st": 2, "t": "u", "when": 44, "poll": 64, "reach": 1, "delay": 188.989, "offset": -59.352, "jitter": 0.0}]

21
tests/fixtures/ubuntu-18.04/ntpq-pn.out vendored Normal file
View File

@@ -0,0 +1,21 @@
remote refid st t when poll reach delay offset jitter
==============================================================================
0.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
1.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
2.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
3.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
ntp.ubuntu.com .POOL. 16 p - 64 0 0.000 0.000 0.000
+216.126.233.109 128.227.205.3 2 u 40 64 1 95.876 -65.426 4.502
+162.159.200.123 10.4.0.197 3 u 39 64 1 25.239 -69.809 3.313
+47.190.36.235 139.78.97.128 2 u 41 64 1 60.008 -70.991 2.884
*209.51.161.238 .CDMA. 1 u 37 64 1 90.113 -65.938 4.621
-23.31.21.164 252.74.143.178 2 u 40 64 1 209.667 -81.337 5.547
+72.30.35.88 98.139.133.62 3 u 40 64 1 104.541 -67.956 5.731
91.189.94.4 17.253.34.125 2 u 48 64 1 176.609 -65.874 0.000
-50.205.244.110 50.205.244.27 2 u 35 64 1 76.322 -65.135 2.334
+199.223.248.99 146.186.222.14 2 u 36 64 1 110.723 -65.056 6.198
91.189.89.199 17.253.34.123 2 u 45 64 1 186.589 -61.769 0.000
-103.105.51.156 206.55.191.142 2 u 34 64 1 38.164 -65.286 6.412
91.189.91.157 17.253.108.125 2 u 48 64 1 105.626 -63.730 0.000
-23.31.21.163 253.109.221.150 2 u 35 64 1 101.941 -73.597 3.390
91.189.89.198 145.238.203.14 2 u 44 64 1 188.989 -59.352 0.000

21
tests/fixtures/ubuntu-18.04/ntqp-p.out vendored Normal file
View File

@@ -0,0 +1,21 @@
remote refid st t when poll reach delay offset jitter
==============================================================================
0.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
1.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
2.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
3.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000
ntp.ubuntu.com .POOL. 16 p - 64 0 0.000 0.000 0.000
+216.126.233.109 128.227.205.3 2 u 24 64 1 95.876 -65.426 4.502
+time.cloudflare 10.4.0.197 3 u 33 64 1 25.239 -69.809 3.313
+titan.crash-ove 139.78.97.128 2 u 35 64 1 60.008 -70.991 2.884
*clock.nyc.he.ne .CDMA. 1 u 31 64 1 90.113 -65.938 4.621
-vf2.bbnx.net 252.74.143.178 2 u 34 64 1 209.667 -81.337 5.547
+t2.time.bf1.yah 98.139.133.62 3 u 35 64 1 104.541 -67.956 5.731
pugot.canonical 17.253.34.125 2 u 43 64 1 176.609 -65.874 0.000
-50-205-244-110- 50.205.244.27 2 u 30 64 1 76.322 -65.135 2.334
+1.time.dbsinet. 146.186.222.14 2 u 31 64 1 110.723 -65.056 6.198
golem.canonical 17.253.34.123 2 u 40 64 1 186.589 -61.769 0.000
-103.105.51.156 206.55.191.142 2 u 30 64 1 38.164 -65.286 6.412
alphyn.canonica 17.253.108.125 2 u 44 64 1 105.626 -63.730 0.000
-vf1.bbnx.net 253.109.221.150 2 u 31 64 1 101.941 -73.597 3.390
chilipepper.can 145.238.203.14 2 u 40 64 1 188.989 -59.352 0.000

View File

@@ -0,0 +1 @@
{"local_time": "Wed 2020-03-11 00:51:11 UTC", "universal_time": "Wed 2020-03-11 00:51:11 UTC", "rtc_time": "Wed 2020-03-11 00:51:11", "time_zone": "Etc/UTC (UTC, +0000)", "system_clock_synchronized": true, "systemd-timesyncd.service_active": true, "rtc_in_local_tz": false}

View File

@@ -0,0 +1,7 @@
Local time: Wed 2020-03-11 00:51:11 UTC
Universal time: Wed 2020-03-11 00:51:11 UTC
RTC time: Wed 2020-03-11 00:51:11
Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
systemd-timesyncd.service active: yes
RTC in local TZ: no

28
tests/test_airport.py Normal file
View File

@@ -0,0 +1,28 @@
import os
import unittest
import json
import jc.parsers.airport
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
class MyTests(unittest.TestCase):
def setUp(self):
# input
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/airport-I.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_airport_I = f.read()
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/airport-I.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_airport_I_json = json.loads(f.read())
def test_airport_I_osx_10_14_6(self):
"""
Test 'airport -I' on OSX 10.14.6
"""
self.assertEqual(jc.parsers.airport.parse(self.osx_10_14_6_airport_I, quiet=True), self.osx_10_14_6_airport_I_json)
if __name__ == '__main__':
unittest.main()

28
tests/test_airport_s.py Normal file
View File

@@ -0,0 +1,28 @@
import os
import unittest
import json
import jc.parsers.airport_s
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
class MyTests(unittest.TestCase):
def setUp(self):
# input
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/airport-s.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_airport_s = f.read()
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/airport-s.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_airport_s_json = json.loads(f.read())
def test_airport_s_osx_10_14_6(self):
"""
Test 'airport -s' on OSX 10.14.6
"""
self.assertEqual(jc.parsers.airport_s.parse(self.osx_10_14_6_airport_s, quiet=True), self.osx_10_14_6_airport_s_json)
if __name__ == '__main__':
unittest.main()

View File

@@ -34,6 +34,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/arp-a.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_arp_a = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/arp-a2.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_arp_a2 = f.read()
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/arp.json'), 'r', encoding='utf-8') as f:
self.centos_7_7_arp_json = json.loads(f.read())
@@ -59,6 +62,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/arp-a.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_arp_a_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/arp-a2.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_arp_a2_json = json.loads(f.read())
def test_arp_centos_7_7(self):
"""
Test 'arp' on Centos 7.7
@@ -107,6 +113,12 @@ class MyTests(unittest.TestCase):
"""
self.assertEqual(jc.parsers.arp.parse(self.osx_10_14_6_arp_a, quiet=True), self.osx_10_14_6_arp_a_json)
def test_arp_a2_osx_10_14_6(self):
"""
Test 'arp -a' with entries with no ifscope on OSX 10.14.6
"""
self.assertEqual(jc.parsers.arp.parse(self.osx_10_14_6_arp_a2, quiet=True), self.osx_10_14_6_arp_a2_json)
if __name__ == '__main__':
unittest.main()

View File

@@ -13,6 +13,9 @@ class MyTests(unittest.TestCase):
'jc -p pip3 show jc': 'pip3 show jc | jc --pip-show -p',
'jc -prd last': 'last | jc --last -prd',
'jc -prd lastb': 'lastb | jc --last -prd',
'jc -p airport -I': 'airport -I | jc --airport -p',
'jc -p -r airport -I': 'airport -I | jc --airport -pr',
'jc -prd airport -I': 'airport -I | jc --airport -prd',
'jc -p nonexistent command': 'nonexistent command',
'jc -ap': None
}

View File

@@ -28,6 +28,33 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/dig-aaaa.out'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_dig_aaaa = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/dig-axfr.out'), 'r', encoding='utf-8') as f:
self.centos_7_7_dig_axfr = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/dig-axfr.out'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_dig_axfr = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.11.6/dig.out'), 'r', encoding='utf-8') as f:
self.osx_10_11_6_dig = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.11.6/dig-x.out'), 'r', encoding='utf-8') as f:
self.osx_10_11_6_dig_x = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.11.6/dig-aaaa.out'), 'r', encoding='utf-8') as f:
self.osx_10_11_6_dig_aaaa = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/dig.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_dig = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/dig-x.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_dig_x = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/dig-aaaa.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_dig_aaaa = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/dig-axfr.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_dig_axfr = f.read()
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/dig.json'), 'r', encoding='utf-8') as f:
self.centos_7_7_dig_json = json.loads(f.read())
@@ -47,6 +74,33 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/dig-aaaa.json'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_dig_aaaa_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/dig-axfr.json'), 'r', encoding='utf-8') as f:
self.centos_7_7_dig_axfr_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/dig-axfr.json'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_dig_axfr_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.11.6/dig.json'), 'r', encoding='utf-8') as f:
self.osx_10_11_6_dig_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.11.6/dig-x.json'), 'r', encoding='utf-8') as f:
self.osx_10_11_6_dig_x_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.11.6/dig-aaaa.json'), 'r', encoding='utf-8') as f:
self.osx_10_11_6_dig_aaaa_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/dig.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_dig_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/dig-x.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_dig_x_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/dig-aaaa.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_dig_aaaa_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/dig-axfr.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_dig_axfr_json = json.loads(f.read())
def test_dig_centos_7_7(self):
"""
Test 'dig' on Centos 7.7
@@ -83,6 +137,60 @@ class MyTests(unittest.TestCase):
"""
self.assertEqual(jc.parsers.dig.parse(self.ubuntu_18_4_dig_aaaa, quiet=True), self.ubuntu_18_4_dig_aaaa_json)
def test_dig_axfr_centos_7_7(self):
"""
Test 'dig axfr' on Centos 7.7
"""
self.assertEqual(jc.parsers.dig.parse(self.centos_7_7_dig_axfr, quiet=True), self.centos_7_7_dig_axfr_json)
def test_dig_axfr_ubuntu_18_4(self):
"""
Test 'dig axfr' on Ubuntu 18.4
"""
self.assertEqual(jc.parsers.dig.parse(self.ubuntu_18_4_dig_axfr, quiet=True), self.ubuntu_18_4_dig_axfr_json)
def test_dig_osx_10_11_6(self):
"""
Test 'dig' on OSX 10.11.6
"""
self.assertEqual(jc.parsers.dig.parse(self.osx_10_11_6_dig, quiet=True), self.osx_10_11_6_dig_json)
def test_dig_x_osx_10_11_6(self):
"""
Test 'dig -x' on OSX 10.11.6
"""
self.assertEqual(jc.parsers.dig.parse(self.osx_10_11_6_dig_x, quiet=True), self.osx_10_11_6_dig_x_json)
def test_dig_aaaa_osx_10_11_6(self):
"""
Test 'dig -aaaa' on OSX 10.11.6
"""
self.assertEqual(jc.parsers.dig.parse(self.osx_10_11_6_dig_aaaa, quiet=True), self.osx_10_11_6_dig_aaaa_json)
def test_dig_osx_10_14_6(self):
"""
Test 'dig' on OSX 10.14.6
"""
self.assertEqual(jc.parsers.dig.parse(self.osx_10_14_6_dig, quiet=True), self.osx_10_14_6_dig_json)
def test_dig_x_osx_10_14_6(self):
"""
Test 'dig -x' on OSX 10.14.6
"""
self.assertEqual(jc.parsers.dig.parse(self.osx_10_14_6_dig_x, quiet=True), self.osx_10_14_6_dig_x_json)
def test_dig_aaaa_osx_10_14_6(self):
"""
Test 'dig -aaaa' on OSX 10.14.6
"""
self.assertEqual(jc.parsers.dig.parse(self.osx_10_14_6_dig_aaaa, quiet=True), self.osx_10_14_6_dig_aaaa_json)
def test_dig_axfr_osx_10_14_6(self):
"""
Test 'dig axfr' on OSX 10.14.6
"""
self.assertEqual(jc.parsers.dig.parse(self.osx_10_14_6_dig_axfr, quiet=True), self.osx_10_14_6_dig_axfr_json)
if __name__ == '__main__':
unittest.main()

64
tests/test_file.py Normal file
View File

@@ -0,0 +1,64 @@
import os
import unittest
import json
import jc.parsers.file
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
class MyTests(unittest.TestCase):
def setUp(self):
# input
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/file.out'), 'r', encoding='utf-8') as f:
self.centos_7_7_file = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/file.out'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_file = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/file.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_file = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/file2.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_file2 = f.read()
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/file.json'), 'r', encoding='utf-8') as f:
self.centos_7_7_file_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/file.json'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_file_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/file.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_file_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/file2.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_file2_json = json.loads(f.read())
def test_file_centos_7_7(self):
"""
Test 'file *' on Centos 7.7
"""
self.assertEqual(jc.parsers.file.parse(self.centos_7_7_file, quiet=True), self.centos_7_7_file_json)
def test_file_ubuntu_18_4(self):
"""
Test 'file *' on Ubuntu 18.4
"""
self.assertEqual(jc.parsers.file.parse(self.ubuntu_18_4_file, quiet=True), self.ubuntu_18_4_file_json)
def test_file_osx_10_14_6(self):
"""
Test 'file *' on OSX 10.14.6
"""
self.assertEqual(jc.parsers.file.parse(self.osx_10_14_6_file, quiet=True), self.osx_10_14_6_file_json)
def test_file2_osx_10_14_6(self):
"""
Test 'file *' with filetpe descriptions including colons on OSX 10.14.6
"""
self.assertEqual(jc.parsers.file.parse(self.osx_10_14_6_file2, quiet=True), self.osx_10_14_6_file2_json)
if __name__ == '__main__':
unittest.main()

76
tests/test_ntpq.py Normal file
View File

@@ -0,0 +1,76 @@
import os
import unittest
import json
import jc.parsers.ntpq
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
class MyTests(unittest.TestCase):
def setUp(self):
# input
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/ntpq-p.out'), 'r', encoding='utf-8') as f:
self.centos_7_7_ntpq_p = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ntpq-p.out'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_ntpq_p = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/ntpq-pn.out'), 'r', encoding='utf-8') as f:
self.centos_7_7_ntpq_pn = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ntpq-pn.out'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_ntpq_pn = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ntpq-p2.out'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_ntpq_p2 = f.read()
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/ntpq-p.json'), 'r', encoding='utf-8') as f:
self.centos_7_7_ntpq_p_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ntpq-p.json'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_ntpq_p_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/ntpq-pn.json'), 'r', encoding='utf-8') as f:
self.centos_7_7_ntpq_pn_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ntpq-pn.json'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_ntpq_pn_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ntpq-p2.json'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_ntpq_p2_json = json.loads(f.read())
def test_ntpq_p_centos_7_7(self):
"""
Test 'ntpq -p' on Centos 7.7
"""
self.assertEqual(jc.parsers.ntpq.parse(self.centos_7_7_ntpq_p, quiet=True), self.centos_7_7_ntpq_p_json)
def test_ntpq_p_ubuntu_18_4(self):
"""
Test 'ntpq -p' on Ubuntu 18.4
"""
self.assertEqual(jc.parsers.ntpq.parse(self.ubuntu_18_4_ntpq_p, quiet=True), self.ubuntu_18_4_ntpq_p_json)
def test_ntpq_pn_centos_7_7(self):
"""
Test 'ntpq -pn' on Centos 7.7
"""
self.assertEqual(jc.parsers.ntpq.parse(self.centos_7_7_ntpq_pn, quiet=True), self.centos_7_7_ntpq_pn_json)
def test_ntpq_pn_ubuntu_18_4(self):
"""
Test 'ntpq -pn' on Ubuntu 18.4
"""
self.assertEqual(jc.parsers.ntpq.parse(self.ubuntu_18_4_ntpq_pn, quiet=True), self.ubuntu_18_4_ntpq_pn_json)
def test_ntpq_p2_ubuntu_18_4(self):
"""
Test 'ntpq -p' with ip data with spaces on Ubuntu 18.4
"""
self.assertEqual(jc.parsers.ntpq.parse(self.ubuntu_18_4_ntpq_p2, quiet=True), self.ubuntu_18_4_ntpq_p2_json)
if __name__ == '__main__':
unittest.main()

40
tests/test_timedatectl.py Normal file
View File

@@ -0,0 +1,40 @@
import os
import unittest
import json
import jc.parsers.timedatectl
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
class MyTests(unittest.TestCase):
def setUp(self):
# input
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/timedatectl.out'), 'r', encoding='utf-8') as f:
self.centos_7_7_timedatectl = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/timedatectl.out'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_timedatectl = f.read()
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/timedatectl.json'), 'r', encoding='utf-8') as f:
self.centos_7_7_timedatectl_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/timedatectl.json'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_timedatectl_json = json.loads(f.read())
def test_timedatectl_centos_7_7(self):
"""
Test 'timedatectl' on Centos 7.7
"""
self.assertEqual(jc.parsers.timedatectl.parse(self.centos_7_7_timedatectl, quiet=True), self.centos_7_7_timedatectl_json)
def test_timedatectl_ubuntu_18_4(self):
"""
Test 'timedatectl' on Ubuntu 18.4
"""
self.assertEqual(jc.parsers.timedatectl.parse(self.ubuntu_18_4_timedatectl, quiet=True), self.ubuntu_18_4_timedatectl_json)
if __name__ == '__main__':
unittest.main()