Add automatic DB migration between any 1.5.x version and the latest one

This commit is contained in:
Théophile Diot 2024-01-05 16:48:59 +00:00
parent 6d5a6a9b90
commit 7e0d9c78be
No known key found for this signature in database
GPG key ID: 248FEA4BAE400D06
3 changed files with 54 additions and 33 deletions

View file

@ -250,15 +250,18 @@ class Database:
"""Initialize the database"""
with self.__db_session() as session:
try:
session.add(
Metadata(
is_initialized=True,
first_config_saved=False,
scheduler_first_start=True,
version=version,
integration=integration,
if session.query(Metadata).get(1):
session.query(Metadata).filter_by(id=1).update({Metadata.version: version, Metadata.integration: integration})
else:
session.add(
Metadata(
is_initialized=True,
first_config_saved=False,
scheduler_first_start=True,
version=version,
integration=integration,
)
)
)
session.commit()
except BaseException:
return format_exc()
@ -332,19 +335,38 @@ class Database:
return ""
def init_tables(self, default_plugins: List[dict]) -> Tuple[bool, str]:
def init_tables(self, default_plugins: List[dict], bunkerweb_version: str) -> Tuple[bool, str]:
"""Initialize the database tables and return the result"""
inspector = inspect(self.__sql_engine)
if len(Base.metadata.tables.keys()) <= len(inspector.get_table_names()):
has_all_tables = True
db_version = None
has_all_tables = True
if inspector and len(inspector.get_table_names()):
db_version = self.get_metadata()["version"]
for table in Base.metadata.tables:
if not inspector.has_table(table):
has_all_tables = False
break
if db_version != bunkerweb_version:
self.__logger.warning(f"Database version ({db_version}) is different from Bunkerweb version ({bunkerweb_version}), checking if it needs to be updated")
for table in Base.metadata.tables:
if not inspector.has_table(table):
has_all_tables = False
else:
missing_columns = []
if has_all_tables:
return False, ""
db_columns = inspector.get_columns(table)
for column in Base.metadata.tables[table].columns:
if not any(db_column["name"] == column.name for db_column in db_columns):
missing_columns.append(column)
try:
with self.__db_session() as session:
if missing_columns:
for column in missing_columns:
session.execute(text(f"ALTER TABLE {table} ADD COLUMN {column.name} {column.type}"))
session.commit()
except BaseException:
return False, format_exc()
if has_all_tables and db_version and db_version == bunkerweb_version:
return False, ""
try:
Base.metadata.create_all(self.__sql_engine, checkfirst=True)

View file

@ -258,7 +258,7 @@ class Users(Base):
username = Column(String(256), nullable=False, unique=True)
password = Column(String(60), nullable=False)
is_two_factor_enabled = Column(Boolean, nullable=False, default=False)
secret_token = Column(String(32), nullable=True, unique=True)
secret_token = Column(String(32), nullable=True, unique=True, default=None)
method = Column(METHODS_ENUM, nullable=False, default="manual")

View file

@ -271,6 +271,8 @@ if __name__ == "__main__":
)
config_files = config.get_config()
bunkerweb_version = Path(sep, "usr", "share", "bunkerweb", "VERSION").read_text().strip()
if not db.is_initialized():
logger.info(
"Database not initialized, initializing ...",
@ -280,7 +282,8 @@ if __name__ == "__main__":
config.get_settings(),
config.get_plugins("core"),
config.get_plugins("external"),
]
],
bunkerweb_version,
)
# Initialize database tables
@ -295,19 +298,6 @@ if __name__ == "__main__":
)
else:
logger.info("Database tables initialized")
err = db.initialize_db(
version=Path(sep, "usr", "share", "bunkerweb", "VERSION").read_text().strip(),
integration=integration,
)
if err:
logger.error(
f"Can't Initialize database : {err}",
)
sys_exit(1)
else:
logger.info("Database initialized")
else:
logger.info("Database is already initialized, checking for changes ...")
@ -316,7 +306,8 @@ if __name__ == "__main__":
config.get_settings(),
config.get_plugins("core"),
config.get_plugins("external"),
]
],
bunkerweb_version,
)
if not ret and err:
@ -327,6 +318,14 @@ if __name__ == "__main__":
else:
logger.info("Database tables successfully updated")
err = db.initialize_db(version=bunkerweb_version, integration=integration)
if err:
logger.error(f"Can't update database metadata : {err}")
sys_exit(1)
else:
logger.info("Database metadata successfully updated")
if args.init:
sys_exit(0)