From bc6b03ab29703dfff857b63727657ca3127eb381 Mon Sep 17 00:00:00 2001 From: xengineering Date: Thu, 11 Feb 2021 13:01:43 +0100 Subject: Refactoring: Reimplement Webroot Deployment --- .gitignore | 2 + Makefile | 21 +++++++ config.json | 11 ---- example_settings.json | 13 +++++ flask/main.py | 42 -------------- flask/main.py.jinja2 | 42 ++++++++++++++ lib/css/debug.html | 31 ++++++++++ lib/css/xengineering.css | 111 ++++++++++++++++++++++++++++++++++++ lib/html/example.html | 31 ++++++++++ lib/img/xengineering.ico | Bin 0 -> 6715 bytes lib/js/example.js | 14 +++++ manage.py | 103 +++++++++++++++++++++++++++------- systemd/webtemplate.service.jinja2 | 14 +++++ webroot/css/xengineering.css | 112 +------------------------------------ webroot/favicon.ico | Bin 6715 -> 27 bytes webroot/index.html | 32 +---------- webroot/js/example.js | 15 +---- 17 files changed, 364 insertions(+), 230 deletions(-) create mode 100644 .gitignore create mode 100644 Makefile delete mode 100644 config.json create mode 100644 example_settings.json delete mode 100755 flask/main.py create mode 100755 flask/main.py.jinja2 create mode 100644 lib/css/debug.html create mode 100644 lib/css/xengineering.css create mode 100644 lib/html/example.html create mode 100644 lib/img/xengineering.ico create mode 100644 lib/js/example.js mode change 100755 => 100644 manage.py create mode 100644 systemd/webtemplate.service.jinja2 mode change 100644 => 120000 webroot/css/xengineering.css mode change 100644 => 120000 webroot/favicon.ico mode change 100644 => 120000 webroot/index.html mode change 100644 => 120000 webroot/js/example.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..08c5ba6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +settings.json +archive diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9fe5771 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +# vim: tabstop=4 shiftwidth=4 noexpandtab + + +all: + mkdir -p systemd/build + python3 manage.py build_systemd_files + mkdir -p flask/build + python3 manage.py build_flask_files + +clean: + rm -rf systemd/build + rm -rf flask/build + +install: all + python3 manage.py install_webroot + #find systemd/build -type f -exec sudo install -Dm 644 "{}" "/etc/systemd/system" \; + +uninstall: + python3 manage.py uninstall_webroot + #python3 manage.py uninstall_systemd_files + diff --git a/config.json b/config.json deleted file mode 100644 index 1ad14b1..0000000 --- a/config.json +++ /dev/null @@ -1,11 +0,0 @@ - -{ - "deployments":[ - { - "host":"example.com", - "username":"exampleuser", - "webroot":"/srv/http/example.com/public/" - } - ] -} - diff --git a/example_settings.json b/example_settings.json new file mode 100644 index 0000000..c08c89c --- /dev/null +++ b/example_settings.json @@ -0,0 +1,13 @@ + +{ + "project_name":"webtemplate", + "project_description":"A Template Web Application", + "user":"http", + "group":"http", + "webroot_installation_path":"/srv/http/example.com/public", + "web_framework":"flask", + "web_framework_installation_path":"/opt", + "framework_port":"8080", + "framework_bind":"127.0.0.1" +} + diff --git a/flask/main.py b/flask/main.py deleted file mode 100755 index be270b1..0000000 --- a/flask/main.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/python3 - - -""" - web-template - A Template Project for dynamic Web Applications. - - Copyright (C) 2020 xengineering - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -""" - - -import waitress -from flask import Flask, request, jsonify - - -app = Flask(__name__) - - -@app.route('/', methods=['POST']) -def api(): - data = request.get_json(force=True) - print(data) - return jsonify({"result":"ok"}) - - -if __name__ == '__main__': - waitress.serve(app, listen='*:8080') # production server / bind to port - #serve(app, unix_socket='/run/web-template/unix.sock') # production server / unix domain socket - #app.run() # debug server - NOT FOR PRODUCTION! - diff --git a/flask/main.py.jinja2 b/flask/main.py.jinja2 new file mode 100755 index 0000000..1e1a653 --- /dev/null +++ b/flask/main.py.jinja2 @@ -0,0 +1,42 @@ +#!/usr/bin/python3 + + +""" + web-template - A Template Project for dynamic Web Applications. + + Copyright (C) 2020 xengineering + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +""" + + +import waitress +from flask import Flask, request, jsonify + + +app = Flask(__name__) + + +@app.route('/', methods=['POST']) +def api(): + data = request.get_json(force=True) + print(data) + return jsonify({"result":"ok"}) + + +if __name__ == '__main__': + waitress.serve(app, listen='{{ framework_bind }}:{{ framework_port }}') # production server / bind to port + #serve(app, unix_socket='/run/web-template/unix.sock') # production server / unix domain socket + #app.run() # debug server - NOT FOR PRODUCTION! + diff --git a/lib/css/debug.html b/lib/css/debug.html new file mode 100644 index 0000000..8d4b997 --- /dev/null +++ b/lib/css/debug.html @@ -0,0 +1,31 @@ + + + + + + + CSS Debugger + + + + + + + + + +
+ HOME +
+ +
+

