1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-07-13 01:20:24 +02:00

add proc-net-igmp parser and tests

This commit is contained in:
Kelly Brazil
2022-09-25 15:19:43 -07:00
parent fcfbbc6d84
commit e4a40704b5
7 changed files with 470 additions and 0 deletions

View File

@ -0,0 +1,152 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.proc_net_igmp"></a>
# jc.parsers.proc\_net\_igmp
jc - JSON Convert `/proc/net/igmp` file parser
Usage (cli):
$ cat /proc/net/igmp | jc --proc
or
$ jc /proc/net/igmp
or
$ cat /proc/net/igmp | jc --proc-net-igmp
Usage (module):
import jc
result = jc.parse('proc', proc_net_igmp_file)
or
import jc
result = jc.parse('proc_net_igmp', proc_net_igmp_file)
Schema:
[
{
"index": integer,
"device": string,
"count": integer,
"querier": string,
"groups": [
{
"address": string,
"users": integer,
"timer": string,
"reporter": integer
}
]
}
]
Examples:
$ cat /proc/net/igmp | jc --proc -p
[
{
"index": 0,
"device": "lo",
"count": 0,
"querier": "V3",
"groups": [
{
"address": "010000E0",
"users": 1,
"timer": "0:00000000",
"reporter": 0
}
]
},
{
"index": 2,
"device": "eth0",
"count": 26,
"querier": "V2",
"groups": [
{
"address": "260301E0",
"users": 1,
"timer": "0:00000000",
"reporter": 1
},
{
"address": "9B0101E0",
"users": 1,
"timer": "0:00000000",
"reporter": 1
},
]
}
...
]
$ cat /proc/net/igmp | jc --proc -p -r
[
{
"index": "0",
"device": "lo",
"count": "0",
"querier": "V3",
"groups": [
{
"address": "010000E0",
"users": "1",
"timer": "0:00000000",
"reporter": "0"
}
]
},
{
"index": "2",
"device": "eth0",
"count": "26",
"querier": "V2",
"groups": [
{
"address": "260301E0",
"users": "1",
"timer": "0:00000000",
"reporter": "1"
},
{
"address": "9B0101E0",
"users": "1",
"timer": "0:00000000",
"reporter": "1"
},
]
}
...
}
<a id="jc.parsers.proc_net_igmp.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> List[Dict]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -125,6 +125,7 @@ parsers = [
'proc-net-dev',
'proc-net-dev-mcast',
'proc-net-if-inet6',
'proc-net-igmp',
'ps',
'route',
'rpm-qi',

231
jc/parsers/proc_net_igmp.py Normal file
View File

