sysview-py 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,38 @@
1
+ .OK {
2
+ color: black;
3
+ background-color: green;
4
+ }
5
+
6
+ .WARNING {
7
+ color: black;
8
+ background-color: gold;
9
+ }
10
+
11
+ .CRITICAL {
12
+ color: black;
13
+ background-color: crimson;
14
+ }
15
+
16
+ .UNKNOWN {
17
+ color: black;
18
+ background-color: purple;
19
+ }
20
+
21
+ .active {
22
+ background-color: dimgrey;
23
+ }
24
+
25
+ :root {
26
+ width: 100%;
27
+ color-scheme: dark;
28
+ --bg: #212121;
29
+ --accent-bg: #2b2b2b;
30
+ --text: #dcdcdc;
31
+ --text-light: #ababab;
32
+ --accent: #ffb300;
33
+ --accent-hover: #ffe099;
34
+ --accent-text: var(--bg);
35
+ --code: #f06292;
36
+ --preformatted: #ccc;
37
+ --disabled: #111;
38
+ }
sysview_py/sysview.py ADDED
@@ -0,0 +1,114 @@
1
+ import shutil
2
+ import sys
3
+ from jinja2 import Environment, PackageLoader, select_autoescape
4
+ from pathlib import Path
5
+ from .db import SysviewDB
6
+ from .report import Report, Host
7
+
8
+ DEFAULT_DB_PATH = Path.home() / ".sysview.db"
9
+ DEFAULT_HTML_PATH = Path.home() / "sysview"
10
+ STATIC_FILES_PATH = Path(__file__).parent / "static"
11
+
12
+
13
+
14
+ class Sysview:
15
+ status_sort_order = ("UNKNOWN", "CRITICAL", "WARNING", "OK")
16
+ def __init__(self, db=DEFAULT_DB_PATH, hosts=[], reports=[], html_root=DEFAULT_HTML_PATH):
17
+ self.db = db
18
+ self.hosts = hosts
19
+ self.reports = reports
20
+ self.html_root = html_root
21
+ self.html_hosts = html_root / "hosts"
22
+
23
+ @property
24
+ def all_services(self):
25
+ items = []
26
+ sorted_items = []
27
+ for host in self.hosts:
28
+ items += host.all_items
29
+ items.sort(key=lambda item: item.status_code, reverse=True)
30
+ return items
31
+
32
+ def setup_db(self, db_path):
33
+ self.db = SysviewDB(path=db_path)
34
+ self.db.connect()
35
+
36
+ def process_reports(self, raw_reports):
37
+ for raw_report in raw_reports:
38
+ report = Report(raw_report)
39
+ report.parse()
40
+ self.db.add(report)
41
+
42
+ def read_hosts(self):
43
+ self.hosts = [
44
+ Host(name=host[0], report_types=host[1]) for host in self.db.get_hosts()
45
+ ]
46
+
47
+ def update_html(self):
48
+ shutil.rmtree(self.html_root)
49
+ self.html_root.mkdir(parents=True)
50
+ self.html_hosts.mkdir(parents=True)
51
+ shutil.copytree(STATIC_FILES_PATH, self.html_root / STATIC_FILES_PATH.name)
52
+ env = Environment(
53
+ loader=PackageLoader("sysview_py"),
54
+ autoescape=select_autoescape()
55
+ )
56
+ html = env.get_template("index.html").render(hosts=self.hosts, title="Hosts", active="Hosts", path="")
57
+ html_path = self.html_root / "index.html"
58
+ with open(html_path, 'w') as f:
59
+ f.write(html)
60
+ for host in self.hosts:
61
+ html = env.get_template("host.html").render(host=host, title=host.name, active="Hosts", path="../../")
62
+ host_dir = self.html_hosts / host.name
63
+ host_dir.mkdir()
64
+ html_path = host_dir / "host.html"
65
+ with open(html_path, 'w') as f:
66
+ f.write(html)
67
+ for item in host.all_items:
68
+ html = env.get_template("service.html").render(item=item, title=host.name, active="Services", path="../../")
69
+ html_path = host_dir / f"{item.report_type}_{item.id}.html"
70
+ with open(html_path, 'w') as f:
71
+ f.write(html)
72
+ html = env.get_template("services.html").render(services=self.all_services, title="Services", active="Services", path="")
73
+ html_path = self.html_root / f"services.html"
74
+ with open(html_path, 'w') as f:
75
+ f.write(html)
76
+
77
+ def get_latest_reports(self):
78
+ for host in self.hosts:
79
+ host.reports = []
80
+ raw_reports = self.db.get_latest_reports(hostname=host.name)
81
+ for report_id, raw_report in raw_reports:
82
+ report = Report(raw_report, report_id=report_id)
83
+ report.parse()
84
+ host.reports.append(report)
85
+ host.reports.sort(key=lambda report: report.status_code, reverse=True)
86
+ self.hosts.sort(key=lambda host: host.status_code, reverse=True)
87
+
88
+ @staticmethod
89
+ def read_raw_reports_from_stdin():
90
+ raw_reports = []
91
+ raw_report = ""
92
+ buffer = ""
93
+ identified_fields = 0
94
+ header_fields = ("Hostname:", "Date:", "Type:")
95
+ for raw_line in sys.stdin:
96
+ line = raw_line.rstrip()
97
+ buffer += f"{line}\n"
98
+ possible_header = False
99
+ for field in header_fields:
100
+ if line.startswith(field):
101
+ identified_fields += 1
102
+ possible_header = True
103
+ break
104
+ if identified_fields > 0 and not possible_header:
105
+ identified_fields = 0
106
+ if identified_fields == 3:
107
+ if raw_report:
108
+ raw_reports.append(raw_report)
109
+ raw_report = buffer
110
+ elif identified_fields == 0:
111
+ raw_report += f"{line}\n"
112
+ buffer = ""
113
+ raw_reports.append(raw_report)
114
+ return raw_reports
@@ -0,0 +1,5 @@
1
+ </main>
2
+ <footer>
3
+ <p>verson 0.0.1<p>
4
+ </footer>
5
+ </body></html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>sysview::{{ title }}</title>
7
+ <link rel="stylesheet" href="{{ path }}static/simple.css">
8
+ <link rel="stylesheet" href="{{ path }}static/sysview.css">
9
+ </head>
10
+ <body><header>
11
+ <nav>
12
+ {% if active == 'Hosts' %}
13
+ <a class="current" href="{{ path }}index.html">Hosts</a>
14
+ {% else %}
15
+ <a href="{{ path }}index.html">Hosts</a>
16
+ {% endif %}
17
+
18
+ {% if active == 'Services' %}
19
+ <a class="current" href="{{ path }}services.html">Services</a>
20
+ {% else %}
21
+ <a href="{{ path }}services.html">Services</a>
22
+ {% endif %}
23
+ </nav>
24
+ <h1>{{ title }}</h1>
25
+ </header>
26
+ <main>
@@ -0,0 +1,19 @@
1
+ {% include 'header.html' %}
2
+ <table>
3
+ <tr>
4
+ <th>Command</th>
5
+ <th>Output</th>
6
+ <th>Last updated</th>
7
+ <th>Status</th>
8
+ </tr>
9
+ {% for item in host.all_items %}
10
+
11
+ <tr>
12
+ <td><a href="{{ item.report_type }}_{{ item.id }}.html">{{ item.command }}</a></td>
13
+ <td>{{ item.status_text }}</td>
14
+ <td>{{ item.date }}</td>
15
+ <td class="{{ item.status }}"></td>
16
+ </tr>
17
+ {% endfor %}
18
+ </table>
19
+ {% include 'footer.html' %}
@@ -0,0 +1,22 @@
1
+ <html>
2
+ {% include 'header.html' %}
3
+ <table>
4
+ <thead><tr>
5
+ <th>Hostname</th>
6
+ <th>Report types</th>
7
+ <th>Last updated</th>
8
+ <th>Status</th>
9
+ </tr></thead>
10
+ <tbody>
11
+ {% for host in hosts %}
12
+ <tr>
13
+ <td><a href="hosts/{{ host.name }}/host.html">{{ host.name }}</a></td>
14
+ <td>{{ host.report_types }}</td>
15
+ <td>{{ host.last_updated }}</td>
16
+ <td class="{{ host.status }}"></td>
17
+ </tr>
18
+ {% endfor %}
19
+ </tbody>
20
+ </table>
21
+ {% include 'footer.html' %}
22
+ </html>
@@ -0,0 +1,22 @@
1
+ <html>
2
+ {% include 'header.html' %}
3
+ <table>
4
+ <thead><tr>
5
+ <th>Hostname</th>
6
+ <th>Report types</th>
7
+ <th>Last updated</th>
8
+ <th>Status</th>
9
+ </tr></thead>
10
+ <tbody>
11
+ {% for host in hosts %}
12
+ <tr>
13
+ <td><a href="hosts/{{ host.name }}/host.html">{{ host.name }}</a></td>
14
+ <td>{{ host.report_types }}</td>
15
+ <td>{{ host.last_updated }}</td>
16
+ <td class="{{ host.status }}"></td>
17
+ </tr>
18
+ {% endfor %}
19
+ </tbody>
20
+ </table>
21
+ {% include 'footer.html' %}
22
+ </html>
@@ -0,0 +1,6 @@
1
+ <html>
2
+ {% include 'header.html' %}
3
+ <a href="host.html">Back to host</a>
4
+ <pre>{{ item.raw_item }}</pre>
5
+ {% include 'footer.html' %}
6
+ </html>
@@ -0,0 +1,22 @@
1
+ <html>
2
+ {% include 'header.html' %}
3
+ <table>
4
+ <tr>
5
+ <th>Hostname</th>
6
+ <th>Command</th>
7
+ <th>Output</th>
8
+ <th>Last updated</th>
9
+ <th>Status</th>
10
+ </tr>
11
+ {% for item in services %}
12
+ <tr>
13
+ <td>{{ item.host }}</td>
14
+ <td><a href="hosts/{{ item.host }}/{{ item.report_type}}_{{ item.id }}.html">{{ item.command }}</a></td>
15
+ <td>{{ item.status_text }}</td>
16
+ <td>{{ item.date }}</td>
17
+ <td class="{{ item.status }}"></td>
18
+ </tr>
19
+ {% endfor %}
20
+ </table>
21
+ {% include 'footer.html' %}
22
+ </html>
@@ -0,0 +1,10 @@
1
+ Metadata-Version: 2.3
2
+ Name: sysview-py
3
+ Version: 0.1.0
4
+ Summary: Add your description here
5
+ Author: Michael Wilson
6
+ Author-email: Michael Wilson <mw@1wilson.org>
7
+ Requires-Dist: jinja2>=3.1.6
8
+ Requires-Python: >=3.12
9
+ Description-Content-Type: text/markdown
10
+
@@ -0,0 +1,19 @@
1
+ sysview_py/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ sysview_py/db.py,sha256=kSkFvD00T68J9YO3Xn6mG1Zc09tqBBKzDgwl8x-CWSQ,4074
3
+ sysview_py/flock.py,sha256=HJnZAMQUPJ6GCjmqyZ8_ST3-a-4xOHCnSAkdM8e6dEo,270
4
+ sysview_py/main.py,sha256=yZQ0VqNItjV3BPS1VAi02DGPoj7r_bXePT2UGGJWLYg,632
5
+ sysview_py/report.py,sha256=nYVDK5qmrpEFmGETfR9-9LqeER-0u5sa6fUrIj-51bY,5856
6
+ sysview_py/static/simple.css,sha256=EN01zNTQvZIZ2n9HNZaV03DD_ie6RUHbEOS6772tRyo,14086
7
+ sysview_py/static/sysview.css,sha256=vWntFiGQrpHBhcZRLg2DX-5lpp73RQmkmj-9NFIMtmI,529
8
+ sysview_py/sysview.py,sha256=LorkHeKDB8OnJYcwn9pdAAKRduCLqD94NkYk_YUEdGM,4348
9
+ sysview_py/templates/footer.html,sha256=DMkYmN0wZRByL_j3LBUEJHSo9U8ncTJQVKvClwuh5AE,66
10
+ sysview_py/templates/header.html,sha256=R_gJhk5ZCw1oFa0cAfXYjvIhiEFTcvRn_88bvZp9QP0,734
11
+ sysview_py/templates/host.html,sha256=SivuflShsO8KHRxDGgQt3hFpk_SCHcURhuc-n2jk9IU,444
12
+ sysview_py/templates/index.html,sha256=NiBPIUluBL-51wJfvde_8uNmSzq0acbAGa1_YReuImA,493
13
+ sysview_py/templates/index.html.table,sha256=NiBPIUluBL-51wJfvde_8uNmSzq0acbAGa1_YReuImA,493
14
+ sysview_py/templates/service.html,sha256=xYNYMJqtotcnWarhXTnit930XDRuesU03k7MEPZFkEM,143
15
+ sysview_py/templates/services.html,sha256=nD8Tllo15LcOh8lvpuc0EOQdsdO44RHjjA0CWmPuJK8,526
16
+ sysview_py-0.1.0.dist-info/WHEEL,sha256=o6xtdofIa8Zz80kUveEHMWeAWtEyZSzYS1bbyKDCgzA,80
17
+ sysview_py-0.1.0.dist-info/entry_points.txt,sha256=CEzvzrPEAijVzJWShPvvtnnSc4WouncYwajUDaSSsR8,53
18
+ sysview_py-0.1.0.dist-info/METADATA,sha256=ecMZthWKWN1SrFhDl4ihJ3ohMYWFf4Sv8fmiCzpP_Z4,252
19
+ sysview_py-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.10.4
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ sysview-py = sysview_py.main:main
3
+