mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
refactor(core): Convert external-secrets code into a backend module (#15769)
This commit is contained in:
committed by
GitHub
parent
10dc73fc82
commit
1587eb0742
@@ -11,7 +11,6 @@ import {
|
|||||||
ObjectStoreService,
|
ObjectStoreService,
|
||||||
DataDeduplicationService,
|
DataDeduplicationService,
|
||||||
ErrorReporter,
|
ErrorReporter,
|
||||||
ExternalSecretsProxy,
|
|
||||||
} from 'n8n-core';
|
} from 'n8n-core';
|
||||||
import { ensureError, sleep, UserError } from 'n8n-workflow';
|
import { ensureError, sleep, UserError } from 'n8n-workflow';
|
||||||
|
|
||||||
@@ -26,7 +25,6 @@ import { TestRunCleanupService } from '@/evaluation.ee/test-runner/test-run-clea
|
|||||||
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
||||||
import { TelemetryEventRelay } from '@/events/relays/telemetry.event-relay';
|
import { TelemetryEventRelay } from '@/events/relays/telemetry.event-relay';
|
||||||
import { ExternalHooks } from '@/external-hooks';
|
import { ExternalHooks } from '@/external-hooks';
|
||||||
import { ExternalSecretsManager } from '@/external-secrets.ee/external-secrets-manager.ee';
|
|
||||||
import { License } from '@/license';
|
import { License } from '@/license';
|
||||||
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
||||||
import { ModuleRegistry } from '@/modules/module-registry';
|
import { ModuleRegistry } from '@/modules/module-registry';
|
||||||
@@ -88,7 +86,6 @@ export abstract class BaseCommand extends Command {
|
|||||||
instance: this.instanceSettings,
|
instance: this.instanceSettings,
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
// register module in the registry for the dependency injection
|
|
||||||
await import(`../modules/${moduleName}/${moduleName}.module`);
|
await import(`../modules/${moduleName}/${moduleName}.module`);
|
||||||
|
|
||||||
this.modulesConfig.addLoadedModule(moduleName);
|
this.modulesConfig.addLoadedModule(moduleName);
|
||||||
@@ -276,12 +273,6 @@ export abstract class BaseCommand extends Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async initExternalSecrets() {
|
|
||||||
const secretsManager = Container.get(ExternalSecretsManager);
|
|
||||||
await secretsManager.init();
|
|
||||||
Container.get(ExternalSecretsProxy).setManager(secretsManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
initWorkflowHistory() {
|
initWorkflowHistory() {
|
||||||
Container.get(WorkflowHistoryManager).init();
|
Container.get(WorkflowHistoryManager).init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,8 +232,6 @@ export class Start extends BaseCommand {
|
|||||||
this.logger.debug('Data deduplication service init complete');
|
this.logger.debug('Data deduplication service init complete');
|
||||||
await this.initExternalHooks();
|
await this.initExternalHooks();
|
||||||
this.logger.debug('External hooks init complete');
|
this.logger.debug('External hooks init complete');
|
||||||
await this.initExternalSecrets();
|
|
||||||
this.logger.debug('External secrets init complete');
|
|
||||||
this.initWorkflowHistory();
|
this.initWorkflowHistory();
|
||||||
this.logger.debug('Workflow history init complete');
|
this.logger.debug('Workflow history init complete');
|
||||||
|
|
||||||
|
|||||||
@@ -77,8 +77,6 @@ export class Webhook extends BaseCommand {
|
|||||||
this.logger.debug('Data deduplication service init complete');
|
this.logger.debug('Data deduplication service init complete');
|
||||||
await this.initExternalHooks();
|
await this.initExternalHooks();
|
||||||
this.logger.debug('External hooks init complete');
|
this.logger.debug('External hooks init complete');
|
||||||
await this.initExternalSecrets();
|
|
||||||
this.logger.debug('External secrets init complete');
|
|
||||||
|
|
||||||
await this.loadModules();
|
await this.loadModules();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,8 +94,6 @@ export class Worker extends BaseCommand {
|
|||||||
this.logger.debug('Data deduplication service init complete');
|
this.logger.debug('Data deduplication service init complete');
|
||||||
await this.initExternalHooks();
|
await this.initExternalHooks();
|
||||||
this.logger.debug('External hooks init complete');
|
this.logger.debug('External hooks init complete');
|
||||||
await this.initExternalSecrets();
|
|
||||||
this.logger.debug('External secrets init complete');
|
|
||||||
await this.initEventBus();
|
await this.initEventBus();
|
||||||
this.logger.debug('Event bus init complete');
|
this.logger.debug('Event bus init complete');
|
||||||
await this.initScalingService();
|
await this.initScalingService();
|
||||||
|
|||||||
@@ -12,19 +12,19 @@ describe('ModulesConfig', () => {
|
|||||||
|
|
||||||
it('should initialize with insights modules if no environment variable is set', () => {
|
it('should initialize with insights modules if no environment variable is set', () => {
|
||||||
const config = Container.get(ModulesConfig);
|
const config = Container.get(ModulesConfig);
|
||||||
expect(config.modules).toEqual(['insights']);
|
expect(config.modules).toEqual(['insights', 'external-secrets.ee']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should parse valid module names from environment variable', () => {
|
it('should parse valid module names from environment variable', () => {
|
||||||
process.env.N8N_ENABLED_MODULES = 'insights';
|
process.env.N8N_ENABLED_MODULES = 'insights';
|
||||||
const config = Container.get(ModulesConfig);
|
const config = Container.get(ModulesConfig);
|
||||||
expect(config.modules).toEqual(['insights']);
|
expect(config.modules).toEqual(['insights', 'external-secrets.ee']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should disable valid module names from environment variable', () => {
|
it('should disable valid module names from environment variable', () => {
|
||||||
process.env.N8N_DISABLED_MODULES = 'insights';
|
process.env.N8N_DISABLED_MODULES = 'insights';
|
||||||
const config = Container.get(ModulesConfig);
|
const config = Container.get(ModulesConfig);
|
||||||
expect(config.modules).toEqual([]);
|
expect(config.modules).toEqual(['external-secrets.ee']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw UnexpectedError for invalid module names', () => {
|
it('should throw UnexpectedError for invalid module names', () => {
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import type { BaseN8nModule } from '@n8n/decorators';
|
||||||
|
import { N8nModule } from '@n8n/decorators';
|
||||||
|
import { ExternalSecretsProxy } from 'n8n-core';
|
||||||
|
|
||||||
|
import { ExternalSecretsManager } from './external-secrets-manager.ee';
|
||||||
|
import './external-secrets.controller.ee';
|
||||||
|
|
||||||
|
@N8nModule()
|
||||||
|
export class ExternalSecretsModule implements BaseN8nModule {
|
||||||
|
constructor(
|
||||||
|
private readonly manager: ExternalSecretsManager,
|
||||||
|
private readonly externalSecretsProxy: ExternalSecretsProxy,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async initialize() {
|
||||||
|
const { externalSecretsProxy, manager } = this;
|
||||||
|
await manager.init();
|
||||||
|
externalSecretsProxy.setManager(manager);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ export type ModulePreInit = {
|
|||||||
shouldLoadModule: (ctx: ModulePreInitContext) => boolean;
|
shouldLoadModule: (ctx: ModulePreInitContext) => boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const moduleNames = ['insights'] as const;
|
const moduleNames = ['insights', 'external-secrets.ee'] as const;
|
||||||
export type ModuleName = (typeof moduleNames)[number];
|
export type ModuleName = (typeof moduleNames)[number];
|
||||||
|
|
||||||
class Modules extends CommaSeparatedStringArray<ModuleName> {
|
class Modules extends CommaSeparatedStringArray<ModuleName> {
|
||||||
@@ -36,7 +36,7 @@ export class ModulesConfig {
|
|||||||
disabledModules: Modules = [];
|
disabledModules: Modules = [];
|
||||||
|
|
||||||
// Default modules are always enabled unless explicitly disabled
|
// Default modules are always enabled unless explicitly disabled
|
||||||
private readonly defaultModules: ModuleName[] = ['insights'];
|
private readonly defaultModules: ModuleName[] = ['insights', 'external-secrets.ee'];
|
||||||
|
|
||||||
// Loaded modules are the ones that have been loaded so far by the instance
|
// Loaded modules are the ones that have been loaded so far by the instance
|
||||||
readonly loadedModules = new Set<ModuleName>();
|
readonly loadedModules = new Set<ModuleName>();
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ import '@/credentials/credentials.controller';
|
|||||||
import '@/eventbus/event-bus.controller';
|
import '@/eventbus/event-bus.controller';
|
||||||
import '@/events/events.controller';
|
import '@/events/events.controller';
|
||||||
import '@/executions/executions.controller';
|
import '@/executions/executions.controller';
|
||||||
import '@/external-secrets.ee/external-secrets.controller.ee';
|
|
||||||
import '@/license/license.controller';
|
import '@/license/license.controller';
|
||||||
import '@/evaluation.ee/test-runs.controller.ee';
|
import '@/evaluation.ee/test-runs.controller.ee';
|
||||||
import '@/workflows/workflow-history.ee/workflow-history.controller.ee';
|
import '@/workflows/workflow-history.ee/workflow-history.controller.ee';
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import config from '@/config';
|
|||||||
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
||||||
import { LogStreamingEventRelay } from '@/events/relays/log-streaming.event-relay';
|
import { LogStreamingEventRelay } from '@/events/relays/log-streaming.event-relay';
|
||||||
import { ExternalHooks } from '@/external-hooks';
|
import { ExternalHooks } from '@/external-hooks';
|
||||||
import { ExternalSecretsManager } from '@/external-secrets.ee/external-secrets-manager.ee';
|
|
||||||
import { License } from '@/license';
|
import { License } from '@/license';
|
||||||
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
||||||
import { Push } from '@/push';
|
import { Push } from '@/push';
|
||||||
@@ -31,7 +30,6 @@ mockInstance(LoadNodesAndCredentials);
|
|||||||
const binaryDataService = mockInstance(BinaryDataService);
|
const binaryDataService = mockInstance(BinaryDataService);
|
||||||
const communityPackagesService = mockInstance(CommunityPackagesService);
|
const communityPackagesService = mockInstance(CommunityPackagesService);
|
||||||
const externalHooks = mockInstance(ExternalHooks);
|
const externalHooks = mockInstance(ExternalHooks);
|
||||||
const externalSecretsManager = mockInstance(ExternalSecretsManager);
|
|
||||||
const license = mockInstance(License, { loadCertStr: async () => '' });
|
const license = mockInstance(License, { loadCertStr: async () => '' });
|
||||||
const messageEventBus = mockInstance(MessageEventBus);
|
const messageEventBus = mockInstance(MessageEventBus);
|
||||||
const logStreamingEventRelay = mockInstance(LogStreamingEventRelay);
|
const logStreamingEventRelay = mockInstance(LogStreamingEventRelay);
|
||||||
@@ -54,7 +52,6 @@ test('worker initializes all its components', async () => {
|
|||||||
expect(binaryDataService.init).toHaveBeenCalledTimes(1);
|
expect(binaryDataService.init).toHaveBeenCalledTimes(1);
|
||||||
expect(communityPackagesService.init).toHaveBeenCalledTimes(1);
|
expect(communityPackagesService.init).toHaveBeenCalledTimes(1);
|
||||||
expect(externalHooks.init).toHaveBeenCalledTimes(1);
|
expect(externalHooks.init).toHaveBeenCalledTimes(1);
|
||||||
expect(externalSecretsManager.init).toHaveBeenCalledTimes(1);
|
|
||||||
expect(messageEventBus.initialize).toHaveBeenCalledTimes(1);
|
expect(messageEventBus.initialize).toHaveBeenCalledTimes(1);
|
||||||
expect(scalingService.setupQueue).toHaveBeenCalledTimes(1);
|
expect(scalingService.setupQueue).toHaveBeenCalledTimes(1);
|
||||||
expect(scalingService.setupWorker).toHaveBeenCalledTimes(1);
|
expect(scalingService.setupWorker).toHaveBeenCalledTimes(1);
|
||||||
|
|||||||
@@ -7,10 +7,13 @@ import type { IDataObject } from 'n8n-workflow';
|
|||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { CREDENTIAL_BLANKING_VALUE } from '@/constants';
|
import { CREDENTIAL_BLANKING_VALUE } from '@/constants';
|
||||||
import type { EventService } from '@/events/event.service';
|
import type { EventService } from '@/events/event.service';
|
||||||
import { ExternalSecretsManager } from '@/external-secrets.ee/external-secrets-manager.ee';
|
|
||||||
import { ExternalSecretsProviders } from '@/external-secrets.ee/external-secrets-providers.ee';
|
|
||||||
import type { ExternalSecretsSettings, SecretsProviderState } from '@/external-secrets.ee/types';
|
|
||||||
import { License } from '@/license';
|
import { License } from '@/license';
|
||||||
|
import { ExternalSecretsManager } from '@/modules/external-secrets.ee/external-secrets-manager.ee';
|
||||||
|
import { ExternalSecretsProviders } from '@/modules/external-secrets.ee/external-secrets-providers.ee';
|
||||||
|
import type {
|
||||||
|
ExternalSecretsSettings,
|
||||||
|
SecretsProviderState,
|
||||||
|
} from '@/modules/external-secrets.ee/types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DummyProvider,
|
DummyProvider,
|
||||||
|
|||||||
@@ -250,10 +250,6 @@ export const setupTestServer = ({
|
|||||||
await import('@/controllers/tags.controller');
|
await import('@/controllers/tags.controller');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'externalSecrets':
|
|
||||||
await import('@/external-secrets.ee/external-secrets.controller.ee');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'workflowHistory':
|
case 'workflowHistory':
|
||||||
await import('@/workflows/workflow-history.ee/workflow-history.controller.ee');
|
await import('@/workflows/workflow-history.ee/workflow-history.controller.ee');
|
||||||
break;
|
break;
|
||||||
@@ -292,8 +288,11 @@ export const setupTestServer = ({
|
|||||||
case 'folder':
|
case 'folder':
|
||||||
await import('@/controllers/folder.controller');
|
await import('@/controllers/folder.controller');
|
||||||
|
|
||||||
|
case 'externalSecrets':
|
||||||
|
await import('@/modules/external-secrets.ee/external-secrets.ee.module');
|
||||||
|
|
||||||
case 'insights':
|
case 'insights':
|
||||||
await import('@/modules/insights/insights.controller');
|
await import('@/modules/insights/insights.module');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import type { IDataObject, INodeProperties } from 'n8n-workflow';
|
import type { IDataObject, INodeProperties } from 'n8n-workflow';
|
||||||
|
|
||||||
import { SecretsProvider } from '@/external-secrets.ee/types';
|
import { SecretsProvider } from '@/modules/external-secrets.ee/types';
|
||||||
import type { SecretsProviderSettings, SecretsProviderState } from '@/external-secrets.ee/types';
|
import type {
|
||||||
|
SecretsProviderSettings,
|
||||||
|
SecretsProviderState,
|
||||||
|
} from '@/modules/external-secrets.ee/types';
|
||||||
|
|
||||||
export class MockProviders {
|
export class MockProviders {
|
||||||
providers: Record<string, { new (): SecretsProvider }> = {
|
providers: Record<string, { new (): SecretsProvider }> = {
|
||||||
|
|||||||
Reference in New Issue
Block a user