mirror of
https://github.com/fosrl/pangolin.git
synced 2026-07-06 12:19:50 +00:00
Skip invalid Docker resources instead of failing entire blueprint (#1784)
This commit is contained in:
@@ -1,10 +1,56 @@
|
|||||||
import { sendToClient } from "#dynamic/routers/ws";
|
import { sendToClient } from "#dynamic/routers/ws";
|
||||||
import { processContainerLabels } from "./parseDockerContainers";
|
import { processContainerLabels } from "./parseDockerContainers";
|
||||||
import { applyBlueprint } from "./applyBlueprint";
|
import { applyBlueprint } from "./applyBlueprint";
|
||||||
|
import { ResourceSchema, ClientResourceSchema } from "./types";
|
||||||
import { db, sites } from "@server/db";
|
import { db, sites } from "@server/db";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import logger from "@server/logger";
|
import logger from "@server/logger";
|
||||||
|
|
||||||
|
type BlueprintResult = ReturnType<typeof processContainerLabels>;
|
||||||
|
|
||||||
|
function filterInvalidResources(blueprint: BlueprintResult): {
|
||||||
|
skippedCount: number;
|
||||||
|
skippedKeys: string[];
|
||||||
|
} {
|
||||||
|
const skippedKeys: string[] = [];
|
||||||
|
|
||||||
|
for (const section of ["proxy-resources", "public-resources"] as const) {
|
||||||
|
const resources = blueprint[section];
|
||||||
|
for (const [key, value] of Object.entries(resources)) {
|
||||||
|
const result = ResourceSchema.safeParse(value);
|
||||||
|
if (!result.success) {
|
||||||
|
const errors = result.error.issues
|
||||||
|
.map((i) => `${i.path.join(".")}: ${i.message}`)
|
||||||
|
.join("; ");
|
||||||
|
logger.warn(
|
||||||
|
`Skipping invalid Docker ${section} "${key}": ${errors}`
|
||||||
|
);
|
||||||
|
delete resources[key];
|
||||||
|
skippedKeys.push(`${section}.${key}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const section of ["client-resources", "private-resources"] as const) {
|
||||||
|
const resources = blueprint[section];
|
||||||
|
for (const [key, value] of Object.entries(resources)) {
|
||||||
|
const result = ClientResourceSchema.safeParse(value);
|
||||||
|
if (!result.success) {
|
||||||
|
const errors = result.error.issues
|
||||||
|
.map((i) => `${i.path.join(".")}: ${i.message}`)
|
||||||
|
.join("; ");
|
||||||
|
logger.warn(
|
||||||
|
`Skipping invalid Docker ${section} "${key}": ${errors}`
|
||||||
|
);
|
||||||
|
delete resources[key];
|
||||||
|
skippedKeys.push(`${section}.${key}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { skippedCount: skippedKeys.length, skippedKeys };
|
||||||
|
}
|
||||||
|
|
||||||
export async function applyNewtDockerBlueprint(
|
export async function applyNewtDockerBlueprint(
|
||||||
siteId: number,
|
siteId: number,
|
||||||
newtId: string,
|
newtId: string,
|
||||||
@@ -21,17 +67,24 @@ export async function applyNewtDockerBlueprint(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// logger.debug(`Applying Docker blueprint to site: ${siteId}`);
|
let skippedCount = 0;
|
||||||
// logger.debug(`Containers: ${JSON.stringify(containers, null, 2)}`);
|
let skippedKeys: string[] = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const blueprint = processContainerLabels(containers);
|
const blueprint = processContainerLabels(containers);
|
||||||
|
|
||||||
logger.debug(`Received Docker blueprint: ${JSON.stringify(blueprint)}`);
|
logger.debug(
|
||||||
|
`Received Docker blueprint with ${Object.keys(blueprint["proxy-resources"]).length} proxy, ${Object.keys(blueprint["client-resources"]).length} client resource(s)`
|
||||||
|
);
|
||||||
|
|
||||||
// make sure this is not an empty object
|
const filterResult = filterInvalidResources(blueprint);
|
||||||
if (isEmptyObject(blueprint)) {
|
skippedCount = filterResult.skippedCount;
|
||||||
return;
|
skippedKeys = filterResult.skippedKeys;
|
||||||
|
|
||||||
|
if (skippedCount > 0) {
|
||||||
|
logger.warn(
|
||||||
|
`Filtered ${skippedCount} invalid resource(s) from Docker blueprint: ${skippedKeys.join(", ")}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -40,6 +93,15 @@ export async function applyNewtDockerBlueprint(
|
|||||||
isEmptyObject(blueprint["public-resources"]) &&
|
isEmptyObject(blueprint["public-resources"]) &&
|
||||||
isEmptyObject(blueprint["private-resources"])
|
isEmptyObject(blueprint["private-resources"])
|
||||||
) {
|
) {
|
||||||
|
if (skippedCount > 0) {
|
||||||
|
await sendToClient(newtId, {
|
||||||
|
type: "newt/blueprint/results",
|
||||||
|
data: {
|
||||||
|
success: false,
|
||||||
|
message: `All resources were invalid and skipped: ${skippedKeys.join(", ")}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +128,10 @@ export async function applyNewtDockerBlueprint(
|
|||||||
type: "newt/blueprint/results",
|
type: "newt/blueprint/results",
|
||||||
data: {
|
data: {
|
||||||
success: true,
|
success: true,
|
||||||
message: "Config updated successfully"
|
message:
|
||||||
|
skippedCount > 0
|
||||||
|
? `Config updated successfully. Skipped ${skippedCount} invalid resource(s): ${skippedKeys.join(", ")}`
|
||||||
|
: "Config updated successfully"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user