From 17302aa76df2225f5fb12cf6ba041bfa8fbbc47e Mon Sep 17 00:00:00 2001 From: Hemna Date: Tue, 4 May 2021 09:55:13 -0400 Subject: [PATCH] Added aprsd version checking This patch adds usage of update_checker to check to make sure the version of APRSD being launched is the latest version. Also added a call to upate_checker as part of the KeepAlive thread. It will call update_check every hour. If there is no aprsd connectivitity, the update check will silently fail. --- README.rst | 2 +- aprsd/main.py | 43 ++++++++++++++++++++++++ aprsd/threads.py | 10 +++++- aprsd/utils.py | 21 +++++++++++- dev-requirements.txt | 79 ++++++++++++++++++++++---------------------- requirements.in | 5 ++- requirements.txt | 24 ++++++++------ 7 files changed, 130 insertions(+), 54 deletions(-) diff --git a/README.rst b/README.rst index 05a183c..09e2e4a 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ ===== -APRSD +APRSD ===== by KM6LYW and WB4BOR diff --git a/aprsd/main.py b/aprsd/main.py index 119a9a6..08ffda6 100644 --- a/aprsd/main.py +++ b/aprsd/main.py @@ -199,6 +199,43 @@ def setup_logging(config, loglevel, quiet): imap_logger.addHandler(sh) +@main.command() +@click.option( + "--loglevel", + default="INFO", + show_default=True, + type=click.Choice( + ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"], + case_sensitive=False, + ), + show_choices=True, + help="The log level to use for aprsd.log", +) +@click.option( + "-c", + "--config", + "config_file", + show_default=True, + default=utils.DEFAULT_CONFIG_FILE, + help="The aprsd config file to use for options.", +) +def check_version(loglevel, config_file): + config = utils.parse_config(config_file) + + # Force setting the config to the modules that need it + # TODO(Walt): convert these modules to classes that can + # Accept the config as a constructor param, instead of this + # hacky global setting + email.CONFIG = config + + setup_logging(config, loglevel, False) + level, msg = utils._check_version() + if level: + LOG.warning(msg) + else: + LOG.info(msg) + + @main.command() def sample_config(): """This dumps the config to stdout.""" @@ -417,6 +454,12 @@ def server( email.CONFIG = config setup_logging(config, loglevel, quiet) + level, msg = utils._check_version() + if level: + LOG.warning(msg) + else: + LOG.info(msg) + if config["aprsd"].get("trace", False): trace.setup_tracing(["method", "api"]) LOG.info("APRSD Started version: {}".format(aprsd.__version__)) diff --git a/aprsd/threads.py b/aprsd/threads.py index 7eb28f6..5e95890 100644 --- a/aprsd/threads.py +++ b/aprsd/threads.py @@ -67,10 +67,11 @@ class APRSDThread(threading.Thread, metaclass=abc.ABCMeta): class KeepAliveThread(APRSDThread): cntr = 0 + checker_time = datetime.datetime.now() def __init__(self): - super().__init__("KeepAlive") tracemalloc.start() + super().__init__("KeepAlive") def loop(self): if self.cntr % 6 == 0: @@ -102,6 +103,13 @@ class KeepAliveThread(APRSDThread): ) ) LOG.debug(keepalive) + # Check version every hour + delta = now - self.checker_time + if delta > datetime.timedelta(hours=1): + self.checker_time = now + level, msg = utils._check_version() + if level: + LOG.warning(msg) self.cntr += 1 time.sleep(10) return True diff --git a/aprsd/utils.py b/aprsd/utils.py index 5158ee5..afeeecb 100644 --- a/aprsd/utils.py +++ b/aprsd/utils.py @@ -8,8 +8,10 @@ from pathlib import Path import sys import threading +import aprsd from aprsd import plugin import click +import update_checker import yaml LOG_LEVELS = { @@ -364,7 +366,7 @@ def parse_config(config_file): def human_size(bytes, units=None): - """ Returns a human readable string representation of bytes """ + """Returns a human readable string representation of bytes""" if not units: units = [" bytes", "KB", "MB", "GB", "TB", "PB", "EB"] return str(bytes) + units[0] if bytes < 1024 else human_size(bytes >> 10, units[1:]) @@ -375,3 +377,20 @@ def strfdelta(tdelta, fmt="{hours}:{minutes}:{seconds}"): d["hours"], rem = divmod(tdelta.seconds, 3600) d["minutes"], d["seconds"] = divmod(rem, 60) return fmt.format(**d) + + +def _check_version(): + # check for a newer version + try: + check = update_checker.UpdateChecker() + result = check.check("aprsd", aprsd.__version__) + if result: + # Looks like there is an updated version. + return 1, result + else: + return 0, "APRSD is up to date" + except Exception: + # probably can't get in touch with pypi for some reason + # Lets put up an error and move on. We might not + # have internet in this aprsd deployment. + return 1, "Couldn't check for new version of APRSD" diff --git a/dev-requirements.txt b/dev-requirements.txt index e407088..5e0b938 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -12,15 +12,15 @@ appdirs==1.4.4 # virtualenv attrs==20.3.0 # via pytest -babel==2.9.0 +babel==2.9.1 # via sphinx -black==20.8b1 +black==21.4b2 # via -r dev-requirements.in bleach==3.3.0 # via readme-renderer certifi==2020.12.5 # via requests -cffi==1.14.4 +cffi==1.14.5 # via cryptography cfgv==3.2.0 # via pre-commit @@ -32,9 +32,9 @@ click==7.1.2 # pip-tools colorama==0.4.4 # via twine -coverage==5.3.1 +coverage==5.5 # via pytest-cov -cryptography==3.3.2 +cryptography==3.4.7 # via secretstorage distlib==0.3.1 # via virtualenv @@ -48,19 +48,23 @@ filelock==3.0.12 # virtualenv flake8-polyfill==1.0.2 # via pep8-naming -flake8==3.8.4 +flake8==3.9.1 # via # -r dev-requirements.in # flake8-polyfill -identify==2.2.2 +identify==2.2.4 # via pre-commit idna==2.10 # via requests imagesize==1.2.0 # via sphinx +importlib-metadata==4.0.1 + # via + # keyring + # twine iniconfig==1.1.1 # via pytest -isort==5.7.0 +isort==5.8.0 # via -r dev-requirements.in jeepney==0.6.0 # via @@ -68,7 +72,7 @@ jeepney==0.6.0 # secretstorage jinja2==2.11.3 # via sphinx -keyring==21.8.0 +keyring==23.0.1 # via twine markupsafe==1.1.1 # via jinja2 @@ -78,11 +82,11 @@ mypy-extensions==0.4.3 # via # black # mypy -mypy==0.790 +mypy==0.812 # via -r dev-requirements.in -nodeenv==1.5.0 +nodeenv==1.6.0 # via pre-commit -packaging==20.8 +packaging==20.9 # via # bleach # pytest @@ -94,45 +98,45 @@ pep517==0.10.0 # via pip-tools pep8-naming==0.11.1 # via -r dev-requirements.in -pip-tools==6.0.1 +pip-tools==6.1.0 # via -r dev-requirements.in -pkginfo==1.6.1 +pkginfo==1.7.0 # via twine pluggy==0.13.1 # via # pytest # tox -pre-commit==2.11.1 +pre-commit==2.12.1 # via -r dev-requirements.in py==1.10.0 # via # pytest # tox -pycodestyle==2.6.0 +pycodestyle==2.7.0 # via flake8 pycparser==2.20 # via cffi -pyflakes==2.2.0 +pyflakes==2.3.1 # via flake8 -pygments==2.7.4 +pygments==2.9.0 # via # readme-renderer # sphinx pyparsing==2.4.7 # via packaging -pytest-cov==2.10.1 +pytest-cov==2.11.1 # via -r dev-requirements.in -pytest==6.2.1 +pytest==6.2.3 # via # -r dev-requirements.in # pytest-cov -pytz==2020.5 +pytz==2021.1 # via babel pyyaml==5.4.1 # via pre-commit -readme-renderer==28.0 +readme-renderer==29.0 # via twine -regex==2020.11.13 +regex==2021.4.4 # via black requests-toolbelt==0.9.1 # via twine @@ -143,18 +147,17 @@ requests==2.25.1 # twine rfc3986==1.4.0 # via twine -secretstorage==3.3.0 +secretstorage==3.3.1 # via keyring six==1.15.0 # via # bleach - # cryptography # readme-renderer # tox # virtualenv -snowballstemmer==2.0.0 +snowballstemmer==2.1.0 # via sphinx -sphinx==3.4.3 +sphinx==3.5.4 # via -r dev-requirements.in sphinxcontrib-applehelp==1.0.2 # via sphinx @@ -175,28 +178,26 @@ toml==0.10.2 # pre-commit # pytest # tox -tox==3.21.0 +tox==3.23.0 # via -r dev-requirements.in -tqdm==4.55.1 +tqdm==4.60.0 # via twine -twine==3.3.0 +twine==3.4.1 # via -r dev-requirements.in -typed-ast==1.4.2 - # via - # black - # mypy -typing-extensions==3.7.4.3 - # via - # black - # mypy +typed-ast==1.4.3 + # via mypy +typing-extensions==3.10.0.0 + # via mypy urllib3==1.26.4 # via requests -virtualenv==20.4.0 +virtualenv==20.4.4 # via # pre-commit # tox webencodings==0.5.1 # via bleach +zipp==3.4.1 + # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: # pip diff --git a/requirements.in b/requirements.in index 9f5a0c3..3a6f437 100644 --- a/requirements.in +++ b/requirements.in @@ -9,9 +9,12 @@ opencage pluggy pbr pyyaml -py3-validate-email +# Allowing a newer version can lead to a conflict with +# requests. +py3-validate-email==0.2.16 pytz requests six thesmuggler yfinance +update_checker diff --git a/requirements.txt b/requirements.txt index 2d8909e..86e7e32 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ backoff==1.10.0 # via opencage certifi==2020.12.5 # via requests -cffi==1.14.4 +cffi==1.14.5 # via cryptography chardet==4.0.0 # via requests @@ -21,7 +21,7 @@ click==7.1.2 # -r requirements.in # click-completion # flask -cryptography==3.3.2 +cryptography==3.4.7 # via pyopenssl dnspython==2.1.0 # via py3-validate-email @@ -29,7 +29,7 @@ filelock==3.0.12 # via py3-validate-email flask-classful==0.14.2 # via -r requirements.in -flask-httpauth==4.2.0 +flask-httpauth==4.3.0 # via -r requirements.in flask==1.1.2 # via @@ -54,19 +54,19 @@ markupsafe==1.1.1 # via jinja2 multitasking==0.0.9 # via yfinance -numpy==1.20.1 +numpy==1.20.2 # via # pandas # yfinance opencage==1.2.2 # via -r requirements.in -pandas==1.2.2 +pandas==1.2.4 # via yfinance -pbr==5.5.1 +pbr==5.6.0 # via -r requirements.in pluggy==0.13.1 # via -r requirements.in -py3-validate-email==0.2.12 +py3-validate-email==0.2.16 # via -r requirements.in pycparser==2.20 # via cffi @@ -74,7 +74,7 @@ pyopenssl==20.0.1 # via opencage python-dateutil==2.8.1 # via pandas -pytz==2020.5 +pytz==2021.1 # via # -r requirements.in # pandas @@ -84,23 +84,25 @@ requests==2.25.1 # via # -r requirements.in # opencage + # update-checker # yfinance -shellingham==1.3.2 +shellingham==1.4.0 # via click-completion six==1.15.0 # via # -r requirements.in # click-completion - # cryptography # imapclient # opencage # pyopenssl # python-dateutil thesmuggler==1.0.1 # via -r requirements.in +update-checker==0.18.0 + # via -r requirements.in urllib3==1.26.4 # via requests werkzeug==1.0.1 # via flask -yfinance==0.1.55 +yfinance==0.1.59 # via -r requirements.in