Skip to content

Commit 61ae41e

Browse files
committed
add initial resource
1 parent d3cbf88 commit 61ae41e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+6461
-0
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
awesome-python3-webapp
2+
======================
3+
4+
A python webapp tutorial.

backup/README

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
stores database backup files.

conf/nginx/README

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sample nginx configuration file

conf/nginx/awesome

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
server {
2+
listen 80;
3+
4+
root /srv/awesome/www;
5+
access_log /srv/awesome/log/access_log;
6+
error_log /srv/awesome/log/error_log;
7+
8+
# server_name awesome.liaoxuefeng.com;
9+
10+
client_max_body_size 1m;
11+
12+
gzip on;
13+
gzip_min_length 1024;
14+
gzip_buffers 4 8k;
15+
gzip_types text/css application/x-javascript application/json;
16+
17+
sendfile on;
18+
19+
location /favicon.ico {
20+
root /srv/awesome/www;
21+
}
22+
23+
location ~ ^\/static\/.*$ {
24+
root /srv/awesome/www;
25+
}
26+
27+
location / {
28+
proxy_pass http://127.0.0.1:9000;
29+
proxy_set_header X-Real-IP $remote_addr;
30+
proxy_set_header Host $host;
31+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
32+
}
33+
}

conf/supervisor/README

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sample supervisor configuration file

conf/supervisor/awesome.conf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[program:awesome]
2+
3+
command = /srv/awesome/www/app.py
4+
directory = /srv/awesome/www
5+
user = www-data
6+
startsecs = 3
7+
8+
redirect_stderr = true
9+
stdout_logfile_maxbytes = 50MB
10+
stdout_logfile_backups = 10
11+
stdout_logfile = /srv/awesome/log/app.log

