1
0
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:
Mateusz Kwasniewski 2024-07-08 11:02:22 +02:00 committed by GitHub
parent ef80d7f81e
commit 7ca2ace0bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 67 additions and 6 deletions

View File

@ -200,6 +200,7 @@ exports[`should create default config 1`] = `
"actionSetsPerProject": 5,
"apiTokens": 2000,
"constraintValues": 250,
"constraints": 30,
"environments": 50,
"featureEnvironmentStrategies": 30,
"featureFlags": 5000,

View File

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

View File

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

View File

@ -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 } =

View File

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