Skip to content

Commit a872814

Browse files
committed
refactor: remove RULE_KEY, exception & rule test consistency
1 parent 387da38 commit a872814

File tree

2 files changed

+55
-67
lines changed

2 files changed

+55
-67
lines changed

aws_lambda_powertools/utilities/feature_flags/schema.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
RULES_KEY = "rules"
1212
FEATURE_DEFAULT_VAL_KEY = "default"
1313
CONDITIONS_KEY = "conditions"
14-
RULE_NAME_KEY = "rule_name"
1514
RULE_DEFAULT_VALUE = "when_match"
1615
CONDITION_KEY = "key"
1716
CONDITION_VALUE = "value"
@@ -80,19 +79,18 @@ def validate(self):
8079
conditions = ConditionsValidator(rule=rule, rule_name=rule_name)
8180
conditions.validate()
8281

83-
def validate_rule(self, rule, rule_name, feature_name):
82+
@staticmethod
83+
def validate_rule(rule, rule_name, feature_name):
8484
if not rule or not isinstance(rule, dict):
8585
raise ConfigurationError(f"Feature rule must be a dictionary, feature_name={feature_name}")
8686

87-
self.validate_rule_name(rule_name=rule_name, feature_name=feature_name)
88-
self.validate_rule_default_value(rule=rule, rule_name=rule_name)
87+
RulesValidator.validate_rule_name(rule_name=rule_name, feature_name=feature_name)
88+
RulesValidator.validate_rule_default_value(rule=rule, rule_name=rule_name)
8989

9090
@staticmethod
9191
def validate_rule_name(rule_name: str, feature_name: str):
9292
if not rule_name or not isinstance(rule_name, str):
93-
raise ConfigurationError(
94-
f"'rule_name' key must be present and have a non-empty string, feature_name={feature_name}"
95-
)
93+
raise ConfigurationError(f"Rule name key must have a non-empty string, feature_name={feature_name}")
9694

9795
@staticmethod
9896
def validate_rule_default_value(rule: Dict, rule_name: str):
@@ -116,7 +114,7 @@ def validate(self):
116114
@staticmethod
117115
def validate_condition(rule_name: str, condition: Dict[str, str]) -> None:
118116
if not condition or not isinstance(condition, dict):
119-
raise ConfigurationError(f"Invalid condition type, not a dictionary, rule_name={rule_name}")
117+
raise ConfigurationError(f"Feature rule condition must be a dictionary, rule_name={rule_name}")
120118

121119
ConditionsValidator.validate_condition_action(condition=condition, rule_name=rule_name)
122120
ConditionsValidator.validate_condition_key(condition=condition, rule_name=rule_name)
@@ -126,16 +124,19 @@ def validate_condition(rule_name: str, condition: Dict[str, str]) -> None:
126124
def validate_condition_action(condition: Dict[str, Any], rule_name: str):
127125
action = condition.get(CONDITION_ACTION, "")
128126
if action not in RuleAction.__members__:
129-
raise ConfigurationError(f"Invalid action value, rule_name={rule_name}, action={action}")
127+
allowed_values = [_action.value for _action in RuleAction]
128+
raise ConfigurationError(
129+
f"'action' value must be either {allowed_values}, rule_name={rule_name}, action={action}"
130+
)
130131

131132
@staticmethod
132133
def validate_condition_key(condition: Dict[str, Any], rule_name: str):
133134
key = condition.get(CONDITION_KEY, "")
134135
if not key or not isinstance(key, str):
135-
raise ConfigurationError(f"Invalid key value, key has to be a non empty string, rule_name={rule_name}")
136+
raise ConfigurationError(f"'key' value must be a non empty string, rule_name={rule_name}")
136137

137138
@staticmethod
138139
def validate_condition_value(condition: Dict[str, Any], rule_name: str):
139140
value = condition.get(CONDITION_VALUE, "")
140141
if not value:
141-
raise ConfigurationError(f"Missing condition value, rule_name={rule_name}")
142+
raise ConfigurationError(f"'value' key must not be empty, rule_name={rule_name}")

