Пример #1
0
def get_appconfig_data_client(cmd, name, connection_string, auth_mode, endpoint):
    azconfig_client = None
    if auth_mode == "key":
        connection_string = resolve_connection_string(cmd, name, connection_string)
        try:
            azconfig_client = AzureAppConfigurationClient.from_connection_string(connection_string=connection_string,
                                                                                 user_agent=HttpHeaders.USER_AGENT)
        except ValueError as ex:
            raise CLIError("Failed to initialize AzureAppConfigurationClient due to an exception: {}".format(str(ex)))

    if auth_mode == "login":
        if not endpoint:
            try:
                if name:
                    _, endpoint = resolve_store_metadata(cmd, name)
                else:
                    raise CLIError("App Configuration endpoint or name should be provided if auth mode is 'login'.")
            except Exception as ex:
                raise CLIError(str(ex) + "\nYou may be able to resolve this issue by providing App Configuration endpoint instead of name.")

        from azure.cli.core._profile import Profile
        profile = Profile(cli_ctx=cmd.cli_ctx)
        cred, _, _ = profile.get_login_credentials()
        try:
            azconfig_client = AzureAppConfigurationClient(credential=cred,
                                                          base_url=endpoint,
                                                          user_agent=HttpHeaders.USER_AGENT)
        except (ValueError, TypeError) as ex:
            raise CLIError("Failed to initialize AzureAppConfigurationClient due to an exception: {}".format(str(ex)))

    return azconfig_client
    def test_mock_policies(self, client, appconfiguration_connection_string):
        from azure.core.pipeline.transport import HttpRequest, HttpResponse, HttpTransport
        from azure.core.pipeline.policies import RetryPolicy
        from azure.core.pipeline import Pipeline, PipelineResponse

        class MockTransport(HttpTransport):
            def __init__(self):
                self._count = 0
                self.auth_headers = None
            def __exit__(self, exc_type, exc_val, exc_tb):
                pass
            def close(self):
                pass
            def open(self):
                pass

            def send(self, request, **kwargs):  # type: (PipelineRequest, Any) -> PipelineResponse
                assert request.headers['Authorization'] != self.auth_headers
                self.auth_headers = request.headers['Authorization']
                response = HttpResponse(request, None)
                response.status_code = 429
                return response

        def new_method(self, request):
            request.http_request.headers["Authorization"] = uuid4()

        from azure.appconfiguration._azure_appconfiguration_requests import AppConfigRequestsCredentialsPolicy
        temp = AppConfigRequestsCredentialsPolicy._signed_request
        AppConfigRequestsCredentialsPolicy._signed_request = new_method

        client = AzureAppConfigurationClient.from_connection_string(appconfiguration_connection_string, transport=MockTransport())

        client.list_configuration_settings()

        AppConfigRequestsCredentialsPolicy._signed_request = temp
def main():
    CONNECTION_STRING = get_connection_string()

    # Create app config client
    client = AzureAppConfigurationClient.from_connection_string(CONNECTION_STRING)

    config_setting = ConfigurationSetting(
        key="MyKey",
        value="my value",
        content_type="my content type",
        tags={"my tag": "my tag value"}
    )
    returned_config_setting = client.set_configuration_setting(config_setting)

    returned_config_setting.value = "new value"
    returned_config_setting.content_type = "new content type"
    client.set_configuration_setting(config_setting)

    items = client.list_revisions(key_filter="MyKey")
    for item in items:
        print_configuration_setting(item)
        print("")

    client.delete_configuration_setting(
        key="MyKey",
    )
def main():
    CONNECTION_STRING = get_connection_string()

    # Create app config client
    client = AzureAppConfigurationClient.from_connection_string(
        CONNECTION_STRING)

    print("Add new configuration setting")
    config_setting = ConfigurationSetting(key="MyKey",
                                          label="MyLabel",
                                          value="my value",
                                          content_type="my content type",
                                          tags={"my tag": "my tag value"})
    added_config_setting = client.add_configuration_setting(config_setting)
    print("New configuration setting:")
    print_configuration_setting(added_config_setting)
    print("")

    print("Set configuration setting")
    added_config_setting.value = "new value"
    added_config_setting.content_type = "new content type"
    updated_config_setting = client.set_configuration_setting(config_setting)
    print_configuration_setting(updated_config_setting)
    print("")

    print("List configuration settings")
    config_settings = client.list_configuration_settings(labels=["MyLabel"])
    for item in config_settings:
        print_configuration_setting(item)

    print("Delete configuration setting")
    client.delete_configuration_setting(
        key="MyKey",
        label="MyLabel",
    )
def main():
    CONNECTION_STRING = get_connection_string()

    # Create app config client
    client = AzureAppConfigurationClient.from_connection_string(CONNECTION_STRING)

    print("Set new configuration setting")
    config_setting = ConfigurationSetting(
        key="MyKey",
        value="my value",
        content_type="my content type",
        tags={"my tag": "my tag value"}
    )
    returned_config_setting = client.set_configuration_setting(config_setting)
    print("New configuration setting:")
    print_configuration_setting(returned_config_setting)
    print("")

    print("Get configuration setting")
    fetched_config_setting = client.get_configuration_setting(
        key="MyKey"
    )
    print("Fetched configuration setting:")
    print_configuration_setting(fetched_config_setting)
    print("")

    print("Delete configuration setting")
    client.delete_configuration_setting(
        key="MyKey"
    )
Пример #6
0
def list_key(cmd,
             key=None,
             fields=None,
             name=None,
             label=None,
             datetime=None,
             connection_string=None,
             top=None,
             all_=False,
             resolve_keyvault=False):
    if fields and resolve_keyvault:
        raise CLIError(
            "Please provide only one of these arguments: '--fields' or '--resolve-keyvault'. See 'az appconfig kv list -h' for examples."
        )

    connection_string = resolve_connection_string(cmd, name, connection_string)
    azconfig_client = AzureAppConfigurationClient.from_connection_string(
        connection_string=connection_string, user_agent=HttpHeaders.USER_AGENT)

    keyvalues = __read_kv_from_config_store(
        azconfig_client,
        key=key if key else SearchFilterOptions.ANY_KEY,
        label=label if label else SearchFilterOptions.ANY_LABEL,
        datetime=datetime,
        fields=fields,
        top=top,
        all_=all_,
        cli_ctx=cmd.cli_ctx if resolve_keyvault else None)
    return keyvalues
