1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-05 17:53:12 +02:00

Added events for feature_strategy update

This commit is contained in:
Christopher Kolstad 2021-09-16 09:07:00 +02:00
parent 68d4ac0252
commit 1ae90f6942
No known key found for this signature in database
GPG Key ID: 559ACB0E3DB5538A
3 changed files with 96 additions and 22 deletions

View File

@ -17,6 +17,7 @@ import {
} from '../../../types/model'; } from '../../../types/model';
import { extractUsername } from '../../../util/extract-user'; import { extractUsername } from '../../../util/extract-user';
import { IAuthRequest } from '../../unleash-types'; import { IAuthRequest } from '../../unleash-types';
import { projectSchema } from '../../../services/project-schema';
interface FeatureStrategyParams { interface FeatureStrategyParams {
projectId: string; projectId: string;
@ -220,14 +221,16 @@ export default class ProjectFeaturesController extends Controller {
} }
async addStrategy( async addStrategy(
req: Request<FeatureStrategyParams, any, IStrategyConfig, any>, req: IAuthRequest<FeatureStrategyParams, any, IStrategyConfig, any>,
res: Response, res: Response,
): Promise<void> { ): Promise<void> {
const { projectId, featureName, environment } = req.params; const { projectId, featureName, environment } = req.params;
const userName = extractUsername(req);
const featureStrategy = await this.featureService.createStrategy( const featureStrategy = await this.featureService.createStrategy(
req.body, req.body,
projectId, projectId,
featureName, featureName,
userName,
environment, environment,
); );
res.status(200).json(featureStrategy); res.status(200).json(featureStrategy);
@ -248,34 +251,42 @@ export default class ProjectFeaturesController extends Controller {
} }
async updateStrategy( async updateStrategy(
req: Request<StrategyIdParams, any, StrategyUpdateBody, any>, req: IAuthRequest<StrategyIdParams, any, StrategyUpdateBody, any>,
res: Response, res: Response,
): Promise<void> { ): Promise<void> {
const { strategyId } = req.params; const { strategyId, environment, projectId } = req.params;
const userName = extractUsername(req);
const updatedStrategy = await this.featureService.updateStrategy( const updatedStrategy = await this.featureService.updateStrategy(
strategyId, strategyId,
environment,
projectId,
userName,
req.body, req.body,
); );
res.status(200).json(updatedStrategy); res.status(200).json(updatedStrategy);
} }
async patchStrategy( async patchStrategy(
req: Request<StrategyIdParams, any, Operation[], any>, req: IAuthRequest<StrategyIdParams, any, Operation[], any>,
res: Response, res: Response,
): Promise<void> { ): Promise<void> {
const { strategyId } = req.params; const { strategyId, projectId, environment } = req.params;
const userName = extractUsername(req);
const patch = req.body; const patch = req.body;
const strategy = await this.featureService.getStrategy(strategyId); const strategy = await this.featureService.getStrategy(strategyId);
const { newDocument } = applyPatch(strategy, patch); const { newDocument } = applyPatch(strategy, patch);
const updatedStrategy = await this.featureService.updateStrategy( const updatedStrategy = await this.featureService.updateStrategy(
strategyId, strategyId,
environment,
projectId,
userName,
newDocument, newDocument,
); );
res.status(200).json(updatedStrategy); res.status(200).json(updatedStrategy);
} }
async getStrategy( async getStrategy(
req: Request<StrategyIdParams, any, any, any>, req: IAuthRequest<StrategyIdParams, any, any, any>,
res: Response, res: Response,
): Promise<void> { ): Promise<void> {
this.logger.info('Getting strategy'); this.logger.info('Getting strategy');
@ -286,18 +297,25 @@ export default class ProjectFeaturesController extends Controller {
} }
async deleteStrategy( async deleteStrategy(
req: Request<StrategyIdParams, any, any, any>, req: IAuthRequest<StrategyIdParams, any, any, any>,
res: Response, res: Response,
): Promise<void> { ): Promise<void> {
this.logger.info('Deleting strategy'); this.logger.info('Deleting strategy');
const { environment, projectId } = req.params;
const userName = extractUsername(req);
const { strategyId } = req.params; const { strategyId } = req.params;
this.logger.info(strategyId); this.logger.info(strategyId);
const strategy = await this.featureService.deleteStrategy(strategyId); const strategy = await this.featureService.deleteStrategy(
strategyId,
userName,
projectId,
environment,
);
res.status(200).json(strategy); res.status(200).json(strategy);
} }
async updateStrategyParameter( async updateStrategyParameter(
req: Request< req: IAuthRequest<
StrategyIdParams, StrategyIdParams,
any, any,
{ name: string; value: string | number }, { name: string; value: string | number },
@ -305,7 +323,8 @@ export default class ProjectFeaturesController extends Controller {
>, >,
res: Response, res: Response,
): Promise<void> { ): Promise<void> {
const { strategyId } = req.params; const { strategyId, environment, projectId } = req.params;
const userName = extractUsername(req);
const { name, value } = req.body; const { name, value } = req.body;
const updatedStrategy = const updatedStrategy =
@ -313,6 +332,9 @@ export default class ProjectFeaturesController extends Controller {
strategyId, strategyId,
name, name,
value, value,
userName,
projectId,
environment,
); );
res.status(200).json(updatedStrategy); res.status(200).json(updatedStrategy);
} }

View File

@ -10,11 +10,14 @@ import {
FEATURE_ARCHIVED, FEATURE_ARCHIVED,
FEATURE_CREATED, FEATURE_CREATED,
FEATURE_DELETED, FEATURE_DELETED,
FEATURE_METADATA_UPDATED,
FEATURE_REVIVED, FEATURE_REVIVED,
FEATURE_STALE_OFF, FEATURE_STALE_OFF,
FEATURE_STALE_ON, FEATURE_STALE_ON,
FEATURE_STRATEGY_ADD,
FEATURE_STRATEGY_REMOVE,
FEATURE_STRATEGY_UPDATE,
FEATURE_UPDATED, FEATURE_UPDATED,
FEATURE_METADATA_UPDATED,
} from '../types/events'; } from '../types/events';
import { GLOBAL_ENV } from '../types/environment'; import { GLOBAL_ENV } from '../types/environment';
import NotFoundError from '../error/notfound-error'; import NotFoundError from '../error/notfound-error';
@ -88,16 +91,11 @@ class FeatureToggleServiceV2 {
this.featureEnvironmentStore = featureEnvironmentStore; this.featureEnvironmentStore = featureEnvironmentStore;
} }
/*
TODO after 4.1.0 release:
- add FEATURE_STRATEGY_ADD event
- add FEATURE_STRATEGY_REMOVE event
- add FEATURE_STRATEGY_UPDATE event
*/
async createStrategy( async createStrategy(
strategyConfig: Omit<IStrategyConfig, 'id'>, strategyConfig: Omit<IStrategyConfig, 'id'>,
projectId: string, projectId: string,
featureName: string, featureName: string,
userName: string,
environment: string = GLOBAL_ENV, environment: string = GLOBAL_ENV,
): Promise<IStrategyConfig> { ): Promise<IStrategyConfig> {
try { try {
@ -111,12 +109,20 @@ class FeatureToggleServiceV2 {
featureName, featureName,
environment, environment,
}); });
return { const data = {
id: newFeatureStrategy.id, id: newFeatureStrategy.id,
name: newFeatureStrategy.strategyName, name: newFeatureStrategy.strategyName,
constraints: newFeatureStrategy.constraints, constraints: newFeatureStrategy.constraints,
parameters: newFeatureStrategy.parameters, parameters: newFeatureStrategy.parameters,
}; };
await this.eventStore.store({
type: FEATURE_STRATEGY_ADD,
project: projectId,
createdBy: userName,
environment,
data,
});
return data;
} catch (e) { } catch (e) {
if (e.code === FOREIGN_KEY_VIOLATION) { if (e.code === FOREIGN_KEY_VIOLATION) {
throw new BadDataError( throw new BadDataError(
@ -126,6 +132,12 @@ class FeatureToggleServiceV2 {
throw e; throw e;
} }
} }
/*
TODO after 4.1.0 release:
- add FEATURE_STRATEGY_ADD event
- add FEATURE_STRATEGY_REMOVE event
- add FEATURE_STRATEGY_UPDATE event
*/
/** /**
* PUT /api/admin/projects/:projectId/features/:featureName/strategies/:strategyId ? * PUT /api/admin/projects/:projectId/features/:featureName/strategies/:strategyId ?
@ -139,6 +151,9 @@ class FeatureToggleServiceV2 {
// TODO: verify projectId is not changed from URL! // TODO: verify projectId is not changed from URL!
async updateStrategy( async updateStrategy(
id: string, id: string,
environment: string,
project: string,
userName: string,
updates: Partial<IFeatureStrategy>, updates: Partial<IFeatureStrategy>,
): Promise<IStrategyConfig> { ): Promise<IStrategyConfig> {
const existingStrategy = await this.featureStrategiesStore.get(id); const existingStrategy = await this.featureStrategiesStore.get(id);
@ -147,12 +162,20 @@ class FeatureToggleServiceV2 {
id, id,
updates, updates,
); );
return { const data = {
id: strategy.id, id: strategy.id,
name: strategy.strategyName, name: strategy.strategyName,
constraints: strategy.constraints || [], constraints: strategy.constraints || [],
parameters: strategy.parameters, parameters: strategy.parameters,
}; };
await this.eventStore.store({
type: FEATURE_STRATEGY_UPDATE,
project,
environment,
createdBy: userName,
data,
});
return data;
} }
throw new NotFoundError(`Could not find strategy with id ${id}`); throw new NotFoundError(`Could not find strategy with id ${id}`);
} }
@ -162,6 +185,9 @@ class FeatureToggleServiceV2 {
id: string, id: string,
name: string, name: string,
value: string | number, value: string | number,
userName: string,
project: string,
environment: string,
): Promise<IStrategyConfig> { ): Promise<IStrategyConfig> {
const existingStrategy = await this.featureStrategiesStore.get(id); const existingStrategy = await this.featureStrategiesStore.get(id);
if (existingStrategy.id === id) { if (existingStrategy.id === id) {
@ -170,12 +196,20 @@ class FeatureToggleServiceV2 {
id, id,
existingStrategy, existingStrategy,
); );
return { const data = {
id: strategy.id, id: strategy.id,
name: strategy.strategyName, name: strategy.strategyName,
constraints: strategy.constraints || [], constraints: strategy.constraints || [],
parameters: strategy.parameters, parameters: strategy.parameters,
}; };
await this.eventStore.store({
type: FEATURE_STRATEGY_UPDATE,
project,
environment,
createdBy: userName,
data,
});
return data;
} }
throw new NotFoundError(`Could not find strategy with id ${id}`); throw new NotFoundError(`Could not find strategy with id ${id}`);
} }
@ -188,8 +222,22 @@ class FeatureToggleServiceV2 {
* @param id * @param id
* @param updates * @param updates
*/ */
async deleteStrategy(id: string): Promise<void> { async deleteStrategy(
return this.featureStrategiesStore.delete(id); id: string,
userName: string,
project: string = 'default',
environment: string = GLOBAL_ENV,
): Promise<void> {
await this.featureStrategiesStore.delete(id);
await this.eventStore.store({
type: FEATURE_STRATEGY_REMOVE,
project,
environment,
createdBy: userName,
data: {
id,
},
});
} }
async getStrategiesForEnvironment( async getStrategiesForEnvironment(
@ -519,6 +567,7 @@ class FeatureToggleServiceV2 {
data, data,
tags, tags,
project: projectId, project: projectId,
environment,
}); });
return feature; return feature;
} }

View File

@ -9,6 +9,9 @@ export const FEATURE_REVIVED = 'feature-revived';
export const FEATURE_IMPORT = 'feature-import'; export const FEATURE_IMPORT = 'feature-import';
export const FEATURE_TAGGED = 'feature-tagged'; export const FEATURE_TAGGED = 'feature-tagged';
export const FEATURE_TAG_IMPORT = 'feature-tag-import'; export const FEATURE_TAG_IMPORT = 'feature-tag-import';
export const FEATURE_STRATEGY_UPDATE = 'feature-strategy-update';
export const FEATURE_STRATEGY_ADD = 'feature-strategy-add';
export const FEATURE_STRATEGY_REMOVE = 'feature-strategy-remove';
export const DROP_FEATURE_TAGS = 'drop-feature-tags'; export const DROP_FEATURE_TAGS = 'drop-feature-tags';
export const FEATURE_UNTAGGED = 'feature-untagged'; export const FEATURE_UNTAGGED = 'feature-untagged';
export const FEATURE_STALE_ON = 'feature-stale-on'; export const FEATURE_STALE_ON = 'feature-stale-on';