fix: move sub2api runtime to PK01 host docker
This commit is contained in:
@@ -19,7 +19,8 @@ import type { ApplyOptions, DisclosureOptions, TargetOptions } from "./options";
|
||||
import { applyScript, dryRunScript } from "./apply-script";
|
||||
import { readSub2ApiConfig } from "./config";
|
||||
import { configPath, fieldManager, manifestPath, serviceName } from "./entry";
|
||||
import { imageRef, isExternalTarget, managedResourceCleanupPlan, manifest, resolveTarget, targetDependencyImages, targetHasSentinel, targetImage } from "./manifest";
|
||||
import { hostDockerApplyScript, hostDockerDryRunScript, hostDockerPlanSummary, hostDockerStatusScript } from "./host-docker";
|
||||
import { imageRef, isExternalTarget, isHostDockerTarget, managedResourceCleanupPlan, manifest, resolveTarget, targetDatabase, targetDependencyImages, targetHasSentinel, targetImage } from "./manifest";
|
||||
import { applyPk01PublicExposure } from "./pk01-public-exposure";
|
||||
import { policyChecks } from "./policy";
|
||||
import { prepareEgressProxySecret, prepareExternalActiveSecret, preparePublicExposureSecret } from "./secrets-and-egress";
|
||||
@@ -29,21 +30,25 @@ import { boolField } from "./utils";
|
||||
export function publicExposureSummary(exposure: Sub2ApiPublicExposureConfig): Record<string, unknown> {
|
||||
return {
|
||||
enabled: exposure.enabled,
|
||||
mode: exposure.mode,
|
||||
publicBaseUrl: exposure.publicBaseUrl,
|
||||
dns: exposure.dns,
|
||||
frpc: {
|
||||
deploymentName: exposure.frpc.deploymentName,
|
||||
secretName: exposure.frpc.secretName,
|
||||
image: exposure.frpc.image,
|
||||
serverAddr: exposure.frpc.serverAddr,
|
||||
serverPort: exposure.frpc.serverPort,
|
||||
proxyName: exposure.frpc.proxyName,
|
||||
remotePort: exposure.frpc.remotePort,
|
||||
localIP: exposure.frpc.localIP,
|
||||
localPort: exposure.frpc.localPort,
|
||||
tokenSourceRef: exposure.frpc.tokenSourceRef,
|
||||
valuesPrinted: false,
|
||||
},
|
||||
local: exposure.local,
|
||||
frpc: exposure.frpc === null
|
||||
? null
|
||||
: {
|
||||
deploymentName: exposure.frpc.deploymentName,
|
||||
secretName: exposure.frpc.secretName,
|
||||
image: exposure.frpc.image,
|
||||
serverAddr: exposure.frpc.serverAddr,
|
||||
serverPort: exposure.frpc.serverPort,
|
||||
proxyName: exposure.frpc.proxyName,
|
||||
remotePort: exposure.frpc.remotePort,
|
||||
localIP: exposure.frpc.localIP,
|
||||
localPort: exposure.frpc.localPort,
|
||||
tokenSourceRef: exposure.frpc.tokenSourceRef,
|
||||
valuesPrinted: false,
|
||||
},
|
||||
pk01: {
|
||||
route: exposure.pk01.route,
|
||||
mode: "caddy-edge",
|
||||
@@ -92,6 +97,8 @@ export function plan(options: TargetOptions): Record<string, unknown> {
|
||||
const target = resolveTarget(sub2api, options.targetId);
|
||||
const yaml = manifest(sub2api, target);
|
||||
const policy = policyChecks(sub2api, yaml, target);
|
||||
const database = targetDatabase(sub2api, target);
|
||||
const hostDocker = isHostDockerTarget(target) ? hostDockerPlanSummary(sub2api, target) : null;
|
||||
return {
|
||||
ok: policy.every((check) => check.ok),
|
||||
action: "platform-infra-sub2api-plan",
|
||||
@@ -99,11 +106,12 @@ export function plan(options: TargetOptions): Record<string, unknown> {
|
||||
id: target.id,
|
||||
route: target.route,
|
||||
namespace: target.namespace,
|
||||
runtimeMode: target.runtimeMode,
|
||||
role: target.role,
|
||||
manifestPath,
|
||||
configPath,
|
||||
fieldManager,
|
||||
serviceDns: `${serviceName}.${target.namespace}.svc.cluster.local:8080`,
|
||||
serviceDns: isHostDockerTarget(target) ? `host-docker:127.0.0.1:${target.hostDocker?.appPort ?? 0}` : `${serviceName}.${target.namespace}.svc.cluster.local:8080`,
|
||||
},
|
||||
config: {
|
||||
path: configPath,
|
||||
@@ -115,10 +123,12 @@ export function plan(options: TargetOptions): Record<string, unknown> {
|
||||
dependencyImages: targetDependencyImages(sub2api, target),
|
||||
security: sub2api.security,
|
||||
target: {
|
||||
runtimeMode: target.runtimeMode,
|
||||
databaseMode: target.databaseMode,
|
||||
redisMode: target.redisMode,
|
||||
appReplicas: target.appReplicas,
|
||||
redisReplicas: target.redisReplicas,
|
||||
hostDocker,
|
||||
publicExposure: target.publicExposure === null ? null : publicExposureSummary(target.publicExposure),
|
||||
egressProxy: target.egressProxy === null ? null : egressProxySummary(target.egressProxy),
|
||||
},
|
||||
@@ -128,12 +138,12 @@ export function plan(options: TargetOptions): Record<string, unknown> {
|
||||
sourceKeys: sub2api.runtime.database.sourceKeys,
|
||||
secretName: sub2api.runtime.database.secretName,
|
||||
passwordKey: sub2api.runtime.database.passwordKey,
|
||||
host: sub2api.runtime.database.host,
|
||||
port: sub2api.runtime.database.port,
|
||||
user: sub2api.runtime.database.user,
|
||||
dbName: sub2api.runtime.database.dbName,
|
||||
sslMode: sub2api.runtime.database.sslMode,
|
||||
pendingAllowed: sub2api.runtime.database.pendingAllowed,
|
||||
host: database.host,
|
||||
port: database.port,
|
||||
user: database.user,
|
||||
dbName: database.dbName,
|
||||
sslMode: database.sslMode,
|
||||
pendingAllowed: database.pendingAllowed,
|
||||
} : null,
|
||||
},
|
||||
decision: {
|
||||
@@ -141,20 +151,26 @@ export function plan(options: TargetOptions): Record<string, unknown> {
|
||||
namespace: target.namespace,
|
||||
reason: target.databaseMode === "external-pending"
|
||||
? `${target.id} is a standby Sub2API platform-infra target prepared through YAML; it stays scaled to zero until this target is promoted in YAML.`
|
||||
: isHostDockerTarget(target)
|
||||
? `${target.id} is activated as a PK01 host-Docker Sub2API target against PK01 local PostgreSQL without k3s or sentinel.`
|
||||
: target.databaseMode === "external-active"
|
||||
? `${target.id} is activated as a platform-infra Sub2API target against the external PK01 PostgreSQL runtime while keeping app state outside the k3s node.`
|
||||
: `${target.id} is a bundled active Sub2API platform-infra target.`,
|
||||
exposure: target.publicExposure?.enabled
|
||||
? `Public HTTPS ${target.publicExposure.publicBaseUrl} through PK01 Caddy and ${target.id} frpc; no master server forwarding and no Kubernetes Ingress/NodePort/LoadBalancer.`
|
||||
? isHostDockerTarget(target)
|
||||
? `Public HTTPS ${target.publicExposure.publicBaseUrl} through PK01 Caddy to PK01 local Docker; no D601 egress, no k3s Ingress/NodePort/LoadBalancer.`
|
||||
: `Public HTTPS ${target.publicExposure.publicBaseUrl} through PK01 Caddy and ${target.id} frpc; no master server forwarding and no Kubernetes Ingress/NodePort/LoadBalancer.`
|
||||
: "ClusterIP only; no public ingress or node-level exposure.",
|
||||
resourcePolicy: "No Kubernetes CPU/memory requests or limits, matching issue #220.",
|
||||
resourcePolicy: isHostDockerTarget(target) ? "PK01 host-Docker compose is controlled by YAML; no Kubernetes resources are rendered." : "No Kubernetes CPU/memory requests or limits, matching issue #220.",
|
||||
imageVersionControl: "Sub2API image repository/tag/pullPolicy are controlled by config/platform-infra/sub2api.yaml in the UniDesk repository.",
|
||||
urlAllowlistControl: "Sub2API upstream URL validation options are controlled by config/platform-infra/sub2api.yaml and rendered to SECURITY_URL_ALLOWLIST_* env vars.",
|
||||
networkPolicy: "NetworkPolicy/allow-all is rendered with the deployment so kube-router cannot silently default-deny Sub2API cross-pod traffic.",
|
||||
networkPolicy: isHostDockerTarget(target) ? "Not applicable for PK01 host-Docker deployment." : "NetworkPolicy/allow-all is rendered with the deployment so kube-router cannot silently default-deny Sub2API cross-pod traffic.",
|
||||
publicExposure: target.publicExposure?.enabled
|
||||
? {
|
||||
mode: "pk01-caddy-frp-direct",
|
||||
dataPath: `client -> PK01 Caddy -> PK01 frps remotePort -> ${target.id} frpc -> Sub2API`,
|
||||
mode: target.publicExposure.mode === "pk01-local" ? "pk01-caddy-local-docker" : "pk01-caddy-frp-direct",
|
||||
dataPath: target.publicExposure.mode === "pk01-local"
|
||||
? `client -> PK01 Caddy -> ${target.publicExposure.local?.upstreamHost}:${target.publicExposure.local?.upstreamPort} -> PK01 Docker Sub2API`
|
||||
: `client -> PK01 Caddy -> PK01 frps remotePort -> ${target.id} frpc -> Sub2API`,
|
||||
pikanodeRole: `pikapython.com upstream only; ${target.publicExposure.dns.hostname} does not pass through pikanode Express`,
|
||||
publicBaseUrl: target.publicExposure.publicBaseUrl,
|
||||
hostname: target.publicExposure.dns.hostname,
|
||||
@@ -175,7 +191,7 @@ export function plan(options: TargetOptions): Record<string, unknown> {
|
||||
: null,
|
||||
dataStores: isExternalTarget(target)
|
||||
? [
|
||||
target.databaseMode === "external-active" ? "External PostgreSQL active from platform-db/PK01" : "External PostgreSQL pending from platform-db/Pika01",
|
||||
isHostDockerTarget(target) ? `PK01 local PostgreSQL through ${database.host}:${database.port}` : target.databaseMode === "external-active" ? "External PostgreSQL active from platform-db/PK01" : "External PostgreSQL pending from platform-db/Pika01",
|
||||
target.redisReplicas === 0 ? `${target.id} local Redis 8 ephemeral cache, scaled to zero until activation` : `${target.id} local Redis 8 ephemeral cache`,
|
||||
]
|
||||
: ["PostgreSQL 18", "Redis 8"],
|
||||
@@ -226,7 +242,7 @@ export async function apply(config: UniDeskConfig, options: ApplyOptions): Promi
|
||||
const job = startJob(
|
||||
`platform_infra_sub2api_apply_${target.id.toLowerCase()}`,
|
||||
["bun", "scripts/cli.ts", "platform-infra", "sub2api", "apply", "--target", target.id, "--confirm", "--wait"],
|
||||
`Apply ${target.id} k3s platform-infra Sub2API manifests through the controlled UniDesk CLI`,
|
||||
`Apply ${target.id} ${isHostDockerTarget(target) ? "host-Docker" : "k3s"} platform-infra Sub2API desired state through the controlled UniDesk CLI`,
|
||||
);
|
||||
return {
|
||||
ok: true,
|
||||
@@ -247,7 +263,7 @@ export async function apply(config: UniDeskConfig, options: ApplyOptions): Promi
|
||||
};
|
||||
}
|
||||
if (options.dryRun) {
|
||||
const result = await capture(config, target.route, ["sh"], dryRunScript(yaml, target));
|
||||
const result = await capture(config, target.route, ["sh"], isHostDockerTarget(target) ? hostDockerDryRunScript(sub2api, target) : dryRunScript(yaml, target));
|
||||
const parsed = parseJsonOutput(result.stdout);
|
||||
return {
|
||||
ok: result.exitCode === 0 && boolField(parsed, "ok", false),
|
||||
@@ -265,9 +281,16 @@ export async function apply(config: UniDeskConfig, options: ApplyOptions): Promi
|
||||
const secretMaterial = target.databaseMode === "external-active" ? prepareExternalActiveSecret(sub2api) : null;
|
||||
const publicExposureSecretMaterial = preparePublicExposureSecret(sub2api, target);
|
||||
const egressProxySecretMaterial = prepareEgressProxySecret(sub2api, target);
|
||||
const result = await capture(config, target.route, ["sh"], applyScript(sub2api, yaml, target, secretMaterial, publicExposureSecretMaterial, egressProxySecretMaterial));
|
||||
const result = await capture(
|
||||
config,
|
||||
target.route,
|
||||
["sh"],
|
||||
isHostDockerTarget(target)
|
||||
? hostDockerApplyScript(sub2api, target, secretMaterial)
|
||||
: applyScript(sub2api, yaml, target, secretMaterial, publicExposureSecretMaterial, egressProxySecretMaterial),
|
||||
);
|
||||
const parsed = parseJsonOutput(result.stdout);
|
||||
const pk01Exposure = publicExposureSecretMaterial === null ? null : await applyPk01PublicExposure(config, target);
|
||||
const pk01Exposure = target.publicExposure?.enabled === true ? await applyPk01PublicExposure(config, target) : null;
|
||||
return {
|
||||
ok: result.exitCode === 0 && boolField(parsed, "ok", false) && (pk01Exposure === null || pk01Exposure.ok === true),
|
||||
action: "platform-infra-sub2api-apply",
|
||||
@@ -290,7 +313,7 @@ export async function apply(config: UniDeskConfig, options: ApplyOptions): Promi
|
||||
export async function status(config: UniDeskConfig, options: DisclosureOptions): Promise<Record<string, unknown>> {
|
||||
const sub2api = readSub2ApiConfig();
|
||||
const target = resolveTarget(sub2api, options.targetId);
|
||||
const result = await capture(config, target.route, ["sh"], statusScript(sub2api, target));
|
||||
const result = await capture(config, target.route, ["sh"], isHostDockerTarget(target) ? hostDockerStatusScript(sub2api, target) : statusScript(sub2api, target));
|
||||
const parsed = parseJsonOutput(result.stdout);
|
||||
if (options.raw) {
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user