Пример #7
0
    def __init__(self):
        self.client = AzureAppConfigurationClient.from_connection_string(APP_CONFIG_CONNECTION_STR)

        self.api_instance = API_INSTANCE_NAME

        # sentinel should change if new configurations are available
        self.sentinel = self._get_sentinel()
        self.allowlist = self._get_allowlist()
 def __init__(self, method_name):
     super(AppConfigurationClientTest, self).__init__(method_name)
     self.vcr.match_on = ["path", "method", "query"]
     if self.is_playback():
         connection_str = "Endpoint=https://fake_app_config.azconfig-test.io;Id=0-l4-s0:h5htBaY5Z1LwFz50bIQv;Secret=bgyvBgwsQIw0s8myrqJJI3nLrj81M/kzSgSuP4BBoVg="
     else:
         connection_str = os.getenv('APP_CONFIG_CONNECTION')
     self.app_config_client = AzureAppConfigurationClient.from_connection_string(connection_str)
Пример #9
0
 def __init__(self, arguments):
     super().__init__(arguments)
     connection_string = self.get_from_env(
         "AZURE_APP_CONFIG_CONNECTION_STRING")
     self.key = "KEY"
     self.service_client = SyncAppConfigClient.from_connection_string(
         connection_string=connection_string)
     self.async_service_client = AsyncAppConfigClient.from_connection_string(
         connection_string=connection_string)
Пример #10
0
def unlock_feature(cmd,
                   feature,
                   name=None,
                   label=None,
                   connection_string=None,
                   yes=False):
    key = FeatureFlagConstants.FEATURE_FLAG_PREFIX + feature
    connection_string = resolve_connection_string(cmd, name, connection_string)
    azconfig_client = AzureAppConfigurationClient.from_connection_string(
        connection_string=connection_string, user_agent=HttpHeaders.USER_AGENT)

    retry_times = 3
    retry_interval = 1
    for i in range(0, retry_times):
        try:
            retrieved_kv = azconfig_client.get_configuration_setting(
                key=key, label=label)
        except ResourceNotFoundError:
            raise CLIError(
                "Feature '{}' with label '{}' does not exist.".format(
                    feature, label))
        except HttpResponseError as exception:
            raise CLIError(
                "Failed to retrieve feature flags from config store. " +
                str(exception))

        if retrieved_kv is None or retrieved_kv.content_type != FeatureFlagConstants.FEATURE_FLAG_CONTENT_TYPE:
            raise CLIError(
                "The feature '{}' you are trying to unlock does not exist.".
                format(feature))

        confirmation_message = "Are you sure you want to unlock the feature '{}' with label '{}'".format(
            feature, label)
        user_confirmation(confirmation_message, yes)

        try:
            new_kv = azconfig_client.set_read_only(
                retrieved_kv,
                read_only=False,
                match_condition=MatchConditions.IfNotModified)
            return map_keyvalue_to_featureflag(
                convert_configurationsetting_to_keyvalue(new_kv),
                show_conditions=False)
        except HttpResponseError as exception:
            if exception.status_code == StatusCodes.PRECONDITION_FAILED:
                logger.debug(
                    'Retrying unlock operation %s times with exception: concurrent setting operations',
                    i + 1)
                time.sleep(retry_interval)
            else:
                raise CLIError(str(exception))
        except Exception as exception:
            raise CLIError(str(exception))
    raise CLIError(
        "Failed to unlock the feature '{}' with label '{}' due to a conflicting operation."
        .format(feature, label))
Пример #11
0
def azure_appconfig_resolver(connection_string):

    client = AzureAppConfigurationClient.from_connection_string(
        connection_string)

    def return_config(k):
        try:
            return client.get_configuration_setting(k).value
        except ResourceNotFoundError as rnfe:
            raise KeyError from rnfe

    return return_config
Пример #12
0
    def wrapper(*args, **kwargs):
        appconfiguration_connection_string = kwargs.pop(
            "appconfiguration_connection_string")
        client = AzureAppConfigurationClient.from_connection_string(
            appconfiguration_connection_string)

        kwargs['client'] = client
        kwargs[
            'appconfiguration_connection_string'] = appconfiguration_connection_string

        # Do setUp on client
        test_config_setting = _add_for_test(
            client,
            ConfigurationSetting(
                key=KEY,
                label=LABEL,
                value=TEST_VALUE,
                content_type=TEST_CONTENT_TYPE,
                tags={
                    "tag1": "tag1",
                    "tag2": "tag2"
                },
            ))
        test_config_setting_no_label = _add_for_test(
            client,
            ConfigurationSetting(
                key=KEY,
                label=None,
                value=TEST_VALUE,
                content_type=TEST_CONTENT_TYPE,
                tags={
                    "tag1": "tag1",
                    "tag2": "tag2"
                },
            ))
        to_delete = [test_config_setting, test_config_setting_no_label]

        kwargs['test_config_setting'] = test_config_setting
        kwargs['test_config_setting_no_label'] = test_config_setting_no_label

        trimmed_kwargs = {k: v for k, v in kwargs.items()}
        trim_kwargs_from_test_function(func, trimmed_kwargs)

        func(*args, **trimmed_kwargs)

        for item in to_delete:
            try:
                client.delete_configuration_setting(key=item.key,
                                                    label=item.label)
            except:
                print("Issue deleting config with key {} and label {}".format(
                    item.key, item.label))
Пример #13
0
 def create_kv(self, connection_str):
     from azure.appconfiguration import (AzureAppConfigurationClient,
                                         ConfigurationSetting)
     app_config_client = AzureAppConfigurationClient.from_connection_string(
         connection_str)
     kv = ConfigurationSetting(key=KEY,
                               label=LABEL,
                               value=TEST_VALUE,
                               content_type=TEST_CONTENT_TYPE,
                               tags={
                                   "tag1": "tag1",
                                   "tag2": "tag2"
                               })
     created_kv = app_config_client.add_configuration_setting(kv)
     return created_kv