Web Template

+ +
+ + + + + + + diff --git a/lib/css/xengineering.css b/lib/css/xengineering.css new file mode 100644 index 0000000..1e14b72 --- /dev/null +++ b/lib/css/xengineering.css @@ -0,0 +1,111 @@ + + +/* + web-template - A Template Project for dynamic Web Applications. + + Copyright (C) 2020 xengineering + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + + +/* + General Stuff +*/ + +* { + box-sizing: border-box; /* Include padding and border in the element's total width and height */ +} + +body { + margin: 0; /* avoid ugly white margin */ + font-family: Arial, Helvetica, sans-serif; /* select a nice font */ +} + +.xmenu { + background-color: black; +} + +.xcontent { + background-color: white; +} + +.xmenu a { + color: lightgray; + text-decoration: none; /* disable ugly underlined links */ +} + +/* How should the link behave if the mouse is over this item? */ +.xmenu a:hover { + background-color: lightgray; + color: black; +} + + + +/* + Default Geometry / Geometry for Phones ('Mobile First Development') +*/ + +.xcontent { + padding-left: 20px; + padding-right: 20px; + text-align: justify; +} + +.xmenu a { + display: block; + padding: 16px; + text-align: center; +} + + + +/* + Geometry for Tablets +*/ + +@media only screen and (min-width: 600px) { + /* empty --> same rules as for phones */ +} + + + +/* + Geometry for Desktops +*/ + +@media only screen and (min-width: 768px) { + + .xmenu { + height: 100%; + width: 200px; + position: fixed; /* position fixed in top left corner (with offset) */ + top: 0px; /* disable the offset from top left corner */ + } + + .xmenu a { + text-align: left; + } + + .xcontent { + margin-left: 200px; /* transparent margin on the left for .xmenu */ + } + + .xcontent *{ /* everything inside the content container */ + max-width: 960px; /* maximum width on desktops should be 960 px */ + margin-left: auto; /* center it with margin */ + margin-right: auto; /* center it with margin */ + } +} diff --git a/lib/html/example.html b/lib/html/example.html new file mode 100644 index 0000000..a406de7 --- /dev/null +++ b/lib/html/example.html @@ -0,0 +1,31 @@ + + + + + + + Web Template + + + + + + + + + +
+ HOME +
+ +
+

Web Template