@ -0,0 +1,231 @@
"""jc - JSON Convert `/proc/net/igmp` file parser
Usage (cli):
$ cat /proc/net/igmp | jc --proc
or
$ jc /proc/net/igmp
or
$ cat /proc/net/igmp | jc --proc-net-igmp
Usage (module):
import jc
result = jc.parse('proc', proc_net_igmp_file)
or
import jc
result = jc.parse('proc_net_igmp', proc_net_igmp_file)
Schema:
[
{
"index": integer,
"device": string,
"count": integer,
"querier": string,
"groups": [
{
"address": string,
"users": integer,
"timer": string,
"reporter": integer
}
]
}
]
Examples:
$ cat /proc/net/igmp | jc --proc -p
[
{
"index": 0,
"device": "lo",
"count": 0,
"querier": "V3",
"groups": [
{
"address": "010000E0",
"users": 1,
"timer": "0:00000000",
"reporter": 0
}
]
},
{
"index": 2,
"device": "eth0",
"count": 26,
"querier": "V2",
"groups": [
{
"address": "260301E0",
"users": 1,
"timer": "0:00000000",
"reporter": 1
},
{
"address": "9B0101E0",
"users": 1,
"timer": "0:00000000",
"reporter": 1
},
]
}
...
]
$ cat /proc/net/igmp | jc --proc -p -r
[
{
"index": "0",
"device": "lo",
"count": "0",
"querier": "V3",
"groups": [
{
"address": "010000E0",
"users": "1",
"timer": "0:00000000",
"reporter": "0"
}
]
},
{
"index": "2",
"device": "eth0",
"count": "26",
"querier": "V2",
"groups": [
{
"address": "260301E0",
"users": "1",
"timer": "0:00000000",
"reporter": "1"
},
{
"address": "9B0101E0",
"users": "1",
"timer": "0:00000000",
"reporter": "1"
},
]
}
...
}
"""
from typing import List, Dict
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = '`/proc/net/igmp` file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux']
hidden = True
__version__ = info.version
def _process(proc_data: List[Dict]) -> List[Dict]:
"""
Final processing to conform to the schema.
Parameters:
proc_data: (List of Dictionaries) raw structured data to process
Returns:
List of Dictionaries. Structured to conform to the schema.
"""
int_list = {'index', 'count', 'users', 'reporter'}
for item in proc_data:
for key, val in item.items():
if key in int_list:
item[key] = int(val)
if 'groups' in item:
for group in item['groups']:
for key, val in group.items():
if key in int_list:
group[key] = int(val)
return proc_data
def parse(
data: str,
raw: bool = False,
quiet: bool = False
) -> List[Dict]:
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output: List = []
output_line: Dict = {}
groups: List = []
group: Dict = {}
if jc.utils.has_data(data):
for line in filter(None, data.splitlines()[1:]):
if not line.startswith('\t'):
if output_line:
if groups:
output_line['groups'] = groups
raw_output.append(output_line)
output_line = {}
groups = []
group = {}
index, device, _, count, querier = line.split()
output_line = {
'index': index,
'device': device,
'count': count,
'querier': querier
}
continue
address, users, timer, reporter = line.split()
group = {
'address': address,
'users': users,
'timer': timer,
'reporter': reporter
}
groups.append(group)
continue
if output_line:
if groups:
output_line['groups'] = groups
raw_output.append(output_line)
return raw_output if raw else _process(raw_output)

View File

@ -0,0 +1 @@
[{"index":1,"device":"lo","count":1,"querier":"V3","groups":[{"address":"010000E0","users":1,"timer":"0:00000000","reporter":0}]},{"index":2,"device":"ens33","count":1,"querier":"V3","groups":[{"address":"010000E0","users":1,"timer":"0:00000000","reporter":0}]}]

30
tests/fixtures/linux-proc/net_igmp_more vendored Normal file
View File

@ -0,0 +1,30 @@
Idx Device : Count Querier Group Users Timer Reporter
0 lo : 0 V3
010000E0 1 0:00000000 0
2 eth0 : 26 V2
260301E0 1 0:00000000 1
9B0101E0 1 0:00000000 1
439501E0 1 0:00000000 1
990101E0 1 0:00000000 1
580101E0 1 0:00000000 1
2A0301E0 1 0:00000000 1
290301E0 1 0:00000000 1
280301E0 1 0:00000000 1
9BD901E0 1 0:00000000 1
2D0301E0 1 0:00000000 1
2C0301E0 1 0:00000000 1
370301E0 1 0:00000000 1
050101E0 1 0:00000000 1
620201E0 1 0:00000000 1
040201E0 1 0:00000000 1
5F0101E0 1 0:00000000 1
520101E0 1 0:00000000 1
2BEF01E0 1 0:00000000 1
4D0101E0 1 0:00000000 1
E00C01E0 1 0:00000000 1
400301E0 1 0:00000000 1
FB0000E0 1 0:00000000 1
010000E0 1 0:00000000 0
3 eth1 : 5 V2
FB0000E0 1 0:00000000 1
010000E0 1 0:00000000 0

View File