Пример #14
0
def list_revision(cmd,
                  key=None,
                  fields=None,
                  name=None,
                  label=None,
                  datetime=None,
                  connection_string=None,
                  top=None,
                  all_=False):
    connection_string = resolve_connection_string(cmd, name, connection_string)
    azconfig_client = AzureAppConfigurationClient.from_connection_string(
        connection_string=connection_string, user_agent=HttpHeaders.USER_AGENT)

    key = key if key else SearchFilterOptions.ANY_KEY
    label = label if label else SearchFilterOptions.ANY_LABEL
    if label == SearchFilterOptions.EMPTY_LABEL:
        label = prep_null_label_for_url_encoding(label)

    try:
        revisions_iterable = azconfig_client.list_revisions(
            key_filter=key,
            label_filter=label,
            accept_datetime=datetime,
            fields=fields)
        retrieved_revisions = []
        count = 0

        if all_:
            top = float('inf')
        elif top is None:
            top = 100

        for revision in revisions_iterable:
            kv_revision = convert_configurationsetting_to_keyvalue(revision)
            if fields:
                partial_revision = {}
                for field in fields:
                    partial_revision[field.name.lower(
                    )] = kv_revision.__dict__[field.name.lower()]
                retrieved_revisions.append(partial_revision)
            else:
                retrieved_revisions.append(kv_revision)
            count += 1
            if count >= top:
                return retrieved_revisions
        return retrieved_revisions
    except HttpResponseError as ex:
        raise CLIError('List revision operation failed.\n' + str(ex))
def handle_event_grid_notifications(event_grid_events):
    # type: (List[dict[str, Any]]) -> None
    CONNECTION_STRING = get_connection_string()

    all_keys = []

    with AzureAppConfigurationClient.from_connection_string(CONNECTION_STRING) as client:

        for event_grid_event in event_grid_events:
            if event_grid_event["eventType"] == 'Microsoft.KeyValueModified':
                sync_token = event['data']['syncToken']
                client.update_sync_token(sync_token)

                new_key = client.get_configuration_setting(key=event['data']['key'], label=event['data']['label'])

                all_keys.append(new_key)
Пример #16
0
def list_feature(cmd,
                 feature=None,
                 name=None,
                 label=None,
                 fields=None,
                 connection_string=None,
                 top=None,
                 all_=False):
    connection_string = resolve_connection_string(cmd, name, connection_string)
    azconfig_client = AzureAppConfigurationClient.from_connection_string(
        connection_string=connection_string, user_agent=HttpHeaders.USER_AGENT)
    try:
        retrieved_keyvalues = __list_all_keyvalues(
            azconfig_client,
            feature=feature if feature else SearchFilterOptions.ANY_KEY,
            label=label if label else SearchFilterOptions.ANY_LABEL)
        retrieved_featureflags = []
        for kv in retrieved_keyvalues:
            retrieved_featureflags.append(
                map_keyvalue_to_featureflag(keyvalue=kv, show_conditions=True))
        filtered_featureflags = []
        count = 0

        if all_:
            top = len(retrieved_featureflags)
        elif top is None:
            top = 100

        for featureflag in retrieved_featureflags:
            if fields:
                partial_featureflags = {}
                for field in fields:
                    # featureflag is guaranteed to have all the fields because
                    # we validate this in map_keyvalue_to_featureflag()
                    # So this line will never throw AttributeError
                    partial_featureflags[field.name.lower()] = getattr(
                        featureflag, field.name.lower())
                filtered_featureflags.append(partial_featureflags)
            else:
                filtered_featureflags.append(featureflag)
            count += 1
            if count >= top:
                break
        return filtered_featureflags

    except Exception as exception:
        raise CLIError(str(exception))
Пример #17
0
def unlock_key(cmd,
               key,
               label=None,
               name=None,
               connection_string=None,
               yes=False):
    connection_string = resolve_connection_string(cmd, name, connection_string)
    azconfig_client = AzureAppConfigurationClient.from_connection_string(
        connection_string=connection_string, user_agent=HttpHeaders.USER_AGENT)

    retry_times = 3
    retry_interval = 1
    for i in range(0, retry_times):
        try:
            retrieved_kv = azconfig_client.get_configuration_setting(
                key=key, label=label)
        except ResourceNotFoundError:
            raise CLIError("Key '{}' with label '{}' does not exist.".format(
                key, label))
        except HttpResponseError as exception:
            raise CLIError(str(exception))

        confirmation_message = "Are you sure you want to unlock the key '{}' with label '{}'".format(
            key, label)
        user_confirmation(confirmation_message, yes)

        try:
            new_kv = azconfig_client.set_read_only(
                retrieved_kv,
                read_only=False,
                match_condition=MatchConditions.IfNotModified)
            return convert_configurationsetting_to_keyvalue(new_kv)
        except HttpResponseError as exception:
            if exception.status_code == StatusCodes.PRECONDITION_FAILED:
                logger.debug(
                    'Retrying unlock operation %s times with exception: concurrent setting operations',
                    i + 1)
                time.sleep(retry_interval)
            else:
                raise CLIError(str(exception))
        except Exception as exception:
            raise CLIError(str(exception))
    raise CLIError(
        "Failed to unlock the key '{}' with label '{}' due to a conflicting operation."
        .format(key, label))
