Refactor and add a number of helper methods
This commit is contained in:
parent
ae06f928bf
commit
ad31f17888
84
second.py
84
second.py
@ -4,8 +4,11 @@ from json import dumps, loads
|
|||||||
from os import environ
|
from os import environ
|
||||||
from os.path import exists
|
from os.path import exists
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from random import choice
|
||||||
from shlex import split
|
from shlex import split
|
||||||
|
from string import ascii_lowercase
|
||||||
from subprocess import run
|
from subprocess import run
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
from flask import Flask, render_template, request
|
from flask import Flask, render_template, request
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
@ -22,37 +25,25 @@ APPS = {"gitea": "https://git.autonomic.zone/compose-stacks/gitea"}
|
|||||||
DATA_DIR = Path("./data")
|
DATA_DIR = Path("./data")
|
||||||
|
|
||||||
|
|
||||||
class GiteaConfigForm(FlaskForm):
|
def get_secret(n: int) -> str:
|
||||||
app_name = StringField("Application name", default="Gitea")
|
"""Generate a ASCII secret that is n chars long."""
|
||||||
db_host = StringField("Database host", default="mariadb:3306")
|
return "".join(choice(ascii_lowercase) for _ in range(n))
|
||||||
db_name = StringField("Database name", default="gitea")
|
|
||||||
db_passwd = PasswordField("Database password", validators=[DataRequired()])
|
|
||||||
db_root_passwd = PasswordField(
|
|
||||||
"Root database password", validators=[DataRequired()]
|
|
||||||
)
|
|
||||||
db_type = StringField("Database type", default="mysql")
|
|
||||||
db_user = StringField("Database user", default="mysql")
|
|
||||||
domain = StringField("Domain name", validators=[DataRequired()])
|
|
||||||
ssh_port = StringField("SSH port", default="2222")
|
|
||||||
stack_name = StringField("Stack name", default="gitea")
|
|
||||||
internal_token = PasswordField("Internal token", validators=[DataRequired()])
|
|
||||||
jwt_secret = PasswordField("JWT secret", validators=[DataRequired()])
|
|
||||||
|
|
||||||
|
|
||||||
def clone_app_template(app_name):
|
def clone_app_template(app_name: str) -> None:
|
||||||
"""Git clone an app template repository."""
|
"""Git clone an app template repository."""
|
||||||
clone_path = DATA_DIR / app_name
|
clone_path = DATA_DIR / app_name
|
||||||
clone_url = apps[app_name]
|
clone_url = APPS[app_name]
|
||||||
run(split(f"git clone {clone_url} {clone_path}"))
|
run(split(f"git clone {clone_url} {clone_path}"))
|
||||||
|
|
||||||
|
|
||||||
def dump_db(db):
|
def dump_db(db: Dict) -> None:
|
||||||
"""Dump the database."""
|
"""Dump the database."""
|
||||||
with open(DATA_DIR / "db.json", "w") as handle:
|
with open(DATA_DIR / "db.json", "w") as handle:
|
||||||
return handle.write(dumps(db))
|
handle.write(dumps(db))
|
||||||
|
|
||||||
|
|
||||||
def load_db():
|
def load_db() -> Dict:
|
||||||
"""Load the database."""
|
"""Load the database."""
|
||||||
db_path = DATA_DIR / "db.json"
|
db_path = DATA_DIR / "db.json"
|
||||||
if exists(db_path):
|
if exists(db_path):
|
||||||
@ -61,33 +52,64 @@ def load_db():
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
def stack_deploy(app_name, env):
|
||||||
|
"""Depoy an application to the swarm."""
|
||||||
|
compose_yml = DATA_DIR / app_name / "compose.yml"
|
||||||
|
command = f"docker stack deploy -c {compose_yml} {app_name}"
|
||||||
|
run(split(command), env=env)
|
||||||
|
|
||||||
|
|
||||||
|
def get_loaded_env(app_name, request_form):
|
||||||
|
"""Load an environment with install form values for compose.yml injection."""
|
||||||
|
environment = environ.copy()
|
||||||
|
for key in request_form.keys():
|
||||||
|
environment[key.upper()] = request.form[key]
|
||||||
|
return environment
|
||||||
|
|
||||||
|
|
||||||
|
class GiteaInstallForm(FlaskForm):
|
||||||
|
"""Gitea installation form."""
|
||||||
|
|
||||||
|
app_name = StringField("Application name", default="Git with a cup of tea")
|
||||||
|
domain = StringField("Domain name", validators=[DataRequired()])
|
||||||
|
|
||||||
|
db_host = StringField("Database host", default="mariadb:3306")
|
||||||
|
db_name = StringField("Database name", default="gitea")
|
||||||
|
db_passwd = PasswordField("DB password", default=get_secret(n=32))
|
||||||
|
db_root_passwd = PasswordField("Root DB password", default=get_secret(n=32))
|
||||||
|
db_type = StringField("Database type", default="mysql")
|
||||||
|
db_user = StringField("Database user", default="mysql")
|
||||||
|
internal_token = PasswordField("Internal token", default=get_secret(n=105))
|
||||||
|
jwt_secret = PasswordField("JWT secret", default=get_secret(n=43))
|
||||||
|
secret_key = PasswordField("Secret key", default=get_secret(n=64))
|
||||||
|
ssh_port = StringField("SSH port", default="2222")
|
||||||
|
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def index():
|
def index():
|
||||||
|
"""Home page for app installation possibilities."""
|
||||||
return render_template("second/index.html", apps=[app for app in APPS])
|
return render_template("second/index.html", apps=[app for app in APPS])
|
||||||
|
|
||||||
|
|
||||||
@app.route("/config/<app_name>")
|
@app.route("/install/<app_name>")
|
||||||
def config(app_name):
|
def install(app_name):
|
||||||
|
"""Installation page for an app."""
|
||||||
if app_name == "gitea":
|
if app_name == "gitea":
|
||||||
# Note(decentral1se): load db.json and pre-populate the form?
|
form = GiteaInstallForm()
|
||||||
form = GiteaConfigForm()
|
return render_template("second/install.html", app_name=app_name, form=form)
|
||||||
return render_template("second/config.html", app_name=app_name, form=form)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/deploy/<app_name>", methods=["POST"])
|
@app.route("/deploy/<app_name>", methods=["POST"])
|
||||||
def deploy(app_name):
|
def deploy(app_name):
|
||||||
environment = environ.copy()
|
"""Deployment end-point for an app."""
|
||||||
for key in request.form.keys():
|
environment = get_loaded_env(app_name, request.form)
|
||||||
environment[key.upper()] = request.form[key]
|
|
||||||
|
|
||||||
# Note(decentral1se): how to handle the following?
|
# Note(decentral1se): how to handle the following?
|
||||||
# configs -> ${STACK_NAME}_app_ini_${APP_INI_VERSION}
|
# configs -> ${STACK_NAME}_app_ini_${APP_INI_VERSION}
|
||||||
# secrets -> ${STACK_NAME}_db_passwd_${DB_PASSWD_VERSION}
|
# secrets -> ${STACK_NAME}_db_passwd_${DB_PASSWD_VERSION}
|
||||||
# and dump it all to the db.json when we're done here too
|
# and dump it all to the db.json when we're done here too
|
||||||
|
|
||||||
compose_yml = DATA_DIR / app_name / "compose.yml"
|
stack_deploy(app_name, environment)
|
||||||
command = f"docker stack deploy -c {compose_yml} {app_name}"
|
|
||||||
run(split(command), env=environment)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
Reference in New Issue
Block a user