diff --git a/src/azure-cli-core/azure/cli/core/cloud.py b/src/azure-cli-core/azure/cli/core/cloud.py index b03c6f96544..c00d924485f 100644 --- a/src/azure-cli-core/azure/cli/core/cloud.py +++ b/src/azure-cli-core/azure/cli/core/cloud.py @@ -20,6 +20,9 @@ CLOUD_CONFIG_FILE = os.path.join(GLOBAL_CONFIG_DIR, 'clouds.config') +# Add names of clouds that don't allow telemetry data collection here such as JEDI. +CLOUDS_FORBIDDING_TELEMETRY = [] + class CloudNotRegisteredException(Exception): def __init__(self, cloud_name): @@ -526,3 +529,7 @@ def remove_cloud(cli_ctx, cloud_name): config.remove_section(cloud_name) with open(CLOUD_CONFIG_FILE, 'w') as configfile: config.write(configfile) + + +def cloud_forbid_telemetry(cli_ctx): + return get_active_cloud_name(cli_ctx) in CLOUDS_FORBIDDING_TELEMETRY diff --git a/src/azure-cli-core/azure/cli/core/telemetry.py b/src/azure-cli-core/azure/cli/core/telemetry.py index 39ceb516e45..f59c5b98d63 100644 --- a/src/azure-cli-core/azure/cli/core/telemetry.py +++ b/src/azure-cli-core/azure/cli/core/telemetry.py @@ -204,7 +204,7 @@ def product_version(self): def _user_agrees_to_telemetry(func): @wraps(func) def _wrapper(*args, **kwargs): - if not _get_config().getboolean('core', 'collect_telemetry', fallback=True): + if not is_telemetry_enabled(): return None return func(*args, **kwargs) @@ -358,6 +358,14 @@ def _add_event(event_name, properties, instrumentation_key=DEFAULT_INSTRUMENTATI }) +@decorators.suppress_all_exceptions() +def is_telemetry_enabled(): + from azure.cli.core.cloud import cloud_forbid_telemetry + if cloud_forbid_telemetry(_session.application): + return False + return _get_config().getboolean('core', 'collect_telemetry', fallback=True) + + # definitions @decorators.call_once diff --git a/src/azure-cli-core/azure/cli/core/tests/test_telemetry.py b/src/azure-cli-core/azure/cli/core/tests/test_telemetry.py index a897be455d8..fc1204da304 100644 --- a/src/azure-cli-core/azure/cli/core/tests/test_telemetry.py +++ b/src/azure-cli-core/azure/cli/core/tests/test_telemetry.py @@ -39,3 +39,21 @@ def test_extract_parameters_correctly(self): args = ['vm', 'show', '-g', 'rg', '--name', 'vm1', '-d', '--debug'] self.assertEqual(['-g', '--name', '-d', '--debug'], AzCliCommandInvoker._extract_parameter_names(args)) + + def test_cloud_forbid_telemetry(self): + import mock + import azure.cli.core.telemetry as telemetry + from azure.cli.core.mock import DummyCli + from knack.completion import ARGCOMPLETE_ENV_NAME + + az_cli = DummyCli() + telemetry.set_application(az_cli, ARGCOMPLETE_ENV_NAME) + # mock user turns off telemetry + with mock.patch('knack.config.CLIConfig.getboolean', return_value=False): + self.assertFalse(telemetry.is_telemetry_enabled()) + # mock user turns on telemetry + with mock.patch('knack.config.CLIConfig.getboolean', return_value=True): + self.assertTrue(telemetry.is_telemetry_enabled()) + # mock to add current cloud name in CLOUDS_FORBIDDING_TELEMETRY + with mock.patch('azure.cli.core.cloud.CLOUDS_FORBIDDING_TELEMETRY', [az_cli.cloud.name]): + self.assertFalse(telemetry.is_telemetry_enabled()) diff --git a/src/azure-cli/azure/cli/command_modules/configure/_consts.py b/src/azure-cli/azure/cli/command_modules/configure/_consts.py index 1fe76a394b9..04ca4af91bc 100644 --- a/src/azure-cli/azure/cli/command_modules/configure/_consts.py +++ b/src/azure-cli/azure/cli/command_modules/configure/_consts.py @@ -30,6 +30,9 @@ ' $ az vm create --help\n' \ ' $ az feedback\n' +WARNING_CLOUD_FORBID_TELEMETRY = '\nYour current cloud: %s does not allow data collection.' \ + ' Telemetry is disabled regardless of the configuration.' + MSG_GLOBAL_SETTINGS_LOCATION = 'Your settings can be found at {}' MSG_HEADING_CURRENT_CONFIG_INFO = 'Your current configuration is as follows:' diff --git a/src/azure-cli/azure/cli/command_modules/configure/custom.py b/src/azure-cli/azure/cli/command_modules/configure/custom.py index b11195eb5b1..62e4cd520cb 100644 --- a/src/azure-cli/azure/cli/command_modules/configure/custom.py +++ b/src/azure-cli/azure/cli/command_modules/configure/custom.py @@ -26,6 +26,7 @@ MSG_PROMPT_TELEMETRY, MSG_PROMPT_FILE_LOGGING, MSG_PROMPT_CACHE_TTL, + WARNING_CLOUD_FORBID_TELEMETRY, DEFAULT_CACHE_TTL) from azure.cli.command_modules.configure._utils import get_default_from_config @@ -96,7 +97,7 @@ def _config_env_public_azure(cli_ctx, _): logger.error(err) -def _handle_global_configuration(config): +def _handle_global_configuration(config, cloud_forbid_telemetry): # print location of global configuration print(MSG_GLOBAL_SETTINGS_LOCATION.format(config.config_path)) # set up the config parsers @@ -118,7 +119,10 @@ def _handle_global_configuration(config): answers['output_type_prompt'] = output_index answers['output_type_options'] = str(OUTPUT_LIST) enable_file_logging = prompt_y_n(MSG_PROMPT_FILE_LOGGING, default='n') - allow_telemetry = prompt_y_n(MSG_PROMPT_TELEMETRY, default='y') + if cloud_forbid_telemetry: + allow_telemetry = False + else: + allow_telemetry = prompt_y_n(MSG_PROMPT_TELEMETRY, default='y') answers['telemetry_prompt'] = allow_telemetry cache_ttl = None while not cache_ttl: @@ -140,6 +144,7 @@ def _handle_global_configuration(config): # pylint: disable=inconsistent-return-statements def handle_configure(cmd, defaults=None, list_defaults=None, scope=None): + from azure.cli.core.cloud import cloud_forbid_telemetry, get_active_cloud_name if defaults: defaults_section = cmd.cli_ctx.config.defaults_section_name with ConfiguredDefaultSetter(cmd.cli_ctx.config, scope.lower() == 'local'): @@ -157,8 +162,11 @@ def handle_configure(cmd, defaults=None, list_defaults=None, scope=None): # if nothing supplied, we go interactively try: print(MSG_INTRO) - _handle_global_configuration(cmd.cli_ctx.config) + cloud_forbid_telemetry = cloud_forbid_telemetry(cmd.cli_ctx) + _handle_global_configuration(cmd.cli_ctx.config, cloud_forbid_telemetry) print(MSG_CLOSING) + if cloud_forbid_telemetry: + logger.warning(WARNING_CLOUD_FORBID_TELEMETRY, get_active_cloud_name(cmd.cli_ctx)) # TODO: log_telemetry('configure', **answers) except NoTTYException: raise CLIError('This command is interactive and no tty available.')