mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
feat: first skeleton of the batch import (#2868)
First skeleton of batch import: * injecting feature toggle service because I want to reuse logic and not just the store
This commit is contained in:
parent
3e4e0e4df9
commit
afdcd45042
@ -7,8 +7,10 @@ import { Logger } from '../../logger';
|
|||||||
import { OpenApiService } from '../../services/openapi-service';
|
import { OpenApiService } from '../../services/openapi-service';
|
||||||
import ExportImportService, {
|
import ExportImportService, {
|
||||||
IExportQuery,
|
IExportQuery,
|
||||||
|
IImportDTO,
|
||||||
} from 'lib/services/export-import-service';
|
} from 'lib/services/export-import-service';
|
||||||
import { InvalidOperationError } from '../../error';
|
import { InvalidOperationError } from '../../error';
|
||||||
|
import { IAuthRequest } from '../unleash-types';
|
||||||
|
|
||||||
class ExportImportController extends Controller {
|
class ExportImportController extends Controller {
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
@ -45,6 +47,12 @@ class ExportImportController extends Controller {
|
|||||||
// }),
|
// }),
|
||||||
// ],
|
// ],
|
||||||
});
|
});
|
||||||
|
this.route({
|
||||||
|
method: 'post',
|
||||||
|
path: '/import',
|
||||||
|
permission: NONE,
|
||||||
|
handler: this.importData,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async export(
|
async export(
|
||||||
@ -65,5 +73,16 @@ class ExportImportController extends Controller {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async importData(
|
||||||
|
req: IAuthRequest<unknown, unknown, IImportDTO, unknown>,
|
||||||
|
res: Response,
|
||||||
|
): Promise<void> {
|
||||||
|
const dto = req.body;
|
||||||
|
const user = req.user;
|
||||||
|
await this.exportImportService.import(dto, user);
|
||||||
|
|
||||||
|
res.status(201).end();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export default ExportImportController;
|
export default ExportImportController;
|
||||||
|
@ -13,14 +13,22 @@ import { IEnvironmentStore } from '../types/stores/environment-store';
|
|||||||
import { IFeatureEnvironmentStore } from '../types/stores/feature-environment-store';
|
import { IFeatureEnvironmentStore } from '../types/stores/feature-environment-store';
|
||||||
import { IUnleashStores } from '../types/stores';
|
import { IUnleashStores } from '../types/stores';
|
||||||
import { ISegmentStore } from '../types/stores/segment-store';
|
import { ISegmentStore } from '../types/stores/segment-store';
|
||||||
import { IFlagResolver } from 'lib/types';
|
import { IFlagResolver, IUnleashServices } from 'lib/types';
|
||||||
import { IContextFieldDto } from '../types/stores/context-field-store';
|
import { IContextFieldDto } from '../types/stores/context-field-store';
|
||||||
|
import FeatureToggleService from './feature-toggle-service';
|
||||||
|
import User from 'lib/types/user';
|
||||||
|
|
||||||
export interface IExportQuery {
|
export interface IExportQuery {
|
||||||
features: string[];
|
features: string[];
|
||||||
environment: string;
|
environment: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IImportDTO {
|
||||||
|
data: IExportData;
|
||||||
|
project?: string;
|
||||||
|
environment?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IExportData {
|
export interface IExportData {
|
||||||
features: FeatureToggle[];
|
features: FeatureToggle[];
|
||||||
tags?: ITag[];
|
tags?: ITag[];
|
||||||
@ -54,12 +62,17 @@ export default class ExportImportService {
|
|||||||
|
|
||||||
private flagResolver: IFlagResolver;
|
private flagResolver: IFlagResolver;
|
||||||
|
|
||||||
|
private featureToggleService: FeatureToggleService;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
stores: IUnleashStores,
|
stores: IUnleashStores,
|
||||||
{
|
{
|
||||||
getLogger,
|
getLogger,
|
||||||
flagResolver,
|
flagResolver,
|
||||||
}: Pick<IUnleashConfig, 'getLogger' | 'flagResolver'>,
|
}: Pick<IUnleashConfig, 'getLogger' | 'flagResolver'>,
|
||||||
|
{
|
||||||
|
featureToggleService,
|
||||||
|
}: Pick<IUnleashServices, 'featureToggleService'>,
|
||||||
) {
|
) {
|
||||||
this.eventStore = stores.eventStore;
|
this.eventStore = stores.eventStore;
|
||||||
this.toggleStore = stores.featureToggleStore;
|
this.toggleStore = stores.featureToggleStore;
|
||||||
@ -73,6 +86,7 @@ export default class ExportImportService {
|
|||||||
this.environmentStore = stores.environmentStore;
|
this.environmentStore = stores.environmentStore;
|
||||||
this.segmentStore = stores.segmentStore;
|
this.segmentStore = stores.segmentStore;
|
||||||
this.flagResolver = flagResolver;
|
this.flagResolver = flagResolver;
|
||||||
|
this.featureToggleService = featureToggleService;
|
||||||
this.logger = getLogger('services/state-service.js');
|
this.logger = getLogger('services/state-service.js');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +96,18 @@ export default class ExportImportService {
|
|||||||
).filter((toggle) => query.features.includes(toggle.name));
|
).filter((toggle) => query.features.includes(toggle.name));
|
||||||
return { features: features };
|
return { features: features };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async import(dto: IImportDTO, user: User): Promise<void> {
|
||||||
|
await Promise.all(
|
||||||
|
dto.data.features.map((feature) =>
|
||||||
|
this.featureToggleService.createFeatureToggle(
|
||||||
|
dto.project || feature.project,
|
||||||
|
feature,
|
||||||
|
user.name,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ExportImportService;
|
module.exports = ExportImportService;
|
||||||
|
@ -61,7 +61,6 @@ export const createServices = (
|
|||||||
const featureTypeService = new FeatureTypeService(stores, config);
|
const featureTypeService = new FeatureTypeService(stores, config);
|
||||||
const resetTokenService = new ResetTokenService(stores, config);
|
const resetTokenService = new ResetTokenService(stores, config);
|
||||||
const stateService = new StateService(stores, config);
|
const stateService = new StateService(stores, config);
|
||||||
const exportImportService = new ExportImportService(stores, config);
|
|
||||||
const strategyService = new StrategyService(stores, config);
|
const strategyService = new StrategyService(stores, config);
|
||||||
const tagService = new TagService(stores, config);
|
const tagService = new TagService(stores, config);
|
||||||
const tagTypeService = new TagTypeService(stores, config);
|
const tagTypeService = new TagTypeService(stores, config);
|
||||||
@ -85,6 +84,9 @@ export const createServices = (
|
|||||||
segmentService,
|
segmentService,
|
||||||
accessService,
|
accessService,
|
||||||
);
|
);
|
||||||
|
const exportImportService = new ExportImportService(stores, config, {
|
||||||
|
featureToggleService: featureToggleServiceV2,
|
||||||
|
});
|
||||||
const environmentService = new EnvironmentService(stores, config);
|
const environmentService = new EnvironmentService(stores, config);
|
||||||
const featureTagService = new FeatureTagService(stores, config);
|
const featureTagService = new FeatureTagService(stores, config);
|
||||||
const favoritesService = new FavoritesService(stores, config);
|
const favoritesService = new FavoritesService(stores, config);
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
import dbInit, { ITestDb } from '../../helpers/database-init';
|
import dbInit, { ITestDb } from '../../helpers/database-init';
|
||||||
import getLogger from '../../../fixtures/no-logger';
|
import getLogger from '../../../fixtures/no-logger';
|
||||||
import { IEventStore } from 'lib/types/stores/event-store';
|
import { IEventStore } from 'lib/types/stores/event-store';
|
||||||
import { FeatureToggleDTO, IStrategyConfig } from 'lib/types';
|
import { FeatureToggle, FeatureToggleDTO, IStrategyConfig } from 'lib/types';
|
||||||
import { DEFAULT_ENV } from '../../../../lib/util';
|
import { DEFAULT_ENV } from '../../../../lib/util';
|
||||||
|
|
||||||
let app: IUnleashTest;
|
let app: IUnleashTest;
|
||||||
@ -79,3 +79,25 @@ test('exports features', async () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('import features', async () => {
|
||||||
|
const feature: FeatureToggle = { project: 'ignore', name: 'first_feature' };
|
||||||
|
await app.request
|
||||||
|
.post('/api/admin/features-batch/import')
|
||||||
|
.send({
|
||||||
|
data: { features: [feature] },
|
||||||
|
project: 'default',
|
||||||
|
environment: 'custom_environment',
|
||||||
|
})
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.expect(201);
|
||||||
|
|
||||||
|
const { body } = await app.request
|
||||||
|
.get('/api/admin/features/first_feature')
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
expect(body).toMatchObject({
|
||||||
|
name: 'first_feature',
|
||||||
|
project: 'default',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user