1
- from urllib . parse import quote
1
+ from tempfile import mkstemp
2
2
import logging
3
+ import os
3
4
4
5
from .base import BaseCommandDBConnector
5
6
from .exceptions import DumpError
6
7
7
8
logger = logging .getLogger ('dbbackup.command' )
8
9
9
10
10
- def create_postgres_uri (self ):
11
- host = self .settings .get ('HOST' )
12
- if not host :
13
- raise DumpError ('A host name is required' )
11
+ class PgEnvWrapper :
12
+ def __init__ (self , settings ):
13
+ self .settings = settings
14
14
15
- dbname = self .settings .get ('NAME' ) or ''
16
- user = quote (self .settings .get ('USER' ) or '' )
17
- password = self .settings .get ('PASSWORD' ) or ''
18
- password = ':{}' .format (quote (password )) if password else ''
19
- if not user :
20
- password = ''
21
- else :
22
- host = '@' + host
15
+ def __enter__ (self ):
16
+ pghost = self .settings .get ('HOST' , None )
17
+ pgport = self .settings .get ('PORT' , None )
18
+ pguser = self .settings .get ('USER' , None )
19
+ pgdatabase = self .settings .get ('NAME' , None )
20
+ pgpassword = self .settings .get ('PASSWORD' , None )
23
21
24
- port = ':{}' .format (self .settings .get ('PORT' )) if self .settings .get ('PORT' ) else ''
25
- dbname = f'--dbname=postgresql://{ user } { password } { host } { port } /{ dbname } '
26
- return dbname
22
+ env = os .environ .copy ()
23
+ if pghost :
24
+ env ['PGHOST' ] = pghost
25
+ if pgport :
26
+ env ['PGPORT' ] = pgport
27
+ if pguser :
28
+ env ['PGUSER' ] = pguser
29
+ if pgdatabase :
30
+ env ['PGDATABASE' ] = pgdatabase
31
+
32
+ if pgpassword :
33
+ self .pgpass_fd , self .pgpass_path = mkstemp (text = True )
34
+ os .write (self .pgpass_fd , f'*:*:*:*:{ pgpassword } \n ' )
35
+ os .close (self .pgpass_fd )
36
+ env ['PGPASSFILE' ] = self .pgpass_path
37
+ else :
38
+ self .pgpass_fd , self .pgpass_path = None , None
39
+
40
+ return env
41
+
42
+ def __exit__ (self ):
43
+ os .unlink (self .pgpass_path )
27
44
28
45
29
46
class PgDumpConnector (BaseCommandDBConnector ):
@@ -39,28 +56,27 @@ class PgDumpConnector(BaseCommandDBConnector):
39
56
40
57
def _create_dump (self ):
41
58
cmd = '{} ' .format (self .dump_cmd )
42
- cmd = cmd + create_postgres_uri (self )
43
59
44
60
for table in self .exclude :
45
61
cmd += ' --exclude-table-data={}' .format (table )
46
62
if self .drop :
47
63
cmd += ' --clean'
48
64
49
65
cmd = '{} {} {}' .format (self .dump_prefix , cmd , self .dump_suffix )
50
- stdout , stderr = self .run_command (cmd , env = self .dump_env )
66
+ with PgEnvWrapper (self .settings ) as env :
67
+ stdout , stderr = self .run_command (cmd , env = {** self .dump_env , ** env })
51
68
return stdout
52
69
53
70
def _restore_dump (self , dump ):
54
71
cmd = '{} ' .format (self .restore_cmd )
55
- cmd = cmd + create_postgres_uri (self )
56
72
57
73
# without this, psql terminates with an exit value of 0 regardless of errors
58
74
cmd += ' --set ON_ERROR_STOP=on'
59
75
if self .single_transaction :
60
76
cmd += ' --single-transaction'
61
- cmd += ' {}' .format (self .settings ['NAME' ])
62
77
cmd = '{} {} {}' .format (self .restore_prefix , cmd , self .restore_suffix )
63
- stdout , stderr = self .run_command (cmd , stdin = dump , env = self .restore_env )
78
+ with PgEnvWrapper (self .settings ) as env :
79
+ stdout , stderr = self .run_command (cmd , stdin = dump , env = {** self .restore_env , ** env })
64
80
return stdout , stderr
65
81
66
82
@@ -76,11 +92,8 @@ def _enable_postgis(self):
76
92
self .psql_cmd )
77
93
cmd += ' --username={}' .format (self .settings ['ADMIN_USER' ])
78
94
cmd += ' --no-password'
79
- if self .settings .get ('HOST' ):
80
- cmd += ' --host={}' .format (self .settings ['HOST' ])
81
- if self .settings .get ('PORT' ):
82
- cmd += ' --port={}' .format (self .settings ['PORT' ])
83
- return self .run_command (cmd )
95
+ with PgEnvWrapper (self .settings ) as env :
96
+ return self .run_command (cmd , env = env )
84
97
85
98
def _restore_dump (self , dump ):
86
99
if self .settings .get ('ADMIN_USER' ):
@@ -101,23 +114,24 @@ class PgDumpBinaryConnector(PgDumpConnector):
101
114
102
115
def _create_dump (self ):
103
116
cmd = '{} ' .format (self .dump_cmd )
104
- cmd = cmd + create_postgres_uri (self )
105
117
106
118
cmd += ' --format=custom'
107
119
for table in self .exclude :
108
120
cmd += ' --exclude-table-data={}' .format (table )
109
121
cmd = '{} {} {}' .format (self .dump_prefix , cmd , self .dump_suffix )
110
- stdout , stderr = self .run_command (cmd , env = self .dump_env )
122
+ with PgEnvWrapper (self .settings ) as env :
123
+ stdout , stderr = self .run_command (cmd , env = {** self .dump_env , ** env })
111
124
return stdout
112
125
113
126
def _restore_dump (self , dump ):
114
- dbname = create_postgres_uri (self )
115
- cmd = '{} {}' .format (self .restore_cmd , dbname )
127
+ cmd = '{} ' .format (self .restore_cmd )
116
128
117
129
if self .single_transaction :
118
130
cmd += ' --single-transaction'
119
131
if self .drop :
120
132
cmd += ' --clean'
133
+ cmd += '-d {}' .format (self .settings .get ('NAME' ))
121
134
cmd = '{} {} {}' .format (self .restore_prefix , cmd , self .restore_suffix )
122
- stdout , stderr = self .run_command (cmd , stdin = dump , env = self .restore_env )
135
+ with PgEnvWrapper (self .settings ) as env :
136
+ stdout , stderr = self .run_command (cmd , stdin = dump , env = {** self .restore_env , ** env })
123
137
return stdout , stderr
0 commit comments