|
|
|
@@ -4772,6 +4772,57 @@ function v02PostgresManifest({ profile = "v02", migrationSql, source }) {
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function externalPostgresConfigForLane(deploy, profile) {
|
|
|
|
|
if (!isRuntimeLane(profile)) return null;
|
|
|
|
|
const config = deploy?.lanes?.[profile]?.externalPostgres;
|
|
|
|
|
if (!config || config.enabled !== true) return null;
|
|
|
|
|
assert.ok(typeof config.serviceName === "string" && config.serviceName.length > 0, `deploy.lanes.${profile}.externalPostgres.serviceName is required`);
|
|
|
|
|
assert.ok(typeof config.endpointAddress === "string" && config.endpointAddress.length > 0, `deploy.lanes.${profile}.externalPostgres.endpointAddress is required`);
|
|
|
|
|
const port = Number(config.port ?? 5432);
|
|
|
|
|
assert.ok(Number.isInteger(port) && port > 0 && port <= 65535, `deploy.lanes.${profile}.externalPostgres.port must be a valid TCP port`);
|
|
|
|
|
return { serviceName: config.serviceName, endpointAddress: config.endpointAddress, port };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function externalPostgresManifest({ profile = "v03", config, source }) {
|
|
|
|
|
const namespace = namespaceNameForProfile(profile);
|
|
|
|
|
const labels = {
|
|
|
|
|
"app.kubernetes.io/name": config.serviceName,
|
|
|
|
|
"app.kubernetes.io/part-of": "hwlab",
|
|
|
|
|
"hwlab.pikastech.local/component": "platform-db-bridge",
|
|
|
|
|
"hwlab.pikastech.local/environment": profile,
|
|
|
|
|
"hwlab.pikastech.local/gitops-target": profile,
|
|
|
|
|
"hwlab.pikastech.local/profile": profile,
|
|
|
|
|
"hwlab.pikastech.local/source-commit": source.full
|
|
|
|
|
};
|
|
|
|
|
const annotations = { "hwlab.pikastech.local/rendered-by": "scripts/gitops-render.mjs" };
|
|
|
|
|
return {
|
|
|
|
|
apiVersion: "v1",
|
|
|
|
|
kind: "List",
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
apiVersion: "v1",
|
|
|
|
|
kind: "Service",
|
|
|
|
|
metadata: { name: config.serviceName, namespace, labels, annotations },
|
|
|
|
|
spec: { type: "ClusterIP", ports: [{ name: "postgres", port: config.port, targetPort: config.port, protocol: "TCP" }] }
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
apiVersion: "v1",
|
|
|
|
|
kind: "Endpoints",
|
|
|
|
|
metadata: { name: config.serviceName, namespace, labels, annotations },
|
|
|
|
|
subsets: [{ addresses: [{ ip: config.endpointAddress }], ports: [{ name: "postgres", port: config.port, protocol: "TCP" }] }]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
apiVersion: "discovery.k8s.io/v1",
|
|
|
|
|
kind: "EndpointSlice",
|
|
|
|
|
metadata: { name: `${config.serviceName}-host`, namespace, labels: { ...labels, "kubernetes.io/service-name": config.serviceName }, annotations },
|
|
|
|
|
addressType: "IPv4",
|
|
|
|
|
ports: [{ name: "postgres", port: config.port, protocol: "TCP" }],
|
|
|
|
|
endpoints: [{ addresses: [config.endpointAddress], conditions: { ready: true } }]
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function v02OpenFgaManifest({ profile = "v02", source }) {
|
|
|
|
|
const namespace = namespaceNameForProfile(profile);
|
|
|
|
|
const name = "hwlab-openfga";
|
|
|
|
@@ -4863,10 +4914,14 @@ function v02OpenFgaManifest({ profile = "v02", source }) {
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function runtimeKustomization({ profile = "dev", includeDeviceAgent = profile === "dev" } = {}) {
|
|
|
|
|
function runtimeKustomization({ profile = "dev", includeDeviceAgent = profile === "dev", externalPostgres = false } = {}) {
|
|
|
|
|
const resources = ["namespace.yaml", "services.yaml", "health-contract.yaml", "workloads.yaml", "deepseek-proxy.yaml"];
|
|
|
|
|
if (!isRuntimeLane(profile)) resources.splice(1, 0, "code-agent-codex-config.yaml");
|
|
|
|
|
if (isRuntimeLane(profile)) resources.push("postgres.yaml", "openfga.yaml", "observability.yaml");
|
|
|
|
|
if (isRuntimeLane(profile)) {
|
|
|
|
|
if (externalPostgres) resources.push("external-postgres.yaml");
|
|
|
|
|
else resources.push("postgres.yaml");
|
|
|
|
|
resources.push("openfga.yaml", "observability.yaml");
|
|
|
|
|
}
|
|
|
|
|
if (includeDeviceAgent) resources.push("device-agent-71-freq.yaml");
|
|
|
|
|
resources.push("node-frpc.yaml");
|
|
|
|
|
return {
|
|
|
|
@@ -4998,6 +5053,7 @@ async function plannedFiles(args) {
|
|
|
|
|
for (const profile of profiles) {
|
|
|
|
|
const namespace = namespaceNameForProfile(profile);
|
|
|
|
|
const includeDeviceAgent = profile === "dev";
|
|
|
|
|
const externalPostgres = externalPostgresConfigForLane(deploy, profile);
|
|
|
|
|
const profileLabels = { ...baseLabels, "hwlab.pikastech.local/environment": runtimeLabelForProfile(profile), "hwlab.pikastech.local/profile": runtimeLabelForProfile(profile) };
|
|
|
|
|
const runtimeNamespace = cloneJson(namespaceTemplate);
|
|
|
|
|
runtimeNamespace.metadata.name = namespace;
|
|
|
|
@@ -5005,14 +5061,15 @@ async function plannedFiles(args) {
|
|
|
|
|
annotate(runtimeNamespace.metadata, annotations);
|
|
|
|
|
const runtimePath = runtimePathForProfile(profile);
|
|
|
|
|
const endpoints = profileEndpoint(args, profile);
|
|
|
|
|
putJson(`${runtimePath}/kustomization.yaml`, runtimeKustomization({ profile, includeDeviceAgent }));
|
|
|
|
|
putJson(`${runtimePath}/kustomization.yaml`, runtimeKustomization({ profile, includeDeviceAgent, externalPostgres: Boolean(externalPostgres) }));
|
|
|
|
|
putJson(`${runtimePath}/namespace.yaml`, runtimeNamespace);
|
|
|
|
|
if (!isRuntimeLane(profile)) putJson(`${runtimePath}/code-agent-codex-config.yaml`, transformListNamespace(config, namespace, profileLabels, annotations));
|
|
|
|
|
putJson(`${runtimePath}/services.yaml`, transformServices({ services, namespace, labels: profileLabels, annotations, profile, deploy }));
|
|
|
|
|
putJson(`${runtimePath}/health-contract.yaml`, transformHealthContract(health, namespace, profileLabels, annotations, endpoints.runtimeEndpoint, endpoints.webEndpoint, profile));
|
|
|
|
|
putJson(`${runtimePath}/workloads.yaml`, transformWorkloads({ workloads, deploy, catalog: artifactCatalog, source, sourceBranch: args.sourceBranch, registryPrefix: args.registryPrefix, runtimeEndpoint: endpoints.runtimeEndpoint, webEndpoint: endpoints.webEndpoint, profile, useDeployImages: args.useDeployImages, metricsSidecarSha256 }));
|
|
|
|
|
putJson(`${runtimePath}/deepseek-proxy.yaml`, deepSeekProxyManifest({ profile, source, sourceBranch: args.sourceBranch, sourceRepo: args.sourceRepo, deploy, registryPrefix: args.registryPrefix, catalog: artifactCatalog, useDeployImages: args.useDeployImages, metricsSidecarSha256 }));
|
|
|
|
|
if (isRuntimeLane(profile)) putJson(`${runtimePath}/postgres.yaml`, v02PostgresManifest({ profile, migrationSql, source }));
|
|
|
|
|
if (isRuntimeLane(profile) && externalPostgres) putJson(`${runtimePath}/external-postgres.yaml`, externalPostgresManifest({ profile, config: externalPostgres, source }));
|
|
|
|
|
if (isRuntimeLane(profile) && !externalPostgres) putJson(`${runtimePath}/postgres.yaml`, v02PostgresManifest({ profile, migrationSql, source }));
|
|
|
|
|
if (isRuntimeLane(profile)) putJson(`${runtimePath}/openfga.yaml`, v02OpenFgaManifest({ profile, source }));
|
|
|
|
|
if (isRuntimeLane(profile)) putJson(`${runtimePath}/observability.yaml`, observabilityManifest({ deploy, profile, namespace, labels: profileLabels, annotations, metricsSidecarScript }));
|
|
|
|
|
if (includeDeviceAgent) putJson(`${runtimePath}/device-agent-71-freq.yaml`, deviceAgent71FreqManifest({ profile, source, registryPrefix: args.registryPrefix, catalog: artifactCatalog, useDeployImages: args.useDeployImages }));
|
|
|
|
|