bunkerweb 1.4.0

This commit is contained in:
bunkerity
2022-06-03 17:24:14 +02:00
parent 3a078326c5
commit a9f886804a
5245 changed files with 1432051 additions and 27894 deletions

View File

@@ -1,156 +1,214 @@
import docker, os, requests, subprocess
import os
from typing import Any
from subprocess import run
class Instances :
from api.API import API
from utils.ApiCaller import ApiCaller
def __init__(self, docker_host, api_uri) :
try :
self.__docker = docker.DockerClient(base_url=docker_host)
except :
self.__docker = None
self.__api_uri = api_uri
def __instance(self, id, name, type, status, data=None) :
instance = {}
instance["id"] = id
instance["name"] = name
instance["type"] = type
instance["status"] = status
instance["data"] = data
return instance
class Instance:
_id: str
name: str
hostname: str
_type: str
health: bool
env: Any
apiCaller: ApiCaller
def __api_request(self, instance, order) :
result = True
hosts = []
if instance["type"] == "container" :
hosts.append(instance["name"])
elif instances["type"] == "service" :
for task in instance["data"].tasks() :
host = instance["name"] + "." + task["NodeID"] + "." + task["ID"]
hosts.append(host)
for host in hosts :
try :
req = requests.post("http://" + host + ":8080" + self.__api_uri + order)
if not req or req.status_code != 200 or req.text != "ok" :
result = False
except :
result = False
return result
def __init__(
self,
_id: str,
name: str,
hostname: str,
_type: str,
status: str,
data: Any = None,
apiCaller: ApiCaller = ApiCaller(),
) -> None:
self._id = _id
self.name = name
self.hostname = hostname
self._type = _type
self.health = status == "up" and (
(
data.attrs["State"]["Health"]["Status"] == "healthy"
if "Health" in data.attrs["State"]
else False
)
if data
else True
)
self.env = data
self.apiCaller = apiCaller
def __instance_from_id(self, id) :
instances = self.get_instances()
for instance in instances :
if instance["id"] == id :
return instance
raise Exception("Can't find instance with id " + id)
def get_id(self) -> str:
return self._id
def get_instances(self) :
instances = []
def run_jobs(self) -> bool:
return self.apiCaller._send_to_apis("POST", "/jobs")
# Docker instances (containers or services)
if self.__docker != None :
for instance in self.__docker.containers.list(all=True, filters={"label" : "bunkerized-nginx.UI"}) :
id = instance.id
name = instance.name
type = "container"
status = "down"
if instance.status == "running" :
status = "up"
instances.append(self.__instance(id, name, type, status, instance))
is_swarm = True
try :
version = self.__docker.swarm.version
except :
is_swarm = False
if is_swarm :
for instance in self.__docker.services.list(filters={"label" : "bunkerized-nginx.UI"}) :
id = instance.id
name = instance.name
type = "service"
status = "down"
desired_tasks = instance.attrs["ServiceStatus"]["DesiredTasks"]
running_tasks = instance.attrs["ServiceStatus"]["RunningTasks"]
if desired_tasks > 0 and (desired_tasks == running_tasks) :
status = "up"
instances.append(self.__instance(id, name, type, status, instance))
def reload(self) -> bool:
return self.apiCaller._send_to_apis("POST", "/reload")
# Local instance
if os.path.exists("/usr/sbin/nginx") :
id = "local"
name = "local"
type = "local"
status = "down"
if os.path.exists("/tmp/nginx.pid") :
status = "up"
instances.append(self.__instance(id, name, type, status))
def start(self) -> bool:
return self.apiCaller._send_to_apis("POST", "/start")
return instances
def stop(self) -> bool:
return self.apiCaller._send_to_apis("POST", "/stop")
def reload_instances(self) :
all_reload = True
for instance in self.get_instances() :
if instance["status"] == "down" :
all_reload = False
continue
if instance["type"] == "local" :
proc = subprocess.run(["/opt/bunkerized-nginx/entrypoint/jobs.sh"], capture_output=True)
if proc.returncode != 0 :
all_reload = False
else :
proc = subprocess.run(["sudo", "/opt/bunkerized-nginx/ui/linux.sh", "reload"], capture_output=True)
if proc.returncode != 0 :
all_reload = False
elif instance["type"] == "container" or instance["type"] == "service" :
all_reload = self.__api_request(instance, "/reload")
return all_reload
def restart(self) -> bool:
return self.apiCaller._send_to_apis("POST", "/restart")
def reload_instance(self, id) :
instance = self.__instance_from_id(id)
result = True
if instance["type"] == "local" :
proc = subprocess.run(["/opt/bunkerized-nginx/entrypoint/jobs.sh"], capture_output=True)
if proc.returncode != 0 :
result = False
else :
proc = subprocess.run(["sudo", "/opt/bunkerized-nginx/ui/linux.sh", "reload"], capture_output=True)
result = proc.returncode == 0
elif instance["type"] == "container" or instance["type"] == "service" :
result = self.__api_request(instance, "/reload")
if result :
return "Instance " + instance["name"] + " has been reloaded."
return "Can't reload " + instance["name"]
def start_instance(self, id) :
instance = self.__instance_from_id(id)
result = True
if instance["type"] == "local" :
proc = subprocess.run(["sudo", "/opt/bunkerized-nginx/ui/linux.sh", "start"], capture_output=True)
result = proc.returncode == 0
elif instance["type"] == "container" or instance["type"] == "service" :
result = False #self.__api_request(instance, "/start")
if result :
return "Instance " + instance["name"] + " has been started."
return "Can't start " + instance["name"]
class Instances:
def __init__(self, docker_client):
self.__docker = docker_client
def stop_instance(self, id) :
instance = self.__instance_from_id(id)
result = True
if instance["type"] == "local" :
proc = subprocess.run(["sudo", "/opt/bunkerized-nginx/ui/linux.sh", "stop"], capture_output=True)
result = proc.returncode == 0
elif instance["type"] == "container" or instance["type"] == "service" :
result = self.__api_request(instance, "/stop")
if result :
return "Instance " + instance["name"] + " has been stopped."
return "Can't stop " + instance["name"]
def __instance_from_id(self, _id) -> Instance:
instances: list[Instance] = self.get_instances()
for instance in instances:
if instance._id == _id:
return instance
def restart_instance(self, id) :
instance = self.__instance_from_id(id)
result = True
if instance["type"] == "local" :
proc = subprocess.run(["sudo", "/opt/bunkerized-nginx/ui/linux.sh", "restart"], capture_output=True)
result = proc.returncode == 0
elif instance["type"] == "container" or instance["type"] == "service" :
result = False #self.__api_request(instance, "/restart")
if result :
return "Instance " + instance["name"] + " has been restarted."
return "Can't restart " + instance["name"]
raise Exception(f"Can't find instance with id {_id}")
def get_instances(self) -> list[Instance]:
instances = []
# Docker instances (containers or services)
if self.__docker is not None:
for instance in self.__docker.containers.list(
all=True, filters={"label": "bunkerweb.UI"}
):
env_variables = {
x[0]: x[1]
for x in [env.split("=") for env in instance.attrs["Config"]["Env"]]
}
apiCaller = ApiCaller()
apiCaller._set_apis(
[
API(
f"http://{instance.name}:{env_variables.get('API_HTTP_PORT', '5000')}",
env_variables.get("API_SERVER_NAME", "bwapi"),
)
]
)
instances.append(
Instance(
instance.id,
instance.name,
instance.name,
"container",
"up" if instance.status == "running" else "down",
instance,
apiCaller,
)
)
instances = sorted(
instances,
key=lambda x: x.name,
)
# Local instance
if os.path.exists("/usr/sbin/nginx"):
instances.insert(
0,
Instance(
"local",
"local",
"127.0.0.1",
"local",
"up" if os.path.exists("/opt/bunkerweb/tmp/nginx.pid") else "down",
),
)
return instances
def reload_instances(self) -> list[str]:
not_reloaded: list[str] = []
for instance in self.get_instances():
if instance.health is False:
not_reloaded.append(instance.name)
continue
if self.reload_instance(None, instance).startswith("Can't reload"):
not_reloaded.append(instance.name)
return not_reloaded
def reload_instance(self, id: int = None, instance: Instance = None) -> str:
if instance is None:
instance = self.__instance_from_id(id)
result = True
if instance._type == "local":
result = (
run(
["sudo", "systemctl", "restart", "bunkerweb"], capture_output=True
).returncode
!= 0
)
elif instance._type == "container":
result = instance.run_jobs()
result = result & instance.reload()
if result:
return f"Instance {instance.name} has been reloaded."
return f"Can't reload {instance.name}"
def start_instance(self, id) -> str:
instance = self.__instance_from_id(id)
result = True
if instance._type == "local":
proc = run(
["sudo", "/opt/bunkerweb/ui/linux.sh", "start"],
capture_output=True,
)
result = proc.returncode == 0
elif instance._type == "container":
result = instance.start()
if result:
return f"Instance {instance.name} has been started."
return f"Can't start {instance.name}"
def stop_instance(self, id) -> str:
instance = self.__instance_from_id(id)
result = True
if instance._type == "local":
proc = run(
["sudo", "/opt/bunkerweb/ui/linux.sh", "stop"],
capture_output=True,
)
result = proc.returncode == 0
elif instance._type == "container":
result = instance.stop()
if result:
return f"Instance {instance.name} has been stopped."
return f"Can't stop {instance.name}"
def restart_instance(self, id) -> str:
instance = self.__instance_from_id(id)
result = True
if instance._type == "local":
proc = run(
["sudo", "/opt/bunkerweb/ui/linux.sh", "restart"],
capture_output=True,
)
result = proc.returncode == 0
elif instance._type == "container":
result = instance.restart()
if result:
return f"Instance {instance.name} has been restarted."
return f"Can't restart {instance.name}"