웹 UI 추가 및 Dockerfile 추가
This commit is contained in:
117
app.py
Normal file
117
app.py
Normal file
@@ -0,0 +1,117 @@
|
||||
from flask import Flask, render_template, request, send_file, abort
|
||||
import subprocess
|
||||
import uuid
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
import zipfile
|
||||
|
||||
#app = Flask(__name__)
|
||||
app = Flask(__name__, static_folder="static")
|
||||
|
||||
BASE = Path("/work")
|
||||
BASE.mkdir(exist_ok=True)
|
||||
|
||||
|
||||
def ts():
|
||||
return datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
|
||||
|
||||
|
||||
@app.route("/", methods=["GET", "POST"])
|
||||
def index():
|
||||
if request.method == "POST":
|
||||
job_id = str(uuid.uuid4())
|
||||
job_dir = BASE / job_id
|
||||
job_dir.mkdir(parents=True)
|
||||
|
||||
cmd = [
|
||||
"python3",
|
||||
"/app/migrator.py",
|
||||
"--split",
|
||||
"--mapping", "/app/mapping.yaml",
|
||||
]
|
||||
|
||||
if request.form.get("from_class"):
|
||||
cmd += ["--from-ingress-class", request.form["from_class"]]
|
||||
|
||||
if request.form.get("to_class"):
|
||||
cmd += ["--ingress-class", request.form["to_class"]]
|
||||
|
||||
if request.form.get("namespace"):
|
||||
cmd += ["--namespace", request.form["namespace"]]
|
||||
|
||||
subprocess.check_call(cmd, cwd=job_dir)
|
||||
|
||||
timestamp = ts()
|
||||
|
||||
# result.zip (yaml + report)
|
||||
result_zip = BASE / f"{timestamp}-result.zip"
|
||||
with zipfile.ZipFile(result_zip, "w", zipfile.ZIP_DEFLATED) as z:
|
||||
for p in (job_dir / "yaml").rglob("*"):
|
||||
z.write(p, p.relative_to(job_dir))
|
||||
report = job_dir / "migration-report.md"
|
||||
if report.exists():
|
||||
z.write(report, report.relative_to(job_dir))
|
||||
|
||||
# backup.zip
|
||||
backup_zip = BASE / f"{timestamp}-backup.zip"
|
||||
with zipfile.ZipFile(backup_zip, "w", zipfile.ZIP_DEFLATED) as z:
|
||||
for p in (job_dir / "backup").rglob("*"):
|
||||
z.write(p, p.relative_to(job_dir))
|
||||
|
||||
return preview(job_id, result_zip.name, backup_zip.name)
|
||||
|
||||
return render_template("index.html")
|
||||
|
||||
|
||||
@app.route("/preview/<job_id>/<result_zip>/<backup_zip>")
|
||||
def preview(job_id, result_zip, backup_zip):
|
||||
job_dir = BASE / job_id
|
||||
|
||||
def tree(root: Path):
|
||||
t = {}
|
||||
if not root.exists():
|
||||
return t
|
||||
for ns in sorted(root.iterdir()):
|
||||
if ns.is_dir():
|
||||
t[ns.name] = sorted(f.name for f in ns.iterdir() if f.is_file())
|
||||
return t
|
||||
|
||||
return render_template(
|
||||
"preview.html",
|
||||
job_id=job_id,
|
||||
yaml_tree=tree(job_dir / "yaml"),
|
||||
backup_tree=tree(job_dir / "backup"),
|
||||
result_zip=result_zip,
|
||||
backup_zip=backup_zip,
|
||||
)
|
||||
|
||||
|
||||
@app.route("/view/<job_id>/<kind>/<path:path>")
|
||||
def view_file(job_id, kind, path):
|
||||
if kind not in ("yaml", "backup"):
|
||||
abort(404)
|
||||
f = BASE / job_id / kind / path
|
||||
if not f.exists():
|
||||
abort(404)
|
||||
return f"<pre>{f.read_text()}</pre>"
|
||||
|
||||
|
||||
@app.route("/report/<job_id>")
|
||||
def view_report(job_id):
|
||||
report = BASE / job_id / "migration-report.md"
|
||||
if not report.exists():
|
||||
abort(404)
|
||||
return f"<pre>{report.read_text()}</pre>"
|
||||
|
||||
|
||||
@app.route("/download/<name>")
|
||||
def download(name):
|
||||
path = BASE / name
|
||||
if not path.exists():
|
||||
abort(404)
|
||||
return send_file(path, as_attachment=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=8080, debug=False)
|
||||
Reference in New Issue
Block a user