Exemple #1
0
def test_loader_initialization(cache_full):  # noqa: F811
    # Set up variables
    in_memory_features = {}
    temp_cache = cache_full

    # Tests
    load_features(temp_cache, in_memory_features, DEFAULT_STRATEGY_MAPPING)
    assert isinstance(in_memory_features["GradualRolloutUserID"], Feature)
    assert isinstance(in_memory_features["GradualRolloutUserID"].strategies[0],
                      GradualRolloutUserId)

    for feature_name in in_memory_features.keys():
        if feature_name == 'Garbage':  # Don't check purposely invalid strategy.
            break

        feature = in_memory_features[feature_name]
        assert len(feature.strategies) > 0
        strategy = feature.strategies[0]

        if isinstance(strategy, UserWithId):
            assert strategy.parameters
            assert len(strategy.parsed_provisioning)

        if isinstance(strategy, FlexibleRollout):
            len(strategy.parsed_constraints) > 0

        if isinstance(strategy, Variants):
            assert strategy.variants
Exemple #2
0
def fetch_and_load_features(url: str,
                            app_name: str,
                            instance_id: str,
                            custom_headers: dict,
                            custom_options: dict,
                            cache: BaseCache,
                            features: dict,
                            strategy_mapping: dict,
                            project: str = None) -> None:
    (feature_provisioning, etag) = get_feature_toggles(
        url,
        app_name,
        instance_id,
        custom_headers,
        custom_options,
        project,
        cache.get(ETAG)
    )

    if feature_provisioning:
        cache.set(FEATURES_URL, feature_provisioning)
    else:
        LOGGER.debug("No feature provisioning returned from server, using cached provisioning.")

    if etag:
        cache.set(ETAG, etag)

    load_features(cache, features, strategy_mapping)
def test_loader_initialization_failure(cache_custom):  # noqa: F811
    # Set up variables
    in_memory_features = {}
    temp_cache = cache_custom

    # Tests
    load_features(temp_cache, in_memory_features, DEFAULT_STRATEGY_MAPPING)
    assert isinstance(in_memory_features["UserWithId"], Feature)
def test_loader_segments(cache_segments):
    # Set up variables
    in_memory_features = {}
    temp_cache = cache_segments

    load_features(temp_cache, in_memory_features, DEFAULT_STRATEGY_MAPPING)
    feature = in_memory_features["Test"]
    loaded_constraints = list(feature.strategies[0].parsed_constraints)
    assert(len(loaded_constraints) == 2)
def test_loader_initialization(cache_full):  # noqa: F811
    # Set up variables
    in_memory_features = {}
    temp_cache = cache_full

    # Tests
    load_features(temp_cache, in_memory_features)
    assert isinstance(in_memory_features["GradualRolloutUserID"], Feature)
    assert isinstance(in_memory_features["GradualRolloutUserID"].strategies[0],
                      GradualRolloutUserId)
def fetch_and_load_features(url, app_name, instance_id, custom_headers, cache,
                            features, strategy_mapping):
    feature_provisioning = get_feature_toggles(url, app_name, instance_id,
                                               custom_headers)

    if feature_provisioning:
        cache[FEATURES_URL] = feature_provisioning
        cache.sync()
    else:
        LOGGER.info("Unable to get feature flag toggles, using cached values.")

    load_features(cache, features, strategy_mapping)
Exemple #7
0
def fetch_and_load_features(url: str, app_name: str, instance_id: str,
                            custom_headers: dict, cache: FileCache,
                            strategies: dict) -> None:
    feature_provisioning = get_feature_toggles(url, app_name, instance_id,
                                               custom_headers)

    if feature_provisioning:
        cache[FEATURES_URL] = feature_provisioning
        cache.sync()
    else:
        LOGGER.info("Unable to get feature flag toggles, using cached values.")

    load_features(cache, strategies)
def test_loader_refresh(cache_full):  # noqa: F811
    # Set up variables
    in_memory_features = {}
    temp_cache = cache_full

    load_features(temp_cache, in_memory_features)

    # Simulate update mutation
    temp_cache[FEATURES_URL] = MOCK_UPDATED
    temp_cache.sync()

    load_features(temp_cache, in_memory_features)

    assert in_memory_features["GradualRolloutUserID"].strategies[0].parameters[
        "percentage"] == 60
def test_loader_refresh_variants(cache_full):  # noqa: F811
    # Set up variables
    in_memory_features = {}
    temp_cache = cache_full

    load_features(temp_cache, in_memory_features, DEFAULT_STRATEGY_MAPPING)

    # Simulate update mutation
    mock_updated = copy.deepcopy(MOCK_ALL_FEATURES)
    mock_updated["features"][8]["variants"][0]["name"] = "VariantA"
    temp_cache.set(FEATURES_URL, mock_updated)

    load_features(temp_cache, in_memory_features, DEFAULT_STRATEGY_MAPPING)

    assert in_memory_features["Variations"].variants.variants[0]["name"] == "VariantA"
def test_loader_refresh_strategies(cache_full):  # noqa: F811
    # Set up variables
    in_memory_features = {}
    temp_cache = cache_full

    load_features(temp_cache, in_memory_features, DEFAULT_STRATEGY_MAPPING)

    # Simulate update mutation
    mock_updated = copy.deepcopy(MOCK_ALL_FEATURES)
    mock_updated["features"][4]["strategies"][0]["parameters"]["percentage"] = 60
    temp_cache.set(FEATURES_URL, mock_updated)

    load_features(temp_cache, in_memory_features, DEFAULT_STRATEGY_MAPPING)

    assert in_memory_features["GradualRolloutUserID"].strategies[0].parameters["percentage"] == 60
    assert len(temp_cache.get(FAILED_STRATEGIES)) == 1
