mirror of
https://github.com/fosrl/pangolin.git
synced 2026-08-26 14:04:57 +02:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 72d2c79793 | |||
| 23764feb4f | |||
| d2809fbfd1 |
@@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
db,
|
db,
|
||||||
|
primaryDb,
|
||||||
newts,
|
newts,
|
||||||
blueprints,
|
blueprints,
|
||||||
Blueprint,
|
Blueprint,
|
||||||
@@ -80,93 +81,103 @@ export async function applyBlueprint({
|
|||||||
trx,
|
trx,
|
||||||
siteId
|
siteId
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
// We need to update the targets on the newts from the successfully updated information
|
// Push updates to newts/clients only after the transaction has
|
||||||
for (const result of publicResourcesResults) {
|
// committed. Doing this while the transaction is still open can
|
||||||
for (const target of result.targetsToUpdate) {
|
// race with the writes (e.g. newts requesting config before the
|
||||||
const [site] = await trx
|
// new targets/resources are actually visible), leaving them out
|
||||||
.select()
|
// of sync until manually toggled.
|
||||||
.from(sites)
|
|
||||||
.innerJoin(newts, eq(sites.siteId, newts.siteId))
|
// We need to update the targets on the newts from the successfully updated information
|
||||||
.where(
|
for (const result of publicResourcesResults) {
|
||||||
and(
|
for (const target of result.targetsToUpdate) {
|
||||||
eq(sites.siteId, target.siteId),
|
// read from the primary: this determines whether/how we push
|
||||||
eq(sites.orgId, orgId),
|
// the just-created target to the newt, so a lagging replica
|
||||||
eq(sites.type, "newt"),
|
// returning stale or missing data here would silently skip
|
||||||
isNotNull(sites.pubKey)
|
// the push
|
||||||
)
|
const [site] = await primaryDb
|
||||||
|
.select()
|
||||||
|
.from(sites)
|
||||||
|
.innerJoin(newts, eq(sites.siteId, newts.siteId))
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(sites.siteId, target.siteId),
|
||||||
|
eq(sites.orgId, orgId),
|
||||||
|
eq(sites.type, "newt"),
|
||||||
|
isNotNull(sites.pubKey)
|
||||||
)
|
)
|
||||||
.limit(1);
|
)
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
if (site) {
|
if (site) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`Updating target ${target.targetId} on site ${site.sites.siteId}`
|
`Updating target ${target.targetId} on site ${site.sites.siteId}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// see if you can find a matching target health check from the healthchecksToUpdate array
|
||||||
|
const matchingHealthcheck =
|
||||||
|
result.healthchecksToUpdate.find(
|
||||||
|
(hc) => hc.targetId === target.targetId
|
||||||
);
|
);
|
||||||
|
|
||||||
// see if you can find a matching target health check from the healthchecksToUpdate array
|
if (["http", "tcp", "udp"].includes(target.mode)) {
|
||||||
const matchingHealthcheck =
|
await addProxyTargets(
|
||||||
result.healthchecksToUpdate.find(
|
site.newt.newtId,
|
||||||
(hc) => hc.targetId === target.targetId
|
[target],
|
||||||
);
|
matchingHealthcheck
|
||||||
|
? [matchingHealthcheck]
|
||||||
if (["http", "tcp", "udp"].includes(target.mode)) {
|
: [],
|
||||||
await addProxyTargets(
|
result.proxyResource.mode === "udp"
|
||||||
site.newt.newtId,
|
? "udp"
|
||||||
[target],
|
: "tcp",
|
||||||
matchingHealthcheck
|
site.newt.version
|
||||||
? [matchingHealthcheck]
|
);
|
||||||
: [],
|
} else if (
|
||||||
result.proxyResource.mode === "udp"
|
["ssh", "rdp", "vnc"].includes(target.mode)
|
||||||
? "udp"
|
) {
|
||||||
: "tcp",
|
await sendBrowserGatewayTargets(
|
||||||
site.newt.version
|
site.newt.newtId,
|
||||||
);
|
[target],
|
||||||
} else if (
|
site.newt.version
|
||||||
["ssh", "rdp", "vnc"].includes(target.mode)
|
);
|
||||||
) {
|
|
||||||
await sendBrowserGatewayTargets(
|
|
||||||
site.newt.newtId,
|
|
||||||
[target],
|
|
||||||
site.newt.version
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`Successfully updated public resources for org ${orgId}: ${JSON.stringify(publicResourcesResults)}`
|
`Successfully updated public resources for org ${orgId}: ${JSON.stringify(publicResourcesResults)}`
|
||||||
);
|
);
|
||||||
|
|
||||||
// We need to update the targets on the newts from the successfully updated information
|
// We need to update the targets on the newts from the successfully updated information
|
||||||
for (const result of privateResourcesResults) {
|
for (const result of privateResourcesResults) {
|
||||||
rebuildClientAssociationsFromSiteResource(
|
rebuildClientAssociationsFromSiteResource(
|
||||||
result.newSiteResource
|
result.newSiteResource
|
||||||
|
)
|
||||||
|
.then(() =>
|
||||||
|
waitForSiteResourceRebuildIdle(
|
||||||
|
result.newSiteResource.siteResourceId
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.then(() =>
|
.then(() =>
|
||||||
waitForSiteResourceRebuildIdle(
|
handleMessagingForUpdatedSiteResource(
|
||||||
result.newSiteResource.siteResourceId
|
result.oldSiteResource,
|
||||||
)
|
result.newSiteResource,
|
||||||
|
result.oldSites.map((s) => s.siteId),
|
||||||
|
result.newSites.map((s) => s.siteId)
|
||||||
)
|
)
|
||||||
.then(() =>
|
)
|
||||||
handleMessagingForUpdatedSiteResource(
|
.catch((e) => {
|
||||||
result.oldSiteResource,
|
logger.error(
|
||||||
result.newSiteResource,
|
`Failed to rebuild and handle messaging for site resource ${result.newSiteResource.siteResourceId}. Error: ${e}`
|
||||||
result.oldSites.map((s) => s.siteId),
|
);
|
||||||
result.newSites.map((s) => s.siteId)
|
});
|
||||||
)
|
}
|
||||||
)
|
|
||||||
.catch((e) => {
|
|
||||||
logger.error(
|
|
||||||
`Failed to rebuild and handle messaging for site resource ${result.newSiteResource.siteResourceId}. Error: ${e}`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`Successfully updated private resources for org ${orgId}: ${JSON.stringify(privateResourcesResults)}`
|
`Successfully updated private resources for org ${orgId}: ${JSON.stringify(privateResourcesResults)}`
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
|
||||||
blueprintSucceeded = true;
|
blueprintSucceeded = true;
|
||||||
blueprintMessage = "Blueprint applied successfully";
|
blueprintMessage = "Blueprint applied successfully";
|
||||||
|
|||||||
@@ -345,6 +345,9 @@ export default async function migration() {
|
|||||||
await db.execute(
|
await db.execute(
|
||||||
sql`ALTER TABLE "virtualApiKeys" ADD CONSTRAINT "virtualApiKeys_createdByUserId_user_id_fk" FOREIGN KEY ("createdByUserId") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;`
|
sql`ALTER TABLE "virtualApiKeys" ADD CONSTRAINT "virtualApiKeys_createdByUserId_user_id_fk" FOREIGN KEY ("createdByUserId") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;`
|
||||||
);
|
);
|
||||||
|
await db.execute(
|
||||||
|
sql`ALTER TABLE "eventStreamingDestinations" ADD "sendAISessionLogs" boolean DEFAULT false NOT NULL;`
|
||||||
|
);
|
||||||
await db.execute(
|
await db.execute(
|
||||||
sql`CREATE INDEX "idx_ai_budget_breach_events_budget_created" ON "aiBudgetBreachEvents" USING btree ("budgetId","createdAt");`
|
sql`CREATE INDEX "idx_ai_budget_breach_events_budget_created" ON "aiBudgetBreachEvents" USING btree ("budgetId","createdAt");`
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -402,6 +402,9 @@ export default async function migration() {
|
|||||||
db.prepare(
|
db.prepare(
|
||||||
`ALTER TABLE 'siteResources' ADD 'requiresExitNodeConnection' integer DEFAULT false NOT NULL;`
|
`ALTER TABLE 'siteResources' ADD 'requiresExitNodeConnection' integer DEFAULT false NOT NULL;`
|
||||||
).run();
|
).run();
|
||||||
|
db.prepare(
|
||||||
|
`ALTER TABLE 'eventStreamingDestinations' ADD 'sendAISessionLogs' integer DEFAULT false NOT NULL;`
|
||||||
|
).run();
|
||||||
|
|
||||||
const insertRoleAction = db.prepare(`
|
const insertRoleAction = db.prepare(`
|
||||||
INSERT INTO 'roleActions' ("roleId", "actionId", "orgId")
|
INSERT INTO 'roleActions' ("roleId", "actionId", "orgId")
|
||||||
|
|||||||
Reference in New Issue
Block a user