+ +
+ + + + + + + diff --git a/lib/img/xengineering.ico b/lib/img/xengineering.ico new file mode 100644 index 0000000..969b451 Binary files /dev/null and b/lib/img/xengineering.ico differ diff --git a/lib/js/example.js b/lib/js/example.js new file mode 100644 index 0000000..59cf1ee --- /dev/null +++ b/lib/js/example.js @@ -0,0 +1,14 @@ + +function example_post() { + + var data = { + "key":"value", + } + var json = JSON.stringify(data); + + var xhr = new XMLHttpRequest(); + xhr.open("POST", "api", true); + xhr.send(json); + +} + diff --git a/manage.py b/manage.py old mode 100755 new mode 100644 index 50249e5..6df9902 --- a/manage.py +++ b/manage.py @@ -1,45 +1,106 @@ #!/usr/bin/python3 +# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab import sys +import os import subprocess import json +import jinja2 + + +SETTINGS_PATH = "settings.json" +SYSTEMD_TEMPLATE = "systemd/webtemplate.service.jinja2" +FLASK_TEMPLATE = "flask/main.py.jinja2" +REPOSITORY_WEBROOT = "webroot" + + +def read_settings(): + """Read the SETTINGS_PATH File and return a Dictionary with its Content""" + + with open(SETTINGS_PATH, "r") as settings: + settings = settings.read() + + settings = json.loads(settings) + return settings + + +def build_systemd_files(settings): + """Generate all Systemd Unit Files with Settings from SETTINGS_PATH""" + + with open(SYSTEMD_TEMPLATE, "r") as template: + template = template.read() + + template = jinja2.Template(template) + systemd_file = template.render(settings) + + file_path = "systemd/build/{}.service".format(settings["project_name"]) + + with open(file_path, "w") as _file: + _file.write(systemd_file) + + +def build_flask_files(settings): + """Generate all Python Flask Files with Settings from SETTINGS_PATH""" + + if settings["web_framework"] == "flask": + with open(FLASK_TEMPLATE, "r") as template: + template = template.read() + + template = jinja2.Template(template) + flask_file = template.render(settings) + + file_path = "flask/build/{}".format(settings["project_name"]) + + with open(file_path, "w") as _file: + _file.write(flask_file) + else: + print("Flask not enabled in settings.json - skipping file generation for Flask") + + +def install_webroot(settings): + """Install every File from the Repositories Webroot to the Systems Webroot""" + + for directory, subdirs, files in os.walk(REPOSITORY_WEBROOT, topdown=False): + for _file in files: + path_to_file = os.path.join(directory, _file) + relative_path = os.path.relpath(path_to_file, REPOSITORY_WEBROOT) + target_path = os.path.join(settings["webroot_installation_path"], relative_path) + subprocess.run("install -Dm 644 {} {}".format(path_to_file, target_path), shell=True) -CONFIG_PATH = "./config.json" +def uninstall_webroot(settings): + """Uninstalls every File from the Systems Webroot""" + + path_to_delete = os.path.join(settings["webroot_installation_path"], "*") + subprocess.run("rm -rf {}".format(path_to_delete), shell=True) def main(): + """The main Function""" + + settings = read_settings() # get settings from SETTINGS_PATH + # just one argument is allowed: if len(sys.argv) != 2: print("Provide exactly one parameter") sys.exit(1) - cfg = read_config() - + # execute given command command = sys.argv[1] - - if command == "deploy": - for deployment in cfg["deployments"]: - subprocess.call( - "rsync -av ./webroot/ {0}@{1}:{2}".format( - deployment["username"], - deployment["host"], - deployment["webroot"] - ), - shell=True - ) + if command == "build_systemd_files": + build_systemd_files(settings) + elif command == "build_flask_files": + build_flask_files(settings) + elif command == "install_webroot": + install_webroot(settings) + elif command == "uninstall_webroot": + uninstall_webroot(settings) else: print("Unknown command") + exit(1) -def read_config(): - with open(CONFIG_PATH, "r") as f: - content = f.read() - return json.loads(content) if __name__ == "__main__": main() - -# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab - diff --git a/systemd/webtemplate.service.jinja2 b/systemd/webtemplate.service.jinja2 new file mode 100644 index 0000000..6861b57 --- /dev/null +++ b/systemd/webtemplate.service.jinja2 @@ -0,0 +1,14 @@ + +[Unit] +Description={{ project_description }} +After=network.target + +[Service] +User={{ user }} +Group={{ group }} +WorkingDirectory={{ web_framework_installation_path }}/{{ project_name }}/ +ExecStart={{ web_framework_installation_path }}/{{ project_name }}/{{ project_name }} + +[Install] +WantedBy=multi-user.target + diff --git a/webroot/css/xengineering.css b/webroot/css/xengineering.css deleted file mode 100644 index 1e14b72..0000000 --- a/webroot/css/xengineering.css +++ /dev/null @@ -1,111 +0,0 @@ - - -/* - web-template - A Template Project for dynamic Web Applications. - - Copyright (C) 2020 xengineering - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - - -/* - General Stuff -*/ - -* { - box-sizing: border-box; /* Include padding and border in the element's total width and height */ -} - -body { - margin: 0; /* avoid ugly white margin */ - font-family: Arial, Helvetica, sans-serif; /* select a nice font */ -} - -.xmenu { - background-color: black; -} - -.xcontent { - background-color: white; -} - -.xmenu a { - color: lightgray; - text-decoration: none; /* disable ugly underlined links */ -} - -/* How should the link behave if the mouse is over this item? */ -.xmenu a:hover { - background-color: lightgray; - color: black; -} - - - -/* - Default Geometry / Geometry for Phones ('Mobile First Development') -*/ - -.xcontent { - padding-left: 20px; - padding-right: 20px; - text-align: justify; -} - -.xmenu a { - display: block; - padding: 16px; - text-align: center; -} - - - -/* - Geometry for Tablets -*/ - -@media only screen and (min-width: 600px) { - /* empty --> same rules as for phones */ -} - - - -/* - Geometry for Desktops -*/ - -@media only screen and (min-width: 768px) { - - .xmenu { - height: 100%; - width: 200px; - position: fixed; /* position fixed in top left corner (with offset) */ - top: 0px; /* disable the offset from top left corner */ - } - - .xmenu a { - text-align: left; - } - - .xcontent { - margin-left: 200px; /* transparent margin on the left for .xmenu */ - } - - .xcontent *{ /* everything inside the content container */ - max-width: 960px; /* maximum width on desktops should be 960 px */ - margin-left: auto; /* center it with margin */ - margin-right: auto; /* center it with margin */ - } -} diff --git a/webroot/css/xengineering.css b/webroot/css/xengineering.css new file mode 120000 index 0000000..73f09ef --- /dev/null +++ b/webroot/css/xengineering.css @@ -0,0 +1 @@ +../../lib/css/xengineering.css \ No newline at end of file diff --git a/webroot/favicon.ico b/webroot/favicon.ico deleted file mode 100644 index 969b451..0000000 Binary files a/webroot/favicon.ico and /dev/null differ diff --git a/webroot/favicon.ico b/webroot/favicon.ico new file mode 120000 index 0000000..18c5c39 --- /dev/null +++ b/webroot/favicon.ico @@ -0,0 +1 @@ +../lib/img/xengineering.ico \ No newline at end of file diff --git a/webroot/index.html b/webroot/index.html deleted file mode 100644 index a406de7..0000000 --- a/webroot/index.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - Web Template - - - - - - - - - -
- HOME -
- -
-

Web Template

- -
- - - - - - - diff --git a/webroot/index.html b/webroot/index.html new file mode 120000 index 0000000..f040f3e --- /dev/null +++ b/webroot/index.html @@ -0,0 +1 @@ +../lib/html/example.html \ No newline at end of file diff --git a/webroot/js/example.js b/webroot/js/example.js deleted file mode 100644 index 59cf1ee..0000000 --- a/webroot/js/example.js +++ /dev/null @@ -1,14 +0,0 @@ - -function example_post() { - - var data = { - "key":"value", - } - var json = JSON.stringify(data); - - var xhr = new XMLHttpRequest(); - xhr.open("POST", "api", true); - xhr.send(json); - -} - diff --git a/webroot/js/example.js b/webroot/js/example.js new file mode 120000 index 0000000..3faf334 --- /dev/null +++ b/webroot/js/example.js @@ -0,0 +1 @@ +../../lib/js/example.js \ No newline at end of file -- cgit v1.2.3-70-g09d2