mirror of
https://github.com/Unleash/unleash.git
synced 2025-09-10 17:53:36 +02:00
Added events for feature_strategy update
This commit is contained in:
parent
68d4ac0252
commit
1ae90f6942
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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';
|
||||||
|
Loading…
Reference in New Issue
Block a user