Skip to content

Commit

Permalink
feat(feature_flags): Added inequality conditions (#721)
Browse files Browse the repository at this point in the history
  • Loading branch information
gwlester authored Oct 3, 2021
1 parent 47ae544 commit 922ecf2
Show file tree
Hide file tree
Showing 4 changed files with 350 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ def _match_by_action(self, action: str, condition_value: Any, context_value: Any
return False
mapping_by_action = {
schema.RuleAction.EQUALS.value: lambda a, b: a == b,
schema.RuleAction.NOT_EQUALS.value: lambda a, b: a != b,
schema.RuleAction.KEY_GREATER_THAN_VALUE.value: lambda a, b: a > b,
schema.RuleAction.KEY_GREATER_THAN_OR_EQUAL_VALUE.value: lambda a, b: a >= b,
schema.RuleAction.KEY_LESS_THAN_VALUE.value: lambda a, b: a < b,
schema.RuleAction.KEY_LESS_THAN_OR_EQUAL_VALUE.value: lambda a, b: a <= b,
schema.RuleAction.STARTSWITH.value: lambda a, b: a.startswith(b),
schema.RuleAction.ENDSWITH.value: lambda a, b: a.endswith(b),
schema.RuleAction.IN.value: lambda a, b: a in b,
Expand Down
5 changes: 5 additions & 0 deletions aws_lambda_powertools/utilities/feature_flags/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@

class RuleAction(str, Enum):
EQUALS = "EQUALS"
NOT_EQUALS = "NOT_EQUALS"
KEY_GREATER_THAN_VALUE = "KEY_GREATER_THAN_VALUE"
KEY_GREATER_THAN_OR_EQUAL_VALUE = "KEY_GREATER_THAN_OR_EQUAL_VALUE"
KEY_LESS_THAN_VALUE = "KEY_LESS_THAN_VALUE"
KEY_LESS_THAN_OR_EQUAL_VALUE = "KEY_LESS_THAN_OR_EQUAL_VALUE"
STARTSWITH = "STARTSWITH"
ENDSWITH = "ENDSWITH"
IN = "IN"
Expand Down
5 changes: 5 additions & 0 deletions docs/utilities/feature_flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,11 @@ The `action` configuration can have the following values, where the expressions
Action | Equivalent expression
------------------------------------------------- | ---------------------------------------------------------------------------------
**EQUALS** | `lambda a, b: a == b`
**NOT_EQUALS** | `lambda a, b: a != b`
**KEY_GREATER_THAN_VALUE** | `lambda a, b: a > b`
**KEY_GREATER_THAN_OR_EQUAL_VALUE** | `lambda a, b: a >= b`
**KEY_LESS_THAN_VALUE** | `lambda a, b: a < b`
**KEY_LESS_THAN_OR_EQUAL_VALUE** | `lambda a, b: a <= b`
**STARTSWITH** | `lambda a, b: a.startswith(b)`
**ENDSWITH** | `lambda a, b: a.endswith(b)`
**KEY_IN_VALUE** | `lambda a, b: a in b`
Expand Down
335 changes: 335 additions & 0 deletions tests/functional/feature_flags/test_feature_flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -802,3 +802,338 @@ def test_get_configuration_with_envelope_and_raw(mocker, config):

assert "log_level" in config
assert "log_level" not in features_config

##
## Inequality test cases
##

# Test not equals
def test_flags_not_equal_no_match(mocker, config):
expected_value = False
mocked_app_config_schema = {
"my_feature": {
"default": expected_value,
"rules": {
"tenant id not equals 345345435": {
"when_match": True,
"conditions": [
{
"action": RuleAction.NOT_EQUALS.value,
"key": "tenant_id",
"value": "345345435",
}
],
}
},
}
}
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "345345435", "username": "a"}, default=False)
assert toggle == expected_value

def test_flags_not_equal_match(mocker, config):
expected_value = True
mocked_app_config_schema = {
"my_feature": {
"default": expected_value,
"rules": {
"tenant id not equals 345345435": {
"when_match": True,
"conditions": [
{
"action": RuleAction.NOT_EQUALS.value,
"key": "tenant_id",
"value": "345345435",
}
],
}
},
}
}
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "", "username": "a"}, default=False)
assert toggle == expected_value


# Test less than
def test_flags_less_than_no_match_1(mocker, config):
expected_value = False
mocked_app_config_schema = {
"my_feature": {
"default": expected_value,
"rules": {
"Date less than 2021.10.31": {
"when_match": True,
"conditions": [
{
"action": RuleAction.KEY_LESS_THAN_VALUE.value,
"key": "current_date",
"value": "2021.10.31",
}
],
}
},
}
}
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "345345435", "username": "a", "current_date": "2021.12.25"}, default=False)
assert toggle == expected_value

def test_flags_less_than_no_match_2(mocker, config):
expected_value = False
mocked_app_config_schema = {
"my_feature": {
"default": expected_value,
"rules": {
"Date less than 2021.10.31": {
"when_match": True,
"conditions": [
{
"action": RuleAction.KEY_LESS_THAN_VALUE.value,
"key": "current_date",
"value": "2021.10.31",
}
],
}
},
}
}
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "345345435", "username": "a", "current_date": "2021.10.31"}, default=False)
assert toggle == expected_value

