1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-06-17 00:07:37 +02:00

fix for cases where the Filesystem data overflows the column length (happens on older versions of df)

This commit is contained in:
Kelly Brazil
2021-11-17 11:26:42 -08:00
parent 086da16b17
commit cd7731484d
4 changed files with 62 additions and 2 deletions

View File

@ -92,13 +92,14 @@ Examples:
...
]
"""
import hashlib
import jc.utils
import jc.parsers.universal
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.7'
version = '1.8'
description = '`df` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@ -165,6 +166,29 @@ def _process(proc_data):
return proc_data
def _long_filesystem_hash(header, line):
"""Returns truncated hash and value of the filesystem field if it is too long for the column"""
filesystem_field = line.split()[0]
# get length of filesystem column
space_count = 0
for char in header[10:]:
if char == ' ':
space_count += 1
continue
break
filesystem_col_len = space_count + 9
# return the hash and value if the field data is longer than the column length
if len(filesystem_field) > filesystem_col_len:
truncated_hash = hashlib.sha256(filesystem_field.encode('utf-8')).hexdigest()[:filesystem_col_len]
return truncated_hash, filesystem_field
return None, None
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
@ -184,7 +208,9 @@ def parse(data, raw=False, quiet=False):
jc.utils.compatibility(__name__, info.compatible)
cleandata = data.splitlines()
fix_data = []
raw_output = []
filesystem_map = {}
if jc.utils.has_data(data):
@ -193,8 +219,25 @@ def parse(data, raw=False, quiet=False):
cleandata[0] = cleandata[0].replace('-', '_')
cleandata[0] = cleandata[0].replace('mounted on', 'mounted_on')
# fix long filesystem data in some older versions of df
header = cleandata[0]
fix_data.append(header)
for line in cleandata[1:]:
field_hash, field_value = _long_filesystem_hash(header, line)
if field_hash:
filesystem_map.update({field_hash: field_value})
newline = line.replace(field_value, field_hash)
fix_data.append(newline)
else:
fix_data.append(line)
# parse the data
raw_output = jc.parsers.universal.sparse_table_parse(cleandata)
raw_output = jc.parsers.universal.sparse_table_parse(fix_data)
# replace hash values with real values to fix long filesystem data in some older versions of df
for item in raw_output:
if item['filesystem'] in filesystem_map:
item['filesystem'] = filesystem_map[item['filesystem']]
if raw:
return raw_output

View File

@ -0,0 +1 @@
[{"filesystem":"/dev/mapper/VolGroup00-LogVol00","type":"ext3","1024_blocks":6030784,"used":1147932,"available":4571556,"mounted_on":"/","capacity_percent":21},{"filesystem":"proc","type":"proc","1024_blocks":0,"used":0,"available":0,"mounted_on":"/proc","capacity_percent":null},{"filesystem":"sysfs","type":"sysfs","1024_blocks":0,"used":0,"available":0,"mounted_on":"/sys","capacity_percent":null}]

View File

@ -0,0 +1,4 @@
Filesystem Type 1024-blocks Used Available Capacity Mounted on
/dev/mapper/VolGroup00-LogVol00 ext3 6030784 1147932 4571556 21% /
proc proc 0 0 0 - /proc
sysfs sysfs 0 0 0 - /sys

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/df-h.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_df_h = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/df-long-filesystem.out'), 'r', encoding='utf-8') as f:
self.generic_df_long_filesystem = f.read()
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/df.json'), 'r', encoding='utf-8') as f:
self.centos_7_7_df_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/df-h.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_df_h_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/df-long-filesystem.json'), 'r', encoding='utf-8') as f:
self.generic_df_long_filesystem_json = json.loads(f.read())
def test_df_nodata(self):
"""
Test plain 'df' with no data
@ -113,6 +119,12 @@ class MyTests(unittest.TestCase):
"""
self.assertEqual(jc.parsers.df.parse(self.osx_10_14_6_df_h, quiet=True), self.osx_10_14_6_df_h_json)
def test_df_long_filesystem(self):
"""
Test older version of 'df' with long filesystem data
"""
self.assertEqual(jc.parsers.df.parse(self.generic_df_long_filesystem, quiet=True), self.generic_df_long_filesystem_json)
if __name__ == '__main__':
unittest.main()