From 3ca619e86d2946483e556040467a26f0836b74d4 Mon Sep 17 00:00:00 2001 From: Andreas Wrede Date: Fri, 6 Feb 2026 15:19:14 -0500 Subject: [PATCH] add hbc and prepare for package --- .gitignore | 1 - .hbc.swp | Bin 0 -> 16384 bytes dist/hbd-5.0-py3-none-any.whl | Bin 0 -> 37372 bytes dist/hbd-5.0.tar.gz | Bin 0 -> 38530 bytes hbc => hbd/hbc.py | 291 ++++++++----------- hbd/http.py | 8 +- hbd/install.sh | 6 + hbd/server.py | 5 +- {templates => hbd/templates}/foot.html | 0 {templates => hbd/templates}/head.html | 0 {templates => hbd/templates}/live.html | 52 ++++ {templates => hbd/templates}/menu.html | 0 hbd/udp.py | 2 +- hbdclass.py | 380 +++++++++++++++++++++++++ pyproject.toml | 5 +- 15 files changed, 574 insertions(+), 176 deletions(-) create mode 100644 .hbc.swp create mode 100644 dist/hbd-5.0-py3-none-any.whl create mode 100644 dist/hbd-5.0.tar.gz rename hbc => hbd/hbc.py (78%) create mode 100644 hbd/install.sh rename {templates => hbd/templates}/foot.html (100%) rename {templates => hbd/templates}/head.html (100%) rename {templates => hbd/templates}/live.html (83%) rename {templates => hbd/templates}/menu.html (100%) create mode 100644 hbdclass.py diff --git a/.gitignore b/.gitignore index fcaa10b..6dad32f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,4 @@ __pycache__/ .venv/ test/ build/ -dist/ *.egg-info/ \ No newline at end of file diff --git a/.hbc.swp b/.hbc.swp new file mode 100644 index 0000000000000000000000000000000000000000..37211faf2f32db78cdd6d046af72b3fe485d9f32 GIT binary patch literal 16384 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 literal 0 HcmV?d00001 diff --git a/hbc b/hbd/hbc.py similarity index 78% rename from hbc rename to hbd/hbc.py index b4bd33f..e507a29 100755 --- a/hbc +++ b/hbd/hbc.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 # $Id: hbc,v 1.9 2012/03/29 02:08:36 andreas Exp $ # NEW +import argparse import sys import time import socket @@ -18,6 +19,7 @@ import subprocess import syslog import codecs +from .config import load_config PORT = 50003 INTERVAL = 10 @@ -30,6 +32,17 @@ running = True dorestart = False warned1 = False +msgonly = False +helpflag = False +verbose = False +fdaemon = False +daemonized = False +optlist = [] +msgboot = {} +home = os.environ["HOME"] +configfile = "%s/.hbrc" % home +cmdargs = [] +iam = socket.gethostname() def log(msg): if fdaemon: @@ -460,181 +473,121 @@ def daemonize( os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno()) - -msgonly = False -helpflag = False -verbose = False -fdaemon = False -daemonized = False -optlist = [] -args = [] -msgboot = {} -home = os.environ["HOME"] -configfile = "%s/.hbrc" % home -cmdargs = [] -iam = socket.gethostname() - - -try: - optlist, args = getopt.getopt(sys.argv[1:], "bc:dhm:n:v") -except: - helpflag = True - -for o, a in optlist: - if o == "-b": - msgboot["boot"] = 1 - elif o == "-c": - configfile = a - cmdargs += [o, a] - elif o == "-d": - fdaemon = True - cmdargs += [o] - elif o == "-h": - helpflag = True - elif o == "-m": - msgboot["service"] = "service" - msgboot["msg"] = a - msgonly = True - elif o == "-n": - iam = a - cmdargs += [o, a] - elif o == "-v": - verbose = True - cmdargs += [o] - - -cmdargs += args -if verbose: - print("cmdargs for restart are %s" % cmdargs) - -if helpflag: - print("hbc HeartBeatClient") - print("usage: hbc [-bdhv] [-c configfile] [-m msg][host1 [..]]") - print() - print(" -b indicate machine boot") - print(" -c configfile") - print(" -d daemonize") - print(" -h this help") - print(" -m send a message") - print(" -v verbose") - print() - print( - """ config file can contain -hb_hosts=('host1', 'host2', ..._ -hb_port=50003 -interval=20 -logfile=... -logfmt={|test|msg} -grace=SECONDS -reportstrict={True|False} -""" +# +# Main program +# +def build_parser(): + parser = argparse.ArgumentParser( + prog="hbc", + description="HeartBeatClient - send a heatbeat message to a HeartBeatDaemon", + formatter_class=argparse.RawDescriptionHelpFormatter, ) + parser.add_argument("-b", "--boot", action="store_true", help="Send a boot message") + parser.add_argument("-c", "--config", dest="configfile", help="Config file path (YAML)") + parser.add_argument("-m", "--message", dest="message", help="Send a message") + parser.add_argument("-n", "--name", dest="name", help="Name to use in heartbeat message") + parser.add_argument("-f", "--daemon", action="store_true", help="Run in daemon mode") + parser.add_argument("-v", "--verbose", action="store_true", help="Verbose output") + parser.add_argument("-x", "--debug", action="count", default=0, help="Increase debug level") + parser.add_argument("hosts", nargs="+", help="Heartbeat daemon hosts to send to") + return parser - sys.exit(1) +def main(argv=None): + global msgonly, helpflag, verbose, fdaemon, daemonized, optlist, msgboot, home, configfile, cmdargs, iam, hb_port, conns, interval, hb_hosts + parser = build_parser() + args = parser.parse_args(argv) + + config = load_config(args.configfile) -# -# set defaults + # Apply CLI overrides + if args.boot: + msgboot["boot"] = 1 + if args.message: + msgboot["service"] = "service" + msgboot["msg"] = args.message + msgonly = True + if args.name: + iam = args.name + if args.daemon: + fdaemon = True + if args.verbose: + verbose = True + if args.debug: + config.setdefault("debug", 0) + config["debug"] += args.debug -hb_port = PORT -interval = INTERVAL -hb_hosts = [] - -try: - f = open(configfile, "r") + cmdargs += argv if verbose: - print("notice: using config file %s" % configfile) -except: - if verbose: - print("warning: running without config file: %s" % configfile) - f = None + print("cmdargs for restart are %s" % cmdargs) + + # + # set defaults + + hb_hosts = args.hosts + hb_port = config.get("hb_port", PORT) + interval = config.get("interval", INTERVAL) -if f: - while 1: - l = f.readline() - if len(l) == 0: + # + if verbose: + print("notice: hb_hosts: %s" % str(hb_hosts)) + print("notice: hb_port: %s" % hb_port) + print("notice: interval: %s" % interval) + print("notice: iam: %s" % iam) + print("notice: msgonly: %s" % msgonly) + print("notice: msgboot: %s" % msgboot) + + if not msgonly: + msgboot["interval"] = interval + + conns = {} + while True: + if verbose: + log("create connections") + createConnections(hb_hosts) + if len(conns) != 0: break - r = l[:-1].split("=") - if r[0] == "hb_hosts": - hb_hosts = eval(r[1]) - if verbose: - print("notice: cfg hb_hosts: %s" % hb_hosts) - elif r[0] == "interval": - interval = eval(r[1]) - elif r[0] == "hb_port": - hb_port = eval(r[1]) - elif r[0] == "name": - iam = eval(r[1]) - if verbose: - print("name set to %s" % iam) - f.close() - -if len(args) != 0: - hb_hosts = args - - -if len(hb_hosts) == 0: - print("no hb server specified") - sys.exit(1) - -# -if verbose: - print("notice: hb_hosts: %s" % str(hb_hosts)) - print("notice: hb_port: %s" % hb_port) - print("notice: interval: %s" % interval) - print("notice: iam: %s" % iam) - print("notice: msgonly: %s" % msgonly) - print("notice: msgboot: %s" % msgboot) - -if not msgonly: - msgboot["interval"] = interval - - -conns = {} -while True: + if verbose: + log("no connections yet, sleep a bit") + time.sleep(2) + if verbose: - log("create connections") - createConnections(hb_hosts) - if len(conns) != 0: - break + log("%s connections created" % (len(conns))) + + if len(msgboot) > 0: + if verbose: + print("on boot") + msgboot["acks"] = 0 + for conn in conns: + conns[conn].sendto(msgboot) + + if msgonly: + if verbose: + print("msgboot done msgonly=%s" % msgonly) + closeall() + sys.exit(0) + + # + syslog.openlog("hbc", syslog.LOG_PID, syslog.LOG_DAEMON) + if fdaemon: + print("daemoinizing.") + daemonize() + daemonized = True + syslog.syslog(syslog.LOG_ERR, "starting heartbeat to %s" % ",".join(hb_hosts)) + + signal.signal(signal.SIGTERM, handler) + running = True + try: + process() + except Exception as e: + syslogtrace("process") + if verbose: + print("err: process exit: %s" % e) + if verbose: - log("no connections yet, sleep a bit") - time.sleep(2) - -if verbose: - log("%s connections created" % (len(conns))) - -if len(msgboot) > 0: - if verbose: - print("on boot") - msgboot["acks"] = 0 - for conn in conns: - conns[conn].sendto(msgboot) - -if msgonly: - if verbose: - print("msgboot done msgonly=%s" % msgonly) - closeall() - sys.exit(0) - -# -syslog.openlog("hbc", syslog.LOG_PID, syslog.LOG_DAEMON) -if fdaemon: - print("daemoinizing.") - daemonize() - daemonized = True - syslog.syslog(syslog.LOG_ERR, "starting heartbeat to %s" % ",".join(hb_hosts)) - -signal.signal(signal.SIGTERM, handler) -running = True -try: - process() -except Exception as e: - syslogtrace("process") - if verbose: - print("err: process exit: %s" % e) - -if verbose: - log("main: cleanup") -cleanup() -if dorestart: - restart() + log("main: cleanup") + cleanup() + if dorestart: + restart() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/hbd/http.py b/hbd/http.py index f18d918..582650f 100644 --- a/hbd/http.py +++ b/hbd/http.py @@ -131,10 +131,14 @@ async def start( return web.Response(text="restart request") async def live(request): - # render template from templates/live.html using Jinja2 - env = jinja2.Environment(loader=jinja2.FileSystemLoader(config.get("templates_dir", "templates"))) + # render template from hbd/templates/live.html using Jinja2 + # Resolve templates directory relative to the hbd package + pkg_dir = os.path.dirname(__file__) + templates_dir = config.get("templates_dir", os.path.join(pkg_dir, "templates")) + env = jinja2.Environment(loader=jinja2.FileSystemLoader(templates_dir)) host = config.get("hb_host", "localhost") extra_scripts = config.get("http_extra_scripts", "") + host = request.host.split(":")[0] heartbeat_ws_url = f"ws://{host}:{config.get('ws_port', 50005)}/hbd" tmpl = env.get_template("live.html") body = tmpl.render( diff --git a/hbd/install.sh b/hbd/install.sh new file mode 100644 index 0000000..c86adf1 --- /dev/null +++ b/hbd/install.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +# install hbd/hbc from wheel and create symlinks for hbd and hbc in /usr/local/bin + +set -e +pip install --upgrade --force-reinstall --no-deps --find-links https://github.com/andreas-h/heartbeat/releases/latest/download/ heartbeat-hbd \ No newline at end of file diff --git a/hbd/server.py b/hbd/server.py index 435b435..3b28a93 100644 --- a/hbd/server.py +++ b/hbd/server.py @@ -9,6 +9,7 @@ from . import __version__ from . import udp from . import hbdclass + from . import ws as ws_mod logger = logging.getLogger(__name__) @@ -73,7 +74,7 @@ async def _run_async(config): # prepare runtime dependencies import threading - from . import hbdclass +# from . import hbdclass from . import http as http_mod from . import dns as dns_mod from . import notify as notify_mod @@ -254,7 +255,7 @@ def load_pickled_hosts(config, hbdclass): lastfm = ["", "", ""] pickf.close() except Exception as e: - print(("load pickled failed: %s" % e)) + logger.exception("load pickled failed: %s", e) os.unlink(pickfile) hbdclass.Connection.htab = {} for h in list(hbdclass.Host.hosts.keys()): diff --git a/templates/foot.html b/hbd/templates/foot.html similarity index 100% rename from templates/foot.html rename to hbd/templates/foot.html diff --git a/templates/head.html b/hbd/templates/head.html similarity index 100% rename from templates/head.html rename to hbd/templates/head.html diff --git a/templates/live.html b/hbd/templates/live.html similarity index 83% rename from templates/live.html rename to hbd/templates/live.html index fd5507c..3e277a8 100644 --- a/templates/live.html +++ b/hbd/templates/live.html @@ -51,6 +51,40 @@ th:not(.sorttable_sorted):not(.sorttable_sorted_reverse):not(.sorttable_nosort):after { content: " \2195"; } + + /* Modal for connection status messages */ + .connection-modal { + display: none; + position: fixed; + z-index: 1000; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.4); + } + + .connection-modal.show { + display: flex; + justify-content: center; + align-items: center; + } + + .connection-modal-content { + background-color: #f9f9f9; + padding: 20px; + border: 1px solid #888; + border-radius: 5px; + text-align: center; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + min-width: 300px; + } + + .connection-modal-content p { + margin: 10px 0; + font-size: 16px; + color: #333; + } diff --git a/templates/menu.html b/hbd/templates/menu.html similarity index 100% rename from templates/menu.html rename to hbd/templates/menu.html diff --git a/hbd/udp.py b/hbd/udp.py index 509c422..35db4af 100644 --- a/hbd/udp.py +++ b/hbd/udp.py @@ -1,6 +1,6 @@ """UDP listener and datagram processing.""" import asyncio -from compression import zlib +import zlib import logging logger = logging.getLogger(__name__) diff --git a/hbdclass.py b/hbdclass.py new file mode 100644 index 0000000..ed7e16d --- /dev/null +++ b/hbdclass.py @@ -0,0 +1,380 @@ +""" +host and connection class shared between hbd and +the websit's heartbeat.py + +""" + +import time +import json +import copy +import queue + +num = 0 + +MAXRTTS = 10 + +DEBUG = 2 + + +def log(host, m): + if DEBUG: + print("class log: %s %s" % (host, m)) + + +class Connection: + # map of addrs to names + + htab = {} + UNKNOWN = "unknown" + UP = "up" + DOWN = "down" + OVERDUE = "overdue" + + def __init__(self, host, cid, addr, afam): + self.host = host + self.cid = cid + if addr[0:7] == "::ffff:": + addr = addr[7:] + self.addr = addr + self.afam = afam + self.rtts = [0] + self.lastbeat = time.time() + self.statetime = self.lastbeat + self.deltastatetime = "computed" + self.state = Connection.UNKNOWN + + if host: + Connection.htab[addr] = self.host.name + if self.host.isDynDns(): + log(self.host.name, "dns update %s" % self.addr) + Host.dnsQ.put((self.host.name, self.addr)) + + def registerDns(self): + Host.dnsQ.put((self.host.name, self.addr)) + + def clearstate(self): + d = {} + d["addr"] = "" + d["rtt"] = "" + d["lastbeat"] = "" + d["state"] = "" + d["statetime"] = "" + d["deltastatetime"] = "" + d["rttstate"] = "" + return d + + def statedict(self, Null=False): + d = self.clearstate() + now = time.time() + if not Null: + d["addr"] = self.addr + if self.rtts[-1]: + d["rtt"] = "%0.1f" % self.rtts[-1] + elif self.state == Connection.UNKNOWN: + d["rtt"] = "" + else: + d["rtt"] = "?" + d["lastbeat"] = self.lastbeat + if self.state == Connection.OVERDUE: + d["state"] = "%s" % self.state + else: + d["state"] = self.state + if self.state == Connection.UP: + d["rttstate"] = d["rtt"] + elif self.state == Connection.OVERDUE: + d["rttstate"] = "" + else: + d["rttstate"] = d["state"] + d["statetime"] = time.strftime( + "%Y-%m-%d %H:%M:%S", time.localtime(self.statetime) + ) + delta = now - self.statetime + + if self.state == Connection.UNKNOWN: + d["deltastatetime"] = "" + elif delta > 86400: + # d['deltastatetime'] = time.strftime("%d %H:%M:%S", time.gmtime(delta)) + d["deltastatetime"] = "%0.1f days" % (delta / 86400.0) + elif delta > 3600: + # d['deltastatetime'] = time.strftime("%H:%M:%S", time.gmtime(delta)) + d["deltastatetime"] = time.strftime("%k:%M hrs", time.gmtime(delta)) + # d['deltastatetime'] = "%0.1f hrs" % (delta / 3600.) + elif delta > 60: + # d['deltastatetime'] = time.strftime("%M:%S", time.gmtime(delta)) + d["deltastatetime"] = time.strftime("%M:%S mins", time.gmtime(delta)) + # d['deltastatetime'] = "%0.1f mins" % (delta / 60.) + else: + # d['deltastatetime'] = time.strftime("%S", time.gmtime(delta)) + d["deltastatetime"] = "%i secs" % (delta) + if self.state == Connection.UNKNOWN and now - self.lastbeat > 86400 * 10: + d = self.clearstate() + + return d + + def headerdict(self, afam): + d = {} + d["addr"] = "%s Addr" % afam + d["rtt"] = "Latencey" + d["lastbeat"] = "Last Contact" + d["state"] = "State" + d["statetime"] = "Last State" + d["rttstate"] = "Reach" + d["deltastatetime"] = "Last State" + return d + + def jsons(self): + return json.dumps(self.__dict__) + + # set new state, return number of secs in previous state + def newstate(self, state, now, when=0): + self.state = state + delta = now - when + s = delta - self.statetime + self.statetime = delta + return s + + def getstate(self): + return self.state + + def newaddr(self, addr, rtt, now): + self.lastbeat = now + self.rtts.append(rtt) + if len(self.rtts) > MAXRTTS: + del self.rtts[0] + + if self.addr == addr: + r = None + else: + r = "changed from %s to %s" % (self.addr, addr) + try: + del Connection.htab[self.addr] + except: + pass + self.addr = addr + Connection.htab[addr] = self.host.name + if self.host.isDynDns(): + Host.dnsQ.put((self.host.name, self.addr)) + return r + + +# +class Host: + # Table of Hosts + hosts = {} + dnsQ = queue.Queue() + + def __init__(self, name): + global num + self.name = name + if name: + num += 1 + Host.hosts[name] = self + self.num = num + self.dyn = False + self.watched = False + self.upcount = 0 + self.interval = 0 + self.doesack = -1 + self.cmds = [] + self.cver = 0 + self.connections = {} + self.hdwcounts = [[0, 0], [0, 0], [0, 0]] + + def statedict(self): + d = {} + d["name"] = self.name + if self.dyn: + d["name"] += "*" + if self.watched: + d["name"] = "%s" % d["name"] + d["dyn"] = str(self.dyn) + d["ver"] = str(self.cver) + d["num"] = self.num + for c in ["IPv4", "IPv6"]: + if c in self.connections: + cs = self.connections[c].statedict() + else: + cs = ubConnection.statedict(True) + for csv in cs: + d["%s.%s" % (c, csv)] = cs[csv] + + return d + + def headerdict(self): + d = {} + d["name"] = "Name" + d["dyn"] = "Dyn" + d["ver"] = "Ver" + d["num"] = "??" + for c in ["IPv4", "IPv6"]: + cs = ubConnection.headerdict(c) + for csv in cs: + d["%s.%s" % (c, csv)] = cs[csv] + return d + + def registerDns(self): + for af in self.connections: + self.connections[af].registerDns() + + def stateinfo(self): + ddict = {} + for d in self.__dict__: + if d == "connections": + cl = [] + for c in self.connections: + # dirty ugly hack: fix conn to host backpointer + cld = copy.deepcopy(self.connections[c].__dict__) + cld["host"] = cld["host"].name + cl.append(cld) + ddict[d] = cl + else: + ddict[d] = self.__dict__[d] + return ddict + + def jsons(self): + return json.dumps(self.stateinfo()) + + def setcver(self, cver): + self.cver = cver + + def isDynDns(self): + return self.dyn + + def isIPv4(self, addr): + if isinstance(addr, tuple): + return addr[0].find(".") > 0 + else: + return addr.find(".") > 0 + + def conndata(self, cid, addr, rtt, now): + if addr[0:7] == "::ffff:": + addr = addr[7:] + if self.isIPv4(addr): + afam = "IPv4" + else: + afam = "IPv6" + + if afam not in self.connections: + self.connections[afam] = Connection(self, cid, addr, afam) + + conn = self.connections[afam] + res = conn.newaddr(addr, rtt, now) + return conn, res + + # called when reloading class from pickle, add new fields here + def fixup(self): + for c in ["IPv4", "IPv6"]: + if c in self.connections: + addr = self.connections[c].addr + if addr[0:7] == "::ffff:": + addr = addr[7:] + self.connections[c].addr = addr + + pass + + # def dispstate(self): + # if self.state in ["down", "overdue"]: + # state = "%s" % self.state + # elif self.state in ["up", "UP"]: + # state = "" + # for x in list(self.connections.keys()): + # try: + # state += " %5.1f" % (self.connections[x].rtts[-1]) + # except: + # state += " %5s" % (self.connections[x].rtts[-1]) + # elif self.state in ["unknown", "UNKNOWN"]: + # state = "" + # else: + # state = "%s" % self.state + # return state + + def dispstats(self): + if self.doesack != -1: + if self.upcount > 0: + # return "(%0.1f%%) %s %s %s " % ((self.doesack * 100.0) / self.upcount, self.doesack, self.upcount, self.hdwcounts) + r = "" + for v in range(3): + a, u = self.hdwcounts[v] + if (self.upcount - u) != 0: + vs = "%0.0f" % ( + 100.0 - (((self.doesack - a) * 100.0) / (self.upcount - u)) + ) + if vs == "0": + vs = "" + else: + vs = "-" + r += '%s' % vs + return r + else: + return "(%s)" % (self.doesack) + return 'N/A>' + + hostfields_long = [ + "name", + "IPv4.addr", + "IPv4.state", + ("IPv4.rtt", 'style="text-align: right;"'), + ("IPv4.statetime", 'style="text-align: right;"'), + "IPv6.addr", + "IPv6.state", + ("IPv6.rtt", 'style="text-align: right;"'), + ("IPv6.statetime", 'style="text-align: right;"'), + "ver", + ] + + hostfields_short = [ + "name", + ("IPv4.rttstate", 'style="text-align: right;"'), + ("IPv4.deltastatetime", 'style="text-align: right;"'), + ("IPv6.rttstate", 'style="text-align: right;"'), + ("IPv6.deltastatetime", 'style="text-align: right;"'), + ] + + def gene(self, tag, v, attrib=None): + if attrib: + a = " %s" % attrib + else: + a = "" + return "<%s%s>%s" % (tag, a, v, tag) + + def htmltable(self, tag, hd, short): + if short: + hostfields = Host.hostfields_short + else: + hostfields = Host.hostfields_long + h = [] + for f in hostfields: + if isinstance(f, tuple): + h.append(self.gene(tag, hd[f[0]], f[1])) + else: + h.append(self.gene(tag, hd[f])) + return self.gene("tr", "\n".join(h)) + + def buildhosttable(self, short=False): + if DEBUG > 1: + print("DBG buildhosttable: start") + res = [] + res.append('') + res.append(ubHost.htmltable("th", ubHost.headerdict(), short)) + hosts_sorted = list(Host.hosts.keys()) + if len(hosts_sorted): + hosts_sorted.sort() + for h in hosts_sorted: + res.append(ubHost.htmltable("td", Host.hosts[h].statedict(), short)) + res.append("
") + if DEBUG > 1: + print("DBG buildhosttable: %s" % res) + return res + + def buildmsgtable(self, msgs): + res = [] + le = max(40 - len(Host.hosts), 3) + res.append("

Log of Events

") + for m in msgs[len(msgs) - le:]: + res.append("%s
" % m) + return res + + +# create fake "unbound objects", remove in Python 3.0 +ubHost = Host(None) +ubConnection = Connection(None, "", "", "") diff --git a/pyproject.toml b/pyproject.toml index bc1ce16..e65cfc7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,6 @@ readme = "README.md" requires-python = ">=3.10" license = { text = "MIT" } keywords = ["heartbeat", "monitoring", "dns", "websocket"] - authors = [ { name = "heartbeat contributors" } ] @@ -38,7 +37,11 @@ dev = [ [project.scripts] hbd = "hbd.cli:main" +hbc = "hbd.hbc:main" [tool.setuptools.packages.find] where = ["."] include = ["hbd*"] + +[tool.setuptools.package-data] +"hbd" = ["*.yaml", "static/*", "static/*/*", "templates/*"] \ No newline at end of file