OpenAPI spec at /api/docs with a Scalar viewer, opt-in via FEAT_API_DOCS
This commit is contained in:
251 files changed
+32497
-66
No files matched your search
@@ -10,6 +10,15 @@ import { serializeLabels, parseLabels, MAX_LABELS } from '$lib/utils/label-color
|
||||
import { cleanPem } from '$lib/utils/pem';
|
||||
import { validateEnvName } from '$lib/utils/env-name';
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* summary: List all Docker environments (hosts) known to Dockhand
|
||||
* resp-200: array<{id:integer!, name:string!, connectionType:string!, host:string, port:integer, protocol:string, icon:string, publicIp:string, timezone:string}>
|
||||
* resp-200-desc: Environments accessible to the caller (filtered by RBAC in Enterprise mode; all environments in Free edition)
|
||||
* resp-200-example: [{"id":1,"name":"hhdocker01","connectionType":"socket","host":null,"port":2375,"protocol":"http","icon":"server","publicIp":"203.0.113.10","timezone":"Europe/Berlin"},{"id":2,"name":"hhdocker02","connectionType":"hawser-edge","host":null,"port":2375,"protocol":"http","icon":"server","publicIp":null,"timezone":"Europe/Berlin"}]
|
||||
* resp-403: Permission denied (RBAC 'environments:view' missing)
|
||||
* resp-500: Unexpected error while loading environments
|
||||
*/
|
||||
export const GET: RequestHandler = async ({ cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
if (auth.authEnabled && !await auth.can('environments', 'view')) {
|
||||
@@ -63,6 +72,18 @@ export const GET: RequestHandler = async ({ cookies }) => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Register a new Docker environment (host)
|
||||
* body: {name:string!, connectionType:string, host:string, port:integer, protocol:string, socketPath:string, icon:string, publicIp:string, labels:string}
|
||||
* body-example: {"name":"hhdocker03","connectionType":"socket","socketPath":"/var/run/docker.sock","icon":"server"}
|
||||
* resp-200: {id:integer!, name:string!, connectionType:string!}
|
||||
* resp-200-example: {"id":3,"name":"hhdocker03","connectionType":"socket"}
|
||||
* resp-400: Invalid name, invalid connectionType, or host missing for direct/hawser-standard
|
||||
* resp-403: Permission denied (RBAC 'environments:create' missing)
|
||||
* resp-409: An environment with this name already exists
|
||||
* resp-500: Unexpected error while creating the environment
|
||||
*/
|
||||
export const POST: RequestHandler = async (event) => {
|
||||
const { request, cookies } = event;
|
||||
const auth = await authorize(cookies);
|
||||
|
||||
@@ -18,6 +18,15 @@ import { closeEdgeConnection } from '$lib/server/hawser';
|
||||
import { computeAuditDiff } from '$lib/utils/diff';
|
||||
import { deleteEnvironmentIcon } from '$lib/server/env-icons';
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Get a single environment by id, including its parsed labels and public IP
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* resp-200: {id:integer!, name:string!, connectionType:string!, labels:array<string>, publicIp:string}
|
||||
* resp-403: Permission denied (RBAC 'environments:view' missing)
|
||||
* resp-404: Environment not found
|
||||
* resp-500: Unexpected error while loading the environment
|
||||
*/
|
||||
export const GET: RequestHandler = async ({ params, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
if (auth.authEnabled && !await auth.can('environments', 'view')) {
|
||||
@@ -48,6 +57,19 @@ export const GET: RequestHandler = async ({ params, cookies }) => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Update an environment; renaming also renames its on-disk stacks/git-repos directories
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* body: {name:string, host:string, port:integer, protocol:string, tlsCa:string, tlsCert:string, tlsKey:string, tlsSkipVerify:boolean, icon:string, socketPath:string, collectActivity:boolean, collectMetrics:boolean, highlightChanges:boolean, labels:string, connectionType:string, hawserToken:string, publicIp:string}
|
||||
* body-example: {"name":"hhdocker03","collectMetrics":true}
|
||||
* resp-200: {id:integer!, name:string!, connectionType:string!, labels:array<string>, publicIp:string}
|
||||
* resp-400: Invalid new name (rename validation)
|
||||
* resp-403: Permission denied (RBAC 'environments:edit' missing)
|
||||
* resp-404: Environment not found
|
||||
* resp-409: Rename target directory already exists, or the on-disk rename failed (e.g. EXDEV across filesystems)
|
||||
* resp-500: Unexpected error while updating the environment
|
||||
*/
|
||||
export const PUT: RequestHandler = async (event) => {
|
||||
const { params, request, cookies } = event;
|
||||
const auth = await authorize(cookies);
|
||||
@@ -195,6 +217,16 @@ export const PUT: RequestHandler = async (event) => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Delete an environment and all its associated git stacks, schedules, icons, and on-disk directories
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* resp-200: {success:boolean!}
|
||||
* resp-400: Invalid environment id, or the environment could not be deleted
|
||||
* resp-403: Permission denied (RBAC 'environments:delete' missing)
|
||||
* resp-404: Environment not found
|
||||
* resp-500: Environment name is empty/whitespace (refuses to delete to avoid an unsafe directory cleanup), or an unexpected error
|
||||
*/
|
||||
export const DELETE: RequestHandler = async (event) => {
|
||||
const { params, cookies } = event;
|
||||
const auth = await authorize(cookies);
|
||||
|
||||
@@ -3,6 +3,16 @@ import type { RequestHandler } from './$types';
|
||||
import { authorize } from '$lib/server/authorize';
|
||||
import { getEnvironment, getEnvSetting, setEnvSetting } from '$lib/server/db';
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Get the disk-space warning thresholds for an environment
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* resp-200: {enabled:boolean!, mode:string!, threshold:integer!, thresholdGb:integer!}
|
||||
* resp-200-example: {"enabled":true,"mode":"percentage","threshold":80,"thresholdGb":50}
|
||||
* resp-403: Permission denied (RBAC 'environments:view' missing)
|
||||
* resp-404: Environment not found
|
||||
* resp-500: Unexpected error while loading the settings
|
||||
*/
|
||||
export const GET: RequestHandler = async ({ params, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
if (auth.authEnabled && !(await auth.can('environments', 'view'))) {
|
||||
@@ -28,6 +38,17 @@ export const GET: RequestHandler = async ({ params, cookies }) => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Save the disk-space warning thresholds for an environment (each field optional/independent)
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* body: {enabled:boolean, mode:string, threshold:integer, thresholdGb:integer}
|
||||
* body-example: {"enabled":true,"mode":"percentage","threshold":85}
|
||||
* resp-200: {success:boolean!}
|
||||
* resp-403: Permission denied (RBAC 'environments:edit' missing)
|
||||
* resp-404: Environment not found
|
||||
* resp-500: Unexpected error while saving the settings
|
||||
*/
|
||||
export const POST: RequestHandler = async ({ params, request, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
if (auth.authEnabled && !(await auth.can('environments', 'edit'))) {
|
||||
|
||||
@@ -4,6 +4,13 @@ import { getEnvironment, updateEnvironment } from '$lib/server/db';
|
||||
import { authorize } from '$lib/server/authorize';
|
||||
import { saveEnvironmentIcon, deleteEnvironmentIcon, getEnvironmentIconBuffer } from '$lib/server/env-icons';
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Get the custom icon image for an environment (raw image/webp bytes, not JSON)
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* resp-200: Binary image/webp response body, Cache-Control public max-age=3600
|
||||
* resp-404: No custom icon set for this environment
|
||||
*/
|
||||
export const GET: RequestHandler = async ({ params }) => {
|
||||
const id = parseInt(params.id);
|
||||
const buffer = getEnvironmentIconBuffer(id);
|
||||
@@ -20,6 +27,17 @@ export const GET: RequestHandler = async ({ params }) => {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Upload a custom icon for an environment (base64-encoded image, ~200KB limit)
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* body: {image:string!}
|
||||
* resp-200: {success:boolean!, icon:string!}
|
||||
* resp-200-example: {"success":true,"icon":"custom:env-3.webp"}
|
||||
* resp-400: Missing image data, or image exceeds the ~300000-char base64 size limit
|
||||
* resp-403: Permission denied (RBAC 'environments:edit' missing)
|
||||
* resp-404: Environment not found
|
||||
*/
|
||||
export const POST: RequestHandler = async ({ params, request, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
if (auth.authEnabled && !await auth.can('environments', 'edit')) {
|
||||
@@ -49,6 +67,15 @@ export const POST: RequestHandler = async ({ params, request, cookies }) => {
|
||||
return json({ success: true, icon: iconValue });
|
||||
};
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Remove an environment's custom icon and reset it to the default "globe" icon
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* resp-200: {success:boolean!, icon:string!}
|
||||
* resp-200-example: {"success":true,"icon":"globe"}
|
||||
* resp-403: Permission denied (RBAC 'environments:edit' missing)
|
||||
* resp-404: Environment not found
|
||||
*/
|
||||
export const DELETE: RequestHandler = async ({ params, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
if (auth.authEnabled && !await auth.can('environments', 'edit')) {
|
||||
|
||||
@@ -10,6 +10,15 @@ import { registerSchedule, unregisterSchedule, triggerImagePrune } from '$lib/se
|
||||
|
||||
/**
|
||||
* Get image prune settings for an environment.
|
||||
*
|
||||
* @openapi
|
||||
* summary: Get the automatic image-prune schedule settings for an environment
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* resp-200: {settings:{enabled:boolean!, cronExpression:string!, pruneMode:string!}!}
|
||||
* resp-200-example: {"settings":{"enabled":false,"cronExpression":"0 3 * * 0","pruneMode":"dangling"}}
|
||||
* resp-403: Permission denied (RBAC 'environments:view' missing)
|
||||
* resp-404: Environment not found
|
||||
* resp-500: Unexpected error while loading the settings
|
||||
*/
|
||||
export const GET: RequestHandler = async ({ params, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
@@ -43,6 +52,16 @@ export const GET: RequestHandler = async ({ params, cookies }) => {
|
||||
|
||||
/**
|
||||
* Save image prune settings for an environment.
|
||||
*
|
||||
* @openapi
|
||||
* summary: Save the automatic image-prune schedule for an environment (registers/unregisters the croner job)
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* body: {enabled:boolean, cronExpression:string, pruneMode:string}
|
||||
* body-example: {"enabled":true,"cronExpression":"0 3 * * 0","pruneMode":"dangling"}
|
||||
* resp-200: {success:boolean!, settings:{enabled:boolean!, cronExpression:string!, pruneMode:string!}!}
|
||||
* resp-403: Permission denied (RBAC 'environments:edit' missing)
|
||||
* resp-404: Environment not found
|
||||
* resp-500: Unexpected error while saving the settings
|
||||
*/
|
||||
export const POST: RequestHandler = async ({ params, request, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
@@ -91,6 +110,15 @@ export const POST: RequestHandler = async ({ params, request, cookies }) => {
|
||||
|
||||
/**
|
||||
* Manually trigger image prune for an environment.
|
||||
*
|
||||
* @openapi
|
||||
* summary: Immediately run an image prune for an environment (outside its schedule)
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* resp-200: {success:boolean!}
|
||||
* resp-400: The prune operation itself failed (Docker error)
|
||||
* resp-403: Permission denied (RBAC 'environments:edit' missing)
|
||||
* resp-404: Environment not found
|
||||
* resp-500: Unexpected error while triggering the prune
|
||||
*/
|
||||
export const PUT: RequestHandler = async ({ params, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
|
||||
@@ -10,6 +10,16 @@ import { authorize } from '$lib/server/authorize';
|
||||
import type { RequestHandler } from './$types';
|
||||
|
||||
// GET /api/environments/[id]/notifications - List all notification configurations for an environment
|
||||
/**
|
||||
* @openapi
|
||||
* summary: List notification channel configurations attached to an environment
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* resp-200: array<{id:integer!, notificationId:integer!, enabled:boolean!, eventTypes:array<string>}>
|
||||
* resp-400: Invalid environment id
|
||||
* resp-403: Permission denied (RBAC 'notifications:view' missing)
|
||||
* resp-404: Environment not found
|
||||
* resp-500: Unexpected error while loading notifications
|
||||
*/
|
||||
export const GET: RequestHandler = async ({ params, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
if (auth.authEnabled && !await auth.can('notifications', 'view')) {
|
||||
@@ -36,6 +46,20 @@ export const GET: RequestHandler = async ({ params, cookies }) => {
|
||||
};
|
||||
|
||||
// POST /api/environments/[id]/notifications - Add a notification channel to an environment
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Attach a notification channel to an environment
|
||||
* description: notificationId from GET /api/notifications.
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* body: {notificationId:integer!, enabled:boolean, eventTypes:array<string>}
|
||||
* body-example: {"notificationId":1,"enabled":true,"eventTypes":["stack_deploy_failed"]}
|
||||
* resp-200: {id:integer!, notificationId:integer!, enabled:boolean!}
|
||||
* resp-400: Invalid environment id, or notificationId missing
|
||||
* resp-403: Permission denied (RBAC 'notifications:edit' missing)
|
||||
* resp-404: Environment not found
|
||||
* resp-409: This notification channel is already configured for this environment
|
||||
* resp-500: Unexpected error while creating the notification link
|
||||
*/
|
||||
export const POST: RequestHandler = async ({ params, request, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
if (auth.authEnabled && !await auth.can('notifications', 'edit')) {
|
||||
|
||||
@@ -10,6 +10,17 @@ import { authorize } from '$lib/server/authorize';
|
||||
import type { RequestHandler } from './$types';
|
||||
|
||||
// GET /api/environments/[id]/notifications/[notificationId] - Get a specific environment notification
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Get one notification-channel link for an environment
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* path: notificationId:integer! Notification channel id (from GET /api/notifications)
|
||||
* resp-200: {id:integer!, notificationId:integer!, enabled:boolean!, eventTypes:array<string>}
|
||||
* resp-400: Invalid id or notificationId
|
||||
* resp-403: Permission denied (RBAC 'notifications:view' missing)
|
||||
* resp-404: Environment not found, or no such notification link for this environment
|
||||
* resp-500: Unexpected error while loading the notification link
|
||||
*/
|
||||
export const GET: RequestHandler = async ({ params, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
if (auth.authEnabled && !await auth.can('notifications', 'view')) {
|
||||
@@ -40,6 +51,19 @@ export const GET: RequestHandler = async ({ params, cookies }) => {
|
||||
};
|
||||
|
||||
// PUT /api/environments/[id]/notifications/[notificationId] - Update an environment notification
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Update a notification-channel link (enabled state and/or event type filter)
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* path: notificationId:integer! Notification channel id (from GET /api/notifications)
|
||||
* body: {enabled:boolean, eventTypes:array<string>}
|
||||
* body-example: {"enabled":false}
|
||||
* resp-200: {id:integer!, notificationId:integer!, enabled:boolean!, eventTypes:array<string>}
|
||||
* resp-400: Invalid id or notificationId
|
||||
* resp-403: Permission denied (RBAC 'notifications:edit' missing)
|
||||
* resp-404: Environment not found, or no such notification link for this environment
|
||||
* resp-500: Unexpected error while updating the notification link
|
||||
*/
|
||||
export const PUT: RequestHandler = async ({ params, request, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
if (auth.authEnabled && !await auth.can('notifications', 'edit')) {
|
||||
@@ -78,6 +102,17 @@ export const PUT: RequestHandler = async ({ params, request, cookies }) => {
|
||||
};
|
||||
|
||||
// DELETE /api/environments/[id]/notifications/[notificationId] - Remove a notification from an environment
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Remove a notification-channel link from an environment
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* path: notificationId:integer! Notification channel id (from GET /api/notifications)
|
||||
* resp-200: {success:boolean!}
|
||||
* resp-400: Invalid id or notificationId
|
||||
* resp-403: Permission denied (RBAC 'notifications:delete' missing)
|
||||
* resp-404: No such notification link for this environment
|
||||
* resp-500: Unexpected error while deleting the notification link
|
||||
*/
|
||||
export const DELETE: RequestHandler = async ({ params, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
if (auth.authEnabled && !await auth.can('notifications', 'delete')) {
|
||||
|
||||
@@ -9,6 +9,15 @@ import { getEnvironment, getEnvSetting, setEnvSetting } from '$lib/server/db';
|
||||
// remote host under this dir before `docker compose up`. Empty/unset = current behavior.
|
||||
// Stored via the generic per-env settings store (no schema column).
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Get the per-environment remote stacks directory used to stage stack files onto a direct (agentless) daemon
|
||||
* path: id:integer! Environment ID (from GET /api/environments)
|
||||
* resp-200: {remoteStacksDir:string}
|
||||
* resp-200-example: {"remoteStacksDir":"/mnt/dockhand/stacks"}
|
||||
* resp-403: Permission denied (requires environments:view)
|
||||
* resp-404: Environment not found
|
||||
*/
|
||||
export const GET: RequestHandler = async ({ params, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
if (auth.authEnabled && !(await auth.can('environments', 'view'))) {
|
||||
@@ -23,6 +32,18 @@ export const GET: RequestHandler = async ({ params, cookies }) => {
|
||||
return json({ remoteStacksDir });
|
||||
};
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Set (or clear) the per-environment remote stacks directory for a direct (agentless) daemon
|
||||
* path: id:integer! Environment ID (from GET /api/environments)
|
||||
* body: {remoteStacksDir:string}
|
||||
* body-example: {"remoteStacksDir":"/mnt/dockhand/stacks"}
|
||||
* resp-200: {success:boolean!, remoteStacksDir:string}
|
||||
* resp-200-example: {"success":true,"remoteStacksDir":"/mnt/dockhand/stacks"}
|
||||
* resp-400: Invalid input — remoteStacksDir must be a string or null, or must be an absolute path with no ".."
|
||||
* resp-403: Permission denied (requires environments:edit)
|
||||
* resp-404: Environment not found
|
||||
*/
|
||||
export const POST: RequestHandler = async ({ params, request, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
if (auth.authEnabled && !(await auth.can('environments', 'edit'))) {
|
||||
|
||||
@@ -5,6 +5,14 @@ import { getDockerInfo, getHawserInfo } from '$lib/server/docker';
|
||||
import { edgeConnections, isEdgeConnected } from '$lib/server/hawser';
|
||||
import { daemonIsPodman } from '$lib/server/scanner-socket-detect';
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* summary: Test connectivity to a saved environment's Docker/Hawser endpoint
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* resp-200: {success:boolean!, info:{serverVersion:string, containers:integer, images:integer, name:string, engine:string}, isEdgeMode:boolean, hawser:{}}
|
||||
* resp-200-desc: success:false with a human-readable error message is also returned as HTTP 200 (connection/agent-not-connected states are not transport errors)
|
||||
* resp-404: Environment not found
|
||||
*/
|
||||
export const POST: RequestHandler = async ({ params }) => {
|
||||
try {
|
||||
const id = parseInt(params.id);
|
||||
|
||||
@@ -38,6 +38,15 @@ function normalizeTimezone(tz: string): string {
|
||||
|
||||
/**
|
||||
* Get timezone for an environment.
|
||||
*
|
||||
* @openapi
|
||||
* summary: Get the IANA timezone used for scheduling on an environment
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* resp-200: {timezone:string!}
|
||||
* resp-200-example: {"timezone":"Europe/Berlin"}
|
||||
* resp-403: Permission denied (RBAC 'environments:view' missing)
|
||||
* resp-404: Environment not found
|
||||
* resp-500: Unexpected error while loading the timezone
|
||||
*/
|
||||
export const GET: RequestHandler = async ({ params, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
@@ -66,6 +75,17 @@ export const GET: RequestHandler = async ({ params, cookies }) => {
|
||||
|
||||
/**
|
||||
* Set timezone for an environment.
|
||||
*
|
||||
* @openapi
|
||||
* summary: Set the IANA timezone for an environment and refresh its schedules to use it
|
||||
* path: id:integer! Environment id (from GET /api/environments)
|
||||
* body: {timezone:string!}
|
||||
* body-example: {"timezone":"Europe/Berlin"}
|
||||
* resp-200: {success:boolean!, timezone:string!}
|
||||
* resp-400: Not a recognized IANA timezone (Intl.supportedValuesOf('timeZone'))
|
||||
* resp-403: Permission denied (RBAC 'environments:edit' missing)
|
||||
* resp-404: Environment not found
|
||||
* resp-500: Unexpected error while saving the timezone
|
||||
*/
|
||||
export const POST: RequestHandler = async ({ params, request, cookies }) => {
|
||||
const auth = await authorize(cookies);
|
||||
|
||||
@@ -11,6 +11,11 @@ interface DetectedSocket {
|
||||
|
||||
/**
|
||||
* Detect available Docker sockets on the system
|
||||
*
|
||||
* @openapi
|
||||
* summary: Detect common Docker/Podman socket paths that exist on the Dockhand host
|
||||
* resp-200: {sockets:array<{path:string!, name:string!, exists:boolean!}>!, homedir:string!}
|
||||
* resp-200-example: {"sockets":[{"path":"/var/run/docker.sock","name":"Docker (default)","exists":true}],"homedir":"/home/dockhand"}
|
||||
*/
|
||||
export const GET: RequestHandler = async () => {
|
||||
const home = homedir();
|
||||
|
||||
@@ -41,6 +41,14 @@ function buildDockerClientConfig(config: TestConnectionRequest): DockerClientCon
|
||||
|
||||
/**
|
||||
* Test Docker connection with provided configuration (without saving to database)
|
||||
*
|
||||
* @openapi
|
||||
* summary: Test a Docker/Hawser connection configuration WITHOUT saving it as an environment
|
||||
* body: {connectionType:string!, socketPath:string, host:string, port:integer, protocol:string, tlsCa:string, tlsCert:string, tlsKey:string, tlsSkipVerify:boolean, hawserToken:string}
|
||||
* body-example: {"connectionType":"socket","socketPath":"/var/run/docker.sock"}
|
||||
* resp-200: {success:boolean!, info:{serverVersion:string, containers:integer, images:integer, name:string}, hawser:{}}
|
||||
* resp-200-desc: success:false with a human-readable error message is also returned as HTTP 200 (connection failures are not transport errors)
|
||||
* resp-400: Host is required for direct/hawser-standard connection types
|
||||
*/
|
||||
export const POST: RequestHandler = async ({ request }) => {
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user