Skip to content

Commit

Permalink
Merge pull request #26 from jurraca/add-version-check
Browse files Browse the repository at this point in the history
Add ./check to print out useful current versions
  • Loading branch information
fjahr authored Nov 13, 2024
2 parents 127be34 + 68abd95 commit 8df428e
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 46 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ $ pip3 install -r requirements.txt

Kartograf has not been tested on Windows.

#### Environment check

To check whether you have all the dependencies required to use Kartograf, you can run the following from the root of the project directory:

```
python check.py
```

## Usage

### Building IP prefix to ASN maps
Expand Down
58 changes: 58 additions & 0 deletions check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import sys
import re
from importlib.metadata import distribution, PackageNotFoundError

from kartograf.util import check_compatibility

CHECK_MARK = "\U00002705"
CROSS_MARK = "\U0000274C"

def __print_with_format(name, version, success, error_msg=None):
col1 = f"{name} version:"
col2 = f"{CHECK_MARK} OK" if success else CROSS_MARK
col3 = "" if success else f"{error_msg}"
return print(f"{col1:25} {col2:5} ({version}) {col3}")

def __read_requirements_txt():
with open("requirements.txt", "r") as f:
package_versions = {}
pattern = r"^(.*?)(>=|==)(.*)$"
for line in f.readlines():
match = re.match(pattern, line)
if match:
package_versions[match.group(1)] = match.group(3)
return package_versions

def rpki_version():
try:
check_compatibility()
except RuntimeError as e:
print(e)

def python_version():
min_version = (3, 10)
sys_version = sys.version_info
result = sys_version >= min_version
__print_with_format(
"Python",
f"{sys_version.major}.{sys_version.minor}",
result)

def installed_packages():
required_packages = __read_requirements_txt()
for package, min_version in required_packages.items():
try:
dist = distribution(package)
result = dist.version >= min_version
__print_with_format(package, dist.version, result)
except PackageNotFoundError:
__print_with_format(package, None, False, "Not Found!")


def check_all():
rpki_version()
python_version()
installed_packages()

if __name__ == "__main__":
check_all()
39 changes: 25 additions & 14 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,28 @@
license = licenses.bsd3;
};
};

rpki-client = rpki-cli.defaultPackage.${system};
pythonBuildDeps = pkgs.python311.withPackages (ps: [
ps.beautifulsoup4
ps.numpy
ps.pandas
ps.requests
ps.tqdm
pandarallel
]);
pythonDevDeps = pkgs.python311.withPackages (ps: [
ps.beautifulsoup4
ps.numpy
ps.pandas
ps.requests
ps.tqdm
pandarallel
]);
kartografDeps = [
rpki-cli.defaultPackage.${system}
(pkgs.python311.withPackages (ps: [
ps.pandas
ps.beautifulsoup4
ps.numpy
ps.requests
ps.tqdm
pandarallel
]))
pythonBuildDeps
rpki-client
];

