mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
feat: file import (#7219)
This commit is contained in:
parent
6340ecd6bf
commit
80ba3647a6
@ -164,9 +164,9 @@ exports[`should create default config 1`] = `
|
||||
],
|
||||
"getLogger": [Function],
|
||||
"import": {
|
||||
"dropBeforeImport": false,
|
||||
"environment": "development",
|
||||
"file": undefined,
|
||||
"keepExisting": false,
|
||||
"project": "default",
|
||||
},
|
||||
"inlineSegmentConstraints": true,
|
||||
"isEnterprise": false,
|
||||
|
@ -333,11 +333,8 @@ const defaultAuthentication: IAuthOption = {
|
||||
|
||||
const defaultImport: WithOptional<IImportOption, 'file'> = {
|
||||
file: process.env.IMPORT_FILE,
|
||||
dropBeforeImport: parseEnvVarBoolean(
|
||||
process.env.IMPORT_DROP_BEFORE_IMPORT,
|
||||
false,
|
||||
),
|
||||
keepExisting: parseEnvVarBoolean(process.env.IMPORT_KEEP_EXISTING, false),
|
||||
project: process.env.IMPORT_PROJECT ?? 'default',
|
||||
environment: process.env.IMPORT_ENVIRONMENT ?? 'development',
|
||||
};
|
||||
|
||||
const defaultEmail: IEmailOption = {
|
||||
|
@ -5,6 +5,8 @@ import type { IFeatureStrategiesStore } from '../feature-toggle/types/feature-to
|
||||
import {
|
||||
FeaturesExportedEvent,
|
||||
FeaturesImportedEvent,
|
||||
SYSTEM_USER,
|
||||
SYSTEM_USER_AUDIT,
|
||||
type FeatureToggleDTO,
|
||||
type IAuditUser,
|
||||
type IContextFieldStore,
|
||||
@ -55,6 +57,7 @@ import type { IDependentFeaturesReadModel } from '../dependent-features/dependen
|
||||
import groupBy from 'lodash.groupby';
|
||||
import { allSettledWithRejection } from '../../util/allSettledWithRejection';
|
||||
import type { ISegmentReadModel } from '../segment/segment-read-model-type';
|
||||
import { readFile } from './import-file-reader';
|
||||
|
||||
export type IImportService = {
|
||||
validate(
|
||||
@ -67,6 +70,12 @@ export type IImportService = {
|
||||
user: IUser,
|
||||
auditUser: IAuditUser,
|
||||
): Promise<void>;
|
||||
|
||||
importFromFile(
|
||||
file: string,
|
||||
project: string,
|
||||
environment: string,
|
||||
): Promise<void>;
|
||||
};
|
||||
|
||||
export type IExportService = {
|
||||
@ -264,6 +273,16 @@ export default class ExportImportService
|
||||
]);
|
||||
}
|
||||
|
||||
async fileImportVerify(dto: ImportTogglesSchema): Promise<void> {
|
||||
await allSettledWithRejection([
|
||||
this.verifyStrategies(dto),
|
||||
this.verifyContextFields(dto),
|
||||
this.verifyFeatures(dto),
|
||||
this.verifySegments(dto),
|
||||
this.verifyDependencies(dto),
|
||||
]);
|
||||
}
|
||||
|
||||
async importFeatureData(
|
||||
dto: ImportTogglesSchema,
|
||||
auditUser: IAuditUser,
|
||||
@ -281,16 +300,40 @@ export default class ExportImportService
|
||||
auditUser: IAuditUser,
|
||||
): Promise<void> {
|
||||
const cleanedDto = await this.cleanData(dto);
|
||||
|
||||
await this.importVerify(cleanedDto, user);
|
||||
await this.processImport(cleanedDto, user, auditUser);
|
||||
}
|
||||
|
||||
await this.importFeatureData(cleanedDto, auditUser);
|
||||
async importFromFile(
|
||||
file: string,
|
||||
project: string,
|
||||
environment: string,
|
||||
): Promise<void> {
|
||||
const content = await readFile(file);
|
||||
const data = JSON.parse(content);
|
||||
const dto = {
|
||||
project,
|
||||
environment,
|
||||
data,
|
||||
};
|
||||
const cleanedDto = await this.cleanData(dto);
|
||||
|
||||
await this.importEnvironmentData(cleanedDto, user, auditUser);
|
||||
await this.fileImportVerify(cleanedDto);
|
||||
await this.processImport(cleanedDto, SYSTEM_USER, SYSTEM_USER_AUDIT);
|
||||
}
|
||||
|
||||
private async processImport(
|
||||
dto: ImportTogglesSchema,
|
||||
user: IUser,
|
||||
auditUser: IAuditUser,
|
||||
) {
|
||||
await this.importFeatureData(dto, auditUser);
|
||||
|
||||
await this.importEnvironmentData(dto, user, auditUser);
|
||||
await this.eventService.storeEvent(
|
||||
new FeaturesImportedEvent({
|
||||
project: cleanedDto.project,
|
||||
environment: cleanedDto.environment,
|
||||
project: dto.project,
|
||||
environment: dto.environment,
|
||||
auditUser,
|
||||
}),
|
||||
);
|
||||
|
@ -0,0 +1,8 @@
|
||||
import * as fs from 'fs';
|
||||
|
||||
export const readFile: (file: string) => Promise<string> = async (file) =>
|
||||
new Promise((resolve, reject) =>
|
||||
fs.readFile(file, (err, v) =>
|
||||
err ? reject(err) : resolve(v.toString('utf-8')),
|
||||
),
|
||||
);
|
@ -97,7 +97,11 @@ async function createApp(
|
||||
};
|
||||
|
||||
if (config.import.file) {
|
||||
// TODO: stateservice was here
|
||||
await services.importService.importFromFile(
|
||||
config.import.file,
|
||||
config.import.project,
|
||||
config.import.environment,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
|
@ -81,8 +81,8 @@ export interface IAuthOption {
|
||||
|
||||
export interface IImportOption {
|
||||
file: string;
|
||||
keepExisting: boolean;
|
||||
dropBeforeImport: boolean;
|
||||
project: string;
|
||||
environment: string;
|
||||
}
|
||||
|
||||
export interface IServerOption {
|
||||
|
Loading…
Reference in New Issue
Block a user