-
Notifications
You must be signed in to change notification settings - Fork 19
/
main.py
executable file
·170 lines (128 loc) · 4.82 KB
/
main.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
#!/usr/bin/env python
""" Taking the magic of fabric and throwing up as a website for ease of use.
"""
from flask import Flask
from flask import render_template
from flask import request, redirect, flash
#
from fabric import state
import easyfab
import settings
app = Flask(__name__)
task_list = easyfab.get_fab_tasks()
def render(template, *args, **kwargs):
""" render a template with a set of standard args that every template
can take advantage of.
This stops every call to render_template adding in the same extra **kwargs
"""
return render_template(template, state=state, env=state.env,
settings=settings, *args, **kwargs)
def get_task(fabfile, task_name):
""" Given a fabfile and task_name, return the task object. """
return task_list[fabfile]['tasks'][task_name]
@app.route("/")
def index():
""" Basic landing page, with a list of all the tasks from all the fabfiles.
"""
return render('index.html', task_list=task_list)
@app.route("/fabfile/<fabfile>")
def task_display_single_Fabfile(fabfile):
""" Provide a fabfile to list only the tasks from that fabfile. """
local_task_list = task_list.copy()
for fabfile_name in local_task_list.keys():
if fabfile_name == fabfile:
continue
del local_task_list[fabfile_name]
return render('index.html', task_list=local_task_list)
@app.route("/fabfile/<fabfile>/task/<task_name>/")
def task_display(fabfile, task_name):
""" Render a task as a html form. """
task = get_task(fabfile, task_name)
wrapped_task = task.__dict__['wrapped']
task_dict = easyfab.task_to_dict(task)
return render('task_form.html', task=task,
wrapped_task=wrapped_task,
task_dict=task_dict,
)
def execute_task(task, hosts, roles, *args, **kwargs):
""" Execute a task, providing all the details from the form. """
from fabric.api import env, execute
from StringIO import StringIO
import sys
env.hosts = hosts
env.roles = roles
output = StringIO()
error = StringIO()
sys.stdout = output
sys.stderr = error
data = None
try:
data = execute(task, hosts=hosts, *args, **kwargs)
except SystemExit:
print "fabric had a fatal exception, that caused it to exit."
finally:
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
print "data: %s" % data
print "out: %s" % str(output.getvalue())
print "err: %s" % str(error.getvalue())
return output.getvalue(), error.getvalue()
@app.route("/settings/apply", methods=['POST'])
def fabric_settings_apply():
""" Apply the settings from the settings form. """
return render('settings.html')
@app.route("/settings")
def fabric_settings():
""" Offer a html form for tuning application settings. """
return render('settings.html')
@app.route("/fabfile/<fabfile>/task/<task_name>/execute", methods=['POST'])
def task_execute(fabfile, task_name):
""" Read in the form post, then execute the task. """
task = get_task(fabfile, task_name)
form = request.form.copy()
filtered_form = {}
hosts = ""
roles = ""
if 'env_hosts' in form:
hosts = form['env_hosts'] + ' '
del form['env_hosts']
if 'env_roles' in form:
roles = request.form['env_roles'] + ' '
del form['env_roles']
if ',' in hosts:
hosts = hosts.split(',')
if ' ' in hosts:
hosts = hosts.split()
if ',' in roles:
roles = roles.split(',')
if ' ' in roles:
roles = roles.split()
if not hosts and not roles:
flash('You need to provide either a hostname or choose a role.')
return redirect("/fabfile/%(fabfile)s/task/%(task_name)s" % locals())
from easyfab import task_to_dict
for field, value in form.items():
value = value.strip()
if not value:
continue
filtered_form[field] = value
missing_required_args = False
for required_arg in task_to_dict(task)['required_args']:
if required_arg not in filtered_form.keys():
missing_required_args = True
flash("Missing required argument: %s" % required_arg)
if missing_required_args:
return redirect("/fabfile/%(fabfile)s/task/%(task_name)s" % locals())
stdout, stderr = execute_task(task,
hosts=hosts,
roles=roles,
**filtered_form
)
stdout = easyfab.format_output(stdout)
return render('execute.html', task=task, results=stdout, errors=stderr)
if __name__ == '__main__':
app.debug = settings.debug
app.secret_key = settings.secret_key
app.run(host=settings.listen_ip, port=settings.listen_port)