From 5fb567715ab43acb29b19b8c35f5c3412df3bf9a Mon Sep 17 00:00:00 2001 From: Matt C Date: Sat, 10 Sep 2022 19:09:39 -0400 Subject: [PATCH] deploy files --- Makefile | 20 +++++++++++ main.py | 52 ++++++++++++++++++++++++--- mlcmanager.py | 98 +++++++++++++++++++++++++++++++++++++++++--------- sample.service | 13 +++++++ sed.py | 18 ++++++++++ users.py | 5 ++- utils.py | 4 +-- 7 files changed, 184 insertions(+), 26 deletions(-) create mode 100644 Makefile create mode 100644 sample.service create mode 100644 sed.py diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7bf676c --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +test: + python3 main.py +pip: + sudo pip3 install -r requirements.txt +deploy: pip + cp sample.service new.service + # yes, this exists because I'm too lazy to escape regex + inline 'sed' + python3 sed.py + sudo mv new.service /etc/systemd/system/webforge.service + sudo systemctl daemon-reload + sudo systemctl enable --now webforge.service +undeploy: + sudo systemctl stop webforge.service + sudo systemctl disable webforge.service + sudo rm /etc/systemd/system/webforge.service + sudo systemctl daemon-reload +update: + make undeploy + git pull + make deploy diff --git a/main.py b/main.py index 11a8ea7..19d0c89 100644 --- a/main.py +++ b/main.py @@ -1,9 +1,10 @@ # Stdlib -import os,yaml +import os, yaml # Pip import flask_login -from flask import Flask,render_template,request,redirect,make_response +from flask import Flask, render_template, request, redirect, make_response +from flask_login import login_required # In-house from utils import run_command_shell @@ -23,6 +24,7 @@ mlc = mlcmgr() class User(flask_login.UserMixin): pass + @login_manager.user_loader def user_loader(uid): if not db.check_user_exists(uid): @@ -81,14 +83,56 @@ def logout(): flask_login.logout_user() return redirect("/") + @app.route("/") def main(): if not flask_login.current_user.is_authenticated: pc = "Login" else: - pc = f"

Hi, {flask_login.current_user.id}

" + render_template("logout.html") + pc = f"

Hi, {flask_login.current_user.id}

" + render_template( + "logout.html" + ) + "

All repos:

" + mlc.html_repo_list() return render_template("page.html", page_title="Home", content=pc) +@app.route("/repos/") +@login_required +def getrepo(name): + if not mlc.config["has_subdirs"]: + return "This repo doesn't have subdirs. Use: TODO: new handler" + else: + return render_template( + "page.html", + page_title=f"Repo Info - {name}", + content=mlc.html_list_packages(name), + ) + + +@app.route("/packages//") +@login_required +def getpackage(repo, name): + if not mlc.config["has_subdirs"]: + return "This repo doesn't have subdirs. Use: TODO: new handler" + else: + return render_template( + "page.html", + page_title=f"Package info - {name}", + content=mlc.pkg_page(name, repo), + ) + + +@app.route("/pkgbuild//") +@login_required +def getpkgbuild(repo, name): + if not mlc.config["has_subdirs"]: + return "This repo doesn't have subdirs. Use: TODO: new handler" + else: + return render_template( + "page.html", + page_title=f"PKGBUILD for - {name}", + content=f"
{mlc.dump_pkgbuild(name, repo)}
", + ) + + if __name__ == "__main__": - app.run(host="127.0.0.1", port=6969, debug=True) \ No newline at end of file + app.run(host="127.0.0.1", port=6969, debug=True) diff --git a/mlcmanager.py b/mlcmanager.py index e3904e7..e0ab0ee 100644 --- a/mlcmanager.py +++ b/mlcmanager.py @@ -1,4 +1,4 @@ -import os,yaml,contextlib +import os, yaml, contextlib import subprocess @@ -21,7 +21,7 @@ class mlcmgr: subdirs = [] has_subdirs = input("Does your repo have subdirs? (Y/n): ") if has_subdirs != "n": - newd = 'foo' + newd = "foo" while newd != "done": newd = input("Subdir (or 'done'): ") if newd == "done": @@ -36,7 +36,7 @@ class mlcmgr: "src": src, "dst": dst, "has_subdirs": has_subdirs, - "subdirs": subdirs + "subdirs": subdirs, } with open("config.yml", "w") as f: f.write(yaml.dump(settings)) @@ -47,52 +47,116 @@ class mlcmgr: def init_workspace(self): if not os.path.exists(self.config["dst"]): os.system(f"git clone {self.config['src']} {self.config['dst']}") - if not self.config['has_subdirs']: + if not self.config["has_subdirs"]: os.system(f"cd {self.config['dst']} && mlc init") else: - for subdir in self.config['subdirs']: - os.system(f"cd {self.config['dst']} && cd {subdir} && mlc init && cd ../") + for subdir in self.config["subdirs"]: + os.system( + f"cd {self.config['dst']} && cd {subdir} && mlc init && cd ../" + ) def pull_all(self): - if self.config['has_subdirs']: - for subdir in self.config['subdirs']: - os.system(f"cd {self.config['dst']} && cd {subdir} && mlc pull && cd ../") + if self.config["has_subdirs"]: + for subdir in self.config["subdirs"]: + os.system( + f"cd {self.config['dst']} && cd {subdir} && mlc pull && cd ../" + ) else: os.system(f"cd {self.config['dst']} && mlc pull && cd ../") return "Done" def get_info(self, subdir=None): - extra = self.config['dst'] + extra = self.config["dst"] if subdir is not None: extra += "/" + subdir with pushd(extra): - out = subprocess.check_output(["mlc","info"]).decode('utf-8') + out = subprocess.check_output(["mlc", "info"]).decode("utf-8") return out def list_packages(self, subdir=None): - extra = self.config['dst'] + extra = self.config["dst"] if subdir is not None: extra += "/" + subdir - return os.listdir(extra) + all_files = os.listdir(extra) + bad = ["mlc.toml", "README.md"] + for thing in bad: + if thing in all_files: + all_files.remove(thing) + return all_files def build(self, package, subdir=None): - p = self.config['dst'] + p = self.config["dst"] if subdir is not None: p += "/" + subdir with pushd(p): os.system(f"mlc build {package}") def gen_repo(self, subdir=None): - p = self.config['dst'] + p = self.config["dst"] if subdir is not None: p += "/" + subdir with pushd(p): os.system("mlc repo-gen") + def html_list_packages(self, subdir=None): + raw = self.list_packages(subdir) + html = "
    " + for pkg in raw: + html += f"
  • - {pkg}


  • " + html += "
