mirror of
https://github.com/nicotsx/ironmount.git
synced 2025-12-10 12:10:51 +01:00
feat: host/proc optional capability
This commit is contained in:
@@ -4,6 +4,7 @@ import { logger } from "../utils/logger";
|
||||
|
||||
export type SystemCapabilities = {
|
||||
docker: boolean;
|
||||
hostProc: boolean;
|
||||
};
|
||||
|
||||
let capabilitiesPromise: Promise<SystemCapabilities> | null = null;
|
||||
@@ -28,6 +29,7 @@ export async function getCapabilities(): Promise<SystemCapabilities> {
|
||||
async function detectCapabilities(): Promise<SystemCapabilities> {
|
||||
return {
|
||||
docker: await detectDocker(),
|
||||
hostProc: await detectHostProc(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -53,3 +55,23 @@ async function detectDocker(): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if host proc is available by attempting to access /host/proc/1/ns/mnt
|
||||
* This allows using nsenter to execute mount commands in the host namespace
|
||||
*/
|
||||
async function detectHostProc(): Promise<boolean> {
|
||||
try {
|
||||
await fs.access("/host/proc/1/ns/mnt");
|
||||
|
||||
logger.info("Host proc capability: enabled");
|
||||
return true;
|
||||
} catch (_) {
|
||||
logger.warn(
|
||||
"Host proc capability: disabled. " +
|
||||
"To enable: mount /proc:/host/proc:ro in docker-compose.yml. " +
|
||||
"Mounts will be executed in container namespace instead of host namespace.",
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,24 +2,24 @@ import { execFile as execFileCb } from "node:child_process";
|
||||
import * as fs from "node:fs/promises";
|
||||
import * as npath from "node:path";
|
||||
import { promisify } from "node:util";
|
||||
import { getCapabilities } from "../../../core/capabilities";
|
||||
import { OPERATION_TIMEOUT } from "../../../core/constants";
|
||||
import { toMessage } from "../../../utils/errors";
|
||||
import { logger } from "../../../utils/logger";
|
||||
import { access, constants } from "node:fs/promises";
|
||||
|
||||
const execFile = promisify(execFileCb);
|
||||
|
||||
export const executeMount = async (args: string[]): Promise<void> => {
|
||||
const capabilities = await getCapabilities();
|
||||
let stderr: string | undefined;
|
||||
|
||||
try {
|
||||
await access("/host/proc", constants.F_OK);
|
||||
if (capabilities.hostProc) {
|
||||
const result = await execFile("nsenter", ["--mount=/host/proc/1/ns/mnt", "mount", ...args], {
|
||||
timeout: OPERATION_TIMEOUT,
|
||||
maxBuffer: 1024 * 1024,
|
||||
});
|
||||
stderr = result.stderr;
|
||||
} catch (_) {
|
||||
} else {
|
||||
const result = await execFile("mount", args, {
|
||||
timeout: OPERATION_TIMEOUT,
|
||||
maxBuffer: 1024 * 1024,
|
||||
@@ -33,16 +33,16 @@ export const executeMount = async (args: string[]): Promise<void> => {
|
||||
};
|
||||
|
||||
export const executeUnmount = async (path: string): Promise<void> => {
|
||||
const capabilities = await getCapabilities();
|
||||
let stderr: string | undefined;
|
||||
|
||||
try {
|
||||
await access("/host/proc", constants.F_OK);
|
||||
if (capabilities.hostProc) {
|
||||
const result = await execFile("nsenter", ["--mount=/host/proc/1/ns/mnt", "umount", "-l", "-f", path], {
|
||||
timeout: OPERATION_TIMEOUT,
|
||||
maxBuffer: 1024 * 1024,
|
||||
});
|
||||
stderr = result.stderr;
|
||||
} catch (_) {
|
||||
} else {
|
||||
const result = await execFile("umount", ["-l", "-f", path], {
|
||||
timeout: OPERATION_TIMEOUT,
|
||||
maxBuffer: 1024 * 1024,
|
||||
|
||||
Reference in New Issue
Block a user