@@ -49,6 +49,29 @@ def _match_by_action(self, action: str, restriction_value: Any, context_value: A
4949 self ._logger .error (f"caught exception while matching action, action={ action } , exception={ str (exc )} " )
5050 return False
5151
52+ def _is_rule_matched (self , feature_name : str , rule : Dict [str , Any ], rules_context : Dict [str , Any ]) -> bool :
53+ rule_name = rule .get (schema .RULE_NAME_KEY , "" )
54+ rule_default_value = rule .get (schema .RULE_DEFAULT_VALUE )
55+ restrictions : Dict [str , str ] = rule .get (schema .RESTRICTIONS_KEY )
56+
57+ for restriction in restrictions :
58+ context_value = rules_context .get (restriction .get (schema .RESTRICTION_KEY ))
59+ if not self ._match_by_action (
60+ restriction .get (schema .RESTRICTION_ACTION ),
61+ restriction .get (schema .RESTRICTION_VALUE ),
62+ context_value ,
63+ ):
64+ logger .debug (
65+ f"rule did not match action, rule_name={ rule_name } , rule_default_value={ rule_default_value } , feature_name={ feature_name } , context_value={ str (context_value )} " # noqa: E501
66+ )
67+ # context doesn't match restriction
68+ return False
69+ # if we got here, all restrictions match
70+ logger .debug (
71+ f"rule matched, rule_name={ rule_name } , rule_default_value={ rule_default_value } , feature_name={ feature_name } " # noqa: E501
72+ )
73+ return True
74+
5275 def _handle_rules (
5376 self ,
5477 * ,
@@ -58,34 +81,14 @@ def _handle_rules(
5881 rules : List [Dict [str , Any ]],
5982 ) -> bool :
6083 for rule in rules :
61- rule_name = rule .get (schema .RULE_NAME_KEY , "" )
6284 rule_default_value = rule .get (schema .RULE_DEFAULT_VALUE )
63- is_match = True
64- restrictions : Dict [str , str ] = rule .get (schema .RESTRICTIONS_KEY )
65-
66- for restriction in restrictions :
67- context_value = rules_context .get (restriction .get (schema .RESTRICTION_KEY ))
68- if not self ._match_by_action (
69- restriction .get (schema .RESTRICTION_ACTION ),
70- restriction .get (schema .RESTRICTION_VALUE ),
71- context_value ,
72- ):
73- logger .debug (
74- f"rule did not match action, rule_name={ rule_name } , rule_default_value={ rule_default_value } , feature_name={ feature_name } , context_value={ str (context_value )} " # noqa: E501
75- )
76- is_match = False # rules doesn't match restriction
77- break
78- # if we got here, all restrictions match
79- if is_match :
80- logger .debug (
81- f"rule matched, rule_name={ rule_name } , rule_default_value={ rule_default_value } , feature_name={ feature_name } " # noqa: E501
82- )
85+ if self ._is_rule_matched (feature_name , rule , rules_context ):
8386 return rule_default_value
84- # no rule matched, return default value of feature
85- logger .debug (
86- f"no rule matched, returning default value of feature, feature_default_value={ feature_default_value } , feature_name={ feature_name } " # noqa: E501
87- )
88- return feature_default_value
87+ # no rule matched, return default value of feature
88+ logger .debug (
89+ f"no rule matched, returning default value of feature, feature_default_value={ feature_default_value } , feature_name={ feature_name } " # noqa: E501
90+ )
91+ return feature_default_value
8992
9093 def get_configuration (self ) -> Dict [str , Any ]:
9194 """Get configuration string from AWs AppConfig and returned the parsed JSON dictionary
@@ -162,3 +165,39 @@ def get_feature_toggle(self, *, feature_name: str, rules_context: Dict[str, Any]
162165 feature_default_value = feature_default_value ,
163166 rules = rules_list ,
164167 )
168+
169+ def get_all_enabled_feature_toggles (self , * , rules_context : Dict [str , Any ]) -> List [str ]:
170+ """Get all enabled feature toggles while also taking into account rule_context (when a feature has defined rules)
171+
172+ Args:
173+ rules_context (Dict[str, Any]): dict of attributes that you would like to match the rules
174+ against, can be {'tenant_id: 'X', 'username':' 'Y', 'region': 'Z'} etc.
175+
176+ Returns:
177+ List[str]: a list of all features name that are enabled by also taking into account
178+ rule_context (when a feature has defined rules)
179+ """
180+ try :
181+ toggles_dict : Dict [str , Any ] = self .get_configuration ()
182+ except ConfigurationException :
183+ logger .error ("unable to get feature toggles JSON" ) # noqa: E501
184+ return []
185+ ret_list = []
186+ features : Dict [str , Any ] = toggles_dict .get (schema .FEATURES_KEY , {})
187+ for feature_name , feature_dict_def in features .items ():
188+ rules_list = feature_dict_def .get (schema .RULES_KEY , [])
189+ feature_default_value = feature_dict_def .get (schema .FEATURE_DEFAULT_VAL_KEY )
190+ if feature_default_value and not rules_list :
191+ self ._logger .debug (
192+ f"feature is enabled by default and has no defined rules, feature_name={ feature_name } "
193+ )
194+ ret_list .append (feature_name )
195+ elif self ._handle_rules (
196+ feature_name = feature_name ,
197+ rules_context = rules_context ,
198+ feature_default_value = feature_default_value ,
199+ rules = rules_list ,
200+ ):
201+ self ._logger .debug (f"feature's calculated value is True, feature_name={ feature_name } " )
202+ ret_list .append (feature_name )
203+ return ret_list
0 commit comments