fabfile.py

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
__author__ = 'Michael Liao'
5+
6+
'''
7+
Deployment toolkit.
8+
'''
9+
10+
import os, re
11+
12+
from datetime import datetime
13+
from fabric.api import *
14+
15+
env.user = 'michael'
16+
env.sudo_user = 'root'
17+
env.hosts = ['192.168.0.3']
18+
19+
db_user = 'www-data'
20+
db_password = 'www-data'
21+
22+
_TAR_FILE = 'dist-awesome.tar.gz'
23+
24+
_REMOTE_TMP_TAR = '/tmp/%s' % _TAR_FILE
25+
26+
_REMOTE_BASE_DIR = '/srv/awesome'
27+
28+
def _current_path():
29+
return os.path.abspath('.')
30+
31+
def _now():
32+
return datetime.now().strftime('%y-%m-%d_%H.%M.%S')
33+
34+
def backup():
35+
'''
36+
Dump entire database on server and backup to local.
37+
'''
38+
dt = _now()
39+
f = 'backup-awesome-%s.sql' % dt
40+
with cd('/tmp'):
41+
run('mysqldump --user=%s --password=%s --skip-opt --add-drop-table --default-character-set=utf8 --quick awesome > %s' % (db_user, db_password, f))
42+
run('tar -czvf %s.tar.gz %s' % (f, f))
43+
get('%s.tar.gz' % f, '%s/backup/' % _current_path())
44+
run('rm -f %s' % f)
45+
run('rm -f %s.tar.gz' % f)
46+
47+
def build():
48+
'''
49+
Build dist package.
50+
'''
51+
includes = ['static', 'templates', 'transwarp', 'favicon.ico', '*.py']
52+
excludes = ['test', '.*', '*.pyc', '*.pyo']
53+
local('rm -f dist/%s' % _TAR_FILE)
54+
with lcd(os.path.join(_current_path(), 'www')):
55+
cmd = ['tar', '--dereference', '-czvf', '../dist/%s' % _TAR_FILE]
56+
cmd.extend(['--exclude=\'%s\'' % ex for ex in excludes])
57+
cmd.extend(includes)
58+
local(' '.join(cmd))
59+
60+
def deploy():
61+
newdir = 'www-%s' % _now()
62+
run('rm -f %s' % _REMOTE_TMP_TAR)
63+
put('dist/%s' % _TAR_FILE, _REMOTE_TMP_TAR)
64+
with cd(_REMOTE_BASE_DIR):
65+
sudo('mkdir %s' % newdir)
66+
with cd('%s/%s' % (_REMOTE_BASE_DIR, newdir)):
67+
sudo('tar -xzvf %s' % _REMOTE_TMP_TAR)
68+
with cd(_REMOTE_BASE_DIR):
69+
sudo('rm -f www')
70+
sudo('ln -s %s www' % newdir)
71+
sudo('chown www-data:www-data www')
72+
sudo('chown -R www-data:www-data %s' % newdir)
73+
with settings(warn_only=True):
74+
sudo('supervisorctl stop awesome')
75+
sudo('supervisorctl start awesome')
76+
sudo('/etc/init.d/nginx reload')
77+
78+
RE_FILES = re.compile('\r?\n')
79+
80+
def rollback():
81+
'''
82+
rollback to previous version
83+
'''
84+
with cd(_REMOTE_BASE_DIR):
85+
r = run('ls -p -1')
86+
files = [s[:-1] for s in RE_FILES.split(r) if s.startswith('www-') and s.endswith('/')]
87+
files.sort(cmp=lambda s1, s2: 1 if s1 < s2 else -1)
88+
r = run('ls -l www')
89+
ss = r.split(' -> ')
90+
if len(ss) != 2:
91+
print ('ERROR: \'www\' is not a symbol link.')
92+
return
93+
current = ss[1]
94+
print ('Found current symbol link points to: %s\n' % current)
95+
try:
96+
index = files.index(current)
97+
except ValueError, e:
98+
print ('ERROR: symbol link is invalid.')
99+
return
100+
if len(files) == index + 1:
101+
print ('ERROR: already the oldest version.')
102+
old = files[index + 1]
103+
print ('==================================================')
104+
for f in files:
105+
if f == current:
106+
print (' Current ---> %s' % current)
107+
elif f == old:
108+
print (' Rollback to ---> %s' % old)
109+
else:
110+
print (' %s' % f)
111+
print ('==================================================')
112+
print ('')
113+
yn = raw_input ('continue? y/N ')
114+
if yn != 'y' and yn != 'Y':
115+
print ('Rollback cancelled.')
116+
return
117+
print ('Start rollback...')
118+
sudo('rm -f www')
119+
sudo('ln -s %s www' % old)
120+
sudo('chown www-data:www-data www')
121+
with settings(warn_only=True):
122+
sudo('supervisorctl stop awesome')
123+
sudo('supervisorctl start awesome')
124+
sudo('/etc/init.d/nginx reload')
125+
print ('ROLLBACKED OK.')
126+
127+
def restore2local():
128+
'''
129+
Restore db to local
130+
'''
131+
backup_dir = os.path.join(_current_path(), 'backup')
132+
fs = os.listdir(backup_dir)
133+
files = [f for f in fs if f.startswith('backup-') and f.endswith('.sql.tar.gz')]
134+
files.sort(cmp=lambda s1, s2: 1 if s1 < s2 else -1)
135+
if len(files)==0:
136+
print 'No backup files found.'
137+
return
138+
print ('Found %s backup files:' % len(files))
139+
print ('==================================================')
140+
n = 0
141+
for f in files:
142+
print ('%s: %s' % (n, f))
143+
n = n + 1
144+
print ('==================================================')
145+
print ('')
146+
try:
147+
num = int(raw_input ('Restore file: '))
148+
except ValueError:
149+
print ('Invalid file number.')
150+
return
151+
restore_file = files[num]
152+
yn = raw_input('Restore file %s: %s? y/N ' % (num, restore_file))
153+
if yn != 'y' and yn != 'Y':
154+
print ('Restore cancelled.')
155+
return
156+
print ('Start restore to local database...')
157+
p = raw_input('Input mysql root password: ')
158+
sqls = [
159+
'drop database if exists awesome;',
160+
'create database awesome;',
161+
'grant select, insert, update, delete on awesome.* to \'%s\'@\'localhost\' identified by \'%s\';' % (db_user, db_password)
162+
]
163+
for sql in sqls:
164+
local(r'mysql -uroot -p%s -e "%s"' % (p, sql))
165+
with lcd(backup_dir):
166+
local('tar zxvf %s' % restore_file)
167+
local(r'mysql -uroot -p%s awesome < backup/%s' % (p, restore_file[:-7]))
168+
with lcd(backup_dir):
169+
local('rm -f %s' % restore_file[:-7])

0 commit comments

Comments
 (0)