Skip to content

Commit 2213b70

Browse files
authored
Merge pull request #72 from open-metadata/ayush-shah-patch-1
Add script to hard-delete soft-deleted tables
2 parents 1d28ece + e8a072a commit 2213b70

1 file changed

Lines changed: 81 additions & 0 deletions

File tree

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#!/usr/bin/env python3
2+
"""Hard-delete soft-deleted table entities via the OpenMetadata REST API.
3+
4+
Dry-run by default. Pass --execute to actually delete.
5+
"""
6+
import argparse
7+
import os
8+
import sys
9+
10+
import requests
11+
12+
13+
def parse_args():
14+
parser = argparse.ArgumentParser(description="Hard-delete soft-deleted OM tables.")
15+
parser.add_argument("--host", default="http://localhost:8585", help="OM server base URL")
16+
parser.add_argument("--token", default=os.environ.get("OM_TOKEN"), help="JWT Bearer token")
17+
parser.add_argument("--page-size", type=int, default=100, help="Search page size")
18+
parser.add_argument("--execute", action="store_true", help="Actually delete (default: dry-run)")
19+
return parser.parse_args()
20+
21+
22+
def fetch_deleted_tables(host, headers, page_size):
23+
"""Yield (id, fqn) for every soft-deleted table via the tables REST API."""
24+
after = None
25+
while True:
26+
params = {"include": "deleted", "limit": page_size}
27+
if after:
28+
params["after"] = after
29+
30+
resp = requests.get(
31+
f"{host}/api/v1/tables",
32+
headers=headers,
33+
params=params,
34+
timeout=30,
35+
)
36+
if not resp.ok:
37+
print(f"[ERROR] List failed: {resp.status_code} {resp.text}")
38+
sys.exit(1)
39+
40+
body = resp.json()
41+
for table in body.get("data", []):
42+
yield table.get("id"), table.get("fullyQualifiedName")
43+
44+
after = body.get("paging", {}).get("after")
45+
if not after:
46+
break
47+
48+
49+
def main():
50+
args = parse_args()
51+
52+
if not args.token:
53+
print("[ERROR] No token provided. Use --token or set OM_TOKEN.")
54+
sys.exit(1)
55+
56+
headers = {"Authorization": f"Bearer {args.token}"}
57+
dry_run = not args.execute
58+
count = 0
59+
60+
for table_id, fqn in fetch_deleted_tables(args.host, headers, args.page_size):
61+
count += 1
62+
if dry_run:
63+
print(f"[DRY-RUN] Would delete: {fqn} ({table_id})")
64+
else:
65+
resp = requests.delete(
66+
f"{args.host}/api/v1/tables/{table_id}",
67+
headers=headers,
68+
params={"hardDelete": "true", "recursive": "false"},
69+
timeout=30,
70+
)
71+
if resp.ok:
72+
print(f"[DELETED] {fqn} ({table_id})")
73+
else:
74+
print(f"[ERROR] {fqn}: {resp.status_code} {resp.text}")
75+
76+
qualifier = "would be " if dry_run else ""
77+
print(f"\nDone. {count} tables {qualifier}deleted.")
78+
79+
80+
if __name__ == "__main__":
81+
main()

0 commit comments

Comments
 (0)