" + return html + + def dump_pkgbuild(self, package, subdir=None): + p = self.config["dst"] + if subdir is not None: + p += "/" + subdir + p += "/" + package + with pushd(p): + return open("PKGBUILD").read() + + def pkg_info(self, package, subdir=None): + p = self.config["dst"] + if subdir is not None: + p += "/" + subdir + p += "/" + package + with pushd(p): + pkgbuild = open("PKGBUILD").read() + pkgbuild_lines = pkgbuild.split("\n") + info = {} + for line in pkgbuild_lines: + if "=" in line: + info[line.split("=")[0]] = line.split("=")[1] + return info + + def pkg_page(self, package, subdir=None): + info = self.pkg_info(package, subdir) + html = f"

pkgname: {info['pkgname']}

" + html += f"

Version: {info['pkgver']}

" + html += f"

Rel: {info['pkgrel']}

" + html += f"

Desc: {info['pkgdesc']}

" + s_url = info["url"].replace("'", "").replace('"',"").replace("$pkgname", info['pkgname']) + html += f"

URL: {s_url}

" + html += f"

You can view the whole pkgbuild here

" + return html + + def list_repos(self): + if not self.config['has_subdirs']: + return [] + else: + return self.config['subdirs'] + + def html_repo_list(self): + repos = self.list_repos() + html = "
    " + for repo in repos: + html += f"
  • {repo}


  • " + html += "
" + return html if __name__ == "__main__": mlc = mlcmgr() - #mlc.pull_all() - mlc.build("base", "any") \ No newline at end of file + # mlc.pull_all() + # mlc.build("base", "any") + print(mlc.pkg_info("base", "any")) diff --git a/sample.service b/sample.service new file mode 100644 index 0000000..2b2d652 --- /dev/null +++ b/sample.service @@ -0,0 +1,13 @@ +[Unit] +Description=Localizer gunicorn service + +[Service] +# WHO is edited by sed.py to become the current user +User=WHO +Type=simple +# GCPATH is edited by sed.py to point to the user's installation of gunicorn +# PATH becomes the output of `pwd` +ExecStart=GCPATH --chdir PATH --workers=8 --bind=0.0.0.0 main:app + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/sed.py b/sed.py new file mode 100644 index 0000000..c4fc765 --- /dev/null +++ b/sed.py @@ -0,0 +1,18 @@ +import os, subprocess, getpass + +# Feel free to edit this file, but note that `make deploy` expects the service file to be output as `new.service` +# It, of course, is renamed to `localizer.service` as it's moved to `/etc/systemd/system/` + +text = open("new.service").read() +text = text.replace( + "GCPATH", + subprocess.check_output(["/usr/bin/bash", "-c", "which gunicorn"]) + .decode("utf-8") + .strip(), +) +text = text.replace("PATH", os.getcwd()) +text = text.replace("WHO", getpass.getuser()) + +os.remove("new.service") +with open("new.service", "w") as f: + f.write(text) diff --git a/users.py b/users.py index eeae386..6cc266d 100644 --- a/users.py +++ b/users.py @@ -1,9 +1,8 @@ -import os,yaml +import os, yaml from passlib.hash import pbkdf2_sha256 class usermgr: - def __init__(self): if not os.path.exists("db"): os.makedirs("db") @@ -47,4 +46,4 @@ class usermgr: self.write_user(uid, obj) return {"message": "done."} else: - return {"message": f"error: no such user {uid}"} \ No newline at end of file + return {"message": f"error: no such user {uid}"} diff --git a/utils.py b/utils.py index ca31ad3..ce841f3 100644 --- a/utils.py +++ b/utils.py @@ -1,4 +1,4 @@ -import asyncio,threading +import asyncio, threading # Maybe add: https://docs.python.org/3/library/shlex.html#shlex.quote ? async def run_command_shell(command, grc=False): @@ -38,4 +38,4 @@ async def run_command_shell(command, grc=False): # Return stdout return result else: - return process.returncode, result \ No newline at end of file + return process.returncode, result