From a1e2a426b91c242363e0b0bb0d9d64a019943ae1 Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 2 Jul 2026 14:20:12 +0200 Subject: [PATCH] ISSUE-WP-0003-T06: issue-core REST sink via actcore-issue-core-bridge (node-local tunnel 18765) Co-Authored-By: Claude Fable 5 --- k8s/railiance/20-runtime.yaml | 115 +++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 2 deletions(-) diff --git a/k8s/railiance/20-runtime.yaml b/k8s/railiance/20-runtime.yaml index 1e017cd..1cf93b2 100644 --- a/k8s/railiance/20-runtime.yaml +++ b/k8s/railiance/20-runtime.yaml @@ -14,8 +14,8 @@ data: LLM_CONNECT_URL: http://llm-connect.activity-core.svc.cluster.local:8080 LLM_CONNECT_TIMEOUT_SECONDS: "300" REPO_SCOPING_URL: http://repo-scoping.repo-scoping.svc.cluster.local:8020 - ISSUE_CORE_URL: http://issue-core.issue-core.svc.cluster.local:8010 - ISSUE_SINK_TYPE: "null" + ISSUE_CORE_URL: http://actcore-issue-core-bridge.activity-core.svc.cluster.local:8765 + ISSUE_SINK_TYPE: "rest" ACTIVITY_DEFINITION_DIRS: /etc/activity-core/external-definitions OPS_INVENTORY_PATH: /etc/activity-core/ops/service-inventory.yml INTER_HUB_URL: "" @@ -643,6 +643,117 @@ spec: periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 6 +apiVersion: v1 +kind: Service +metadata: + name: actcore-issue-core-bridge + namespace: activity-core + labels: + app.kubernetes.io/name: actcore-issue-core-bridge + app.kubernetes.io/part-of: activity-core +spec: + selector: + app.kubernetes.io/name: actcore-issue-core-bridge + ports: + - name: http + port: 8765 + targetPort: http +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: actcore-issue-core-bridge + namespace: activity-core + labels: + app.kubernetes.io/name: actcore-issue-core-bridge + app.kubernetes.io/part-of: activity-core +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: actcore-issue-core-bridge + template: + metadata: + labels: + app.kubernetes.io/name: actcore-issue-core-bridge + app.kubernetes.io/part-of: activity-core + spec: + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet + containers: + - name: proxy + image: activity-core:railiance01-prod + imagePullPolicy: Never + ports: + - name: http + containerPort: 18081 + command: + - python + - -c + - | + from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer + from urllib.error import HTTPError, URLError + from urllib.request import Request, urlopen + + TARGET = "http://127.0.0.1:18765" + HOP_HEADERS = {"connection", "host", "keep-alive", "proxy-authenticate", + "proxy-authorization", "te", "trailers", + "transfer-encoding", "upgrade"} + + class Proxy(BaseHTTPRequestHandler): + def do_GET(self): + self._proxy() + + def do_POST(self): + self._proxy() + + def do_PATCH(self): + self._proxy() + + def _proxy(self): + length = int(self.headers.get("content-length", "0") or "0") + body = self.rfile.read(length) if length else None + headers = { + key: value + for key, value in self.headers.items() + if key.lower() not in HOP_HEADERS + } + request = Request( + TARGET + self.path, + data=body, + headers=headers, + method=self.command, + ) + try: + timeout = 360 if self.command == "POST" else 30 + with urlopen(request, timeout=timeout) as response: + payload = response.read() + self.send_response(response.status) + for key, value in response.headers.items(): + if key.lower() not in HOP_HEADERS: + self.send_header(key, value) + self.end_headers() + self.wfile.write(payload) + except HTTPError as exc: + payload = exc.read() + self.send_response(exc.code) + self.end_headers() + self.wfile.write(payload) + except URLError as exc: + self.send_response(502) + self.end_headers() + self.wfile.write(str(exc).encode()) + + ThreadingHTTPServer(("0.0.0.0", 18081), Proxy).serve_forever() + readinessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 +--- --- apiVersion: batch/v1 kind: Job