postgresai 0.16.0-rc.1 → 0.16.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/postgres-ai.ts +98 -7
- package/dist/bin/postgres-ai.js +7631 -7408
- package/lib/aas-onboard.ts +251 -0
- package/package.json +1 -1
- package/test/aas-onboard.test.ts +301 -0
- package/test/monitoring.test.ts +54 -3
package/bin/postgres-ai.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { startMcpServer } from "../lib/mcp-server";
|
|
|
14
14
|
import { fetchIssues, fetchIssueComments, createIssueComment, fetchIssue, createIssue, updateIssue, updateIssueComment, fetchActionItem, fetchActionItems, createActionItem, updateActionItem, type ConfigChange } from "../lib/issues";
|
|
15
15
|
import { fetchReports, fetchAllReports, fetchReportFiles, fetchReportFileData, renderMarkdownForTerminal, parseFlexibleDate } from "../lib/reports";
|
|
16
16
|
import { resolveBaseUrls } from "../lib/util";
|
|
17
|
+
import { registerAasCollection, parseVcpus } from "../lib/aas-onboard";
|
|
17
18
|
import { uploadFile, downloadFile, buildMarkdownLink, uploadAttachments, appendAttachmentsToContent } from "../lib/storage";
|
|
18
19
|
import { applyInitPlan, applyUninitPlan, buildInitPlan, buildUninitPlan, checkCurrentUserPermissions, connectWithSslFallback, DEFAULT_MONITORING_USER, formatPermissionCheckMessages, KNOWN_PROVIDERS, redactPasswordsInSql, resolveAdminConnection, resolveMonitoringPassword, validateProvider, verifyInitSetup } from "../lib/init";
|
|
19
20
|
import { SupabaseClient, resolveSupabaseConfig, extractProjectRefFromUrl, applyInitPlanViaSupabase, verifyInitSetupViaSupabase, fetchPoolerDatabaseUrl, type PgCompatibleError } from "../lib/supabase";
|
|
@@ -2442,9 +2443,44 @@ interface MonitoringRegistration {
|
|
|
2442
2443
|
*
|
|
2443
2444
|
* Never throws — registration is best-effort; returns null on failure.
|
|
2444
2445
|
*/
|
|
2446
|
+
|
|
2447
|
+
/**
|
|
2448
|
+
* Classify how `mon local-install` should register the monitoring instance,
|
|
2449
|
+
* given the raw `--project` value and the resolved instance id.
|
|
2450
|
+
*
|
|
2451
|
+
* - With an instance id: ADOPT the provisioned instance. No project name is
|
|
2452
|
+
* required (the platform returns the real project); a provided name is
|
|
2453
|
+
* normalized and carried through for messaging/fallback.
|
|
2454
|
+
* - No instance id and no project name: ERROR. The hardcoded
|
|
2455
|
+
* "postgres-ai-monitoring" default was removed, and a nameless legacy
|
|
2456
|
+
* self-registration is rejected by v1.monitoring_instance_register (PT400).
|
|
2457
|
+
* - No instance id but a project name: legacy SELF-REGISTER.
|
|
2458
|
+
*
|
|
2459
|
+
* Pure (no I/O) so the decision is unit-testable independently of the large
|
|
2460
|
+
* install command. `projectName` is the trimmed value, or undefined when empty.
|
|
2461
|
+
*/
|
|
2462
|
+
type MonRegistrationPlan =
|
|
2463
|
+
| { kind: "adopt"; projectName: string | undefined }
|
|
2464
|
+
| { kind: "self-register"; projectName: string }
|
|
2465
|
+
| { kind: "error-missing-project"; projectName: undefined };
|
|
2466
|
+
|
|
2467
|
+
function planMonitoringRegistration(args: {
|
|
2468
|
+
project?: string;
|
|
2469
|
+
instanceId?: string;
|
|
2470
|
+
}): MonRegistrationPlan {
|
|
2471
|
+
const projectName = args.project?.trim() || undefined;
|
|
2472
|
+
if (args.instanceId) {
|
|
2473
|
+
return { kind: "adopt", projectName };
|
|
2474
|
+
}
|
|
2475
|
+
if (!projectName) {
|
|
2476
|
+
return { kind: "error-missing-project", projectName: undefined };
|
|
2477
|
+
}
|
|
2478
|
+
return { kind: "self-register", projectName };
|
|
2479
|
+
}
|
|
2480
|
+
|
|
2445
2481
|
async function registerMonitoringInstance(
|
|
2446
2482
|
apiKey: string,
|
|
2447
|
-
projectName: string,
|
|
2483
|
+
projectName: string | undefined,
|
|
2448
2484
|
opts?: { apiBaseUrl?: string; debug?: boolean; instanceId?: string; retries?: number; retryDelayMs?: number }
|
|
2449
2485
|
): Promise<MonitoringRegistration | null> {
|
|
2450
2486
|
const { apiBaseUrl } = resolveBaseUrls(opts);
|
|
@@ -2456,16 +2492,25 @@ async function registerMonitoringInstance(
|
|
|
2456
2492
|
// moment to recover; skipped before the first attempt. Tests pass 0.
|
|
2457
2493
|
const retryDelayMs = opts?.retryDelayMs ?? 400;
|
|
2458
2494
|
|
|
2495
|
+
// Omit project_name entirely when empty: the adopt path (instance_id present)
|
|
2496
|
+
// relies on the platform returning the real project, and a nameless legacy
|
|
2497
|
+
// self-registration is rejected by v1.monitoring_instance_register (PT400).
|
|
2498
|
+
const hasProjectName = !!(projectName && projectName.trim());
|
|
2499
|
+
|
|
2459
2500
|
if (debug) {
|
|
2460
2501
|
console.error(`\nDebug: Registering monitoring instance...`);
|
|
2461
2502
|
console.error(`Debug: POST ${url}`);
|
|
2462
|
-
console.error(
|
|
2503
|
+
console.error(
|
|
2504
|
+
`Debug: ${hasProjectName ? `project_name=${projectName}` : "project_name=(omitted)"}${instanceId ? ` instance_id=${instanceId}` : ""}`
|
|
2505
|
+
);
|
|
2463
2506
|
}
|
|
2464
2507
|
|
|
2465
2508
|
const requestBody: Record<string, string> = {
|
|
2466
2509
|
api_token: apiKey,
|
|
2467
|
-
project_name: projectName,
|
|
2468
2510
|
};
|
|
2511
|
+
if (hasProjectName) {
|
|
2512
|
+
requestBody.project_name = projectName as string;
|
|
2513
|
+
}
|
|
2469
2514
|
if (instanceId) {
|
|
2470
2515
|
requestBody.instance_id = instanceId;
|
|
2471
2516
|
}
|
|
@@ -2712,8 +2757,12 @@ mon
|
|
|
2712
2757
|
"--instance-id <uuid>",
|
|
2713
2758
|
"adopt a console-provisioned monitoring instance instead of self-registering a new one (set automatically by the provisioning flow; PGAI_INSTANCE_ID env also works)"
|
|
2714
2759
|
)
|
|
2760
|
+
.option(
|
|
2761
|
+
"--vcpus <n>",
|
|
2762
|
+
"source DB vCPU count used for AAS zone thresholds (set automatically by the provisioning flow; PGAI_VCPUS env also works). Omit or 0 = unknown — AAS collection stays off until a real value is set."
|
|
2763
|
+
)
|
|
2715
2764
|
.option("-y, --yes", "accept all defaults and skip interactive prompts", false)
|
|
2716
|
-
.action(async (opts: { demo: boolean; apiKey?: string; dbUrl?: string; tag?: string; project?: string; instanceId?: string; yes: boolean }) => {
|
|
2765
|
+
.action(async (opts: { demo: boolean; apiKey?: string; dbUrl?: string; tag?: string; project?: string; instanceId?: string; vcpus?: string; yes: boolean }) => {
|
|
2717
2766
|
// Get apiKey from global program options (--api-key is defined globally)
|
|
2718
2767
|
// This is needed because Commander.js routes --api-key to the global option, not the subcommand's option
|
|
2719
2768
|
const globalOpts = program.opts<CliOptions>();
|
|
@@ -3132,8 +3181,11 @@ mon
|
|
|
3132
3181
|
// and persisted; the legacy self-registration stays fire-and-forget
|
|
3133
3182
|
// (issue platform-all#311).
|
|
3134
3183
|
if (apiKey && !opts.demo) {
|
|
3135
|
-
const projectName = opts.project || "postgres-ai-monitoring";
|
|
3136
3184
|
const instanceId = opts.instanceId || process.env.PGAI_INSTANCE_ID;
|
|
3185
|
+
const plan = planMonitoringRegistration({ project: opts.project, instanceId });
|
|
3186
|
+
const projectName = plan.projectName;
|
|
3187
|
+
// `instanceId` truthy ⟺ plan.kind === "adopt"; branch on it directly so
|
|
3188
|
+
// TypeScript narrows instanceId to a defined string in the adopt path.
|
|
3137
3189
|
if (instanceId) {
|
|
3138
3190
|
const reg = await registerMonitoringInstance(apiKey, projectName, {
|
|
3139
3191
|
apiBaseUrl: globalOpts.apiBaseUrl,
|
|
@@ -3155,13 +3207,51 @@ mon
|
|
|
3155
3207
|
// Request succeeded but carried no usable project field — don't claim
|
|
3156
3208
|
// adoption, but don't report a hard failure either (no re-run needed).
|
|
3157
3209
|
console.error(
|
|
3158
|
-
`⚠ Adopted provisioned instance ${instanceId} but the platform returned no project
|
|
3210
|
+
`⚠ Adopted provisioned instance ${instanceId} but the platform returned no project` +
|
|
3211
|
+
(projectName
|
|
3212
|
+
? ` — reports will use project '${projectName}'`
|
|
3213
|
+
: ` — reports will have no project until 'postgresai mon local-install' is re-run with --project <name>`)
|
|
3159
3214
|
);
|
|
3160
3215
|
} else {
|
|
3161
3216
|
console.error(
|
|
3162
|
-
`⚠ Could not adopt provisioned instance ${instanceId}
|
|
3217
|
+
`⚠ Could not adopt provisioned instance ${instanceId}` +
|
|
3218
|
+
(projectName
|
|
3219
|
+
? ` — reports will use project '${projectName}' until 'postgresai mon local-install' is re-run`
|
|
3220
|
+
: ` — reports will have no project until 'postgresai mon local-install' is re-run with --project <name>`)
|
|
3163
3221
|
);
|
|
3164
3222
|
}
|
|
3223
|
+
|
|
3224
|
+
// Best-effort: arm hands-off AAS auto-collection for this adopted
|
|
3225
|
+
// instance. Mints a Grafana Viewer SA on the LOCAL Grafana, resolves
|
|
3226
|
+
// the datasource id + (cluster, node_name) labels from the pgwatch
|
|
3227
|
+
// config we wrote, and hands the platform a finished token via the
|
|
3228
|
+
// API-token RPC (v1.monitoring_instance_aas_register). Never fatal —
|
|
3229
|
+
// it can be enabled later by re-running local-install.
|
|
3230
|
+
const aas = await registerAasCollection(apiKey, instanceId, {
|
|
3231
|
+
grafanaPassword,
|
|
3232
|
+
instancesPath,
|
|
3233
|
+
vcpus: parseVcpus(opts.vcpus ?? process.env.PGAI_VCPUS),
|
|
3234
|
+
apiBaseUrl: globalOpts.apiBaseUrl,
|
|
3235
|
+
debug: !!process.env.DEBUG,
|
|
3236
|
+
});
|
|
3237
|
+
if (aas.ok) {
|
|
3238
|
+
console.log("✓ AAS auto-collection registered\n");
|
|
3239
|
+
} else {
|
|
3240
|
+
console.error(
|
|
3241
|
+
`⚠ AAS auto-collection not registered (${aas.reason}); it can be enabled later by re-running 'postgresai mon local-install'\n`
|
|
3242
|
+
);
|
|
3243
|
+
}
|
|
3244
|
+
} else if (plan.kind === "error-missing-project") {
|
|
3245
|
+
// Legacy self-registration (no --instance-id) now requires a project
|
|
3246
|
+
// name: the hardcoded "postgres-ai-monitoring" default was removed, and
|
|
3247
|
+
// v1.monitoring_instance_register raises PT400 for a nameless legacy
|
|
3248
|
+
// registration. Console-provisioned installs should adopt with
|
|
3249
|
+
// --instance-id instead.
|
|
3250
|
+
console.error(
|
|
3251
|
+
"✗ A project name is required for self-registration (the 'postgres-ai-monitoring' default was removed). " +
|
|
3252
|
+
"Re-run with --project <name>, or adopt a console-provisioned instance with --instance-id <uuid>."
|
|
3253
|
+
);
|
|
3254
|
+
process.exitCode = 1;
|
|
3165
3255
|
} else {
|
|
3166
3256
|
void registerMonitoringInstance(apiKey, projectName, {
|
|
3167
3257
|
apiBaseUrl: globalOpts.apiBaseUrl,
|
|
@@ -5462,3 +5552,4 @@ if (import.meta.main) {
|
|
|
5462
5552
|
// same functions used by the `mon` commands).
|
|
5463
5553
|
export { refreshBundledComposeIfStale, readDeployedTag, isValidComposeYaml };
|
|
5464
5554
|
export { registerMonitoringInstance, resolveAdoptedProject, type MonitoringRegistration };
|
|
5555
|
+
export { planMonitoringRegistration, type MonRegistrationPlan };
|