Added comments
This commit is contained in:
203
service.py
203
service.py
@@ -1,59 +1,160 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
from pathlib import Path
|
||||
from os import path
|
||||
import subprocess as sub
|
||||
import re
|
||||
from typing import Any, Callable
|
||||
|
||||
P_BANNER = """
|
||||
██╗ ██╗███████╗██╗ ██╗ ██╗ ██████╗ ███╗ ███╗
|
||||
██║ ██║██╔════╝██║ ██║ ██╔╝██╔═══██╗████╗ ████║
|
||||
██║ █╗ ██║█████╗ ██║ █████╔╝ ██║ ██║██╔████╔██║
|
||||
██║███╗██║██╔══╝ ██║ ██╔═██╗ ██║ ██║██║╚██╔╝██║
|
||||
╚███╔███╔╝███████╗███████╗██║ ██╗╚██████╔╝██║ ╚═╝ ██║
|
||||
╚══╝╚══╝ ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
|
||||
"""
|
||||
|
||||
P_OPTIONS = """
|
||||
Options:
|
||||
0) Exit
|
||||
1) Maak/Update klantomgeving(en)
|
||||
2) Vernietig klantomgeving(en)
|
||||
3) Recover klantomgeving(en)
|
||||
4) List klantomgeving(en)
|
||||
|
||||
h) Help
|
||||
Opties:
|
||||
0) Afsluiten
|
||||
1) Maak/Wijzig omgeving(en)
|
||||
2) Vernietig omgeving(en)
|
||||
3) Recover omgeving(en)
|
||||
4) List omgeving(en)
|
||||
"""
|
||||
|
||||
RE_TEXT = re.compile(r"^\w+$")
|
||||
RE_NUM = re.compile(r"^\d+$")
|
||||
RE_ANY = re.compile(r".+")
|
||||
|
||||
|
||||
def _take_input(prompt: str, pattern: re.Pattern, default: str="") -> str:
|
||||
while True:
|
||||
i = input(prompt)
|
||||
if i == "":
|
||||
i = default
|
||||
if pattern.match(i):
|
||||
return i
|
||||
class Prompter:
|
||||
|
||||
def __init__(self, ps1: str = "") -> None:
|
||||
self.ps1 = ps1
|
||||
|
||||
def _build_prompt(self, prompt: str) -> str:
|
||||
return self.ps1 + prompt
|
||||
|
||||
def take_input(self,
|
||||
prompt: str,
|
||||
pattern: re.Pattern[Any],
|
||||
default: str = "") -> str:
|
||||
prompt = self._build_prompt(prompt)
|
||||
return Prompter.input(prompt, lambda x: bool(pattern.match(x)),
|
||||
default)
|
||||
|
||||
def take_choice(self, prompt: str, options: list[str]) -> str:
|
||||
prompt = self._build_prompt(prompt)
|
||||
return Prompter.input(prompt, lambda x: x in options)
|
||||
|
||||
@staticmethod
|
||||
def input(prompt: str,
|
||||
validate: Callable[[str], bool],
|
||||
default: str = "") -> str:
|
||||
while True:
|
||||
i = input(prompt)
|
||||
if i == "":
|
||||
i = default
|
||||
if validate(i):
|
||||
return i
|
||||
|
||||
|
||||
def get_env_list(customer: str) -> list[str]:
|
||||
"""Fetches and parses a list of a customer's environments
|
||||
|
||||
Args:
|
||||
customer (str): The customer to fetch environments from
|
||||
|
||||
Returns:
|
||||
list[str]: The parsed environments
|
||||
"""
|
||||
return sub.check_output(["python3", "cli.py", "list",
|
||||
customer]).decode().strip("\n").split(" ")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
print(P_BANNER)
|
||||
customer_name = Prompter.input("Wat is uw naam: ",
|
||||
lambda x: bool(RE_TEXT.match(x)))
|
||||
|
||||
"""
|
||||
Ensures the necessary customer setup.
|
||||
"""
|
||||
envs_dir = path.join("customers", customer_name, "envs")
|
||||
Path(envs_dir).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
"""
|
||||
Initializes models for the event loop
|
||||
"""
|
||||
p = Prompter(ps1=f"{customer_name} > ")
|
||||
|
||||
"""
|
||||
The main "event" loop
|
||||
"""
|
||||
while True:
|
||||
print(P_OPTIONS)
|
||||
c = input("Input: ")
|
||||
if c == "h":
|
||||
continue
|
||||
c = p.take_input("Keuze: ", RE_ANY)
|
||||
print(end="\n")
|
||||
|
||||
if c == "0":
|
||||
"""
|
||||
Used to break out of the loop and exit the portal.
|
||||
"""
|
||||
break
|
||||
|
||||
if c == "1":
|
||||
customer_name = _take_input("Customer name (example=opg): ",
|
||||
RE_TEXT)
|
||||
env_name = _take_input("Environment name (example=prod): ",
|
||||
RE_TEXT)
|
||||
amnt_nginx_web = _take_input(
|
||||
"Number of nginx webservers (default=1): ", RE_NUM, default="1")
|
||||
amnt_nginx_lb = _take_input(
|
||||
"Number of nginx loadbalancers (default=1): ", RE_NUM, default="1")
|
||||
amnt_psql = _take_input(
|
||||
"Number of postgres instances (default=1): ", RE_NUM, default="1")
|
||||
ip_format = _take_input(
|
||||
"Format of ip (default=192.168.56.{}, `{}` will be replaced with the correct octet at runtime): ",
|
||||
re.compile(r".+"), default="192.168.56.{}")
|
||||
ip_int = _take_input(
|
||||
"Number to start formatting the IP from (default=10): ",
|
||||
RE_NUM, default="10")
|
||||
"""
|
||||
Used to either update or create an environment.
|
||||
"""
|
||||
envs = get_env_list(customer_name)
|
||||
print(f"NOTE: Kies een albestaande omgevingen {envs} of iets nieuws...")
|
||||
fmt = "Omgevingsnaam:"
|
||||
env_name = p.take_input(fmt, RE_TEXT)
|
||||
|
||||
templates = ["production", "acceptance", "test", "custom"]
|
||||
fmt = f"Het type omgeving {templates}: "
|
||||
template_name = p.take_choice(fmt, templates)
|
||||
|
||||
if template_name == "custom":
|
||||
"""
|
||||
Asks for all machine's individually
|
||||
"""
|
||||
fmt = "Aantal nginx webservers (default=1): "
|
||||
amnt_nginx_web = p.take_input(fmt, RE_NUM, default="1")
|
||||
|
||||
fmt = "Aantal nginx loadbalancers (default=1): "
|
||||
amnt_nginx_lb = p.take_input(fmt, RE_NUM, default="1")
|
||||
|
||||
fmt = "Aantal postgres instances (default=1): "
|
||||
amnt_psql = p.take_input(fmt, RE_NUM, default="1")
|
||||
elif template_name == "production":
|
||||
amnt_nginx_web = "2"
|
||||
amnt_nginx_lb = "1"
|
||||
amnt_psql = "1"
|
||||
elif template_name == "acceptance":
|
||||
amnt_nginx_web = "1"
|
||||
amnt_nginx_lb = "0"
|
||||
amnt_psql = "1"
|
||||
# elif template_name == "test":
|
||||
else:
|
||||
amnt_nginx_web = "1"
|
||||
amnt_nginx_lb = "0"
|
||||
amnt_psql = "0"
|
||||
|
||||
"""
|
||||
Define the format for templating ip-addresses.`{}` is required
|
||||
and will be subbed at runtime with the correct octet.
|
||||
"""
|
||||
print(end="\n")
|
||||
fmt = "NOTE: `{}` will be replaced with the correct octet at runtime"
|
||||
print(fmt)
|
||||
fmt = "Format of ip (default=192.168.56.{}): "
|
||||
ip_format = p.take_input(fmt, RE_ANY, default="192.168.56.{}")
|
||||
|
||||
fmt = "Number to start formatting the IP from (default=10): "
|
||||
ip_int = p.take_input(fmt, RE_NUM, default="10")
|
||||
|
||||
sub.call([
|
||||
"python3", "cli.py", "create", customer_name, env_name,
|
||||
@@ -61,25 +162,37 @@ def main() -> int:
|
||||
"--num-nginx-lb", amnt_nginx_lb, "--ip-format", ip_format,
|
||||
"--ip-int", ip_int
|
||||
])
|
||||
print(f"Omgeving `{env_name}` successvol gemaakt.")
|
||||
|
||||
if c == "2":
|
||||
customer_name = _take_input("Customer name (example=opg): ",
|
||||
RE_TEXT)
|
||||
env_name = _take_input("Environment name (example=prod): ",
|
||||
RE_TEXT)
|
||||
"""
|
||||
Deletes all traces of the chosen environment.
|
||||
"""
|
||||
envs = get_env_list(customer_name)
|
||||
fmt = f"Omgevingsnaam {envs}: "
|
||||
env_name = p.take_choice(fmt, envs)
|
||||
sub.call(["python3", "cli.py", "delete", customer_name, env_name])
|
||||
|
||||
if c == "3":
|
||||
customer_name = _take_input("Customer name (example=opg): ",
|
||||
RE_TEXT)
|
||||
env_name = _take_input("Environment name (example=prod): ",
|
||||
RE_TEXT)
|
||||
"""
|
||||
Allows the customer to "force" their environment into the desired `up-state`.
|
||||
This `up-state` is a representation of the Vagrantfile, Ansible inventory and
|
||||
.ssh directory of that specific environment. The .ssh directory is only
|
||||
necessary in case of an existing storage-volume. Otherwise a new one
|
||||
keypair can be manually created or created using option 1.
|
||||
"""
|
||||
envs = get_env_list(customer_name)
|
||||
fmt = f"Omgevingsnaam {envs}: "
|
||||
env_name = p.take_choice(fmt, envs)
|
||||
sub.call(["python3", "cli.py", "recover", customer_name, env_name])
|
||||
|
||||
if c == "4":
|
||||
customer_name = _take_input("Customer name (example=opg): ",
|
||||
RE_TEXT)
|
||||
sub.call(["python3", "cli.py", "list", customer_name])
|
||||
"""
|
||||
This branch displays the customer's existing environments
|
||||
"""
|
||||
print("De volgende omgeving(en) zijn aanwezig: ")
|
||||
for env in get_env_list(customer_name):
|
||||
print(f" - {env}")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user