much cleanup

This commit is contained in:
Lee 2024-01-15 22:59:08 +00:00
parent 23852729c1
commit 7b83facc21
8 changed files with 247 additions and 155 deletions

12
src/command/command.py Normal file

@ -0,0 +1,12 @@
class Command:
def __init__(self, name:str, description:str, usage:str):
self.name = name
self.description = description
self.usage = usage
async def execute(self, traefikConfig, args):
pass
def printUsage(self):
print("Usage: %s" % self.usage)
pass

@ -0,0 +1,27 @@
from command.impl.addCommand import AddCommand
from command.impl.listCommand import ListCommand
from command.impl.removeCommand import RemoveCommand
class CommandManager:
commands = []
def __init__(self):
self.addCommand(AddCommand())
self.addCommand(RemoveCommand())
self.addCommand(ListCommand())
pass
def addCommand(self, command):
self.commands.append(command)
pass
def getCommand(self, name):
for command in self.commands:
if command.name == name:
return command
return None
def commandExists(self, name):
return self.getCommand(name) != None

@ -0,0 +1,31 @@
from command.command import Command
from traefik.traefikConfig import TraefikConfig
from utils.dockerUtils import restartTraefik
class AddCommand(Command):
def __init__(self):
super().__init__("add", "Add a domain", "add <name> <domain> <service host>")
def execute(self, traefikConfig:TraefikConfig, args):
if len(args) < 3:
self.printUsage()
return
name = args[0]
domain = args[1]
serviceHost = args[2]
if traefikConfig.hasRouter(name):
print(f"Router \"{name}\" already exists")
return
print(f"Adding \"{domain}\" -> \"{serviceHost}\"")
traefikConfig.addRouter(name, domain, serviceHost)
traefikConfig.addService(name, serviceHost)
traefikConfig.save()
restartTraefik()
print("Done!")

@ -0,0 +1,19 @@
from colorama import Fore
from command.command import Command
from traefik.traefikConfig import TraefikConfig
class ListCommand(Command):
def __init__(self):
super().__init__("list", "List all services", "list")
def execute(self, traefikConfig:TraefikConfig, args):
print("Listing all services:")
domains = traefikConfig.getAll()
# Print domains
for name, domain in domains.items():
print(f" - {Fore.CYAN}[{name}] {Fore.GREEN}http://{domain['domain']} {Fore.RESET}-> {Fore.YELLOW}{domain['serviceHost']}{Fore.RESET}")
print("")
print("Total: %s" % len(domains))

@ -0,0 +1,29 @@
from colorama import Fore
from command.command import Command
from traefik.traefikConfig import TraefikConfig
from utils.dockerUtils import restartTraefik
class RemoveCommand(Command):
def __init__(self):
super().__init__("remove", "Remove a domain", "remove <name>")
def execute(self, traefikConfig:TraefikConfig, args):
if len(args) < 0:
self.printUsage()
return
name = args[0]
if not traefikConfig.hasRouter(name):
print(f"Router \"{name}\" does not exist")
return
print(f"Removing \"{name}\"")
traefikConfig.removeRouter(name)
traefikConfig.save()
restartTraefik()
print(f"Removed \"{name}\"")

