Shows environment, count and an irreversibility warning, requires typing the confirmation word (plus the environment name on prod), backs every registration up through get-by-id before deleting and aborts the whole run if the backup cannot be completed.
87 lines
3.1 KiB
Python
87 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
||
"""Delete point alarm registrations listed in a CSV/TXT file, with confirmation and backup."""
|
||
|
||
from __future__ import annotations
|
||
|
||
import argparse
|
||
import logging
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
from common import ApiError, ConfigurationError, IklimClient, configure_logging
|
||
from point_alarm import (
|
||
PointAlarmService,
|
||
PointUnregisterProcessor,
|
||
read_id_list,
|
||
timestamped_path,
|
||
write_records,
|
||
)
|
||
|
||
|
||
BASE_DIR = Path(__file__).resolve().parent
|
||
|
||
|
||
def parse_args() -> argparse.Namespace:
|
||
parser = argparse.ArgumentParser(
|
||
description=(
|
||
"Dosyadaki registrationId'leri siler (DELETE /v1/alarms/points/unregister/{id}). "
|
||
"Girdi CSV (registrationId sütunu) veya TXT (satır başına bir ID). Başlamadan önce "
|
||
"ortam, silinecek sayı ve 'geri alınamaz' uyarısı gösterilir; onay için SİL yazılmalıdır "
|
||
"(prod ortamında ek olarak 'prod' yazılır). Bir hesabın son kaydı silinirse webhook da "
|
||
"silinir. Silmeden önce her kayıt get-by-id ile yedeklenir; yedek yazılamazsa hiçbir "
|
||
"kayıt silinmez."
|
||
)
|
||
)
|
||
parser.add_argument("input_file", type=Path, help="ID listesi (.csv veya .txt)")
|
||
parser.add_argument(
|
||
"--backup",
|
||
type=Path,
|
||
default=BASE_DIR / "nowcast-point-unregister-backup.csv",
|
||
help="Yedek dosyası (.csv/.txt, zaman soneki eklenir; varsayılan: nowcast-point-unregister-backup.csv)",
|
||
)
|
||
parser.add_argument("--no-backup", action="store_true", help="Silmeden önce yedek almayı kapatır")
|
||
parser.add_argument(
|
||
"--output",
|
||
type=Path,
|
||
help="Sonuç dosyası (.csv/.txt, zaman soneki eklenir); verilmezse yalnızca özet yazılır",
|
||
)
|
||
parser.add_argument(
|
||
"--debug-log",
|
||
type=Path,
|
||
default=BASE_DIR / "logs" / "iklim-api-debug.log",
|
||
help="Maskelenmiş HTTP debug log dosyası",
|
||
)
|
||
return parser.parse_args()
|
||
|
||
|
||
def main() -> int:
|
||
args = parse_args()
|
||
configure_logging(args.debug_log)
|
||
try:
|
||
ids = read_id_list(args.input_file, "registrationId")
|
||
client = IklimClient.from_env(BASE_DIR / ".env")
|
||
processor = PointUnregisterProcessor(
|
||
PointAlarmService(client),
|
||
ids=ids,
|
||
environment=client.settings.environment,
|
||
base_url=client.settings.base_url,
|
||
backup_path=None if args.no_backup else timestamped_path(args.backup),
|
||
)
|
||
results = processor.run()
|
||
if not results:
|
||
return 1
|
||
failed = sum(1 for row in results if row["status"] == "FAILED")
|
||
print(f"{len(results) - failed} silindi, {failed} başarısız.")
|
||
if args.output:
|
||
path = timestamped_path(args.output)
|
||
write_records(path, results, [], columns=["registrationId", "status", "httpStatus", "errorBody"])
|
||
print(f"Sonuçlar yazıldı: {path.resolve()}")
|
||
return 1 if failed else 0
|
||
except (ConfigurationError, ApiError, OSError) as exc:
|
||
logging.error("İşlem durduruldu: %s", exc)
|
||
return 1
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|