@ -0,0 +1 @@
[{"index":0,"device":"lo","count":0,"querier":"V3","groups":[{"address":"010000E0","users":1,"timer":"0:00000000","reporter":0}]},{"index":2,"device":"eth0","count":26,"querier":"V2","groups":[{"address":"260301E0","users":1,"timer":"0:00000000","reporter":1},{"address":"9B0101E0","users":1,"timer":"0:00000000","reporter":1},{"address":"439501E0","users":1,"timer":"0:00000000","reporter":1},{"address":"990101E0","users":1,"timer":"0:00000000","reporter":1},{"address":"580101E0","users":1,"timer":"0:00000000","reporter":1},{"address":"2A0301E0","users":1,"timer":"0:00000000","reporter":1},{"address":"290301E0","users":1,"timer":"0:00000000","reporter":1},{"address":"280301E0","users":1,"timer":"0:00000000","reporter":1},{"address":"9BD901E0","users":1,"timer":"0:00000000","reporter":1},{"address":"2D0301E0","users":1,"timer":"0:00000000","reporter":1},{"address":"2C0301E0","users":1,"timer":"0:00000000","reporter":1},{"address":"370301E0","users":1,"timer":"0:00000000","reporter":1},{"address":"050101E0","users":1,"timer":"0:00000000","reporter":1},{"address":"620201E0","users":1,"timer":"0:00000000","reporter":1},{"address":"040201E0","users":1,"timer":"0:00000000","reporter":1},{"address":"5F0101E0","users":1,"timer":"0:00000000","reporter":1},{"address":"520101E0","users":1,"timer":"0:00000000","reporter":1},{"address":"2BEF01E0","users":1,"timer":"0:00000000","reporter":1},{"address":"4D0101E0","users":1,"timer":"0:00000000","reporter":1},{"address":"E00C01E0","users":1,"timer":"0:00000000","reporter":1},{"address":"400301E0","users":1,"timer":"0:00000000","reporter":1},{"address":"FB0000E0","users":1,"timer":"0:00000000","reporter":1},{"address":"010000E0","users":1,"timer":"0:00000000","reporter":0}]},{"index":3,"device":"eth1","count":5,"querier":"V2","groups":[{"address":"FB0000E0","users":1,"timer":"0:00000000","reporter":1},{"address":"010000E0","users":1,"timer":"0:00000000","reporter":0}]}]

View File

@ -0,0 +1,54 @@
import os
import unittest
import json
from typing import Dict
import jc.parsers.proc_net_igmp
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
class MyTests(unittest.TestCase):
f_in: Dict = {}
f_json: Dict = {}
@classmethod
def setUpClass(cls):
fixtures = {
'proc_net_igmp': (
'fixtures/linux-proc/net_igmp',
'fixtures/linux-proc/net_igmp.json'),
'proc_net_igmp_more': (
'fixtures/linux-proc/net_igmp_more',
'fixtures/linux-proc/net_igmp_more.json')
}
for file, filepaths in fixtures.items():
with open(os.path.join(THIS_DIR, filepaths[0]), 'r', encoding='utf-8') as a, \
open(os.path.join(THIS_DIR, filepaths[1]), 'r', encoding='utf-8') as b:
cls.f_in[file] = a.read()
cls.f_json[file] = json.loads(b.read())
def test_proc_net_igmp_nodata(self):
"""
Test 'proc_net_igmp' with no data
"""
self.assertEqual(jc.parsers.proc_net_igmp.parse('', quiet=True), [])
def test_proc_net_igmp(self):
"""
Test '/proc/net/igmp'
"""
self.assertEqual(jc.parsers.proc_net_igmp.parse(self.f_in['proc_net_igmp'], quiet=True),
self.f_json['proc_net_igmp'])
def test_proc_net_igmp_more(self):
"""
Test '/proc/net/igmp' additional file
"""
self.assertEqual(jc.parsers.proc_net_igmp.parse(self.f_in['proc_net_igmp_more'], quiet=True),
self.f_json['proc_net_igmp_more'])
if __name__ == '__main__':
unittest.main()