Create client to convert json to web requests

This commit is contained in:
George Lacey 2021-05-08 10:51:12 +01:00
parent 3babf80a3b
commit 1362410ae6
8 changed files with 220 additions and 0 deletions

0
borg-client/__init__.py Normal file
View File

50
borg-client/borgclient.py Normal file
View File

@ -0,0 +1,50 @@
import requests
class BorgClient(object):
def __init__(self, url: str, username: str, password: str):
self.url = url
self.client = requests.Session()
self.referer = self.url
self.username = username
self.password = password
self.__login()
def __login(self):
url = f"{self.url}/accounts/login/"
post_data = {
"username": self.username,
"password": self.password,
}
return self.__post(url, post_data).text
def __post(self, url, post_data):
self.client.get(url=url, verify=False)
csrf_token = self.client.cookies['csrftoken']
post_data['csrfmiddlewaretoken'] = csrf_token
headers = dict(self.client.headers)
headers['X-CSRFToken'] = csrf_token
headers['Referer'] = self.referer
post_responce = self.client.post(url=url, data=post_data, headers=headers,
verify=False)
return post_responce
def post_error(self, post_data):
url = f"{self.url}/error"
return self.__post(url, post_data).text
def post_repo(self, post_data):
url = f"{self.url}/repo"
return self.__post(url, post_data).text
def post_archive_and_cache(self, post_data):
url = f"{self.url}/archive"
return self.__post(url, post_data).text

40
borg-client/main.py Normal file
View File

@ -0,0 +1,40 @@
from borgclient import BorgClient
from sys import stdin
import argparse
from tables import Error, Repo, Archive, Cache
import json
from datetime import datetime
def main(args):
borg_output = " ".join(stdin.readlines())
if not (args.label and args.username and args.password and args.url):
raise Exception("Supply label, username, password and url")
else:
client = BorgClient(url=args.url, username=args.username, password=args.password)
try:
borg_json = json.loads(borg_output)
repo = Repo.from_json(borg_json['repository'])
archive = Archive.from_json(borg_json['archive'])
cache = Cache.from_json(borg_json['cache']['stats'])
client.post_repo(repo.get_dict(args.label))
archive_cache = archive.get_dict(args.label)
archive_cache.update(cache.get_dict(args.label))
client.post_archive_and_cache(archive_cache)
except json.JSONDecodeError:
error = Error(borg_output, datetime.utcnow())
client.post_error(error.get_dict(args.label))
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument("-l", "--label", help="Repo Label", type=str, required=True)
parser.add_argument("-u", "--username", help="Username", type=str, required=True)
parser.add_argument("-p", "--password", help="Password", type=str, required=True)
parser.add_argument("-w", "--url", help="Server Url", type=str, required=True)
return parser.parse_args()
if __name__ == "__main__":
main(get_args())

View File

@ -0,0 +1,4 @@
from .error import Error
from .repo import Repo
from .archive import Archive
from .cache import Cache

View File

@ -0,0 +1,44 @@
from datetime import datetime, timezone
class Archive(object):
def __init__(self, fingerprint: str, name: str, start: datetime, end: datetime, file_count: int, original_size: int,
compressed_size: int, deduplicated_size: int):
self.fingerprint = fingerprint
self.name = name
self.start = start
self.end = end
self.file_count = file_count
self.original_size = original_size
self.compressed_size = compressed_size
self.deduplicated_size = deduplicated_size
@classmethod
def from_json(cls, json: dict):
fingerprint = json['id']
name = json['name']
start = datetime.fromisoformat(json['start']).astimezone(tz=timezone.utc).replace(tzinfo=None)
end = datetime.fromisoformat(json['end']).astimezone(tz=timezone.utc).replace(tzinfo=None)
stats_json = json['stats']
file_count = stats_json['nfiles']
original_size = stats_json['original_size']
compressed_size = stats_json['compressed_size']
deduplicated_size = stats_json['deduplicated_size']
return cls(fingerprint, name, start, end, file_count, original_size, compressed_size, deduplicated_size)
def get_dict(self, label):
if not label.strip():
raise Exception("No label supplied")
return {
"label": label,
"fingerprint": self.fingerprint,
"name": self.name,
"start": self.start.isoformat(),
"end": self.end.isoformat(),
"file_count": self.file_count,
"original_size": self.original_size,
"compressed_size": self.compressed_size,
"deduplicated_size": self.deduplicated_size
}

View File

@ -0,0 +1,36 @@
from datetime import datetime, timezone
from pathlib import Path
class Cache(object):
def __init__(self, total_chunks: int, total_csize: int, total_size: int, total_unique_chunks: int,
unique_csize: int, unique_size: int):
self.total_chunks = total_chunks
self.total_csize = total_csize
self.total_size = total_size
self.total_unique_chunks = total_unique_chunks
self.unique_csize = unique_csize
self.unique_size = unique_size
@classmethod
def from_json(cls, json: dict):
total_chunks = json['total_chunks']
total_csize = json['total_csize']
total_size = json['total_size']
total_unique_chunks = json['total_unique_chunks']
unique_csize = json['unique_csize']
unique_size = json['unique_size']
return cls(total_chunks, total_csize, total_size, total_unique_chunks, unique_csize, unique_size)
def get_dict(self, label):
if not label.strip():
raise Exception("No label supplied")
return {
"label": label,
"total_chunks": self.total_chunks,
"total_csize": self.total_csize,
"total_size": self.total_size,
"total_unique_chunks": self.total_unique_chunks,
"unique_csize": self.unique_csize,
"unique_size": self.unique_size
}

View File

@ -0,0 +1,18 @@
from datetime import datetime
class Error(object):
def __init__(self, error: str, time: datetime):
self.error = error.strip()
if not self.error:
self.error = "No error information supplied"
self.time = time
def get_dict(self, label):
if not label.strip():
raise Exception("No label supplied")
return {
"label": label,
"error": self.error.strip(),
"time": self.time.isoformat()
}

View File

@ -0,0 +1,28 @@
from datetime import datetime, timezone
from pathlib import Path
class Repo(object):
def __init__(self, fingerprint: str, location, last_modified: datetime):
self.fingerprint = fingerprint
self.location = location
self.last_modified = last_modified
@classmethod
def from_json(cls, json: dict):
uuid = json['id']
location = Path(json['location'])
last_modified = datetime.fromisoformat(json['last_modified']) \
.astimezone(tz=timezone.utc) \
.replace(tzinfo=None)
return cls(uuid, location, last_modified)
def get_dict(self, label):
if not label.strip():
raise Exception("No label supplied")
return {
"label": label,
"fingerprint": self.fingerprint,
"location": self.location,
"last_modified": self.last_modified.isoformat()
}