mirror of
https://github.com/Unleash/unleash.git
synced 2025-09-05 17:53:12 +02:00
fix: support importing envs
This commit is contained in:
parent
1e5a7adb6d
commit
b616a762f6
@ -39,6 +39,17 @@ function mapRow(row: IEnvironmentsTable): IEnvironment {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fieldToRow(env: IEnvironment): IEnvironmentsTable {
|
||||||
|
return {
|
||||||
|
name: env.name,
|
||||||
|
display_name: env.displayName,
|
||||||
|
type: env.type,
|
||||||
|
sort_order: env.sortOrder,
|
||||||
|
enabled: env.enabled,
|
||||||
|
protected: env.protected,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const TABLE = 'environments';
|
const TABLE = 'environments';
|
||||||
|
|
||||||
export default class EnvironmentStore implements IEnvironmentStore {
|
export default class EnvironmentStore implements IEnvironmentStore {
|
||||||
@ -58,6 +69,18 @@ export default class EnvironmentStore implements IEnvironmentStore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async importEnvironments(
|
||||||
|
environments: IEnvironment[],
|
||||||
|
): Promise<IEnvironment[]> {
|
||||||
|
const rows = await this.db(TABLE)
|
||||||
|
.insert(environments.map(fieldToRow))
|
||||||
|
.returning(COLUMNS)
|
||||||
|
.onConflict('name')
|
||||||
|
.ignore();
|
||||||
|
|
||||||
|
return rows.map(mapRow);
|
||||||
|
}
|
||||||
|
|
||||||
async deleteAll(): Promise<void> {
|
async deleteAll(): Promise<void> {
|
||||||
await this.db(TABLE).del();
|
await this.db(TABLE).del();
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { stateSchema } from './state-schema';
|
import { stateSchema } from './state-schema';
|
||||||
import {
|
import {
|
||||||
|
DROP_ENVIRONMENTS,
|
||||||
DROP_FEATURE_TAGS,
|
DROP_FEATURE_TAGS,
|
||||||
DROP_FEATURES,
|
DROP_FEATURES,
|
||||||
DROP_PROJECTS,
|
DROP_PROJECTS,
|
||||||
DROP_STRATEGIES,
|
DROP_STRATEGIES,
|
||||||
DROP_TAG_TYPES,
|
DROP_TAG_TYPES,
|
||||||
DROP_TAGS,
|
DROP_TAGS,
|
||||||
|
ENVIRONMENT_IMPORT,
|
||||||
FEATURE_IMPORT,
|
FEATURE_IMPORT,
|
||||||
FEATURE_TAG_IMPORT,
|
FEATURE_TAG_IMPORT,
|
||||||
PROJECT_IMPORT,
|
PROJECT_IMPORT,
|
||||||
@ -151,6 +153,15 @@ export default class StateService {
|
|||||||
}
|
}
|
||||||
const importData = await stateSchema.validateAsync(data);
|
const importData = await stateSchema.validateAsync(data);
|
||||||
|
|
||||||
|
if (importData.environments) {
|
||||||
|
await this.importEnvironments({
|
||||||
|
environments: data.environments,
|
||||||
|
userName,
|
||||||
|
dropBeforeImport,
|
||||||
|
keepExisting,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (importData.features) {
|
if (importData.features) {
|
||||||
let projectData;
|
let projectData;
|
||||||
if (!importData.version || importData.version === 1) {
|
if (!importData.version || importData.version === 1) {
|
||||||
@ -365,6 +376,42 @@ export default class StateService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
|
async importEnvironments({
|
||||||
|
environments,
|
||||||
|
userName,
|
||||||
|
dropBeforeImport,
|
||||||
|
keepExisting,
|
||||||
|
}): Promise<void> {
|
||||||
|
this.logger.info(`Import ${environments.length} projects`);
|
||||||
|
const oldEnvs = dropBeforeImport
|
||||||
|
? []
|
||||||
|
: await this.environmentStore.getAll();
|
||||||
|
if (dropBeforeImport) {
|
||||||
|
this.logger.info('Dropping existing environments');
|
||||||
|
await this.environmentStore.deleteAll();
|
||||||
|
await this.eventStore.store({
|
||||||
|
type: DROP_ENVIRONMENTS,
|
||||||
|
createdBy: userName,
|
||||||
|
data: { name: 'all-projects' },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const envsImport = environments.filter((env) =>
|
||||||
|
keepExisting ? !oldEnvs.some((old) => old.name === env.name) : true,
|
||||||
|
);
|
||||||
|
if (envsImport.length > 0) {
|
||||||
|
const importedEnvs = await this.environmentStore.importEnvironments(
|
||||||
|
envsImport,
|
||||||
|
);
|
||||||
|
const importedEnvironmentEvents = importedEnvs.map((env) => ({
|
||||||
|
type: ENVIRONMENT_IMPORT,
|
||||||
|
createdBy: userName,
|
||||||
|
data: env,
|
||||||
|
}));
|
||||||
|
await this.eventStore.batchStore(importedEnvironmentEvents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
async importProjects({
|
async importProjects({
|
||||||
projects,
|
projects,
|
||||||
|
@ -48,3 +48,5 @@ export const DB_POOL_UPDATE = 'db-pool-update';
|
|||||||
export const USER_CREATED = 'user-created';
|
export const USER_CREATED = 'user-created';
|
||||||
export const USER_UPDATED = 'user-updated';
|
export const USER_UPDATED = 'user-updated';
|
||||||
export const USER_DELETED = 'user-deleted';
|
export const USER_DELETED = 'user-deleted';
|
||||||
|
export const DROP_ENVIRONMENTS = 'drop-environments';
|
||||||
|
export const ENVIRONMENT_IMPORT = 'environment-import';
|
||||||
|
@ -14,4 +14,5 @@ export interface IEnvironmentStore extends Store<IEnvironment, string> {
|
|||||||
value: string | number | boolean,
|
value: string | number | boolean,
|
||||||
): Promise<void>;
|
): Promise<void>;
|
||||||
updateSortOrder(id: string, value: number): Promise<void>;
|
updateSortOrder(id: string, value: number): Promise<void>;
|
||||||
|
importEnvironments(environments: IEnvironment[]): Promise<IEnvironment[]>;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import dbInit, { ITestDb } from '../../../helpers/database-init';
|
import dbInit, { ITestDb } from '../../../helpers/database-init';
|
||||||
import { IUnleashTest, setupApp } from '../../../helpers/test-helper';
|
import { IUnleashTest, setupApp } from '../../../helpers/test-helper';
|
||||||
import getLogger from '../../../../fixtures/no-logger';
|
import getLogger from '../../../../fixtures/no-logger';
|
||||||
import { GLOBAL_ENV } from '../../../../../lib/types/environment';
|
|
||||||
import { DEFAULT_ENV } from '../../../../../lib/util/constants';
|
import { DEFAULT_ENV } from '../../../../../lib/util/constants';
|
||||||
|
|
||||||
let app: IUnleashTest;
|
let app: IUnleashTest;
|
||||||
@ -645,7 +644,7 @@ test('Environments are returned in sortOrder', async () => {
|
|||||||
.expect(200)
|
.expect(200)
|
||||||
.expect((res) => {
|
.expect((res) => {
|
||||||
expect(res.body.environments).toHaveLength(3);
|
expect(res.body.environments).toHaveLength(3);
|
||||||
expect(res.body.environments[0].name).toBe(GLOBAL_ENV);
|
expect(res.body.environments[0].name).toBe(DEFAULT_ENV);
|
||||||
expect(res.body.environments[1].name).toBe(sortedSecond);
|
expect(res.body.environments[1].name).toBe(sortedSecond);
|
||||||
expect(res.body.environments[2].name).toBe(sortedLast);
|
expect(res.body.environments[2].name).toBe(sortedLast);
|
||||||
});
|
});
|
||||||
|
5
src/test/fixtures/fake-environment-store.ts
vendored
5
src/test/fixtures/fake-environment-store.ts
vendored
@ -3,6 +3,11 @@ import NotFoundError from '../../lib/error/notfound-error';
|
|||||||
import { IEnvironmentStore } from '../../lib/types/stores/environment-store';
|
import { IEnvironmentStore } from '../../lib/types/stores/environment-store';
|
||||||
|
|
||||||
export default class FakeEnvironmentStore implements IEnvironmentStore {
|
export default class FakeEnvironmentStore implements IEnvironmentStore {
|
||||||
|
importEnvironments(envs: IEnvironment[]): Promise<IEnvironment[]> {
|
||||||
|
this.environments = envs;
|
||||||
|
return Promise.resolve(envs);
|
||||||
|
}
|
||||||
|
|
||||||
environments: IEnvironment[] = [];
|
environments: IEnvironment[] = [];
|
||||||
|
|
||||||
async getAll(): Promise<IEnvironment[]> {
|
async getAll(): Promise<IEnvironment[]> {
|
||||||
|
Loading…
Reference in New Issue
Block a user