chore: openapi docs for host metrics manager routes

This commit is contained in:
LukeGus committed 2026-09-30 14:49:56 -05:00
1 parent d8fb2e75af
commit 5ecf8156e6
8 files changed
+426

No files matched your search

@@ -82,6 +82,23 @@ export function buildApplyCrontabCommand(body: string): string {
export function registerCronRoutes(app: Router, deps: ManagerRoutesDeps): void {
const { validateHostId } = deps;
/**
* @openapi
* /plugin-api/host-metrics/managers/cron/{id}:
* get:
* summary: List the SSH user's crontab entries
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* responses:
* 200: { description: The parsed crontab entries. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.get(
"/host-metrics/managers/cron/:id",
validateHostId,
@@ -91,6 +108,32 @@ export function registerCronRoutes(app: Router, deps: ManagerRoutesDeps): void {
}),
);
/**
* @openapi
* /plugin-api/host-metrics/managers/cron/{id}:
* post:
* summary: Replace the SSH user's crontab
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required: [entries]
* properties:
* entries: { type: array, items: { type: object, properties: { schedule: { type: string }, command: { type: string }, enabled: { type: boolean } } } }
* responses:
* 200: { description: The crontab was written. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.post(
"/host-metrics/managers/cron/:id",
validateHostId,
@@ -48,6 +48,23 @@ export function registerFirewallRoutes(
deps: ManagerRoutesDeps,
): void {
const { validateHostId } = deps;
/**
* @openapi
* /plugin-api/host-metrics/managers/firewall/{id}:
* get:
* summary: Read the host firewall (iptables, nftables or ufw)
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* responses:
* 200: { description: The firewall type, status and rules. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.get(
"/host-metrics/managers/firewall/:id",
validateHostId,
@@ -56,6 +73,35 @@ export function registerFirewallRoutes(
}),
);
/**
* @openapi
* /plugin-api/host-metrics/managers/firewall/{id}/rule:
* post:
* summary: Add or delete an input rule
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required: [op, protocol, port, target]
* properties:
* op: { type: string, enum: [add, delete] }
* protocol: { type: string, enum: [tcp, udp] }
* port: { type: integer }
* target: { type: string, description: ACCEPT, DROP or REJECT }
* responses:
* 200: { description: The command result and firewall backend used. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.post(
"/host-metrics/managers/firewall/:id/rule",
validateHostId,
@@ -101,6 +147,23 @@ export function registerFirewallRoutes(
),
);
/**
* @openapi
* /plugin-api/host-metrics/managers/firewall/{id}/persist:
* post:
* summary: Save the current firewall rules so they survive a reboot
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* responses:
* 200: { description: The save result. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.post(
"/host-metrics/managers/firewall/:id/persist",
validateHostId,
@@ -149,6 +149,23 @@ export function registerHealthRoutes(
});
}
};
/**
* @openapi
* /plugin-api/host-metrics/managers/health/{id}:
* get:
* summary: Get the host's health checks and their last results
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* responses:
* 200: { description: The configured checks and results. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.get(
"/host-metrics/managers/health/:id",
validateHostId,
@@ -162,6 +179,33 @@ export function registerHealthRoutes(
}),
);
/**
* @openapi
* /plugin-api/host-metrics/managers/health/{id}/config:
* post:
* summary: Save the host's health checks
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required: [checks]
* properties:
* checks: { type: array, items: { type: object, properties: { id: { type: string }, name: { type: string }, type: { type: string }, target: { type: string }, port: { type: integer }, path: { type: string } } } }
* intervalSeconds: { type: integer }
* responses:
* 200: { description: The saved checks. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.post(
"/host-metrics/managers/health/:id/config",
validateHostId,
@@ -195,6 +239,23 @@ export function registerHealthRoutes(
),
);
/**
* @openapi
* /plugin-api/host-metrics/managers/health/{id}/run:
* post:
* summary: Run the host's health checks now
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* responses:
* 200: { description: The result of each check. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.post(
"/host-metrics/managers/health/:id/run",
validateHostId,
@@ -43,6 +43,23 @@ export function buildJournalCommand(unit: string, lines: number): string {
export function registerLogRoutes(app: Router, deps: ManagerRoutesDeps): void {
const { validateHostId } = deps;
/**
* @openapi
* /plugin-api/host-metrics/managers/logs/{id}/files:
* get:
* summary: List readable log files under /var/log
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* responses:
* 200: { description: Common logs and the files found. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.get(
"/host-metrics/managers/logs/:id/files",
validateHostId,
@@ -57,6 +74,34 @@ export function registerLogRoutes(app: Router, deps: ManagerRoutesDeps): void {
}),
);
/**
* @openapi
* /plugin-api/host-metrics/managers/logs/{id}:
* get:
* summary: Tail a log file or a systemd unit's journal
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* - in: query
* name: path
* schema: { type: string }
* description: A log file under an allowed directory.
* - in: query
* name: unit
* schema: { type: string }
* description: A systemd unit. Used instead of path when given.
* - in: query
* name: lines
* schema: { type: integer }
* responses:
* 200: { description: The last lines of the log. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.get(
"/host-metrics/managers/logs/:id",
validateHostId,
@@ -17,6 +17,23 @@ export function registerPackageRoutes(
deps: ManagerRoutesDeps,
): void {
const { validateHostId } = deps;
/**
* @openapi
* /plugin-api/host-metrics/managers/packages/{id}:
* get:
* summary: List upgradable packages and the package manager
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* responses:
* 200: { description: The package manager and upgradable packages. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.get(
"/host-metrics/managers/packages/:id",
validateHostId,
@@ -32,6 +49,33 @@ export function registerPackageRoutes(
}),
);
/**
* @openapi
* /plugin-api/host-metrics/managers/packages/{id}/action:
* post:
* summary: Install or upgrade a package, or upgrade everything
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required: [action]
* properties:
* action: { type: string, enum: [install, upgrade, upgrade-all] }
* pkg: { type: string, description: The package name. Not needed for upgrade-all. }
* responses:
* 200: { description: The command output. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.post(
"/host-metrics/managers/packages/:id/action",
validateHostId,
@@ -110,6 +110,23 @@ export function registerSimpleReadRoutes(
deps: ManagerRoutesDeps,
): void {
const { validateHostId } = deps;
/**
* @openapi
* /plugin-api/host-metrics/managers/top-memory/{id}:
* get:
* summary: List the processes using the most memory
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* responses:
* 200: { description: The top processes by memory. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.get(
"/host-metrics/managers/top-memory/:id",
validateHostId,
@@ -119,6 +136,23 @@ export function registerSimpleReadRoutes(
}),
);
/**
* @openapi
* /plugin-api/host-metrics/managers/timers/{id}:
* get:
* summary: List systemd timers
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* responses:
* 200: { description: The timers with their next and last runs. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.get(
"/host-metrics/managers/timers/:id",
validateHostId,
@@ -128,6 +162,23 @@ export function registerSimpleReadRoutes(
}),
);
/**
* @openapi
* /plugin-api/host-metrics/managers/disk-breakdown/{id}:
* get:
* summary: List mounted filesystems and their usage
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* responses:
* 200: { description: Size, used and free space per mount. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.get(
"/host-metrics/managers/disk-breakdown/:id",
validateHostId,
@@ -151,6 +151,23 @@ export function buildRevokeCommand(client: AcmeClient, name: string): string {
export function registerSslRoutes(app: Router, deps: ManagerRoutesDeps): void {
const { validateHostId } = deps;
/**
* @openapi
* /plugin-api/host-metrics/managers/ssl/{id}:
* get:
* summary: List certificates from certbot and acme.sh
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* responses:
* 200: { description: The installed ACME clients and certificates. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.get(
"/host-metrics/managers/ssl/:id",
validateHostId,
@@ -183,6 +200,36 @@ export function registerSslRoutes(app: Router, deps: ManagerRoutesDeps): void {
}),
);
/**
* @openapi
* /plugin-api/host-metrics/managers/ssl/{id}/issue:
* post:
* summary: Issue a certificate with certbot or acme.sh
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required: [client, domains, challenge]
* properties:
* client: { type: string, enum: [certbot, acme.sh] }
* domains: { type: array, items: { type: string } }
* challenge: { type: string, enum: [http-standalone, http-webroot, dns] }
* webroot: { type: string }
* dnsProvider: { type: string }
* responses:
* 200: { description: The issue result. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.post(
"/host-metrics/managers/ssl/:id/issue",
validateHostId,
@@ -227,6 +274,33 @@ export function registerSslRoutes(app: Router, deps: ManagerRoutesDeps): void {
}),
);
/**
* @openapi
* /plugin-api/host-metrics/managers/ssl/{id}/renew:
* post:
* summary: Renew certificates
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required: [client]
* properties:
* client: { type: string, enum: [certbot, acme.sh] }
* dryRun: { type: boolean }
* responses:
* 200: { description: The renew result. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.post(
"/host-metrics/managers/ssl/:id/renew",
validateHostId,
@@ -73,6 +73,23 @@ export type UserAction = "create" | "delete" | "addToGroup" | "removeFromGroup";
export function registerUserRoutes(app: Router, deps: ManagerRoutesDeps): void {
const { validateHostId } = deps;
/**
* @openapi
* /plugin-api/host-metrics/managers/users/{id}:
* get:
* summary: List local users and groups
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* responses:
* 200: { description: The users and groups. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.get(
"/host-metrics/managers/users/:id",
validateHostId,
@@ -90,6 +107,34 @@ export function registerUserRoutes(app: Router, deps: ManagerRoutesDeps): void {
}),
);
/**
* @openapi
* /plugin-api/host-metrics/managers/users/{id}/action:
* post:
* summary: Create or delete a user, or change a user's groups
* tags: [Host Metrics]
* parameters:
* - in: path
* name: id
* required: true
* schema: { type: integer }
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required: [action, username]
* properties:
* action: { type: string, enum: [create, delete, addToGroup, removeFromGroup] }
* username: { type: string }
* group: { type: string, description: Needed for the group actions. }
* responses:
* 200: { description: The command result. }
* 400: { description: Invalid input. }
* 403: { description: No access to the host, or elevation denied. }
* 500: { description: The command failed on the host. }
*/
app.post(
"/host-metrics/managers/users/:id/action",
validateHostId,