portune 0.1.9__tar.gz → 0.1.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of portune might be problematic. Click here for more details.
- {portune-0.1.9/portune.egg-info → portune-0.1.11}/PKG-INFO +1 -1
- {portune-0.1.9 → portune-0.1.11}/portune/portune.py +23 -9
- {portune-0.1.9 → portune-0.1.11}/portune/version.py +2 -2
- {portune-0.1.9 → portune-0.1.11/portune.egg-info}/PKG-INFO +1 -1
- {portune-0.1.9 → portune-0.1.11}/.github/workflows/python-publish.yml +0 -0
- {portune-0.1.9 → portune-0.1.11}/.gitignore +0 -0
- {portune-0.1.9 → portune-0.1.11}/LICENSE +0 -0
- {portune-0.1.9 → portune-0.1.11}/README.md +0 -0
- {portune-0.1.9 → portune-0.1.11}/portune/__init__.py +0 -0
- {portune-0.1.9 → portune-0.1.11}/portune.egg-info/SOURCES.txt +0 -0
- {portune-0.1.9 → portune-0.1.11}/portune.egg-info/dependency_links.txt +0 -0
- {portune-0.1.9 → portune-0.1.11}/portune.egg-info/entry_points.txt +0 -0
- {portune-0.1.9 → portune-0.1.11}/portune.egg-info/top_level.txt +0 -0
- {portune-0.1.9 → portune-0.1.11}/pyproject.toml +0 -0
- {portune-0.1.9 → portune-0.1.11}/setup.cfg +0 -0
|
@@ -24,6 +24,7 @@ import time
|
|
|
24
24
|
import subprocess
|
|
25
25
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
26
26
|
from collections import defaultdict
|
|
27
|
+
import json
|
|
27
28
|
from html import escape
|
|
28
29
|
import smtplib
|
|
29
30
|
from email.mime.text import MIMEText
|
|
@@ -619,7 +620,7 @@ class ProgressBar:
|
|
|
619
620
|
sys.stderr.write('\n')
|
|
620
621
|
sys.stderr.flush()
|
|
621
622
|
|
|
622
|
-
def parse_input_file(filename: str) -> List[Tuple[str, List[int]]]:
|
|
623
|
+
def parse_input_file(filename: str, info_command: Optional[str] = None) -> List[Tuple[str, List[int]]]:
|
|
623
624
|
"""Parse the input file containing host and port information.
|
|
624
625
|
|
|
625
626
|
Reads a text file where each line contains a hostname and optionally a list of ports.
|
|
@@ -660,17 +661,29 @@ def parse_input_file(filename: str) -> List[Tuple[str, List[int]]]:
|
|
|
660
661
|
fqdn = words[0].lower()
|
|
661
662
|
ports = words[1] if len(words) > 1 else '22'
|
|
662
663
|
port_list = [int(p) for p in ports.split(',')]
|
|
663
|
-
desc = ' '.join(words[2:]).strip() if len(words) > 2 else
|
|
664
|
+
desc = ' '.join(words[2:]).strip().split('|') if len(words) > 2 else []
|
|
664
665
|
if fqdn in host_dict:
|
|
665
666
|
existing_ports, existing_desc = host_dict[fqdn]
|
|
666
667
|
host_dict[fqdn] = (list(set(existing_ports + port_list)), existing_desc or desc)
|
|
667
668
|
else:
|
|
668
|
-
host_dict[fqdn] = (port_list, desc)
|
|
669
|
+
host_dict[fqdn] = (port_list, desc)
|
|
670
|
+
desc_titles = []
|
|
671
|
+
if info_command:
|
|
672
|
+
res = subprocess.run(info_command, shell=True, input='\n'.join(host_dict.keys())+'\n', text=True, capture_output=True)
|
|
673
|
+
lines = res.stdout.splitlines()
|
|
674
|
+
desc_titles = lines[0].strip().split('\t')[1:] # Get the description titles from the first line
|
|
675
|
+
lines.pop(0) # Remove the first line with titles
|
|
676
|
+
for line in lines:
|
|
677
|
+
info = line.strip().split('\t')
|
|
678
|
+
fqdn = info[0].lower()
|
|
679
|
+
info.pop(0) # Remove the hostname from the info list
|
|
680
|
+
if fqdn in host_dict:
|
|
681
|
+
host_dict[fqdn] = (host_dict[fqdn][0], info)
|
|
669
682
|
hosts = []
|
|
670
683
|
for fqdn in host_dict:
|
|
671
684
|
ports, desc = host_dict[fqdn]
|
|
672
685
|
hosts.append((fqdn, sorted(ports), desc))
|
|
673
|
-
return hosts
|
|
686
|
+
return (hosts, desc_titles)
|
|
674
687
|
|
|
675
688
|
def ping_host(ip: str, timeout: float = 2.0) -> bool:
|
|
676
689
|
"""Test if a host responds to ICMP ping.
|
|
@@ -807,7 +820,7 @@ def ping_hosts(hosts: List[Tuple[str, List[int], str]],
|
|
|
807
820
|
def check_port(hostname: str,
|
|
808
821
|
port: int,
|
|
809
822
|
host_info: Dict[str, Union[str, bool]],
|
|
810
|
-
desc:
|
|
823
|
+
desc: list,
|
|
811
824
|
timeout: float = 2.0) -> Tuple[str, str, int, str, bool]:
|
|
812
825
|
"""Check if a specific TCP port is accessible on a host.
|
|
813
826
|
|
|
@@ -1236,7 +1249,7 @@ def generate_html_report(
|
|
|
1236
1249
|
# Write detailed results table
|
|
1237
1250
|
if not desc_titles:
|
|
1238
1251
|
_, _, _, _, _, desc = results[0]
|
|
1239
|
-
desc_titles = ["Description" for d in desc
|
|
1252
|
+
desc_titles = ["Description" for d in desc]
|
|
1240
1253
|
f.write(f'''
|
|
1241
1254
|
<div class="table-container" id="result-container">
|
|
1242
1255
|
<table id="commandTable">
|
|
@@ -1270,7 +1283,7 @@ def generate_html_report(
|
|
|
1270
1283
|
<td style="text-align: right;">{port}</td>
|
|
1271
1284
|
<td style="text-align: center;"><span class="{status_class} status">{escape(status)}</span></td>
|
|
1272
1285
|
<td style="text-align: center;"><span class="{ping_class} ping">{ping_status}</span></td>
|
|
1273
|
-
{"\n".join([f'<td class="desc">{escape(
|
|
1286
|
+
{"\n".join([f'<td class="desc">{escape(desc[i] if i < len(desc) else "")}</td>' for i in range(len(desc_titles))])}
|
|
1274
1287
|
</tr>
|
|
1275
1288
|
''')
|
|
1276
1289
|
|
|
@@ -1457,6 +1470,7 @@ def main():
|
|
|
1457
1470
|
parser.add_argument('-d', '--desc_titles', type=str, nargs='*', help='List of custom description titles for hosts (optional)')
|
|
1458
1471
|
parser.add_argument('-f', '--filter', type=str, help='default status filter for html report (optional)',
|
|
1459
1472
|
choices=['CONNECTED', 'REFUSED', 'TIMEOUT', 'UNREACHABLE', 'RESOLVE_FAIL'], default='')
|
|
1473
|
+
parser.add_argument('-i', '--info_command', type=str, help='Exernal command to get hosts information (optional)',)
|
|
1460
1474
|
|
|
1461
1475
|
# Email related arguments
|
|
1462
1476
|
email_group = parser.add_argument_group('Email Options')
|
|
@@ -1474,7 +1488,7 @@ def main():
|
|
|
1474
1488
|
if not os.path.exists(args.input_file):
|
|
1475
1489
|
print(f"Input file '{args.input_file}' does not exist.", file=sys.stderr)
|
|
1476
1490
|
sys.exit(1)
|
|
1477
|
-
hosts = parse_input_file(args.input_file)
|
|
1491
|
+
(hosts, desc_titles) = parse_input_file(args.input_file, args.info_command)
|
|
1478
1492
|
if not hosts:
|
|
1479
1493
|
print(f"No valid hosts found in input file '{args.input_file}'.", file=sys.stderr)
|
|
1480
1494
|
sys.exit(1)
|
|
@@ -1524,7 +1538,7 @@ def main():
|
|
|
1524
1538
|
args.noping,
|
|
1525
1539
|
stats,
|
|
1526
1540
|
args.input_file,
|
|
1527
|
-
args.desc_titles,
|
|
1541
|
+
args.desc_titles or desc_titles or [],
|
|
1528
1542
|
args.filter,
|
|
1529
1543
|
)
|
|
1530
1544
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|