mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
137 lines
5.2 KiB
Python
137 lines
5.2 KiB
Python
from io import BytesIO
|
|
from os import environ, getenv
|
|
from sys import path as sys_path
|
|
from tarfile import open as taropen
|
|
|
|
if "/opt/bunkerweb/utils" not in sys_path:
|
|
sys_path.append("/opt/bunkerweb/utils")
|
|
|
|
from logger import setup_logger
|
|
from API import API
|
|
|
|
if "/opt/bunkerweb/deps/python" not in sys_path:
|
|
sys_path.append("/opt/bunkerweb/deps/python")
|
|
|
|
from kubernetes import client as kube_client
|
|
from docker import DockerClient
|
|
|
|
|
|
class ApiCaller:
|
|
def __init__(self, apis=[]):
|
|
self.__apis = apis
|
|
self.__logger = setup_logger("Api", environ.get("LOG_LEVEL", "INFO"))
|
|
|
|
def auto_setup(self, bw_integration: str = None):
|
|
if bw_integration is None:
|
|
if getenv("KUBERNETES_MODE", "no") == "yes":
|
|
bw_integration = "Kubernetes"
|
|
elif getenv("SWARM_MODE", "no") == "yes":
|
|
bw_integration = "Swarm"
|
|
|
|
if bw_integration == "Kubernetes":
|
|
corev1 = kube_client.CoreV1Api()
|
|
for pod in corev1.list_pod_for_all_namespaces(watch=False).items:
|
|
if (
|
|
pod.metadata.annotations != None
|
|
and "bunkerweb.io/INSTANCE" in pod.metadata.annotations
|
|
):
|
|
api_http_port = None
|
|
api_server_name = None
|
|
|
|
for pod_env in pod.spec.containers[0].env:
|
|
if pod_env.name == "API_HTTP_PORT":
|
|
api_http_port = pod_env.value or "5000"
|
|
elif pod_env.name == "API_SERVER_NAME":
|
|
api_server_name = pod_env.value or "bwapi"
|
|
|
|
self.__apis.append(
|
|
API(
|
|
f"http://{pod.status.pod_ip}:{api_http_port or getenv('API_HTTP_PORT', '5000')}",
|
|
host=api_server_name or getenv("API_SERVER_NAME", "bwapi"),
|
|
)
|
|
)
|
|
elif bw_integration == "Swarm":
|
|
for instance in docker_client.services.list(
|
|
filters={"label": "bunkerweb.INSTANCE"}
|
|
):
|
|
api_http_port = None
|
|
api_server_name = None
|
|
|
|
for var in instance.attrs["Spec"]["TaskTemplate"]["ContainerSpec"][
|
|
"Env"
|
|
]:
|
|
if var.startswith("API_HTTP_PORT="):
|
|
api_http_port = var.replace("API_HTTP_PORT=", "", 1)
|
|
elif var.startswith("API_SERVER_NAME="):
|
|
api_server_name = var.replace("API_SERVER_NAME=", "", 1)
|
|
|
|
self.__apis.append(
|
|
API(
|
|
f"http://{instance.name}:{api_http_port or getenv('API_HTTP_PORT', '5000')}",
|
|
host=api_server_name or getenv("API_SERVER_NAME", "bwapi"),
|
|
)
|
|
)
|
|
else:
|
|
docker_client = DockerClient(
|
|
base_url=getenv("DOCKER_HOST", "unix:///var/run/docker.sock")
|
|
)
|
|
for instance in docker_client.containers.list(
|
|
filters={"label": "bunkerweb.INSTANCE"}
|
|
):
|
|
api_http_port = None
|
|
api_server_name = None
|
|
|
|
for var in instance.attrs["Config"]["Env"]:
|
|
if var.startswith("API_HTTP_PORT="):
|
|
api_http_port = var.replace("API_HTTP_PORT=", "", 1)
|
|
elif var.startswith("API_SERVER_NAME="):
|
|
api_server_name = var.replace("API_SERVER_NAME=", "", 1)
|
|
|
|
self.__apis.append(
|
|
API(
|
|
f"http://{instance.name}:{api_http_port or getenv('API_HTTP_PORT', '5000')}",
|
|
host=api_server_name or getenv("API_SERVER_NAME", "bwapi"),
|
|
)
|
|
)
|
|
|
|
def _set_apis(self, apis):
|
|
self.__apis = apis
|
|
|
|
def _get_apis(self):
|
|
return self.__apis
|
|
|
|
def _send_to_apis(self, method, url, files=None, data=None):
|
|
ret = True
|
|
for api in self.__apis:
|
|
if files is not None:
|
|
for buffer in files.values():
|
|
buffer.seek(0, 0)
|
|
sent, err, status, resp = api.request(method, url, files=files, data=data)
|
|
if not sent:
|
|
ret = False
|
|
self.__logger.error(
|
|
f"Can't send API request to {api.get_endpoint()}{url} : {err}",
|
|
)
|
|
else:
|
|
if status != 200:
|
|
ret = False
|
|
self.__logger.error(
|
|
f"Error while sending API request to {api.get_endpoint()}{url} : status = {resp['status']}, msg = {resp['msg']}",
|
|
)
|
|
else:
|
|
self.__logger.info(
|
|
f"Successfully sent API request to {api.get_endpoint()}{url}",
|
|
)
|
|
return ret
|
|
|
|
def _send_files(self, path, url):
|
|
ret = True
|
|
tgz = BytesIO()
|
|
with taropen(mode="w:gz", fileobj=tgz) as tf:
|
|
tf.add(path, arcname=".")
|
|
tgz.seek(0, 0)
|
|
files = {"archive.tar.gz": tgz}
|
|
if not self._send_to_apis("POST", url, files=files):
|
|
ret = False
|
|
tgz.close()
|
|
return ret
|