fix(pikaoa): 注入 Web 同源 API upstream

This commit is contained in:
Codex
2026-07-15 03:34:03 +02:00
parent 5a8f2d6713
commit e37b4dc79a
4 changed files with 23 additions and 3 deletions
+2
View File
@@ -47,9 +47,11 @@ testRuntime:
targetKey: DATABASE_URL
runtime:
secretName: pikaoa-test-runtime
apiServiceName: pikaoa-api
apiPort: 8080
workerMetricsPort: 8081
webPort: 8080
webApiUpstreamEnv: PIKAOA_API_UPSTREAM
attachment:
storageRoot: /var/lib/pikaoa/attachments
maxBytes: 104857600
+2
View File
@@ -66,9 +66,11 @@ testRuntime:
targetKey: DATABASE_URL
runtime:
secretName: pikaoa-test-runtime
apiServiceName: pikaoa-api
apiPort: 8080
workerMetricsPort: 8081
webPort: 8080
webApiUpstreamEnv: PIKAOA_API_UPSTREAM
attachment:
storageRoot: /var/lib/pikaoa/attachments
maxBytes: 104857600
@@ -171,6 +171,7 @@ exit 64
assert.equal(objects.some((object) => object.kind === "Deployment" && object.name === "pikaoa-web"), true);
assert.equal(objects.find((object) => object.kind === "Deployment" && object.name === "pikaoa-api")?.podFsGroup, 65532);
assert.deepEqual(plan.exposure, { serviceType: "NodePort", serviceName: "pikaoa-web", hostIP: "192.0.2.10", port: 32080 });
assert.deepEqual(plan.webApiUpstream, { envName: "PIKAOA_API_UPSTREAM", value: "http://pikaoa-api:8080", scope: "same-namespace" });
const missing = await projection("status", "runtime", false, "api");
assert.equal((missing.status as Record<string, unknown>).code, "start-not-found");
+18 -3
View File
@@ -69,9 +69,11 @@ interface TestTargetSpec {
};
runtime: {
secretName: string;
apiServiceName: string;
apiPort: number;
workerMetricsPort: number;
webPort: number;
webApiUpstreamEnv: string;
attachment: {
storageRoot: string;
maxBytes: number;
@@ -343,9 +345,11 @@ function parseTarget(id: string, root: Record<string, unknown>, configLabel: str
},
runtime: {
secretName: kubernetesName(nonEmpty(runtime.secretName, `${path}.runtime.secretName`), `${path}.runtime.secretName`, 63),
apiServiceName: kubernetesName(nonEmpty(runtime.apiServiceName, `${path}.runtime.apiServiceName`), `${path}.runtime.apiServiceName`, 63),
apiPort: positiveInteger(runtime.apiPort, `${path}.runtime.apiPort`, 65_535),
workerMetricsPort: positiveInteger(runtime.workerMetricsPort, `${path}.runtime.workerMetricsPort`, 65_535),
webPort: positiveInteger(runtime.webPort, `${path}.runtime.webPort`, 65_535),
webApiUpstreamEnv: envName(runtime.webApiUpstreamEnv, `${path}.runtime.webApiUpstreamEnv`),
attachment: {
storageRoot: absolutePath(attachment.storageRoot, `${path}.runtime.attachment.storageRoot`),
maxBytes: positiveInteger(attachment.maxBytes, `${path}.runtime.attachment.maxBytes`, Number.MAX_SAFE_INTEGER),
@@ -502,6 +506,7 @@ function renderedPlan(selection: Selection, context: RenderContext): Record<stri
exporterFailure: { warning: target.observability.exporterWarning, blocking: false },
},
exposure: { serviceType: target.exposure.serviceType, serviceName: target.exposure.serviceName, hostIP: target.exposure.hostIP, port: target.exposure.port },
webApiUpstream: { envName: target.runtime.webApiUpstreamEnv, value: `http://${target.runtime.apiServiceName}:${target.runtime.apiPort}`, scope: "same-namespace" },
attachment: {
storageRoot: target.runtime.attachment.storageRoot,
maxBytes: target.runtime.attachment.maxBytes,
@@ -683,7 +688,7 @@ function buildManifest(target: TestTargetSpec, context: RenderContext, secrets:
},
},
{
apiVersion: "v1", kind: "Service", metadata: { name: "pikaoa-api", namespace: context.namespace, labels: { ...labels, ...apiSelector } },
apiVersion: "v1", kind: "Service", metadata: { name: target.runtime.apiServiceName, namespace: context.namespace, labels: { ...labels, ...apiSelector } },
spec: { selector: apiSelector, ports: [{ name: "http", port: target.runtime.apiPort, targetPort: target.runtime.apiPort }] },
},
{
@@ -724,7 +729,9 @@ function buildManifest(target: TestTargetSpec, context: RenderContext, secrets:
deployment(target, context, "worker", context.workerImage, workerSelector, target.runtime.workerMetricsPort, commonPodAnnotations(target.observability.workerMetricsPath, target.runtime.workerMetricsPort), [
{ name: "PIKAOA_CONFIG", value: "/etc/pikaoa/pikaoa.yaml" },
], target.probes.workerLivenessPath, target.probes.workerReadinessPath),
deployment(target, context, "web", context.webImage, webSelector, target.runtime.webPort, {}, [], target.probes.webLivenessPath, target.probes.webReadinessPath),
deployment(target, context, "web", context.webImage, webSelector, target.runtime.webPort, {}, [
{ name: target.runtime.webApiUpstreamEnv, value: `http://${target.runtime.apiServiceName}:${target.runtime.apiPort}` },
], target.probes.webLivenessPath, target.probes.webReadinessPath),
];
}
@@ -1024,7 +1031,9 @@ function startRunnerScript(target: TestTargetSpec, context: RenderContext, manif
const migration = manifest.filter((object) => object.kind === "Job");
const workload = (name: string): Record<string, unknown>[] => manifest.filter((object) => {
if (object.kind !== "Deployment" && object.kind !== "Service") return false;
return optionalRecord(object.metadata, "metadata")?.name === `pikaoa-${name}`;
const metadata = optionalRecord(object.metadata, "metadata") ?? {};
const labels = optionalRecord(metadata.labels, "metadata.labels") ?? {};
return labels["app.kubernetes.io/component"] === name;
});
const foundation = manifest.filter((object) => object.kind !== "Job" && object.kind !== "Deployment" && object.kind !== "Service");
const encode = (objects: Record<string, unknown>[]): string => Buffer.from(objects.map((object) => JSON.stringify(object)).join("\n---\n"), "utf8").toString("base64");
@@ -1582,6 +1591,12 @@ function httpPath(value: unknown, path: string): string {
return result;
}
function envName(value: unknown, path: string): string {
const result = nonEmpty(value, path);
if (!/^[A-Za-z_][A-Za-z0-9_]*$/u.test(result)) throw new Error(`${path} `);
return result;
}
function ipv4Address(value: unknown, path: string): string {
const result = nonEmpty(value, path);
const octets = result.split(".");