mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-21 11:49:59 +00:00
feat(core): Use hostname in host ID for Docker (#16544)
This commit is contained in:
@@ -9,7 +9,6 @@ import { WorkerMissingEncryptionKey } from '../worker-missing-encryption-key.err
|
|||||||
|
|
||||||
describe('InstanceSettings', () => {
|
describe('InstanceSettings', () => {
|
||||||
const userFolder = '/test';
|
const userFolder = '/test';
|
||||||
const settingsFile = `${userFolder}/.n8n/config`;
|
|
||||||
|
|
||||||
const mockFs = mock(fs);
|
const mockFs = mock(fs);
|
||||||
const logger = mock<Logger>();
|
const logger = mock<Logger>();
|
||||||
@@ -202,25 +201,16 @@ describe('InstanceSettings', () => {
|
|||||||
|
|
||||||
const settings = createInstanceSettings();
|
const settings = createInstanceSettings();
|
||||||
|
|
||||||
const [instanceType, nanoid] = settings.hostId.split('-');
|
const [instanceType, hostId] = settings.hostId.split('-');
|
||||||
expect(instanceType).toEqual('main');
|
expect(instanceType).toEqual('main');
|
||||||
expect(nanoid).toHaveLength(16); // e.g. sDX6ZPc0bozv66zM
|
expect(hostId.length).toBeGreaterThan(0); // hostname or nanoID
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('isDocker', () => {
|
describe('isDocker', () => {
|
||||||
let settings: InstanceSettings;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
mockFs.existsSync.calledWith(settingsFile).mockReturnValue(true);
|
|
||||||
mockFs.readFileSync
|
|
||||||
.calledWith(settingsFile)
|
|
||||||
.mockReturnValue(JSON.stringify({ encryptionKey: 'test_key' }));
|
|
||||||
settings = createInstanceSettings();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return true if /.dockerenv exists', () => {
|
it('should return true if /.dockerenv exists', () => {
|
||||||
mockFs.existsSync.mockImplementation((path) => path === '/.dockerenv');
|
mockFs.existsSync.mockImplementation((path) => path === '/.dockerenv');
|
||||||
|
const settings = createInstanceSettings();
|
||||||
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');
|
||||||
@@ -228,6 +218,7 @@ describe('InstanceSettings', () => {
|
|||||||
|
|
||||||
it('should return true if /run/.containerenv exists', () => {
|
it('should return true if /run/.containerenv exists', () => {
|
||||||
mockFs.existsSync.mockImplementation((path) => path === '/run/.containerenv');
|
mockFs.existsSync.mockImplementation((path) => path === '/run/.containerenv');
|
||||||
|
const settings = createInstanceSettings();
|
||||||
expect(settings.isDocker).toBe(true);
|
expect(settings.isDocker).toBe(true);
|
||||||
expect(mockFs.existsSync).toHaveBeenCalledWith('/run/.containerenv');
|
expect(mockFs.existsSync).toHaveBeenCalledWith('/run/.containerenv');
|
||||||
expect(mockFs.readFileSync).not.toHaveBeenCalledWith('/proc/self/cgroup', 'utf8');
|
expect(mockFs.readFileSync).not.toHaveBeenCalledWith('/proc/self/cgroup', 'utf8');
|
||||||
@@ -239,6 +230,7 @@ describe('InstanceSettings', () => {
|
|||||||
mockFs.existsSync.mockReturnValueOnce(false);
|
mockFs.existsSync.mockReturnValueOnce(false);
|
||||||
mockFs.readFileSync.calledWith('/proc/self/cgroup', 'utf8').mockReturnValueOnce(str);
|
mockFs.readFileSync.calledWith('/proc/self/cgroup', 'utf8').mockReturnValueOnce(str);
|
||||||
|
|
||||||
|
const settings = createInstanceSettings();
|
||||||
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');
|
||||||
@@ -252,6 +244,7 @@ describe('InstanceSettings', () => {
|
|||||||
mockFs.readFileSync.calledWith('/proc/self/cgroup', 'utf8').mockReturnValueOnce('');
|
mockFs.readFileSync.calledWith('/proc/self/cgroup', 'utf8').mockReturnValueOnce('');
|
||||||
mockFs.readFileSync.calledWith('/proc/self/mountinfo', 'utf8').mockReturnValueOnce(str);
|
mockFs.readFileSync.calledWith('/proc/self/mountinfo', 'utf8').mockReturnValueOnce(str);
|
||||||
|
|
||||||
|
const settings = createInstanceSettings();
|
||||||
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');
|
||||||
@@ -263,6 +256,7 @@ describe('InstanceSettings', () => {
|
|||||||
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('');
|
mockFs.readFileSync.calledWith('/proc/self/mountinfo', 'utf8').mockReturnValueOnce('');
|
||||||
|
const settings = createInstanceSettings();
|
||||||
expect(settings.isDocker).toBe(false);
|
expect(settings.isDocker).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -272,12 +266,14 @@ describe('InstanceSettings', () => {
|
|||||||
throw new Error('File not found');
|
throw new Error('File not found');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const settings = createInstanceSettings();
|
||||||
expect(settings.isDocker).toBe(false);
|
expect(settings.isDocker).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should cache the result of isDocker check', () => {
|
it('should cache the result of isDocker check', () => {
|
||||||
mockFs.existsSync.calledWith('/.dockerenv').mockReturnValueOnce(true);
|
mockFs.existsSync.calledWith('/.dockerenv').mockReturnValueOnce(true);
|
||||||
|
|
||||||
|
const settings = createInstanceSettings();
|
||||||
expect(settings.isDocker).toBe(true);
|
expect(settings.isDocker).toBe(true);
|
||||||
|
|
||||||
mockFs.existsSync.mockClear();
|
mockFs.existsSync.mockClear();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { createHash, randomBytes } from 'crypto';
|
|||||||
import { ApplicationError, jsonParse, ALPHABET, toResult } from 'n8n-workflow';
|
import { ApplicationError, jsonParse, ALPHABET, toResult } from 'n8n-workflow';
|
||||||
import { customAlphabet } from 'nanoid';
|
import { customAlphabet } from 'nanoid';
|
||||||
import { chmodSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
import { chmodSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
||||||
|
import os from 'node:os';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
import { WorkerMissingEncryptionKey } from './worker-missing-encryption-key.error';
|
import { WorkerMissingEncryptionKey } from './worker-missing-encryption-key.error';
|
||||||
@@ -60,7 +61,7 @@ export class InstanceSettings {
|
|||||||
const command = process.argv[2] as InstanceType;
|
const command = process.argv[2] as InstanceType;
|
||||||
this.instanceType = ['webhook', 'worker'].includes(command) ? command : 'main';
|
this.instanceType = ['webhook', 'worker'].includes(command) ? command : 'main';
|
||||||
|
|
||||||
this.hostId = `${this.instanceType}-${nanoid()}`;
|
this.hostId = `${this.instanceType}-${this.isDocker ? os.hostname() : nanoid()}`;
|
||||||
this.settings = this.loadOrCreate();
|
this.settings = this.loadOrCreate();
|
||||||
this.instanceId = this.generateInstanceId();
|
this.instanceId = this.generateInstanceId();
|
||||||
}
|
}
|
||||||
@@ -76,12 +77,11 @@ export class InstanceSettings {
|
|||||||
instanceRole: InstanceRole = 'unset';
|
instanceRole: InstanceRole = 'unset';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transient ID of this n8n instance, for scaling mode.
|
* ID of this n8n instance. Hostname-based when in Docker, or nanoID-based
|
||||||
* Reset on restart. Do not confuse with `instanceId`.
|
* otherwise (resets on restart). Do not confuse with `instanceId`.
|
||||||
*
|
*
|
||||||
* @example 'main-bnxa1riryKUNHtln'
|
* @example 'main-bnxa1riryKUNHtln' (local)
|
||||||
* @example 'worker-nDJR0FnSd2Vf6DB5'
|
* @example 'main-6bf523178bc6' (Docker)
|
||||||
* @example 'webhook-jxQ7AO8IzxEtfW1F'
|
|
||||||
*/
|
*/
|
||||||
readonly hostId: string;
|
readonly hostId: string;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user