215 lines
6.1 KiB
Python
215 lines
6.1 KiB
Python
import os
|
|
from typing import Any
|
|
from subprocess import run
|
|
|
|
from api.API import API
|
|
from utils.ApiCaller import ApiCaller
|
|
|
|
|
|
class Instance:
|
|
_id: str
|
|
name: str
|
|
hostname: str
|
|
_type: str
|
|
health: bool
|
|
env: Any
|
|
apiCaller: ApiCaller
|
|
|
|
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 get_id(self) -> str:
|
|
return self._id
|
|
|
|
def run_jobs(self) -> bool:
|
|
return self.apiCaller._send_to_apis("POST", "/jobs")
|
|
|
|
def reload(self) -> bool:
|
|
return self.apiCaller._send_to_apis("POST", "/reload")
|
|
|
|
def start(self) -> bool:
|
|
return self.apiCaller._send_to_apis("POST", "/start")
|
|
|
|
def stop(self) -> bool:
|
|
return self.apiCaller._send_to_apis("POST", "/stop")
|
|
|
|
def restart(self) -> bool:
|
|
return self.apiCaller._send_to_apis("POST", "/restart")
|
|
|
|
|
|
class Instances:
|
|
def __init__(self, docker_client):
|
|
self.__docker = docker_client
|
|
|
|
def __instance_from_id(self, _id) -> Instance:
|
|
instances: list[Instance] = self.get_instances()
|
|
for instance in instances:
|
|
if instance._id == _id:
|
|
return instance
|
|
|
|
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}"
|