guanghu-ice-heart/server-tools/hololake-code-channel/jd-candidate/prepare-owner-identity-source.py

99 lines
3.2 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""Create a one-user SQLite handoff without exposing the legacy database to HLCC."""
from __future__ import annotations
import argparse
import json
import os
import pathlib
import pwd
import sqlite3
import tempfile
OWNER_NAME = "bingshuo"
def prepare(source: pathlib.Path, destination: pathlib.Path, owner: str) -> None:
if not source.is_file():
raise RuntimeError("legacy database unavailable")
destination.parent.mkdir(parents=True, exist_ok=True)
legacy = sqlite3.connect(f"file:{source}?mode=ro", uri=True, timeout=15)
try:
schema = legacy.execute(
"select sql from sqlite_master where type = 'table' and name = 'user'"
).fetchone()
row = legacy.execute(
"select * from user where lower_name = ?",
(OWNER_NAME,),
).fetchall()
if not schema or not schema[0] or len(row) != 1:
raise RuntimeError("legacy owner identity mismatch")
file_descriptor, temporary_name = tempfile.mkstemp(
prefix=".owner-identity-source.",
suffix=".db",
dir=destination.parent,
)
os.close(file_descriptor)
temporary = pathlib.Path(temporary_name)
try:
handoff = sqlite3.connect(temporary)
try:
handoff.execute(schema[0])
columns = [item[1] for item in legacy.execute("pragma table_info(user)")]
placeholders = ",".join("?" for _column in columns)
column_sql = ",".join(f'"{column}"' for column in columns)
handoff.execute(
f"insert into user ({column_sql}) values ({placeholders})",
row[0],
)
handoff.commit()
finally:
handoff.close()
temporary.chmod(0o600)
identity = pwd.getpwnam(owner)
os.chown(temporary, identity.pw_uid, identity.pw_gid)
temporary.replace(destination)
finally:
temporary.unlink(missing_ok=True)
finally:
legacy.close()
receipt = destination.with_suffix(".receipt.json")
receipt.write_text(
json.dumps(
{
"schema": "guanghu.hlcc-owner-identity-handoff/v1",
"owner": OWNER_NAME,
"rows": 1,
"contains_repository_data": False,
"contains_access_tokens": False,
"result": "PREPARED",
},
ensure_ascii=False,
indent=2,
)
+ "\n",
encoding="utf-8",
)
identity = pwd.getpwnam(owner)
os.chown(receipt, identity.pw_uid, identity.pw_gid)
receipt.chmod(0o600)
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--source", required=True, type=pathlib.Path)
parser.add_argument("--destination", required=True, type=pathlib.Path)
parser.add_argument("--owner", default="guanghu")
arguments = parser.parse_args()
prepare(arguments.source, arguments.destination, arguments.owner)
print("OWNER_IDENTITY_SOURCE_PREPARED rows=1 tokens=0 repositories=0")
if __name__ == "__main__":
main()