Пример #18
0
def list_filter(cmd,
                feature,
                name=None,
                label=None,
                connection_string=None,
                top=None,
                all_=False):
    key = FeatureFlagConstants.FEATURE_FLAG_PREFIX + feature
    connection_string = resolve_connection_string(cmd, name, connection_string)
    azconfig_client = AzureAppConfigurationClient.from_connection_string(
        connection_string=connection_string, user_agent=HttpHeaders.USER_AGENT)

    try:
        retrieved_kv = azconfig_client.get_configuration_setting(key=key,
                                                                 label=label)
    except ResourceNotFoundError:
        raise CLIError("Feature flag '{}' with label '{}' not found.".format(
            feature, label))
    except HttpResponseError as exception:
        raise CLIError("Failed to retrieve feature flags from config store. " +
                       str(exception))

    try:
        if retrieved_kv is None or retrieved_kv.content_type != FeatureFlagConstants.FEATURE_FLAG_CONTENT_TYPE:
            raise CLIError(
                "The feature flag {} does not exist.".format(feature))

        # we make sure that value retrieved is a valid json and only has the fields supported by backend.
        # if it's invalid, we catch appropriate exception that contains
        # detailed message
        feature_flag_value = map_keyvalue_to_featureflagvalue(retrieved_kv)
        feature_filters = feature_flag_value.conditions['client_filters']

        if all_:
            top = len(feature_filters)
        elif top is None:
            top = 100

        return feature_filters[:top]

    except Exception as exception:
        raise CLIError(str(exception))
Пример #19
0
def show_feature(cmd,
                 feature,
                 name=None,
                 label=None,
                 fields=None,
                 connection_string=None):
    key = FeatureFlagConstants.FEATURE_FLAG_PREFIX + feature
    connection_string = resolve_connection_string(cmd, name, connection_string)
    azconfig_client = AzureAppConfigurationClient.from_connection_string(
        connection_string=connection_string, user_agent=HttpHeaders.USER_AGENT)

    try:
        config_setting = azconfig_client.get_configuration_setting(key=key,
                                                                   label=label)
        if config_setting is None or config_setting.content_type != FeatureFlagConstants.FEATURE_FLAG_CONTENT_TYPE:
            raise CLIError("The feature flag does not exist.")

        retrieved_kv = convert_configurationsetting_to_keyvalue(config_setting)
        feature_flag = map_keyvalue_to_featureflag(keyvalue=retrieved_kv,
                                                   show_conditions=True)

        # If user has specified fields, we still get all the fields and then
        # filter what we need from the response.
        if fields:
            partial_featureflag = {}
            for field in fields:
                # feature_flag is guaranteed to have all the fields because
                # we validate this in map_keyvalue_to_featureflag()
                # So this line will never throw AttributeError
                partial_featureflag[field.name.lower()] = getattr(
                    feature_flag, field.name.lower())
            return partial_featureflag
        return feature_flag
    except ResourceNotFoundError:
        raise CLIError("Feature '{}' with label '{}' does not exist.".format(
            feature, label))
    except HttpResponseError as exception:
        raise CLIError(str(exception))

    raise CLIError("Failed to get the feature '{}' with label '{}'.".format(
        feature, label))
def main():
    CONNECTION_STRING = get_connection_string()

    # Create app config client
    client = AzureAppConfigurationClient.from_connection_string(
        CONNECTION_STRING)

    # Unconditional set
    config_setting = ConfigurationSetting(key="MyKey",
                                          value="my value",
                                          content_type="my content type",
                                          tags={"my tag": "my tag value"})
    client.set_configuration_setting(config_setting)

    # Unconditional get
    first_get = client.get_configuration_setting(key="MyKey")
    print_configuration_setting(first_get)

    # Conditional get, expect to return None because it is not modified
    second_get = client.get_configuration_setting(
        key="MyKey",
        etag=first_get.etag,
        match_condition=MatchConditions.IfModified)
    print_configuration_setting(second_get)

    # Conditional set
    first_get.value = "new value"
    client.set_configuration_setting(
        configuration_setting=first_get,
        match_condition=MatchConditions.IfNotModified)

    # Conditional set, expect to see error because it is modified
    try:
        client.set_configuration_setting(
            configuration_setting=first_get,
            match_condition=MatchConditions.IfNotModified)
    except ResourceModifiedError:
        pass

    client.delete_configuration_setting(key="MyKey")
def main():
    CONNECTION_STRING = get_connection_string()

    # Create app config client
    client = AzureAppConfigurationClient.from_connection_string(CONNECTION_STRING)

    print("Set new configuration setting")
    config_setting = ConfigurationSetting(
        key="MyKey",
        value="my value",
        content_type="my content type",
        tags={"my tag": "my tag value"}
    )
    returned_config_setting = client.set_configuration_setting(config_setting)
    print("New configuration setting:")
    print_configuration_setting(returned_config_setting)
    print("")

    print("Read only configuration setting:")
    read_only_config_setting = client.set_read_only(
        returned_config_setting
    )
    print_configuration_setting(read_only_config_setting)
    print("")

    print("Clear read only configuration setting:")
    read_write_config_setting = client.set_read_only(
        returned_config_setting, False
    )
    print_configuration_setting(read_write_config_setting)
    print("")

    print("Delete configuration setting")
    client.delete_configuration_setting(
        key="MyKey",
    )
Пример #22
0
def show_key(cmd,
             key,
             name=None,
             label=None,
             datetime=None,
             connection_string=None):
    connection_string = resolve_connection_string(cmd, name, connection_string)
    azconfig_client = AzureAppConfigurationClient.from_connection_string(
        connection_string=connection_string, user_agent=HttpHeaders.USER_AGENT)

    try:
        key_value = azconfig_client.get_configuration_setting(
            key=key, label=label, accept_datetime=datetime)
        if key_value is None:
            raise CLIError("The key-value does not exist.")
        return convert_configurationsetting_to_keyvalue(key_value)
    except ResourceNotFoundError:
        raise CLIError("Key '{}' with label '{}' does not exist.".format(
            key, label))
    except HttpResponseError as exception:
        raise CLIError(str(exception))

    raise CLIError("Failed to get the key '{}' with label '{}'.".format(
        key, label))
Пример #23
0
    def get_azure_app_configuration_client(self):
        connection_str = self.config.AZURE_APP_CONFIGURATION_CONNECTION_STRING
        client = AzureAppConfigurationClient.from_connection_string(
            connection_str)

        return client