tests/functional/feature_toggles/test_schema_validation.py

Lines changed: 43 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
FEATURE_DEFAULT_VAL_KEY,
1212
FEATURES_KEY,
1313
RULE_DEFAULT_VALUE,
14-
RULE_NAME_KEY,
1514
RULES_KEY,
1615
ConditionsValidator,
1716
RuleAction,
@@ -116,12 +115,11 @@ def test_invalid_rule():
116115
FEATURES_KEY: {
117116
"my_feature": {
118117
FEATURE_DEFAULT_VAL_KEY: False,
119-
RULES_KEY: [
120-
{
121-
RULE_NAME_KEY: "tenant id equals 345345435",
118+
RULES_KEY: {
119+
"tenant id equals 345345435": {
122120
RULE_DEFAULT_VALUE: "False",
123-
},
124-
],
121+
}
122+
},
125123
}
126124
}
127125
}
@@ -134,12 +132,11 @@ def test_invalid_rule():
134132
FEATURES_KEY: {
135133
"my_feature": {
136134
FEATURE_DEFAULT_VAL_KEY: False,
137-
RULES_KEY: [
138-
{
139-
RULE_NAME_KEY: "tenant id equals 345345435",
135+
RULES_KEY: {
136+
"tenant id equals 345345435": {
140137
RULE_DEFAULT_VALUE: False,
141-
},
142-
],
138+
}
139+
},
143140
}
144141
}
145142
}
@@ -152,9 +149,9 @@ def test_invalid_rule():
152149
FEATURES_KEY: {
153150
"my_feature": {
154151
FEATURE_DEFAULT_VAL_KEY: False,
155-
RULES_KEY: [
156-
{RULE_NAME_KEY: "tenant id equals 345345435", RULE_DEFAULT_VALUE: False, CONDITIONS_KEY: []},
157-
],
152+
RULES_KEY: {
153+
"tenant id equals 345345435": {RULE_DEFAULT_VALUE: False, CONDITIONS_KEY: []},
154+
},
158155
}
159156
}
160157
}
@@ -167,9 +164,9 @@ def test_invalid_rule():
167164
FEATURES_KEY: {
168165
"my_feature": {
169166
FEATURE_DEFAULT_VAL_KEY: False,
170-
RULES_KEY: [
171-
{RULE_NAME_KEY: "tenant id equals 345345435", RULE_DEFAULT_VALUE: False, CONDITIONS_KEY: {}},
172-
],
167+
RULES_KEY: {
168+
"tenant id equals 345345435": {RULE_DEFAULT_VALUE: False, CONDITIONS_KEY: {}},
169+
},
173170
}
174171
}
175172
}
@@ -184,13 +181,12 @@ def test_invalid_condition():
184181
FEATURES_KEY: {
185182
"my_feature": {
186183
FEATURE_DEFAULT_VAL_KEY: False,
187-
RULES_KEY: [
188-
{
189-
RULE_NAME_KEY: "tenant id equals 345345435",
184+
RULES_KEY: {
185+
"tenant id equals 345345435": {
190186
RULE_DEFAULT_VALUE: False,
191187
CONDITIONS_KEY: {CONDITION_ACTION: "stuff", CONDITION_KEY: "a", CONDITION_VALUE: "a"},
192-
},
193-
],
188+
}
189+
},
194190
}
195191
}
196192
}
@@ -203,13 +199,12 @@ def test_invalid_condition():
203199
FEATURES_KEY: {
204200
"my_feature": {
205201
FEATURE_DEFAULT_VAL_KEY: False,
206-
RULES_KEY: [
207-
{
208-
RULE_NAME_KEY: "tenant id equals 345345435",
202+
RULES_KEY: {
203+
"tenant id equals 345345435": {
209204
RULE_DEFAULT_VALUE: False,
210205
CONDITIONS_KEY: {CONDITION_ACTION: RuleAction.EQUALS.value},
211-
},
212-
],
206+
}
207+
},
213208
}
214209
}
215210
}
@@ -222,17 +217,16 @@ def test_invalid_condition():
222217
FEATURES_KEY: {
223218
"my_feature": {
224219
FEATURE_DEFAULT_VAL_KEY: False,
225-
RULES_KEY: [
226-
{
227-
RULE_NAME_KEY: "tenant id equals 345345435",
220+
RULES_KEY: {
221+
"tenant id equals 345345435": {
228222
RULE_DEFAULT_VALUE: False,
229223
CONDITIONS_KEY: {
230224
CONDITION_ACTION: RuleAction.EQUALS.value,
231225
CONDITION_KEY: 5,
232226
CONDITION_VALUE: "a",
233227
},
234-
},
235-
],
228+
}
229+
},
236230
}
237231
}
238232
}
@@ -286,7 +280,7 @@ def test_validate_condition_invalid_condition_type():
286280

