diff --git a/aws_lambda_powertools/utilities/feature_flags/comparators.py b/aws_lambda_powertools/utilities/feature_flags/comparators.py index 78370f1b5b1..1419dd6dd83 100644 --- a/aws_lambda_powertools/utilities/feature_flags/comparators.py +++ b/aws_lambda_powertools/utilities/feature_flags/comparators.py @@ -4,6 +4,7 @@ from dateutil.tz import gettz from .schema import HOUR_MIN_SEPARATOR, ModuloRangeValues, TimeValues +from .exceptions import SchemaValidationError def _get_now_from_timezone(timezone: Optional[tzinfo]) -> datetime: @@ -82,3 +83,43 @@ def compare_modulo_range(context_value: int, condition_value: Dict) -> bool: end = condition_value.get(ModuloRangeValues.END.value, 1) return start <= context_value % base <= end + + +def compare_any_in_list(key_list, value_list): + if not (isinstance(key_list, list) and isinstance(value_list, list)): + raise SchemaValidationError() + + results = False + for key in key_list: + if key in value_list: + results = True + break + + return results + + +def compare_all_in_list(key_list, value_list): + if not (isinstance(key_list, list) and isinstance(value_list, list)): + raise SchemaValidationError() + + results = True + for key in key_list: + if key not in value_list: + results = False + break + + return results + + +def compare_none_in_list(key_list, value_list): + if not (isinstance(key_list, list) and isinstance(value_list, list)): + raise SchemaValidationError() + + results = True + for key in key_list: + if key in value_list: + results = False + break + + return results + diff --git a/aws_lambda_powertools/utilities/feature_flags/feature_flags.py b/aws_lambda_powertools/utilities/feature_flags/feature_flags.py index 8610d68a8f6..ac4dfef0162 100644 --- a/aws_lambda_powertools/utilities/feature_flags/feature_flags.py +++ b/aws_lambda_powertools/utilities/feature_flags/feature_flags.py @@ -10,6 +10,9 @@ compare_days_of_week, compare_modulo_range, compare_time_range, + compare_all_in_list, + compare_any_in_list, + compare_none_in_list ) from .exceptions import ConfigurationStoreError @@ -63,6 +66,9 @@ def _match_by_action(self, action: str, condition_value: Any, context_value: Any schema.RuleAction.KEY_NOT_IN_VALUE.value: lambda a, b: a not in b, schema.RuleAction.VALUE_IN_KEY.value: lambda a, b: b in a, schema.RuleAction.VALUE_NOT_IN_KEY.value: lambda a, b: b not in a, + schema.RuleAction.ALL_IN_VALUE.value: lambda a, b: compare_all_in_list(a, b), + schema.RuleAction.ANY_IN_VALUE.value: lambda a, b: compare_any_in_list(a, b), + schema.RuleAction.NONE_IN_VALUE.value: lambda a, b: compare_none_in_list(a, b), schema.RuleAction.SCHEDULE_BETWEEN_TIME_RANGE.value: lambda a, b: compare_time_range(a, b), schema.RuleAction.SCHEDULE_BETWEEN_DATETIME_RANGE.value: lambda a, b: compare_datetime_range(a, b), schema.RuleAction.SCHEDULE_BETWEEN_DAYS_OF_WEEK.value: lambda a, b: compare_days_of_week(a, b), diff --git a/aws_lambda_powertools/utilities/feature_flags/schema.py b/aws_lambda_powertools/utilities/feature_flags/schema.py index 0dc5e8d56bc..2ef4b9e29a4 100644 --- a/aws_lambda_powertools/utilities/feature_flags/schema.py +++ b/aws_lambda_powertools/utilities/feature_flags/schema.py @@ -38,6 +38,9 @@ class RuleAction(str, Enum): KEY_NOT_IN_VALUE = "KEY_NOT_IN_VALUE" VALUE_IN_KEY = "VALUE_IN_KEY" VALUE_NOT_IN_KEY = "VALUE_NOT_IN_KEY" + ALL_IN_VALUE = "ALL_IN_VALUE" + ANY_IN_VALUE = "ANY_IN_VALUE" + NONE_IN_VALUE = "NONE_IN_VALUE" SCHEDULE_BETWEEN_TIME_RANGE = "SCHEDULE_BETWEEN_TIME_RANGE" # hour:min 24 hours clock SCHEDULE_BETWEEN_DATETIME_RANGE = "SCHEDULE_BETWEEN_DATETIME_RANGE" # full datetime format, excluding timezone SCHEDULE_BETWEEN_DAYS_OF_WEEK = "SCHEDULE_BETWEEN_DAYS_OF_WEEK" # MONDAY, TUESDAY, .... see TimeValues enum diff --git a/docs/utilities/feature_flags.md b/docs/utilities/feature_flags.md index b68fcc594fb..c33efe30429 100644 --- a/docs/utilities/feature_flags.md +++ b/docs/utilities/feature_flags.md @@ -431,10 +431,13 @@ The `action` configuration can have the following values, where the expressions | **ENDSWITH** | `lambda a, b: a.endswith(b)` | | **KEY_IN_VALUE** | `lambda a, b: a in b` | | **KEY_NOT_IN_VALUE** | `lambda a, b: a not in b` | +| **ANY_IN_VALUE** | `lambda a, b: any of a is in b` | +| **ALL_IN_VALUE** | `lambda a, b: all of a is in b` | +| **NONE_IN_VALUE** | `lambda a, b: none of a is in b` | | **VALUE_IN_KEY** | `lambda a, b: b in a` | | **VALUE_NOT_IN_KEY** | `lambda a, b: b not in a` | -| **SCHEDULE_BETWEEN_TIME_RANGE** | `lambda a, b: b.start <= time(a) <= b.end` | -| **SCHEDULE_BETWEEN_DATETIME_RANGE** | `lambda a, b: b.start <= datetime(a) <= b.end` | +| **SCHEDULE_BETWEEN_TIME_RANGE** | `lambda a, b: b.start <= time(a) <= b.end` | +| **SCHEDULE_BETWEEN_DATETIME_RANGE** | `lambda a, b: b.start <= datetime(a) <= b.end` | | **SCHEDULE_BETWEEN_DAYS_OF_WEEK** | `lambda a, b: day_of_week(a) in b` | | **MODULO_RANGE** | `lambda a, b: b.start <= a % b.base <= b.end` |