mirror of
https://github.com/vacp2p/pod-api-requester.git
synced 2026-08-27 09:41:16 +00:00
- Use configs to define actions - Run a server to allow running commands interactively
137 lines
4.2 KiB
Python
137 lines
4.2 KiB
Python
import asyncio
|
|
import json
|
|
from typing import Literal, Optional
|
|
|
|
import requests
|
|
from kubernetes import client, config
|
|
from pydantic import NonNegativeInt
|
|
|
|
from utils import setup_logger
|
|
|
|
logger = setup_logger(__file__)
|
|
|
|
|
|
async def main():
|
|
raise NotImplementedError("Choose your Kubernetes config path and remove this.")
|
|
config.load_kube_config("/path_to_kube_config.yaml")
|
|
config.load_kube_config() # WARNING! LOCAL
|
|
publish_message(
|
|
namespace="zerotesting",
|
|
message_type="lightpush",
|
|
pod_name_template="lpclient-0-0",
|
|
service="zerotesting-lightpush-client",
|
|
)
|
|
|
|
|
|
PublishType = Literal["lightpush", "relay"]
|
|
|
|
|
|
async def publish_message(
|
|
namespace: str,
|
|
message_type: PublishType,
|
|
*,
|
|
pod_name_template: Optional[str] = None,
|
|
service: Optional[str] = None,
|
|
stateful_set_name: Optional[str] = None,
|
|
port: NonNegativeInt = 80,
|
|
):
|
|
if message_type == "lightpush":
|
|
endpoint = "lightpush-publish-static-sharding"
|
|
elif message_type == "relay":
|
|
raise NotImplementedError()
|
|
else:
|
|
raise ValueError("Unknown message type")
|
|
|
|
data = {
|
|
"target": {
|
|
"name": "dummy",
|
|
"service": service,
|
|
"name_template": pod_name_template,
|
|
"stateful_set": stateful_set_name,
|
|
"port": port,
|
|
},
|
|
"endpoint": endpoint,
|
|
}
|
|
|
|
return await pod_api_request(
|
|
namespace=namespace,
|
|
service_name="zerotesting-publisher",
|
|
app="zerotenkay-publisher",
|
|
data=data,
|
|
)
|
|
|
|
|
|
class PodApiRequestError(Exception):
|
|
pass
|
|
|
|
|
|
async def pod_api_request(
|
|
namespace: str,
|
|
service_name: str,
|
|
app: str,
|
|
data: dict,
|
|
*,
|
|
publisher_pod: str | NonNegativeInt = 0,
|
|
) -> dict:
|
|
v1 = client.CoreV1Api()
|
|
|
|
try:
|
|
pods = v1.list_namespaced_pod(namespace=namespace, label_selector=f"app={app}")
|
|
if isinstance(publisher_pod, str):
|
|
pod = next(pod for pod in pods.items if pod.metadata.name == publisher_pod)
|
|
else:
|
|
pod = pods.items[publisher_pod]
|
|
except IndexError as e:
|
|
logger.error(f"No pod found. app: `{app}` pod_index: `{publisher_pod}`")
|
|
raise ValueError() from e
|
|
except StopIteration as e:
|
|
logger.error(f"No pod found. app: `{app}` pod_name: `{publisher_pod}`")
|
|
raise ValueError() from e
|
|
|
|
# Get publisher IP.
|
|
node = v1.read_node(name=pod.spec.node_name)
|
|
target_ip = kube_utils.get_node_ip(node)
|
|
|
|
# Get publisher port.
|
|
service = v1.read_namespaced_service(service_name, namespace)
|
|
node_port = service.spec.ports[0].node_port
|
|
if node_port is None:
|
|
raise ValueError(f"Failed to find port for service. Service: `{service.metadata.name}`")
|
|
|
|
url = f"http://{target_ip}:{node_port}/process"
|
|
|
|
logger.info(f"publishing message. url: `{url}` data: `{data}`")
|
|
response = requests.post(url, json=data)
|
|
response_obj = json.loads(response.text)
|
|
if response.status_code != 200:
|
|
err = response_obj["detail"].replace("\n", "\n")
|
|
logger.error(err)
|
|
raise PodApiRequestError(response_obj)
|
|
|
|
try:
|
|
# Assuming that the pod we made the API request to returns a response with a JSON object.
|
|
inner_response_obj = json.loads(response_obj["response"]["text"])
|
|
response_obj["inner_response"] = inner_response_obj
|
|
if response_obj["response"]["status_code"] != 200:
|
|
# JsWaku puts the error under the key "error".
|
|
try:
|
|
err = inner_response_obj["error"].replace("\n", "\n")
|
|
except KeyError as e:
|
|
err = "<Failed to extract inner error>"
|
|
logger.error(f"Publisher request returned failure. inner_error: `{err}`")
|
|
raise PodApiRequestError(response_obj)
|
|
except json.JSONDecodeError as e:
|
|
# Response was not a Json object.
|
|
pass
|
|
except KeyError as e:
|
|
err = response_obj["exception"].replace("\n", "\n")
|
|
logger.error(f"The publisher's API request attempt failed. Exception: `{err}`")
|
|
raise PodApiRequestError(response_obj) from e
|
|
|
|
logger.info(f"Response: `{response_obj}`")
|
|
return response_obj
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|