1
0
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:
Ivar Conradi Østhus 2021-09-23 21:04:29 +02:00
parent 1e5a7adb6d
commit b616a762f6
No known key found for this signature in database
GPG Key ID: 31AC596886B0BD09
6 changed files with 79 additions and 2 deletions

View File

@ -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();
} }

View File

@ -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,

View File

@ -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';

View File

@ -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[]>;
} }

View File

@ -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);
}); });

View File

@ -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[]> {