def fetch_and_load_features(url: str,
                            app_name: str,
                            instance_id: str,
                            custom_headers: dict,
                            custom_options: dict,
                            cache: FileCache,
                            features: dict,
                            strategy_mapping: dict) -> None:
    feature_provisioning = get_feature_toggles(url, app_name, instance_id, custom_headers, custom_options)

    if feature_provisioning:
        cache[FEATURES_URL] = feature_provisioning
        cache.sync()
    else:
        LOGGER.warning("Unable to get feature flag toggles, using cached provisioning.")

    load_features(cache, features, strategy_mapping)
Exemple #12
0
def fetch_and_load_features(url: str, app_name: str, instance_id: str,
                            custom_headers: dict, custom_options: dict,
                            cache: redis.Redis, features: dict,
                            strategy_mapping: dict) -> None:
    feature_provisioning = get_feature_toggles(url, app_name, instance_id,
                                               custom_headers, custom_options)

    if feature_provisioning:
        # Sample data we're writing into cache
        # {
        #   "features": [{
        #     "name": "haptik.development.enable_smart_skills",
        #     "description": "Feature to enable smart skills on dev servers",
        #     "type": "release",
        #     "project": "default",
        #     "enabled": true,
        #     "stale": false,
        #     "strategies": [
        #         {
        #         "name": "EnableForPartners",
        #         "parameters": {
        #             "partner_names": "Platform Demo,haptik,demo,aksc"
        #         }
        #         }
        #     ],
        #     "variants": [],
        #     "createdAt": "2021-03-08T09:14:41.828Z"
        #   }]
        # }
        features = feature_provisioning.get('features', [])
        if not features:
            LOGGER.warning("Features are empty")
        cache.set(FEATURES_URL, pickle.dumps(features))
    else:
        LOGGER.warning(
            "Unable to get feature flag toggles, using cached provisioning.")

    load_features(cache, features, strategy_mapping)
Exemple #13
0
    def __init__(self,
                 url: str,
                 app_name: str,
                 environment: str = "default",
                 instance_id: str = "unleash-client-python",
                 refresh_interval: int = 15,
                 refresh_jitter: Optional[int] = None,
                 metrics_interval: int = 60,
                 metrics_jitter: Optional[int] = None,
                 disable_metrics: bool = False,
                 disable_registration: bool = False,
                 custom_headers: Optional[dict] = None,
                 custom_options: Optional[dict] = None,
                 custom_strategies: Optional[dict] = None,
                 cache_directory: Optional[str] = None,
                 project_name: str = None,
                 verbose_log_level: int = 30,
                 cache: Optional[BaseCache] = None) -> None:
        custom_headers = custom_headers or {}
        custom_options = custom_options or {}
        custom_strategies = custom_strategies or {}

        # Configuration
        self.unleash_url = url.rstrip('/')
        self.unleash_app_name = app_name
        self.unleash_environment = environment
        self.unleash_instance_id = instance_id
        self.unleash_refresh_interval = refresh_interval
        self.unleash_refresh_jitter = int(
            refresh_jitter) if refresh_jitter is not None else None
        self.unleash_metrics_interval = metrics_interval
        self.unleash_metrics_jitter = int(
            metrics_jitter) if metrics_jitter is not None else None
        self.unleash_disable_metrics = disable_metrics
        self.unleash_disable_registration = disable_registration
        self.unleash_custom_headers = custom_headers
        self.unleash_custom_options = custom_options
        self.unleash_static_context = {
            "appName": self.unleash_app_name,
            "environment": self.unleash_environment
        }
        self.unleash_project_name = project_name
        self.unleash_verbose_log_level = verbose_log_level

        # Class objects
        self.features: dict = {}
        self.scheduler = BackgroundScheduler()
        self.fl_job: Job = None
        self.metric_job: Job = None

        self.cache = cache or FileCache(self.unleash_app_name,
                                        directory=cache_directory)
        self.cache.mset({
            METRIC_LAST_SENT_TIME: datetime.now(timezone.utc),
            ETAG: ''
        })
        self.unleash_bootstrapped = self.cache.bootstrapped

        # Mappings
        default_strategy_mapping = {
            "applicationHostname": ApplicationHostname,
            "default": Default,
            "gradualRolloutRandom": GradualRolloutRandom,
            "gradualRolloutSessionId": GradualRolloutSessionId,
            "gradualRolloutUserId": GradualRolloutUserId,
            "remoteAddress": RemoteAddress,
            "userWithId": UserWithId,
            "flexibleRollout": FlexibleRollout
        }

        if custom_strategies:
            strategy_v2xx_deprecation_check(
                [x for x in custom_strategies.values()])  # pylint: disable=R1721

        self.strategy_mapping = {
            **custom_strategies,
            **default_strategy_mapping
        }

        # Client status
        self.is_initialized = False

        # Bootstrapping
        if self.unleash_bootstrapped:
            load_features(cache=self.cache,
                          feature_toggles=self.features,
                          strategy_mapping=self.strategy_mapping)