diff --git a/man/jc.1 b/man/jc.1 index 66190af2..f2b1bf87 100644 --- a/man/jc.1 +++ b/man/jc.1 @@ -1,4 +1,4 @@ -.TH jc 1 2023-02-21 1.23.0 "JSON Convert" +.TH jc 1 2023-02-27 1.23.0 "JSON Convert" .SH NAME \fBjc\fP \- JSON Convert JSONifies the output of many CLI tools, file-types, and strings diff --git a/tests/fixtures/generic/zpool-iostat-v.json b/tests/fixtures/generic/zpool-iostat-v.json new file mode 100644 index 00000000..eebbc114 --- /dev/null +++ b/tests/fixtures/generic/zpool-iostat-v.json @@ -0,0 +1 @@ +[{"pool":"zhgstera6","cap_alloc":2.89,"cap_free":2.2,"ops_read":0,"ops_write":2,"bw_read":349.0,"bw_write":448.0,"cap_alloc_unit":"T","cap_free_unit":"T","bw_read_unit":"K","bw_write_unit":"K"},{"pool":"726060ALE614-K8JAPRGN:10","parent":"zhgstera6","cap_alloc":2.89,"cap_free":2.2,"ops_read":0,"ops_write":2,"bw_read":349.0,"bw_write":448.0,"cap_alloc_unit":"T","cap_free_unit":"T","bw_read_unit":"K","bw_write_unit":"K"},{"pool":"zint500","cap_alloc":230.0,"cap_free":24.0,"ops_read":0,"ops_write":9,"bw_read":112.0,"bw_write":318.0,"cap_alloc_unit":"G","cap_free_unit":"G","bw_read_unit":"K","bw_write_unit":"K"},{"pool":"ST3500418AS-5VMSTSSX:5","parent":"zint500","cap_alloc":230.0,"cap_free":24.0,"ops_read":0,"ops_write":9,"bw_read":112.0,"bw_write":318.0,"cap_alloc_unit":"G","cap_free_unit":"G","bw_read_unit":"K","bw_write_unit":"K"},{"pool":"zsam53","cap_alloc":211.0,"cap_free":24.5,"ops_read":0,"ops_write":0,"bw_read":14.7,"bw_write":74.4,"cap_alloc_unit":"G","cap_free_unit":"G","bw_read_unit":"K","bw_write_unit":"K"},{"pool":"Portable_SSD_T5-S49WNP0N120517B:8","parent":"zsam53","cap_alloc":211.0,"cap_free":24.5,"ops_read":0,"ops_write":0,"bw_read":14.7,"bw_write":74.4,"cap_alloc_unit":"G","cap_free_unit":"G","bw_read_unit":"K","bw_write_unit":"K"}] diff --git a/tests/fixtures/generic/zpool-iostat-v.out b/tests/fixtures/generic/zpool-iostat-v.out new file mode 100644 index 00000000..bdf5f561 --- /dev/null +++ b/tests/fixtures/generic/zpool-iostat-v.out @@ -0,0 +1,12 @@ + capacity operations bandwidth +pool alloc free read write read write +----------------------------------- ----- ----- ----- ----- ----- ----- +zhgstera6 2.89T 2.20T 0 2 349K 448K + 726060ALE614-K8JAPRGN:10 2.89T 2.20T 0 2 349K 448K +----------------------------------- ----- ----- ----- ----- ----- ----- +zint500 230G 24.0G 0 9 112K 318K + ST3500418AS-5VMSTSSX:5 230G 24.0G 0 9 112K 318K +----------------------------------- ----- ----- ----- ----- ----- ----- +zsam53 211G 24.5G 0 0 14.7K 74.4K + Portable_SSD_T5-S49WNP0N120517B:8 211G 24.5G 0 0 14.7K 74.4K +----------------------------------- ----- ----- ----- ----- ----- ----- diff --git a/tests/fixtures/generic/zpool-iostat.json b/tests/fixtures/generic/zpool-iostat.json new file mode 100644 index 00000000..d9b92004 --- /dev/null +++ b/tests/fixtures/generic/zpool-iostat.json @@ -0,0 +1 @@ +[{"pool":"zhgstera6","cap_alloc":2.89,"cap_free":2.2,"ops_read":0,"ops_write":2,"bw_read":349.0,"bw_write":448.0,"cap_alloc_unit":"T","cap_free_unit":"T","bw_read_unit":"K","bw_write_unit":"K"},{"pool":"zint500","cap_alloc":230.0,"cap_free":24.0,"ops_read":0,"ops_write":9,"bw_read":112.0,"bw_write":318.0,"cap_alloc_unit":"G","cap_free_unit":"G","bw_read_unit":"K","bw_write_unit":"K"},{"pool":"zsam53","cap_alloc":211.0,"cap_free":24.5,"ops_read":0,"ops_write":0,"bw_read":14.7,"bw_write":74.4,"cap_alloc_unit":"G","cap_free_unit":"G","bw_read_unit":"K","bw_write_unit":"K"}] diff --git a/tests/fixtures/generic/zpool-iostat.out b/tests/fixtures/generic/zpool-iostat.out new file mode 100644 index 00000000..8192fab1 --- /dev/null +++ b/tests/fixtures/generic/zpool-iostat.out @@ -0,0 +1,7 @@ + capacity operations bandwidth +pool alloc free read write read write +---------- ----- ----- ----- ----- ----- ----- +zhgstera6 2.89T 2.20T 0 2 349K 448K +zint500 230G 24.0G 0 9 112K 318K +zsam53 211G 24.5G 0 0 14.7K 74.4K +---------- ----- ----- ----- ----- ----- ----- diff --git a/tests/fixtures/generic/zpool-status-v.json b/tests/fixtures/generic/zpool-status-v.json new file mode 100644 index 00000000..bb257c8c --- /dev/null +++ b/tests/fixtures/generic/zpool-status-v.json @@ -0,0 +1 @@ +[{"pool":"zhgstera6","state":"ONLINE","scan":"scrub canceled on Fri Aug 19 15:33:19 2022","config":[{"name":"zhgstera6","state":"ONLINE","read":0,"write":0,"checksum":0},{"name":"726060ALE614-K8JAPRGN:10","state":"ONLINE","read":0,"write":0,"checksum":0}],"errors":"No known data errors"},{"pool":"zint500","state":"ONLINE","scan":"scrub repaired 0 in 0 days 00:19:47 with 0 errors on Tue Aug 16 00:20:50 2022","config":[{"name":"zint500","state":"ONLINE","read":0,"write":0,"checksum":0},{"name":"ST3500418AS-5VMSTSSX:5","state":"ONLINE","read":0,"write":0,"checksum":0}],"errors":"No known data errors"},{"pool":"zsam53","state":"ONLINE","scan":"scrub repaired 0 in 0 days 01:25:43 with 0 errors on Mon Aug 15 01:26:46 2022","config":[{"name":"zsam53","state":"ONLINE","read":0,"write":0,"checksum":0},{"name":"Portable_SSD_T5-S49WNP0N120517B:8","state":"ONLINE","read":0,"write":0,"checksum":0}],"errors":"No known data errors"}] diff --git a/tests/fixtures/generic/zpool-status-v.out b/tests/fixtures/generic/zpool-status-v.out new file mode 100644 index 00000000..8d92c7ce --- /dev/null +++ b/tests/fixtures/generic/zpool-status-v.out @@ -0,0 +1,24 @@ + pool: zhgstera6 + state: ONLINE + scan: scrub canceled on Fri Aug 19 15:33:19 2022 +config: + NAME STATE READ WRITE CKSUM + zhgstera6 ONLINE 0 0 0 + 726060ALE614-K8JAPRGN:10 ONLINE 0 0 0 +errors: No known data errors + pool: zint500 + state: ONLINE + scan: scrub repaired 0 in 0 days 00:19:47 with 0 errors on Tue Aug 16 00:20:50 2022 +config: + NAME STATE READ WRITE CKSUM + zint500 ONLINE 0 0 0 + ST3500418AS-5VMSTSSX:5 ONLINE 0 0 0 +errors: No known data errors + pool: zsam53 + state: ONLINE + scan: scrub repaired 0 in 0 days 01:25:43 with 0 errors on Mon Aug 15 01:26:46 2022 +config: + NAME STATE READ WRITE CKSUM + zsam53 ONLINE 0 0 0 + Portable_SSD_T5-S49WNP0N120517B:8 ONLINE 0 0 0 +errors: No known data errors diff --git a/tests/fixtures/generic/zpool-status-v2.json b/tests/fixtures/generic/zpool-status-v2.json new file mode 100644 index 00000000..c3ab6d9e --- /dev/null +++ b/tests/fixtures/generic/zpool-status-v2.json @@ -0,0 +1 @@ +[{"pool":"tank","state":"DEGRADED","status":"One or more devices could not be opened. Sufficient replicas exist for\nthe pool to continue functioning in a degraded state.","action":"Attach the missing device and online it using 'zpool online'.","see":"http://www.sun.com/msg/ZFS-8000-2Q","scrub":"none requested","config":[{"name":"tank","state":"DEGRADED","read":0,"write":0,"checksum":0},{"name":"mirror-0","state":"DEGRADED","read":0,"write":0,"checksum":0},{"name":"c1t0d0","state":"ONLINE","read":0,"write":0,"checksum":0},{"name":"c1t1d0","state":"UNAVAIL","read":0,"write":0,"checksum":0,"errors":"cannot open"}],"errors":"No known data errors"}] diff --git a/tests/fixtures/generic/zpool-status-v2.out b/tests/fixtures/generic/zpool-status-v2.out new file mode 100644 index 00000000..a7b3a23e --- /dev/null +++ b/tests/fixtures/generic/zpool-status-v2.out @@ -0,0 +1,17 @@ + pool: tank + state: DEGRADED +status: One or more devices could not be opened. Sufficient replicas exist for + the pool to continue functioning in a degraded state. +action: Attach the missing device and online it using 'zpool online'. + see: http://www.sun.com/msg/ZFS-8000-2Q + scrub: none requested +config: + + NAME STATE READ WRITE CKSUM + tank DEGRADED 0 0 0 + mirror-0 DEGRADED 0 0 0 + c1t0d0 ONLINE 0 0 0 + c1t1d0 UNAVAIL 0 0 0 cannot open + +errors: No known data errors + diff --git a/tests/fixtures/generic/zpool-status-v3.json b/tests/fixtures/generic/zpool-status-v3.json new file mode 100644 index 00000000..6b54de88 --- /dev/null +++ b/tests/fixtures/generic/zpool-status-v3.json @@ -0,0 +1 @@ +[{"pool":"tank","state":"UNAVAIL","status":"One or more devices are faulted in response to IO failures.","action":"Make sure the affected devices are connected, then run 'zpool clear'.","see":"http://www.sun.com/msg/ZFS-8000-HC","scrub":"scrub completed after 0h0m with 0 errors on Tue Feb 2 13:08:42 2010","config":[{"name":"tank","state":"UNAVAIL","read":0,"write":0,"checksum":0,"errors":"insufficient replicas"},{"name":"c1t0d0","state":"ONLINE","read":0,"write":0,"checksum":0},{"name":"c1t1d0","state":"UNAVAIL","read":4,"write":1,"checksum":0,"errors":"cannot open"}],"errors":"Permanent errors have been detected in the following files:\n/tank/data/aaa\n/tank/data/bbb\n/tank/data/ccc"}] diff --git a/tests/fixtures/generic/zpool-status-v3.out b/tests/fixtures/generic/zpool-status-v3.out new file mode 100644 index 00000000..4314f1ee --- /dev/null +++ b/tests/fixtures/generic/zpool-status-v3.out @@ -0,0 +1,18 @@ + pool: tank + state: UNAVAIL +status: One or more devices are faulted in response to IO failures. +action: Make sure the affected devices are connected, then run 'zpool clear'. + see: http://www.sun.com/msg/ZFS-8000-HC + scrub: scrub completed after 0h0m with 0 errors on Tue Feb 2 13:08:42 2010 +config: + + NAME STATE READ WRITE CKSUM + tank UNAVAIL 0 0 0 insufficient replicas + c1t0d0 ONLINE 0 0 0 + c1t1d0 UNAVAIL 4 1 0 cannot open + +errors: Permanent errors have been detected in the following files: + +/tank/data/aaa +/tank/data/bbb +/tank/data/ccc diff --git a/tests/test_zpool_iostat.py b/tests/test_zpool_iostat.py new file mode 100644 index 00000000..64e961fd --- /dev/null +++ b/tests/test_zpool_iostat.py @@ -0,0 +1,59 @@ +import os +import unittest +import json +from typing import Dict +from jc.parsers.zpool_iostat import parse + +THIS_DIR = os.path.dirname(os.path.abspath(__file__)) + + +class MyTests(unittest.TestCase): + f_in: Dict = {} + f_json: Dict = {} + + @classmethod + def setUpClass(cls): + fixtures = { + 'zpool_iostat': ( + 'fixtures/generic/zpool-iostat.out', + 'fixtures/generic/zpool-iostat.json'), + 'zpool_iostat_v': ( + 'fixtures/generic/zpool-iostat-v.out', + 'fixtures/generic/zpool-iostat-v.json') + } + + for file, filepaths in fixtures.items(): + with open(os.path.join(THIS_DIR, filepaths[0]), 'r', encoding='utf-8') as a, \ + open(os.path.join(THIS_DIR, filepaths[1]), 'r', encoding='utf-8') as b: + cls.f_in[file] = a.read() + cls.f_json[file] = json.loads(b.read()) + + + def test_zpool_iostat_nodata(self): + """ + Test 'zpool iostat' with no data + """ + self.assertEqual(parse('', quiet=True), []) + + + def test_zpool_iostat(self): + """ + Test 'zpool iostat' + """ + self.assertEqual( + parse(self.f_in['zpool_iostat'], quiet=True), + self.f_json['zpool_iostat'] + ) + + def test_zpool_iostat_v(self): + """ + Test 'zpool iostat -v' + """ + self.assertEqual( + parse(self.f_in['zpool_iostat_v'], quiet=True), + self.f_json['zpool_iostat_v'] + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_zpool_status.py b/tests/test_zpool_status.py new file mode 100644 index 00000000..e31c4c4c --- /dev/null +++ b/tests/test_zpool_status.py @@ -0,0 +1,71 @@ +import os +import unittest +import json +from typing import Dict +from jc.parsers.zpool_status import parse + +THIS_DIR = os.path.dirname(os.path.abspath(__file__)) + + +class MyTests(unittest.TestCase): + f_in: Dict = {} + f_json: Dict = {} + + @classmethod + def setUpClass(cls): + fixtures = { + 'zpool_status': ( + 'fixtures/generic/zpool-status-v.out', + 'fixtures/generic/zpool-status-v.json'), + 'zpool_status2': ( + 'fixtures/generic/zpool-status-v2.out', + 'fixtures/generic/zpool-status-v2.json'), + 'zpool_status3': ( + 'fixtures/generic/zpool-status-v3.out', + 'fixtures/generic/zpool-status-v3.json') + } + + for file, filepaths in fixtures.items(): + with open(os.path.join(THIS_DIR, filepaths[0]), 'r', encoding='utf-8') as a, \ + open(os.path.join(THIS_DIR, filepaths[1]), 'r', encoding='utf-8') as b: + cls.f_in[file] = a.read() + cls.f_json[file] = json.loads(b.read()) + + + def test_zpool_status_nodata(self): + """ + Test 'zpool_status' with no data + """ + self.assertEqual(parse('', quiet=True), []) + + + def test_zpool_status_v(self): + """ + Test 'zpool status -v' + """ + self.assertEqual( + parse(self.f_in['zpool_status'], quiet=True), + self.f_json['zpool_status'] + ) + + def test_zpool_status_v_2(self): + """ + Test 'zpool status -v' #2 + """ + self.assertEqual( + parse(self.f_in['zpool_status2'], quiet=True), + self.f_json['zpool_status2'] + ) + + def test_zpool_status_v_3(self): + """ + Test 'zpool status -v' #3 + """ + self.assertEqual( + parse(self.f_in['zpool_status3'], quiet=True), + self.f_json['zpool_status3'] + ) + + +if __name__ == '__main__': + unittest.main()