1*9e94795aSAndroid Build Coastguard Worker# Copyright 2024, The Android Open Source Project 2*9e94795aSAndroid Build Coastguard Worker# 3*9e94795aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*9e94795aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*9e94795aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*9e94795aSAndroid Build Coastguard Worker# 7*9e94795aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*9e94795aSAndroid Build Coastguard Worker# 9*9e94795aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*9e94795aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*9e94795aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9e94795aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*9e94795aSAndroid Build Coastguard Worker# limitations under the License. 14*9e94795aSAndroid Build Coastguard Worker 15*9e94795aSAndroid Build Coastguard Workerimport hashlib 16*9e94795aSAndroid Build Coastguard Workerimport logging 17*9e94795aSAndroid Build Coastguard Workerimport os 18*9e94795aSAndroid Build Coastguard Worker 19*9e94795aSAndroid Build Coastguard Worker 20*9e94795aSAndroid Build Coastguard Workerdef is_feature_enabled( 21*9e94795aSAndroid Build Coastguard Worker feature_name: str, 22*9e94795aSAndroid Build Coastguard Worker user_name: str, 23*9e94795aSAndroid Build Coastguard Worker enable_flag: str = None, 24*9e94795aSAndroid Build Coastguard Worker rollout_percent: int = 100, 25*9e94795aSAndroid Build Coastguard Worker) -> bool: 26*9e94795aSAndroid Build Coastguard Worker """Determine whether the given feature is enabled. 27*9e94795aSAndroid Build Coastguard Worker 28*9e94795aSAndroid Build Coastguard Worker Whether a given feature is enabled or not depends on two flags: 1) the 29*9e94795aSAndroid Build Coastguard Worker enable_flag that explicitly enable/disable the feature and 2) the rollout_flag 30*9e94795aSAndroid Build Coastguard Worker that controls the rollout percentage. 31*9e94795aSAndroid Build Coastguard Worker 32*9e94795aSAndroid Build Coastguard Worker Args: 33*9e94795aSAndroid Build Coastguard Worker feature_name: name of the feature. 34*9e94795aSAndroid Build Coastguard Worker user_name: system user name. 35*9e94795aSAndroid Build Coastguard Worker enable_flag: name of the env var that enables/disables the feature 36*9e94795aSAndroid Build Coastguard Worker explicitly. 37*9e94795aSAndroid Build Coastguard Worker rollout_flg: name of the env var that controls the rollout percentage, the 38*9e94795aSAndroid Build Coastguard Worker value stored in the env var should be an int between 0 and 100 string 39*9e94795aSAndroid Build Coastguard Worker """ 40*9e94795aSAndroid Build Coastguard Worker if enable_flag: 41*9e94795aSAndroid Build Coastguard Worker if os.environ.get(enable_flag, "") == "false": 42*9e94795aSAndroid Build Coastguard Worker logging.info("feature: %s is disabled", feature_name) 43*9e94795aSAndroid Build Coastguard Worker return False 44*9e94795aSAndroid Build Coastguard Worker 45*9e94795aSAndroid Build Coastguard Worker if os.environ.get(enable_flag, "") == "true": 46*9e94795aSAndroid Build Coastguard Worker logging.info("feature: %s is enabled", feature_name) 47*9e94795aSAndroid Build Coastguard Worker return True 48*9e94795aSAndroid Build Coastguard Worker 49*9e94795aSAndroid Build Coastguard Worker hash_object = hashlib.sha256() 50*9e94795aSAndroid Build Coastguard Worker hash_object.update((user_name + feature_name).encode("utf-8")) 51*9e94795aSAndroid Build Coastguard Worker hash_number = int(hash_object.hexdigest(), 16) % 100 52*9e94795aSAndroid Build Coastguard Worker 53*9e94795aSAndroid Build Coastguard Worker return hash_number < rollout_percent 54