|
|
|
@@ -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(".");
|
|
|
|
|