Skip to content

Bug: Feature Flag Rule Conditions Values and Context Key Variables cannot have Falsy values #2051

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ajwad-shaikh opened this issue Mar 25, 2023 · 4 comments
Assignees
Labels
bug Something isn't working feature_flags Feature Flags utility

Comments

@ajwad-shaikh
Copy link
Contributor

ajwad-shaikh commented Mar 25, 2023

Expected Behaviour

Rule Conditions allow users to evaluate context attributes against values and actions defined in Rule Conditions.
The condition can easily be pivoted on a certain value in the context evaluating to falsy values. Consider the following example -

Context-

{
   "is_paid": 0,
}

Feature Flag -

{
  "sales_offer": {
    "default": false,
    "rules": {
      "unpaid_users": {
        "when_match": true,
        "conditions": [ {"action": "EQUALS", "key": "is_paid", "value": 0} ]
      }
   }
}

The values attribute should be able to accept any value except null
The condition should also honor any value for context key variable.

Current Behaviour

Definition - Falsy Values

In python, the following values evaluate to False in boolean context - these are known as falsy values.

empty_list = []
empty_string = ""
zero = 0
false_boolean = False

Falsy Values in Condition value

The values attribute in conditions cannot accept any of the falsy values, some of which are essential to framing conditions in practical use-cases.

If any of the falsy values are present in the condition - the utility throws the error below

File ~/venv/lib/python3.8/site-packages/aws_lambda_powertools/utilities/feature_flags/schema.py:330, in ConditionsValidator.validate_condition_value(condition, rule_name)
    328 value = condition.get(CONDITION_VALUE, "")
    329 if not value:
--> 330     raise SchemaValidationError(f"'value' key must not be empty, rule={rule_name}")
    331 action = condition.get(CONDITION_ACTION, "")
    333 # time actions need to be parsed to make sure date and time format is valid and timezone is recognized

SchemaValidationError: 'value' key must not be empty, rule=unpaid_users

Falsy Values in context value

The conditions simply return evaluate to false if the value for the key passed in context is falsy. These are also extremely essential to framing conditions in practical use-cases.

Example -

🚨 The condition below will evaluate to False even if the context value (0) is NOT EQUAL to condition value (1) 🚨

{
  "sales_offer": {
    "default": false,
    "rules": {
      "unpaid_users": {
        "when_match": true,
        "conditions": [ {"action": "NOT_EQUALS", "key": "is_paid", "value": 1} ]
      }
   }
}

Code snippet

Falsy Values in Condition value

// context.json

{
  "is_paid": 0
}
// features.json

{
  "sales_offer": {
    "default": false,
    "rules": {
      "unpaid_users": {
        "when_match": true,
        "conditions": [ {"action": "EQUALS", "key": "is_paid", "value": 0} ]
      }
   }
}
from aws_lambda_powertools.utilities.feature_flags import FeatureFlags, AppConfigStore

app_config = AppConfigStore(
    environment="dev",
    application="product-catalogue",
    name="features"
)

feature_flags = FeatureFlags(store=app_config)

def lambda_handler(event, context):
    # Get customer's tier from incoming request
    ctx = { "is_paid": 2 } # 1: Standard Plan | 2: Advanced Plan
    is_unpaid: bool = feature_flags.evaluate(name="sales_offer", context=ctx, default=True)

Falsy Values in Context key value

// context.json

{
  "is_paid": 0
}
// features.json

{
  "sales_offer": {
    "default": false,
    "rules": {
      "unpaid_users": {
        "when_match": true,
        "conditions": [ {"action": "NOT_EQUALS", "key": "is_paid", "value": 1} ]
      }
   }
}
from aws_lambda_powertools.utilities.feature_flags import FeatureFlags, AppConfigStore

app_config = AppConfigStore(
    environment="dev",
    application="product-catalogue",
    name="features"
)

feature_flags = FeatureFlags(store=app_config)

def lambda_handler(event, context):
    # Get customer's tier from incoming request
    ctx = { "is_paid": 2 } # 1: Standard Plan | 2: Advanced Plan
    is_unpaid: bool = feature_flags.evaluate(name="sales_offer", context=ctx, default=True)

Possible Solution

Falsy Values in condition value

Instead of
https://github.com/awslabs/aws-lambda-powertools-python/blob/f2435070d53aba8fced2901380438cc6015c6f49/aws_lambda_powertools/utilities/feature_flags/schema.py#L328-L330

suggest

value = condition.get(CONDITION_VALUE, None)
if value is None:
  raise SchemaValidationError(f"'value' key must not be null, rule={rule_name}")

Falsy Values in context key value

Instead of
https://github.com/awslabs/aws-lambda-powertools-python/blob/f2435070d53aba8fced2901380438cc6015c6f49/aws_lambda_powertools/utilities/feature_flags/feature_flags.py#L49-L51

suggest

def _match_by_action(self, action: str, condition_value: Any, context_value: Any) -> bool:
  if context_value is None:
    return False

Steps to Reproduce

Shared code snippet should reproduce the issue

AWS Lambda Powertools for Python version

latest

AWS Lambda function runtime

3.6

Packaging format used

PyPi

Debugging logs

No response

@ajwad-shaikh ajwad-shaikh added bug Something isn't working triage Pending triage from maintainers labels Mar 25, 2023
@ajwad-shaikh ajwad-shaikh changed the title Bug: Feature Flag Rule Conditions cannot have Falsy values Bug: Feature Flag Rule Conditions Values and Context Key Variables cannot have Falsy values Mar 25, 2023
@ran-isenberg
Copy link
Contributor

@ajwad-shaikh thanks for finding this.
@heitorlessa I took the liberty of opening a PR with a fix and two tests.
I dont think the change in the feature_flags.py is required, as it has already passed schema validation, so i deleted this line entirely.

see #2052

@heitorlessa
Copy link
Contributor

Looking into it... and thanks a lot @ran-isenberg for the swift PR

@heitorlessa heitorlessa self-assigned this Mar 27, 2023
@heitorlessa
Copy link
Contributor

I must say I'm impressed with the quality of this bug report @ajwad-shaikh - THANK YOU for the lengths in which you took to describe not only the problem concisely, but also potential solutions to it regardless of the complexity.

We'll revert quickly with a patch release once we're confident with the fix!

@heitorlessa heitorlessa added feature_flags Feature Flags utility pending-release Fix or implementation already in dev waiting to be released and removed triage Pending triage from maintainers labels Mar 27, 2023
@github-actions
Copy link
Contributor

This is now released under 2.11.0 version!

@github-actions github-actions bot removed the pending-release Fix or implementation already in dev waiting to be released label Mar 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working feature_flags Feature Flags utility
Projects
None yet
Development

No branches or pull requests

3 participants