aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornkozlovskiy <nmk@ydb.tech>2023-12-11 19:20:11 +0300
committernkozlovskiy <nmk@ydb.tech>2023-12-11 20:10:34 +0300
commite032a9d10c50b991ce08b32590bbaf15089ff059 (patch)
tree08f835e5978e2411a830b9f1376355c5c4c4d27f
parentb881dd49f80073cf4e78ce7a30d342254252e40b (diff)
downloadydb-e032a9d10c50b991ce08b32590bbaf15089ff059.tar.gz
ci: add missing ydb/ci sync
-rwxr-xr-xydb/ci/testmo-proxy/testmo-proxy.py111
1 files changed, 111 insertions, 0 deletions
diff --git a/ydb/ci/testmo-proxy/testmo-proxy.py b/ydb/ci/testmo-proxy/testmo-proxy.py
new file mode 100755
index 0000000000..9014de0110
--- /dev/null
+++ b/ydb/ci/testmo-proxy/testmo-proxy.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python3
+import argparse
+import http.server
+import ssl
+import time
+import urllib.parse
+from typing import Tuple
+
+import requests
+from requests.utils import CaseInsensitiveDict
+
+
+class Handler(http.server.BaseHTTPRequestHandler):
+ protocol_version = "HTTP/1.1"
+ error_message_format = '{"status":"error", "code":"%(code)d", "message": "%(message)s"}\n'
+
+ # noinspection PyMissingConstructor
+ def __init__(self, target_url: str, timeout: Tuple[int, int], max_reqest_time: int):
+ self._target_url = target_url
+ self._timeout = timeout
+ self._max_request_time = max_reqest_time
+
+ def __call__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ def log_date_time_string(self):
+ """Return the current time formatted for logging."""
+ now = time.time()
+ msecs = int((now - int(now)) * 1000) + 0.0
+ return f"{time.strftime('%Y-%m-%d %H:%M:%S')},{msecs:03.0f}"
+
+ def _proxy_request(self, method):
+ url = urllib.parse.urljoin(self._target_url, self.path)
+
+ headers = CaseInsensitiveDict(self.headers.items())
+ del headers["host"]
+
+ body = ""
+
+ if "content-length" in headers:
+ body = self.rfile.read(int(headers["content-length"]))
+
+ self.log_message(f"< method={method} url={url} length={len(body)}")
+
+ start_time = time.monotonic()
+
+ response = None
+
+ while time.monotonic() - start_time < self._max_request_time:
+ try:
+ response = requests.request(method, url, data=body, headers=headers, timeout=self._timeout)
+ break
+ except requests.exceptions.ConnectionError as e:
+ self.log_message("! catch IOError(%s), retry", e)
+ time.sleep(0.25)
+ continue
+
+ if response is None:
+ self.log_message("! Unable to get testmo response, send 204 response for skipping this batch")
+ self.send_response_only(204)
+ self.send_header("X-Fake-Status", "true")
+ self.end_headers()
+ return
+
+ response_body = response.content
+ self.log_message(f"= status={response.status_code}, length={len(response_body)}")
+
+ self.send_response_only(response.status_code, response.reason)
+
+ for k, v in response.headers.items():
+ if k.lower() in ("connection", "transfer-encoding", "content-length"):
+ continue
+
+ self.send_header(k, v)
+
+ self.send_header("Content-Length", str(len(response_body)))
+ self.end_headers()
+ self.wfile.write(response_body)
+
+ def do_GET(self):
+ self._proxy_request("GET")
+
+ def do_POST(self):
+ self._proxy_request("POST")
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-l", dest="listen", default="127.0.0.1:8888")
+ parser.add_argument("--cert-file", dest="certfile", required=True)
+ parser.add_argument("--cert-key", dest="keyfile", required=True)
+ parser.add_argument("--target-timeout", dest="target_timeout", default="3,10")
+ parser.add_argument("--max-request-time", dest="max_request_time", type=int, default=55)
+ parser.add_argument("target_url")
+ args = parser.parse_args()
+
+ addr_parts = args.listen.split(":")
+ addr = (addr_parts[0], int(addr_parts[1]))
+ timeout = tuple(map(int, args.target_timeout.split(",")))
+
+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
+ ctx.load_cert_chain(certfile=args.certfile, keyfile=args.keyfile)
+
+ # noinspection PyTypeChecker
+ srv = http.server.HTTPServer(addr, Handler(args.target_url, timeout, args.max_request_time))
+ srv.socket = ctx.wrap_socket(srv.socket, server_side=True)
+ srv.serve_forever()
+
+
+if __name__ == "__main__":
+ main()