-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.py
169 lines (131 loc) · 4.92 KB
/
app.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
import json
import os
import platform
import re
import shlex
from flask import Flask, request, jsonify, render_template, send_from_directory
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.wsgi import WSGIContainer
if platform.system() == "Windows":
import asyncio
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
app = Flask(__name__)
@app.route('/source', methods=['POST'])
def docker_run():
command = request.json.get('command')
args = shlex.split(command)
try:
name = None
for i, arg in enumerate(args):
if arg.startswith('--name='):
name = arg.split('=')[1]
break
elif arg == '--name':
name = args[i + 1]
break
if name is None:
image = None
for arg in reversed(args):
if '/' in arg:
image = arg
break
if image is None:
return jsonify('错误: 命令中没有找到镜像名'), 200
name = image.split('/')[-1].split(':')[0]
ports = [args[i + 1] for i, x in enumerate(args) if x == '-p']
volumes = [args[i + 1] for i, x in enumerate(args) if x == '-v']
envs = [args[i + 1] for i, x in enumerate(args) if x == '-e']
run_cmds = []
for i, x in enumerate(args):
if x == '-run_cmd':
run_cmds.append(args[i + 1])
break
except (ValueError, IndexError) as e:
return jsonify(f'解析错误,请检查命令{e}'), 200
image = None
for arg in reversed(args):
if '/' in arg:
image = arg
break
if image is None:
return jsonify('错误: 命令中没有找到镜像名'), 200
ports_dict = {p.split(':')[1]: int(p.split(':')[0]) for p in ports if ':' in p}
volumes_dict = {f"{name}_{v.split(':')[1].split('/')[-1]}_volume": {"bind": v.split(':')[1], "mode": "rw"} for v in
volumes}
envs_dict = {e.split('=')[0]: e.split('=')[1] for e in envs if '=' in e}
container_config = {
'image': image,
'name': name,
'ports': ports_dict,
'restart_policy': {'Name': 'always'}
}
if volumes_dict:
container_config['volumes'] = volumes_dict
if run_cmds:
container_config['run_cmd'] = {list(volumes_dict.keys())[0]: run_cmds}
if envs_dict:
container_config['env'] = envs_dict
return jsonify(container_config), 200
@app.route('/confirm', methods=['POST'])
def confirm():
container_config = request.json.get('container_config')
description = request.json.get('description') # 获取软件简介
try:
name = container_config['name']
except TypeError:
return jsonify('json格式错误')
if os.path.exists('app.json') and os.path.getsize('app.json') > 0:
with open('app.json', 'r') as f:
app_data = json.load(f)
else:
app_data = {}
app_data[name] = {
"url": request.url_root + f"app/{name}/run.json",
"description": description # 保存软件简介
}
with open('app.json', 'w') as f:
json.dump(app_data, f, indent=4)
os.makedirs(f'app/{name}', exist_ok=True)
with open(f'app/{name}/run.json', 'w') as f:
json.dump(container_config, f, indent=4)
return jsonify({"message": "Success"}), 200
@app.route('/', methods=['GET'])
def index():
return render_template('index.html')
@app.route('/app/<path:app_name>/run.json', methods=['GET'])
def run_json(app_name):
return send_from_directory(f'app/{app_name}', 'run.json')
@app.route('/app.json', methods=['GET'])
def app_json():
return send_from_directory('.', 'app.json')
@app.route('/delete/<app_name>', methods=['DELETE'])
def delete_app(app_name):
try:
# 删除 run.json 文件
run_json_path = f'app/{app_name}/run.json'
if os.path.exists(run_json_path):
os.remove(run_json_path)
# 删除应用目录
app_dir_path = f'app/{app_name}'
if os.path.exists(app_dir_path):
os.rmdir(app_dir_path)
# 从 app.json 中删除应用条目
with open('app.json', 'r') as f:
app_data = json.load(f)
if app_name in app_data:
del app_data[app_name]
# 将更新后的内容写回 app.json
with open('app.json', 'w') as f:
json.dump(app_data, f, indent=4)
return jsonify({"message": "Success"}), 200
except OSError as e:
return jsonify({"message": f"文件操作错误: {str(e)}"}), 500
except json.JSONDecodeError as e:
return jsonify({"message": f"JSON操作错误: {str(e)}"}), 500
if __name__ == '__main__':
s = HTTPServer(WSGIContainer(app))
port = 10010
s.listen(port=port, address='0.0.0.0')
print(f"Taichi_OS_Software_Source启动在0.0.0.0:{port}")
IOLoop.current().start()