Пример #24
0
def export_config(
        cmd,
        destination,
        name=None,
        connection_string=None,
        label=None,
        key=None,
        prefix="",  # prefix to remove
        yes=False,
        skip_features=False,
        skip_keyvault=False,
        # to-file parameters
        path=None,
        format_=None,
        separator=None,
        naming_convention='pascal',
        resolve_keyvault=False,
        # to-config-store parameters
        dest_name=None,
        dest_connection_string=None,
        dest_label=None,
        preserve_labels=False,
        # to-app-service parameters
        appservice_account=None):
    src_features = []
    dest_features = []
    dest_kvs = []
    destination = destination.lower()
    format_ = format_.lower() if format_ else None
    naming_convention = naming_convention.lower()

    connection_string = resolve_connection_string(cmd, name, connection_string)
    azconfig_client = AzureAppConfigurationClient.from_connection_string(
        connection_string=connection_string, user_agent=HttpHeaders.USER_AGENT)
    dest_azconfig_client = None
    if destination == 'appconfig':
        if dest_label is not None and preserve_labels:
            raise CLIError(
                "Export failed! Please provide only one of these arguments: '--dest-label' or '--preserve-labels'. See 'az appconfig kv export -h' for examples."
            )
        if preserve_labels:
            # We need dest_label to be the same as label for preview later.
            # This will have no effect on label while writing to config store
            # as we check preserve_labels again before labelling KVs.
            dest_label = label
        dest_connection_string = resolve_connection_string(
            cmd, dest_name, dest_connection_string)
        dest_azconfig_client = AzureAppConfigurationClient.from_connection_string(
            connection_string=dest_connection_string,
            user_agent=HttpHeaders.USER_AGENT)

    # fetch key values from user's configstore
    src_kvs = __read_kv_from_config_store(
        azconfig_client,
        key=key,
        label=label if label else SearchFilterOptions.EMPTY_LABEL,
        prefix_to_remove=prefix,
        cli_ctx=cmd.cli_ctx if resolve_keyvault else None)

    if skip_keyvault:
        src_kvs = [
            keyvalue for keyvalue in src_kvs
            if keyvalue.content_type != KeyVaultConstants.KEYVAULT_CONTENT_TYPE
        ]

    # We need to separate KV from feature flags
    __discard_features_from_retrieved_kv(src_kvs)

    if not skip_features:
        # Get all Feature flags with matching label
        if (destination == 'file'
                and format_ == 'properties') or destination == 'appservice':
            skip_features = True
            logger.warning(
                "Exporting feature flags to properties file or appservice is currently not supported."
            )
        else:
            # src_features is a list of FeatureFlag objects
            src_features = list_feature(
                cmd,
                feature='*',
                label=label if label else SearchFilterOptions.EMPTY_LABEL,
                name=name,
                connection_string=connection_string,
                all_=True)

    # if customer needs preview & confirmation
    if not yes:
        if destination == 'appconfig':
            # dest_kvs contains features and KV that match the label
            dest_kvs = __read_kv_from_config_store(
                dest_azconfig_client,
                key=SearchFilterOptions.ANY_KEY,
                label=dest_label
                if dest_label else SearchFilterOptions.EMPTY_LABEL)
            __discard_features_from_retrieved_kv(dest_kvs)

            if not skip_features:
                # Append all features to dest_features list
                dest_features = list_feature(
                    cmd,
                    feature='*',
                    label=dest_label
                    if dest_label else SearchFilterOptions.EMPTY_LABEL,
                    name=dest_name,
                    connection_string=dest_connection_string,
                    all_=True)

        elif destination == 'appservice':
            dest_kvs = __read_kv_from_app_service(
                cmd, appservice_account=appservice_account)

        # generate preview and wait for user confirmation
        need_kv_change = __print_preview(
            old_json=__serialize_kv_list_to_comparable_json_object(
                keyvalues=dest_kvs, level=destination),
            new_json=__serialize_kv_list_to_comparable_json_object(
                keyvalues=src_kvs, level=destination))

        need_feature_change = False
        if src_features:
            need_feature_change = __print_features_preview(
                old_json=__serialize_feature_list_to_comparable_json_object(
                    features=dest_features),
                new_json=__serialize_feature_list_to_comparable_json_object(
                    features=src_features))

        if not need_kv_change and not need_feature_change:
            return

        user_confirmation("Do you want to continue? \n")

    # export to destination
    if destination == 'file':
        __write_kv_and_features_to_file(file_path=path,
                                        key_values=src_kvs,
                                        features=src_features,
                                        format_=format_,
                                        separator=separator,
                                        skip_features=skip_features,
                                        naming_convention=naming_convention)
    elif destination == 'appconfig':
        __write_kv_and_features_to_config_store(
            dest_azconfig_client,
            key_values=src_kvs,
            features=src_features,
            label=dest_label,
            preserve_labels=preserve_labels)
    elif destination == 'appservice':
        __write_kv_to_app_service(cmd,
                                  key_values=src_kvs,
                                  appservice_account=appservice_account)
