-
Notifications
You must be signed in to change notification settings - Fork 29
/
reel2reel.py
129 lines (90 loc) · 3.13 KB
/
reel2reel.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
"""
Reel2Reel - a script to move a database from one Postgres
server to to another because we like to move it, move it.
Usage:
python3 reel2reel.py <Source URL> <Destination URL>
or interactively:
python3 reel2reel.py
Matt Rudge
Code Institute
October, 2022
"""
import os
import re
import sys
from urllib.parse import urlparse
def split_url(db_url):
"""
Performs checks on the URL for completeness and then
parses it using urllib
"""
if db_url[0:11] != "postgres://" and db_url[0:13] != "postgresql://":
print("Error: The URL seems incorrectly formatted.")
sys.exit(1)
e = urlparse(db_url)
if not e.hostname or not e.username or not e.password or not e.path:
print("Error: The URL seems incorrectly formatted.")
sys.exit(1)
return e
def parse_dump(h_user, h_db, e_user, e_db):
"""
Takes the dumped SQL file and replaces the database details
with the new user and database
"""
with open("dump.sql", "r", encoding="utf8") as f:
data = f.read()
data = re.sub(h_user, e_user, data)
data = re.sub(h_db, e_db, data)
with open("dump.sql", "w", encoding="utf8") as f:
# Why not just open the file as r+ earlier and
# f.seek(0) to the beginning? Because not all of the
# file would get overwritten.
f.write(data)
def do_source(s):
"""
Performs the dump of the source data
"""
os.environ["PGPASSWORD"] = s.password
print("Extracting the source database.")
res = os.system(f"pg_dump --host={s.hostname} \
--username={s.username} --dbname={s.path[1:]} -w > dump.sql")
if res != 0:
print("Error: Cannot connect to source database server.")
sys.exit(2)
print("Extraction successful. File saved to dump.sql.")
def do_dest(d):
"""
Uploads the modified data to the destination server
"""
print("Uploading to destination server")
os.environ["PGPASSWORD"] = d.password
res = os.system(f"psql --host={d.hostname} --username={d.username} \
--dbname={d.path[1:]} -w < dump.sql >/dev/null 2>&1")
if res != 0:
print("Error: Cannot upload the data to destination.")
sys.exit(2)
print("Upload complete. Please check your destination database.")
def main(s_url, d_url):
"""
The main function. Calls other functions to perform the migration
"""
s = split_url(s_url)
d = split_url(d_url)
do_source(s)
print("Modifying the downloaded data.")
parse_dump(s.username, s.path[1:], d.username, d.path[1:])
do_dest(d)
if __name__ == "__main__":
print("Reel2Reel - PostgreSQL to PostgreSQL Mover")
print("Code Institute, 2022\n")
if len(sys.argv) == 2:
print("You can supply the source and destination URLs as arguments")
print("Usage: python3 reel2reel.py <Source DB URL> <Destination DB URL>")
sys.exit(1)
if len(sys.argv) > 1:
source = sys.argv[1]
dest = sys.argv[2]
else:
source = input("Paste your source DATABASE_URL here: ")
dest = input("Paste your destination DATABASE_URL here: ")
main(source, dest)