forked from clevyr/pg_dump-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
120 lines (104 loc) · 3.92 KB
/
main.py
File metadata and controls
120 lines (104 loc) · 3.92 KB
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
import json
from os import environ, mkdir, path, getcwd
from threading import Timer
import tarfile
from time import strftime, gmtime
import inquirer
import boto3 as boto
import hvac
import shutil
import subprocess
import traceback
import sys
s3 = boto.resource("s3")
def exit(error=None):
if error is not None:
print('Error occured, sending email...')
print(error)
email(error, environ.get('EMAIL_FROM'), environ.get('EMAIL_TO').split(';'))
def main():
try:
vault_secret = environ.get("VAULT_SECRET")
bucket_name = environ.get("BUCKET_NAME")
postgres_host = environ.get("POSTGRES_HOST")
username = environ.get("POSTGRES_USERNAME")
password = environ.get("POSTGRES_PASSWORD")
database = environ.get("POSTGRES_DATABASE")
if postgres_host is None:
questions = [
inquirer.Text('postgres_host', message='What is the host of the Postgres instance?'),
inquirer.Text('postgres_database', message='What is the host of the Postgres instance?'),
inquirer.Text('username', message='What is the username for postgres?'),
inquirer.Password('password', message='What is the password for postgres?'),
]
answers = inquirer.prompt(questions)
postgres_host = answers['postgres_host']
database = answers['postgres_database']
username = answers['username']
password = answers['password']
if vault_secret is not None:
client = hvac.Client(
url=environ.get('VAULT_HOST'),
token=environ.get('VAULT_TOKEN')
)
try:
client.renew_token(increment=60 * 60 * 72)
except hvac.exceptions.InvalidRequest as _:
# Swallow, as this is probably a root token
pass
except hvac.exceptions.Forbidden as _:
# Swallow, as this is probably a root token
pass
except Exception as e:
exit(e)
secret = client.read(vault_secret)['data']
username = secret['username']
password = secret['password']
database = secret['database']
filename = "/tmp/backup-{}.tar".format(strftime("%Y-%m-%d_%H%M%S", gmtime()))
completed_process = None
with open(filename, 'w') as backup:
completed_process = subprocess.run(
[f'/usr/local/bin/pg_dump', '-h', postgres_host, '-U', username, '-F', 't', database],
stdout=backup,
env={'PGPASSWORD': password})
try:
completed_process.check_returncode()
except subprocess.CalledProcessError as e:
exit(e)
if bucket_name is not None:
s3.Bucket(bucket_name).upload_file(filename, path.basename(filename))
else:
print(f"Backup is available at {filename}")
print("Done")
exit()
except Exception as e:
exit(e)
def email(error, from_address, addresses):
try:
ses = boto.client('ses', region_name=environ.get('SES_REGION'))
bucket_name = environ.get('BUCKET_NAME')
errString = ''.join(traceback.format_exception(etype=type(error), value=error, tb=error.__traceback__))
response = ses.send_email(
Source=from_address,
Destination={
'ToAddresses': addresses
},
Message={
'Subject': {
'Data': 'Error: Backup Failed'
},
'Body': {
'Text': {
'Data': f'The database backup for {bucket_name} failed:\n{errString}'
}
}
}
)
except Exception as e:
print('Error sending email...')
print(e)
if __name__ == "__main__":
main()
def lambda_handler(_, __):
main()