def test_flags_less_than_match(mocker, config):
expected_value = True
mocked_app_config_schema = {
"my_feature": {
"default": expected_value,
"rules": {
"Date less than 2021.10.31": {
"when_match": True,
"conditions": [
{
"action": RuleAction.KEY_LESS_THAN_VALUE.value,
"key": "current_date",
"value": "2021.10.31",
}
],
}
},
}
}
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "345345435", "username": "a", "current_date": "2021.04.01"}, default=False)
assert toggle == expected_value

# Test less than or equal to
def test_flags_less_than_or_equal_no_match(mocker, config):
expected_value = False
mocked_app_config_schema = {
"my_feature": {
"default": expected_value,
"rules": {
"Date less than or equal 2021.10.31": {
"when_match": True,
"conditions": [
{
"action": RuleAction.KEY_LESS_THAN_OR_EQUAL_VALUE.value,
"key": "current_date",
"value": "2021.10.31",
}
],
}
},
}
}
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "345345435", "username": "a", "current_date": "2021.12.25"}, default=False)
assert toggle == expected_value

def test_flags_less_than_or_equal_match_1(mocker, config):
expected_value = True
mocked_app_config_schema = {
"my_feature": {
"default": expected_value,
"rules": {
"Date less than or equal 2021.10.31": {
"when_match": True,
"conditions": [
{
"action": RuleAction.KEY_LESS_THAN_OR_EQUAL_VALUE.value,
"key": "current_date",
"value": "2021.10.31",
}
],
}
},
}
}
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "345345435", "username": "a", "current_date": "2021.04.01"}, default=False)
assert toggle == expected_value


def test_flags_less_than_or_equal_match_2(mocker, config):
expected_value = True
mocked_app_config_schema = {
"my_feature": {
"default": expected_value,
"rules": {
"Date less than or equal 2021.10.31": {
"when_match": True,
"conditions": [
{
"action": RuleAction.KEY_LESS_THAN_OR_EQUAL_VALUE.value,
"key": "current_date",
"value": "2021.10.31",
}
],
}
},
}
}
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "345345435", "username": "a", "current_date": "2021.10.31"}, default=False)
assert toggle == expected_value

# Test greater than
def test_flags_greater_than_no_match_1(mocker, config):
expected_value = False
mocked_app_config_schema = {
"my_feature": {
"default": expected_value,
"rules": {
"Date greater than 2021.10.31": {
"when_match": True,
"conditions": [
{
"action": RuleAction.KEY_GREATER_THAN_VALUE.value,
"key": "current_date",
"value": "2021.10.31",
}
],
}
},
}
}
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "345345435", "username": "a", "current_date": "2021.04.01"}, default=False)
assert toggle == expected_value

def test_flags_greater_than_no_match_2(mocker, config):
expected_value = False
mocked_app_config_schema = {
"my_feature": {
"default": expected_value,
"rules": {
"Date greater than 2021.10.31": {
"when_match": True,
"conditions": [
{
"action": RuleAction.KEY_GREATER_THAN_VALUE.value,
"key": "current_date",
"value": "2021.10.31",
}
],
}
},
}
}
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "345345435", "username": "a", "current_date": "2021.10.31"}, default=False)
assert toggle == expected_value

def test_flags_greater_than_match(mocker, config):
expected_value = True
mocked_app_config_schema = {
"my_feature": {
"default": expected_value,
"rules": {
"Date greater than 2021.10.31": {
"when_match": True,
"conditions": [
{
"action": RuleAction.KEY_GREATER_THAN_VALUE.value,
"key": "current_date",
"value": "2021.10.31",
}
],
}
},
}
}
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "345345435", "username": "a", "current_date": "2021.12.25"}, default=False)
assert toggle == expected_value

# Test greater than or equal to
def test_flags_greater_than_or_equal_no_match(mocker, config):
expected_value = False
mocked_app_config_schema = {
"my_feature": {
"default": expected_value,
"rules": {
"Date greater than or equal 2021.10.31": {
"when_match": True,
"conditions": [
{
"action": RuleAction.KEY_GREATER_THAN_OR_EQUAL_VALUE.value,
"key": "current_date",
"value": "2021.10.31",
}
],
}
},
}
}
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "345345435", "username": "a", "current_date": "2021.04.01"}, default=False)
assert toggle == expected_value

def test_flags_greater_than_or_equal_match_1(mocker, config):
expected_value = True
mocked_app_config_schema = {
"my_feature": {
"default": expected_value,
"rules": {
"Date greater than or equal 2021.10.31": {
"when_match": True,
"conditions": [
{
"action": RuleAction.KEY_GREATER_THAN_OR_EQUAL_VALUE.value,
"key": "current_date",
"value": "2021.10.31",
}
],
}
},
}
}
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "345345435", "username": "a", "current_date": "2021.12.25"}, default=False)
assert toggle == expected_value


def test_flags_greater_than_or_equal_match_2(mocker, config):
expected_value = True
mocked_app_config_schema = {
"my_feature": {
"default": expected_value,
"rules": {
"Date greater than or equal 2021.10.31": {
"when_match": True,
"conditions": [
{
"action": RuleAction.KEY_GREATER_THAN_OR_EQUAL_VALUE.value,
"key": "current_date",
"value": "2021.10.31",
}
],
}
},
}
}
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "345345435", "username": "a", "current_date": "2021.10.31"}, default=False)
assert toggle == expected_value

0 comments on commit 922ecf2

Please sign in to comment.