mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-22 11:04:42 -07:00
feat(cli): add native gVisor (runsc) sandboxing support (#21062)
Co-authored-by: Zheyuan <zlin252@emory.edu> Co-authored-by: Kartik Angiras <angiraskartik@gmail.com>
This commit is contained in:
@@ -97,7 +97,7 @@ describe('loadSandboxConfig', () => {
|
||||
it('should throw if GEMINI_SANDBOX is an invalid command', async () => {
|
||||
process.env['GEMINI_SANDBOX'] = 'invalid-command';
|
||||
await expect(loadSandboxConfig({}, {})).rejects.toThrow(
|
||||
"Invalid sandbox command 'invalid-command'. Must be one of docker, podman, sandbox-exec, lxc",
|
||||
"Invalid sandbox command 'invalid-command'. Must be one of docker, podman, sandbox-exec, runsc, lxc",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -194,7 +194,7 @@ describe('loadSandboxConfig', () => {
|
||||
await expect(
|
||||
loadSandboxConfig({}, { sandbox: 'invalid-command' }),
|
||||
).rejects.toThrow(
|
||||
"Invalid sandbox command 'invalid-command'. Must be one of docker, podman, sandbox-exec",
|
||||
"Invalid sandbox command 'invalid-command'. Must be one of docker, podman, sandbox-exec, runsc, lxc",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -247,4 +247,92 @@ describe('loadSandboxConfig', () => {
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('with sandbox: runsc (gVisor)', () => {
|
||||
beforeEach(() => {
|
||||
mockedOsPlatform.mockReturnValue('linux');
|
||||
mockedCommandExistsSync.mockReturnValue(true);
|
||||
});
|
||||
|
||||
it('should use runsc via CLI argument on Linux', async () => {
|
||||
const config = await loadSandboxConfig({}, { sandbox: 'runsc' });
|
||||
|
||||
expect(config).toEqual({ command: 'runsc', image: 'default/image' });
|
||||
expect(mockedCommandExistsSync).toHaveBeenCalledWith('runsc');
|
||||
expect(mockedCommandExistsSync).toHaveBeenCalledWith('docker');
|
||||
});
|
||||
|
||||
it('should use runsc via GEMINI_SANDBOX environment variable', async () => {
|
||||
process.env['GEMINI_SANDBOX'] = 'runsc';
|
||||
const config = await loadSandboxConfig({}, {});
|
||||
|
||||
expect(config).toEqual({ command: 'runsc', image: 'default/image' });
|
||||
expect(mockedCommandExistsSync).toHaveBeenCalledWith('runsc');
|
||||
expect(mockedCommandExistsSync).toHaveBeenCalledWith('docker');
|
||||
});
|
||||
|
||||
it('should use runsc via settings file', async () => {
|
||||
const config = await loadSandboxConfig(
|
||||
{ tools: { sandbox: 'runsc' } },
|
||||
{},
|
||||
);
|
||||
|
||||
expect(config).toEqual({ command: 'runsc', image: 'default/image' });
|
||||
expect(mockedCommandExistsSync).toHaveBeenCalledWith('runsc');
|
||||
expect(mockedCommandExistsSync).toHaveBeenCalledWith('docker');
|
||||
});
|
||||
|
||||
it('should prioritize GEMINI_SANDBOX over CLI and settings', async () => {
|
||||
process.env['GEMINI_SANDBOX'] = 'runsc';
|
||||
const config = await loadSandboxConfig(
|
||||
{ tools: { sandbox: 'docker' } },
|
||||
{ sandbox: 'podman' },
|
||||
);
|
||||
|
||||
expect(config).toEqual({ command: 'runsc', image: 'default/image' });
|
||||
});
|
||||
|
||||
it('should reject runsc on macOS (Linux-only)', async () => {
|
||||
mockedOsPlatform.mockReturnValue('darwin');
|
||||
|
||||
await expect(loadSandboxConfig({}, { sandbox: 'runsc' })).rejects.toThrow(
|
||||
'gVisor (runsc) sandboxing is only supported on Linux',
|
||||
);
|
||||
});
|
||||
|
||||
it('should reject runsc on Windows (Linux-only)', async () => {
|
||||
mockedOsPlatform.mockReturnValue('win32');
|
||||
|
||||
await expect(loadSandboxConfig({}, { sandbox: 'runsc' })).rejects.toThrow(
|
||||
'gVisor (runsc) sandboxing is only supported on Linux',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw if runsc binary not found', async () => {
|
||||
mockedCommandExistsSync.mockReturnValue(false);
|
||||
|
||||
await expect(loadSandboxConfig({}, { sandbox: 'runsc' })).rejects.toThrow(
|
||||
"Missing sandbox command 'runsc' (from GEMINI_SANDBOX)",
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw if Docker not available (runsc requires Docker)', async () => {
|
||||
mockedCommandExistsSync.mockImplementation((cmd) => cmd === 'runsc');
|
||||
|
||||
await expect(loadSandboxConfig({}, { sandbox: 'runsc' })).rejects.toThrow(
|
||||
"runsc (gVisor) requires Docker. Install Docker, or use sandbox: 'docker'.",
|
||||
);
|
||||
});
|
||||
|
||||
it('should NOT auto-detect runsc when both runsc and docker available', async () => {
|
||||
mockedCommandExistsSync.mockImplementation(
|
||||
(cmd) => cmd === 'runsc' || cmd === 'docker',
|
||||
);
|
||||
|
||||
const config = await loadSandboxConfig({}, { sandbox: true });
|
||||
|
||||
expect(config?.command).toBe('docker');
|
||||
expect(config?.command).not.toBe('runsc');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user