-
Notifications
You must be signed in to change notification settings - Fork 1
/
fabfile.py
228 lines (168 loc) · 5.93 KB
/
fabfile.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# coding: utf-8
import os
from fabric import colors
from fabric.decorators import task
from fabric.api import env, run, sudo, local
from fabric.contrib.files import exists
from fabric.operations import prompt, put
from fabric.context_managers import prefix, cd, settings, shell_env
### Start of config
APP_USER = APP_NAME = VENV_NAME = 'expensereport'
REPO_URL = '[email protected]:seocam/expensereport.git'
environments = {
'dev': {
'hosts': ['127.0.0.1'],
'key_filename': '~/.vagrant.d/insecure_private_key',
'port': 2222,
'is_vagrant': True,
'superuser': 'vagrant',
},
'qa': {
'hosts': [],
'port': 22,
'is_vagrant': False,
'superuser': 'root',
},
'prod': {
'hosts': ['162.243.230.194'],
'port': 22,
'is_vagrant': False,
'superuser': 'root',
},
}
DEFAULT_ENVIRONMENT = 'dev'
### End of config
env.user = APP_USER
env.use_shell = False
PROJECT_PATH = os.path.join(os.path.dirname(__file__))
REPO_PATH = '/home/{}/{}'.format(APP_USER, APP_NAME)
SOURCE_VENV = 'source /usr/local/bin/virtualenvwrapper.sh'
WORKON_ENV = '{} && workon {}'.format(SOURCE_VENV, VENV_NAME)
MANAGE_PATH = os.path.join(REPO_PATH, 'src')
SETTINGS_PATH = os.path.join(MANAGE_PATH, APP_NAME)
@task
def environment(name):
"""Set the environment where the tasks will be executed"""
env.update(environments[name])
env.environment = name
environment(DEFAULT_ENVIRONMENT)
def aptget_install(pkg):
sudo('DEBIAN_FRONTEND=noninteractive apt-get install -y -q {}'.format(pkg))
def install_requirements():
with cd(REPO_PATH), prefix(WORKON_ENV):
run('pip install -U distribute')
if not env.is_vagrant:
run('pip install -r requirements.txt')
return
if exists('requirements-{}.txt'.format(env.environment)):
run('pip install -r requirements-{}.txt'.format(env.environment))
else:
run('pip install -r requirements.txt')
def mkvirtualenv():
if not exists('~/.virtualenvs/' + VENV_NAME):
with prefix(SOURCE_VENV):
run('mkvirtualenv ' + VENV_NAME)
return True
def manage(command):
django_settings = env.get('django_settings')
env_vars = {}
if django_settings:
env_vars.update({'DJANGO_SETTINGS_MODULE': django_settings})
with shell_env(**env_vars):
with cd(MANAGE_PATH), prefix(WORKON_ENV):
run('python manage.py {}'.format(command))
def syncdb():
manage('syncdb')
def migrate():
manage('migrate')
def collectstatic():
sudo('mkdir -p /usr/share/nginx/{}'.format(APP_NAME))
sudo('chown {} /usr/share/nginx/{}'.format(env.user, APP_NAME))
manage('collectstatic --noinput')
def create_local_settings():
with cd(SETTINGS_PATH), settings(user=env.superuser):
env_local_settings = 'local_settings-{}.py'.format(env.environment)
if not exists('local_settings.py') and exists(env_local_settings):
run('ln -s {} {}'.format(env_local_settings, 'local_settings.py'))
run('chown {} local_settings.py'.format(env.user))
def update_code():
if env.is_vagrant:
if not exists(REPO_PATH):
run('ln -s /vagrant/ {}'.format(REPO_PATH))
return
if not exists(REPO_PATH):
run('git clone {} {}'.format(REPO_URL, REPO_PATH))
else:
with cd(REPO_PATH):
run('git pull')
@task
def bootstrap():
"""Bootstrap machine to run fabric tasks"""
with settings(user=env.superuser):
if not exists('/usr/bin/git'):
aptget_install('git')
if env.is_vagrant:
groups = 'sudo,vagrant'
local('chmod -fR g+w {}'.format(PROJECT_PATH))
else:
groups = 'sudo'
sudo('useradd {} -G {} -m -s /bin/bash'.format(APP_USER, groups),
quiet=True)
ssh_dir = '/home/{0}/.ssh/'.format(APP_USER)
if not exists(ssh_dir):
sudo('mkdir -p {0}'.format(ssh_dir))
sudo('chmod 700 {0}'.format(ssh_dir))
sudo('cp ~{}/.ssh/authorized_keys /home/{}/.ssh/'.format(
env.superuser,
APP_USER
))
sudo('chown -fR {0}:{0} {1}'.format(APP_USER, ssh_dir))
sudoers_file = os.path.join('/etc/sudoers.d/', APP_USER)
tmp_file = os.path.join('/tmp', APP_USER)
if not exists(sudoers_file):
sudo('echo "{} ALL=NOPASSWD: ALL" > {}'.format(APP_USER, tmp_file))
sudo('chown root:root {}'.format(tmp_file))
sudo('chmod 440 {}'.format(tmp_file))
sudo('mv {} {}'.format(tmp_file, sudoers_file))
@task
def provision():
"""Run puppet"""
update_code()
puppet_path = os.path.join(REPO_PATH, 'puppet/')
modules_path = os.path.join(puppet_path, 'modules')
puppet_modules = '{}:/etc/puppet/modules'.format(modules_path)
with cd(puppet_path):
run('sudo python bootstrap.py')
if env.is_vagrant:
cmd = os.path.join(puppet_path, 'manifests', 'site.pp')
else:
cmd = '-e "include {}"'.format(APP_NAME)
if not exists('/usr/bin/puppet'):
print(colors.red('Please install `puppet` before continue.'))
return
sudo('puppet apply --modulepath={} {}'.format(puppet_modules, cmd))
@task
def ssh_keygen():
"""Create SSH credentials"""
if not exists('~/.ssh/id_rsa'):
run("ssh-keygen -f ~/.ssh/id_rsa -N '' -b 1024 -q")
key = run('cat ~/.ssh/id_rsa.pub')
print('Public key:')
print(colors.yellow(key))
print('')
print('Add the key above to your github repository deploy keys')
@task
def deploy(noprovision=False):
"""Deploy and run the new code (master branch)"""
if noprovision is False:
provision()
else:
update_code()
mkvirtualenv()
sudo('supervisorctl stop all')
install_requirements()
create_local_settings()
collectstatic()
syncdb()
migrate()
sudo('supervisorctl start all')