@ -1,171 +1,31 @@
import sys
import subprocess
import yaml
import os
from colorama import Fore
from command.commandManager import CommandManager
from traefik.traefikConfig import TraefikConfig
# Variables
configFile = "./config.yml"
containerName = "traefik"
# Are we running in a Docker container?
if os.environ.get("CONFIG_FILE"):
configFile = os.environ.get("CONFIG_FILE")
if os.environ.get("CONTAINER_NAME"):
containerName = os.environ.get("CONTAINER_NAME")
# DO NOT TOUCH
commands = ["add", "remove", "list", "update"]
traefikConfig = TraefikConfig(configFile)
if traefikConfig.isValid() == False:
print("Invalid traefik config file, please check your config.yml file")
exit(1)
command = len(sys.argv) > 1 and sys.argv[1]
commandManager = CommandManager()
if command not in commands:
print("")
print("Usage: manage.py [command]")
if not commandManager.commandExists(command):
print("Usage: manage [command]")
print("")
print("Commands:")
print(" - add [name] [domain] [service host]")
print(" - remove [name]")
print(" - update [name] [new service host]")
print(" - list")
for command in commandManager.commands:
print(f" - {command.usage}")
exit()
with open(configFile, "r") as config:
configYml = yaml.safe_load(config)
http = configYml["http"]
routers = http["routers"]
services = http["services"]
def restartTraefik():
print("Restarting Traefik, please wait this can take a while...")
# Restart Traefik in the base directory
subprocess.run(["docker", "restart", "traefik"])
print(f"{Fore.GREEN}Done!{Fore.RESET}")
def addDomain(name, domain, serviceHost):
# Check if name already exists
if name in routers:
print(f"Name \"{Fore.RED}{name}{Fore.RESET}\" already exists")
exit()
print(f"Adding domain \"{Fore.CYAN}{name}{Fore.RESET}\" -> \"{Fore.YELLOW}{serviceHost}{Fore.RESET}\"")
print(f"Domain: {Fore.GREEN}http://{domain}{Fore.RESET}")
# Add router
routers[name] = {
"entryPoints": ["https"],
"rule": "Host(`%s`)" % domain,
"middlewares": ["default-headers", "https-redirectscheme"],
"tls": {},
"service": name
}
# Add service
services[name] = {
"loadBalancer": {
"servers": [
{
"url": serviceHost
}
]
}
}
# Write to file
with open(configFile, "w") as config:
yaml.dump(configYml, config)
# Restart Traefik
restartTraefik()
def removeDomain(name):
# Check if name exists
if name not in routers:
print(f"Name \"{Fore.RED}{name}{Fore.RESET}\" does not exist")
exit()
print(f"Removing domain \"{Fore.CYAN}{name}{Fore.RESET}\"")
# Remove router
del routers[name]
# Remove service
del services[name]
# Write to file
with open(configFile, "w") as config:
yaml.dump(configYml, config)
# Restart Traefik
restartTraefik()
def listDomains():
print("Listing domains:")
# name and domain -> service host
domains = {}
# Loop through routers
for name, router in routers.items():
# Get domain
domain = router["rule"].split("`")[1]
# Get service host
serviceHost = services[name]["loadBalancer"]["servers"][0]["url"]
# Add to domains
domains[name] = {
"domain": domain,
"serviceHost": serviceHost
}
# Print domains
for name, domain in domains.items():
print(f" - {Fore.CYAN}[{name}] {Fore.GREEN}http://{domain['domain']} {Fore.RESET}-> {Fore.YELLOW}{domain['serviceHost']}{Fore.RESET}")
print("")
print("Total: %s" % len(domains))
def updateDomain(name, serviceHost):
# Check if name exists
if name not in routers:
print("Name \"%s\" does not exist" % name)
exit()
print(f"Updating domain \"{Fore.CYAN}{name}{Fore.RESET}\" -> \"{Fore.YELLOW}{serviceHost}{Fore.RESET}\"")
# Update service
services[name] = {
"loadBalancer": {
"servers": [
{
"url": serviceHost
}
]
}
}
# Write to file
with open(configFile, "w") as config:
yaml.dump(configYml, config)
# Restart Traefik
restartTraefik()
match command:
case "add":
name = sys.argv[2]
domain = sys.argv[3]
serviceHost = sys.argv[4]
addDomain(name, domain, serviceHost)
case "remove":
name = sys.argv[2]
removeDomain(name)
case "update":
name = sys.argv[2]
serviceHost = sys.argv[3]
updateDomain(name, serviceHost)
case "list":
listDomains()
args = sys.argv[2:]
commandManager.getCommand(command).execute(traefikConfig, args)

@ -0,0 +1,96 @@
import yaml
class TraefikConfig:
def __init__(self, configFile) -> None:
self.configFile = configFile
with open(configFile, "r") as config:
self.configYml = yaml.safe_load(config)
def isValid(self) -> bool:
return "http" in self.configYml and "routers" in self.configYml["http"] and "services" in self.configYml["http"]
def getRouter(self, name):
return self.configYml["http"]["routers"][name]
def getService(self, name):
return self.configYml["http"]["services"][name]
def addRouter(self, name, domain, serviceHost):
# Add router
self.configYml["http"]["routers"][name] = {
"entryPoints": ["https"],
"rule": "Host(`%s`)" % domain,
"middlewares": ["default-headers", "https-redirectscheme"],
"tls": {},
"service": name
}
# Add service
self.configYml["http"]["services"][name] = {
"loadBalancer": {
"servers": [
{
"url": serviceHost
}
]
}
}
def removeRouter(self, name):
# Remove router
del self.configYml["http"]["routers"][name]
# Remove service
del self.configYml["http"]["services"][name]
def hasRouter(self, name):
return name in self.configYml["http"]["routers"]
def addService(self, name, serviceHost):
# Add service
self.configYml["http"]["services"][name] = {
"loadBalancer": {
"servers": [
{
"url": serviceHost
}
]
}
}
def hasService(self, name):
return name in self.configYml["http"]["services"]
def getRouters(self):
return self.configYml["http"]["routers"]
def getServices(self):
return self.configYml["http"]["services"]
def getAll(self):
domains = {}
routers = self.getRouters()
services = self.getServices()
# Loop through routers
for name, router in routers.items():
# Get domain
domain = router["rule"].split("`")[1]
# Get service host
serviceHost = services[name]["loadBalancer"]["servers"][0]["url"]
# Add to domains
domains[name] = {
"domain": domain,
"serviceHost": serviceHost
}
return domains
def save(self):
with open(self.configFile, "w") as config:
yaml.dump(self.configYml, config)

18
src/utils/dockerUtils.py Normal file

@ -0,0 +1,18 @@
import subprocess
import os
containerName = "traefik"
if os.environ.get("CONTAINER_NAME"):
containerName = os.environ.get("CONTAINER_NAME")
def restartTraefik():
# Check if we're in Windows, if so, don't restart Traefik
if os.name == "nt":
print("Restarting Traefik is not supported on Windows.")
return
print("Restarting Traefik, please wait this can take a while...")
# Restart Traefik in the base directory
subprocess.run(["docker", "restart", containerName])
print("Done!")