in {
# This flake exposes the following attributes:
# * A development shell containing the rpki-client and the necessary
Expand All @@ -58,16 +68,17 @@
# * A default/kartograf package
# * A NixOS module
devShells.default = pkgs.mkShell {
packages = kartografDeps;
packages = [rpki-client pythonDevDeps];
};
packages = {
kartograf = pkgs.stdenv.mkDerivation { # not a python-installable package, so just manually copy files
kartograf = pkgs.stdenv.mkDerivation {
# not a python-installable package, so just manually copy files
pname = "kartograf";
version = "1.0.0";
src = ./.;
nativeBuildInputs = [ pkgs.makeWrapper ];
nativeBuildInputs = [pkgs.makeWrapper];
buildInputs = kartografDeps;
propagatedBuildInputs = [ rpki-cli.defaultPackage.${system} ];
propagatedBuildInputs = [rpki-client];
buildPhase = ''
mkdir -p $out/lib/kartograf
cp -r ${./kartograf}/* $out/lib/kartograf/
Expand Down
80 changes: 48 additions & 32 deletions kartograf/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import subprocess
import time

RPKI_VERSION = 9.3


def calculate_sha256(file_path):
sha256_hash = hashlib.sha256()
Expand Down Expand Up @@ -53,41 +55,47 @@ def rir_from_str(maybe_rir):
raise Exception("No RIR found in String")


def check_compatibility():
exception_msg = "Could not determine rpki-client version. Is it installed?"

def get_rpki_local_version():
"""Return the rpki-client version in the user's path"""
try:
result = subprocess.run(['rpki-client', '-V'],
capture_output=True,
text=True,
check=True)
result = subprocess.run(
["rpki-client", "-V"], capture_output=True, text=True, check=True
)

# On OpenBSD the result should include 'rpki-client', everywhere else
# it should be 'rpki-client-portable'.
version_match = re.search(r'rpki-client(?:-portable)? (\d+\.\d+)',
result.stderr)
version_match = re.search(
r"rpki-client(?:-portable)? (\d+\.\d+)", result.stderr
)
if version_match:
version = version_match.group(1)
version_number = float(version)
latest_version = 9.3
return float(version)
return None

if version_number < 8.4:
raise Exception("Error: rpki-client version 8.4 or higher is "
"required.")
except FileNotFoundError:
return None

if version_number == latest_version:
print(f"Using rpki-client version {version} (recommended).")
elif version_number > latest_version:
print("Warning: This kartograf version has not been tested with "
f"rpki-client versions higher than {latest_version}.")
else:
print(f"Using rpki-client version {version}. Please beware that running with the latest tested version ({latest_version}) is recommend.")

else:
raise Exception(exception_msg)

except subprocess.CalledProcessError:
raise Exception(exception_msg)
def check_compatibility():
local_version = get_rpki_local_version()
latest_version = RPKI_VERSION

if local_version is None:
raise RuntimeError("Could not determine rpki-client version. Is it installed?")
if local_version < 8.4:
raise Exception("Error: rpki-client version 8.4 or higher is required.")

if local_version == latest_version:
print(f"Using rpki-client version {local_version} (recommended).")
elif local_version > latest_version:
print(
"Warning: This kartograf version has not been tested with "
f"rpki-client versions higher than {latest_version}."
)
else:
print(
f"Using rpki-client version {local_version}. Please beware that running with the latest tested version ({latest_version}) is recommend."
)


def wait_for_launch(wait):
Expand All @@ -104,13 +112,21 @@ def wait_for_launch(wait):
days, remainder = divmod(remaining, 86400)
hours, remainder = divmod(remainder, 3600)
minutes, seconds = divmod(remainder, 60)
days, hours, minutes, seconds = int(days), int(hours), int(minutes), int(seconds)
days, hours, minutes, seconds = (
int(days),
int(hours),
int(minutes),
int(seconds),
)

# Print the countdown, using '\r' to remain on the same line
print(f"Countdown:{'' if days <= 0 else ' ' + str(days) + ' day(s),'}"
f"{'' if hours <= 0 else ' ' + str(hours) + ' hour(s),'}"
f"{'' if minutes <= 0 else ' ' + str(minutes) + ' minute(s),'}"
f" {seconds} second(s)".ljust(80), end='\r')
print(
f"Countdown:{'' if days <= 0 else ' ' + str(days) + ' day(s),'}"
f"{'' if hours <= 0 else ' ' + str(hours) + ' hour(s),'}"
f"{'' if minutes <= 0 else ' ' + str(minutes) + ' minute(s),'}"
f" {seconds} second(s)".ljust(80),
end="\r",
)

time.sleep(1)

Expand All @@ -121,7 +137,7 @@ def format_pfx(pfx):
which can cause problems.
"""
try:
if '/' in pfx:
if "/" in pfx:
formatted_pfx = str(ipaddress.ip_network(pfx))
return f"{formatted_pfx}"
return str(ipaddress.ip_address(pfx))
Expand Down

0 comments on commit 8df428e

Please sign in to comment.