def get_feature_toggles(api_url, client_access_token, defer=None): # hide INFO logging from UnleashClient logger = logging.getLogger() default_logging = logger.level logger.setLevel(logging.ERROR) defer(lambda: logger.setLevel(default_logging)) # create temporary cache dir cache_dir = tempfile.mkdtemp() defer(lambda: shutil.rmtree(cache_dir)) # create Unleash client headers = {"Authorization": f"Bearer {client_access_token}"} client = UnleashClient( url=api_url, app_name="qontract-reconcile", custom_headers=headers, cache_directory=cache_dir, ) client.initialize_client() defer(client.destroy) return { k: "enabled" if v.enabled else "disabled" for k, v in client.features.items() }
class Unleash(): def __init__(self, app=None): # Constants self.name = 'unleash_client' self.client = None # Setup self.app = app if app is not None: self.init_app(app) def init_app(self, app): # Populate required arguments. unleash_args = { 'url': app.config['UNLEASH_URL'], 'app_name': app.config['UNLEASH_APP_NAME'], 'environment': app.config['UNLEASH_ENVIRONMENT'] } # Populate optional arguments. populated_optional_args = filter(lambda x: x in app.config, CONFIG_MAPPING.keys()) for option in populated_optional_args: unleash_args[CONFIG_MAPPING[option]] = app.config[option] # Set up client. self.client = UnleashClient(**unleash_args) self.client.initialize_client() app.extensions = getattr(app, 'extensions', {}) app.extensions['Unleash'] = self
def unleash_client(): unleash_client = UnleashClient(URL, APP_NAME, refresh_interval=REFRESH_INTERVAL, metrics_interval=METRICS_INTERVAL) yield unleash_client unleash_client.destroy()
def unleash_client(tmpdir): unleash_client = UnleashClient(URL, APP_NAME, refresh_interval=REFRESH_INTERVAL, metrics_interval=METRICS_INTERVAL, cache_directory=tmpdir.dirname) yield unleash_client unleash_client.destroy()
def unleash_client_toggle_only(): unleash_client = UnleashClient(URL, APP_NAME, refresh_interval=REFRESH_INTERVAL, metrics_interval=METRICS_INTERVAL, disable_registration=True, disable_metrics=True) yield unleash_client unleash_client.destroy()
def unleash_client_project(cache): unleash_client = UnleashClient( URL, APP_NAME, refresh_interval=REFRESH_INTERVAL, metrics_interval=METRICS_INTERVAL, cache=cache, project_name=PROJECT_NAME ) yield unleash_client unleash_client.destroy()
def test_uc_get_variant(): # Set up API responses.add(responses.POST, URL + REGISTER_URL, json={}, status=202) responses.add(responses.GET, URL + FEATURES_URL, json=MOCK_FEATURE_RESPONSE, status=200) responses.add(responses.POST, URL + METRICS_URL, json={}, status=202) unleash_client = UnleashClient(URL, APP_NAME) # Create Unleash client and check initial load unleash_client.initialize_client() time.sleep(1) # If feature flag is on. variant = unleash_client.get_variant("testVariations", context={'userId': '2'}) assert variant['name'] == 'VarA' assert variant['enabled'] # If feature flag is not. variant = unleash_client.get_variant("testVariations", context={'userId': '3'}) assert variant['name'] == 'disabled' assert not variant['enabled'] unleash_client.destroy()
def test_uc_cache_bootstrap_file(cache): # Set up cache test_file = Path(Path(__file__).parent.resolve(), '..', 'utilities', 'mocks', 'mock_bootstrap.json') cache.bootstrap_from_file(initial_config_file=test_file) # Check bootstrapping unleash_client = UnleashClient( URL, APP_NAME, refresh_interval=REFRESH_INTERVAL, metrics_interval=METRICS_INTERVAL, cache=cache ) assert len(unleash_client.features) >= 1 assert unleash_client.is_enabled("ivan-project")
def test_uc_cache_bootstrap_url(cache): # Set up API responses.add(responses.GET, URL + FEATURES_URL, json=MOCK_FEATURE_RESPONSE, status=200, headers={'etag': ETAG_VALUE}) # Set up cache cache.bootstrap_from_url(initial_config_url=URL + FEATURES_URL) # Check bootstrapping unleash_client = UnleashClient( URL, APP_NAME, refresh_interval=REFRESH_INTERVAL, metrics_interval=METRICS_INTERVAL, cache=cache ) assert len(unleash_client.features) >= 4 assert unleash_client.is_enabled("testFlag")
def test_UC_initialize_full(): client = UnleashClient(URL, APP_NAME, INSTANCE_ID, REFRESH_INTERVAL, METRICS_INTERVAL, DISABLE_METRICS, CUSTOM_HEADERS) assert client.unleash_instance_id == INSTANCE_ID assert client.unleash_refresh_interval == REFRESH_INTERVAL assert client.unleash_metrics_interval == METRICS_INTERVAL assert client.unleash_disable_metrics == DISABLE_METRICS assert client.unleash_custom_headers == CUSTOM_HEADERS
def get_feature_toggle_state(integration_name, defer=None): api_url = os.environ.get("UNLEASH_API_URL") client_access_token = os.environ.get("UNLEASH_CLIENT_ACCESS_TOKEN") if not (api_url and client_access_token): return True # create temporary cache dir cache_dir = tempfile.mkdtemp() defer(lambda: shutil.rmtree(cache_dir)) # hide INFO logging from UnleashClient with log_lock: logger = logging.getLogger() default_logging = logger.level logger.setLevel(logging.ERROR) # create Unleash client headers = {"Authorization": f"Bearer {client_access_token}"} client = UnleashClient( url=api_url, app_name="qontract-reconcile", custom_headers=headers, cache_directory=cache_dir, ) client.initialize_client() # get feature toggle state state = client.is_enabled(integration_name, fallback_function=get_feature_toggle_default) client.destroy() logger.setLevel(default_logging) return state
def unleash_client_nodestroy(cache): unleash_client = UnleashClient( URL, APP_NAME, refresh_interval=REFRESH_INTERVAL, metrics_interval=METRICS_INTERVAL, cache=cache ) yield unleash_client
def test_uc_customstrategy_depredationwarning(): responses.add(responses.POST, URL + REGISTER_URL, json={}, status=202) responses.add(responses.GET, URL + FEATURES_URL, json=MOCK_CUSTOM_STRATEGY, status=200) responses.add(responses.POST, URL + METRICS_URL, json={}, status=202) custom_strategies_dict = {"amIACat": CatTest, "amIADog": DogTest} unleash_client = UnleashClient(URL, APP_NAME, environment="prod", custom_strategies=custom_strategies_dict) unleash_client.initialize_client() # Check a toggle that contains an outdated custom strategy assert unleash_client.is_enabled("CustomToggleWarning", {"sound": "meow"})
def test_UC_initialize_full(): client = UnleashClient(URL, APP_NAME, ENVIRONMENT, INSTANCE_ID, REFRESH_INTERVAL, METRICS_INTERVAL, DISABLE_METRICS, DISABLE_REGISTRATION, CUSTOM_HEADERS, CUSTOM_OPTIONS) assert client.unleash_instance_id == INSTANCE_ID assert client.unleash_refresh_interval == REFRESH_INTERVAL assert client.unleash_metrics_interval == METRICS_INTERVAL assert client.unleash_disable_metrics == DISABLE_METRICS assert client.unleash_disable_registration == DISABLE_REGISTRATION assert client.unleash_custom_headers == CUSTOM_HEADERS assert client.unleash_custom_options == CUSTOM_OPTIONS
def test_uc_cache_bootstrap_dict(cache): # Set up API responses.add(responses.POST, URL + REGISTER_URL, json={}, status=202) responses.add(responses.GET, URL + FEATURES_URL, json=MOCK_FEATURE_RESPONSE, status=200, headers={'etag': ETAG_VALUE}) responses.add(responses.POST, URL + METRICS_URL, json={}, status=202) # Set up cache cache.bootstrap_from_dict(initial_config=MOCK_FEATURE_RESPONSE_PROJECT) # Check bootstrapping unleash_client = UnleashClient( URL, APP_NAME, refresh_interval=REFRESH_INTERVAL, metrics_interval=METRICS_INTERVAL, cache=cache ) assert len(unleash_client.features) == 1 assert unleash_client.is_enabled("ivan-project") # Create Unleash client and check initial load unleash_client.initialize_client() time.sleep(1) assert unleash_client.is_initialized assert len(unleash_client.features) >= 4 assert unleash_client.is_enabled("testFlag")
def get_unleash_strategies(api_url, token, strategy_names, defer=None): # create strategy mapping unleash_strategies = {name: strategies.Strategy for name in strategy_names} # create temporary cache dir cache_dir = tempfile.mkdtemp() defer(lambda: shutil.rmtree(cache_dir)) # hide INFO logging from UnleashClient with log_lock: logger = logging.getLogger() default_logging = logger.level logger.setLevel(logging.ERROR) # create Unleash client headers = {"Authorization": f"Bearer {token}"} client = UnleashClient( url=api_url, app_name="qontract-reconcile", custom_headers=headers, cache_directory=cache_dir, custom_strategies=unleash_strategies, ) client.initialize_client() strats = { name: toggle.strategies for name, toggle in client.features.items() } client.destroy() logger.setLevel(default_logging) return strats
def test_uc_is_enabled_with_context(): # Set up API responses.add(responses.POST, URL + REGISTER_URL, json={}, status=202) responses.add(responses.GET, URL + FEATURES_URL, json=MOCK_FEATURE_RESPONSE, status=200) responses.add(responses.POST, URL + METRICS_URL, json={}, status=202) custom_strategies_dict = { "custom-context": EnvironmentStrategy } unleash_client = UnleashClient(URL, APP_NAME, environment='prod', custom_strategies=custom_strategies_dict) # Create Unleash client and check initial load unleash_client.initialize_client() time.sleep(1) assert unleash_client.is_enabled("testContextFlag") unleash_client.destroy()
def __get_unleash_client(): """ Initialize the client if client is None Else Return the established client """ if FeatureToggles.__enable_toggle_service: if FeatureToggles.__client is None: FeatureToggles.__client = UnleashClient( url=FeatureToggles.__url, app_name=FeatureToggles.__app_name, instance_id=FeatureToggles.__instance_id, cas_name=FeatureToggles.__cas_name, environment=FeatureToggles.__environment, redis_host=FeatureToggles.__redis_host, redis_port=FeatureToggles.__redis_port, redis_db=FeatureToggles.__redis_db) FeatureToggles.__client.initialize_client() else: FeatureToggles.__client = FeatureTogglesFromConst() return FeatureToggles.__client
def test_uc_custom_strategy(): # Set up API responses.add(responses.POST, URL + REGISTER_URL, json={}, status=202) responses.add(responses.GET, URL + FEATURES_URL, json=MOCK_CUSTOM_STRATEGY, status=200) responses.add(responses.POST, URL + METRICS_URL, json={}, status=202) custom_strategies_dict = {"amIACat": CatTest} unleash_client = UnleashClient(URL, APP_NAME, custom_strategies=custom_strategies_dict) # Create Unleash client and check initial load unleash_client.initialize_client() assert unleash_client.is_enabled("CustomToggle", {"sound": "meow"}) assert not unleash_client.is_enabled("CustomToggle", {"sound": "bark"})
def test_uc_customstrategy_happypath(recwarn): responses.add(responses.POST, URL + REGISTER_URL, json={}, status=202) responses.add(responses.GET, URL + FEATURES_URL, json=MOCK_CUSTOM_STRATEGY, status=200) responses.add(responses.POST, URL + METRICS_URL, json={}, status=202) custom_strategies_dict = {"amIACat": CatTest, "amIADog": DogTest} unleash_client = UnleashClient(URL, APP_NAME, environment="prod", custom_strategies=custom_strategies_dict) unleash_client.initialize_client() # Check custom strategy. assert unleash_client.is_enabled("CustomToggle", {"sound": "meow"}) assert not unleash_client.is_enabled("CustomToggle", {"sound": "bark"}) # Check warning on deprecated strategy. assert len(recwarn) == 1 assert recwarn.pop(DeprecationWarning)
def test_uc_with_network_error(): unleash_client = UnleashClient("https://thisisavalidurl.com", APP_NAME) unleash_client.initialize_client() assert unleash_client.is_enabled
def test_uc_with_invalid_url(): unleash_client = UnleashClient("thisisnotavalidurl", APP_NAME) with pytest.raises(ValueError): unleash_client.initialize_client()
def test_uc_not_initialized_getvariant(): unleash_client = UnleashClient(URL, APP_NAME) variant = unleash_client.get_variant("ThisFlagDoesn'tExist") assert not variant['enabled'] assert variant['name'] == 'disabled'
def test_uc_not_initialized_isenabled(): unleash_client = UnleashClient(URL, APP_NAME) assert not unleash_client.is_enabled("ThisFlagDoesn'tExist") assert unleash_client.is_enabled("ThisFlagDoesn'tExist", fallback_function=lambda x, y: True)
def test_UC_type_violation(): client = UnleashClient(URL, APP_NAME, refresh_interval="60") assert client.unleash_url == URL assert client.unleash_app_name == APP_NAME assert client.unleash_refresh_interval == "60"
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, { "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, ] # Internationalization # https://docs.djangoproject.com/en/3.1/topics/i18n/ LANGUAGE_CODE = "en-us" TIME_ZONE = "UTC" USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.1/howto/static-files/ STATIC_URL = "/static/" # unleash (feature-flag service) UNLEASH_CLIENT = UnleashClient("http://localhost:4242/api", "Flagged App") UNLEASH_CLIENT.initialize_client()
def test_UC_initialize_default(): client = UnleashClient(URL, APP_NAME) assert client.unleash_url == URL assert client.unleash_app_name == APP_NAME assert client.unleash_metrics_interval == 60
import time from UnleashClient import UnleashClient # --- import logging import sys root = logging.getLogger() root.setLevel(logging.DEBUG) handler = logging.StreamHandler(sys.stdout) handler.setLevel(logging.DEBUG) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) root.addHandler(handler) # --- my_client = UnleashClient(url="http://localhost:4242/api", app_name="pyIvan") my_client.initialize_client() while True: time.sleep(10) print(my_client.is_enabled("Demo"))
def unleash_client(): unleash_client = UnleashClient(url=URL, app_name=APP_NAME, instance_id='pytest_%s' % uuid.uuid4()) yield unleash_client unleash_client.destroy()
from UnleashClient import UnleashClient from UnleashClient.strategies import Strategy # --- import logging import sys root = logging.getLogger() root.setLevel(logging.DEBUG) handler = logging.StreamHandler(sys.stdout) handler.setLevel(logging.DEBUG) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) root.addHandler(handler) # --- my_client = UnleashClient( url="https://unleash.herokuapp.com/api", environment="staging", app_name="pyIvan", ) my_client.initialize_client() while True: time.sleep(10) context = {'userId': "1", 'sound': 'woof'} print(f"ivantest: {my_client.is_enabled('ivantest', context)}")