majuna/app/cli/db.py

97 lines
3.2 KiB
Python
Raw Normal View History

2022-04-22 12:52:41 +01:00
import argparse
import csv
import datetime
import logging
import sys
2022-05-16 11:44:03 +01:00
from typing import TYPE_CHECKING, Any
2022-04-22 12:52:41 +01:00
from app import app
from app.extensions import db
2022-04-22 14:29:24 +01:00
from app.models.base import Group, MirrorList
2022-05-06 12:28:11 +01:00
from app.models.bridges import Bridge, BridgeConf
2022-04-22 14:29:24 +01:00
from app.models.mirrors import Mirror, Origin, Proxy
2022-04-22 14:45:47 +01:00
from app.models.alarms import Alarm, AlarmState
2022-04-22 12:52:41 +01:00
2022-05-16 11:44:03 +01:00
if TYPE_CHECKING:
_SubparserType = argparse._SubParsersAction[argparse.ArgumentParser]
else:
_SubparserType = Any
2022-04-22 12:52:41 +01:00
models = {
2022-05-06 12:28:11 +01:00
"bridge": Bridge,
"bridgeconf": BridgeConf,
2022-04-22 14:29:24 +01:00
"alarm": Alarm,
2022-04-22 12:52:41 +01:00
"group": Group,
2022-04-22 14:29:24 +01:00
"list": MirrorList,
"mirror": Mirror,
2022-04-22 12:52:41 +01:00
"origin": Origin,
2022-04-22 14:29:24 +01:00
"proxy": Proxy
2022-04-22 12:52:41 +01:00
}
2022-05-16 11:44:03 +01:00
def export(model: db.Model) -> None:
2022-04-22 12:52:41 +01:00
out = csv.writer(sys.stdout)
out.writerow(model.csv_header())
for r in model.query.all():
out.writerow(r.csv_row())
2022-05-16 11:44:03 +01:00
def impot(model: db.Model) -> None:
2022-04-22 12:52:41 +01:00
first = True
header = model.csv_header()
try:
for line in csv.reader(sys.stdin):
if first:
if line != header:
logging.error("CSV header mismatch")
sys.exit(1)
first = False
continue
x = model()
for i in range(len(header)):
if header[i] in ["added", "updated", "destroyed", "deprecated", "last_updated", "terraform_updated"]:
# datetime fields
2022-04-22 12:52:41 +01:00
if line[i] == "":
2022-05-16 11:44:03 +01:00
line[i] = None # type: ignore
2022-04-22 12:52:41 +01:00
else:
2022-05-16 11:44:03 +01:00
line[i] = datetime.datetime.strptime(line[i], "%Y-%m-%d %H:%M:%S.%f") # type: ignore
elif header[i] in ["eotk"]:
# boolean fields
2022-05-16 11:44:03 +01:00
line[i] = line[i] == "True" # type: ignore
elif header[i].endswith("_id") and line[i] == "":
# integer foreign keys
2022-05-16 11:44:03 +01:00
line[i] = None # type: ignore
2022-04-22 14:45:47 +01:00
elif header[i] in ["alarm_state"]:
# alarm states
line[i] = getattr(AlarmState, line[i][len("AlarmState."):])
2022-04-22 12:52:41 +01:00
setattr(x, header[i], line[i])
db.session.add(x)
db.session.commit()
logging.info("Import completed successfully")
except Exception as e:
logging.exception(e)
db.session.rollback()
class DbCliHandler:
@classmethod
2022-05-16 11:44:03 +01:00
def add_subparser_to(cls, subparsers: _SubparserType) -> None:
2022-04-22 12:52:41 +01:00
parser = subparsers.add_parser("db", help="database operations")
2022-04-22 14:30:53 +01:00
parser.add_argument("--export", choices=sorted(models.keys()),
2022-04-22 12:52:41 +01:00
help="export data to CSV format")
2022-04-22 14:30:53 +01:00
parser.add_argument("--import", choices=sorted(models.keys()),
2022-04-22 12:52:41 +01:00
help="import data from CSV format", dest="impot")
parser.set_defaults(cls=cls)
2022-05-16 11:44:03 +01:00
def __init__(self, args: argparse.Namespace) -> None:
2022-04-22 12:52:41 +01:00
self.args = args
2022-05-16 11:44:03 +01:00
def run(self) -> None:
2022-04-22 12:52:41 +01:00
with app.app_context():
if self.args.export:
export(models[self.args.export])
elif self.args.impot:
impot(models[self.args.impot])
else:
logging.error("No action requested")