Пример #25
0
def set_key(cmd,
            key,
            name=None,
            label=None,
            content_type=None,
            tags=None,
            value=None,
            yes=False,
            connection_string=None):
    connection_string = resolve_connection_string(cmd, name, connection_string)
    azconfig_client = AzureAppConfigurationClient.from_connection_string(
        connection_string=connection_string, user_agent=HttpHeaders.USER_AGENT)

    if content_type:
        if content_type.lower() == KeyVaultConstants.KEYVAULT_CONTENT_TYPE:
            logger.warning(
                "There is a dedicated command to set key vault reference. 'appconfig kv set-keyvault -h'"
            )
        elif content_type.lower(
        ) == FeatureFlagConstants.FEATURE_FLAG_CONTENT_TYPE:
            logger.warning(
                "There is a dedicated command to set feature flag. 'appconfig feature set -h'"
            )

    retry_times = 3
    retry_interval = 1

    label = label if label and label != SearchFilterOptions.EMPTY_LABEL else None
    for i in range(0, retry_times):
        retrieved_kv = None
        set_kv = None
        new_kv = None

        try:
            retrieved_kv = azconfig_client.get_configuration_setting(
                key=key, label=label)
        except ResourceNotFoundError:
            logger.debug(
                "Key '%s' with label '%s' not found. A new key-value will be created.",
                key, label)
        except HttpResponseError as exception:
            raise CLIError(
                "Failed to retrieve key-values from config store. " +
                str(exception))

        if retrieved_kv is None:
            if content_type and __is_json_content_type(content_type):
                try:
                    # Ensure that provided value is valid JSON. Error out if value is invalid JSON.
                    value = 'null' if value is None else value
                    json.loads(value)
                except ValueError:
                    raise CLIError(
                        'Value "{}" is not a valid JSON object, which conflicts with the content type "{}".'
                        .format(value, content_type))

            set_kv = ConfigurationSetting(key=key,
                                          label=label,
                                          value=value,
                                          content_type=content_type,
                                          tags=tags)
        else:
            value = retrieved_kv.value if value is None else value
            content_type = retrieved_kv.content_type if content_type is None else content_type
            if content_type and __is_json_content_type(content_type):
                try:
                    # Ensure that provided/existing value is valid JSON. Error out if value is invalid JSON.
                    json.loads(value)
                except (TypeError, ValueError):
                    raise CLIError(
                        'Value "{}" is not a valid JSON object, which conflicts with the content type "{}". Set the value again in valid JSON format.'
                        .format(value, content_type))
            set_kv = ConfigurationSetting(
                key=key,
                label=label,
                value=value,
                content_type=content_type,
                tags=retrieved_kv.tags if tags is None else tags,
                read_only=retrieved_kv.read_only,
                etag=retrieved_kv.etag)

        verification_kv = {
            "key": set_kv.key,
            "label": set_kv.label,
            "content_type": set_kv.content_type,
            "value": set_kv.value,
            "tags": set_kv.tags
        }

        entry = json.dumps(verification_kv,
                           indent=2,
                           sort_keys=True,
                           ensure_ascii=False)
        confirmation_message = "Are you sure you want to set the key: \n" + entry + "\n"
        user_confirmation(confirmation_message, yes)

        try:
            if set_kv.etag is None:
                new_kv = azconfig_client.add_configuration_setting(set_kv)
            else:
                new_kv = azconfig_client.set_configuration_setting(
                    set_kv, match_condition=MatchConditions.IfNotModified)
            return convert_configurationsetting_to_keyvalue(new_kv)

        except ResourceReadOnlyError:
            raise CLIError(
                "Failed to update read only key-value. Unlock the key-value before updating it."
            )
        except HttpResponseError as exception:
            if exception.status_code == StatusCodes.PRECONDITION_FAILED:
                logger.debug(
                    'Retrying setting %s times with exception: concurrent setting operations',
                    i + 1)
                time.sleep(retry_interval)
            else:
                raise CLIError(str(exception))
        except Exception as exception:
            raise CLIError(str(exception))
    raise CLIError(
        "Failed to set the key '{}' due to a conflicting operation.".format(
            key))
from azure.appconfiguration import AzureAppConfigurationClient

connection_str = "Endpoint=https://config-demo-azure.azconfig.io;Id=/sWh-l9-s0:n06YX28m2mvHmdknfJdx;Secret=lVepuj2LbqdRjl5dHDXc1U/M7Q0QkXlt71Qhdq6SxSE="
client = AzureAppConfigurationClient.from_connection_string(connection_str)


def get_tweeter_config():
    tweeter_conf = {}
    tweeter_conf['access_token'] = client.get_configuration_setting(
        key="tweeter_access_token").value
    tweeter_conf['access_token_secret'] = client.get_configuration_setting(
        key="tweeter_access_token_secret").value
    tweeter_conf['consumer_key'] = client.get_configuration_setting(
        key="tweeter_consumer_key").value
    tweeter_conf['consumer_secret'] = client.get_configuration_setting(
        key="tweeter_consumer_secret").value
    tweeter_conf['tweets_number'] = client.get_configuration_setting(
        key="tweets_number").value
    return tweeter_conf


def get_eventhub_config():
    eventhub_conf = {}
    eventhub_conf['tweeter-name'] = client.get_configuration_setting(
        key="eventhub-tweeter-name").value
    eventhub_conf['connection_string'] = client.get_configuration_setting(
        key="evet_hub_connection_string").value
    return eventhub_conf
