mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-02 07:01:30 -08:00
fix(core): Update isDocker check to return true on kubernetes/containerd (#12603)
This commit is contained in:
parent
7ae1483792
commit
c55dac66ed
|
@ -142,20 +142,31 @@ export class InstanceSettings {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether this instance is running inside a Docker container.
|
* Whether this instance is running inside a Docker/Podman/Kubernetes container.
|
||||||
*
|
|
||||||
* Based on: https://github.com/sindresorhus/is-docker
|
|
||||||
*/
|
*/
|
||||||
@Memoized
|
@Memoized
|
||||||
get isDocker() {
|
get isDocker() {
|
||||||
|
if (existsSync('/.dockerenv') || existsSync('/run/.containerenv')) return true;
|
||||||
try {
|
try {
|
||||||
return (
|
const cgroupV1 = readFileSync('/proc/self/cgroup', 'utf8');
|
||||||
existsSync('/.dockerenv') || readFileSync('/proc/self/cgroup', 'utf8').includes('docker')
|
if (
|
||||||
);
|
cgroupV1.includes('docker') ||
|
||||||
} catch {
|
cgroupV1.includes('kubepods') ||
|
||||||
|
cgroupV1.includes('containerd')
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
} catch {}
|
||||||
|
try {
|
||||||
|
const cgroupV2 = readFileSync('/proc/self/mountinfo', 'utf8');
|
||||||
|
if (
|
||||||
|
cgroupV2.includes('docker') ||
|
||||||
|
cgroupV2.includes('kubelet') ||
|
||||||
|
cgroupV2.includes('containerd')
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
} catch {}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
update(newSettings: WritableSettings) {
|
update(newSettings: WritableSettings) {
|
||||||
this.save({ ...this.settings, ...newSettings });
|
this.save({ ...this.settings, ...newSettings });
|
||||||
|
|
|
@ -214,33 +214,58 @@ describe('InstanceSettings', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return true if /.dockerenv exists', () => {
|
it('should return true if /.dockerenv exists', () => {
|
||||||
mockFs.existsSync.calledWith('/.dockerenv').mockReturnValueOnce(true);
|
mockFs.existsSync.mockImplementation((path) => path === '/.dockerenv');
|
||||||
expect(settings.isDocker).toBe(true);
|
expect(settings.isDocker).toBe(true);
|
||||||
expect(mockFs.existsSync).toHaveBeenCalledWith('/.dockerenv');
|
expect(mockFs.existsSync).toHaveBeenCalledWith('/.dockerenv');
|
||||||
expect(mockFs.readFileSync).not.toHaveBeenCalledWith('/proc/self/cgroup', 'utf8');
|
expect(mockFs.readFileSync).not.toHaveBeenCalledWith('/proc/self/cgroup', 'utf8');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return true if /proc/self/cgroup contains docker', () => {
|
it('should return true if /run/.containerenv exists', () => {
|
||||||
mockFs.existsSync.calledWith('/.dockerenv').mockReturnValueOnce(false);
|
mockFs.existsSync.mockImplementation((path) => path === '/run/.containerenv');
|
||||||
mockFs.readFileSync
|
expect(settings.isDocker).toBe(true);
|
||||||
.calledWith('/proc/self/cgroup', 'utf8')
|
expect(mockFs.existsSync).toHaveBeenCalledWith('/run/.containerenv');
|
||||||
.mockReturnValueOnce('docker cgroup');
|
expect(mockFs.readFileSync).not.toHaveBeenCalledWith('/proc/self/cgroup', 'utf8');
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each(['docker', 'kubepods', 'containerd'])(
|
||||||
|
'should return true if /proc/self/cgroup contains %s',
|
||||||
|
(str) => {
|
||||||
|
mockFs.existsSync.mockReturnValueOnce(false);
|
||||||
|
mockFs.readFileSync.calledWith('/proc/self/cgroup', 'utf8').mockReturnValueOnce(str);
|
||||||
|
|
||||||
expect(settings.isDocker).toBe(true);
|
expect(settings.isDocker).toBe(true);
|
||||||
expect(mockFs.existsSync).toHaveBeenCalledWith('/.dockerenv');
|
expect(mockFs.existsSync).toHaveBeenCalledWith('/.dockerenv');
|
||||||
expect(mockFs.readFileSync).toHaveBeenCalledWith('/proc/self/cgroup', 'utf8');
|
expect(mockFs.readFileSync).toHaveBeenCalledWith('/proc/self/cgroup', 'utf8');
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test.each(['docker', 'kubelet', 'containerd'])(
|
||||||
|
'should return true if /proc/self/mountinfo contains %s',
|
||||||
|
(str) => {
|
||||||
|
mockFs.existsSync.mockReturnValueOnce(false);
|
||||||
|
mockFs.readFileSync.calledWith('/proc/self/cgroup', 'utf8').mockReturnValueOnce('');
|
||||||
|
mockFs.readFileSync.calledWith('/proc/self/mountinfo', 'utf8').mockReturnValueOnce(str);
|
||||||
|
|
||||||
|
expect(settings.isDocker).toBe(true);
|
||||||
|
expect(mockFs.existsSync).toHaveBeenCalledWith('/.dockerenv');
|
||||||
|
expect(mockFs.readFileSync).toHaveBeenCalledWith('/proc/self/cgroup', 'utf8');
|
||||||
|
expect(mockFs.readFileSync).toHaveBeenCalledWith('/proc/self/mountinfo', 'utf8');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
it('should return false if no docker indicators are found', () => {
|
it('should return false if no docker indicators are found', () => {
|
||||||
mockFs.existsSync.calledWith('/.dockerenv').mockReturnValueOnce(false);
|
mockFs.existsSync.calledWith('/.dockerenv').mockReturnValueOnce(false);
|
||||||
mockFs.readFileSync.calledWith('/proc/self/cgroup', 'utf8').mockReturnValueOnce('');
|
mockFs.readFileSync.calledWith('/proc/self/cgroup', 'utf8').mockReturnValueOnce('');
|
||||||
|
mockFs.readFileSync.calledWith('/proc/self/mountinfo', 'utf8').mockReturnValueOnce('');
|
||||||
expect(settings.isDocker).toBe(false);
|
expect(settings.isDocker).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false if checking for docker throws an error', () => {
|
it('should return false if reading any of these files throws an error', () => {
|
||||||
mockFs.existsSync.calledWith('/.dockerenv').mockImplementationOnce(() => {
|
mockFs.existsSync.mockReturnValue(false);
|
||||||
throw new Error('Access denied');
|
mockFs.readFileSync.mockImplementation(() => {
|
||||||
|
throw new Error('File not found');
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(settings.isDocker).toBe(false);
|
expect(settings.isDocker).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue