#!/bin/python3 ''' Web app to offer a frontend to the doc2tosca and tosca2doc tools ''' import os import shutil import tempfile from zipfile import ZipFile from flask import Flask, flash, request, redirect, send_file, render_template, g from werkzeug.utils import secure_filename import docx import config import tosca2doc import doc2tosca class ReverseProxied(object): def __init__(self, the_app, script_name=None, scheme=None, server=None): self.app = the_app self.script_name = script_name self.scheme = scheme self.server = server def __call__(self, environ, start_response): script_name = environ.get('HTTP_X_SCRIPT_NAME', '') or self.script_name if script_name: environ['SCRIPT_NAME'] = script_name path_info = environ['PATH_INFO'] if path_info.startswith(script_name): environ['PATH_INFO'] = path_info[len(script_name):] scheme = environ.get('HTTP_X_SCHEME', '') or self.scheme if scheme: environ['wsgi.url_scheme'] = scheme server = environ.get('HTTP_X_FORWARDED_HOST', '') or self.server if server: environ['HTTP_HOST'] = server return self.app(environ, start_response) app = Flask(__name__) app.wsgi_app = ReverseProxied(app.wsgi_app, script_name='/tosca-ie') UPLOAD_FOLDER = '/tmp/upload' ALLOWED_EXTENSIONS = set(['txt', 'yaml', 'docx']) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER app.secret_key = config.SECRET app.config['SESSION_TYPE'] = 'filesystem' TOSCA_DEFS = ['VNFD', 'NSD', 'PNFD'] MISSING_MODULE_ERR_MSG = \ 'Error: some TOSCA module missing. Make sure to \ upload definitions for NSD, VNFD, PNFD.' def allowed_file(filename): ''' Check filename is in the list of allowed extensions ''' return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS @app.route("/") def hello(): ''' Render home page ''' if config.LAST_COMMIT is not False: link = config.REPO_URL+config.LAST_COMMIT.split(" ")[0] else: link = "#" return render_template( "./home.html", VERSION=config.VERSION, doc_allowed_versions=doc2tosca.allowed_versions, default_tosca_version=doc2tosca.DEFAULT_TOSCA_VERSION, last_rev=config.LAST_COMMIT, rev_link=link ) @app.route("/doc2tosca-info") def doc2tosca_info(): ''' Render home page ''' return render_template("./doc2tosca-details.html", VERSION=config.VERSION) @app.route("/tosca2doc-info") def tosca2doc_info(): ''' Render home page ''' return render_template("./tosca2doc-details.html", VERSION=config.VERSION) @app.route("/tosca2doc", methods=['POST']) def mk_tosca2doc(): ''' Execute tosca2doc on the uploaded files ''' if 'file' not in request.files: flash('Error: No file uploaded.') return redirect("/tosca-ie") ufiles=request.files.getlist("file") for tosca_def in TOSCA_DEFS: found=False for uploaded_file in ufiles: if tosca_def in uploaded_file.filename or \ tosca_def.lower() in uploaded_file.filename: found=True if not found: flash(MISSING_MODULE_ERR_MSG) print('Error: TOSCA module missing.') return redirect("/tosca-ie") for file in ufiles: if file.filename == '': print('Error: No selected file') flash('Error: No file uploaded or wrong name.') return redirect("/tosca-ie") tmp_dir = tempfile.mkdtemp() g.tmp_dir = tmp_dir doc = docx.Document() for tosca_def in TOSCA_DEFS: for file in ufiles: if tosca_def in uploaded_file.filename or \ tosca_def.lower() in uploaded_file.filename: filename = secure_filename(file.filename) filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) file.save(filepath) file.close() tosca2doc.generate_from_file(tosca_def, doc, filepath) outfilename = os.path.join(tmp_dir, 'myfile.docx') doc.save(outfilename) return send_file(outfilename) #return ("No content found") def get_all_yaml_file_paths(directory): ''' Finds yaml files within a directory and sub directories and returns the list of paths ''' file_paths = [] for root, _, files in os.walk(directory): for filename in files: if ".yaml" in filename: filepath = os.path.join(root, filename) file_paths.append(filepath) return file_paths @app.after_request def after_request(response): ''' Clean up files created by doc2tosca ''' if request.path != '/doc2tosca': return response if g.get('tmp_dir') is None: return response shutil.rmtree(g.tmp_dir, ignore_errors=True) print("Deleted {}\n\n".format(g.tmp_dir)) return response @app.route("/doc2tosca", methods=['POST']) def mk_doc2tosca(): ''' Executes doc2tosca on the uploaded file ''' zip_fn = "tosca_defs.zip" if 'file' not in request.files: flash('No file uploaded') return redirect("/tosca-ie") ufiles = request.files.getlist("file") try: print(request.form) doc_version = request.form.get('doc-version') custom_doc_version = request.form.get('custom-doc-version') custom_tosca_version = request.form.get('custom-tosca-version') yaml_root_path = request.form.get('yaml-root-path') except: flash("Something went wrong :/") return redirect("/tosca-ie") if doc_version not in doc2tosca.allowed_versions: flash('Incorrect doc version selected') return redirect("/tosca-ie") sol001_file = ufiles[0] tosca_version = doc2tosca.DEFAULT_TOSCA_VERSION if custom_doc_version != "": doc_version = custom_doc_version if custom_tosca_version != "": tosca_version = custom_tosca_version try: doc2tosca.generate_templates(sol001_file, doc_version, yaml_root_path, tosca_version) except ValueError as e: flash(str(e)) return redirect("/tosca-ie") except BaseException as e: flash(str(e)) flash("Unknown error in the generation of the files. Please contact the support.") return redirect("/tosca-ie") tmp_dir = tempfile.mkdtemp() print("TMP DIR: " + tmp_dir) doc2tosca.print_to_files(tmp_dir) file_paths = get_all_yaml_file_paths(tmp_dir) zip_path = os.path.join(tmp_dir, zip_fn) with ZipFile( zip_path, 'w') as archive: for myfile in file_paths: archive.write(myfile, arcname=os.path.basename(myfile)) g.tmp_dir = tmp_dir return send_file(zip_path, as_attachment=True) if __name__ == '__main__': app.run(debug=True,host='0.0.0.0')