Пример #27
0
def import_config(
        cmd,
        source,
        name=None,
        connection_string=None,
        label=None,
        prefix="",  # prefix to add
        yes=False,
        skip_features=False,
        content_type=None,
        # from-file parameters
        path=None,
        format_=None,
        separator=None,
        depth=None,
        # from-configstore parameters
        src_name=None,
        src_connection_string=None,
        src_key=None,
        src_label=None,
        preserve_labels=False,
        # from-appservice parameters
        appservice_account=None):
    src_features = []
    dest_features = []
    dest_kvs = []
    source = source.lower()
    format_ = format_.lower() if format_ else None

    connection_string = resolve_connection_string(cmd, name, connection_string)
    azconfig_client = AzureAppConfigurationClient.from_connection_string(
        connection_string=connection_string, user_agent=HttpHeaders.USER_AGENT)
    # fetch key values from source
    if source == 'file':
        if format_ and content_type:
            # JSON content type is only supported with JSON format.
            # Error out if user has provided JSON content type with any other format.
            if format_ != 'json' and __is_json_content_type(content_type):
                raise CLIError(
                    "Failed to import '{}' file format with '{}' content type. Please provide JSON file format to match your content type."
                    .format(format_, content_type))

        if separator:
            # If separator is provided, use max depth by default unless depth is specified.
            depth = sys.maxsize if depth is None else int(depth)
        else:
            if depth and int(depth) != 1:
                logger.warning(
                    "Cannot flatten hierarchical data without a separator. --depth argument will be ignored."
                )
            depth = 1
        src_kvs = __read_kv_from_file(file_path=path,
                                      format_=format_,
                                      separator=separator,
                                      prefix_to_add=prefix,
                                      depth=depth,
                                      content_type=content_type)

        if not skip_features:
            # src_features is a list of KeyValue objects
            src_features = __read_features_from_file(file_path=path,
                                                     format_=format_)

    elif source == 'appconfig':
        src_connection_string = resolve_connection_string(
            cmd, src_name, src_connection_string)
        src_azconfig_client = AzureAppConfigurationClient.from_connection_string(
            connection_string=src_connection_string,
            user_agent=HttpHeaders.USER_AGENT)

        if label is not None and preserve_labels:
            raise CLIError(
                "Import failed! Please provide only one of these arguments: '--label' or '--preserve-labels'. See 'az appconfig kv import -h' for examples."
            )
        if preserve_labels:
            # We need label to be the same as src_label for preview later.
            # This will have no effect on label while writing to config store
            # as we check preserve_labels again before labelling KVs.
            label = src_label

        src_kvs = __read_kv_from_config_store(
            src_azconfig_client,
            key=src_key,
            label=src_label if src_label else SearchFilterOptions.EMPTY_LABEL,
            prefix_to_add=prefix)
        # We need to separate KV from feature flags
        __discard_features_from_retrieved_kv(src_kvs)

        if not skip_features:
            # Get all Feature flags with matching label
            all_features = __read_kv_from_config_store(
                src_azconfig_client,
                key=FeatureFlagConstants.FEATURE_FLAG_PREFIX + '*',
                label=src_label
                if src_label else SearchFilterOptions.EMPTY_LABEL)
            for feature in all_features:
                if feature.content_type == FeatureFlagConstants.FEATURE_FLAG_CONTENT_TYPE:
                    src_features.append(feature)

    elif source == 'appservice':
        src_kvs = __read_kv_from_app_service(
            cmd,
            appservice_account=appservice_account,
            prefix_to_add=prefix,
            content_type=content_type)

    # if customer needs preview & confirmation
    if not yes:
        # fetch key values from user's configstore
        dest_kvs = __read_kv_from_config_store(
            azconfig_client,
            key=SearchFilterOptions.ANY_KEY,
            label=label if label else SearchFilterOptions.EMPTY_LABEL)
        __discard_features_from_retrieved_kv(dest_kvs)

        # generate preview and wait for user confirmation
        need_kv_change = __print_preview(
            old_json=__serialize_kv_list_to_comparable_json_object(
                keyvalues=dest_kvs, level=source),
            new_json=__serialize_kv_list_to_comparable_json_object(
                keyvalues=src_kvs, level=source))

        need_feature_change = False
        if src_features and not skip_features:
            # Append all features to dest_features list
            all_features = __read_kv_from_config_store(
                azconfig_client,
                key=FeatureFlagConstants.FEATURE_FLAG_PREFIX + '*',
                label=label if label else SearchFilterOptions.EMPTY_LABEL)
            for feature in all_features:
                if feature.content_type == FeatureFlagConstants.FEATURE_FLAG_CONTENT_TYPE:
                    dest_features.append(feature)

            need_feature_change = __print_features_preview(
                old_json=
                __serialize_features_from_kv_list_to_comparable_json_object(
                    keyvalues=dest_features),
                new_json=
                __serialize_features_from_kv_list_to_comparable_json_object(
                    keyvalues=src_features))

        if not need_kv_change and not need_feature_change:
            return

        user_confirmation("Do you want to continue? \n")

    # append all feature flags to src_kvs list
    src_kvs.extend(src_features)

    # import into configstore
    __write_kv_and_features_to_config_store(azconfig_client,
                                            key_values=src_kvs,
                                            label=label,
                                            preserve_labels=preserve_labels,
                                            content_type=content_type)
Пример #28
0
def set_keyvault(cmd,
                 key,
                 secret_identifier,
                 name=None,
                 label=None,
                 tags=None,
                 yes=False,
                 connection_string=None):
    connection_string = resolve_connection_string(cmd, name, connection_string)
    azconfig_client = AzureAppConfigurationClient.from_connection_string(
        connection_string=connection_string, user_agent=HttpHeaders.USER_AGENT)

    keyvault_ref_value = json.dumps({"uri": secret_identifier},
                                    ensure_ascii=False,
                                    separators=(',', ':'))
    retry_times = 3
    retry_interval = 1

    label = label if label and label != SearchFilterOptions.EMPTY_LABEL else None
    for i in range(0, retry_times):
        retrieved_kv = None
        set_kv = None
        new_kv = None

        try:
            retrieved_kv = azconfig_client.get_configuration_setting(
                key=key, label=label)
        except ResourceNotFoundError:
            logger.debug(
                "Key '%s' with label '%s' not found. A new key-vault reference will be created.",
                key, label)
        except HttpResponseError as exception:
            raise CLIError(
                "Failed to retrieve key-values from config store. " +
                str(exception))

        if retrieved_kv is None:
            set_kv = ConfigurationSetting(
                key=key,
                label=label,
                value=keyvault_ref_value,
                content_type=KeyVaultConstants.KEYVAULT_CONTENT_TYPE,
                tags=tags)
        else:
            set_kv = ConfigurationSetting(
                key=key,
                label=label,
                value=keyvault_ref_value,
                content_type=KeyVaultConstants.KEYVAULT_CONTENT_TYPE,
                tags=retrieved_kv.tags if tags is None else tags,
                read_only=retrieved_kv.read_only,
                etag=retrieved_kv.etag)

        verification_kv = {
            "key": set_kv.key,
            "label": set_kv.label,
            "content_type": set_kv.content_type,
            "value": set_kv.value,
            "tags": set_kv.tags
        }
        entry = json.dumps(verification_kv,
                           indent=2,
                           sort_keys=True,
                           ensure_ascii=False)
        confirmation_message = "Are you sure you want to set the keyvault reference: \n" + entry + "\n"
        user_confirmation(confirmation_message, yes)

        try:
            if set_kv.etag is None:
                new_kv = azconfig_client.add_configuration_setting(set_kv)
            else:
                new_kv = azconfig_client.set_configuration_setting(
                    set_kv, match_condition=MatchConditions.IfNotModified)
            return convert_configurationsetting_to_keyvalue(new_kv)

        except ResourceReadOnlyError:
            raise CLIError(
                "Failed to update read only key vault reference. Unlock the key vault reference before updating it."
            )
        except HttpResponseError as exception:
            if exception.status_code == StatusCodes.PRECONDITION_FAILED:
                logger.debug(
                    'Retrying setting %s times with exception: concurrent setting operations',
                    i + 1)
                time.sleep(retry_interval)
            else:
                raise CLIError(str(exception))
        except Exception as exception:
            raise CLIError(str(exception))
    raise CLIError(
        "Failed to set the keyvault reference '{}' due to a conflicting operation."
        .format(key))