287281
# WHEN calling validate_condition
288282
# THEN raise ConfigurationError
289-
with pytest.raises(ConfigurationError, match="Invalid condition type"):
283+
with pytest.raises(ConfigurationError, match="Feature rule condition must be a dictionary"):
290284
ConditionsValidator.validate_condition(condition=condition, rule_name="dummy")
291285

292286

@@ -296,7 +290,7 @@ def test_validate_condition_invalid_condition_action():
296290

297291
# WHEN calling validate_condition
298292
# THEN raise ConfigurationError
299-
with pytest.raises(ConfigurationError, match="Invalid action value"):
293+
with pytest.raises(ConfigurationError, match="'action' value must be either"):
300294
ConditionsValidator.validate_condition_action(condition=condition, rule_name="dummy")
301295

302296

@@ -306,7 +300,7 @@ def test_validate_condition_invalid_condition_key():
306300

307301
# WHEN calling validate_condition
308302
# THEN raise ConfigurationError
309-
with pytest.raises(ConfigurationError, match="Invalid key value"):
303+
with pytest.raises(ConfigurationError, match="'key' value must be a non empty string"):
310304
ConditionsValidator.validate_condition_key(condition=condition, rule_name="dummy")
311305

312306

@@ -318,28 +312,21 @@ def test_validate_condition_missing_condition_value():
318312
}
319313

320314
# WHEN calling validate_condition
321-
with pytest.raises(ConfigurationError, match="Missing condition value"):
315+
with pytest.raises(ConfigurationError, match="'value' key must not be empty"):
322316
ConditionsValidator.validate_condition_value(condition=condition, rule_name="dummy")
323317

324318

325-
def test_new_rule_format():
326-
new_features = {
327-
"my_feature": {
328-
"default": True,
329-
"rules": {
330-
"tenant id equals 345345435": {
331-
"when_match": False,
332-
"conditions": [
333-
{
334-
"action": "EQUALS",
335-
"key": "tenant_id",
336-
"value": "345345435",
337-
}
338-
],
339-
},
340-
},
341-
}
342-
}
319+
def test_validate_rule_invalid_rule_type():
320+
# GIVEN an invalid rule type of empty list
321+
# WHEN calling validate_rule
322+
# THEN raise ConfigurationError
323+
with pytest.raises(ConfigurationError, match="Feature rule must be a dictionary"):
324+
RulesValidator.validate_rule(rule=[], rule_name="dummy", feature_name="dummy")
343325

344-
rules = RulesValidator(feature=new_features)
345-
rules.validate()
326+
327+
def test_validate_rule_invalid_rule_name():
328+
# GIVEN a rule name is empty
329+
# WHEN calling validate_rule_name
330+
# THEN raise ConfigurationError
331+
with pytest.raises(ConfigurationError, match="Rule name key must have a non-empty string"):
332+
RulesValidator.validate_rule_name(rule_name="", feature_name="dummy")

0 commit comments

Comments
 (0)