Fixed up config option checking for KISS

This patch updates the config option checking for
required fields in the config yaml file.  Specifically
for the existence of the aprsd: section
and the required fields for the 3 supported client types
apris,
kiss serial,
kiss tcp
This commit is contained in:
Hemna 2022-02-21 16:04:33 -05:00
parent e739441268
commit 1c052a63c0
8 changed files with 93 additions and 27 deletions

View File

@ -55,7 +55,8 @@ def process_standard_options(f: F) -> F:
ctx.obj["quiet"] = kwargs["quiet"]
ctx.obj["config"] = aprsd_config.parse_config(kwargs["config_file"])
log.setup_logging(
ctx.obj["config"], ctx.obj["loglevel"],
ctx.obj["config"],
ctx.obj["loglevel"],
ctx.obj["quiet"],
)

View File

@ -5,7 +5,8 @@ import time
import aprslib
from aprslib.exceptions import LoginError
from aprsd import trace
from aprsd import config as aprsd_config
from aprsd import exception, trace
from aprsd.clients import aprsis, kiss
@ -76,7 +77,21 @@ class APRSISClient(Client):
@staticmethod
def is_enabled(config):
# Defaults to True if the enabled flag is non existent
return config["aprs"].get("enabled", True)
try:
return config["aprs"].get("enabled", True)
except KeyError:
return False
@staticmethod
def is_configured(config):
if APRSISClient.is_enabled(config):
# Ensure that the config vars are correctly set
config.check_option("aprs.login")
config.check_option("aprs.password")
config.check_option("aprs.host")
return True
return True
@staticmethod
def transport(config):
@ -133,6 +148,26 @@ class KISSClient(Client):
return False
@staticmethod
def is_configured(config):
# Ensure that the config vars are correctly set
if KISSClient.is_enabled(config):
config.check_option(
"kiss.callsign",
default_fail=aprsd_config.DEFAULT_CONFIG_DICT["kiss"]["callsign"],
)
transport = KISSClient.transport(config)
if transport == TRANSPORT_SERIALKISS:
config.check_option("kiss.serial")
config.check_option("kiss.serial.device")
elif transport == TRANSPORT_TCPKISS:
config.check_option("kiss.tcp")
config.check_option("kiss.tcp.host")
config.check_option("kiss.tcp.port")
return True
return True
@staticmethod
def transport(config):
if config.get("kiss.serial.enabled", default=False):
@ -195,7 +230,26 @@ class ClientFactory:
"""Make sure at least one client is enabled."""
enabled = False
for key in self._builders.keys():
enabled |= self._builders[key].is_enabled(self.config)
try:
enabled |= self._builders[key].is_enabled(self.config)
except KeyError:
pass
return enabled
def is_client_configured(self):
enabled = False
for key in self._builders.keys():
try:
enabled |= self._builders[key].is_configured(self.config)
except KeyError:
pass
except exception.MissingConfigOptionException as ex:
LOG.error(ex.message)
return False
except exception.ConfigOptionBogusDefaultException as ex:
LOG.error(ex.message)
return False
return enabled

View File

@ -70,6 +70,10 @@ def server(ctx, flush):
LOG.error("No Clients are enabled in config.")
sys.exit(-1)
if not client.factory.is_client_configured():
LOG.error("APRS client is not properly configured in config file.")
sys.exit(-1)
# Creates the client object
LOG.info("Creating client connection")
client.factory.create().client

View File

@ -7,7 +7,7 @@ import sys
import click
import yaml
from aprsd import utils
from aprsd import exception, utils
home = str(Path.home())
@ -63,6 +63,7 @@ DEFAULT_CONFIG_DICT = {
"port": 14580,
},
"kiss": {
"callsign": "NOCALL",
"tcp": {
"enabled": False,
"host": "direwolf.ip.address",
@ -174,22 +175,15 @@ class Config(collections.UserDict):
def check_option(self, path, default_fail=None):
"""Make sure the config option doesn't have default value."""
if not self.exists(path):
raise Exception(
"Option '{}' was not in config file".format(
path,
),
)
if type(path) is list:
path = ".".join(path)
raise exception.MissingConfigOption(path)
val = self.get(path)
if val == default_fail:
# We have to fail and bail if the user hasn't edited
# this config option.
raise Exception(
"Config file needs to be changed from provided"
" defaults for '{}'".format(
path,
),
)
raise exception.ConfigOptionBogusDefault(path, default_fail)
def add_config_comments(raw_yaml):
@ -330,13 +324,7 @@ def parse_config(config_file):
)
check_option(
config,
"aprs.login",
default_fail=DEFAULT_CONFIG_DICT["aprs"]["login"],
)
check_option(
config,
["aprs", "password"],
default_fail=DEFAULT_CONFIG_DICT["aprs"]["password"],
["aprsd"],
)
# Ensure they change the admin password

13
aprsd/exception.py Normal file
View File

@ -0,0 +1,13 @@
class MissingConfigOptionException(Exception):
"""Missing a config option."""
def __init__(self, config_option):
self.message = f"Option '{config_option}' was not in config file"
class ConfigOptionBogusDefaultException(Exception):
"""Missing a config option."""
def __init__(self, config_option, default_fail):
self.message = (
f"Config file option '{config_option}' needs to be "
f"changed from provided default of '{default_fail}'"
)

View File

@ -33,10 +33,10 @@ def setup_logging(config, loglevel, quiet):
rich_logging = True
log_file = config["aprsd"].get("logfile", None)
log_format = config["aprsd"].get("logformat", aprsd_config.DEFAULT_LOG_FORMAT)
log_formatter = logging.Formatter(fmt=log_format, datefmt=date_format)
if log_file:
log_format = config["aprsd"].get("logformat", aprsd_config.DEFAULT_LOG_FORMAT)
log_formatter = logging.Formatter(fmt=log_format, datefmt=date_format)
fh = RotatingFileHandler(log_file, maxBytes=(10248576 * 5), backupCount=4)
fh.setFormatter(log_formatter)
LOG.addHandler(fh)

View File

@ -109,11 +109,17 @@ class KeepAliveThread(APRSDThread):
current, peak = tracemalloc.get_traced_memory()
stats_obj.set_memory(current)
stats_obj.set_memory_peak(peak)
try:
login = self.config["aprs"]["login"]
except KeyError:
login = self.config["ham"]["callsign"]
keepalive = (
"{} - Uptime {} RX:{} TX:{} Tracker:{} Msgs TX:{} RX:{} "
"Last:{} Email: {} - RAM Current:{} Peak:{} Threads:{}"
).format(
self.config["aprs"]["login"],
login,
utils.strfdelta(stats_obj.uptime),
pl.total_recv,
pl.total_tx,

View File

@ -61,7 +61,7 @@ commands =
[flake8]
max-line-length = 99
show-source = True
ignore = E713,E501,W503
ignore = E713,E501,W503,N818
extend-ignore = E203,W503
extend-exclude = venv
exclude = .venv,.git,.tox,dist,doc,.ropeproject