-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathfabfile.py
273 lines (208 loc) · 7.37 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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
from fabric.api import env
from fabric.api import local
from fabric.api import run
from fabric.api import task
from fabric.context_managers import cd, lcd
import os
import json
env.forward_agent = True
env.user = 'root'
env.hosts = ['your production host']
project_dst = 'project-name'
compose_cmd = [
'docker-compose',
'-f', 'docker-compose.yml',
'-f',
]
# service to run commands against
service_name = None
renv = 'dev' # dev by default
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
STYLES_DIR = os.path.join(CURRENT_DIR, 'styles')
UX_DIR = os.path.join(CURRENT_DIR, 'ux')
APP_DIR = os.path.join(CURRENT_DIR, 'app')
def get_compose_cmd():
return compose_cmd + ['docker-compose-%s.yml' % renv]
def get_fn():
"""
Returns the correct function call for the environment.
"""
return run if renv == 'prd' else local
def get_cmd_exists(cmd):
def tell_on(arg, rs):
if rs:
print('"%s" found in path.' % arg)
else:
print('"%s" not found in path. Please, install it to continue.' % arg) # noqa
return rs
fn = get_fn()
rs = fn('which %s' % cmd, capture=True)
return tell_on(cmd, ('not found' not in rs))
def insert_line_after(lines, line, after):
for i in range(len(lines)):
if after in lines[i]:
lines.insert(i+1, line)
break
def replace_line(lines, line, condition):
for i in range(len(lines)):
if condition in lines[i]:
lines[i] = line
break
def update_webpack_config(path):
with open(path) as fs:
lines = fs.readlines()
line_to_insert = " poll: 800,\n"
line_condition = "poll: false"
replace_line(lines, line_to_insert, line_condition)
with open(path, 'w') as fs:
fs.write(''.join(lines))
def update_webpack_base_conf(conf_path):
with open(conf_path) as fs:
lines = fs.readlines()
line_to_insert = ""\
" plugins: [\n"\
" new webpack.ProvidePlugin({\n"\
" '$': 'jquery',\n"\
" 'jQuery': 'jquery',\n"\
" 'window.jQuery': 'jquery'\n"\
" })],\n"
line_condition = 'module.exports = {'
insert_line_after(lines, line_to_insert, line_condition)
line_to_insert = " exclude: [resolve('src/styles')],\n"
line_condition = "include: [resolve('src'), resolve('test')]"
insert_line_after(lines, line_to_insert, line_condition)
line_to_insert = "const webpack = require('webpack')\n"
line_condition = "const vueLoaderConfig"
insert_line_after(lines, line_to_insert, line_condition)
with open(conf_path, 'w') as fs:
fs.write(''.join(lines))
def update_webpack_dev_conf(conf_path):
with open(conf_path) as fs:
lines = fs.readlines()
# add disable host check; required for development with webpack
line_to_insert = ' disableHostCheck: true,\n'
line_condition = 'devServer: {'
insert_line_after(lines, line_to_insert, line_condition)
with open(conf_path, 'w') as fs:
fs.write(''.join(lines))
def update_ux_main(path):
with open(path) as fs:
lines = fs.readlines()
line_to_insert = "\n"\
"require('./styles/semantic.css')\n"\
"require('./styles/semantic.js')\n"
line_condition = "productionTip"
insert_line_after(lines, line_to_insert, line_condition)
with open(path, 'w') as fs:
fs.write(''.join(lines))
@task(alias='setup')
def do_setup():
"""
Helps you setup your environment. Call it once per project.
"""
msg = "Command not found. Please, install %s"
assert get_cmd_exists('npm'), msg % "npm"
assert get_cmd_exists('gulp'), msg % "gulp"
assert get_cmd_exists('yarn'), msg % "yarn"
assert get_cmd_exists('vue'), msg % "vue-cli"
assert get_cmd_exists('fab'), msg % "fabric3"
assert get_cmd_exists('docker'), msg % "docker"
assert get_cmd_exists('docker-compose'), msg % "docker-compose"
with lcd(APP_DIR):
# make sure entrypoint has execution permission
# so that the development environment doesn't break
local('chmod +x entrypoint.sh')
# do not change the directory context here
local('vue init webpack ux', shell='/bin/bash')
with lcd(UX_DIR):
print("Setting up VueJS (just accept defaults)")
# make sure entrypoint has execution permission
# so that the development environment doesn't break
local('chmod +x entrypoint.sh')
update_webpack_config("ux/config/index.js")
update_webpack_base_conf("ux/build/webpack.base.conf.js")
update_webpack_dev_conf("ux/build/webpack.dev.conf.js")
update_ux_main("ux/src/main.js")
local("yarn add jquery")
with lcd(STYLES_DIR):
print("Setting up SemanticUI (just accept defaults)")
# make sure entrypoint has execution permission
# so that the development environment doesn't break
local('chmod +x entrypoint.sh')
local('npm install semantic-ui', shell='/bin/bash')
semantic_settings = os.path.join(STYLES_DIR, 'semantic.json')
with open(semantic_settings, 'r') as fs:
data = json.load(fs)
data['autoInstall'] = True
with open(semantic_settings, 'w') as fs:
json.dump(data, fs)
print(
"IMPORTANT: run the following command:\n"
"sudo echo \"127.0.0.1 dv\" >> /etc/hosts")
print(
"IMPORTANT: make sure to update your envfile file with "
"your project production configuration.")
print(
"IMPORTANT: make sure to update your fabfile "
"hosts with your production host.")
print("")
print("Now you're ready to go:")
print(' fab env:dev up # for development mode')
print(' fab env:prd up # for production mode')
print(' fab env:tst up # to simulate production mode')
print('Locally, your project will be available at http://dv:8080')
@task(alias='env')
def set_renv(local_renv):
"Sets docker-compose environment"
global renv
assert local_renv in ('dev', 'prd')
renv = local_renv
@task(alias='up')
def compose_up(name=None):
"""
Calls docker compose up using the correct environment.
"""
opt = ['-d'] if renv == 'prd' else []
with cd(project_dst):
local_cmd = get_compose_cmd() + ['up']
local_cmd += opt
local_cmd += [name] if name else []
get_fn()(' '.join(local_cmd))
@task(alias='build')
def compose_build(name=None):
"""
Calls docker compose build using the correct environment.
"""
with cd(project_dst):
local_cmd = get_compose_cmd() + ['build']
local_cmd += [name] if name else []
get_fn()(' '.join(local_cmd))
@task(alias='on')
def on_service(name):
"""
Define service where command should run
"""
global service_name
service_name = name
@task(alias='run')
def compose_run(cmd):
"""
Calls docker compose run using the correct environment.
:param cmd: run command, including container name.
"""
opt = ['--rm']
if service_name is None:
print("please, provide service name")
exit()
with cd(project_dst):
local_cmd = get_compose_cmd() + ['run']
local_cmd += opt
local_cmd += [service_name]
local_cmd += cmd.split()
get_fn()(' '.join(local_cmd))
@task(alias='logs')
def docker_logs(name):
"""
Get docker container logs.
"""
get_fn()('docker logs %s' % name)