Пример #29
0
def delete_key(cmd,
               key,
               name=None,
               label=None,
               yes=False,
               connection_string=None):
    connection_string = resolve_connection_string(cmd, name, connection_string)
    azconfig_client = AzureAppConfigurationClient.from_connection_string(
        connection_string=connection_string, user_agent=HttpHeaders.USER_AGENT)

    # list_configuration_settings returns kv with null label when:
    # label = ASCII null 0x00, or URL encoded %00
    # In delete, import and export commands, we treat missing --label as null label
    # In list, restore and revision commands, we treat missing --label as all labels

    entries = __read_kv_from_config_store(
        azconfig_client,
        key=key,
        label=label if label else SearchFilterOptions.EMPTY_LABEL)
    confirmation_message = "Found '{}' key-values matching the specified key and label. Are you sure you want to delete these key-values?".format(
        len(entries))
    user_confirmation(confirmation_message, yes)

    deleted_entries = []
    exception_messages = []
    for entry in entries:
        try:
            deleted_kv = azconfig_client.delete_configuration_setting(
                key=entry.key,
                label=entry.label,
                etag=entry.etag,
                match_condition=MatchConditions.IfNotModified)
            deleted_entries.append(
                convert_configurationsetting_to_keyvalue(deleted_kv))

        except ResourceReadOnlyError:
            exception = "Failed to delete read-only key-value with key '{}' and label '{}'. Unlock the key-value before deleting it.".format(
                entry.key, entry.label)
            exception_messages.append(exception)
        except ResourceModifiedError:
            exception = "Failed to delete key-value with key '{}' and label '{}' due to a conflicting operation.".format(
                entry.key, entry.label)
            exception_messages.append(exception)
        except HttpResponseError as ex:
            exception_messages.append(str(ex))
            raise CLIError(
                'Delete operation failed. The following error(s) occurred:\n' +
                json.dumps(exception_messages, indent=2, ensure_ascii=False))

    # Log errors if partially succeeded
    if exception_messages:
        if deleted_entries:
            logger.error(
                'Delete operation partially failed. The following error(s) occurred:\n%s\n',
                json.dumps(exception_messages, indent=2, ensure_ascii=False))
        else:
            raise CLIError(
                'Delete operation failed. \n' +
                json.dumps(exception_messages, indent=2, ensure_ascii=False))

    return deleted_entries
Пример #30
0
def restore_key(cmd,
                datetime,
                key=None,
                name=None,
                label=None,
                connection_string=None,
                yes=False):

    connection_string = resolve_connection_string(cmd, name, connection_string)
    azconfig_client = AzureAppConfigurationClient.from_connection_string(
        connection_string=connection_string, user_agent=HttpHeaders.USER_AGENT)

    exception_messages = []
    try:
        restore_keyvalues = __read_kv_from_config_store(
            azconfig_client,
            key=key if key else SearchFilterOptions.ANY_KEY,
            label=label if label else SearchFilterOptions.ANY_LABEL,
            datetime=datetime)
        current_keyvalues = __read_kv_from_config_store(
            azconfig_client,
            key=key if key else SearchFilterOptions.ANY_KEY,
            label=label if label else SearchFilterOptions.ANY_LABEL)
    except HttpResponseError as exception:
        raise CLIError(
            'Failed to read key-value(s) that match the specified key and label.'
            + str(exception))

    try:
        kvs_to_restore, kvs_to_modify, kvs_to_delete = __compare_kvs_for_restore(
            restore_keyvalues, current_keyvalues)
        if not yes:
            need_change = __print_restore_preview(kvs_to_restore,
                                                  kvs_to_modify, kvs_to_delete)
            if need_change is False:
                logger.debug(
                    'Canceling the restore operation based on user selection.')
                return

        keys_to_restore = len(kvs_to_restore) + len(kvs_to_modify) + len(
            kvs_to_delete)
        restored_so_far = 0

        for kv in chain(kvs_to_restore, kvs_to_modify):
            set_kv = convert_keyvalue_to_configurationsetting(kv)
            try:
                azconfig_client.set_configuration_setting(set_kv)
                restored_so_far += 1
            except ResourceReadOnlyError:
                exception = "Failed to update read-only key-value with key '{}' and label '{}'. Unlock the key-value before updating it.".format(
                    set_kv.key, set_kv.label)
                exception_messages.append(exception)
            except ResourceModifiedError:
                exception = "Failed to update key-value with key '{}' and label '{}' due to a conflicting operation.".format(
                    set_kv.key, set_kv.label)
                exception_messages.append(exception)

        for kv in kvs_to_delete:
            try:
                azconfig_client.delete_configuration_setting(
                    key=kv.key,
                    label=kv.label,
                    etag=kv.etag,
                    match_condition=MatchConditions.IfNotModified)
                restored_so_far += 1
            except ResourceReadOnlyError:
                exception = "Failed to delete read-only key-value with key '{}' and label '{}'. Unlock the key-value before deleting it.".format(
                    kv.key, kv.label)
                exception_messages.append(exception)
            except ResourceModifiedError:
                exception = "Failed to delete key-value with key '{}' and label '{}' due to a conflicting operation.".format(
                    kv.key, kv.label)
                exception_messages.append(exception)

        if restored_so_far != keys_to_restore:
            logger.error(
                'Failed after restoring %d out of %d keys. The following error(s) occurred:\n%s\n',
                restored_so_far, keys_to_restore,
                json.dumps(exception_messages, indent=2, ensure_ascii=False))
        else:
            logger.debug('Successfully restored %d out of %d keys',
                         restored_so_far, keys_to_restore)
        return

    except HttpResponseError as ex:
        exception_messages.append(str(ex))

    raise CLIError(
        'Restore operation failed. The following error(s) occurred:\n' +
        json.dumps(exception_messages, indent=2, ensure_ascii=False))