mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-15 01:16:22 +02:00
feat: constraints limit in a strategy (#7554)
This commit is contained in:
parent
ef80d7f81e
commit
7ca2ace0bc
@ -200,6 +200,7 @@ exports[`should create default config 1`] = `
|
||||
"actionSetsPerProject": 5,
|
||||
"apiTokens": 2000,
|
||||
"constraintValues": 250,
|
||||
"constraints": 30,
|
||||
"environments": 50,
|
||||
"featureEnvironmentStrategies": 30,
|
||||
"featureFlags": 5000,
|
||||
|
@ -663,6 +663,10 @@ export function createConfig(options: IUnleashOptions): IUnleashConfig {
|
||||
options?.resourceLimits?.constraintValues || 250,
|
||||
),
|
||||
),
|
||||
constraints: Math.max(
|
||||
0,
|
||||
parseEnvVarNumber(process.env.UNLEASH_CONSTRAINTS_LIMIT, 30),
|
||||
),
|
||||
environments: parseEnvVarNumber(
|
||||
process.env.UNLEASH_ENVIRONMENTS_LIMIT,
|
||||
50,
|
||||
|
@ -387,19 +387,24 @@ class FeatureToggleService {
|
||||
}
|
||||
}
|
||||
|
||||
validateConstraintValuesLimit(updatedConstrains: IConstraint[]) {
|
||||
validateConstraintsLimit(updatedConstrains: IConstraint[]) {
|
||||
if (!this.flagResolver.isEnabled('resourceLimits')) return;
|
||||
|
||||
const limit = this.resourceLimits.constraintValues;
|
||||
const constraintsLimit = this.resourceLimits.constraints;
|
||||
if (updatedConstrains.length > constraintsLimit) {
|
||||
throw new ExceedsLimitError(`constraints`, constraintsLimit);
|
||||
}
|
||||
|
||||
const constraintValuesLimit = this.resourceLimits.constraintValues;
|
||||
const constraintOverLimit = updatedConstrains.find(
|
||||
(constraint) =>
|
||||
Array.isArray(constraint.values) &&
|
||||
constraint.values?.length > limit,
|
||||
constraint.values?.length > constraintValuesLimit,
|
||||
);
|
||||
if (constraintOverLimit) {
|
||||
throw new ExceedsLimitError(
|
||||
`content values for ${constraintOverLimit.contextName}`,
|
||||
limit,
|
||||
constraintValuesLimit,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -649,7 +654,7 @@ class FeatureToggleService {
|
||||
strategyConfig.constraints &&
|
||||
strategyConfig.constraints.length > 0
|
||||
) {
|
||||
this.validateConstraintValuesLimit(strategyConfig.constraints);
|
||||
this.validateConstraintsLimit(strategyConfig.constraints);
|
||||
strategyConfig.constraints = await this.validateConstraints(
|
||||
strategyConfig.constraints,
|
||||
);
|
||||
@ -808,7 +813,7 @@ class FeatureToggleService {
|
||||
|
||||
if (existingStrategy.id === id) {
|
||||
if (updates.constraints && updates.constraints.length > 0) {
|
||||
this.validateConstraintValuesLimit(updates.constraints);
|
||||
this.validateConstraintsLimit(updates.constraints);
|
||||
updates.constraints = await this.validateConstraints(
|
||||
updates.constraints,
|
||||
);
|
||||
|
@ -47,6 +47,50 @@ describe('Strategy limits', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('Should not allow to exceed constraints limit', async () => {
|
||||
const LIMIT = 1;
|
||||
const { featureToggleService, featureToggleStore } =
|
||||
createFakeFeatureToggleService({
|
||||
getLogger,
|
||||
flagResolver: alwaysOnFlagResolver,
|
||||
resourceLimits: {
|
||||
constraints: LIMIT,
|
||||
},
|
||||
} as unknown as IUnleashConfig);
|
||||
|
||||
const addStrategy = (constraints: IConstraint[]) =>
|
||||
featureToggleService.unprotectedCreateStrategy(
|
||||
{
|
||||
name: 'default',
|
||||
featureName: 'feature',
|
||||
constraints: constraints,
|
||||
} as IStrategyConfig,
|
||||
{ projectId: 'default', featureName: 'feature' } as any,
|
||||
{} as IAuditUser,
|
||||
);
|
||||
await featureToggleStore.create('default', {
|
||||
name: 'feature',
|
||||
createdByUserId: 1,
|
||||
});
|
||||
|
||||
await expect(
|
||||
addStrategy([
|
||||
{
|
||||
values: ['1'],
|
||||
operator: 'IN',
|
||||
contextName: 'accountId',
|
||||
},
|
||||
{
|
||||
values: ['2'],
|
||||
operator: 'IN',
|
||||
contextName: 'accountId',
|
||||
},
|
||||
]),
|
||||
).rejects.toThrow(
|
||||
"Failed to create constraints. You can't create more than the established limit of 1",
|
||||
);
|
||||
});
|
||||
|
||||
test('Should not allow to exceed constraint values limit', async () => {
|
||||
const LIMIT = 3;
|
||||
const { featureToggleService, featureToggleStore } =
|
||||
|
@ -20,6 +20,7 @@ export const resourceLimitsSchema = {
|
||||
'apiTokens',
|
||||
'segments',
|
||||
'featureFlags',
|
||||
'constraints',
|
||||
],
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
@ -80,6 +81,12 @@ export const resourceLimitsSchema = {
|
||||
description:
|
||||
'The maximum number of values for a single constraint.',
|
||||
},
|
||||
constraints: {
|
||||
type: 'integer',
|
||||
example: 30,
|
||||
description:
|
||||
'The maximum number of constraints in a single strategy.',
|
||||
},
|
||||
environments: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
|
Loading…
Reference in New Issue
Block a user